forked from github/server
bug 2387: create a ghost to hold on to magical notlost items.
This commit is contained in:
parent
01c808da66
commit
6927eed52e
7 changed files with 130 additions and 35 deletions
|
@ -35,6 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include <spells/unitcurse.h>
|
#include <spells/unitcurse.h>
|
||||||
#include <attributes/otherfaction.h>
|
#include <attributes/otherfaction.h>
|
||||||
|
#include <attributes/racename.h>
|
||||||
|
|
||||||
/* util includes */
|
/* util includes */
|
||||||
#include <util/attrib.h>
|
#include <util/attrib.h>
|
||||||
|
@ -361,6 +362,71 @@ void free_flist(faction **fp) {
|
||||||
|
|
||||||
static faction *dead_factions;
|
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)
|
void destroyfaction(faction ** fp)
|
||||||
{
|
{
|
||||||
faction * f = *fp;
|
faction * f = *fp;
|
||||||
|
@ -385,22 +451,19 @@ void destroyfaction(faction ** fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (u) {
|
while (u) {
|
||||||
/* give away your stuff, make zombies if you cannot (quest items) */
|
/* give away your stuff, to ghosts if you cannot (quest items) */
|
||||||
int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS);
|
if (u->items) {
|
||||||
if (result != 0) {
|
|
||||||
unit *zombie = u;
|
|
||||||
u = u->nextF;
|
|
||||||
make_zombie(zombie);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
region *r = u->region;
|
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))) {
|
if (r->land && !!playerrace(u_race(u))) {
|
||||||
const race *rc = u_race(u);
|
const race *rc = u_race(u);
|
||||||
int m = rmoney(r);
|
int m = rmoney(r);
|
||||||
|
|
||||||
/* Personen gehen nur an die Bauern, wenn sie auch von dort
|
/* Personen gehen nur an die Bauern, wenn sie auch von dort
|
||||||
* stammen */
|
* stammen */
|
||||||
if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) {
|
if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) {
|
||||||
int p = rpeasants(u->region);
|
int p = rpeasants(u->region);
|
||||||
int h = rhorses(u->region);
|
int h = rhorses(u->region);
|
||||||
|
@ -418,9 +481,9 @@ void destroyfaction(faction ** fp)
|
||||||
m += get_money(u);
|
m += get_money(u);
|
||||||
rsetmoney(r, m);
|
rsetmoney(r, m);
|
||||||
}
|
}
|
||||||
set_number(u, 0);
|
|
||||||
u = u->nextF;
|
|
||||||
}
|
}
|
||||||
|
set_number(u, 0);
|
||||||
|
u = u->nextF;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_event(f->attribs, "destroy", f);
|
handle_event(f->attribs, "destroy", f);
|
||||||
|
|
|
@ -168,7 +168,13 @@ extern "C" {
|
||||||
int count_maxmigrants(const struct faction * f);
|
int count_maxmigrants(const struct faction * f);
|
||||||
int max_magicians(const struct faction * f);
|
int max_magicians(const struct faction * f);
|
||||||
|
|
||||||
|
#define MONSTER_ID 666
|
||||||
struct faction *getfaction(void);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <kernel/ally.h>
|
#include <kernel/ally.h>
|
||||||
#include <kernel/alliance.h>
|
#include <kernel/alliance.h>
|
||||||
#include <kernel/faction.h>
|
#include <kernel/faction.h>
|
||||||
|
#include <kernel/item.h>
|
||||||
#include <kernel/plane.h>
|
#include <kernel/plane.h>
|
||||||
#include <kernel/race.h>
|
#include <kernel/race.h>
|
||||||
#include <kernel/region.h>
|
#include <kernel/region.h>
|
||||||
|
@ -12,6 +13,8 @@
|
||||||
#include <util/language.h>
|
#include <util/language.h>
|
||||||
#include <util/password.h>
|
#include <util/password.h>
|
||||||
|
|
||||||
|
#include <attributes/racename.h>
|
||||||
|
|
||||||
#include "monsters.h"
|
#include "monsters.h"
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
@ -250,6 +253,44 @@ static void test_set_email(CuTest *tc) {
|
||||||
test_cleanup();
|
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 *get_faction_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
@ -265,5 +306,6 @@ CuSuite *get_faction_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_check_passwd);
|
SUITE_ADD_TEST(suite, test_check_passwd);
|
||||||
SUITE_ADD_TEST(suite, test_valid_race);
|
SUITE_ADD_TEST(suite, test_valid_race);
|
||||||
SUITE_ADD_TEST(suite, test_set_email);
|
SUITE_ADD_TEST(suite, test_set_email);
|
||||||
|
SUITE_ADD_TEST(suite, test_items_notlost);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
void make_zombie(unit * u)
|
||||||
{
|
{
|
||||||
u_setfaction(u, get_monsters());
|
u_setfaction(u, get_monsters());
|
||||||
|
|
|
@ -35,13 +35,8 @@ extern "C" {
|
||||||
|
|
||||||
void monster_kills_peasants(struct unit *u);
|
void monster_kills_peasants(struct unit *u);
|
||||||
bool monster_is_waiting(const 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);
|
void make_zombie(struct unit * u);
|
||||||
|
|
||||||
#define MONSTER_ID 666
|
|
||||||
#define is_monsters(f) ((f->flags & FFL_NPC) && f==get_monsters())
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -390,6 +390,12 @@ void test_translate_param(const struct locale *lang, param_t param, const char *
|
||||||
add_translation(cb, text, param);
|
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 *test_create_horse(void) {
|
||||||
item_type * itype;
|
item_type * itype;
|
||||||
|
|
|
@ -50,6 +50,7 @@ extern "C" {
|
||||||
struct unit *test_create_unit(struct faction *f, struct region *r);
|
struct unit *test_create_unit(struct faction *f, struct region *r);
|
||||||
void test_create_world(void);
|
void test_create_world(void);
|
||||||
struct item_type * test_create_horse(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 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 ship * test_create_ship(struct region * r, const struct ship_type * stype);
|
||||||
struct item_type * test_create_itemtype(const char * name);
|
struct item_type * test_create_itemtype(const char * name);
|
||||||
|
|
Loading…
Reference in a new issue