bug 2387: create a ghost to hold on to magical notlost items.

This commit is contained in:
Enno Rehling 2017-12-25 19:11:12 +01:00
parent 01c808da66
commit 6927eed52e
7 changed files with 130 additions and 35 deletions

View file

@ -35,6 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <spells/unitcurse.h>
#include <attributes/otherfaction.h>
#include <attributes/racename.h>
/* util includes */
#include <util/attrib.h>
@ -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);

View file

@ -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
}

View file

@ -3,6 +3,7 @@
#include <kernel/ally.h>
#include <kernel/alliance.h>
#include <kernel/faction.h>
#include <kernel/item.h>
#include <kernel/plane.h>
#include <kernel/race.h>
#include <kernel/region.h>
@ -12,6 +13,8 @@
#include <util/language.h>
#include <util/password.h>
#include <attributes/racename.h>
#include "monsters.h"
#include <CuTest.h>
#include <tests.h>
@ -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;
}

View file

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

View file

@ -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

View file

@ -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;

View file

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