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();