diff --git a/src/bindings.c b/src/bindings.c index a8581f2d1..4444a5515 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -399,7 +399,7 @@ static int tolua_equipunit(lua_State * L) const char *eqname = tolua_tostring(L, 2, 0); int mask = (int)tolua_tonumber(L, 3, EQUIP_ALL); assert(u && mask > 0); - equip_unit_mask(u, get_equipment(eqname), mask); + equip_unit_mask(u, eqname, mask); return 0; } diff --git a/src/economy.c b/src/economy.c index a41b4525e..5fbb0111c 100644 --- a/src/economy.c +++ b/src/economy.c @@ -263,7 +263,7 @@ void add_recruits(unit * u, int number, int wanted) len = snprintf(equipment, sizeof(equipment), "new_%s", u_race(u)->_name); if (len > 0 && (size_t)len < sizeof(equipment)) { - equip_unit(unew, get_equipment(equipment)); + equip_unit(unew, equipment); } if (unew != u) { transfermen(unew, u, unew->number); diff --git a/src/kernel/callbacks.h b/src/kernel/callbacks.h index dcdf6ac90..1977cd284 100644 --- a/src/kernel/callbacks.h +++ b/src/kernel/callbacks.h @@ -19,6 +19,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef H_KRNL_CALLBACKS_H #define H_KRNL_CALLBACKS_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -31,6 +33,7 @@ extern "C" { struct resource_type; struct callback_struct { + bool (*equip_unit)(struct unit *u, const char *eqname, int mask); int (*cast_spell)(struct castorder *co, const char *fname); int (*use_item)(struct unit *u, const struct item_type *itype, int amount, struct order *ord); diff --git a/src/kernel/equipment.c b/src/kernel/equipment.c index 99c0bba7b..7b1af07f9 100644 --- a/src/kernel/equipment.c +++ b/src/kernel/equipment.c @@ -21,11 +21,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "equipment.h" /* kernel includes */ -#include "item.h" -#include "unit.h" +#include "callbacks.h" #include "faction.h" +#include "item.h" #include "race.h" #include "spell.h" +#include "unit.h" /* util includes */ #include @@ -88,80 +89,90 @@ equipment_setitem(equipment * eq, const item_type * itype, const char *value) } void -equipment_setcallback(struct equipment *eq, -void(*callback) (const struct equipment *, struct unit *)) +equipment_setcallback(struct equipment *eq, equip_callback_fun callback) { eq->callback = callback; } -void equip_unit(struct unit *u, const struct equipment *eq) +bool equip_unit(struct unit *u, const char *eqname) { - equip_unit_mask(u, eq, EQUIP_ALL); + return equip_unit_mask(u, eqname, EQUIP_ALL); } -void equip_unit_mask(struct unit *u, const struct equipment *eq, int mask) +bool equip_unit_mask(struct unit *u, const char *eqname, int mask) { + const equipment * eq = get_equipment(eqname); if (eq) { + equip_unit_set(u, eq, mask); + return true; + } + if (callbacks.equip_unit) { + return callbacks.equip_unit(u, eqname, mask); + } + return false; +} - if (mask & EQUIP_SKILLS) { - int sk; - for (sk = 0; sk != MAXSKILLS; ++sk) { - if (eq->skills[sk] != NULL) { - int i = dice_rand(eq->skills[sk]); - if (i > 0) { - set_level(u, (skill_t)sk, i); - if (sk == SK_STAMINA) { - u->hp = unit_max_hp(u) * u->number; - } - } - } - } - } - - if (mask & EQUIP_SPELLS) { - if (eq->spells) { - selist * ql = eq->spells; - int qi; - sc_mage * mage = get_mage_depr(u); - - for (qi = 0; ql; selist_advance(&ql, &qi, 1)) { - lazy_spell *sbe = (lazy_spell *)selist_get(ql, qi); - spell *sp = spellref_get(sbe->spref); - unit_add_spell(u, mage, sp, sbe->level); - } - } - } - - if (mask & EQUIP_ITEMS) { - itemdata *idata; - for (idata = eq->items; idata != NULL; idata = idata->next) { - int i = u->number * dice_rand(idata->value); +void equip_unit_set(struct unit *u, const equipment *eq, int mask) +{ + if (mask & EQUIP_SKILLS) { + int sk; + for (sk = 0; sk != MAXSKILLS; ++sk) { + if (eq->skills[sk] != NULL) { + int i = dice_rand(eq->skills[sk]); if (i > 0) { - i_add(&u->items, i_new(idata->itype, i)); - } - } - } - - if (eq->subsets) { - int i; - for (i = 0; eq->subsets[i].sets; ++i) { - if (chance(eq->subsets[i].chance)) { - double rnd = (1 + rng_int() % 1000) / 1000.0; - int k; - for (k = 0; eq->subsets[i].sets[k].set; ++k) { - if (rnd <= eq->subsets[i].sets[k].chance) { - equip_unit_mask(u, eq->subsets[i].sets[k].set, mask); - break; - } - rnd -= eq->subsets[i].sets[k].chance; + set_level(u, (skill_t)sk, i); + if (sk == SK_STAMINA) { + u->hp = unit_max_hp(u) * u->number; } } } } + } - if (mask & EQUIP_SPECIAL) { - if (eq->callback) - eq->callback(eq, u); + if (mask & EQUIP_SPELLS) { + if (eq->spells) { + selist * ql = eq->spells; + int qi; + sc_mage * mage = get_mage_depr(u); + + for (qi = 0; ql; selist_advance(&ql, &qi, 1)) { + lazy_spell *sbe = (lazy_spell *)selist_get(ql, qi); + spell *sp = spellref_get(sbe->spref); + unit_add_spell(u, mage, sp, sbe->level); + } + } + } + + if (eq->items && mask & EQUIP_ITEMS) { + itemdata *idata; + for (idata = eq->items; idata != NULL; idata = idata->next) { + int i = u->number * dice_rand(idata->value); + if (i > 0) { + i_add(&u->items, i_new(idata->itype, i)); + } + } + } + + if (eq->subsets) { + int i; + for (i = 0; eq->subsets[i].sets; ++i) { + if (chance(eq->subsets[i].chance)) { + double rnd = (1 + rng_int() % 1000) / 1000.0; + int k; + for (k = 0; eq->subsets[i].sets[k].set; ++k) { + if (rnd <= eq->subsets[i].sets[k].chance) { + equip_unit_set(u, eq->subsets[i].sets[k].set, mask); + break; + } + rnd -= eq->subsets[i].sets[k].chance; + } + } + } + } + + if (mask & EQUIP_SPECIAL) { + if (eq->callback) { + eq->callback(eq, u); } } } diff --git a/src/kernel/equipment.h b/src/kernel/equipment.h index 9fbffe67f..5ba1a4182 100644 --- a/src/kernel/equipment.h +++ b/src/kernel/equipment.h @@ -21,6 +21,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "skill.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -44,12 +46,14 @@ extern "C" { subsetitem *sets; } subset; + typedef void(*equip_callback_fun) (const struct equipment *, struct unit *); + typedef struct equipment { struct itemdata *items; char *skills[MAXSKILLS]; struct selist *spells; struct subset *subsets; - void(*callback) (const struct equipment *, struct unit *); + equip_callback_fun callback; } equipment; void equipment_done(void); @@ -64,18 +68,17 @@ extern "C" { void equipment_setskill(struct equipment *eq, skill_t sk, const char *value); void equipment_addspell(struct equipment *eq, const char *name, int level); - void equipment_setcallback(struct equipment *eq, - void(*callback) (const struct equipment *, struct unit *)); + void equipment_setcallback(struct equipment *eq, equip_callback_fun callback); - void equip_unit(struct unit *u, const struct equipment *eq); #define EQUIP_SKILLS (1<<1) #define EQUIP_SPELLS (1<<2) #define EQUIP_ITEMS (1<<3) #define EQUIP_SPECIAL (1<<4) #define EQUIP_ALL (0xFF) - void equip_unit_mask(struct unit *u, const struct equipment *eq, - int mask); void equip_items(struct item **items, const struct equipment *eq); + void equip_unit_set(struct unit *u, const struct equipment *eq, int mask); + bool equip_unit_mask(struct unit *u, const char *eqname, int mask); + bool equip_unit(struct unit *u, const char *eqname); #ifdef __cplusplus } diff --git a/src/kernel/equipment.test.c b/src/kernel/equipment.test.c index 1a1bbfdf1..c09945865 100644 --- a/src/kernel/equipment.test.c +++ b/src/kernel/equipment.test.c @@ -2,6 +2,7 @@ #include "magic.h" +#include #include #include #include @@ -35,7 +36,7 @@ static void test_equipment(CuTest * tc) equipment_addspell(eq, sp->sname, 1); u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); - equip_unit_mask(u, eq, EQUIP_ALL); + equip_unit_set(u, eq, EQUIP_ALL); CuAssertIntEquals(tc, 1, i_get(u->items, it_horses)); CuAssertIntEquals(tc, 5, get_level(u, SK_MAGIC)); @@ -69,10 +70,35 @@ static void test_get_equipment(CuTest * tc) test_teardown(); } +static bool equip_test(unit *u, const char *name, int mask) { + if (mask & EQUIP_ITEMS) { + i_change(&u->items, it_find("horse"), 1); + return true; + } + return false; +} + +static void test_equipment_callback(CuTest *tc) { + unit *u; + item_type *itype; + test_setup(); + itype = test_create_horse(); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + CuAssertTrue(tc, !equip_unit_mask(u, "horse", EQUIP_ITEMS)); + CuAssertPtrEquals(tc, NULL, u->items); + callbacks.equip_unit = equip_test; + CuAssertTrue(tc, equip_unit(u, "horse")); + CuAssertIntEquals(tc, 1, i_get(u->items, itype)); + CuAssertTrue(tc, !equip_unit_mask(u, "horse", EQUIP_SPELLS)); + CuAssertIntEquals(tc, 1, i_get(u->items, itype)); + test_teardown(); +} + CuSuite *get_equipment_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_equipment); SUITE_ADD_TEST(suite, test_get_equipment); + SUITE_ADD_TEST(suite, test_equipment_callback); return suite; } diff --git a/src/kernel/save.c b/src/kernel/save.c index 858cd7040..c1c8010d1 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1349,7 +1349,7 @@ static void fix_familiars(void) { log_error("%s seems to be a familiar with no spells.", unitname(u)); /* magical familiar, no spells */ - equip_unit_mask(u, eq, EQUIP_SPELLS); + equip_unit_set(u, eq, EQUIP_SPELLS); } } } diff --git a/src/magic.c b/src/magic.c index 1b41b87af..1f1ec9c26 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2181,18 +2181,13 @@ void remove_familiar(unit * mage) void create_newfamiliar(unit * mage, unit * fam) { /* skills and spells: */ - const struct equipment *eq; char eqname[64]; const race *rc = u_race(fam); set_familiar(mage, fam); snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name); - eq = get_equipment(eqname); - if (eq != NULL) { - equip_unit(fam, eq); - } - else { + if (!equip_unit(fam, eqname)) { log_info("could not perform initialization for familiar %s.\n", rc->_name); } /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ diff --git a/src/monsters.c b/src/monsters.c index 9d113c0e9..db70bebfc 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -612,7 +612,7 @@ static void recruit_dracoids(unit * dragon, int size) name_unit(un); change_money(dragon, -un->number * 50); - equip_unit(un, get_equipment("new_dracoid")); + equip_unit(un, "new_dracoid"); unit_setstatus(un, ST_FIGHT); for (weapon = un->items; weapon; weapon = weapon->next) { @@ -864,7 +864,7 @@ static int nrand(int start, int sub) unit *spawn_seaserpent(region *r, faction *f) { unit *u = create_unit(r, f, 1, get_race(RC_SEASERPENT), 0, NULL, NULL); fset(u, UFL_ISNEW | UFL_MOVED); - equip_unit(u, get_equipment("seed_seaserpent")); + equip_unit(u, "seed_seaserpent"); return u; } @@ -903,7 +903,7 @@ void spawn_dragons(void) u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL); } fset(u, UFL_ISNEW | UFL_MOVED); - equip_unit(u, get_equipment("seed_dragon")); + equip_unit(u, "seed_dragon"); log_debug("spawning %d %s in %s.\n", u->number, LOC(default_locale, @@ -965,7 +965,7 @@ void spawn_undead(void) fset(u, UFL_ISNEW | UFL_MOVED); if ((rc == get_race(RC_SKELETON) || rc == get_race(RC_ZOMBIE)) && rng_int() % 10 < 4) { - equip_unit(u, get_equipment("rising_undead")); + equip_unit(u, "rising_undead"); } for (i = 0; i < MAXSKILLS; i++) { diff --git a/src/randenc.c b/src/randenc.c index 9630d6e85..709702513 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -265,7 +265,7 @@ static void get_villagers(region * r, unit * u) u); leave(newunit, true); fset(newunit, UFL_ISNEW | UFL_MOVED); - equip_unit(newunit, get_equipment("rand_villagers")); + equip_unit(newunit, "rand_villagers"); } static void get_allies(region * r, unit * u) @@ -352,7 +352,7 @@ static void get_allies(region * r, unit * u) newunit = create_unit(r, u->faction, number, u->faction->race, 0, LOC(u->faction->locale, name), u); - equip_unit(newunit, get_equipment(equip)); + equip_unit(newunit, equip); u_setfaction(newunit, u->faction); set_racename(&newunit->attribs, get_racename(u->attribs)); diff --git a/src/teleport.c b/src/teleport.c index 439b44955..36634c5cd 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -181,7 +181,7 @@ void spawn_braineaters(float chance) if (next-- == 0) { u = create_unit(r, f, 1 + rng_int() % 10 + rng_int() % 10, rc_brain, 0, NULL, NULL); - equip_unit(u, get_equipment("seed_braineater")); + equip_unit(u, "seed_braineater"); next = rng_int() % (int)(chance * 100); } diff --git a/src/xmlreader.c b/src/xmlreader.c index fe6f18e1f..5b6f7d8c1 100644 --- a/src/xmlreader.c +++ b/src/xmlreader.c @@ -875,8 +875,7 @@ static void add_callbacks(equipment * eq, xmlNodeSetPtr nsetItems) if (propValue != NULL) { fun = get_function((const char *)propValue); if (fun) { - equipment_setcallback(eq, (void(*)(const struct equipment *, - struct unit *))fun); + equipment_setcallback(eq, (equip_callback_fun)fun); } xmlFree(propValue); }