diff --git a/scripts/tests/economy.lua b/scripts/tests/economy.lua index 9c72e7e70..0c140e418 100644 --- a/scripts/tests/economy.lua +++ b/scripts/tests/economy.lua @@ -28,8 +28,6 @@ function test_work() end function test_bug_2361_forget_magic() - -- https://bugs.eressea.de/view.php?id=2361 - -- familiars cannot forget magic local r = region.create(0, 0, "plain") local f = faction.create("human") local u = unit.create(f, r, 1) @@ -38,12 +36,30 @@ function test_bug_2361_forget_magic() u:add_order("VERGESSE Magie") u:set_skill('magic', 5) uf.race = 'unicorn' + u.familiar = uf + process_orders() + assert_equal(0, u:get_skill('magic')) + assert_nil(u.familiar) + -- without a mage, familiars become ghosts: + assert_equal('ghost', uf.race_name) + assert_equal(0, uf:get_skill('magic')) +end + +function test_bug_2361_familiar_cannot_forget_magic_() + -- https://bugs.eressea.de/view.php?id=2361 + local r = region.create(0, 0, "plain") + local f = faction.create("human") + local u = unit.create(f, r, 1) + local uf = unit.create(f, r, 1) + u:clear_orders() + u:set_skill('magic', 5) + uf.race = 'unicorn' uf:clear_orders() uf:add_order("VERGESSE Magie") uf:set_skill('magic', 5) u.familiar = uf process_orders() - assert_equal(0, u:get_skill('magic')) + -- familiars cannot forget magic: assert_equal(5, uf:get_skill('magic')) end diff --git a/src/chaos.c b/src/chaos.c index ef1dffca6..2639592f0 100644 --- a/src/chaos.c +++ b/src/chaos.c @@ -86,6 +86,7 @@ static void chaos(region * r) if (u && playerrace(u_race(u))) { ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u)); u_setfaction(u, get_monsters()); + u_freeorders(u); u_setrace(u, get_race(RC_GHOUL)); } } diff --git a/src/economy.c b/src/economy.c index 7cd28f6b9..35e08ade6 100644 --- a/src/economy.c +++ b/src/economy.c @@ -292,6 +292,7 @@ static int forget_cmd(unit * u, order * ord) if (ufam) { a_removeall(&ufam->attribs, NULL); u_setfaction(ufam, get_monsters()); + u_freeorders(ufam); unit_convert_race(ufam, NULL, "ghost"); } a_removeall(&u->attribs, &at_mage); diff --git a/src/give.c b/src/give.c index 47f472ec1..ac792da9a 100644 --- a/src/give.c +++ b/src/give.c @@ -709,6 +709,7 @@ void give_unit(unit * u, unit * u2, order * ord) } add_give_person(u, u2, u->number, ord, 0); u_setfaction(u, u2->faction); + u_freeorders(u); u2->faction->newbies += u->number; } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 06463820c..e9ec8e657 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -886,6 +886,12 @@ struct building *inside_building(const struct unit *u) return NULL; } +void u_freeorders(unit *u) +{ + free_orders(&u->orders); + set_order(&u->thisorder, NULL); +} + void u_setfaction(unit * u, faction * f) { if (u->faction == f) @@ -896,9 +902,6 @@ void u_setfaction(unit * u, faction * f) u->faction->num_people -= u->number; } set_group(u, NULL); - free_orders(&u->orders); - set_order(&u->thisorder, NULL); - if (u->nextF) { u->nextF->prevF = u->prevF; } diff --git a/src/kernel/unit.h b/src/kernel/unit.h index c77cfdb7a..7fc6fa730 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -179,6 +179,7 @@ extern "C" { /* cleanup code for this module */ void free_units(void); void u_setfaction(struct unit *u, struct faction *f); + void u_freeorders(struct unit *u); void set_number(struct unit *u, int count); int invisible(const struct unit *target, const struct unit *viewer); diff --git a/src/laws.c b/src/laws.c index b1ca5e300..285ee3f1c 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3764,6 +3764,10 @@ void process(void) } if (ord) { porder->data.per_order.process(u, ord); + if (!u->orders) { + /* GIVE UNIT or QUIT delete all orders of the unit, stop */ + break; + } } } if (!ord || *ordp == ord) diff --git a/src/monsters.c b/src/monsters.c index 7cdebfd6c..6f20a8c8b 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -174,6 +174,7 @@ void monsters_desert(struct faction *monsters) ADDMSG(&u->faction->msgs, msg_message("desertion", "unit region", u, r)); u_setfaction(u, monsters); + u_freeorders(u); } } } @@ -1157,6 +1158,7 @@ void monster_kills_peasants(unit * u) void make_zombie(unit * u) { u_setfaction(u, get_monsters()); + u_freeorders(u); scale_number(u, 1); u->hp = unit_max_hp(u) * u->number; u_setrace(u, get_race(RC_ZOMBIE)); diff --git a/src/spells.c b/src/spells.c index 200e87f62..6cff4bb9b 100644 --- a/src/spells.c +++ b/src/spells.c @@ -3553,7 +3553,7 @@ static int sp_charmingsong(castorder * co) /* setze Partei um und loesche langen Befehl aus Sicherheitsgruenden */ u_setfaction(target, mage->faction); - set_order(&target->thisorder, NULL); + u_freeorders(target); /* setze Parteitarnung, damit nicht sofort klar ist, wer dahinter * steckt */ @@ -3796,7 +3796,7 @@ static int sp_migranten(castorder * co) return 0; } u_setfaction(target, mage->faction); - set_order(&target->thisorder, NULL); + u_freeorders(target); /* Erfolg melden */ ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "sp_migranten", diff --git a/src/triggers/changefaction.c b/src/triggers/changefaction.c index 36e40ed46..85403083b 100644 --- a/src/triggers/changefaction.c +++ b/src/triggers/changefaction.c @@ -48,7 +48,9 @@ static int changefaction_handle(trigger * t, void *data) */ changefaction_data *td = (changefaction_data *)t->data.v; if (td->unit && td->faction) { - u_setfaction(td->unit, td->faction); + unit * u = td->unit; + u_setfaction(u, td->faction); + u_freeorders(u); } else { log_error("could not perform changefaction::handle()\n");