From 9d09574d5e10c8ec30e6ae8c564030e872ba0e20 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 27 Feb 2017 19:35:14 +0100 Subject: [PATCH] enable process_orders to be done in steps. by checking before turn_end(), we can sense temporary attributes and curses on a unit before they age away. --- res/core/common/items.xml | 10 +++---- res/eressea/artrewards.xml | 8 ++---- scripts/tests/e2/items.lua | 18 ++++++++----- scripts/tests/items.lua | 27 +++++++++++++++++-- src/bind_unit.c | 19 ++++++++++++++ src/bindings.c | 53 +++++++++++++++----------------------- src/items.c | 27 ++++++++++++++++++- src/kernel/item.c | 24 ----------------- src/laws.c | 49 +++++++++++++++++++++++++++++++++-- src/laws.h | 4 ++- src/util/attrib.c | 16 +++++++++--- src/util/attrib.h | 18 ++++++------- 12 files changed, 180 insertions(+), 93 deletions(-) diff --git a/res/core/common/items.xml b/res/core/common/items.xml index 0e1505205..8f2bbabf8 100644 --- a/res/core/common/items.xml +++ b/res/core/common/items.xml @@ -110,20 +110,16 @@ - - - + - - - + - + diff --git a/res/eressea/artrewards.xml b/res/eressea/artrewards.xml index 2a3c09950..b18fd5b20 100644 --- a/res/eressea/artrewards.xml +++ b/res/eressea/artrewards.xml @@ -3,16 +3,12 @@ - - - + - - - + diff --git a/scripts/tests/e2/items.lua b/scripts/tests/e2/items.lua index da72bdbbc..9bc747650 100644 --- a/scripts/tests/e2/items.lua +++ b/scripts/tests/e2/items.lua @@ -1,6 +1,6 @@ require "lunit" -module("tests.items", package.seeall, lunit.testcase ) +module("tests.e2.items", package.seeall, lunit.testcase ) function setup() eressea.free_game() @@ -18,9 +18,11 @@ function test_meow() u:add_item("aoc", 1) u:clear_orders() u:add_order("BENUTZEN 1 Katzenamulett") - process_orders() + turn_begin() + turn_process() assert_equal(1, u:get_item("aoc")) assert_equal(1, r:count_msg_type('meow')) + turn_end() end function test_aurapotion50() @@ -33,10 +35,12 @@ function test_aurapotion50() u.aura = 0 u:clear_orders() u:add_order("BENUTZEN 1 Auratrank") - process_orders() + turn_begin() + turn_process() assert_equal(0, u:get_item("aurapotion50")) assert_equal(1, f:count_msg_type('aurapotion50')) assert_equal(50, u.aura) + turn_end() end function test_bagpipe() @@ -69,24 +73,26 @@ function test_foolpotion() local r = region.create(0, 0, "plain") local f = faction.create("noreply@eressea.de", "human", "de") local u = unit.create(f, r, 1) + turn_begin() u:add_item("p7", 1) u:clear_orders() u:add_order("BENUTZEN 1 Dumpfbackenbrot 4242") - process_orders() + turn_process() assert_equal(1, u:get_item("p7")) assert_equal(1, f:count_msg_type('feedback_unit_not_found')) local u2 = unit.create(f, r, 1) u:clear_orders() u:add_order("BENUTZEN 1 Dumpfbackenbrot " .. itoa36(u2.id)) - process_orders() + turn_process() assert_equal(1, u:get_item("p7")) assert_equal(1, f:count_msg_type('error64')) u:set_skill("stealth", 1); - process_orders() + turn_process() assert_equal(0, u:get_item("p7")) assert_equal(1, f:count_msg_type('givedumb')) + turn_end() end function test_snowman() diff --git a/scripts/tests/items.lua b/scripts/tests/items.lua index ff292b4cb..48f466409 100644 --- a/scripts/tests/items.lua +++ b/scripts/tests/items.lua @@ -11,6 +11,22 @@ function setup() eressea.settings.set("magic.regeneration.enable", "0") end +function test_mistletoe() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:add_item('mistletoe', 2) + u:clear_orders() + u:add_order("BENUTZEN 1 Mistelzweig") + process_orders() + assert_equal(1, u:get_item('mistletoe')) + assert_equal(1, f:count_msg_type('use_item')) + u.number = 2 + process_orders() + assert_equal(1, u:get_item('mistletoe')) + assert_equal(1, f:count_msg_type('use_singleperson')) +end + function test_dreameye() local r = region.create(0, 0, "plain") local f = faction.create("noreply@eressea.de", "human", "de") @@ -18,9 +34,14 @@ function test_dreameye() u:add_item("dreameye", 2) u:clear_orders() u:add_order("BENUTZEN 1 Traumauge") - process_orders() + assert_false(u:is_cursed('skillmod')) + turn_begin() + turn_process() + assert_true(u:is_cursed('skillmod')) assert_equal(1, u:get_item("dreameye")) assert_equal(1, f:count_msg_type('use_tacticcrystal')) + turn_end() + assert_false(u:is_cursed('skillmod')) end function test_manacrystal() @@ -33,10 +54,12 @@ function test_manacrystal() u:set_skill('magic', 1) u.aura = 0 u:add_order("BENUTZEN 1 Astralkristall") - process_orders() + turn_begin() + turn_process() assert_equal(1, u:get_item("manacrystal")) assert_equal(25, u.aura) assert_equal(1, f:count_msg_type('manacrystal_use')) + turn_end() end function test_skillpotion() diff --git a/src/bind_unit.c b/src/bind_unit.c index c8ac2b362..0358e1938 100755 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -26,6 +26,7 @@ without prior permission by the authors of Eressea. /* kernel includes */ #include #include +#include #include #include #include @@ -770,6 +771,21 @@ static int tolua_unit_get_orders(lua_State * L) return 1; } +static int tolua_unit_is_cursed(lua_State *L) { + unit *self = (unit *)tolua_tousertype(L, 1, 0); + const char *name = tolua_tostring(L, 2, 0); + lua_pushboolean(L, self->attribs && curse_active(get_curse(self->attribs, ct_find(name)))); + return 1; +} + +static int tolua_unit_has_attrib(lua_State *L) { + unit *self = (unit *)tolua_tousertype(L, 1, 0); + const char *name = tolua_tostring(L, 2, 0); + attrib * a = a_find(self->attribs, at_find(name)); + lua_pushboolean(L, a != NULL); + return 1; +} + static int tolua_unit_get_flag(lua_State * L) { unit *self = (unit *)tolua_tousertype(L, 1, 0); @@ -956,6 +972,9 @@ void tolua_unit_open(lua_State * L) tolua_function(L, TOLUA_CAST "clear_orders", &tolua_unit_clear_orders); tolua_variable(L, TOLUA_CAST "orders", &tolua_unit_get_orders, 0); + tolua_function(L, TOLUA_CAST "is_cursed", &tolua_unit_is_cursed); + tolua_function(L, TOLUA_CAST "has_attrib", &tolua_unit_has_attrib); + /* key-attributes for named flags: */ tolua_function(L, TOLUA_CAST "set_flag", &tolua_unit_set_flag); tolua_function(L, TOLUA_CAST "get_flag", &tolua_unit_get_flag); diff --git a/src/bindings.c b/src/bindings.c index 18261a507..1d6270b35 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -480,44 +480,30 @@ static int tolua_write_reports(lua_State * L) return 1; } -static void reset_game(void) -{ - region *r; - faction *f; - for (r = regions; r; r = r->next) { - unit *u; - building *b; - r->flags &= RF_SAVEMASK; - for (u = r->units; u; u = u->next) { - u->flags &= UFL_SAVEMASK; - } - for (b = r->buildings; b; b = b->next) { - b->flags &= BLD_SAVEMASK; - } - if (r->land && r->land->ownership && r->land->ownership->owner) { - faction *owner = r->land->ownership->owner; - if (owner == get_monsters()) { - /* some compat-fix, i believe. */ - owner = update_owners(r); - } - if (owner) { - fset(r, RF_GUARDED); - } - } - } - for (f = factions; f; f = f->next) { - f->flags &= FFL_SAVEMASK; - } -} - static int tolua_process_orders(lua_State * L) { - ++turn; - reset_game(); processorders(); return 0; } +static int tolua_turn_begin(lua_State * L) +{ + turn_begin(); + return 0; +} + +static int tolua_turn_process(lua_State * L) +{ + turn_process(); + return 0; +} + +static int tolua_turn_end(lua_State * L) +{ + turn_end(); + return 0; +} + static int tolua_write_passwords(lua_State * L) { int result = writepasswd(); @@ -1063,6 +1049,9 @@ int tolua_bindings_open(lua_State * L, const dictionary *inifile) tolua_function(L, TOLUA_CAST "factions", tolua_get_factions); tolua_function(L, TOLUA_CAST "regions", tolua_get_regions); tolua_function(L, TOLUA_CAST "read_turn", tolua_read_turn); + tolua_function(L, TOLUA_CAST "turn_begin", tolua_turn_begin); + tolua_function(L, TOLUA_CAST "turn_process", tolua_turn_process); + tolua_function(L, TOLUA_CAST "turn_end", tolua_turn_end); tolua_function(L, TOLUA_CAST "process_orders", tolua_process_orders); tolua_function(L, TOLUA_CAST "init_reports", tolua_init_reports); tolua_function(L, TOLUA_CAST "write_reports", tolua_write_reports); diff --git a/src/items.c b/src/items.c index ccba7ae7f..192bb111d 100644 --- a/src/items.c +++ b/src/items.c @@ -21,6 +21,8 @@ #include #include +#include + /* triggers includes */ #include #include @@ -347,7 +349,7 @@ use_tacticcrystal(unit * u, const struct item_type *itype, int amount, { int i; for (i = 0; i != amount; ++i) { - int duration = 1; /* wirkt nur eine Runde */ + int duration = 1; /* wirkt nur in dieser Runde */ curse *c; float effect; float power = 5; /* Widerstand gegen Antimagiesprueche, ist in diesem @@ -366,9 +368,32 @@ use_tacticcrystal(unit * u, const struct item_type *itype, int amount, return 0; } +static int +use_mistletoe(struct unit *user, const struct item_type *itype, int amount, + struct order *ord) +{ + int mtoes = + get_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, + user->number); + + if (user->number > mtoes) { + ADDMSG(&user->faction->msgs, msg_message("use_singleperson", + "unit item region command", user, itype->rtype, user->region, ord)); + return -1; + } + use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, + user->number); + a_add(&user->attribs, make_fleechance((float)1.0)); + ADDMSG(&user->faction->msgs, + msg_message("use_item", "unit item", user, itype->rtype)); + + return 0; +} + void register_itemfunctions(void) { /* have tests: */ + register_item_use(use_mistletoe, "use_mistletoe"); register_item_use(use_tacticcrystal, "use_dreameye"); register_item_use(use_studypotion, "use_studypotion"); register_item_use(use_antimagiccrystal, "use_antimagic"); diff --git a/src/kernel/item.c b/src/kernel/item.c index adfddf6f4..1692ed706 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -746,29 +746,6 @@ static int use_warmthpotion(unit *u, const item_type *itype, return 0; } -#include -static int -use_mistletoe(struct unit *user, const struct item_type *itype, int amount, -struct order *ord) -{ - int mtoes = - get_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, - user->number); - - if (user->number > mtoes) { - ADDMSG(&user->faction->msgs, msg_message("use_singleperson", - "unit item region command", user, itype->rtype, user->region, ord)); - return -1; - } - use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, - user->number); - a_add(&user->attribs, make_fleechance((float)1.0)); - ADDMSG(&user->faction->msgs, - msg_message("use_item", "unit item", user, itype->rtype)); - - return 0; -} - static int use_magicboost(struct unit *user, const struct item_type *itype, int amount, struct order *ord) @@ -1137,7 +1114,6 @@ void register_resources(void) register_item_use(use_potion_delayed, "use_p2"); register_item_use(use_warmthpotion, "use_nestwarmth"); - register_item_use(use_mistletoe, "usemistletoe"); register_item_use(use_magicboost, "usemagicboost"); register_item_use(use_snowball, "usesnowball"); diff --git a/src/laws.c b/src/laws.c index 0d0e53110..cc10baeb5 100644 --- a/src/laws.c +++ b/src/laws.c @@ -4186,16 +4186,54 @@ void init_processor(void) } } -void processorders(void) +static void reset_game(void) +{ + region *r; + faction *f; + for (r = regions; r; r = r->next) { + unit *u; + building *b; + r->flags &= RF_SAVEMASK; + for (u = r->units; u; u = u->next) { + u->flags &= UFL_SAVEMASK; + } + for (b = r->buildings; b; b = b->next) { + b->flags &= BLD_SAVEMASK; + } + if (r->land && r->land->ownership && r->land->ownership->owner) { + faction *owner = r->land->ownership->owner; + if (owner == get_monsters()) { + /* some compat-fix, i believe. */ + owner = update_owners(r); + } + if (owner) { + fset(r, RF_GUARDED); + } + } + } + for (f = factions; f; f = f->next) { + f->flags &= FFL_SAVEMASK; + } +} + +void turn_begin(void) +{ + ++turn; + reset_game(); +} + +void turn_process(void) { init_processor(); process(); - /*************************************************/ if (config_get_int("modules.markets", 0)) { do_markets(); } +} +void turn_end(void) +{ log_info(" - Attribute altern"); ageing(); remove_empty_units(); @@ -4210,6 +4248,13 @@ void processorders(void) update_spells(); } +void processorders(void) +{ + turn_begin(); + turn_process(); + turn_end(); +} + void update_subscriptions(void) { FILE *F; diff --git a/src/laws.h b/src/laws.h index f05c11ab4..090d2b978 100755 --- a/src/laws.h +++ b/src/laws.h @@ -53,8 +53,10 @@ extern "C" { int enter_building(struct unit *u, struct order *ord, int id, bool report); int enter_ship(struct unit *u, struct order *ord, int id, bool report); - /* eressea-specific. put somewhere else, please. */ void processorders(void); + void turn_begin(void); + void turn_process(void); + void turn_end(void); void new_units(void); void defaultorders(void); diff --git a/src/util/attrib.c b/src/util/attrib.c index fda143168..993f634d2 100644 --- a/src/util/attrib.c +++ b/src/util/attrib.c @@ -179,7 +179,17 @@ void at_register(attrib_type * at) at_hash[at->hashkey % MAXATHASH] = at; } -static attrib_type *at_find(unsigned int hk) +struct attrib_type *at_find(const char *name) { + attrib_type *find; + unsigned int hash = __at_hashkey(name); + find = at_hash[hash % MAXATHASH]; + while (find && hash != find->hashkey) { + find = find->nexthash; + } + return find; +} + +static attrib_type *at_find_key(unsigned int hk) { const char *translate[3][2] = { { "zielregion", "targetregion" }, /* remapping: from 'zielregion, heute targetregion */ @@ -193,7 +203,7 @@ static attrib_type *at_find(unsigned int hk) int i = 0; while (translate[i][0]) { if (__at_hashkey(translate[i][0]) == hk) - return at_find(__at_hashkey(translate[i][1])); + return at_find_key(__at_hashkey(translate[i][1])); ++i; } } @@ -408,7 +418,7 @@ void at_deprecate(const char * name, int(*reader)(attrib *, void *, struct gamed static int a_read_i(gamedata *data, attrib ** attribs, void *owner, unsigned int key) { int retval = AT_READ_OK; int(*reader)(attrib *, void *, struct gamedata *) = 0; - attrib_type *at = at_find(key); + attrib_type *at = at_find_key(key); attrib * na = 0; if (at) { diff --git a/src/util/attrib.h b/src/util/attrib.h index 601a6f32a..6043a960f 100644 --- a/src/util/attrib.h +++ b/src/util/attrib.h @@ -65,19 +65,19 @@ extern "C" { unsigned int hashkey; } attrib_type; - extern void at_register(attrib_type * at); - extern void at_deprecate(const char * name, int(*reader)(attrib *, void *, struct gamedata *)); + void at_register(attrib_type * at); + void at_deprecate(const char * name, int(*reader)(attrib *, void *, struct gamedata *)); + struct attrib_type *at_find(const char *name); void write_attribs(struct storage *store, struct attrib *alist, const void *owner); int read_attribs(struct gamedata *store, struct attrib **alist, void *owner); - extern attrib *a_select(attrib * a, const void *data, - bool(*compare) (const attrib *, const void *)); - extern attrib *a_find(attrib * a, const attrib_type * at); - extern attrib *a_add(attrib ** pa, attrib * at); - extern int a_remove(attrib ** pa, attrib * at); - extern void a_removeall(attrib ** a, const attrib_type * at); - extern attrib *a_new(const attrib_type * at); + attrib *a_select(attrib * a, const void *data, bool(*compare) (const attrib *, const void *)); + attrib *a_find(attrib * a, const attrib_type * at); + attrib *a_add(attrib ** pa, attrib * at); + int a_remove(attrib ** pa, attrib * at); + void a_removeall(attrib ** a, const attrib_type * at); + attrib *a_new(const attrib_type * at); int a_age(attrib ** attribs, void *owner); int a_read_orig(struct gamedata *data, attrib ** attribs, void *owner);