diff --git a/src/bind_unit.c b/src/bind_unit.c index 1d6579b0e..d95d9d930 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -638,8 +638,14 @@ static int tolua_unit_get_familiar(lua_State * L) static int tolua_unit_set_familiar(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - create_newfamiliar(self, (unit *)tolua_tousertype(L, 2, 0)); + unit *mag = (unit *)tolua_tousertype(L, 1, NULL); + unit *fam = (unit *)tolua_tousertype(L, 2, NULL); + if (fam) { + set_familiar(mag, fam); + } + else { + remove_familiar(mag); + } return 0; } diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 6ca15a7f0..1d2fc8124 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -274,7 +274,7 @@ static void test_skill_familiar(CuTest *tc) { CuAssertIntEquals(tc, 6, effskill(mag, SK_PERCEPTION, 0)); /* make them mage and familiar to each other */ - CuAssertIntEquals(tc, true, create_newfamiliar(mag, fam)); + create_newfamiliar(mag, fam); /* when they are in the same region, the mage gets half their skill as a bonus */ CuAssertIntEquals(tc, 6, effskill(fam, SK_PERCEPTION, 0)); diff --git a/src/magic.c b/src/magic.c index 0961071b4..21db1e672 100644 --- a/src/magic.c +++ b/src/magic.c @@ -42,6 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include #include #include #include @@ -2218,23 +2219,35 @@ void remove_familiar(unit * mage) while (a && a->type == &at_skillmod) { an = a->next; smd = (skillmod_data *)a->data.v; - if (smd->special == sm_familiar) + if (smd->special == sm_familiar) { a_remove(&mage->attribs, a); + } a = an; } } -bool create_newfamiliar(unit * mage, unit * familiar) +void create_newfamiliar(unit * mage, unit * fam) { - set_familiar(mage, familiar); + /* 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_items(&fam->items, eq); + } + else { + log_info("could not perform initialization for familiar %s.\n", rc->_name); + } /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ /* Wenn der Magier stirbt, dann auch der Vertraute */ - add_trigger(&mage->attribs, "destroy", trigger_killunit(familiar)); + add_trigger(&mage->attribs, "destroy", trigger_killunit(fam)); /* Wenn der Vertraute stirbt, dann bekommt der Magier einen Schock */ - add_trigger(&familiar->attribs, "destroy", trigger_shock(mage)); - - return true; + add_trigger(&fam->attribs, "destroy", trigger_shock(mage)); } static void * resolve_familiar(int id, void *data) { diff --git a/src/magic.h b/src/magic.h index f5d2ff0f4..329a0012a 100644 --- a/src/magic.h +++ b/src/magic.h @@ -329,7 +329,7 @@ extern "C" { struct unit *get_clone(const struct unit *u); struct unit *get_clone_mage(const struct unit *u); void remove_familiar(struct unit *mage); - bool create_newfamiliar(struct unit *mage, struct unit *familiar); + void create_newfamiliar(struct unit *mage, struct unit *familiar); void create_newclone(struct unit *mage, struct unit *familiar); struct unit *has_clone(struct unit *mage); diff --git a/src/magic.test.c b/src/magic.test.c index 0ce454af1..b069dd165 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -491,6 +492,9 @@ static void test_familiar_set(CuTest *tc) { CuAssertPtrEquals(tc, fam, get_familiar(mag)); CuAssertPtrEquals(tc, mag, get_familiar_mage(fam)); CuAssertPtrNotNull(tc, a_find(mag->attribs, &at_skillmod)); + remove_familiar(mag); + CuAssertPtrEquals(tc, NULL, get_familiar(mag)); + CuAssertPtrEquals(tc, NULL, a_find(mag->attribs, &at_skillmod)); test_cleanup(); } @@ -514,10 +518,47 @@ static void test_familiar_age(CuTest *tc) { test_cleanup(); } +static void test_familiar_equip(CuTest *tc) { + unit *mag, *u; + equipment *eq; + const item_type * itype; + spell *sp; + sc_mage * mage; + + test_setup(); + + itype = test_create_itemtype("horse"); + CuAssertPtrNotNull(tc, itype); + sp = create_spell("testspell"); + CuAssertPtrNotNull(tc, sp); + + eq = get_or_create_equipment("fam_human"); + equipment_setitem(eq, itype, "1"); + equipment_setskill(eq, SK_ENTERTAINMENT, "5"); + equipment_addspell(eq, sp->sname, 1); + + mag = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u = test_create_unit(mag->faction, test_create_region(0, 0, 0)); + set_familiar(mag, u); + create_newfamiliar(mag, u); + CuAssertIntEquals(tc, 1, i_get(u->items, itype)); + CuAssertIntEquals(tc, 5, get_level(u, SK_ENTERTAINMENT)); + CuAssertIntEquals(tc, 0, get_level(u, SK_MAGIC)); + + mage = get_mage(u); + CuAssertPtrNotNull(tc, mage); + CuAssertPtrNotNull(tc, mage->spellbook); + set_level(u, SK_MAGIC, 1); + CuAssertPtrEquals(tc, mage, get_mage(u)); + CuAssertTrue(tc, u_hasspell(u, sp)); + + test_cleanup(); +} CuSuite *get_familiar_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_familiar_equip); SUITE_ADD_TEST(suite, test_familiar_set); SUITE_ADD_TEST(suite, test_familiar_age); return suite; diff --git a/src/spells.c b/src/spells.c index 9d5481a60..0e9f5cffd 100644 --- a/src/spells.c +++ b/src/spells.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -513,27 +512,22 @@ static const race *select_familiar(const race * magerace, magic_t magiegebiet) /* ------------------------------------------------------------- */ /* der Vertraue des Magiers */ -static void make_familiar(unit * familiar, unit * mage) +static unit * make_familiar(unit * mage, region *r, const race *rc, const char *name) { - /* skills and spells: */ - const struct equipment *eq; - char eqname[64]; - const race * rc = u_race(familiar); - snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name); - eq = get_equipment(eqname); - if (eq != NULL) { - equip_items(&familiar->items, eq); - } - else { - log_info("could not perform initialization for familiar %s.\n", rc->_name); - } + unit *fam; + + fam = create_unit(r, mage->faction, 1, rc, 0, name, mage); + setstatus(fam, ST_FLEE); + fset(fam, UFL_LOCKED); /* triggers: */ - create_newfamiliar(mage, familiar); + create_newfamiliar(mage, fam); /* Hitpoints nach Talenten korrigieren, sonst starten vertraute * mit Ausdauerbonus verwundet */ - familiar->hp = unit_max_hp(familiar); + fam->hp = unit_max_hp(fam); + + return fam; } static int sp_summon_familiar(castorder * co) @@ -586,10 +580,7 @@ static int sp_summon_familiar(castorder * co) msg = msg_message("familiar_name", "unit", mage); nr_render(msg, mage->faction->locale, zText, sizeof(zText), mage->faction); msg_release(msg); - familiar = create_unit(r, mage->faction, 1, rc, 0, zText, mage); - setstatus(familiar, ST_FLEE); - fset(familiar, UFL_LOCKED); - make_familiar(familiar, mage); + familiar = make_familiar(mage, r, rc, zText); dh = 0; dh1 = 0; diff --git a/src/util/attrib.c b/src/util/attrib.c index b3b9c0a6e..b6214fdd6 100644 --- a/src/util/attrib.c +++ b/src/util/attrib.c @@ -396,7 +396,6 @@ int a_age(attrib ** p, void *owner) static critbit_tree cb_deprecated = { 0 }; - typedef struct deprecated_s { unsigned int hash; int(*reader)(attrib *, void *, struct gamedata *);