forked from github/server
- 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:
parent
78520fb9bf
commit
8452dc365e
17 changed files with 324 additions and 279 deletions
|
@ -230,6 +230,7 @@ select_recruitment(request ** rop, int (*quantify)(const struct race*, int), int
|
|||
static void
|
||||
add_recruits(unit * u, int number, int wanted)
|
||||
{
|
||||
region * r = u->region;
|
||||
assert(number<=wanted);
|
||||
if (number > 0) {
|
||||
unit * unew;
|
||||
|
@ -242,7 +243,7 @@ add_recruits(unit * u, int number, int wanted)
|
|||
u->hp = number * unit_max_hp(u);
|
||||
unew = u;
|
||||
} 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]) {
|
||||
|
@ -271,12 +272,12 @@ add_recruits(unit * u, int number, int wanted)
|
|||
#endif /* KARMA_MODULE */
|
||||
if (unew!=u) {
|
||||
transfermen(unew, u, unew->number);
|
||||
destroy_unit(unew);
|
||||
remove_unit(&r->units, unew);
|
||||
}
|
||||
}
|
||||
if (number < wanted) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
boolean given = false;
|
||||
if (!(u->race->ec_flags & GIVEITEM) && u2!=NULL) {
|
||||
|
|
|
@ -335,7 +335,7 @@ age_unit(region * r, unit * u)
|
|||
{
|
||||
if (u->race == new_race[RC_SPELL]) {
|
||||
if (--u->age <= 0) {
|
||||
destroy_unit(u);
|
||||
remove_unit(&r->units, u);
|
||||
}
|
||||
} else {
|
||||
++u->age;
|
||||
|
@ -343,24 +343,6 @@ age_unit(region * r, unit * 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();
|
||||
f = getfaction();
|
||||
|
||||
if (is_monsters(f)) {
|
||||
if (f==NULL || is_monsters(f)) {
|
||||
cmistake(u, ord, 66, MSG_EVENT);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2908,7 +2890,7 @@ age_building(building * b)
|
|||
* find out if there's a magician in there. */
|
||||
for (u=r->units;u;u=u->next) {
|
||||
if (b==u->building && inside_building(u)) {
|
||||
if (!(u->race->ec_flags & NOGIVE)) {
|
||||
if (!(u->race->ec_flags & GIVEITEM)==0) {
|
||||
int n, unicorns = 0;
|
||||
for (n=0; n!=u->number; ++n) {
|
||||
if (chance(0.02)) {
|
||||
|
|
|
@ -510,8 +510,9 @@ sink_ship(region * r, ship * sh, const char *name, char spy, unit * saboteur)
|
|||
msg_release(msg);
|
||||
if (dead == u->number) {
|
||||
/* the poor creature, she dies */
|
||||
*ui = u->next;
|
||||
destroy_unit(u);
|
||||
if (remove_unit(ui, u)!=0) {
|
||||
ui = &u->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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->faction!=NULL) destroy_unit(u);
|
||||
if (u->number==0) remove_unit(u);
|
||||
remove_unit(up, u);
|
||||
}
|
||||
if (*up==u) up=&u->next;
|
||||
}
|
||||
|
|
|
@ -241,7 +241,20 @@ destroyfaction(faction * f)
|
|||
|
||||
for (u=f->units;u;u=u->nextF) {
|
||||
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)) {
|
||||
const race * rc = u->race;
|
||||
int m = rmoney(u->region);
|
||||
|
|
|
@ -189,7 +189,6 @@ get_pooled(const unit * u, const resource_type * rtype, unsigned int mode, int c
|
|||
int mask;
|
||||
|
||||
if (u==v) continue;
|
||||
if (urace(v)->ec_flags & NOGIVE) continue;
|
||||
if ((urace(v)->ec_flags & GIVEITEM) == 0) continue;
|
||||
|
||||
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)) {
|
||||
for (v = r->units; use>0 && v!=NULL; v = v->next) if (u!=v) {
|
||||
int mask;
|
||||
if (urace(v)->ec_flags & NOGIVE) continue;
|
||||
if ((urace(v)->ec_flags & GIVEITEM) == 0) continue;
|
||||
|
||||
if (v->faction == f) {
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/* Economic flags */
|
||||
#define NOGIVE (1<<0) /* gibt niemals nix */
|
||||
#define GIVEITEM (1<<1) /* gibt Gegenstände weg */
|
||||
#define GIVEPERSON (1<<2) /* übergibt Personen */
|
||||
#define GIVEUNIT (1<<3) /* Einheiten an andere Partei übergeben */
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "region.h"
|
||||
#include "resources.h"
|
||||
#include "save.h"
|
||||
#include "ship.h"
|
||||
#include "terrain.h"
|
||||
#include "terrainid.h"
|
||||
#include "unit.h"
|
||||
|
@ -859,6 +860,26 @@ new_region(short x, short y, unsigned int uid)
|
|||
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
|
||||
freeland(land_region * lr)
|
||||
{
|
||||
|
@ -874,7 +895,6 @@ freeland(land_region * lr)
|
|||
void
|
||||
free_region(region * r)
|
||||
{
|
||||
runhash(r);
|
||||
if (last == r) last = NULL;
|
||||
free(r->display);
|
||||
if (r->land) freeland(r->land);
|
||||
|
@ -904,9 +924,49 @@ free_region(region * r)
|
|||
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);
|
||||
}
|
||||
|
||||
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
|
||||
* TODO: Make this XML-configurable and allow non-ascii characters again.
|
||||
*/
|
||||
|
|
|
@ -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 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_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 void free_regions(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -155,47 +155,99 @@ dfindhash(int no)
|
|||
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
|
||||
* this happens when units die and no own units are in the region
|
||||
*/
|
||||
void
|
||||
distribute_items(unit * u)
|
||||
static friend *
|
||||
get_friends(const unit * u, int * numfriends)
|
||||
{
|
||||
friend * friends = 0;
|
||||
faction * f = u->faction;
|
||||
region * r = u->region;
|
||||
unit * au;
|
||||
int number = 0;
|
||||
struct friend {
|
||||
struct friend * next;
|
||||
int number;
|
||||
faction * faction;
|
||||
unit * unit;
|
||||
} * friends = NULL;
|
||||
unit * u2;
|
||||
|
||||
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) {
|
||||
if (alliedunit(u, au->faction, HELP_MONEY) && alliedunit(au, f, HELP_GIVE)) {
|
||||
struct friend * nf, ** fr = &friends;
|
||||
|
||||
while (*fr && (*fr)->faction->no<au->faction->no) fr = &(*fr)->next;
|
||||
nf = *fr;
|
||||
if (nf==NULL || nf->faction!=au->faction) {
|
||||
nf = malloc(sizeof(struct friend));
|
||||
nf->next = *fr;
|
||||
nf->faction = au->faction;
|
||||
nf->unit = au;
|
||||
nf->number = 0;
|
||||
*fr = nf;
|
||||
/* some units won't take stuff: */
|
||||
if (u2->race->ec_flags & GETITEM) {
|
||||
while (*fr && (*fr)->faction->no<u2->faction->no) fr = &(*fr)->next;
|
||||
nf = *fr;
|
||||
if (nf==NULL || nf->faction!=u2->faction) {
|
||||
nf = malloc(sizeof(friend));
|
||||
nf->next = *fr;
|
||||
nf->faction = u2->faction;
|
||||
nf->unit = u2;
|
||||
nf->number = 0;
|
||||
*fr = nf;
|
||||
} else if (nf->faction==u2->faction && (u2->race->ec_flags & GIVEITEM)) {
|
||||
/* 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) {
|
||||
struct friend * nf = friends;
|
||||
unit * u2 = nf->unit;
|
||||
|
@ -215,116 +267,85 @@ distribute_items(unit * u)
|
|||
friends = nf->next;
|
||||
free(nf);
|
||||
}
|
||||
friends = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (u->items==NULL) return 0;
|
||||
}
|
||||
|
||||
/* Wir machen das erst nach dem Löschen der Items. Der Klon darf keine
|
||||
* Items haben, sonst Memory-Leak. */
|
||||
#if 0
|
||||
/* broken. */
|
||||
clone = has_clone(u);
|
||||
if (clone && rng_int()%100 < 90) {
|
||||
attrib *a;
|
||||
int i;
|
||||
/* last, but not least, give money and horses to peasants */
|
||||
while (*itm_p) {
|
||||
item * itm = *itm_p;
|
||||
|
||||
/* TODO: Messages generieren. */
|
||||
if (u->region!=clone->region) {
|
||||
move_unit(u, clone->region, NULL);
|
||||
if (flags & GIFT_PEASANTS) {
|
||||
if (!fval(u->region->terrain, SEA_REGION)) {
|
||||
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)) {
|
||||
u->ship = clone->ship;
|
||||
}
|
||||
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];
|
||||
if (itm->number>0 && (itm->type->flags & ITF_NOTLOST)) {
|
||||
itm_p = &itm->next;
|
||||
retval = -1;
|
||||
} else {
|
||||
if (u->number) set_number(u, 0);
|
||||
handle_event(u->attribs, "destroy", u);
|
||||
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);
|
||||
i_remove(itm_p, itm);
|
||||
i_free(itm);
|
||||
}
|
||||
}
|
||||
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 *
|
||||
|
@ -588,10 +609,10 @@ ucontact(const unit * u, const unit * u2)
|
|||
void
|
||||
free_units(void)
|
||||
{
|
||||
while (udestroy) {
|
||||
unit * u = udestroy;
|
||||
udestroy = udestroy->next;
|
||||
stripunit(u);
|
||||
while (deleted_units) {
|
||||
unit * u = deleted_units;
|
||||
deleted_units = deleted_units->next;
|
||||
free_unit(u);
|
||||
free(u);
|
||||
}
|
||||
}
|
||||
|
@ -1294,14 +1315,19 @@ invisible(const unit *target, const unit * viewer)
|
|||
#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
|
||||
stripunit(unit * u)
|
||||
free_unit(unit * u)
|
||||
{
|
||||
free(u->name);
|
||||
free(u->display);
|
||||
free_order(u->thisorder);
|
||||
free_orders(&u->orders);
|
||||
if(u->skills) free(u->skills);
|
||||
if (u->skills) free(u->skills);
|
||||
while (u->items) {
|
||||
item * it = u->items->next;
|
||||
u->items->next = NULL;
|
||||
|
|
|
@ -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);
|
||||
|
||||
extern struct unit * udestroy;
|
||||
extern const char * u_description(const unit * u, const struct locale * lang);
|
||||
extern struct skill * add_skill(struct unit * u, skill_t id);
|
||||
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 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. */
|
||||
extern void destroy_unit(struct unit * u);
|
||||
extern void remove_unit(struct unit * u);
|
||||
extern void distribute_items(struct unit * u);
|
||||
#define GIFT_SELF 1<<0
|
||||
#define GIFT_FRIENDS 1<<1
|
||||
#define GIFT_PEASANTS 1<<2
|
||||
int gift_items(struct unit * u, int flags);
|
||||
void make_zombie(unit * u);
|
||||
|
||||
/* see resolve.h */
|
||||
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 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 struct unit * create_unit(struct region * r1, struct faction * f, int number, const struct race * rc, int id, const char * dname, struct unit *creator);
|
||||
|
|
|
@ -1489,7 +1489,6 @@ parse_races(xmlDocPtr doc)
|
|||
if (xml_bvalue(node, "undead", false)) rc->flags |= RCF_UNDEAD;
|
||||
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, "giveperson", false)) rc->ec_flags |= GIVEPERSON;
|
||||
if (xml_bvalue(node, "giveunit", false)) rc->ec_flags |= GIVEUNIT;
|
||||
|
|
|
@ -142,41 +142,39 @@ sp_summon_alp(struct castorder *co)
|
|||
void
|
||||
alp_findet_opfer(unit *alp, region *r)
|
||||
{
|
||||
curse * c;
|
||||
attrib * a = a_find(alp->attribs, &at_alp);
|
||||
alp_data * ad = (alp_data*)a->data.v;
|
||||
unit *mage = ad->mage;
|
||||
unit *opfer = ad->target;
|
||||
curse * c;
|
||||
attrib * a = a_find(alp->attribs, &at_alp);
|
||||
alp_data * ad = (alp_data*)a->data.v;
|
||||
unit *mage = ad->mage;
|
||||
unit *opfer = ad->target;
|
||||
variant effect;
|
||||
message * msg;
|
||||
|
||||
assert(opfer);
|
||||
assert(mage);
|
||||
assert(opfer);
|
||||
assert(mage);
|
||||
|
||||
/* Magier und Opfer Bescheid geben */
|
||||
/* Magier und Opfer Bescheid geben */
|
||||
msg = msg_message("alp_success", "target", opfer);
|
||||
add_message(&mage->faction->msgs, msg);
|
||||
r_addmessage(opfer->region, opfer->faction, msg);
|
||||
msg_release(msg);
|
||||
|
||||
/* Relations werden in destroy_unit(alp) automatisch gelöscht.
|
||||
* Die Aktionen, die beim Tod des Alps ausgelöst werden sollen,
|
||||
* müssen jetzt aber deaktiviert werden, sonst werden sie gleich
|
||||
* beim destroy_unit(alp) ausgelöst.
|
||||
*/
|
||||
a_removeall(&alp->attribs, &at_eventhandler);
|
||||
/* Relations werden in destroy_unit(alp) automatisch gelöscht.
|
||||
* Die Aktionen, die beim Tod des Alps ausgelöst werden sollen,
|
||||
* müssen jetzt aber deaktiviert werden, sonst werden sie gleich
|
||||
* beim destroy_unit(alp) ausgelöst.
|
||||
*/
|
||||
a_removeall(&alp->attribs, &at_eventhandler);
|
||||
|
||||
/* Alp umwandeln in Curse */
|
||||
effect.i = -2;
|
||||
c = create_curse(mage, &opfer->attribs, ct_find("worse"), 2, 2, effect, opfer->number);
|
||||
/* solange es noch keine spezielle alp-Antimagie gibt, reagiert der
|
||||
* auch auf normale */
|
||||
destroy_unit(alp);
|
||||
c = create_curse(mage, &opfer->attribs, ct_find("worse"), 2, 2, effect, opfer->number);
|
||||
/* solange es noch keine spezielle alp-Antimagie gibt, reagiert der
|
||||
* auch auf normale */
|
||||
remove_unit(&r->units, alp);
|
||||
|
||||
{
|
||||
/* wenn der Magier stirbt, wird der Curse wieder vom Opfer genommen */
|
||||
add_trigger(&mage->attribs, "destroy", trigger_removecurse(c, opfer));
|
||||
}
|
||||
/* wenn der Magier stirbt, wird der Curse wieder vom Opfer genommen */
|
||||
add_trigger(&mage->attribs, "destroy", trigger_removecurse(c, opfer));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <kernel/eressea.h>
|
||||
#include "killunit.h"
|
||||
|
||||
#include <kernel/region.h>
|
||||
#include <kernel/unit.h>
|
||||
|
||||
/* util includes */
|
||||
|
@ -34,17 +35,17 @@
|
|||
static int
|
||||
killunit_handle(trigger * t, void * data)
|
||||
{
|
||||
/* call an event handler on killunit.
|
||||
* data.v -> ( variant event, int timer )
|
||||
*/
|
||||
unit * u = (unit*)t->data.v;
|
||||
if (u!=NULL) {
|
||||
destroy_unit(u);
|
||||
/* call an event handler on killunit.
|
||||
* data.v -> ( variant event, int timer )
|
||||
*/
|
||||
unit * u = (unit*)t->data.v;
|
||||
if (u!=NULL) {
|
||||
remove_unit(&u->region->units, u);
|
||||
} else {
|
||||
log_warning(("could not perform killunit::handle()\n"));
|
||||
log_warning(("could not perform killunit::handle()\n"));
|
||||
}
|
||||
unused(data);
|
||||
return 0;
|
||||
unused(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -243,31 +243,21 @@ region_adddirection(region& r, region &rt, const char * name, const char * info)
|
|||
|
||||
static void
|
||||
region_remove(region& r)
|
||||
{
|
||||
remove_region(®ions, &r);
|
||||
}
|
||||
|
||||
static void
|
||||
plane_remove(int plane_id)
|
||||
{
|
||||
region ** rp = ®ions;
|
||||
while (*rp) {
|
||||
if (*rp==&r) {
|
||||
while (r.units) {
|
||||
unit * u = r.units;
|
||||
destroy_unit(u);
|
||||
remove_unit(u);
|
||||
}
|
||||
*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;
|
||||
region * r = *rp;
|
||||
if (r->planep && r->planep->id==plane_id) {
|
||||
remove_region(rp, r);
|
||||
} else {
|
||||
rp = &r->next;
|
||||
}
|
||||
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
|
||||
bind_region(lua_State * L)
|
||||
|
@ -351,6 +348,9 @@ bind_region(lua_State * L)
|
|||
def("get_region", &findregion),
|
||||
def("terraform", ®ion_terraform),
|
||||
def("distance", &distance),
|
||||
def("remove_region", ®ion_remove),
|
||||
def("remove_plane", &plane_remove),
|
||||
def("getplanebyname", &plane_getbyname),
|
||||
|
||||
class_<struct region>("region")
|
||||
.def(tostring(self))
|
||||
|
@ -369,7 +369,6 @@ bind_region(lua_State * L)
|
|||
.def("get_flag", ®ion_getflag)
|
||||
.def("set_flag", ®ion_setflag)
|
||||
|
||||
.def("remove", ®ion_remove)
|
||||
.def("move", ®ion_move)
|
||||
|
||||
.def("get_road", ®ion_getroad)
|
||||
|
|
|
@ -335,36 +335,7 @@ game_done(void)
|
|||
* wird (temporäre Hilsstrukturen) */
|
||||
|
||||
free_units();
|
||||
|
||||
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);
|
||||
}
|
||||
free_regions();
|
||||
|
||||
while (factions) {
|
||||
faction * f = factions;
|
||||
|
|
|
@ -611,7 +611,7 @@
|
|||
<skill name="stamina" modifier="-10"/>
|
||||
<attack type="4" damage="1d2"/>
|
||||
</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"/>
|
||||
<skill name="alchemy" modifier="-10"/>
|
||||
<skill name="crossbow" modifier="-10"/>
|
||||
|
@ -653,14 +653,14 @@
|
|||
<function name="name" value="namegeneric"/>
|
||||
<attack type="4" damage="2d40"/>
|
||||
</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"/>
|
||||
<function name="name" value="namegeneric"/>
|
||||
<attack type="4" damage="2d4"/>
|
||||
<attack type="2" damage="2d30"/>
|
||||
<attack type="3" damage="1d2"/>
|
||||
</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"/>
|
||||
<function name="name" value="namegeneric"/>
|
||||
<attack type="4" damage="2d3"/>
|
||||
|
@ -1029,7 +1029,7 @@
|
|||
<attack type="2" damage="5d600"/>
|
||||
<attack type="1" damage="1d4"/>
|
||||
</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"/>
|
||||
<function name="name" value="nameghoul"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
|
@ -1047,7 +1047,7 @@
|
|||
<attack type="2" damage="1d30"/>
|
||||
<attack type="2" damage="1d30"/>
|
||||
</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"/>
|
||||
<function name="name" value="nameghoul"/>
|
||||
<function name="age" value="ageghoul"/>
|
||||
|
@ -1065,7 +1065,7 @@
|
|||
<attack type="3" damage="1d2"/>
|
||||
<attack type="2" damage="1d30"/>
|
||||
</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"/>
|
||||
<function name="name" value="namezombie"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
|
@ -1081,7 +1081,7 @@
|
|||
<attack type="3" damage="1d1"/>
|
||||
<attack type="3" damage="1d1"/>
|
||||
</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"/>
|
||||
<function name="name" value="namezombie"/>
|
||||
<function name="age" value="agezombie"/>
|
||||
|
@ -1096,7 +1096,7 @@
|
|||
<skill name="unarmed" modifier="1"/>
|
||||
<attack type="1" damage="1d7"/>
|
||||
</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"/>
|
||||
<function name="name" value="nameskeleton"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
|
@ -1111,7 +1111,7 @@
|
|||
<attack type="1" damage="1d7"/>
|
||||
<attack type="1" damage="1d7"/>
|
||||
</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"/>
|
||||
<function name="name" value="nameskeleton"/>
|
||||
<function name="age" value="ageskeleton"/>
|
||||
|
@ -1154,7 +1154,7 @@
|
|||
<familiar race="nymph"/>
|
||||
<familiar race="imp"/>
|
||||
</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"/>
|
||||
<function name="name" value="namegeneric"/>
|
||||
<attack type="1" damage="1d1"/>
|
||||
|
|
Loading…
Reference in a new issue