diff --git a/src/kernel/faction.c b/src/kernel/faction.c index f0010ddce..6f2a34d5e 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -35,6 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include /* util includes */ #include @@ -361,6 +362,71 @@ void free_flist(faction **fp) { static faction *dead_factions; +static void give_special_items(unit *u, item **items) { + item **iter = items; + while (*iter) { + item *itm = *iter; + if (itm->number > 0 && itm->type->flags & ITF_NOTLOST) { + i_change(&u->items, itm->type, itm->number); + *iter = itm->next; + if (iter == items) { + *items = *iter; + } + i_free(itm); + } + else { + iter = &itm->next; + } + } +} + +faction *get_or_create_monsters(void) +{ + faction *f = findfaction(MONSTER_ID); + if (!f) { + const race *rc = rc_get_or_create("dragon"); + const char *email = config_get("monster.email"); + f = addfaction(email, NULL, rc, default_locale, 0); + renumber_faction(f, MONSTER_ID); + faction_setname(f, "Monster"); + fset(f, FFL_NPC | FFL_NOIDLEOUT); + } + return f; +} + +faction *get_monsters(void) { + return get_or_create_monsters(); +} + +void save_special_items(unit *usrc) +{ + unit *u; + region *r = usrc->region; + faction *fm = get_monsters(); + static const race *rc_ghost; + static int cache; + static const char *name = NULL; + if (rc_changed(&cache)) { + rc_ghost = rc_find("ghost"); + if (!rc_ghost) { + rc_ghost = get_race(RC_TEMPLATE); + name = "ghost"; + } + assert(rc_ghost); + } + for (u = r->units; u; u = u->next) { + if (u->faction == fm) { + give_special_items(u, &usrc->items); + return; + } + } + u = create_unit(r, fm, 1, rc_ghost, 0, NULL, NULL); + if (name) { + set_racename(&u->attribs, name); + } + give_special_items(u, &usrc->items); +} + void destroyfaction(faction ** fp) { faction * f = *fp; @@ -385,22 +451,19 @@ void destroyfaction(faction ** fp) } while (u) { - /* give away your stuff, make zombies if you cannot (quest items) */ - int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS); - if (result != 0) { - unit *zombie = u; - u = u->nextF; - make_zombie(zombie); - } - else { + /* give away your stuff, to ghosts if you cannot (quest items) */ + if (u->items) { region *r = u->region; - + int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS); + if (result != 0) { + save_special_items(u); + } if (r->land && !!playerrace(u_race(u))) { const race *rc = u_race(u); int m = rmoney(r); /* Personen gehen nur an die Bauern, wenn sie auch von dort - * stammen */ + * stammen */ if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { int p = rpeasants(u->region); int h = rhorses(u->region); @@ -418,9 +481,9 @@ void destroyfaction(faction ** fp) m += get_money(u); rsetmoney(r, m); } - set_number(u, 0); - u = u->nextF; } + set_number(u, 0); + u = u->nextF; } handle_event(f->attribs, "destroy", f); diff --git a/src/kernel/faction.h b/src/kernel/faction.h index 8b8c88abe..e884c71c6 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -168,7 +168,13 @@ extern "C" { int count_maxmigrants(const struct faction * f); int max_magicians(const struct faction * f); +#define MONSTER_ID 666 struct faction *getfaction(void); + struct faction *get_monsters(void); + struct faction *get_or_create_monsters(void); + void save_special_items(struct unit *u); + +#define is_monsters(f) (f->no==MONSTER_ID) #ifdef __cplusplus } diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index 251f11bb9..8440e6e05 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -12,6 +13,8 @@ #include #include +#include + #include "monsters.h" #include #include @@ -250,6 +253,44 @@ static void test_set_email(CuTest *tc) { test_cleanup(); } +static void test_items_notlost(CuTest *tc) { + unit *u, *ug; + race * rc; + struct item_type *itype, *it_silver, *it_horse; + + test_setup(); + it_horse = test_create_horse(); + it_silver = test_create_silver(); + itype = test_create_itemtype("banana"); + itype->flags |= ITF_NOTLOST; + rc = test_create_race("template"); + u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + i_change(&u->items, itype, 1); + save_special_items(u); + CuAssertPtrNotNull(tc, u->next); + ug = u->next; + CuAssertPtrEquals(tc, NULL, ug->next); + CuAssertPtrEquals(tc, rc, (void *)ug->_race); + CuAssertIntEquals(tc, 0, i_get(u->items, itype)); + CuAssertIntEquals(tc, 1, i_get(ug->items, itype)); + CuAssertStrEquals(tc, "ghost", get_racename(ug->attribs)); + + i_change(&u->items, itype, 1); + save_special_items(u); + CuAssertPtrEquals(tc, NULL, ug->next); + CuAssertIntEquals(tc, 2, i_get(ug->items, itype)); + CuAssertPtrEquals(tc, NULL, u->items); + + i_change(&u->items, itype, 1); + i_change(&u->items, it_horse, 5); + i_change(&u->items, it_silver, 10); + save_special_items(u); + CuAssertIntEquals(tc, 3, i_get(ug->items, itype)); + CuAssertIntEquals(tc, 5, i_get(u->items, it_horse)); + CuAssertIntEquals(tc, 10, i_get(u->items, it_silver)); + test_cleanup(); +} + CuSuite *get_faction_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -265,5 +306,6 @@ CuSuite *get_faction_suite(void) SUITE_ADD_TEST(suite, test_check_passwd); SUITE_ADD_TEST(suite, test_valid_race); SUITE_ADD_TEST(suite, test_set_email); + SUITE_ADD_TEST(suite, test_items_notlost); return suite; } diff --git a/src/monsters.c b/src/monsters.c index a17d9f1fa..ade13af48 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -1128,24 +1128,6 @@ void monster_kills_peasants(unit * u) } } -faction *get_or_create_monsters(void) -{ - faction *f = findfaction(MONSTER_ID); - if (!f) { - const race *rc = rc_get_or_create("dragon"); - const char *email = config_get("monster.email"); - f = addfaction(email, NULL, rc, default_locale, 0); - renumber_faction(f, MONSTER_ID); - faction_setname(f, "Monster"); - fset(f, FFL_NPC | FFL_NOIDLEOUT); - } - return f; -} - -faction *get_monsters(void) { - return get_or_create_monsters(); -} - void make_zombie(unit * u) { u_setfaction(u, get_monsters()); diff --git a/src/monsters.h b/src/monsters.h index a5a3ccd15..f3ea2d362 100644 --- a/src/monsters.h +++ b/src/monsters.h @@ -35,13 +35,8 @@ extern "C" { void monster_kills_peasants(struct unit *u); bool monster_is_waiting(const struct unit *u); - struct faction *get_monsters(void); - struct faction *get_or_create_monsters(void); void make_zombie(struct unit * u); -#define MONSTER_ID 666 -#define is_monsters(f) ((f->flags & FFL_NPC) && f==get_monsters()) - #ifdef __cplusplus } #endif diff --git a/src/tests.c b/src/tests.c index 70f006ef6..2773602de 100644 --- a/src/tests.c +++ b/src/tests.c @@ -390,6 +390,12 @@ void test_translate_param(const struct locale *lang, param_t param, const char * add_translation(cb, text, param); } +item_type *test_create_silver(void) { + item_type * itype; + itype = test_create_itemtype("money"); + itype->weight = 1; + return itype; +} item_type *test_create_horse(void) { item_type * itype; diff --git a/src/tests.h b/src/tests.h index 669318d99..f771786ff 100644 --- a/src/tests.h +++ b/src/tests.h @@ -50,6 +50,7 @@ extern "C" { struct unit *test_create_unit(struct faction *f, struct region *r); void test_create_world(void); struct item_type * test_create_horse(void); + struct item_type * test_create_silver(void); struct building * test_create_building(struct region * r, const struct building_type * btype); struct ship * test_create_ship(struct region * r, const struct ship_type * stype); struct item_type * test_create_itemtype(const char * name);