Merge branch 'Burgen_Bonus_configurierbar' of https://github.com/CTD1/eressea-server-bugfixing into CTD1-Burgen_Bonus_configurierbar

This commit is contained in:
Enno Rehling 2015-01-12 20:10:34 +01:00
commit e897b667f6
11 changed files with 180 additions and 151 deletions

View File

@ -1,24 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<building name="castle" capacity="1"> <building name="castle" capacity="1">
<function name="name" value="castle_name_2"/> <function name="name" value="castle_name_2"/>
<function name="protection" value="lua_building_protection"/> <function name="protection" value="building_protection"/>
<function name="taxes" value="lua_building_taxes"/> <function name="taxes" value="lua_building_taxes"/>
<construction skill="building" minskill="1" maxsize="10" reqsize="1"> <construction skill="building" minskill="1" maxsize="10" reqsize="1" defense_bonus="0">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="40" reqsize="1"> <construction skill="building" minskill="2" maxsize="40" reqsize="1" defense_bonus="1">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="3" maxsize="200" reqsize="1"> <construction skill="building" minskill="3" maxsize="200" reqsize="1" defense_bonus="3">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="4" maxsize="1000" reqsize="1"> <construction skill="building" minskill="4" maxsize="1000" reqsize="1" defense_bonus="5">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="5" maxsize="5000" reqsize="1"> <construction skill="building" minskill="5" maxsize="5000" reqsize="1" defense_bonus="8">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="6" reqsize="1"> <construction skill="building" minskill="6" reqsize="1" defense_bonus="12">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
</building> </building>

View File

@ -1,26 +1,26 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<building name="castle" capacity="1"> <building name="castle" capacity="1">
<function name="name" value="castle_name"/> <function name="name" value="castle_name"/>
<function name="protection" value="eressea_building_protection"/> <function name="protection" value="building_protection"/>
<construction skill="building" minskill="1" maxsize="2" reqsize="1"> <construction skill="building" minskill="1" maxsize="2" reqsize="1" defense_bonus="0">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="1" maxsize="8" reqsize="1"> <construction skill="building" minskill="1" maxsize="8" reqsize="1" defense_bonus="0">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="40" reqsize="1"> <construction skill="building" minskill="2" maxsize="40" reqsize="1" defense_bonus="1">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="3" maxsize="200" reqsize="1"> <construction skill="building" minskill="3" maxsize="200" reqsize="1" defense_bonus="3">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="4" maxsize="1000" reqsize="1"> <construction skill="building" minskill="4" maxsize="1000" reqsize="1" defense_bonus="5">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="5" maxsize="5000" reqsize="1"> <construction skill="building" minskill="5" maxsize="5000" reqsize="1" defense_bonus="8">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="6" reqsize="1"> <construction skill="building" minskill="6" reqsize="1" defense_bonus="12">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
</building> </building>

View File

@ -5,15 +5,15 @@
<building name="watch" capacity="1" maxsize="10"> <building name="watch" capacity="1" maxsize="10">
<function name="name" value="fort_name"/> <function name="name" value="fort_name"/>
<function name="protection" value="lua_building_protection"/> <function name="protection" value="building_protection"/>
<function name="taxes" value="lua_building_taxes"/> <function name="taxes" value="lua_building_taxes"/>
<construction skill="building" minskill="1" maxsize="5" reqsize="1"> <construction skill="building" minskill="1" maxsize="5" reqsize="1" defense_bonus="0">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="5" reqsize="1"> <construction skill="building" minskill="2" maxsize="5" reqsize="1" defense_bonus="1">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" reqsize="1"> <construction skill="building" minskill="2" reqsize="1" defense_bonus="2">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
</building> </building>

View File

@ -26,10 +26,6 @@ function item_canuse(u, iname)
return true return true
end end
function building_protection(b, u)
return 1
end
function building_taxes(b, blevel) function building_taxes(b, blevel)
btype = b.type btype = b.type
if btype=="castle" then if btype=="castle" then

View File

@ -1901,7 +1901,7 @@ int skilldiff(troop at, troop dt, int dist)
init = true; init = true;
} }
if (df->building->type->protection) { if (df->building->type->protection) {
int beff = df->building->type->protection(df->building, du); int beff = df->building->type->protection(df->building, du, DEFENSE_BONUS);
if (beff) { if (beff) {
skdiff -= beff; skdiff -= beff;
is_protected = 2; is_protected = 2;
@ -1918,7 +1918,7 @@ int skilldiff(troop at, troop dt, int dist)
if (magicwalls_ct if (magicwalls_ct
&& curse_active(get_curse(df->building->attribs, magicwalls_ct))) { && curse_active(get_curse(df->building->attribs, magicwalls_ct))) {
/* Verdoppelt Burgenbonus */ /* Verdoppelt Burgenbonus */
skdiff -= buildingeffsize(df->building, false); skdiff -= df->building->type->protection(df->building, du, DEFENSE_BONUS);
} }
} }
/* Goblin-Verteidigung /* Goblin-Verteidigung

View File

@ -57,131 +57,160 @@ static void test_make_fighter(CuTest * tc)
test_cleanup(); test_cleanup();
} }
static int add_two(building * b, unit * u) { static int add_two(building * b, unit * u, building_bonus bonus) {
return 2; return 2;
} }
static void test_defenders_get_building_bonus(CuTest * tc) static void test_defenders_get_building_bonus(CuTest * tc)
{ {
unit *du, *au; unit *du, *au;
region *r; region *r;
building * bld; building * bld;
fighter *df, *af; fighter *df, *af;
battle *b; battle *b;
side *ds, *as; side *ds, *as;
int diff; int diff;
troop dt, at; troop dt, at;
building_type * btype; building_type * btype;
test_cleanup(); test_cleanup();
test_create_world(); test_create_world();
r = findregion(0, 0); r = findregion(0, 0);
btype = bt_get_or_create("castle"); btype = bt_get_or_create("castle");
btype->protection = &add_two; btype->protection = &add_two;
bld = test_create_building(r, btype); bld = test_create_building(r, btype);
bld->size = 10; bld->size = 10;
du = test_create_unit(test_create_faction(rc_find("human")), r); du = test_create_unit(test_create_faction(rc_find("human")), r);
au = test_create_unit(test_create_faction(rc_find("human")), r); au = test_create_unit(test_create_faction(rc_find("human")), r);
u_set_building(du, bld); u_set_building(du, bld);
b = make_battle(r); b = make_battle(r);
ds = make_side(b, du->faction, 0, 0, 0); ds = make_side(b, du->faction, 0, 0, 0);
df = make_fighter(b, du, ds, false); df = make_fighter(b, du, ds, false);
as = make_side(b, au->faction, 0, 0, 0); as = make_side(b, au->faction, 0, 0, 0);
af = make_fighter(b, au, as, true); af = make_fighter(b, au, as, true);
CuAssertPtrEquals(tc, bld, df->building); CuAssertPtrEquals(tc, bld, df->building);
CuAssertPtrEquals(tc, 0, af->building); CuAssertPtrEquals(tc, 0, af->building);
dt.fighter = df; dt.fighter = df;
dt.index = 0; dt.index = 0;
at.fighter = af; at.fighter = af;
at.index = 0; at.index = 0;
diff = skilldiff(at, dt, 0); diff = skilldiff(at, dt, 0);
CuAssertIntEquals(tc, -2, diff); CuAssertIntEquals(tc, -2, diff);
diff = skilldiff(dt, at, 0); diff = skilldiff(dt, at, 0);
CuAssertIntEquals(tc, 0, diff); CuAssertIntEquals(tc, 0, diff);
free_battle(b); free_battle(b);
test_cleanup(); test_cleanup();
} }
static void test_attackers_get_no_building_bonus(CuTest * tc) static void test_attackers_get_no_building_bonus(CuTest * tc)
{ {
unit *au; unit *au;
region *r; region *r;
building * bld; building * bld;
fighter *af; fighter *af;
battle *b; battle *b;
side *as; side *as;
building_type * btype; building_type * btype;
test_cleanup(); test_cleanup();
test_create_world(); test_create_world();
r = findregion(0, 0); r = findregion(0, 0);
btype = bt_get_or_create("castle"); btype = bt_get_or_create("castle");
btype->protection = &add_two; btype->protection = &add_two;
bld = test_create_building(r, btype); bld = test_create_building(r, btype);
bld->size = 10; bld->size = 10;
au = test_create_unit(test_create_faction(rc_find("human")), r); au = test_create_unit(test_create_faction(rc_find("human")), r);
u_set_building(au, bld); u_set_building(au, bld);
b = make_battle(r); b = make_battle(r);
as = make_side(b, au->faction, 0, 0, 0); as = make_side(b, au->faction, 0, 0, 0);
af = make_fighter(b, au, as, true); af = make_fighter(b, au, as, true);
CuAssertPtrEquals(tc, 0, af->building); CuAssertPtrEquals(tc, 0, af->building);
free_battle(b); free_battle(b);
test_cleanup(); test_cleanup();
} }
static void test_building_bonus_respects_size(CuTest * tc) static void test_building_bonus_respects_size(CuTest * tc)
{ {
unit *au, *du; unit *au, *du;
region *r; region *r;
building * bld; building * bld;
fighter *af, *df; fighter *af, *df;
battle *b; battle *b;
side *as; side *as;
building_type * btype; building_type * btype;
faction * f; faction * f;
test_cleanup(); test_cleanup();
test_create_world(); test_create_world();
r = findregion(0, 0); r = findregion(0, 0);
btype = bt_get_or_create("castle"); btype = bt_get_or_create("castle");
btype->protection = &add_two; btype->protection = &add_two;
bld = test_create_building(r, btype); bld = test_create_building(r, btype);
bld->size = 10; bld->size = 10;
f = test_create_faction(rc_find("human")); f = test_create_faction(rc_find("human"));
au = test_create_unit(f, r); au = test_create_unit(f, r);
scale_number(au, 9); scale_number(au, 9);
u_set_building(au, bld); u_set_building(au, bld);
du = test_create_unit(f, r); du = test_create_unit(f, r);
u_set_building(du, bld); u_set_building(du, bld);
scale_number(du, 2); scale_number(du, 2);
b = make_battle(r); b = make_battle(r);
as = make_side(b, au->faction, 0, 0, 0); as = make_side(b, au->faction, 0, 0, 0);
af = make_fighter(b, au, as, false); af = make_fighter(b, au, as, false);
df = make_fighter(b, du, as, false); df = make_fighter(b, du, as, false);
CuAssertPtrEquals(tc, bld, af->building); CuAssertPtrEquals(tc, bld, af->building);
CuAssertPtrEquals(tc, 0, df->building); CuAssertPtrEquals(tc, 0, df->building);
free_battle(b); free_battle(b);
test_cleanup(); test_cleanup();
} }
static void test_building_defence_bonus(CuTest * tc)
{
unit *au;
region *r;
building * bld;
building_type * btype;
faction * f;
int def;
test_cleanup();
test_create_world();
r = findregion(0, 0);
register_buildings();
btype = bt_get_or_create("castle");
btype->protection = get_function("building_protection");
btype->construction->defense_bonus = 3;
bld = test_create_building(r, btype);
bld->size = 1;
f = test_create_faction(rc_find("human"));
au = test_create_unit(f, r);
scale_number(au, 1);
u_set_building(au, bld);
def = btype->protection(bld, au, DEFENSE_BONUS);
CuAssertIntEquals(tc, 3, def);
test_cleanup();
}
CuSuite *get_battle_suite(void) CuSuite *get_battle_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_make_fighter); SUITE_ADD_TEST(suite, test_make_fighter);
SUITE_ADD_TEST(suite, test_defenders_get_building_bonus); SUITE_ADD_TEST(suite, test_defenders_get_building_bonus);
SUITE_ADD_TEST(suite, test_attackers_get_no_building_bonus); SUITE_ADD_TEST(suite, test_attackers_get_no_building_bonus);
SUITE_ADD_TEST(suite, test_building_bonus_respects_size); SUITE_ADD_TEST(suite, test_building_bonus_respects_size);
return suite; SUITE_ADD_TEST(suite, test_building_defence_bonus);
return suite;
} }

View File

@ -388,32 +388,6 @@ static void lua_agebuilding(building * b)
} }
} }
static int lua_building_protection(building * b, unit * u)
{
lua_State *L = (lua_State *) global.vm_state;
const char *fname = "building_protection";
int result = 0;
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)b, TOLUA_CAST "building");
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
if (lua_pcall(L, 2, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("building_protection(%s, %s) calling '%s': %s.\n", buildingname(b), unitname(u), fname, error);
lua_pop(L, 1);
} else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
} else {
log_error("building_protection(%s, %s) calling '%s': not a function.\n", buildingname(b), unitname(u), fname);
lua_pop(L, 1);
}
return result;
}
static double lua_building_taxes(building * b, int level) static double lua_building_taxes(building * b, int level)
{ {
lua_State *L = (lua_State *) global.vm_state; lua_State *L = (lua_State *) global.vm_state;
@ -545,8 +519,6 @@ void register_tolua_helpers(void)
at_register(&at_direction); at_register(&at_direction);
at_register(&at_building_action); at_register(&at_building_action);
register_function((pf_generic) & lua_building_protection,
TOLUA_CAST "lua_building_protection");
register_function((pf_generic) & lua_building_taxes, register_function((pf_generic) & lua_building_taxes,
TOLUA_CAST "lua_building_taxes"); TOLUA_CAST "lua_building_taxes");
register_function((pf_generic) & lua_agebuilding, register_function((pf_generic) & lua_agebuilding,

View File

@ -45,6 +45,9 @@ extern "C" {
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. */
int defense_bonus; /* protection bonus (defense) during combat */
int close_combat_bonus; /* close combat attack bonus*/
int ranged_bonus; /* ranged attack bonus */
requirement *materials; /* material req'd to build one object */ requirement *materials; /* material req'd to build one object */
const struct building_type *btype; const struct building_type *btype;
/* building type required to make this thing */ /* building type required to make this thing */

View File

@ -316,12 +316,32 @@ const building_type *findbuildingtype(const char *name,
return (const building_type *)type.v; return (const building_type *)type.v;
} }
static int eressea_building_protection(building * b, unit * u) static int building_protection(building * b, unit * u, building_bonus bonus)
{ {
int beff = buildingeffsize(b, false) - 1;
/* -1 because the tradepost has no protection value */
return beff; int i = 0;
int bsize = buildingeffsize(b, false);
const construction *cons = b->type->construction;
if (!cons) {
return 0;
}
for (i = 0; i < bsize; i++)
{
cons = cons->improvement;
}
switch (bonus)
{
case DEFENSE_BONUS:
return cons->defense_bonus;
case CLOSE_COMBAT_ATTACK_BONUS:
return cons->close_combat_bonus;
case RANGED_ATTACK_BONUS:
return cons->ranged_bonus;
default:
return 0;
}
} }
static int meropis_building_protection(building * b, unit * u) static int meropis_building_protection(building * b, unit * u)
@ -331,8 +351,8 @@ static int meropis_building_protection(building * b, unit * u)
void register_buildings(void) void register_buildings(void)
{ {
register_function((pf_generic)& eressea_building_protection, register_function((pf_generic)& building_protection,
"eressea_building_protection"); "building_protection");
register_function((pf_generic)& meropis_building_protection, register_function((pf_generic)& meropis_building_protection,
"meropis_building_protection"); "meropis_building_protection");
register_function((pf_generic)& init_smithy, "init_smithy"); register_function((pf_generic)& init_smithy, "init_smithy");

View File

@ -48,6 +48,12 @@ extern "C" {
#define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */ #define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */
#define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */ #define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */
typedef enum {
DEFENSE_BONUS,
CLOSE_COMBAT_ATTACK_BONUS,
RANGED_ATTACK_BONUS,
} building_bonus;
typedef struct building_type { typedef struct building_type {
char *_name; char *_name;
@ -66,7 +72,7 @@ extern "C" {
const struct building * b, int size); const struct building * b, int size);
void (*init) (struct building_type *); void (*init) (struct building_type *);
void (*age) (struct building *); void (*age) (struct building *);
int (*protection) (struct building *, struct unit *); int (*protection) (struct building *, struct unit *, building_bonus);
double (*taxes) (const struct building *, int size); double (*taxes) (const struct building *, int size);
struct attrib *attribs; struct attrib *attribs;
} building_type; } building_type;

View File

@ -167,6 +167,9 @@ construction ** consPtr)
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);
con->defense_bonus = xml_ivalue(node, "defense_bonus", 0);
con->close_combat_bonus = xml_ivalue(node, "close_combat_bonus", 0);
con->ranged_bonus = xml_ivalue(node, "ranged_bonus", 0);
propValue = xmlGetProp(node, BAD_CAST "building"); propValue = xmlGetProp(node, BAD_CAST "building");
if (propValue != NULL) { if (propValue != NULL) {
@ -297,7 +300,7 @@ static int parse_buildings(xmlDocPtr doc)
btype->age = (void(*)(struct building *))fun; btype->age = (void(*)(struct building *))fun;
} }
else if (strcmp((const char *)propValue, "protection") == 0) { else if (strcmp((const char *)propValue, "protection") == 0) {
btype->protection = (int(*)(struct building *, struct unit *))fun; btype->protection = (int(*)(struct building *, struct unit *, building_bonus))fun;
} }
else if (strcmp((const char *)propValue, "taxes") == 0) { else if (strcmp((const char *)propValue, "taxes") == 0) {
btype->taxes = (double(*)(const struct building *, int))fun; btype->taxes = (double(*)(const struct building *, int))fun;