diff --git a/res/core/resources/iron.xml b/res/core/resources/iron.xml index 38ddb33c8..ae4829dd7 100644 --- a/res/core/resources/iron.xml +++ b/res/core/resources/iron.xml @@ -8,7 +8,7 @@ - + diff --git a/res/core/resources/stone.xml b/res/core/resources/stone.xml index b8f91eadc..459e66074 100644 --- a/res/core/resources/stone.xml +++ b/res/core/resources/stone.xml @@ -7,7 +7,7 @@ - + diff --git a/res/core/weapons/greatbow.xml b/res/core/weapons/greatbow.xml index a63761535..ad6a4e018 100644 --- a/res/core/weapons/greatbow.xml +++ b/res/core/weapons/greatbow.xml @@ -2,7 +2,7 @@ - + diff --git a/res/e3a/armor.xml b/res/e3a/armor.xml index 160e527d9..207f873b2 100644 --- a/res/e3a/armor.xml +++ b/res/e3a/armor.xml @@ -2,8 +2,7 @@ - - + @@ -20,8 +19,7 @@ - - + diff --git a/res/e3a/weapons.xml b/res/e3a/weapons.xml index 6f9b5fa5e..3eea6dc44 100644 --- a/res/e3a/weapons.xml +++ b/res/e3a/weapons.xml @@ -31,7 +31,7 @@ - + @@ -127,7 +127,7 @@ * has a lua canuse function * has lower damage --> - + diff --git a/src/economy.c b/src/economy.c index 18ca23b8e..4cabb4ab5 100644 --- a/src/economy.c +++ b/src/economy.c @@ -833,7 +833,8 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type * for (mod = rtype->modifiers; mod && mod->type != RMT_END; ++mod) { if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { + const race * rc = u_race(u); + if (mod->race_mask == 0 || (mod->race_mask & rc->mask_item)) { switch (mod->type) { case RMT_PROD_SAVE: if (savep) { @@ -845,7 +846,7 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type * mod_skill(mod, sk, &skill); break; case RMT_PROD_REQUIRE: - if (mod->race) need_race |= 1; + if (mod->race_mask) need_race |= 1; if (mod->btype) { need_bldg |= 1; } @@ -857,7 +858,7 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type * } } if (mod->type == RMT_PROD_REQUIRE) { - if (mod->race) need_race |= 2; + if (mod->race_mask) need_race |= 2; if (mod->btype) { btype_needed = mod->btype; need_bldg |= 2; diff --git a/src/economy.test.c b/src/economy.test.c index 282318191..3e5d39007 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -509,7 +509,7 @@ static void test_modify_material(CuTest *tc) { mod = rtype->modifiers = calloc(2, sizeof(resource_mod)); mod[0].type = RMT_USE_SAVE; mod[0].value = frac_make(2, 1); - mod[0].race = u_race(u); + mod[0].race_mask = rc_mask(u_race(u)); itype = test_create_itemtype("sword"); make_item(u, itype, 1); @@ -574,7 +574,7 @@ static void test_modify_skill(CuTest *tc) { mod[0].type = RMT_PROD_SKILL; mod[0].value.sa[0] = SK_WEAPONSMITH; mod[0].value.sa[1] = 1; - mod[0].race = u_race(u); + mod[0].race_mask = rc_mask(u_race(u)); set_item(u, rtype->itype, 2); /* 2 iron should get us 2 swords */ make_item(u, itype, 2); @@ -647,7 +647,7 @@ static void test_modify_production(CuTest *tc) { rtype->modifiers = calloc(3, sizeof(resource_mod)); rtype->modifiers[0].type = RMT_PROD_SAVE; - rtype->modifiers[0].race = u->_race; + rtype->modifiers[0].race_mask = rc_mask(u->_race); rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d); rtype->modifiers[0].value.sa[1] = 100; rtype->modifiers[1].type = RMT_END; @@ -668,7 +668,7 @@ static void test_modify_production(CuTest *tc) { CuAssertIntEquals(tc, 280, region_getresource(u->region, rtype)); /* 50% saving = 3 stones make 6 stones */ rtype->modifiers[0].type = RMT_PROD_REQUIRE; - rtype->modifiers[0].race = NULL; + rtype->modifiers[0].race_mask = 0; rtype->modifiers[0].btype = bt_get_or_create("mine"); test_clear_messages(u->faction); @@ -677,7 +677,7 @@ static void test_modify_production(CuTest *tc) { CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "building_needed")); rtype->modifiers[0].type = RMT_PROD_REQUIRE; - rtype->modifiers[0].race = test_create_race("smurf"); + rtype->modifiers[0].race_mask = rc_mask(test_create_race("smurf")); rtype->modifiers[0].btype = NULL; test_clear_messages(u->faction); @@ -686,7 +686,7 @@ static void test_modify_production(CuTest *tc) { CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error117")); rtype->modifiers[1].type = RMT_PROD_REQUIRE; - rtype->modifiers[1].race = u_race(u); + rtype->modifiers[1].race_mask = rc_mask(u_race(u)); rtype->modifiers[1].btype = NULL; rtype->modifiers[2].type = RMT_END; diff --git a/src/kernel/build.c b/src/kernel/build.c index b2774fbd7..96aee5662 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -419,7 +419,7 @@ static int matmod(const unit * u, const resource_type * rtype, int value) for (mod = rtype->modifiers; mod->type != RMT_END; ++mod) { if (mod->type == RMT_USE_SAVE) { if (!mod->btype || mod->btype == btype) { - if (!mod->race || mod->race == rc) { + if (!mod->race_mask || (mod->race_mask & rc->mask_item)) { save = frac_mul(save, mod->value); } } diff --git a/src/kernel/race.c b/src/kernel/race.c index c9299d5bd..ac81f7f78 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -259,7 +259,10 @@ void racelist_insert(struct race_list **rl, const struct race *r) *rl = rl2; } +static int race_mask = 0; + void free_races(void) { + race_mask = 0; while (races) { int i; race * rc = races->next; @@ -347,6 +350,10 @@ race *rc_create(const char *zName) assert(zName); rc = (race *)calloc(sizeof(race), 1); + + rc->mask_item = 1 << race_mask; + ++race_mask; + rc->magres.sa[1] = 1; rc->hitpoints = 1; rc->weight = PERSON_WEIGHT; @@ -575,18 +582,17 @@ void register_race_function(race_func func, const char *name) { register_function((pf_generic)func, name); } -static int race_mask = 1; +int rc_mask(const race * rc) { + assert(rc->mask_item); + return rc->mask_item; +} -int rc_mask(char *list) { +int rc_get_mask(char *list) { int mask = 0; char * tok = strtok(list, " ,"); while (tok) { race * rc = rc_get_or_create(tok); - if (!rc->mask_item) { - rc->mask_item = race_mask; - race_mask = race_mask << 1; - } - mask |= rc->mask_item; + mask |= rc_mask(rc); tok = strtok(NULL, " ,"); } return mask; diff --git a/src/kernel/race.h b/src/kernel/race.h index 042cb5e78..7c38eec57 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -198,7 +198,8 @@ extern "C" { #define MIGRANTS_LOG10 1 int rc_migrants_formula(const race *rc); - int rc_mask(char *list); + int rc_mask(const race *rc); + int rc_get_mask(char *list); /* Flags. Do not reorder these without changing json_race() in jsonconf.c */ #define RCF_NPC (1<<0) /* cannot be the race for a player faction (and other limits?) */ diff --git a/src/kernel/race.test.c b/src/kernel/race.test.c index 2f34c127e..d695969b7 100644 --- a/src/kernel/race.test.c +++ b/src/kernel/race.test.c @@ -178,10 +178,10 @@ static void test_rc_mask(CuTest *tc) { char list[64]; test_setup(); strcpy(list, "goblin dwarf"); - mask = rc_mask(list); + mask = rc_get_mask(list); CuAssertIntEquals(tc, 3, mask); CuAssertStrEquals(tc, "goblin", list); - mask = rc_mask(list); + mask = rc_get_mask(list); CuAssertIntEquals(tc, 1, mask); test_teardown(); } diff --git a/src/kernel/resources.h b/src/kernel/resources.h index 2daa44dd8..8f291c305 100644 --- a/src/kernel/resources.h +++ b/src/kernel/resources.h @@ -50,7 +50,7 @@ extern "C" { resource_modifier_type type; variant value; const struct building_type *btype; - const struct race *race; + int race_mask; } resource_mod; typedef struct rawmaterial_type { diff --git a/src/xmlreader.c b/src/xmlreader.c index edbf677ef..adddb808e 100644 --- a/src/xmlreader.c +++ b/src/xmlreader.c @@ -61,6 +61,17 @@ without prior permission by the authors of Eressea. #include +static void mask_races(xmlNodePtr node, const char *key, int *maskp) { + xmlChar *propValue = xmlGetProp(node, BAD_CAST key); + int mask = 0; + assert(maskp); + if (propValue) { + mask = rc_get_mask((char *)propValue); + xmlFree(propValue); + } + *maskp = mask; +} + static variant xml_fraction(xmlNodePtr node, const char *name) { xmlChar *propValue = xmlGetProp(node, BAD_CAST name); if (propValue != NULL) { @@ -129,16 +140,8 @@ static resource_mod * xml_readmodifiers(xmlXPathObjectPtr result, xmlNodePtr nod xmlNodePtr node = result->nodesetval->nodeTab[k]; xmlChar *propValue; building_type *btype = NULL; - const race *rc = NULL; - propValue = xmlGetProp(node, BAD_CAST "race"); - if (propValue != NULL) { - rc = rc_find((const char *)propValue); - if (rc == NULL) - rc = rc_get_or_create((const char *)propValue); - xmlFree(propValue); - } - modifiers[k].race = rc; + mask_races(node, "races", &modifiers[k].race_mask); propValue = xmlGetProp(node, BAD_CAST "building"); if (propValue != NULL) { @@ -520,8 +523,6 @@ static armor_type *xml_readarmor(xmlXPathContextPtr xpath, item_type * itype) return atype; } -static void mask_races(xmlNodePtr node, const char *key, int *maskp); - static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) { xmlNodePtr node = xpath->node; @@ -656,17 +657,6 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) return wtype; } -static void mask_races(xmlNodePtr node, const char *key, int *maskp) { - xmlChar *propValue = xmlGetProp(node, BAD_CAST key); - int mask = 0; - assert(maskp); - if (propValue) { - mask = rc_mask((char *)propValue); - xmlFree(propValue); - } - *maskp = mask; -} - static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype) { xmlNodePtr node = xpath->node;