[go: up one dir, main page]

Menu

[897c37]: / mlib / std / armourer.lpc  Maximize  Restore  History

Download this file

351 lines (310 with data), 11.4 kB

/*
        Shattered World's Standard Armor Generator.

        By Dredd the Dreddfullest.
        (geoff@bruce.cs.monash.edu.au)

    19980517 D     Support for persistence
    19990813 Jenna Added protection types ("cut", "impact", etc)
    20000309 Jenna Added more materials: dragon/drake scale/plate, voidian
    20000819 Jenna Added "custom" armour type - if the arg "name" to
		   make_auto() or create_armour() is an array, the first
		   arg of which is "custom", then the rest of the array
		   is interpreted as the body areas it will cover. E.g.
		   ARMOURER->create_armour("chainmail",["custom","tail"]);
		   makes a chainmail tailplate.
    20010714 Jenna Added is_standard(ob).
    20010718 Jenna Specified arg types for make()
    20010724 Dredd Added in material types, reworked arrays.
    20010831 Bel   Added the "caller" parameter for SHOP_SERVER->get_cheapest().
		   Let's track where the money is being spent *properly*.

*/

/*
 * WEAR possibilities:
 *      Area    type            desc
 *      hands   gloves          1 layer only
 *      arms    sleeves         inner layer; soft materials only
 *      arms    vambrace        outer layer; may be jointed
 *      legs    pants           inner - soft
 *      legs    greaves         outer - hard should only cover half
 *      feet    boots
 *      head    hood            may be worn inside helmet (padding)
 *      head    helmet
 *      chest   shirt           innermost layer; must be soft
 *      chest
 */

/*
 * short:               an adjective for the construction type.
 * folds:               stored folded in pack - same enc as when worn.
 * under:               can be worn under other armour
                        1-under, 2-over
 * slices:              not resistant to slicing attack
 * weight:              grams, whole body suit (not underdax)
 * enc:                 whole suit, worn.  If carried, double enc if not folded.
 * ac:                  per location.  some locs can wear undergarments.
 * blunt_mod:           percentage of AC used against blunt attacks.
 */

inherit "RO/Servers";
inherit "std/materials";

array acm, armour_types;
#define ATYPEF_0 1

reset() {
  acm = [
   [ "leather",  1,  1,  1,  3000,  300,  1000,  50, 0 | ATYPEF_0 ,
	[ "cut", 1, "impact", 2 ], 50, MAT_LEATHER ],
   [ "hard leather",  1,  0,  1,  5000,  400,  1400,  60, 0 | ATYPEF_0 ,
	[ "cut", 3, "impact", 3 ], 50, MAT_LEATHER ],
   [ "cuirbolli",  0,  0,  1,  6000,  600,  1800,  90, 0 | ATYPEF_0 ,
	[ "cut", 3, "impact", 3, "puncture", 1 ], 100, MAT_LEATHER ],
   [ "ringmail",  1,  1,  0,  12000,  1000,  2800,  80, 0 | ATYPEF_0 ,
	[ "cut", 5, "impact", 2, "puncture", 1 ], 100, MAT_BRONZE ],
   [ "byzantine",  1,  0,  0,  9000,  800,  2600,  70, 0 | ATYPEF_0 ,
	[ "cut", 3, "impact", 5, "puncture", 3 ], 100, MAT_BRONZE ],
   [ "lamellar",  1,  0,  0,  21500,  1500,  3200,  110, 0 | ATYPEF_0 ,
	[ "cut", 4, "impact", 6, "puncture", 3 ], 100, MAT_BRONZE ],
   [ "scalemail",  0,  0,  0,  24000,  1800,  3400,  100, 0 | ATYPEF_0 ,
	[ "cut", 5, "impact", 7, "puncture", 5 ], 100, MAT_BRONZE ],
   [ "chainmail",  1,  1,  0,  24000,  1500,  3800,  85, 0 | ATYPEF_0 ,
	[ "cut", 6, "impact", 6, "puncture", 6 ], 100, MAT_STEEL ],
   [ "brigadine",  0,  0,  0,  26500,  1600,  4000,  110, 0 | ATYPEF_0 ,
	[ "cut", 6, "impact", 8, "puncture", 5 ], 100, MAT_STEEL ]
    ];
acm += [
   [ "plate",  0,  0,  0,  30000,  2000,  4400,  130, 0 | ATYPEF_0,
	[ "cut", 7, "impact", 7, "puncture", 6 ], 100, MAT_STEEL ],
   [ "mithril",  0,  0,  0,  14000,  1200,  4400,  130, 0 | ATYPEF_0,
	[ "cut", 10, "impact", 7, "puncture", 8 ], 100, MAT_MITHRIL ],
   [ "dragon scale", 0, 0, 0, 22000, 1600, 3600, 110, 0 | ATYPEF_0,
        [ "cut", 4, "impact", 2, "puncture", 6, "heat", 8 ], 100, MAT_DRAGON  ],
   [ "dragon plate", 0, 0, 0, 22000, 1600, 3600, 110, 0 | ATYPEF_0,
        [ "cut", 7, "impact", 5, "puncture", 6, "heat", 8 ], 100, MAT_DRAGON  ],
   [ "drake scale",  0, 0, 0, 14000, 1400, 2000, 100, 0 | ATYPEF_0,
        [ "cut", 2, "cold", 12, "magic", 4 ], 100, MAT_DRAGON  ],
   [ "drake plate",  0, 0, 0, 14000, 1400, 2000, 100, 0 | ATYPEF_0,
        [ "cut", 6, "impact", 4, "puncture", 3, "cold", 12, "magic", 4 ], 100, 
        MAT_DRAGON  ],
   [ "voidian",      0, 0, 0,  8000, 1400, 1800, 100, 0 | ATYPEF_0,
 	[ "cut", 3, "puncture", 4, "magic", 10 ], 100, MAT_MAGICAL ]
   ];

  armour_types = [
   "cloak",  [ "chest", "abdomen" ],   9,  2,  8,  8 ,
   "shirt",  [ "chest", "arm" ],   3,  1,  8,  8 ,
   "pants", [ "leg",  "abdomen" ],     3,  1,  10,  10 ,
   "sleeves", [ "arm" ],    4,  1,  5,  5 ,
   "coif", [ "head" ],      5,  1,  5,  5 ,
   "gauntlets", [ "hand" ], 2,  0,  5,  5 ,
   "boots", [ "foot" ],     2,  0,  7,  7 ,
   "greaves", [ "leg" ],    4,  0,  15,  15 ,
   "skirt", [ "abdomen" ],  4,  0,  15,  15 ,
   "hauberk", [ "chest",  "abdomen" ], 7,  0,  28,  28 ,
   "helmet", [ "head" ],    6,  0,  10,  10 ,
   "cuirass", [ "chest" ],  6,  0,  20,  20 ,
   "vambraces", [ "arm" ],  4,  0,  10,  10 ,
   "shield", [ "left arm", "chest" ],  8,  3,  25,  25 ,
   "custom", [ ], 4, 0, 25, 10
   ];

  }



// armour_types access
#define COVER 1
#define LAYER 2
#define A_WEIGHT 5

// acm array access
#define M_UNDER 2
#define M_WEIGHT 4
#define ABSORB 6
#define PROTECTIONS  9
#define PROTECTION_PERC  10
#define MATERIAL 11

// default size
#define MEDIUM 12

/*
** Automatic creation (emulated persistence)
*/
object make_auto(array args)
{
    object arm;
    arm = create_armour(args[0], args[1], args[2], 0);
    if (sizeof(args) > 3)
	arm->set_damage(args[3]);
    return arm;
}

armour_exists(str)
{
    return (index(armour_types, str) != -1);
}

make(string mat, string name, size, optpoint, (object|int) source)
{
    string who;
    array armcost;
    int n,m, max;
    object callr = caller();

        /* we trust the itemer to do the right thing; nothing else. */
        if ((file_name(callr) == ITEMER) && objectp(source))
            callr = source;

        who = query_su_name(callr);
        if (!who) who = "#treasury";
        if (optpoint) return create_armour(mat, name, size, optpoint);

        if (!is_cloned(callr) && callr->query_living())
                return create_armour(mat, name, size);

        m = "modules/misc"->array_index(acm, 0, mat);
        n = index(armour_types, name);
        if (n < 0 || m < 0) max = 0;
        else max = acm[m][M_WEIGHT] * armour_types[n+A_WEIGHT] / 400;
        armcost = SHOP_SERVER->get_cheapest(mat+" "+name, who, max, 0,
		callr);
        if (!armcost) {
/*              LOG->log("NPC_BUY", "0 coins: "+ who + " creates " + 
                (mat+" "+name) +" for " + file_name(callr) + ".");
*/              return create_armour(mat, name, size, optpoint);
        }
        LOG->log("NPC_BUY", STRINGS->itoa(armcost[1]) + " coins: "+
                who + " bought " + armcost[0]->short() + " (requested " + 
                (mat+" "+name) + ") from " +              
                armcost[2] + " (" + armcost[2]->query_short_desc() +
                ") for " + file_name(callr) + ".");
        return armcost[0];
}

create_armour(mat, auto_name, size, optpoint)
{
    int i, m, n, wght; 
    string alt, b, name;
    object am;
    array cov;

    if (mat == "any")
    {
        m = random(5);
        mat = acm[m][0];
    }
    else
    {
        m = "modules/misc"->array_index(acm, 0, mat);
        if (m < 0) return;
    }

	if (arrayp(auto_name))
	{
	    if (auto_name[0] == "custom")
	    {
		cov = auto_name[1..];
		name = auto_name[1]+"plate";
		n = index(armour_types, "custom");
	    }
	    else return 0;
	}
    else
	{
	    name = auto_name;
	    n = index(armour_types, name);
	}

    if (n < 0) return;
    if (!size) size = MEDIUM;
    if (optpoint) am = optpoint;
    else am = clone_object("obj/armour");

    am->set_name(name);
    am->add_id(mat);
    am->add_id(name);
	if (!cov) cov = armour_types[n + COVER];
    am->set_cover(cov);
	am->set_layer(armour_types[n + LAYER]);
    wght = ( acm[m][M_WEIGHT] * size * armour_types[n + A_WEIGHT] )
                                                         / 2000000;
    if (!wght) wght = 1;
    am->set_weight(wght);
    am->set_under( acm[m][M_UNDER] );
    b = mat + " " + name;
    am->set_short(b);
    am->add_id(mat+" "+name);
    am->set_long("A " + capitalize(b) + ", it has some small writing upon it.\n");
    am->set_type(name);
    am->set_read("Made by an accredited member of the SCAA.\n");
    am->set_value(acm[m][M_WEIGHT] * armour_types[n+A_WEIGHT] / 400);
    am->set_ac(acm[m][ABSORB] / 3);
    am->set_robust(acm[m][ABSORB]);
    am->set_material(acm[m][MATERIAL]);
    am->set_invoke("worn");
    for (i = 0; i < sizeof(acm[m][PROTECTIONS]); i += 2)
	am->add_protection(acm[m][PROTECTIONS][i], acm[m][PROTECTIONS][i + 1],
			cov, acm[m][PROTECTION_PERC]);
    if (!optpoint) am->set_auto("ARMOURER", ({ mat,auto_name,size }));
        return am;
}

/* a clothing support thing - sigh */
fix_layer(object o)
{
    int n;

        n = index(armour_types, o->query_type());
        if (n < 0) n = index(armour_types, o->query_type() + "s");
    if (n < 0) return 0;

    o->set_layer(armour_types[n + LAYER]);
    return 1;
}

test(str) {
int count;
string ret = "";

    if (str == "materials")
    {
        ret += "Armor Materials:\n";
        for (count = 0; count < sizeof(acm); count++)
        {
            //write(acm[count]+(count == sizeof(acm)-SIZEOF_ACM?".\n":", "));
            ret += acm[count][0]+(count == sizeof(acm)?".\n":", ");
        }
        return ret;
    }

    if (str == "types")
    {
        ret += "Armor types:\n";
        for (count = 0; count < sizeof(armour_types); count += 6)
        {
            //write(armour_types[count]+" ("+implode(armour_types[count+1],"+")+ ")"+
            //(count == sizeof(armour_types)-5?".\n":", "));
            ret += armour_types[count]+" ("+implode(armour_types[count+1],"+")+ ")"+
                (count == sizeof(armour_types)-5?".\n":", ");
        }
        return ret;
    }
}

query_acm() { return acm + []; }

query_armour_types() { return armour_types + []; }

/* query_standard_protections(object armour)
 *     or
 * query_standard_protections(string material, string type)
 *
 * Returns array of protections this armour has when brand new, e.g.
 * leather hauberk returns:
 * ["cut", 2, ["chest", "abdomen"], "impact", 3, ["chest", "abdomen"]]
 */
query_standard_protections(arg1, arg2) 
{
    array ret = [];
    int i, n, m;

    if (objectp(arg1)) {
	arg2 = arg1->query_type();
	arg1 = arg1->query_material();  /* ??? set_auto? */
	}
    if (!stringp(arg2)) return 0;
    m = "modules/misc"->array_index(acm, 0, arg1);
    n = index(armour_types, arg2);
    if (m == -1 || n == -1)
	return 0;
    for (i = 0, ret = [ ]; i < sizeof(acm[m][PROTECTIONS]); i += 2)
	ret += [ acm[m][PROTECTIONS][i], acm[m][PROTECTIONS][i + 1],
		armour_types[n + COVER] ];
    return ret;
}

// returns 1 if this is a standard armour object
// Jenna, July 2001
is_standard(ob)
{
    array al;

    if (!objectp(ob)) return 0;
    al = ob->query_auto_load();
    if (!arrayp(al) || sizeof(al) != 2
	    || al[0] != "ARMOURER"
	    || !arrayp(al[1])
    	|| sizeof(al[1]) < 2)
    {
	    return 0;
    }
    if ("modules/misc"->array_index(acm, 0, al[1][0]) == -1) return 0;
    if (index(armour_types, al[1][1], 0, 6) == -1)
	return 0;
    return 1;
}