forked from github/server
WIP: reimplemented production modifiers.
The system itself seems to work, but some Lua tests are still failing.
This commit is contained in:
parent
4aa26343f6
commit
e72155a563
|
@ -93,7 +93,6 @@
|
||||||
</building>
|
</building>
|
||||||
|
|
||||||
<building name="smithy" capacity="1">
|
<building name="smithy" capacity="1">
|
||||||
<function name="init" value="init_smithy"/>
|
|
||||||
<maintenance type="money" amount="300"/>
|
<maintenance type="money" amount="300"/>
|
||||||
<maintenance type="log" amount="1"/>
|
<maintenance type="log" amount="1"/>
|
||||||
<construction skill="building" minskill="3">
|
<construction skill="building" minskill="3">
|
||||||
|
@ -102,6 +101,8 @@
|
||||||
<requirement type="iron" quantity="2"/>
|
<requirement type="iron" quantity="2"/>
|
||||||
<requirement type="money" quantity="200"/>
|
<requirement type="money" quantity="200"/>
|
||||||
</construction>
|
</construction>
|
||||||
|
<modifier type="skill" skill="weaponsmithing" value="1"/>
|
||||||
|
<modifier type="skill" skill="armorer" value="1"/>
|
||||||
</building>
|
</building>
|
||||||
|
|
||||||
<building name="magictower" maxcapacity="2" maxsize="50" magic="yes" magres="40" fumblebonus="10" auraregen="1.75">
|
<building name="magictower" maxcapacity="2" maxsize="50" magic="yes" magres="40" fumblebonus="10" auraregen="1.75">
|
||||||
|
|
|
@ -5539,6 +5539,15 @@
|
||||||
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Gegenstand kann die Einheit nicht herstellen."</text>
|
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Gegenstand kann die Einheit nicht herstellen."</text>
|
||||||
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit cannot produce that."</text>
|
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit cannot produce that."</text>
|
||||||
</message>
|
</message>
|
||||||
|
<message name="error117" section="errors">
|
||||||
|
<type>
|
||||||
|
<arg name="unit" type="unit"/>
|
||||||
|
<arg name="region" type="region"/>
|
||||||
|
<arg name="command" type="order"/>
|
||||||
|
</type>
|
||||||
|
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Rasse kann das nicht herstellen."</text>
|
||||||
|
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - This race cannot produce that."</text>
|
||||||
|
</message>
|
||||||
<message name="error116" section="errors">
|
<message name="error116" section="errors">
|
||||||
<type>
|
<type>
|
||||||
<arg name="unit" type="unit"/>
|
<arg name="unit" type="unit"/>
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
<item weight="500" score="10">
|
<item weight="500" score="10">
|
||||||
<construction skill="mining" minskill="1"/>
|
<construction skill="mining" minskill="1"/>
|
||||||
</item>
|
</item>
|
||||||
|
<modifier building="smithy" type="save" value="2"/>
|
||||||
<modifier building="mine" type="skill" value="1"/>
|
<modifier building="mine" type="skill" value="1"/>
|
||||||
<modifier building="mine" type="material" value="0.5"/>
|
<modifier building="mine" type="material" value="0.5"/>
|
||||||
<modifier race="dwarf" type="material" value="0.60"/>
|
<modifier race="dwarf" type="material" value="0.6"/>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="greatbow">
|
<resource name="greatbow">
|
||||||
|
<modifier type="require" race="elf"/>
|
||||||
<item weight="100">
|
<item weight="100">
|
||||||
<construction skill="weaponsmithing" minskill="5">
|
<construction skill="weaponsmithing" minskill="5">
|
||||||
<modifier function="mod_elves_only"/>
|
|
||||||
<requirement type="mallorn" quantity="2"/>
|
<requirement type="mallorn" quantity="2"/>
|
||||||
</construction>
|
</construction>
|
||||||
<weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0">
|
<weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0">
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="scale">
|
<resource name="scale">
|
||||||
|
<modifier type="require" race="dwarf"/>
|
||||||
<item weight="300" score="150" allow="dwarf halfling">
|
<item weight="300" score="150" allow="dwarf halfling">
|
||||||
<construction skill="armorer" minskill="5">
|
<construction skill="armorer" minskill="5">
|
||||||
<modifier function="mod_dwarves_only"/>
|
|
||||||
<requirement type="iron" quantity="2"/>
|
<requirement type="iron" quantity="2"/>
|
||||||
</construction>
|
</construction>
|
||||||
<armor ac="3" penalty="0.10" projectile="0.05" magres="0.0"/>
|
<armor ac="3" penalty="0.10" projectile="0.05" magres="0.0"/>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="towershield">
|
<resource name="towershield">
|
||||||
|
<modifier type="require" race="dwarf"/>
|
||||||
<item weight="200" score="60" allow="dwarf">
|
<item weight="200" score="60" allow="dwarf">
|
||||||
<construction skill="armorer" minskill="4">
|
<construction skill="armorer" minskill="4">
|
||||||
<modifier function="mod_dwarves_only"/>
|
|
||||||
<requirement type="iron" quantity="1"/>
|
<requirement type="iron" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<armor ac="0" penalty="-0.15" projectile="0.25" magres="0.0" shield="yes">
|
<armor ac="0" penalty="-0.15" projectile="0.25" magres="0.0" shield="yes">
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<item weight="500" score="10">
|
<item weight="500" score="10">
|
||||||
<construction skill="mining" minskill="1"/>
|
<construction skill="mining" minskill="1"/>
|
||||||
</item>
|
</item>
|
||||||
|
<modifier building="smithy" type="save" value="2"/>
|
||||||
<modifier building="mine" type="skill" value="1"/>
|
<modifier building="mine" type="skill" value="1"/>
|
||||||
<modifier building="mine" type="material" value="0.5"/>
|
<modifier building="mine" type="material" value="0.5"/>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* has lower damage
|
* has lower damage
|
||||||
-->
|
-->
|
||||||
<resource name="greatbow">
|
<resource name="greatbow">
|
||||||
|
<modifier type="require" race="elf"/>
|
||||||
<item weight="100" allow="elf">
|
<item weight="100" allow="elf">
|
||||||
<construction skill="weaponsmithing" minskill="5">
|
<construction skill="weaponsmithing" minskill="5">
|
||||||
<modifier function="mod_elves_only"/>
|
|
||||||
<requirement type="mallorn" quantity="2"/>
|
<requirement type="mallorn" quantity="2"/>
|
||||||
</construction>
|
</construction>
|
||||||
<weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0">
|
<weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0">
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="rep_crossbow">
|
<resource name="rep_crossbow">
|
||||||
|
<modifier type="require" race="dwarf"/>
|
||||||
<item weight="100" allow="dwarf halfling">
|
<item weight="100" allow="dwarf halfling">
|
||||||
<construction skill="weaponsmithing" minskill="5">
|
<construction skill="weaponsmithing" minskill="5">
|
||||||
<modifier function="mod_dwarves_only"/>
|
|
||||||
<requirement type="log" quantity="1"/>
|
<requirement type="log" quantity="1"/>
|
||||||
<requirement type="iron" quantity="1"/>
|
<requirement type="iron" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
|
|
|
@ -124,6 +124,33 @@ function test_quarry_bonus()
|
||||||
turn_end()
|
turn_end()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function test_smithy_no_bonus()
|
||||||
|
-- a smithy does not give a bonus to other skills
|
||||||
|
-- five cartmakers make 5 carts, no matter what
|
||||||
|
local r = region.create(0, 0, 'mountain')
|
||||||
|
local f = create_faction('human')
|
||||||
|
local u = unit.create(f, r, 1)
|
||||||
|
|
||||||
|
turn_begin()
|
||||||
|
u.building = building.create(u.region, 'smithy')
|
||||||
|
u.building.working = false
|
||||||
|
u.building.size = 10
|
||||||
|
u.number = 5
|
||||||
|
u:set_skill('cartmaking', 1) -- needs 1 min
|
||||||
|
u:add_item('log', 100)
|
||||||
|
u:add_order("MACHE Wagen")
|
||||||
|
turn_process() -- building disabled
|
||||||
|
assert_equal(5, u:get_item('cart'))
|
||||||
|
assert_equal(75, u:get_item('log'))
|
||||||
|
|
||||||
|
u.building.working = true
|
||||||
|
turn_process() -- building active
|
||||||
|
assert_equal(10, u:get_item('cart'))
|
||||||
|
assert_equal(50, u:get_item('log'))
|
||||||
|
|
||||||
|
turn_end()
|
||||||
|
end
|
||||||
|
|
||||||
function test_smithy_bonus_iron()
|
function test_smithy_bonus_iron()
|
||||||
-- a smithy adds +1 to weaponsmithing, and saves 50% iron
|
-- a smithy adds +1 to weaponsmithing, and saves 50% iron
|
||||||
local r = region.create(0, 0, 'mountain')
|
local r = region.create(0, 0, 'mountain')
|
||||||
|
|
|
@ -12,7 +12,6 @@ follow.c
|
||||||
hate.c
|
hate.c
|
||||||
iceberg.c
|
iceberg.c
|
||||||
key.c
|
key.c
|
||||||
matmod.c
|
|
||||||
moved.c
|
moved.c
|
||||||
movement.c
|
movement.c
|
||||||
dict.c
|
dict.c
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
|
||||||
Katja Zedel <katze@felidae.kn-bremen.de
|
|
||||||
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include <platform.h>
|
|
||||||
#include "matmod.h"
|
|
||||||
|
|
||||||
#include <util/attrib.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
attrib_type at_matmod = {
|
|
||||||
"matmod",
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
ATF_PRESERVE
|
|
||||||
};
|
|
||||||
|
|
||||||
attrib *make_matmod(mm_fun function)
|
|
||||||
{
|
|
||||||
attrib *a = a_new(&at_matmod);
|
|
||||||
a->data.f = (void(*)(void))function;
|
|
||||||
return a;
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
|
||||||
Katja Zedel <katze@felidae.kn-bremen.de
|
|
||||||
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef H_ATTRIBUTE_MATMOD
|
|
||||||
#define H_ATTRIBUTE_MATMOD
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct resource_type;
|
|
||||||
struct unit;
|
|
||||||
typedef int(*mm_fun) (const struct unit * u,
|
|
||||||
const struct resource_type * rtype, int value);
|
|
||||||
|
|
||||||
extern struct attrib_type at_matmod;
|
|
||||||
extern struct attrib *make_matmod(mm_fun function);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
125
src/economy.c
125
src/economy.c
|
@ -798,7 +798,69 @@ void economics(region * r)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
static void mod_skill(const resource_mod *mod, skill_t sk, int *skill) {
|
||||||
|
skill_t msk;
|
||||||
|
assert(mod->type == RMT_PROD_SKILL);
|
||||||
|
msk = (skill_t)mod->value.sa[0];
|
||||||
|
if (msk == NOSKILL || msk == sk) {
|
||||||
|
*skill += mod->value.sa[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct message * get_modifiers(unit *u, skill_t sk, const resource_type *rtype, variant *savep, int *skillp) {
|
||||||
|
struct building *b = inside_building(u);
|
||||||
|
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
|
||||||
|
int save_n = 1, save_d = 1;
|
||||||
|
int skill = 0;
|
||||||
|
int need_race = 0, need_bldg = 0;
|
||||||
|
resource_mod *mod;
|
||||||
|
|
||||||
|
if (btype && btype->modifiers) {
|
||||||
|
for (mod = btype->modifiers; mod && mod->type != RMT_END; ++mod) {
|
||||||
|
if (mod->type == RMT_PROD_SKILL) {
|
||||||
|
mod_skill(mod, sk, &skill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
switch (mod->type) {
|
||||||
|
case RMT_PROD_SAVE:
|
||||||
|
if (savep) {
|
||||||
|
save_n *= mod->value.sa[0];
|
||||||
|
save_d *= mod->value.sa[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RMT_PROD_SKILL:
|
||||||
|
mod_skill(mod, sk, &skill);
|
||||||
|
break;
|
||||||
|
case RMT_PROD_REQUIRE:
|
||||||
|
if (mod->race) need_race |= 1;
|
||||||
|
if (mod->btype) need_bldg |= 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* is not a production modifier, ignore it */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mod->type == RMT_PROD_REQUIRE) {
|
||||||
|
if (mod->race) need_race |= 2;
|
||||||
|
if (mod->btype) need_bldg |= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (need_race == 2) {
|
||||||
|
return msg_error(u, u->thisorder, 117);
|
||||||
|
}
|
||||||
|
if (need_bldg == 2) {
|
||||||
|
return msg_error(u, u->thisorder, 104);
|
||||||
|
}
|
||||||
|
*skillp = skill;
|
||||||
|
if (savep) *savep = frac_make(save_n, save_d);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void manufacture(unit * u, const item_type * itype, int want)
|
static void manufacture(unit * u, const item_type * itype, int want)
|
||||||
{
|
{
|
||||||
|
@ -806,22 +868,20 @@ static void manufacture(unit * u, const item_type * itype, int want)
|
||||||
int skill;
|
int skill;
|
||||||
int minskill = itype->construction->minskill;
|
int minskill = itype->construction->minskill;
|
||||||
skill_t sk = itype->construction->skill;
|
skill_t sk = itype->construction->skill;
|
||||||
|
message *msg;
|
||||||
|
int skill_mod;
|
||||||
|
|
||||||
skill = effskill(u, sk, 0);
|
msg = get_modifiers(u, sk, itype->rtype, NULL, &skill_mod);
|
||||||
skill =
|
if (msg) {
|
||||||
skillmod(itype->construction->attribs, u, u->region, sk, skill, SMF_PRODUCTION);
|
ADDMSG(&u->faction->msgs, msg);
|
||||||
|
|
||||||
if (skill < 0) {
|
|
||||||
/* an error occured */
|
|
||||||
int err = -skill;
|
|
||||||
cmistake(u, u->thisorder, err, MSG_PRODUCE);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skill = effskill(u, sk, 0);
|
||||||
if (want == 0) {
|
if (want == 0) {
|
||||||
want = maxbuild(u, itype->construction);
|
want = maxbuild(u, itype->construction);
|
||||||
}
|
}
|
||||||
n = build(u, itype->construction, 0, want);
|
n = build(u, itype->construction, 0, want, skill_mod);
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case ENEEDSKILL:
|
case ENEEDSKILL:
|
||||||
ADDMSG(&u->faction->msgs,
|
ADDMSG(&u->faction->msgs,
|
||||||
|
@ -879,38 +939,6 @@ enum {
|
||||||
AFL_LOWSKILL = 1 << 1
|
AFL_LOWSKILL = 1 << 1
|
||||||
};
|
};
|
||||||
|
|
||||||
struct message * get_modifiers(unit *u, const resource_type *rtype, variant *savep, int *skillp) {
|
|
||||||
struct building *b = inside_building(u);
|
|
||||||
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
|
|
||||||
int save_n = 1, save_d = 1;
|
|
||||||
int skill = 0;
|
|
||||||
resource_mod *mod;
|
|
||||||
|
|
||||||
for (mod = rtype->modifiers; mod && mod->flags != 0; ++mod) {
|
|
||||||
if (mod->btype == NULL || mod->btype == btype) {
|
|
||||||
if (mod->race == NULL || mod->race == u_race(u)) {
|
|
||||||
if (mod->flags & RMF_SAVEMATERIAL) {
|
|
||||||
save_n *= mod->value.sa[0];
|
|
||||||
save_d *= mod->value.sa[1];
|
|
||||||
}
|
|
||||||
if (mod->flags & RMF_SKILL) {
|
|
||||||
skill += mod->value.i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (mod->flags & RMF_REQUIREDBUILDING) {
|
|
||||||
return msg_error(u, u->thisorder, 104);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*skillp = skill;
|
|
||||||
assert(save_n < SHRT_MAX);
|
|
||||||
assert(save_n > SHRT_MIN);
|
|
||||||
assert(save_d < SHRT_MAX);
|
|
||||||
assert(save_d > SHRT_MIN);
|
|
||||||
savep->sa[0] = (short)save_n;
|
|
||||||
savep->sa[1] = (short)save_d;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void allocate_resource(unit * u, const resource_type * rtype, int want)
|
static void allocate_resource(unit * u, const resource_type * rtype, int want)
|
||||||
{
|
{
|
||||||
const item_type *itype = resource2item(rtype);
|
const item_type *itype = resource2item(rtype);
|
||||||
|
@ -921,12 +949,14 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
|
||||||
const resource_type *rring;
|
const resource_type *rring;
|
||||||
int amount, skill, skill_mod = 0;
|
int amount, skill, skill_mod = 0;
|
||||||
variant save_mod;
|
variant save_mod;
|
||||||
|
skill_t sk;
|
||||||
|
|
||||||
/* momentan kann man keine ressourcen abbauen, wenn man daf<61>r
|
/* momentan kann man keine ressourcen abbauen, wenn man daf<61>r
|
||||||
* Materialverbrauch hat: */
|
* Materialverbrauch hat: */
|
||||||
assert(itype != NULL && (itype->construction == NULL
|
assert(itype != NULL && (itype->construction == NULL
|
||||||
|| itype->construction->materials == NULL));
|
|| itype->construction->materials == NULL));
|
||||||
|
|
||||||
|
sk = itype->construction->skill;
|
||||||
if (!rtype->raw) {
|
if (!rtype->raw) {
|
||||||
int avail = limit_resource(r, rtype);
|
int avail = limit_resource(r, rtype);
|
||||||
if (avail <= 0) {
|
if (avail <= 0) {
|
||||||
|
@ -941,7 +971,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtype->modifiers) {
|
if (rtype->modifiers) {
|
||||||
message *msg = get_modifiers(u, rtype, &save_mod, &skill_mod);
|
message *msg = get_modifiers(u, sk, rtype, &save_mod, &skill_mod);
|
||||||
if (msg) {
|
if (msg) {
|
||||||
ADDMSG(&u->faction->msgs, msg);
|
ADDMSG(&u->faction->msgs, msg);
|
||||||
return;
|
return;
|
||||||
|
@ -969,17 +999,14 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(itype->construction->skill != 0
|
assert(sk != NOSKILL || "limited resource needs a required skill for making it");
|
||||||
|| "limited resource needs a required skill for making it");
|
skill = effskill(u, sk, 0);
|
||||||
skill = effskill(u, itype->construction->skill, 0);
|
|
||||||
if (skill == 0) {
|
if (skill == 0) {
|
||||||
skill_t sk = itype->construction->skill;
|
|
||||||
add_message(&u->faction->msgs,
|
add_message(&u->faction->msgs,
|
||||||
msg_feedback(u, u->thisorder, "skill_needed", "skill", sk));
|
msg_feedback(u, u->thisorder, "skill_needed", "skill", sk));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (skill < itype->construction->minskill) {
|
if (skill < itype->construction->minskill) {
|
||||||
skill_t sk = itype->construction->skill;
|
|
||||||
add_message(&u->faction->msgs,
|
add_message(&u->faction->msgs,
|
||||||
msg_feedback(u, u->thisorder, "manufacture_skills",
|
msg_feedback(u, u->thisorder, "manufacture_skills",
|
||||||
"skill minskill product", sk, itype->construction->minskill,
|
"skill minskill product", sk, itype->construction->minskill,
|
||||||
|
@ -1204,7 +1231,7 @@ static void create_potion(unit * u, const potion_type * ptype, int want)
|
||||||
if (want == 0) {
|
if (want == 0) {
|
||||||
want = maxbuild(u, ptype->itype->construction);
|
want = maxbuild(u, ptype->itype->construction);
|
||||||
}
|
}
|
||||||
built = build(u, ptype->itype->construction, 0, want);
|
built = build(u, ptype->itype->construction, 0, want, 0);
|
||||||
switch (built) {
|
switch (built) {
|
||||||
case ELOWSKILL:
|
case ELOWSKILL:
|
||||||
case ENEEDSKILL:
|
case ENEEDSKILL:
|
||||||
|
|
|
@ -345,7 +345,114 @@ static void test_income(CuTest *tc)
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_make_item(CuTest *tc) {
|
static void test_modify_material(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
struct item_type *itype;
|
||||||
|
resource_type *rtype;
|
||||||
|
resource_mod *mod;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
init_resources();
|
||||||
|
|
||||||
|
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||||
|
set_level(u, SK_WEAPONSMITH, 1);
|
||||||
|
|
||||||
|
/* the unit's race gets 2x savings on iron used to produce goods */
|
||||||
|
itype = test_create_itemtype("iron");
|
||||||
|
rtype = itype->rtype;
|
||||||
|
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);
|
||||||
|
|
||||||
|
itype = test_create_itemtype("sword");
|
||||||
|
make_item(u, itype, 1);
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_cannotmake"));
|
||||||
|
CuAssertIntEquals(tc, 0, get_item(u, itype));
|
||||||
|
test_clear_messages(u->faction);
|
||||||
|
itype->construction = calloc(1, sizeof(construction));
|
||||||
|
itype->construction->skill = SK_WEAPONSMITH;
|
||||||
|
itype->construction->minskill = 1;
|
||||||
|
itype->construction->maxsize = 1;
|
||||||
|
itype->construction->reqsize = 1;
|
||||||
|
itype->construction->materials = calloc(2, sizeof(requirement));
|
||||||
|
itype->construction->materials[0].rtype = rtype;
|
||||||
|
itype->construction->materials[0].number = 2;
|
||||||
|
|
||||||
|
set_item(u, rtype->itype, 1); /* 1 iron should get us 1 sword */
|
||||||
|
make_item(u, itype, 1);
|
||||||
|
CuAssertIntEquals(tc, 1, get_item(u, itype));
|
||||||
|
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
|
||||||
|
|
||||||
|
u_setrace(u, test_create_race("smurf"));
|
||||||
|
set_item(u, rtype->itype, 2); /* 2 iron should be required now */
|
||||||
|
make_item(u, itype, 1);
|
||||||
|
CuAssertIntEquals(tc, 2, get_item(u, itype));
|
||||||
|
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modify_skill(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
struct item_type *itype;
|
||||||
|
/* building_type *btype; */
|
||||||
|
resource_type *rtype;
|
||||||
|
resource_mod *mod;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
init_resources();
|
||||||
|
|
||||||
|
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||||
|
set_level(u, SK_WEAPONSMITH, 1);
|
||||||
|
|
||||||
|
itype = test_create_itemtype("iron");
|
||||||
|
rtype = itype->rtype;
|
||||||
|
|
||||||
|
itype = test_create_itemtype("sword");
|
||||||
|
make_item(u, itype, 1);
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_cannotmake"));
|
||||||
|
CuAssertIntEquals(tc, 0, get_item(u, itype));
|
||||||
|
test_clear_messages(u->faction);
|
||||||
|
itype->construction = calloc(1, sizeof(construction));
|
||||||
|
itype->construction->skill = SK_WEAPONSMITH;
|
||||||
|
itype->construction->minskill = 1;
|
||||||
|
itype->construction->maxsize = -1;
|
||||||
|
itype->construction->reqsize = 1;
|
||||||
|
itype->construction->materials = calloc(2, sizeof(requirement));
|
||||||
|
itype->construction->materials[0].rtype = rtype;
|
||||||
|
itype->construction->materials[0].number = 1;
|
||||||
|
|
||||||
|
/* our race gets a +1 bonus to the item's production skill */
|
||||||
|
mod = itype->rtype->modifiers = calloc(2, sizeof(resource_mod));
|
||||||
|
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);
|
||||||
|
|
||||||
|
set_item(u, rtype->itype, 2); /* 2 iron should get us 2 swords */
|
||||||
|
make_item(u, itype, 2);
|
||||||
|
CuAssertIntEquals(tc, 2, get_item(u, itype));
|
||||||
|
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
|
||||||
|
|
||||||
|
mod[0].value.sa[0] = NOSKILL; /* match any skill */
|
||||||
|
set_item(u, rtype->itype, 2);
|
||||||
|
make_item(u, itype, 2);
|
||||||
|
CuAssertIntEquals(tc, 4, get_item(u, itype));
|
||||||
|
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
|
||||||
|
|
||||||
|
|
||||||
|
u_setrace(u, test_create_race("smurf"));
|
||||||
|
set_item(u, rtype->itype, 2);
|
||||||
|
make_item(u, itype, 1); /* only enough skill to make 1 now */
|
||||||
|
CuAssertIntEquals(tc, 5, get_item(u, itype));
|
||||||
|
CuAssertIntEquals(tc, 1, get_item(u, rtype->itype));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_modify_production(CuTest *tc) {
|
||||||
unit *u;
|
unit *u;
|
||||||
struct item_type *itype;
|
struct item_type *itype;
|
||||||
const struct resource_type *rt_silver;
|
const struct resource_type *rt_silver;
|
||||||
|
@ -393,7 +500,7 @@ static void test_make_item(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, 290, region_getresource(u->region, rtype)); /* used 10 stones to make 10 stones */
|
CuAssertIntEquals(tc, 290, region_getresource(u->region, rtype)); /* used 10 stones to make 10 stones */
|
||||||
|
|
||||||
rtype->modifiers = calloc(2, sizeof(resource_mod));
|
rtype->modifiers = calloc(2, sizeof(resource_mod));
|
||||||
rtype->modifiers[0].flags = RMF_SAVEMATERIAL;
|
rtype->modifiers[0].type = RMT_PROD_SAVE;
|
||||||
rtype->modifiers[0].race = u->_race;
|
rtype->modifiers[0].race = u->_race;
|
||||||
rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d);
|
rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d);
|
||||||
rtype->modifiers[0].value.sa[1] = 100;
|
rtype->modifiers[0].value.sa[1] = 100;
|
||||||
|
@ -413,13 +520,34 @@ static void test_make_item(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, 28, get_item(u, itype));
|
CuAssertIntEquals(tc, 28, get_item(u, itype));
|
||||||
CuAssertIntEquals(tc, 280, region_getresource(u->region, rtype)); /* 50% saving = 3 stones make 6 stones */
|
CuAssertIntEquals(tc, 280, region_getresource(u->region, rtype)); /* 50% saving = 3 stones make 6 stones */
|
||||||
|
|
||||||
rtype->modifiers[0].flags = RMF_REQUIREDBUILDING;
|
rtype->modifiers[0].type = RMT_PROD_REQUIRE;
|
||||||
rtype->modifiers[0].race = NULL;
|
rtype->modifiers[0].race = NULL;
|
||||||
rtype->modifiers[0].btype = bt_get_or_create("mine");
|
rtype->modifiers[0].btype = bt_get_or_create("mine");
|
||||||
|
|
||||||
|
test_clear_messages(u->faction);
|
||||||
make_item(u, itype, 10);
|
make_item(u, itype, 10);
|
||||||
|
CuAssertIntEquals(tc, 28, get_item(u, itype));
|
||||||
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error104"));
|
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error104"));
|
||||||
|
|
||||||
|
rtype->modifiers[0].type = RMT_PROD_REQUIRE;
|
||||||
|
rtype->modifiers[0].race = test_create_race("smurf");
|
||||||
|
rtype->modifiers[0].btype = NULL;
|
||||||
|
|
||||||
|
test_clear_messages(u->faction);
|
||||||
|
make_item(u, itype, 10);
|
||||||
|
CuAssertIntEquals(tc, 28, get_item(u, itype));
|
||||||
|
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].btype = NULL;
|
||||||
|
|
||||||
|
test_clear_messages(u->faction);
|
||||||
|
make_item(u, itype, 10);
|
||||||
|
CuAssertPtrEquals(tc, NULL, u->faction->msgs);
|
||||||
|
split_allocations(u->region);
|
||||||
|
CuAssertIntEquals(tc, 38, get_item(u, itype));
|
||||||
|
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +557,9 @@ CuSuite *get_economy_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_give_control_building);
|
SUITE_ADD_TEST(suite, test_give_control_building);
|
||||||
SUITE_ADD_TEST(suite, test_give_control_ship);
|
SUITE_ADD_TEST(suite, test_give_control_ship);
|
||||||
SUITE_ADD_TEST(suite, test_income);
|
SUITE_ADD_TEST(suite, test_income);
|
||||||
SUITE_ADD_TEST(suite, test_make_item);
|
SUITE_ADD_TEST(suite, test_modify_production);
|
||||||
|
SUITE_ADD_TEST(suite, test_modify_skill);
|
||||||
|
SUITE_ADD_TEST(suite, test_modify_material);
|
||||||
SUITE_ADD_TEST(suite, test_steal_okay);
|
SUITE_ADD_TEST(suite, test_steal_okay);
|
||||||
SUITE_ADD_TEST(suite, test_steal_ocean);
|
SUITE_ADD_TEST(suite, test_steal_ocean);
|
||||||
SUITE_ADD_TEST(suite, test_steal_nosteal);
|
SUITE_ADD_TEST(suite, test_steal_nosteal);
|
||||||
|
|
|
@ -43,6 +43,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <kernel/pool.h>
|
#include <kernel/pool.h>
|
||||||
#include <kernel/race.h>
|
#include <kernel/race.h>
|
||||||
#include <kernel/region.h>
|
#include <kernel/region.h>
|
||||||
|
#include <kernel/resources.h>
|
||||||
#include <kernel/ship.h>
|
#include <kernel/ship.h>
|
||||||
#include <kernel/terrain.h>
|
#include <kernel/terrain.h>
|
||||||
#include <kernel/terrainid.h>
|
#include <kernel/terrainid.h>
|
||||||
|
@ -67,9 +68,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* attributes inclues */
|
|
||||||
#include <attributes/matmod.h>
|
|
||||||
|
|
||||||
struct building *getbuilding(const struct region *r)
|
struct building *getbuilding(const struct region *r)
|
||||||
{
|
{
|
||||||
building *b = findbuilding(getid());
|
building *b = findbuilding(getid());
|
||||||
|
@ -404,16 +402,26 @@ static int required(int size, int msize, int maxneed)
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int matmod(const unit * u, const resource_type * rtype, int value)
|
||||||
matmod(const attrib * a, const unit * u, const resource_type * material,
|
|
||||||
int value)
|
|
||||||
{
|
{
|
||||||
for (a = a_find((attrib *)a, &at_matmod); a && a->type == &at_matmod;
|
if (rtype->modifiers) {
|
||||||
a = a->next) {
|
variant save = frac_make(1, 1);
|
||||||
mm_fun fun = (mm_fun)a->data.f;
|
const struct building_type *btype = NULL;
|
||||||
value = fun(u, material, value);
|
const struct race *rc = u_race(u);
|
||||||
if (value < 0)
|
resource_mod *mod;
|
||||||
return value; /* pass errors to caller */
|
if (u->building && inside_building(u)) {
|
||||||
|
btype = u->building->type;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
save = frac_mul(save, mod->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value * save.sa[0] / save.sa[1];
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -439,14 +447,8 @@ static int use_materials(unit *u, const construction *type, int n, int completed
|
||||||
required(completed + n, type->reqsize, type->materials[c].number);
|
required(completed + n, type->reqsize, type->materials[c].number);
|
||||||
int multi = 1;
|
int multi = 1;
|
||||||
int canuse = 100; /* normalization */
|
int canuse = 100; /* normalization */
|
||||||
if (building_is_active(u->building) && inside_building(u)) {
|
canuse = matmod(u, rtype, canuse);
|
||||||
canuse = matmod(u->building->type->attribs, u, rtype, canuse);
|
assert(canuse >= 0);
|
||||||
}
|
|
||||||
if (canuse < 0) {
|
|
||||||
return canuse; /* pass errors to caller */
|
|
||||||
}
|
|
||||||
canuse = matmod(type->attribs, u, rtype, canuse);
|
|
||||||
|
|
||||||
assert(canuse % 100 == 0
|
assert(canuse % 100 == 0
|
||||||
|| !"only constant multipliers are implemented in build()");
|
|| !"only constant multipliers are implemented in build()");
|
||||||
multi = canuse / 100;
|
multi = canuse / 100;
|
||||||
|
@ -468,14 +470,9 @@ static int count_materials(unit *u, const construction *type, int n, int complet
|
||||||
const struct resource_type *rtype = type->materials[c].rtype;
|
const struct resource_type *rtype = type->materials[c].rtype;
|
||||||
int need, prebuilt;
|
int need, prebuilt;
|
||||||
int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX);
|
int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX);
|
||||||
|
canuse = matmod(u, rtype, canuse);
|
||||||
|
|
||||||
if (building_is_active(u->building) && inside_building(u)) {
|
assert(canuse >= 0);
|
||||||
canuse = matmod(u->building->type->attribs, u, rtype, canuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canuse < 0)
|
|
||||||
return canuse; /* pass errors to caller */
|
|
||||||
canuse = matmod(type->attribs, u, rtype, canuse);
|
|
||||||
if (type->reqsize > 1) {
|
if (type->reqsize > 1) {
|
||||||
prebuilt =
|
prebuilt =
|
||||||
required(completed, type->reqsize, type->materials[c].number);
|
required(completed, type->reqsize, type->materials[c].number);
|
||||||
|
@ -503,7 +500,7 @@ static int count_materials(unit *u, const construction *type, int n, int complet
|
||||||
* of the first object have already been finished. return the
|
* of the first object have already been finished. return the
|
||||||
* actual size that could be built.
|
* actual size that could be built.
|
||||||
*/
|
*/
|
||||||
int build(unit * u, const construction * ctype, int completed, int want)
|
int build(unit * u, const construction * ctype, int completed, int want, int skill_mod)
|
||||||
{
|
{
|
||||||
const construction *type = ctype;
|
const construction *type = ctype;
|
||||||
int skills = INT_MAX; /* number of skill points remainig */
|
int skills = INT_MAX; /* number of skill points remainig */
|
||||||
|
@ -536,17 +533,8 @@ int build(unit * u, const construction * ctype, int completed, int want)
|
||||||
if (basesk == 0)
|
if (basesk == 0)
|
||||||
return ENEEDSKILL;
|
return ENEEDSKILL;
|
||||||
|
|
||||||
effsk = basesk;
|
effsk = basesk + skill_mod;
|
||||||
if (building_is_active(u->building) && inside_building(u)) {
|
assert(effsk >= 0);
|
||||||
effsk = skillmod(u->building->type->attribs, u, u->region, type->skill,
|
|
||||||
effsk, SMF_PRODUCTION);
|
|
||||||
}
|
|
||||||
effsk = skillmod(type->attribs, u, u->region, type->skill,
|
|
||||||
effsk, SMF_PRODUCTION);
|
|
||||||
if (effsk < 0)
|
|
||||||
return effsk; /* pass errors to caller */
|
|
||||||
if (effsk == 0)
|
|
||||||
return ENEEDSKILL;
|
|
||||||
|
|
||||||
skills = effsk * u->number;
|
skills = effsk * u->number;
|
||||||
|
|
||||||
|
@ -799,7 +787,7 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
built = build(u, btype->construction, built, n);
|
built = build(u, btype->construction, built, n, 0);
|
||||||
|
|
||||||
switch (built) {
|
switch (built) {
|
||||||
case ECOMPLETE:
|
case ECOMPLETE:
|
||||||
|
@ -884,7 +872,7 @@ static void build_ship(unit * u, ship * sh, int want)
|
||||||
const construction *construction = sh->type->construction;
|
const construction *construction = sh->type->construction;
|
||||||
int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE;
|
int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE;
|
||||||
int n;
|
int n;
|
||||||
int can = build(u, construction, size, want);
|
int can = build(u, construction, size, want, 0);
|
||||||
|
|
||||||
if ((n = construction->maxsize - sh->size) > 0 && can > 0) {
|
if ((n = construction->maxsize - sh->size) > 0 && can > 0) {
|
||||||
if (can >= n) {
|
if (can >= n) {
|
||||||
|
|
|
@ -55,9 +55,6 @@ extern "C" {
|
||||||
* last level of a building points to NULL, as do objects of
|
* last level of a building points to NULL, as do objects of
|
||||||
* an unlimited size.
|
* an unlimited size.
|
||||||
*/
|
*/
|
||||||
struct attrib *attribs;
|
|
||||||
/* stores skill modifiers and other attributes */
|
|
||||||
|
|
||||||
} construction;
|
} construction;
|
||||||
|
|
||||||
void free_construction(struct construction *cons);
|
void free_construction(struct construction *cons);
|
||||||
|
@ -76,7 +73,7 @@ extern "C" {
|
||||||
void sunhash(struct ship *sh);
|
void sunhash(struct ship *sh);
|
||||||
int roqf_factor(void);
|
int roqf_factor(void);
|
||||||
|
|
||||||
int build(struct unit *u, const construction * ctype, int completed, int want);
|
int build(struct unit *u, const construction * ctype, int completed, int want, int skill_mod);
|
||||||
int maxbuild(const struct unit *u, const construction * cons);
|
int maxbuild(const struct unit *u, const construction * cons);
|
||||||
struct message *msg_materials_required(struct unit *u, struct order *ord,
|
struct message *msg_materials_required(struct unit *u, struct order *ord,
|
||||||
const struct construction *ctype, int multi);
|
const struct construction *ctype, int multi);
|
||||||
|
|
|
@ -63,10 +63,10 @@ static void test_build_requires_materials(CuTest *tc) {
|
||||||
|
|
||||||
u = setup_build(&bf);
|
u = setup_build(&bf);
|
||||||
set_level(u, SK_ARMORER, 2);
|
set_level(u, SK_ARMORER, 2);
|
||||||
CuAssertIntEquals(tc, ENOMATERIALS, build(u, &bf.cons, 0, 1));
|
CuAssertIntEquals(tc, ENOMATERIALS, build(u, &bf.cons, 0, 1, 0));
|
||||||
itype = bf.cons.materials[0].rtype->itype;
|
itype = bf.cons.materials[0].rtype->itype;
|
||||||
i_change(&u->items, itype, 2);
|
i_change(&u->items, itype, 2);
|
||||||
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1));
|
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1, 0));
|
||||||
CuAssertIntEquals(tc, 1, i_get(u->items, itype));
|
CuAssertIntEquals(tc, 1, i_get(u->items, itype));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
@ -84,12 +84,12 @@ static void test_build_requires_building(CuTest *tc) {
|
||||||
bf.cons.btype = btype = bt_get_or_create("hodor");
|
bf.cons.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));
|
CuAssertIntEquals_Msg(tc, "must be inside a production building", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0));
|
||||||
u->building = test_create_building(u->region, btype);
|
u->building = test_create_building(u->region, btype);
|
||||||
fset(u->building, BLD_MAINTAINED);
|
fset(u->building, BLD_MAINTAINED);
|
||||||
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1));
|
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1, 0));
|
||||||
btype->maxcapacity = 0;
|
btype->maxcapacity = 0;
|
||||||
CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1));
|
CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ static void test_build_failure_missing_skill(CuTest *tc) {
|
||||||
u = setup_build(&bf);
|
u = setup_build(&bf);
|
||||||
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);
|
||||||
CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1));
|
CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1, 0));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ static void test_build_failure_low_skill(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, bf.cons.minskill - 1);
|
set_level(u, SK_ARMORER, bf.cons.minskill - 1);
|
||||||
CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10));
|
CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10, 0));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ static void test_build_failure_completed(CuTest *tc) {
|
||||||
i_change(&u->items, rtype->itype, 1);
|
i_change(&u->items, rtype->itype, 1);
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill);
|
set_level(u, SK_ARMORER, bf.cons.minskill);
|
||||||
bf.cons.maxsize = 1;
|
bf.cons.maxsize = 1;
|
||||||
CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10));
|
CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10, 0));
|
||||||
CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype));
|
CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
@ -143,19 +143,19 @@ static void test_build_limits(CuTest *tc) {
|
||||||
assert(rtype);
|
assert(rtype);
|
||||||
i_change(&u->items, rtype->itype, 1);
|
i_change(&u->items, rtype->itype, 1);
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill);
|
set_level(u, SK_ARMORER, bf.cons.minskill);
|
||||||
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 10));
|
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 10, 0));
|
||||||
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
|
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
|
||||||
|
|
||||||
scale_number(u, 2);
|
scale_number(u, 2);
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill);
|
set_level(u, SK_ARMORER, bf.cons.minskill);
|
||||||
i_change(&u->items, rtype->itype, 2);
|
i_change(&u->items, rtype->itype, 2);
|
||||||
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 10));
|
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 10, 0));
|
||||||
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
|
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
|
||||||
|
|
||||||
scale_number(u, 2);
|
scale_number(u, 2);
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill * 2);
|
set_level(u, SK_ARMORER, bf.cons.minskill * 2);
|
||||||
i_change(&u->items, rtype->itype, 4);
|
i_change(&u->items, rtype->itype, 4);
|
||||||
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 10));
|
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 10, 0));
|
||||||
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
|
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ static void test_build_with_ring(CuTest *tc) {
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill);
|
set_level(u, SK_ARMORER, bf.cons.minskill);
|
||||||
i_change(&u->items, rtype->itype, 20);
|
i_change(&u->items, rtype->itype, 20);
|
||||||
i_change(&u->items, ring, 1);
|
i_change(&u->items, ring, 1);
|
||||||
CuAssertIntEquals(tc, 10, build(u, &bf.cons, 0, 20));
|
CuAssertIntEquals(tc, 10, build(u, &bf.cons, 0, 20, 0));
|
||||||
CuAssertIntEquals(tc, 10, i_get(u->items, rtype->itype));
|
CuAssertIntEquals(tc, 10, i_get(u->items, rtype->itype));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
@ -193,16 +193,16 @@ static void test_build_with_potion(CuTest *tc) {
|
||||||
i_change(&u->items, rtype->itype, 20);
|
i_change(&u->items, rtype->itype, 20);
|
||||||
change_effect(u, ptype, 4);
|
change_effect(u, ptype, 4);
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill);
|
set_level(u, SK_ARMORER, bf.cons.minskill);
|
||||||
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 20));
|
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 20, 0));
|
||||||
CuAssertIntEquals(tc, 18, i_get(u->items, rtype->itype));
|
CuAssertIntEquals(tc, 18, i_get(u->items, rtype->itype));
|
||||||
CuAssertIntEquals(tc, 3, get_effect(u, ptype));
|
CuAssertIntEquals(tc, 3, get_effect(u, ptype));
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill * 2);
|
set_level(u, SK_ARMORER, bf.cons.minskill * 2);
|
||||||
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20));
|
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20, 0));
|
||||||
CuAssertIntEquals(tc, 2, get_effect(u, ptype));
|
CuAssertIntEquals(tc, 2, get_effect(u, ptype));
|
||||||
set_level(u, SK_ARMORER, bf.cons.minskill);
|
set_level(u, SK_ARMORER, bf.cons.minskill);
|
||||||
scale_number(u, 2); /* OBS: this scales the effects, too: */
|
scale_number(u, 2); /* OBS: this scales the effects, too: */
|
||||||
CuAssertIntEquals(tc, 4, get_effect(u, ptype));
|
CuAssertIntEquals(tc, 4, get_effect(u, ptype));
|
||||||
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20));
|
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20, 0));
|
||||||
CuAssertIntEquals(tc, 2, get_effect(u, ptype));
|
CuAssertIntEquals(tc, 2, get_effect(u, ptype));
|
||||||
teardown_build(&bf);
|
teardown_build(&bf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
/* attributes includes */
|
/* attributes includes */
|
||||||
#include <attributes/reduceproduction.h>
|
#include <attributes/reduceproduction.h>
|
||||||
#include <attributes/matmod.h>
|
|
||||||
|
|
||||||
typedef struct building_typelist {
|
typedef struct building_typelist {
|
||||||
struct building_typelist *next;
|
struct building_typelist *next;
|
||||||
|
@ -99,9 +98,6 @@ bool bt_changed(int *cache)
|
||||||
|
|
||||||
void bt_register(building_type * type)
|
void bt_register(building_type * type)
|
||||||
{
|
{
|
||||||
if (type->init) {
|
|
||||||
type->init(type);
|
|
||||||
}
|
|
||||||
selist_push(&buildingtypes, (void *)type);
|
selist_push(&buildingtypes, (void *)type);
|
||||||
++bt_changes;
|
++bt_changes;
|
||||||
}
|
}
|
||||||
|
@ -224,31 +220,6 @@ building *findbuilding(int i)
|
||||||
return bfindhash(i);
|
return bfindhash(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ** old building types ** */
|
|
||||||
|
|
||||||
static int sm_smithy(const unit * u, const region * r, skill_t sk, int value)
|
|
||||||
{ /* skillmod */
|
|
||||||
if (sk == SK_WEAPONSMITH || sk == SK_ARMORER) {
|
|
||||||
if (u->region == r)
|
|
||||||
return value + 1;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mm_smithy(const unit * u, const resource_type * rtype, int value)
|
|
||||||
{ /* material-mod */
|
|
||||||
if (rtype == get_resourcetype(R_IRON))
|
|
||||||
return value * 2;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_smithy(struct building_type *bt)
|
|
||||||
{
|
|
||||||
a_add(&bt->attribs, make_skillmod(NOSKILL, SMF_PRODUCTION, sm_smithy, 1.0,
|
|
||||||
0));
|
|
||||||
a_add(&bt->attribs, make_matmod(mm_smithy));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *castle_name_i(const struct building_type *btype,
|
static const char *castle_name_i(const struct building_type *btype,
|
||||||
const struct building *b, int bsize, const char *fname[])
|
const struct building *b, int bsize, const char *fname[])
|
||||||
{
|
{
|
||||||
|
@ -915,7 +886,6 @@ int cmp_current_owner(const building * b, const building * a)
|
||||||
|
|
||||||
void register_buildings(void)
|
void register_buildings(void)
|
||||||
{
|
{
|
||||||
register_function((pf_generic)init_smithy, "init_smithy");
|
|
||||||
register_function((pf_generic)castle_name, "castle_name");
|
register_function((pf_generic)castle_name, "castle_name");
|
||||||
register_function((pf_generic)castle_name_2, "castle_name_2");
|
register_function((pf_generic)castle_name_2, "castle_name_2");
|
||||||
register_function((pf_generic)fort_name, "fort_name");
|
register_function((pf_generic)fort_name, "fort_name");
|
||||||
|
|
|
@ -66,10 +66,10 @@ extern "C" {
|
||||||
double auraregen; /* modifier for aura regeneration inside building */
|
double auraregen; /* modifier for aura regeneration inside building */
|
||||||
struct maintenance *maintenance; /* array of requirements */
|
struct maintenance *maintenance; /* array of requirements */
|
||||||
struct construction *construction; /* construction of 1 building-level */
|
struct construction *construction; /* construction of 1 building-level */
|
||||||
|
struct resource_mod *modifiers; /* modify production skills */
|
||||||
|
|
||||||
const char *(*name) (const struct building_type *,
|
const char *(*name) (const struct building_type *,
|
||||||
const struct building * b, int size);
|
const struct building * b, int size);
|
||||||
void(*init) (struct building_type *);
|
|
||||||
void(*age) (struct building *);
|
void(*age) (struct building *);
|
||||||
double(*taxes) (const struct building *, int size);
|
double(*taxes) (const struct building *, int size);
|
||||||
struct attrib *attribs;
|
struct attrib *attribs;
|
||||||
|
|
|
@ -296,7 +296,6 @@ static void test_btype_defaults(CuTest *tc) {
|
||||||
CuAssertPtrEquals(tc, 0, btype->maintenance);
|
CuAssertPtrEquals(tc, 0, btype->maintenance);
|
||||||
CuAssertPtrEquals(tc, 0, btype->construction);
|
CuAssertPtrEquals(tc, 0, btype->construction);
|
||||||
CuAssertTrue(tc, !btype->name);
|
CuAssertTrue(tc, !btype->name);
|
||||||
CuAssertTrue(tc, !btype->init);
|
|
||||||
CuAssertTrue(tc, !btype->age);
|
CuAssertTrue(tc, !btype->age);
|
||||||
CuAssertTrue(tc, !btype->taxes);
|
CuAssertTrue(tc, !btype->taxes);
|
||||||
CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0);
|
CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0);
|
||||||
|
|
|
@ -90,11 +90,6 @@ extern "C" {
|
||||||
const resource_type *findresourcetype(const char *name,
|
const resource_type *findresourcetype(const char *name,
|
||||||
const struct locale *lang);
|
const struct locale *lang);
|
||||||
|
|
||||||
/* resource-limits for regions */
|
|
||||||
#define RMF_SKILL 0x01 /* int, bonus on resource production skill */
|
|
||||||
#define RMF_SAVEMATERIAL 0x02 /* fraction (sa[0]/sa[1]), multiplier on resource usage */
|
|
||||||
#define RMF_REQUIREDBUILDING 0x04 /* building, required to build */
|
|
||||||
|
|
||||||
/* bitfield values for item_type::flags */
|
/* bitfield values for item_type::flags */
|
||||||
#define ITF_NONE 0x0000
|
#define ITF_NONE 0x0000
|
||||||
#define ITF_HERB 0x0001 /* this item is a herb */
|
#define ITF_HERB 0x0001 /* this item is a herb */
|
||||||
|
|
|
@ -34,8 +34,17 @@ extern "C" {
|
||||||
struct rawmaterial *next;
|
struct rawmaterial *next;
|
||||||
} rawmaterial;
|
} rawmaterial;
|
||||||
|
|
||||||
|
/* resource-limits for regions */
|
||||||
|
typedef enum resource_modifier_type {
|
||||||
|
RMT_END, /* array terminator */
|
||||||
|
RMT_PROD_SKILL, /* bonus on resource production skill */
|
||||||
|
RMT_PROD_SAVE, /* fractional multiplier when produced */
|
||||||
|
RMT_PROD_REQUIRE, /* building or race is required to produce this item */
|
||||||
|
RMT_USE_SAVE, /* fractional multiplier when used to manufacture something */
|
||||||
|
} resource_modifier_type;
|
||||||
|
|
||||||
typedef struct resource_mod {
|
typedef struct resource_mod {
|
||||||
int flags;
|
resource_modifier_type type;
|
||||||
variant value;
|
variant value;
|
||||||
const struct building_type *btype;
|
const struct building_type *btype;
|
||||||
const struct race *race;
|
const struct race *race;
|
||||||
|
|
|
@ -120,6 +120,72 @@ static xmlChar *xml_cleanup_string(xmlChar * str)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static resource_mod * xml_readmodifiers(xmlXPathObjectPtr result, xmlNodePtr node) {
|
||||||
|
/* reading eressea/resources/resource/modifier */
|
||||||
|
if (result->nodesetval != NULL && result->nodesetval->nodeNr > 0) {
|
||||||
|
int k;
|
||||||
|
resource_mod * modifiers =
|
||||||
|
calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod));
|
||||||
|
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
propValue = xmlGetProp(node, BAD_CAST "building");
|
||||||
|
if (propValue != NULL) {
|
||||||
|
btype = bt_get_or_create((const char *)propValue);
|
||||||
|
xmlFree(propValue);
|
||||||
|
}
|
||||||
|
modifiers[k].btype = btype;
|
||||||
|
|
||||||
|
propValue = xmlGetProp(node, BAD_CAST "type");
|
||||||
|
assert(propValue != NULL);
|
||||||
|
if (strcmp((const char *)propValue, "skill") == 0) {
|
||||||
|
xmlChar *propSkill;
|
||||||
|
skill_t sk = NOSKILL;
|
||||||
|
|
||||||
|
modifiers[k].type = RMT_PROD_SKILL;
|
||||||
|
propSkill = xmlGetProp(node, BAD_CAST "skill");
|
||||||
|
if (propSkill) {
|
||||||
|
sk = findskill((const char *)propSkill);
|
||||||
|
xmlFree(propSkill);
|
||||||
|
}
|
||||||
|
modifiers[k].value.sa[0] = (short)sk;
|
||||||
|
modifiers[k].value.sa[1] = (short)xml_ivalue(node, "value", 0);
|
||||||
|
}
|
||||||
|
else if (strcmp((const char *)propValue, "material") == 0) {
|
||||||
|
modifiers[k].value = xml_fraction(node, "value");
|
||||||
|
modifiers[k].type = RMT_PROD_SAVE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (strcmp((const char *)propValue, "require") == 0) {
|
||||||
|
modifiers[k].type = RMT_PROD_REQUIRE;
|
||||||
|
}
|
||||||
|
else if (strcmp((const char *)propValue, "save") == 0) {
|
||||||
|
modifiers[k].type = RMT_USE_SAVE;
|
||||||
|
modifiers[k].value = xml_fraction(node, "value");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log_error("unknown type '%s' for resourcelimit-modifier", (const char *)propValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree(propValue);
|
||||||
|
}
|
||||||
|
return modifiers;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
|
xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
|
||||||
{
|
{
|
||||||
|
@ -157,7 +223,6 @@ construction ** consPtr)
|
||||||
xmlChar *propValue;
|
xmlChar *propValue;
|
||||||
construction *con;
|
construction *con;
|
||||||
xmlXPathObjectPtr req;
|
xmlXPathObjectPtr req;
|
||||||
int m;
|
|
||||||
skill_t sk = NOSKILL;
|
skill_t sk = NOSKILL;
|
||||||
|
|
||||||
propValue = xmlGetProp(node, BAD_CAST "skill");
|
propValue = xmlGetProp(node, BAD_CAST "skill");
|
||||||
|
@ -193,23 +258,6 @@ construction ** consPtr)
|
||||||
xml_readrequirements(req->nodesetval->nodeTab,
|
xml_readrequirements(req->nodesetval->nodeTab,
|
||||||
req->nodesetval->nodeNr, &con->materials);
|
req->nodesetval->nodeNr, &con->materials);
|
||||||
xmlXPathFreeObject(req);
|
xmlXPathFreeObject(req);
|
||||||
|
|
||||||
/* read construction/modifier */
|
|
||||||
xpath->node = node;
|
|
||||||
req = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
|
|
||||||
for (m = 0; m != req->nodesetval->nodeNr; ++m) {
|
|
||||||
xmlNodePtr node = req->nodesetval->nodeTab[m];
|
|
||||||
|
|
||||||
propValue = xmlGetProp(node, BAD_CAST "function");
|
|
||||||
if (propValue != NULL) {
|
|
||||||
pf_generic foo = get_function((const char *)propValue);
|
|
||||||
a_add(&con->attribs, make_skillmod(NOSKILL, SMF_PRODUCTION,
|
|
||||||
(skillmod_fun)foo, 1.0, 0));
|
|
||||||
xmlFree(propValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
xmlXPathFreeObject(req);
|
|
||||||
}
|
}
|
||||||
xpath->node = pushNode;
|
xpath->node = pushNode;
|
||||||
}
|
}
|
||||||
|
@ -280,6 +328,12 @@ static int parse_buildings(xmlDocPtr doc)
|
||||||
if (xml_bvalue(node, "fort", false))
|
if (xml_bvalue(node, "fort", false))
|
||||||
btype->flags |= BTF_FORTIFICATION;
|
btype->flags |= BTF_FORTIFICATION;
|
||||||
|
|
||||||
|
/* reading eressea/buildings/building/modifier */
|
||||||
|
xpath->node = node;
|
||||||
|
result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
|
||||||
|
btype->modifiers = xml_readmodifiers(result, node);
|
||||||
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -305,9 +359,6 @@ static int parse_buildings(xmlDocPtr doc)
|
||||||
(const char *(*)(const struct building_type *,
|
(const char *(*)(const struct building_type *,
|
||||||
const struct building *, int))fun;
|
const struct building *, int))fun;
|
||||||
}
|
}
|
||||||
else if (strcmp((const char *)propValue, "init") == 0) {
|
|
||||||
btype->init = (void(*)(struct building_type *))fun;
|
|
||||||
}
|
|
||||||
else if (strcmp((const char *)propValue, "age") == 0) {
|
else if (strcmp((const char *)propValue, "age") == 0) {
|
||||||
btype->age = (void(*)(struct building *))fun;
|
btype->age = (void(*)(struct building *))fun;
|
||||||
}
|
}
|
||||||
|
@ -344,10 +395,6 @@ static int parse_buildings(xmlDocPtr doc)
|
||||||
mt->flags |= MTF_VARIABLE;
|
mt->flags |= MTF_VARIABLE;
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
/* finally, initialize the new building type */
|
|
||||||
if (btype->init)
|
|
||||||
btype->init(btype);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(buildings);
|
xmlXPathFreeObject(buildings);
|
||||||
|
@ -951,58 +998,9 @@ static int parse_resources(xmlDocPtr doc)
|
||||||
if (xml_bvalue(node, "limited", false)) {
|
if (xml_bvalue(node, "limited", false)) {
|
||||||
rtype->flags |= RTF_LIMITED;
|
rtype->flags |= RTF_LIMITED;
|
||||||
}
|
}
|
||||||
/* reading eressea/resources/resource/modifier */
|
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
|
||||||
if (result->nodesetval != NULL && result->nodesetval->nodeNr > 0) {
|
rtype->modifiers = xml_readmodifiers(result, node);
|
||||||
rtype->modifiers =
|
|
||||||
calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod));
|
|
||||||
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
|
||||||
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
rtype->modifiers[k].race = rc;
|
|
||||||
|
|
||||||
propValue = xmlGetProp(node, BAD_CAST "building");
|
|
||||||
if (propValue != NULL) {
|
|
||||||
btype = bt_get_or_create((const char *)propValue);
|
|
||||||
xmlFree(propValue);
|
|
||||||
}
|
|
||||||
rtype->modifiers[k].btype = btype;
|
|
||||||
|
|
||||||
propValue = xmlGetProp(node, BAD_CAST "type");
|
|
||||||
assert(propValue != NULL);
|
|
||||||
if (strcmp((const char *)propValue, "skill") == 0) {
|
|
||||||
rtype->modifiers[k].value.i = xml_ivalue(node, "value", 0);
|
|
||||||
rtype->modifiers[k].flags = RMF_SKILL;
|
|
||||||
}
|
|
||||||
else if (strcmp((const char *)propValue, "material") == 0) {
|
|
||||||
rtype->modifiers[k].value = xml_fraction(node, "value");
|
|
||||||
rtype->modifiers[k].flags = RMF_SAVEMATERIAL;
|
|
||||||
}
|
|
||||||
else if (strcmp((const char *)propValue, "require") == 0) {
|
|
||||||
xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building");
|
|
||||||
if (propBldg != NULL) {
|
|
||||||
btype = bt_get_or_create((const char *)propBldg);
|
|
||||||
rtype->modifiers[k].btype = btype;
|
|
||||||
rtype->modifiers[k].flags = RMF_REQUIREDBUILDING;
|
|
||||||
xmlFree(propBldg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name);
|
|
||||||
}
|
|
||||||
xmlFree(propValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
/* reading eressea/resources/resource/resourcelimit/function */
|
/* reading eressea/resources/resource/resourcelimit/function */
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
|
|
Loading…
Reference in New Issue