move building names from function to construction data.

This commit is contained in:
Enno Rehling 2017-04-26 21:44:24 +02:00
parent f2d8392206
commit a313e78de5
11 changed files with 115 additions and 133 deletions

View File

@ -1,23 +1,22 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<building name="castle" capacity="1" fort="yes"> <building name="castle" capacity="1" fort="yes">
<function name="name" value="castle_name_2"/>
<function name="taxes" value="lua_building_taxes"/> <function name="taxes" value="lua_building_taxes"/>
<construction skill="building" minskill="1" maxsize="10"> <construction skill="building" minskill="1" maxsize="10" name="site">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="40"> <construction skill="building" minskill="2" maxsize="40" name="fortification">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="3" maxsize="200"> <construction skill="building" minskill="3" maxsize="200" name="tower">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="4" maxsize="1000"> <construction skill="building" minskill="4" maxsize="1000" name="castle">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="5" maxsize="5000"> <construction skill="building" minskill="5" maxsize="5000" name="fortress">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="6"> <construction skill="building" minskill="6" name="citadel">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
</building> </building>

View File

@ -1,25 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<building name="castle" capacity="1" fort="yes"> <building name="castle" capacity="1" fort="yes">
<function name="name" value="castle_name"/> <construction skill="building" minskill="1" maxsize="2" name="site">
<construction skill="building" minskill="1" maxsize="2">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="1" maxsize="8"> <construction skill="building" minskill="1" maxsize="8" name="tradepost">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="40"> <construction skill="building" minskill="2" maxsize="40" name="fortification">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="3" maxsize="200"> <construction skill="building" minskill="3" maxsize="200" name="tower">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="4" maxsize="1000"> <construction skill="building" minskill="4" maxsize="1000" name="castle">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="5" maxsize="5000"> <construction skill="building" minskill="5" maxsize="5000" name="fortress">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="6"> <construction skill="building" minskill="6" name="citadel">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
</building> </building>

View File

@ -4,15 +4,14 @@
<xi:include href="config://default/buildings/castle-2.xml" /> <xi:include href="config://default/buildings/castle-2.xml" />
<building name="watch" maxsize="10" capacity="1" fort="yes"> <building name="watch" maxsize="10" capacity="1" fort="yes">
<function name="name" value="fort_name"/>
<function name="taxes" value="lua_building_taxes"/> <function name="taxes" value="lua_building_taxes"/>
<construction skill="building" minskill="1" maxsize="5"> <construction skill="building" minskill="1" maxsize="5" name="scaffolding">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="5"> <construction skill="building" minskill="2" maxsize="5" name="guardhouse">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2"> <construction skill="building" minskill="2" name="guardtower">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
</building> </building>

View File

@ -888,7 +888,7 @@ static void manufacture(unit * u, const item_type * itype, int want)
case EBUILDINGREQ: case EBUILDINGREQ:
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "building_needed", "building", msg_feedback(u, u->thisorder, "building_needed", "building",
itype->construction->btype->_name)); itype->construction->extra.btype->_name));
return; return;
case ELOWSKILL: case ELOWSKILL:
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
@ -1239,7 +1239,7 @@ static void create_potion(unit * u, const potion_type * ptype, int want)
case EBUILDINGREQ: case EBUILDINGREQ:
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "building_needed", "building", msg_feedback(u, u->thisorder, "building_needed", "building",
ptype->itype->construction->btype->_name)); ptype->itype->construction->extra.btype->_name));
break; break;
case ECOMPLETE: case ECOMPLETE:
assert(0); assert(0);

View File

@ -70,7 +70,6 @@ void game_init(void)
register_spells(); register_spells();
register_names(); register_names();
register_resources(); register_resources();
register_buildings();
register_itemfunctions(); register_itemfunctions();
#if MUSEUM_MODULE #if MUSEUM_MODULE
register_museum(); register_museum();

View File

@ -502,20 +502,20 @@ static int count_materials(unit *u, const construction *type, int n, int complet
*/ */
int build(unit * u, const construction * ctype, int completed, int want, int skill_mod) int build(unit * u, const construction * ctype, int completed, int want, int skill_mod)
{ {
const construction *type = ctype; const construction *con = ctype;
int skills = INT_MAX; /* number of skill points remainig */ int skills = INT_MAX; /* number of skill points remainig */
int basesk = 0; int basesk = 0;
int made = 0; int made = 0;
if (want <= 0) if (want <= 0)
return 0; return 0;
if (type == NULL) if (con == NULL)
return ENOMATERIALS; return ENOMATERIALS;
if (type->improvement == NULL && completed == type->maxsize) if (con->improvement == NULL && completed == con->maxsize)
return ECOMPLETE; return ECOMPLETE;
if (type->btype != NULL) { if (con->type==CONS_ITEM && con->extra.btype) {
building *b; building *b;
if (!u->building || u->building->type != type->btype) { if (!u->building || u->building->type != con->extra.btype) {
return EBUILDINGREQ; return EBUILDINGREQ;
} }
b = inside_building(u); b = inside_building(u);
@ -524,12 +524,12 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
} }
} }
if (type->skill != NOSKILL) { if (con->skill != NOSKILL) {
int effsk; int effsk;
int dm = get_effect(u, oldpotiontype[P_DOMORE]); int dm = get_effect(u, oldpotiontype[P_DOMORE]);
assert(u->number); assert(u->number);
basesk = effskill(u, type->skill, 0); basesk = effskill(u, con->skill, 0);
if (basesk == 0) if (basesk == 0)
return ENEEDSKILL; return ENEEDSKILL;
@ -557,13 +557,13 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
* type->improvement==type means build another object of the same time * type->improvement==type means build another object of the same time
* while material lasts type->improvement==x means build x when type * while material lasts type->improvement==x means build x when type
* is finished */ * is finished */
while (type && type->improvement && while (con && con->improvement &&
type->improvement != type && con->improvement != con &&
type->maxsize > 0 && type->maxsize <= completed) { con->maxsize > 0 && con->maxsize <= completed) {
completed -= type->maxsize; completed -= con->maxsize;
type = type->improvement; con = con->improvement;
} }
if (type == NULL) { if (con == NULL) {
if (made == 0) if (made == 0)
return ECOMPLETE; return ECOMPLETE;
break; /* completed */ break; /* completed */
@ -574,15 +574,15 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
* (enno): Nein, das ist f<EFBFBD>r Dinge, bei denen die n<EFBFBD>chste Ausbaustufe * (enno): Nein, das ist f<EFBFBD>r Dinge, bei denen die n<EFBFBD>chste Ausbaustufe
* die gleiche wie die vorherige ist. z.b. gegenst<EFBFBD>nde. * die gleiche wie die vorherige ist. z.b. gegenst<EFBFBD>nde.
*/ */
if (type->maxsize > 0) { if (con->maxsize > 0) {
completed = completed % type->maxsize; completed = completed % con->maxsize;
} }
else { else {
completed = 0; completed = 0;
assert(type->reqsize >= 1); assert(con->reqsize >= 1);
} }
if (basesk < type->minskill) { if (basesk < con->minskill) {
if (made == 0) if (made == 0)
return ELOWSKILL; return ELOWSKILL;
else else
@ -590,15 +590,15 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
} }
/* n = maximum buildable size */ /* n = maximum buildable size */
if (type->minskill > 1) { if (con->minskill > 1) {
n = skills / type->minskill; n = skills / con->minskill;
} }
else { else {
n = skills; n = skills;
} }
/* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische) /* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische)
* Talente */ * Talente */
if (skill_limit(u->faction, type->skill) == INT_MAX) { if (skill_limit(u->faction, con->skill) == INT_MAX) {
const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
item *itm = ring ? *i_find(&u->items, ring->itype) : 0; item *itm = ring ? *i_find(&u->items, ring->itype) : 0;
int i = itm ? itm->number : 0; int i = itm ? itm->number : 0;
@ -610,26 +610,26 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
if (want < n) n = want; if (want < n) n = want;
if (type->maxsize > 0) { if (con->maxsize > 0) {
n = MIN(type->maxsize - completed, n); n = MIN(con->maxsize - completed, n);
if (type->improvement == NULL) { if (con->improvement == NULL) {
want = n; want = n;
} }
} }
n = count_materials(u, type, n, completed); n = count_materials(u, con, n, completed);
if (n <= 0) { if (n <= 0) {
if (made == 0) if (made == 0)
return ENOMATERIALS; return ENOMATERIALS;
else else
break; break;
} }
err = use_materials(u, type, n, completed); err = use_materials(u, con, n, completed);
if (err < 0) { if (err < 0) {
return err; return err;
} }
made += n; made += n;
skills -= n * type->minskill; skills -= n * con->minskill;
want -= n; want -= n;
completed = completed + n; completed = completed + n;
} }

View File

@ -37,15 +37,27 @@ extern "C" {
int number; int number;
} requirement; } requirement;
typedef enum construct_t {
CONS_OTHER,
CONS_ITEM,
CONS_BUILDING
} construct_t;
typedef struct construction { typedef struct construction {
construct_t type;
skill_t skill; /* skill req'd per point of size */ skill_t skill; /* skill req'd per point of size */
int minskill; /* skill req'd per point of size */ int minskill; /* skill req'd per point of size */
int maxsize; /* maximum size of this type */ int maxsize; /* maximum size of this type */
int reqsize; /* size of object using up 1 set of requirement. */ int reqsize; /* size of object using up 1 set of requirement. */
requirement *materials; /* material req'd to build one object */ requirement *materials; /* material req'd to build one object */
const struct building_type *btype;
/* building type required to make this thing */ union {
/* CONS_BUILDING: */
char * name; /* building level name */
/* CONS_ITEM: */
const struct building_type *btype; /* building required to build item */
} extra;
struct construction *improvement; struct construction *improvement;
/* next level, if upgradable. if more than one of these items /* next level, if upgradable. if more than one of these items

View File

@ -81,7 +81,8 @@ static void test_build_requires_building(CuTest *tc) {
rtype = bf.cons.materials[0].rtype; rtype = bf.cons.materials[0].rtype;
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, 2); set_level(u, SK_ARMORER, 2);
bf.cons.btype = btype = bt_get_or_create("hodor"); bf.cons.type = CONS_ITEM;
bf.cons.extra.btype = btype = bt_get_or_create("hodor");
btype->maxcapacity = 1; btype->maxcapacity = 1;
btype->capacity = 1; btype->capacity = 1;
CuAssertIntEquals_Msg(tc, "must be inside a production building", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0)); CuAssertIntEquals_Msg(tc, "must be inside a production building", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0));

View File

@ -157,27 +157,52 @@ attrib_type at_building_generic_type = {
ATF_UNIQUE ATF_UNIQUE
}; };
/* TECH DEBT: simplest thing that works for E3 dwarf/halfling faction rules */
static int adjust_size(const building *b, int bsize) {
assert(b);
if (config_get_int("rules.dwarf_castles", 0)
&& strcmp(b->type->_name, "castle") == 0) {
unit *u = building_owner(b);
if (u && u->faction->race == get_race(RC_HALFLING)) {
return bsize * 5 / 4;
}
}
return bsize;
}
/* Returns the (internal) name for a building of given size and type. Especially, returns the correct /* Returns the (internal) name for a building of given size and type. Especially, returns the correct
* name if it depends on the size (as for Eressea castles). * name if it depends on the size (as for Eressea castles).
*/ */
const char *buildingtype(const building_type * btype, const building * b, int bsize) const char *buildingtype(const building_type * btype, const building * b, int bsize)
{ {
const char *s; const construction *con;
assert(btype); assert(btype);
s = btype->_name;
if (btype->name) {
s = btype->name(btype, b, bsize);
}
if (b && b->attribs) { if (b && b->attribs) {
if (is_building_type(btype, "generic")) { if (is_building_type(btype, "generic")) {
const attrib *a = a_find(b->attribs, &at_building_generic_type); const attrib *a = a_find(b->attribs, &at_building_generic_type);
if (a) { if (a) {
s = (const char *)a->data.v; return (const char *)a->data.v;
} }
} }
} }
return s; if (btype->name) {
return btype->name(btype, b, bsize);
}
if (btype->construction->extra.name) {
if (b) {
assert(b->type == btype);
bsize = adjust_size(b, bsize);
}
for (con = btype->construction; con; con = con->improvement) {
bsize -= con->maxsize;
if (!con->improvement || bsize <0) {
return con->extra.name;
}
}
}
return btype->_name;
} }
#define BMAXHASH 7919 #define BMAXHASH 7919
@ -219,55 +244,6 @@ building *findbuilding(int i)
{ {
return bfindhash(i); return bfindhash(i);
} }
static const char *castle_name_i(const struct building_type *btype,
const struct building *b, int bsize, const char *fname[])
{
int i = bt_effsize(btype, b, bsize);
return fname[i];
}
static const char *castle_name_2(const struct building_type *btype,
const struct building *b, int bsize)
{
const char *fname[] = {
"site",
"fortification",
"tower",
"castle",
"fortress",
"citadel"
};
return castle_name_i(btype, b, bsize, fname);
}
static const char *castle_name(const struct building_type *btype,
const struct building *b, int bsize)
{
const char *fname[] = {
"site",
"tradepost",
"fortification",
"tower",
"castle",
"fortress",
"citadel"
};
return castle_name_i(btype, b, bsize, fname);
}
static const char *fort_name(const struct building_type *btype,
const struct building *b, int bsize)
{
const char *fname[] = {
"scaffolding",
"guardhouse",
"guardtower",
};
return castle_name_i(btype, b, bsize, fname);
}
/* for finding out what was meant by a particular building string */ /* for finding out what was meant by a particular building string */
static local_names *bnames; static local_names *bnames;
@ -486,24 +462,19 @@ int buildingeffsize(const building * b, int img)
int bt_effsize(const building_type * btype, const building * b, int bsize) int bt_effsize(const building_type * btype, const building * b, int bsize)
{ {
int i = bsize, n = 0; int n = 0;
const construction *cons = btype->construction; const construction *cons = btype->construction;
/* TECH DEBT: simplest thing that works for E3 dwarf/halfling faction rules */ if (b) {
if (b && config_get_int("rules.dwarf_castles", 0) bsize = adjust_size(b, bsize);
&& strcmp(btype->_name, "castle") == 0) {
unit *u = building_owner(b);
if (u && u->faction->race == get_race(RC_HALFLING)) {
i = bsize * 10 / 8;
}
} }
if (!cons || !cons->improvement) { if (!cons || !cons->improvement) {
return 0; return 0;
} }
while (cons && cons->maxsize != -1 && i >= cons->maxsize) { while (cons && cons->maxsize != -1 && bsize >= cons->maxsize) {
i -= cons->maxsize; bsize -= cons->maxsize;
cons = cons->improvement; cons = cons->improvement;
++n; ++n;
} }
@ -883,10 +854,3 @@ int cmp_current_owner(const building * b, const building * a)
} }
return -1; return -1;
} }
void register_buildings(void)
{
register_function((pf_generic)castle_name, "castle_name");
register_function((pf_generic)castle_name_2, "castle_name_2");
register_function((pf_generic)fort_name, "fort_name");
}

View File

@ -84,7 +84,6 @@ extern "C" {
bool bt_changed(int *cache); bool bt_changed(int *cache);
const building_type *bt_find(const char *name); const building_type *bt_find(const char *name);
void free_buildingtypes(void); void free_buildingtypes(void);
void register_buildings(void);
void bt_register(struct building_type *type); void bt_register(struct building_type *type);
int bt_effsize(const struct building_type *btype, int bt_effsize(const struct building_type *btype,
const struct building *b, int bsize); const struct building *b, int bsize);

View File

@ -214,7 +214,7 @@ xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
void void
xml_readconstruction(xmlXPathContextPtr xpath, xmlNodeSetPtr nodeSet, xml_readconstruction(xmlXPathContextPtr xpath, xmlNodeSetPtr nodeSet,
construction ** consPtr) construction ** consPtr, construct_t type)
{ {
xmlNodePtr pushNode = xpath->node; xmlNodePtr pushNode = xpath->node;
int k; int k;
@ -241,15 +241,25 @@ construction ** consPtr)
*consPtr = con = (construction *)calloc(sizeof(construction), 1); *consPtr = con = (construction *)calloc(sizeof(construction), 1);
consPtr = &con->improvement; consPtr = &con->improvement;
con->type = type;
con->skill = sk; con->skill = sk;
con->maxsize = xml_ivalue(node, "maxsize", -1); con->maxsize = xml_ivalue(node, "maxsize", -1);
con->minskill = xml_ivalue(node, "minskill", -1); con->minskill = xml_ivalue(node, "minskill", -1);
con->reqsize = xml_ivalue(node, "reqsize", 1); con->reqsize = xml_ivalue(node, "reqsize", 1);
propValue = xmlGetProp(node, BAD_CAST "building"); if (type == CONS_ITEM) {
if (propValue != NULL) { propValue = xmlGetProp(node, BAD_CAST "building");
con->btype = bt_get_or_create((const char *)propValue); if (propValue != NULL) {
xmlFree(propValue); con->extra.btype = bt_get_or_create((const char *)propValue);
xmlFree(propValue);
}
}
else if (type == CONS_BUILDING) {
propValue = xmlGetProp(node, BAD_CAST "name");
if (propValue != NULL) {
con->extra.name = strdup((const char *)propValue);
xmlFree(propValue);
}
} }
/* read construction/requirement */ /* read construction/requirement */
@ -337,7 +347,7 @@ static int parse_buildings(xmlDocPtr doc)
/* reading eressea/buildings/building/construction */ /* reading eressea/buildings/building/construction */
xpath->node = node; xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
xml_readconstruction(xpath, result->nodesetval, &btype->construction); xml_readconstruction(xpath, result->nodesetval, &btype->construction, CONS_BUILDING);
xmlXPathFreeObject(result); xmlXPathFreeObject(result);
/* reading eressea/buildings/building/function */ /* reading eressea/buildings/building/function */
@ -572,7 +582,7 @@ static int parse_ships(xmlDocPtr doc)
/* reading eressea/ships/ship/construction */ /* reading eressea/ships/ship/construction */
xpath->node = node; xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
xml_readconstruction(xpath, result->nodesetval, &st->construction); xml_readconstruction(xpath, result->nodesetval, &st->construction, CONS_OTHER);
xmlXPathFreeObject(result); xmlXPathFreeObject(result);
for (child = node->children; child; child = child->next) { for (child = node->children; child; child = child->next) {
@ -858,7 +868,7 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
/* reading item/construction */ /* reading item/construction */
xpath->node = node; xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
xml_readconstruction(xpath, result->nodesetval, &itype->construction); xml_readconstruction(xpath, result->nodesetval, &itype->construction, CONS_ITEM);
xmlXPathFreeObject(result); xmlXPathFreeObject(result);
/* reading item/weapon */ /* reading item/weapon */