diff --git a/conf/e3/races.json b/conf/e3/races.json index 1ac473f49..a7cd06857 100644 --- a/conf/e3/races.json +++ b/conf/e3/races.json @@ -1,9 +1,9 @@ { "include": [ - "config://res/races/goblin-3.xml", - "config://res/races/wyrm.xml", - "config://res/races/dragon.xml", - "config://res/races/youngdragon.xml", - "config://res/e3a/races.xml" + "config://res/e3a/races.xml", + "config://res/e3a/races/goblin.xml", + "config://res/e3a/races/wyrm.xml", + "config://res/e3a/races/dragon.xml", + "config://res/e3a/races/youngdragon.xml" ] } diff --git a/res/races/dragon.xml b/res/e3a/races/dragon.xml similarity index 100% rename from res/races/dragon.xml rename to res/e3a/races/dragon.xml diff --git a/res/races/goblin-3.xml b/res/e3a/races/goblin.xml similarity index 100% rename from res/races/goblin-3.xml rename to res/e3a/races/goblin.xml diff --git a/res/races/wyrm.xml b/res/e3a/races/wyrm.xml similarity index 100% rename from res/races/wyrm.xml rename to res/e3a/races/wyrm.xml diff --git a/res/races/youngdragon.xml b/res/e3a/races/youngdragon.xml similarity index 100% rename from res/races/youngdragon.xml rename to res/e3a/races/youngdragon.xml diff --git a/res/races/aquarian.xml b/res/races/aquarian.xml deleted file mode 100644 index 4950d60d1..000000000 --- a/res/races/aquarian.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/res/races/cat.xml b/res/races/cat.xml deleted file mode 100644 index 2e0f73dcf..000000000 --- a/res/races/cat.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/demon.xml b/res/races/demon.xml deleted file mode 100644 index 21a1f289d..000000000 --- a/res/races/demon.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/dwarf.xml b/res/races/dwarf.xml deleted file mode 100644 index 4f2719649..000000000 --- a/res/races/dwarf.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/elf.xml b/res/races/elf.xml deleted file mode 100644 index 968ad22f2..000000000 --- a/res/races/elf.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/goblin.xml b/res/races/goblin.xml deleted file mode 100644 index ec224a0c7..000000000 --- a/res/races/goblin.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/halfling.xml b/res/races/halfling.xml deleted file mode 100644 index 22001df7d..000000000 --- a/res/races/halfling.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/human.xml b/res/races/human.xml deleted file mode 100644 index 00c11f8a6..000000000 --- a/res/races/human.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/res/races/insect.xml b/res/races/insect.xml deleted file mode 100644 index b783f047a..000000000 --- a/res/races/insect.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/orc.xml b/res/races/orc.xml deleted file mode 100644 index 47754152a..000000000 --- a/res/races/orc.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/troll.xml b/res/races/troll.xml deleted file mode 100644 index 7d3f18551..000000000 --- a/res/races/troll.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/zombie.xml b/res/races/zombie.xml deleted file mode 100644 index 01407b29a..000000000 --- a/res/races/zombie.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/src/kernel/equipment.test.c b/src/kernel/equipment.test.c index 331625c14..ff6b5621f 100644 --- a/src/kernel/equipment.test.c +++ b/src/kernel/equipment.test.c @@ -24,10 +24,10 @@ static bool equip_callback(unit *u, const char *eqname, int mask) { static void test_equipment(CuTest * tc) { - callbacks.equip_unit = equip_callback; unit * u; test_setup(); + callbacks.equip_unit = equip_callback; u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); CuAssertIntEquals(tc, true, equip_unit_mask(u, "hodor", EQUIP_ALL)); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index beec40e0a..86f74dc03 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -281,6 +281,7 @@ unit *addplayer(region * r, faction * f) assert(f->units == NULL); faction_setorigin(f, 0, r->x, r->y); u = create_unit(r, f, 1, f->race, 0, NULL, NULL); + u->status = ST_FLEE; u->thisorder = default_order(f->locale); unit_addorder(u, copy_order(u->thisorder)); name = config_get("rules.equip_first"); diff --git a/src/kernel/gamedata.h b/src/kernel/gamedata.h index 527d2c5e7..bc1701173 100644 --- a/src/kernel/gamedata.h +++ b/src/kernel/gamedata.h @@ -44,8 +44,9 @@ #define FIX_STARTLEVEL_VERSION 366 /* fixing resource startlevels */ #define FIX_RES_BASE_VERSION 367 /* fixing resource base */ #define FIX_CLONES_VERSION 368 /* dissolve clones */ +#define FIX_MIGRANT_AURA_VERSION 369 /* bug 2585, migrants with aura */ -#define RELEASE_VERSION FIX_CLONES_VERSION /* current datafile */ +#define RELEASE_VERSION FIX_MIGRANT_AURA_VERSION /* current datafile */ #define MIN_VERSION UIDHASH_VERSION /* minimal datafile we support */ #define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */ diff --git a/src/kernel/save.c b/src/kernel/save.c index f43c21f20..2b66c7f18 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1659,7 +1659,10 @@ int read_game(gamedata *data) fix_familiars(fix_fam_triggers); } if (data->version < FAMILIAR_FIXSPELLBOOK_VERSION) { - fix_familiars(fix_fam_mage); + fix_familiars(fix_fam_spells); + } + if (data->version < FIX_MIGRANT_AURA_VERSION) { + fix_familiars(fix_fam_migrant); } log_debug("Done loading turn %d.", turn); diff --git a/src/magic.c b/src/magic.c index 7b15bb71d..5b64b1459 100644 --- a/src/magic.c +++ b/src/magic.c @@ -651,12 +651,13 @@ int max_spellpoints(const struct unit *u, const region * r) const sc_mage *m; assert(u); + m = get_mage(u); + if (!m) return 0; if (!r) r = u->region; sk = effskill(u, SK_MAGIC, r); msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1); - m = get_mage(u); - if (m) msp += m->spchange; + msp += m->spchange; rtype = rt_find("aurafocus"); if (rtype && i_get(u->items, rtype->itype) > 0) { @@ -2250,12 +2251,29 @@ static int copy_spell_cb(spellbook_entry *sbe, void *udata) { } /** + * Entferne Magie-Attribut von Migranten, die keine Vertrauten sind. + * + * Einmalige Reparatur von Vertrauten (Bug 2585). + */ +void fix_fam_migrant(unit *u) { + if (!is_familiar(u)) { + a_removeall(&u->attribs, &at_mage); + } +} + +/** + * Einheiten, die Vertraute sind, bekommen ihre fehlenden Zauber. + * * Einmalige Reparatur von Vertrauten (Bugs 2451, 2517). */ -void fix_fam_mage(unit *u) { +void fix_fam_spells(unit *u) { sc_mage *dmage; unit *du = unit_create(0); + if (!is_familiar(u)) { + return; + } + u_setrace(du, u_race(u)); dmage = create_mage(du, M_GRAY); equip_familiar(du); @@ -2285,7 +2303,6 @@ void fix_fam_mage(unit *u) { void create_newfamiliar(unit * mage, unit * fam) { - create_mage(fam, M_GRAY); set_familiar(mage, fam); equip_familiar(fam); diff --git a/src/magic.h b/src/magic.h index 5269e3259..15870e90c 100644 --- a/src/magic.h +++ b/src/magic.h @@ -330,7 +330,8 @@ extern "C" { void create_newfamiliar(struct unit *mage, struct unit *familiar); void create_newclone(struct unit *mage, struct unit *familiar); - void fix_fam_mage(struct unit *u); + void fix_fam_spells(struct unit *u); + void fix_fam_migrant(struct unit *u); const char *spell_info(const struct spell *sp, const struct locale *lang); diff --git a/src/magic.test.c b/src/magic.test.c index 160662c15..068efdfa4 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -442,25 +442,30 @@ static void test_magic_resistance(CuTest *tc) { static void test_max_spellpoints(CuTest *tc) { unit *u; race *rc; + item_type *it_aura; test_setup(); rc = test_create_race("human"); u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0)); - CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u)); - CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); - CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); - rc->maxaura = 100; - CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); - rc->maxaura = 200; - CuAssertIntEquals(tc, 2, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 0, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 0, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 0, max_spellpoints(u, NULL)); create_mage(u, M_GWYRRD); + rc->maxaura = 100; + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); + rc->maxaura = 200; + CuAssertIntEquals(tc, 2, max_spellpoints(u, NULL)); set_level(u, SK_MAGIC, 1); - CuAssertIntEquals(tc, 3, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 3, max_spellpoints(u, NULL)); set_level(u, SK_MAGIC, 2); - CuAssertIntEquals(tc, 9, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 9, max_spellpoints(u, NULL)); /* permanent aura loss: */ CuAssertIntEquals(tc, 7, change_maxspellpoints(u, -2)); - CuAssertIntEquals(tc, 7, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 7, max_spellpoints(u, NULL)); + /* aurafocus: */ + it_aura = test_create_itemtype("aurafocus"); + i_change(&u->items, it_aura, 1); + CuAssertIntEquals(tc, 9, max_spellpoints(u, NULL)); test_teardown(); } @@ -468,7 +473,6 @@ static void test_regenerate_aura(CuTest *tc) { unit *u; test_setup(); - test_teardown(); u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); create_mage(u, M_GWYRRD); CuAssertIntEquals(tc, 0, get_spellpoints(u)); @@ -482,6 +486,110 @@ static void test_regenerate_aura(CuTest *tc) { CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); regenerate_aura(); CuAssertIntEquals(tc, 1, get_spellpoints(u)); + test_teardown(); +} + +/** + * Test for Bug 2582. + * + * Migrant units that are not familiars, but whose race has a maxaura + * must not regenerate aura. + */ +static void test_regenerate_aura_migrants(CuTest *tc) { + unit *u; + race *rc; + + test_setup(); + rc = test_create_race("demon"); + rc->maxaura = 100; + rc->flags |= RCF_FAMILIAR; + + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); + regenerate_aura(); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); + test_teardown(); +} + +static void test_fix_fam_migrants(CuTest *tc) { + unit *u, *mage; + race *rc; + + test_setup(); + rc = test_create_race("demon"); + rc->maxaura = 100; + rc->flags |= RCF_FAMILIAR; + + /* u is a migrant with at_mage attribute, but not a familiar */ + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + create_mage(u, M_GRAY); + CuAssertTrue(tc, !is_familiar(u)); + CuAssertPtrNotNull(tc, get_mage(u)); + fix_fam_migrant(u); + CuAssertTrue(tc, !is_familiar(u)); + CuAssertPtrEquals(tc, NULL, get_mage(u)); + + /* u is a familiar, and stays unchanged: */ + mage = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + /* reproduce the bug, create a broken familiar: */ + create_newfamiliar(mage, u); + set_level(u, SK_MAGIC, 1); + CuAssertTrue(tc, is_familiar(u)); + CuAssertPtrNotNull(tc, get_mage(u)); + fix_fam_migrant(u); + CuAssertTrue(tc, is_familiar(u)); + CuAssertPtrNotNull(tc, get_mage(u)); + + test_teardown(); +} + +static bool equip_spell(unit *u, const char *eqname, int mask) { + spell * sp = find_spell("test"); + unit_add_spell(u, sp, 1); + return true; +} + +static void test_fix_fam_spells(CuTest *tc) { + unit *u, *mage; + race *rc; + spell * sp; + + test_setup(); + sp = create_spell("test"); + rc = test_create_race("demon"); + rc->maxaura = 100; + rc->flags |= RCF_FAMILIAR; + + /* u is a familiar, and gets equipped: */ + mage = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + /* reproduce the bug, create a broken familiar: */ + callbacks.equip_unit = NULL; + create_newfamiliar(mage, u); + set_level(u, SK_MAGIC, 1); + CuAssertPtrEquals(tc, NULL, unit_get_spellbook(u)); + CuAssertTrue(tc, !u_hasspell(u, sp)); + callbacks.equip_unit = equip_spell; + CuAssertTrue(tc, is_familiar(u)); + fix_fam_spells(u); + CuAssertTrue(tc, is_familiar(u)); + CuAssertPtrNotNull(tc, unit_get_spellbook(u)); + CuAssertTrue(tc, u_hasspell(u, sp)); + + /* u is a migrant, and does not get equipped: */ + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + CuAssertTrue(tc, !is_familiar(u)); + fix_fam_spells(u); + CuAssertTrue(tc, !is_familiar(u)); + CuAssertPtrEquals(tc, NULL, unit_get_spellbook(u)); + + test_teardown(); } static void test_illusioncastle(CuTest *tc) @@ -635,5 +743,8 @@ CuSuite *get_magic_suite(void) SUITE_ADD_TEST(suite, test_max_spellpoints); SUITE_ADD_TEST(suite, test_illusioncastle); SUITE_ADD_TEST(suite, test_regenerate_aura); + SUITE_ADD_TEST(suite, test_regenerate_aura_migrants); + SUITE_ADD_TEST(suite, test_fix_fam_spells); + SUITE_ADD_TEST(suite, test_fix_fam_migrants); return suite; } diff --git a/src/randenc.c b/src/randenc.c index 9c3fd4739..e6ebf549b 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -239,6 +239,7 @@ static void move_iceberg(region * r) "region dir", r, dir)); } + stats_count("iceberg.drift", 1); x = r->x; y = r->y; @@ -379,6 +380,7 @@ static void create_icebergs(void) continue; r->terrain = t_iceberg; + stats_count("iceberg.terraform", 1); fset(r, RF_SELECT); move_iceberg(r); diff --git a/src/tests.c b/src/tests.c index 26e57d23a..a34e6c743 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7,8 +7,9 @@ #include "vortex.h" #include "kernel/calendar.h" -#include -#include +#include "kernel/callbacks.h" +#include "kernel/config.h" +#include "kernel/alliance.h" #include #include #include @@ -228,7 +229,7 @@ static void test_reset(void) { errno = 0; log_error("errno: %d (%s)", error, strerror(error)); } - + memset(&callbacks, 0, sizeof(callbacks)); free_gamedata(); free_terrains(); free_resources();