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"?>
<building name="castle" capacity="1" fort="yes">
<function name="name" value="castle_name_2"/>
<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"/>
</construction>
<construction skill="building" minskill="2" maxsize="40">
<construction skill="building" minskill="2" maxsize="40" name="fortification">
<requirement type="stone" quantity="1"/>
</construction>
<construction skill="building" minskill="3" maxsize="200">
<construction skill="building" minskill="3" maxsize="200" name="tower">
<requirement type="stone" quantity="1"/>
</construction>
<construction skill="building" minskill="4" maxsize="1000">
<construction skill="building" minskill="4" maxsize="1000" name="castle">
<requirement type="stone" quantity="1"/>
</construction>
<construction skill="building" minskill="5" maxsize="5000">
<construction skill="building" minskill="5" maxsize="5000" name="fortress">
<requirement type="stone" quantity="1"/>
</construction>
<construction skill="building" minskill="6">
<construction skill="building" minskill="6" name="citadel">
<requirement type="stone" quantity="1"/>
</construction>
</building>

View File

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

View File

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

View File

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

View File

@ -70,7 +70,6 @@ void game_init(void)
register_spells();
register_names();
register_resources();
register_buildings();
register_itemfunctions();
#if MUSEUM_MODULE
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)
{
const construction *type = ctype;
const construction *con = ctype;
int skills = INT_MAX; /* number of skill points remainig */
int basesk = 0;
int made = 0;
if (want <= 0)
return 0;
if (type == NULL)
if (con == NULL)
return ENOMATERIALS;
if (type->improvement == NULL && completed == type->maxsize)
if (con->improvement == NULL && completed == con->maxsize)
return ECOMPLETE;
if (type->btype != NULL) {
if (con->type==CONS_ITEM && con->extra.btype) {
building *b;
if (!u->building || u->building->type != type->btype) {
if (!u->building || u->building->type != con->extra.btype) {
return EBUILDINGREQ;
}
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 dm = get_effect(u, oldpotiontype[P_DOMORE]);
assert(u->number);
basesk = effskill(u, type->skill, 0);
basesk = effskill(u, con->skill, 0);
if (basesk == 0)
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
* while material lasts type->improvement==x means build x when type
* is finished */
while (type && type->improvement &&
type->improvement != type &&
type->maxsize > 0 && type->maxsize <= completed) {
completed -= type->maxsize;
type = type->improvement;
while (con && con->improvement &&
con->improvement != con &&
con->maxsize > 0 && con->maxsize <= completed) {
completed -= con->maxsize;
con = con->improvement;
}
if (type == NULL) {
if (con == NULL) {
if (made == 0)
return ECOMPLETE;
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
* die gleiche wie die vorherige ist. z.b. gegenst<EFBFBD>nde.
*/
if (type->maxsize > 0) {
completed = completed % type->maxsize;
if (con->maxsize > 0) {
completed = completed % con->maxsize;
}
else {
completed = 0;
assert(type->reqsize >= 1);
assert(con->reqsize >= 1);
}
if (basesk < type->minskill) {
if (basesk < con->minskill) {
if (made == 0)
return ELOWSKILL;
else
@ -590,15 +590,15 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
}
/* n = maximum buildable size */
if (type->minskill > 1) {
n = skills / type->minskill;
if (con->minskill > 1) {
n = skills / con->minskill;
}
else {
n = skills;
}
/* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische)
* 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);
item *itm = ring ? *i_find(&u->items, ring->itype) : 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 (type->maxsize > 0) {
n = MIN(type->maxsize - completed, n);
if (type->improvement == NULL) {
if (con->maxsize > 0) {
n = MIN(con->maxsize - completed, n);
if (con->improvement == NULL) {
want = n;
}
}
n = count_materials(u, type, n, completed);
n = count_materials(u, con, n, completed);
if (n <= 0) {
if (made == 0)
return ENOMATERIALS;
else
break;
}
err = use_materials(u, type, n, completed);
err = use_materials(u, con, n, completed);
if (err < 0) {
return err;
}
made += n;
skills -= n * type->minskill;
skills -= n * con->minskill;
want -= n;
completed = completed + n;
}

View File

@ -37,15 +37,27 @@ extern "C" {
int number;
} requirement;
typedef enum construct_t {
CONS_OTHER,
CONS_ITEM,
CONS_BUILDING
} construct_t;
typedef struct construction {
construct_t type;
skill_t skill; /* skill req'd per point of size */
int minskill; /* skill req'd per point of size */
int maxsize; /* maximum size of this type */
int reqsize; /* size of object using up 1 set of requirement. */
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;
/* 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;
i_change(&u->items, rtype->itype, 1);
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->capacity = 1;
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
};
/* 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
* 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 *s;
const construction *con;
assert(btype);
s = btype->_name;
if (btype->name) {
s = btype->name(btype, b, bsize);
}
if (b && b->attribs) {
if (is_building_type(btype, "generic")) {
const attrib *a = a_find(b->attribs, &at_building_generic_type);
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
@ -219,55 +244,6 @@ building *findbuilding(int 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 */
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 i = bsize, n = 0;
int n = 0;
const construction *cons = btype->construction;
/* TECH DEBT: simplest thing that works for E3 dwarf/halfling faction rules */
if (b && config_get_int("rules.dwarf_castles", 0)
&& strcmp(btype->_name, "castle") == 0) {
unit *u = building_owner(b);
if (u && u->faction->race == get_race(RC_HALFLING)) {
i = bsize * 10 / 8;
}
if (b) {
bsize = adjust_size(b, bsize);
}
if (!cons || !cons->improvement) {
return 0;
}
while (cons && cons->maxsize != -1 && i >= cons->maxsize) {
i -= cons->maxsize;
while (cons && cons->maxsize != -1 && bsize >= cons->maxsize) {
bsize -= cons->maxsize;
cons = cons->improvement;
++n;
}
@ -883,10 +854,3 @@ int cmp_current_owner(const building * b, const building * a)
}
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);
const building_type *bt_find(const char *name);
void free_buildingtypes(void);
void register_buildings(void);
void bt_register(struct building_type *type);
int bt_effsize(const struct building_type *btype,
const struct building *b, int bsize);

View File

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