- removing planes

- removing units and regions more cleanly
- dying units won't give items to undead or others who don't want/won't return them
- removed old "nogive" attribute for races.
This commit is contained in:
Enno Rehling 2008-05-18 13:46:18 +00:00
parent 78520fb9bf
commit 8452dc365e
17 changed files with 324 additions and 279 deletions

View File

@ -230,6 +230,7 @@ select_recruitment(request ** rop, int (*quantify)(const struct race*, int), int
static void static void
add_recruits(unit * u, int number, int wanted) add_recruits(unit * u, int number, int wanted)
{ {
region * r = u->region;
assert(number<=wanted); assert(number<=wanted);
if (number > 0) { if (number > 0) {
unit * unew; unit * unew;
@ -242,7 +243,7 @@ add_recruits(unit * u, int number, int wanted)
u->hp = number * unit_max_hp(u); u->hp = number * unit_max_hp(u);
unew = u; unew = u;
} else { } else {
unew = create_unit(u->region, u->faction, number, u->race, 0, NULL, u); unew = create_unit(r, u->faction, number, u->race, 0, NULL, u);
} }
if (unew->race == new_race[RC_URUK]) { if (unew->race == new_race[RC_URUK]) {
@ -271,12 +272,12 @@ add_recruits(unit * u, int number, int wanted)
#endif /* KARMA_MODULE */ #endif /* KARMA_MODULE */
if (unew!=u) { if (unew!=u) {
transfermen(unew, u, unew->number); transfermen(unew, u, unew->number);
destroy_unit(unew); remove_unit(&r->units, unew);
} }
} }
if (number < wanted) { if (number < wanted) {
ADDMSG(&u->faction->msgs, msg_message("recruit", ADDMSG(&u->faction->msgs, msg_message("recruit",
"unit region amount want", u, u->region, number, wanted)); "unit region amount want", u, r, number, wanted));
} }
} }
@ -653,12 +654,6 @@ give_cmd(unit * u, order * ord)
return; return;
} }
else if (u2 && u->race->ec_flags & NOGIVE) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "race_nogive", "race", u->race));
return;
}
else if (p == P_HERBS) { else if (p == P_HERBS) {
boolean given = false; boolean given = false;
if (!(u->race->ec_flags & GIVEITEM) && u2!=NULL) { if (!(u->race->ec_flags & GIVEITEM) && u2!=NULL) {

View File

@ -335,7 +335,7 @@ age_unit(region * r, unit * u)
{ {
if (u->race == new_race[RC_SPELL]) { if (u->race == new_race[RC_SPELL]) {
if (--u->age <= 0) { if (--u->age <= 0) {
destroy_unit(u); remove_unit(&r->units, u);
} }
} else { } else {
++u->age; ++u->age;
@ -343,24 +343,6 @@ age_unit(region * r, unit * u)
u->race->age(u); u->race->age(u);
} }
} }
#ifdef ASTRAL_ITEM_RESTRICTIONS
if (u->region->planep==get_astralplane()) {
item ** itemp = &u->items;
while (*itemp) {
item * itm = *itemp;
if ((itm->type->flags & ITF_NOTLOST) == 0) {
if (itm->type->flags & (ITF_BIG|ITF_ANIMAL|ITF_CURSED)) {
ADDMSG(&u->faction->msgs, msg_message("itemcrumble", "unit region item amount",
u, u->region, itm->type->rtype, itm->number));
i_free(i_remove(itemp, itm));
continue;
}
}
itemp=&itm->next;
}
}
#endif
} }
@ -1132,7 +1114,7 @@ ally_cmd(unit * u, struct order * ord)
skip_token(); skip_token();
f = getfaction(); f = getfaction();
if (is_monsters(f)) { if (f==NULL || is_monsters(f)) {
cmistake(u, ord, 66, MSG_EVENT); cmistake(u, ord, 66, MSG_EVENT);
return 0; return 0;
} }
@ -2908,7 +2890,7 @@ age_building(building * b)
* find out if there's a magician in there. */ * find out if there's a magician in there. */
for (u=r->units;u;u=u->next) { for (u=r->units;u;u=u->next) {
if (b==u->building && inside_building(u)) { if (b==u->building && inside_building(u)) {
if (!(u->race->ec_flags & NOGIVE)) { if (!(u->race->ec_flags & GIVEITEM)==0) {
int n, unicorns = 0; int n, unicorns = 0;
for (n=0; n!=u->number; ++n) { for (n=0; n!=u->number; ++n) {
if (chance(0.02)) { if (chance(0.02)) {

View File

@ -510,8 +510,9 @@ sink_ship(region * r, ship * sh, const char *name, char spy, unit * saboteur)
msg_release(msg); msg_release(msg);
if (dead == u->number) { if (dead == u->number) {
/* the poor creature, she dies */ /* the poor creature, she dies */
*ui = u->next; if (remove_unit(ui, u)!=0) {
destroy_unit(u); ui = &u->next;
}
} }
} }
} }

View File

@ -2392,8 +2392,7 @@ remove_empty_units_in_region(region *r)
} }
} }
if ((u->number == 0 && u->race != new_race[RC_SPELL]) || (u->age <= 0 && u->race == new_race[RC_SPELL])) { if ((u->number == 0 && u->race != new_race[RC_SPELL]) || (u->age <= 0 && u->race == new_race[RC_SPELL])) {
if (u->faction!=NULL) destroy_unit(u); remove_unit(up, u);
if (u->number==0) remove_unit(u);
} }
if (*up==u) up=&u->next; if (*up==u) up=&u->next;
} }

View File

@ -241,7 +241,20 @@ destroyfaction(faction * f)
for (u=f->units;u;u=u->nextF) { for (u=f->units;u;u=u->nextF) {
region * r = u->region; region * r = u->region;
distribute_items(u);
/* give away your stuff, make zombies if you cannot (quest items) */
while (u) {
int result = gift_items(u, GIFT_FRIENDS|GIFT_PEASANTS);
if (result!=0) {
unit * zombie = u;
u = u->nextF;
make_zombie(zombie);
} else {
break;
}
}
if (u==NULL) continue;
if (!fval(r->terrain, SEA_REGION) && !!playerrace(u->race)) { if (!fval(r->terrain, SEA_REGION) && !!playerrace(u->race)) {
const race * rc = u->race; const race * rc = u->race;
int m = rmoney(u->region); int m = rmoney(u->region);

View File

@ -189,7 +189,6 @@ get_pooled(const unit * u, const resource_type * rtype, unsigned int mode, int c
int mask; int mask;
if (u==v) continue; if (u==v) continue;
if (urace(v)->ec_flags & NOGIVE) continue;
if ((urace(v)->ec_flags & GIVEITEM) == 0) continue; if ((urace(v)->ec_flags & GIVEITEM) == 0) continue;
if (v->faction == f) { if (v->faction == f) {
@ -238,7 +237,6 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count)
if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK|GET_RESERVE)) { if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK|GET_RESERVE)) {
for (v = r->units; use>0 && v!=NULL; v = v->next) if (u!=v) { for (v = r->units; use>0 && v!=NULL; v = v->next) if (u!=v) {
int mask; int mask;
if (urace(v)->ec_flags & NOGIVE) continue;
if ((urace(v)->ec_flags & GIVEITEM) == 0) continue; if ((urace(v)->ec_flags & GIVEITEM) == 0) continue;
if (v->faction == f) { if (v->faction == f) {

View File

@ -136,7 +136,6 @@ extern int rc_specialdamage(const race *, const race *, const struct weapon_type
#define RCF_INVISIBLE (1<<25) /* not visible in any report */ #define RCF_INVISIBLE (1<<25) /* not visible in any report */
/* Economic flags */ /* Economic flags */
#define NOGIVE (1<<0) /* gibt niemals nix */
#define GIVEITEM (1<<1) /* gibt Gegenstände weg */ #define GIVEITEM (1<<1) /* gibt Gegenstände weg */
#define GIVEPERSON (1<<2) /* übergibt Personen */ #define GIVEPERSON (1<<2) /* übergibt Personen */
#define GIVEUNIT (1<<3) /* Einheiten an andere Partei übergeben */ #define GIVEUNIT (1<<3) /* Einheiten an andere Partei übergeben */

View File

@ -35,6 +35,7 @@
#include "region.h" #include "region.h"
#include "resources.h" #include "resources.h"
#include "save.h" #include "save.h"
#include "ship.h"
#include "terrain.h" #include "terrain.h"
#include "terrainid.h" #include "terrainid.h"
#include "unit.h" #include "unit.h"
@ -859,6 +860,26 @@ new_region(short x, short y, unsigned int uid)
return r; return r;
} }
static region * deleted_regions;
void
remove_region(region ** rlist, region * r)
{
while (r->units) {
unit * u = r->units;
i_freeall(&u->items);
remove_unit(&r->units, u);
}
runhash(r);
while (*rlist && *rlist!=r) rlist=&(*rlist)->next;
assert(*rlist==r);
*rlist = r->next;
r->next = deleted_regions;
deleted_regions = r;
}
static void static void
freeland(land_region * lr) freeland(land_region * lr)
{ {
@ -874,7 +895,6 @@ freeland(land_region * lr)
void void
free_region(region * r) free_region(region * r)
{ {
runhash(r);
if (last == r) last = NULL; if (last == r) last = NULL;
free(r->display); free(r->display);
if (r->land) freeland(r->land); if (r->land) freeland(r->land);
@ -904,9 +924,49 @@ free_region(region * r)
free(don); free(don);
} }
while (r->units) {
unit * u = r->units;
r->units = u->next;
uunhash(u);
free_unit(u);
free(u);
}
while (r->buildings) {
building * b = r->buildings;
r->buildings = b->next;
free(b->name);
free(b->display);
free(b);
}
while (r->ships) {
ship * s = r->ships;
r->ships = s->next;
free(s->name);
free(s->display);
free(s);
}
free(r); free(r);
} }
void
free_regions(void)
{
while (deleted_regions) {
region * r = deleted_regions;
deleted_regions = r->next;
free_region(r);
}
while (regions) {
region * r = regions;
regions = r->next;
runhash(r);
free_region(r);
}
}
/** creates a name for a region /** creates a name for a region
* TODO: Make this XML-configurable and allow non-ascii characters again. * TODO: Make this XML-configurable and allow non-ascii characters again.
*/ */

View File

@ -221,6 +221,7 @@ extern const char * write_regionname(const struct region * r, const struct facti
extern void resolve_region(variant data, void * address); extern void resolve_region(variant data, void * address);
extern struct region * new_region(short x, short y, unsigned int uid); extern struct region * new_region(short x, short y, unsigned int uid);
extern void remove_region(region ** rlist, region * r);
extern void terraform(struct region * r, terrain_t terrain); extern void terraform(struct region * r, terrain_t terrain);
extern void terraform_region(struct region * r, const struct terrain_type * terrain); extern void terraform_region(struct region * r, const struct terrain_type * terrain);
@ -243,6 +244,8 @@ extern struct region * r_connect(const struct region *, direction_t dir);
extern unsigned int generate_region_id(void); extern unsigned int generate_region_id(void);
extern void free_regions(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -155,47 +155,99 @@ dfindhash(int no)
return 0; return 0;
} }
unit * udestroy = NULL; typedef struct friend {
struct friend * next;
int number;
faction * faction;
unit * unit;
} friend;
/** distributes a unit's posessions to friendly units static friend *
* this happens when units die and no own units are in the region get_friends(const unit * u, int * numfriends)
*/
void
distribute_items(unit * u)
{ {
friend * friends = 0;
faction * f = u->faction; faction * f = u->faction;
region * r = u->region; region * r = u->region;
unit * au;
int number = 0; int number = 0;
struct friend { unit * u2;
struct friend * next;
int number;
faction * faction;
unit * unit;
} * friends = NULL;
if (u->items==NULL) return; for (u2=r->units;u2;u2=u2->next) {
if (u2->faction!=f && u2->number>0) {
if (alliedunit(u, u2->faction, HELP_MONEY) && alliedunit(u2, f, HELP_GIVE)) {
friend * nf, ** fr = &friends;
for (au=r->units;au;au=au->next) if (au->faction!=f && au->number>0) { /* some units won't take stuff: */
if (alliedunit(u, au->faction, HELP_MONEY) && alliedunit(au, f, HELP_GIVE)) { if (u2->race->ec_flags & GETITEM) {
struct friend * nf, ** fr = &friends; while (*fr && (*fr)->faction->no<u2->faction->no) fr = &(*fr)->next;
nf = *fr;
while (*fr && (*fr)->faction->no<au->faction->no) fr = &(*fr)->next; if (nf==NULL || nf->faction!=u2->faction) {
nf = *fr; nf = malloc(sizeof(friend));
if (nf==NULL || nf->faction!=au->faction) { nf->next = *fr;
nf = malloc(sizeof(struct friend)); nf->faction = u2->faction;
nf->next = *fr; nf->unit = u2;
nf->faction = au->faction; nf->number = 0;
nf->unit = au; *fr = nf;
nf->number = 0; } else if (nf->faction==u2->faction && (u2->race->ec_flags & GIVEITEM)) {
*fr = nf; /* we don't like to gift it to units that won't give it back */
if ((nf->unit->race->ec_flags & GIVEITEM) == 0) {
nf->unit = u2;
}
}
nf->number += u2->number;
number += u2->number;
}
} }
nf->number += au->number;
number += au->number;
} }
} }
if (numfriends) *numfriends = number;
return friends;
}
/** give all items to friends or peasants.
* this function returns 0 on success, or 1 if there are items that
* could not be destroyed.
*/
int
gift_items(unit * u, int flags)
{
region * r = u->region;
item ** itm_p = &u->items;
int retval = 0;
if (u->items==NULL || fval(u->race, RCF_ILLUSIONARY)) return 0;
if ((u->race->ec_flags & GIVEITEM) == 0) return 0;
/* at first, I should try giving my crap to my own units in this region */
if (u->faction && (flags & GIFT_SELF)) {
unit * u2, * u3 = NULL;
for (u2 = r->units; u2; u2 = u2->next) {
if (u2 != u && u2->faction == u->faction && u2->number>0) {
/* some units won't take stuff: */
if (u2->race->ec_flags & GETITEM) {
/* we don't like to gift it to units that won't give it back */
if (u2->race->ec_flags & GIVEITEM) {
i_merge(&u2->items, &u->items);
u->items = NULL;
break;
} else {
u3 = u2;
}
}
}
}
if (u->items && u3) {
/* if nobody else takes it, we give it to a unit that has issues */
i_merge(&u3->items, &u->items);
u->items = NULL;
}
if (u->items==NULL) return 0;
}
/* if I have friends, I'll try to give my stuff to them */
if (u->faction && (flags & GIFT_FRIENDS)) {
int number = 0;
friend * friends = get_friends(u, &number);
if (friends) {
while (friends) { while (friends) {
struct friend * nf = friends; struct friend * nf = friends;
unit * u2 = nf->unit; unit * u2 = nf->unit;
@ -215,116 +267,85 @@ distribute_items(unit * u)
friends = nf->next; friends = nf->next;
free(nf); free(nf);
} }
friends = NULL; if (u->items==NULL) return 0;
}
}
void
remove_unit(unit * u)
{
region * r = u->region;
assert(u->number==0);
uunhash(u);
if (r) choplist(&r->units, u);
u->next = udestroy;
udestroy = u;
}
void
destroy_unit(unit * u)
{
region *r = u->region;
boolean zombie = false;
#if 0
unit *clone;
#endif
if (!ufindhash(u->no)) return;
if (!fval(u->race, RCF_ILLUSIONARY)) {
item ** p_item = &u->items;
unit * u3;
/* u->faction->no_units--; */ /* happens in u_setfaction now */
if (r) for (u3 = r->units; u3; u3 = u3->next) {
if (u3 != u && u3->faction == u->faction && playerrace(u3->race)) {
i_merge(&u3->items, &u->items);
u->items = NULL;
break;
}
}
u3 = NULL;
while (*p_item) {
item * item = *p_item;
if (item->number && item->type->flags & ITF_NOTLOST) {
if (u3==NULL) {
u3 = r->units;
while (u3 && u3!=u) u3 = u3->next;
if (!u3) {
zombie = true;
break;
}
}
if (u3) {
i_add(&u3->items, i_remove(p_item, item));
}
}
if (*p_item == item) p_item=&item->next;
}
if (u->items && (u->faction==NULL || u->faction->passw[0])) {
distribute_items(u);
}
} }
/* Wir machen das erst nach dem Löschen der Items. Der Klon darf keine /* last, but not least, give money and horses to peasants */
* Items haben, sonst Memory-Leak. */ while (*itm_p) {
#if 0 item * itm = *itm_p;
/* broken. */
clone = has_clone(u);
if (clone && rng_int()%100 < 90) {
attrib *a;
int i;
/* TODO: Messages generieren. */ if (flags & GIFT_PEASANTS) {
if (u->region!=clone->region) { if (!fval(u->region->terrain, SEA_REGION)) {
move_unit(u, clone->region, NULL); if (itm->type==olditemtype[I_HORSE]) {
rsethorses(r, rhorses(r) + itm->number);
itm->number = 0;
} else if (itm->type==i_silver) {
rsetmoney(r, rmoney(r) + itm->number);
itm->number = 0;
}
}
} }
if (fval(u->race, RCF_CANSAIL)) { if (itm->number>0 && (itm->type->flags & ITF_NOTLOST)) {
u->ship = clone->ship; itm_p = &itm->next;
} retval = -1;
u->building = clone->building;
u->hp = 1;
i = u->no;
uunhash(u);
uunhash(clone);
u->no = clone->no;
clone->no = i;
uhash(u);
uhash(clone);
set_number(u, 1);
set_spellpoints(u, 0);
a = a_find(u->attribs, &at_clone);
if (a!=NULL) a_remove(&u->attribs, a);
a = a_find(clone->attribs, &at_clonemage);
if (a!=NULL) a_remove(&clone->attribs, a);
fset(u, UFL_LONGACTION|UFL_NOTMOVING);
set_number(clone, 0);
} else
#endif
if (zombie) {
u_setfaction(u, get_monsters());
scale_number(u, 1);
u->race = u->irace = new_race[RC_ZOMBIE];
} else { } else {
if (u->number) set_number(u, 0); i_remove(itm_p, itm);
handle_event(u->attribs, "destroy", u); i_free(itm);
if (r && !fval(r->terrain, SEA_REGION)) {
rsetmoney(r, rmoney(r) + get_money(u));
}
dhash(u->no, u->faction);
u_setfaction(u, NULL);
if (r) leave(r, u);
} }
}
return retval;
}
void
make_zombie(unit * u)
{
u_setfaction(u, get_monsters());
scale_number(u, 1);
u->race = u->irace = new_race[RC_ZOMBIE];
}
/** remove the unit from the list of active units.
* the unit is not actually freed, because there may still be references
* dangling to it (from messages, for example). To free all removed units,
* call free_units().
* returns 0 on success, or -1 if unit could not be removed.
*/
static unit * deleted_units = NULL;
int
remove_unit(unit ** ulist, unit * u)
{
int result;
assert(ufindhash(u->no));
handle_event(u->attribs, "destroy", u);
result = gift_items(u, GIFT_SELF|GIFT_FRIENDS|GIFT_PEASANTS);
if (result!=0) {
make_zombie(u);
return -1;
}
if (u->number) set_number(u, 0);
leave(u->region, u);
uunhash(u);
if (ulist) {
while (*ulist!=u) {
ulist = &(*ulist)->next;
}
assert(*ulist==u);
*ulist = u->next;
}
u->next = deleted_units;
deleted_units = u;
dhash(u->no, u->faction);
u_setfaction(u, NULL);
return 0;
} }
unit * unit *
@ -588,10 +609,10 @@ ucontact(const unit * u, const unit * u2)
void void
free_units(void) free_units(void)
{ {
while (udestroy) { while (deleted_units) {
unit * u = udestroy; unit * u = deleted_units;
udestroy = udestroy->next; deleted_units = deleted_units->next;
stripunit(u); free_unit(u);
free(u); free(u);
} }
} }
@ -1294,14 +1315,19 @@ invisible(const unit *target, const unit * viewer)
#endif #endif
} }
/** remove the unit from memory.
* this frees all memory that's only accessible through the unit,
* and you should already have called uunhash and removed the unit from the
* region.
*/
void void
stripunit(unit * u) free_unit(unit * u)
{ {
free(u->name); free(u->name);
free(u->display); free(u->display);
free_order(u->thisorder); free_order(u->thisorder);
free_orders(&u->orders); free_orders(&u->orders);
if(u->skills) free(u->skills); if (u->skills) free(u->skills);
while (u->items) { while (u->items) {
item * it = u->items->next; item * it = u->items->next;
u->items->next = NULL; u->items->next = NULL;

View File

@ -159,7 +159,6 @@ void usetcontact(struct unit * u, const struct unit * c);
struct unit * findnewunit (const struct region * r, const struct faction *f, int alias); struct unit * findnewunit (const struct region * r, const struct faction *f, int alias);
extern struct unit * udestroy;
extern const char * u_description(const unit * u, const struct locale * lang); extern const char * u_description(const unit * u, const struct locale * lang);
extern struct skill * add_skill(struct unit * u, skill_t id); extern struct skill * add_skill(struct unit * u, skill_t id);
extern void remove_skill(struct unit *u, skill_t sk); extern void remove_skill(struct unit *u, skill_t sk);
@ -174,11 +173,13 @@ extern int eff_skill(const struct unit * u, skill_t sk, const struct region * r)
extern int eff_skill_study(const struct unit * u, skill_t sk, const struct region * r); extern int eff_skill_study(const struct unit * u, skill_t sk, const struct region * r);
extern int get_modifier(const struct unit * u, skill_t sk, int lvl, const struct region * r, boolean noitem); extern int get_modifier(const struct unit * u, skill_t sk, int lvl, const struct region * r, boolean noitem);
extern int remove_unit(struct unit ** ulist, struct unit * u);
/* Einheiten werden nicht wirklich zerstört. */ #define GIFT_SELF 1<<0
extern void destroy_unit(struct unit * u); #define GIFT_FRIENDS 1<<1
extern void remove_unit(struct unit * u); #define GIFT_PEASANTS 1<<2
extern void distribute_items(struct unit * u); int gift_items(struct unit * u, int flags);
void make_zombie(unit * u);
/* see resolve.h */ /* see resolve.h */
extern void resolve_unit(variant data, void * address); extern void resolve_unit(variant data, void * address);
@ -205,7 +206,7 @@ extern void set_number(struct unit * u, int count);
extern boolean learn_skill(struct unit * u, skill_t sk, double chance); extern boolean learn_skill(struct unit * u, skill_t sk, double chance);
extern int invisible(const struct unit *target, const struct unit * viewer); extern int invisible(const struct unit *target, const struct unit * viewer);
extern void stripunit(struct unit * u); extern void free_unit(struct unit * u);
extern void name_unit(struct unit *u); extern void name_unit(struct unit *u);
extern struct unit * create_unit(struct region * r1, struct faction * f, int number, const struct race * rc, int id, const char * dname, struct unit *creator); extern struct unit * create_unit(struct region * r1, struct faction * f, int number, const struct race * rc, int id, const char * dname, struct unit *creator);

View File

@ -1489,7 +1489,6 @@ parse_races(xmlDocPtr doc)
if (xml_bvalue(node, "undead", false)) rc->flags |= RCF_UNDEAD; if (xml_bvalue(node, "undead", false)) rc->flags |= RCF_UNDEAD;
if (xml_bvalue(node, "dragon", false)) rc->flags |= RCF_DRAGON; if (xml_bvalue(node, "dragon", false)) rc->flags |= RCF_DRAGON;
if (xml_bvalue(node, "nogive", false)) rc->ec_flags |= NOGIVE;
if (xml_bvalue(node, "giveitem", false)) rc->ec_flags |= GIVEITEM; if (xml_bvalue(node, "giveitem", false)) rc->ec_flags |= GIVEITEM;
if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON; if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON;
if (xml_bvalue(node, "giveunit", false)) rc->ec_flags |= GIVEUNIT; if (xml_bvalue(node, "giveunit", false)) rc->ec_flags |= GIVEUNIT;

View File

@ -142,41 +142,39 @@ sp_summon_alp(struct castorder *co)
void void
alp_findet_opfer(unit *alp, region *r) alp_findet_opfer(unit *alp, region *r)
{ {
curse * c; curse * c;
attrib * a = a_find(alp->attribs, &at_alp); attrib * a = a_find(alp->attribs, &at_alp);
alp_data * ad = (alp_data*)a->data.v; alp_data * ad = (alp_data*)a->data.v;
unit *mage = ad->mage; unit *mage = ad->mage;
unit *opfer = ad->target; unit *opfer = ad->target;
variant effect; variant effect;
message * msg; message * msg;
assert(opfer); assert(opfer);
assert(mage); assert(mage);
/* Magier und Opfer Bescheid geben */ /* Magier und Opfer Bescheid geben */
msg = msg_message("alp_success", "target", opfer); msg = msg_message("alp_success", "target", opfer);
add_message(&mage->faction->msgs, msg); add_message(&mage->faction->msgs, msg);
r_addmessage(opfer->region, opfer->faction, msg); r_addmessage(opfer->region, opfer->faction, msg);
msg_release(msg); msg_release(msg);
/* Relations werden in destroy_unit(alp) automatisch gelöscht. /* Relations werden in destroy_unit(alp) automatisch gelöscht.
* Die Aktionen, die beim Tod des Alps ausgelöst werden sollen, * Die Aktionen, die beim Tod des Alps ausgelöst werden sollen,
* müssen jetzt aber deaktiviert werden, sonst werden sie gleich * müssen jetzt aber deaktiviert werden, sonst werden sie gleich
* beim destroy_unit(alp) ausgelöst. * beim destroy_unit(alp) ausgelöst.
*/ */
a_removeall(&alp->attribs, &at_eventhandler); a_removeall(&alp->attribs, &at_eventhandler);
/* Alp umwandeln in Curse */ /* Alp umwandeln in Curse */
effect.i = -2; effect.i = -2;
c = create_curse(mage, &opfer->attribs, ct_find("worse"), 2, 2, effect, opfer->number); c = create_curse(mage, &opfer->attribs, ct_find("worse"), 2, 2, effect, opfer->number);
/* solange es noch keine spezielle alp-Antimagie gibt, reagiert der /* solange es noch keine spezielle alp-Antimagie gibt, reagiert der
* auch auf normale */ * auch auf normale */
destroy_unit(alp); remove_unit(&r->units, alp);
{ /* wenn der Magier stirbt, wird der Curse wieder vom Opfer genommen */
/* wenn der Magier stirbt, wird der Curse wieder vom Opfer genommen */ add_trigger(&mage->attribs, "destroy", trigger_removecurse(c, opfer));
add_trigger(&mage->attribs, "destroy", trigger_removecurse(c, opfer));
}
} }
void void

View File

@ -16,6 +16,7 @@
#include <kernel/eressea.h> #include <kernel/eressea.h>
#include "killunit.h" #include "killunit.h"
#include <kernel/region.h>
#include <kernel/unit.h> #include <kernel/unit.h>
/* util includes */ /* util includes */
@ -34,17 +35,17 @@
static int static int
killunit_handle(trigger * t, void * data) killunit_handle(trigger * t, void * data)
{ {
/* call an event handler on killunit. /* call an event handler on killunit.
* data.v -> ( variant event, int timer ) * data.v -> ( variant event, int timer )
*/ */
unit * u = (unit*)t->data.v; unit * u = (unit*)t->data.v;
if (u!=NULL) { if (u!=NULL) {
destroy_unit(u); remove_unit(&u->region->units, u);
} else { } else {
log_warning(("could not perform killunit::handle()\n")); log_warning(("could not perform killunit::handle()\n"));
} }
unused(data); unused(data);
return 0; return 0;
} }
static void static void

View File

@ -243,31 +243,21 @@ region_adddirection(region& r, region &rt, const char * name, const char * info)
static void static void
region_remove(region& r) region_remove(region& r)
{
remove_region(&regions, &r);
}
static void
plane_remove(int plane_id)
{ {
region ** rp = &regions; region ** rp = &regions;
while (*rp) { while (*rp) {
if (*rp==&r) { region * r = *rp;
while (r.units) { if (r->planep && r->planep->id==plane_id) {
unit * u = r.units; remove_region(rp, r);
destroy_unit(u); } else {
remove_unit(u); rp = &r->next;
}
*rp = r.next;
#ifdef FAST_CONNECT
direction_t dir;
for (dir=0;dir!=MAXDIRECTIONS;++dir) {
region * rn = r.connect[dir];
if (rn) {
direction_t reldir = reldirection(rn, &r);
r.connect[dir] = NULL;
rn->connect[reldir] = NULL;
}
}
#endif
runhash(&r);
break;
} }
rp = &(*rp)->next;
} }
} }
@ -342,6 +332,13 @@ region_setkey(region& r, const char * name, bool value)
} }
} }
static int
plane_getbyname(const char * str)
{
plane * pl = getplanebyname(str);
if (pl) return pl->id;
return 0;
}
void void
bind_region(lua_State * L) bind_region(lua_State * L)
@ -351,6 +348,9 @@ bind_region(lua_State * L)
def("get_region", &findregion), def("get_region", &findregion),
def("terraform", &region_terraform), def("terraform", &region_terraform),
def("distance", &distance), def("distance", &distance),
def("remove_region", &region_remove),
def("remove_plane", &plane_remove),
def("getplanebyname", &plane_getbyname),
class_<struct region>("region") class_<struct region>("region")
.def(tostring(self)) .def(tostring(self))
@ -369,7 +369,6 @@ bind_region(lua_State * L)
.def("get_flag", &region_getflag) .def("get_flag", &region_getflag)
.def("set_flag", &region_setflag) .def("set_flag", &region_setflag)
.def("remove", &region_remove)
.def("move", &region_move) .def("move", &region_move)
.def("get_road", &region_getroad) .def("get_road", &region_getroad)

View File

@ -335,36 +335,7 @@ game_done(void)
* wird (temporäre Hilsstrukturen) */ * wird (temporäre Hilsstrukturen) */
free_units(); free_units();
free_regions();
while (regions) {
region *r = regions;
regions = r->next;
while (r->units) {
unit * u = r->units;
r->units = u->next;
stripunit(u);
uunhash(u);
free(u);
}
while (r->buildings) {
building * b = r->buildings;
r->buildings = b->next;
free(b->name);
free(b->display);
free(b);
}
while (r->ships) {
ship * s = r->ships;
r->ships = s->next;
free(s->name);
free(s->display);
free(s);
}
free_region(r);
}
while (factions) { while (factions) {
faction * f = factions; faction * f = factions;

View File

@ -611,7 +611,7 @@
<skill name="stamina" modifier="-10"/> <skill name="stamina" modifier="-10"/>
<attack type="4" damage="1d2"/> <attack type="4" damage="1d2"/>
</race> </race>
<race name="smurf" weight="1000" capacity="540" speed="1.000000" hp="10" damage="1d2" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" giveitem="yes" giveperson="yes" giveunit="yes" getitem="yes" walk="yes"> <race name="smurf" weight="1000" capacity="540" speed="1.000000" hp="10" damage="1d2" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" giveperson="yes" giveunit="yes" getitem="yes" walk="yes">
<ai splitsize="1" learn="yes"/> <ai splitsize="1" learn="yes"/>
<skill name="alchemy" modifier="-10"/> <skill name="alchemy" modifier="-10"/>
<skill name="crossbow" modifier="-10"/> <skill name="crossbow" modifier="-10"/>
@ -653,14 +653,14 @@
<function name="name" value="namegeneric"/> <function name="name" value="namegeneric"/>
<attack type="4" damage="2d40"/> <attack type="4" damage="2d40"/>
</race> </race>
<race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="0.750000" maxaura="1.000000" regaura="2.000000" recruitcost="50000" weight="500" capacity="540" speed="1.000000" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" teach="no" desert="yes" nogive="yes"> <race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="0.750000" maxaura="1.000000" regaura="2.000000" recruitcost="50000" weight="500" capacity="540" speed="1.000000" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" teach="no" desert="yes">
<ai splitsize="50" killpeasants="yes" moverandom="yes" learn="yes"/> <ai splitsize="50" killpeasants="yes" moverandom="yes" learn="yes"/>
<function name="name" value="namegeneric"/> <function name="name" value="namegeneric"/>
<attack type="4" damage="2d4"/> <attack type="4" damage="2d4"/>
<attack type="2" damage="2d30"/> <attack type="2" damage="2d30"/>
<attack type="3" damage="1d2"/> <attack type="3" damage="1d2"/>
</race> </race>
<race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="0.750000" maxaura="1.000000" regaura="1.000000" recruitcost="5000" weight="500" capacity="540" speed="1.000000" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" teach="no" desert="yes" recruitethereal="yes" nogive="yes"> <race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="0.750000" maxaura="1.000000" regaura="1.000000" recruitcost="5000" weight="500" capacity="540" speed="1.000000" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" teach="no" desert="yes" recruitethereal="yes">
<ai splitsize="1000" killpeasants="yes" moverandom="yes" learn="yes"/> <ai splitsize="1000" killpeasants="yes" moverandom="yes" learn="yes"/>
<function name="name" value="namegeneric"/> <function name="name" value="namegeneric"/>
<attack type="4" damage="2d3"/> <attack type="4" damage="2d3"/>
@ -1029,7 +1029,7 @@
<attack type="2" damage="5d600"/> <attack type="2" damage="5d600"/>
<attack type="1" damage="1d4"/> <attack type="1" damage="1d4"/>
</race> </race>
<race name="ghast" magres="0.600000" maxaura="1.000000" regaura="1.000000" recruitcost="5" weight="1000" capacity="540" speed="1.000000" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" nogive="yes"> <race name="ghast" magres="0.600000" maxaura="1.000000" regaura="1.000000" recruitcost="5" weight="1000" capacity="540" speed="1.000000" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes">
<ai splitsize="2000" aggression="0.02" killpeasants="yes" moverandom="yes"/> <ai splitsize="2000" aggression="0.02" killpeasants="yes" moverandom="yes"/>
<function name="name" value="nameghoul"/> <function name="name" value="nameghoul"/>
<skill name="crossbow" modifier="1"/> <skill name="crossbow" modifier="1"/>
@ -1047,7 +1047,7 @@
<attack type="2" damage="1d30"/> <attack type="2" damage="1d30"/>
<attack type="2" damage="1d30"/> <attack type="2" damage="1d30"/>
</race> </race>
<race name="ghoul" magres="0.300000" maxaura="1.000000" regaura="1.000000" recruitcost="5" weight="1000" capacity="540" speed="1.000000" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" nogive="yes"> <race name="ghoul" magres="0.300000" maxaura="1.000000" regaura="1.000000" recruitcost="5" weight="1000" capacity="540" speed="1.000000" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes">
<ai splitsize="10000" killpeasants="yes" moverandom="yes"/> <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
<function name="name" value="nameghoul"/> <function name="name" value="nameghoul"/>
<function name="age" value="ageghoul"/> <function name="age" value="ageghoul"/>
@ -1065,7 +1065,7 @@
<attack type="3" damage="1d2"/> <attack type="3" damage="1d2"/>
<attack type="2" damage="1d30"/> <attack type="2" damage="1d30"/>
</race> </race>
<race name="juju-zombie" magres="0.500000" maxaura="1.000000" regaura="1.000000" recruitcost="8" weight="1000" capacity="540" speed="1.000000" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" nogive="yes"> <race name="juju-zombie" magres="0.500000" maxaura="1.000000" regaura="1.000000" recruitcost="8" weight="1000" capacity="540" speed="1.000000" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes">
<ai splitsize="2000" aggression="0.02" killpeasants="yes" moverandom="yes"/> <ai splitsize="2000" aggression="0.02" killpeasants="yes" moverandom="yes"/>
<function name="name" value="namezombie"/> <function name="name" value="namezombie"/>
<skill name="crossbow" modifier="1"/> <skill name="crossbow" modifier="1"/>
@ -1081,7 +1081,7 @@
<attack type="3" damage="1d1"/> <attack type="3" damage="1d1"/>
<attack type="3" damage="1d1"/> <attack type="3" damage="1d1"/>
</race> </race>
<race name="zombie" magres="0.200000" maxaura="1.000000" regaura="1.000000" recruitcost="4" weight="1000" capacity="540" speed="1.000000" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" nogive="yes"> <race name="zombie" magres="0.200000" maxaura="1.000000" regaura="1.000000" recruitcost="4" weight="1000" capacity="540" speed="1.000000" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes">
<ai splitsize="10000" killpeasants="yes" moverandom="yes"/> <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
<function name="name" value="namezombie"/> <function name="name" value="namezombie"/>
<function name="age" value="agezombie"/> <function name="age" value="agezombie"/>
@ -1096,7 +1096,7 @@
<skill name="unarmed" modifier="1"/> <skill name="unarmed" modifier="1"/>
<attack type="1" damage="1d7"/> <attack type="1" damage="1d7"/>
</race> </race>
<race name="skeletonlord" magres="0.300000" maxaura="1.000000" regaura="1.000000" recruitcost="2" weight="1000" capacity="540" speed="1.000000" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" nogive="yes"> <race name="skeletonlord" magres="0.300000" maxaura="1.000000" regaura="1.000000" recruitcost="2" weight="1000" capacity="540" speed="1.000000" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes">
<ai splitsize="2000" aggression="0.02" killpeasants="yes" moverandom="yes"/> <ai splitsize="2000" aggression="0.02" killpeasants="yes" moverandom="yes"/>
<function name="name" value="nameskeleton"/> <function name="name" value="nameskeleton"/>
<skill name="crossbow" modifier="1"/> <skill name="crossbow" modifier="1"/>
@ -1111,7 +1111,7 @@
<attack type="1" damage="1d7"/> <attack type="1" damage="1d7"/>
<attack type="1" damage="1d7"/> <attack type="1" damage="1d7"/>
</race> </race>
<race name="skeleton" magres="0.100000" maxaura="1.000000" regaura="1.000000" recruitcost="0" weight="500" capacity="540" speed="1.000000" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" nogive="yes"> <race name="skeleton" magres="0.100000" maxaura="1.000000" regaura="1.000000" recruitcost="0" weight="500" capacity="540" speed="1.000000" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes">
<ai splitsize="10000" killpeasants="yes" moverandom="yes"/> <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
<function name="name" value="nameskeleton"/> <function name="name" value="nameskeleton"/>
<function name="age" value="ageskeleton"/> <function name="age" value="ageskeleton"/>
@ -1154,7 +1154,7 @@
<familiar race="nymph"/> <familiar race="nymph"/>
<familiar race="imp"/> <familiar race="imp"/>
</race> </race>
<race name="shadowknight" magres="0.000000" maxaura="0.000000" regaura="0.000000" recruitcost="5" weight="1000" capacity="540" speed="1.000000" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" nogive="yes" walk="yes" canlearn="no" teach="no" noblock="yes"> <race name="shadowknight" magres="0.000000" maxaura="0.000000" regaura="0.000000" recruitcost="5" weight="1000" capacity="540" speed="1.000000" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noblock="yes">
<ai splitsize="20000" moverandom="yes"/> <ai splitsize="20000" moverandom="yes"/>
<function name="name" value="namegeneric"/> <function name="name" value="namegeneric"/>
<attack type="1" damage="1d1"/> <attack type="1" damage="1d1"/>