Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: CF: Wizard Crashes
- To: crossfire (at) ifi.uio.no
- Subject: Re: CF: Wizard Crashes
- From: Jan Echternach <>
- Date: Fri, 26 May 2000 14:44:28 +0200
- In-Reply-To: <>; from on Fri, May 26, 2000 at 12:24:23PM +0200
- Mail-Followup-To:
- References: <> <>
- Reply-To: Jan Echternach <>
- Sender:
On Fri, May 26, 2000 at 12:24:23PM +0200, Jan Echternach wrote:
> Thanks for the server logs. This is fixed by the attached patch. The
> patch is already applied to the CVS tree.
The patch triggered other bugs in that area: Two functions called
add_friendly_object() without setting FLAG_FRIENDLY. I fixed these
bugs and some more that I have found while trying to crash the server
on /Lake_Country/Mwizard/Mwizard6 and /Lake_Country/Mwizard/Mwizard6
maps (however, the server didn't crash - I can't reproduce the wizard
problems).
I have also added handling of magic missiles to move_apply(). That
should get rid of many debugging messages.
From the CHANGES file:
* server/attack.c: hit_map(), hit_player(); server/spell_effect.c:
move_cone(); server/rune.c: spring_trap(); server/spell_util.c:
move_missile(): Bugfix: Added missing was_destroyed() calls.
* server/rune.c: spring_trap(): Bugfix: Call trap_show() before the rune
has a chance to be destroyed.
* server/attack.c: hit_map(), hit_player(): Check for freed objects
right at the beginning of the function. Removed check that hitter has
a name from hit_player().
* server/spell_util.c: move_cone(): Bugfix: Remove cone objects in
inventories from active list, this fixes the cone without map problem when
a flower was hit with ice and put into an icecube.
* server/spell_util.c: move_missile(): Bugfix: Don't call hit_map() while
missile is removed from the map.
* server/apply.c: manual_apply(): Handle MMISSILE.
--
Jan
diff -ru orig/crossfire-0.95.5-cvs2-patch14/server/spell_effect.c crossfire-0.95.5-cvs2/server/spell_effect.c
--- orig/crossfire-0.95.5-cvs2-patch14/server/spell_effect.c Fri May 26 11:26:52 2000
+++ crossfire-0.95.5-cvs2/server/spell_effect.c Fri May 26 12:53:26 2000
@@ -3043,6 +3043,7 @@
/* if animated by a player, give the player control of the golem */
if(op->type==PLAYER) {
CLEAR_FLAG(tmp, FLAG_MONSTER);
+ SET_FLAG(tmp, FLAG_FRIENDLY);
tmp->stats.exp=0;
add_friendly_object(tmp);
tmp->type=GOLEM;
diff -ru orig/crossfire-0.95.5-cvs2-patch14/server/spell_util.c crossfire-0.95.5-cvs2/server/spell_util.c
--- orig/crossfire-0.95.5-cvs2-patch14/server/spell_util.c Fri May 26 11:26:52 2000
+++ crossfire-0.95.5-cvs2/server/spell_util.c Fri May 26 12:50:03 2000
@@ -822,6 +822,7 @@
tmp=arch_to_object(at);
if(op->type==PLAYER) {
CLEAR_FLAG(tmp, FLAG_MONSTER);
+ SET_FLAG(tmp, FLAG_FRIENDLY);
tmp->stats.exp=0;
add_friendly_object(tmp);
tmp->type=GOLEM;
diff -ru orig/crossfire-0.95.5-cvs2-patch15/server/attack.c crossfire-0.95.5-cvs2/server/attack.c
--- orig/crossfire-0.95.5-cvs2-patch15/server/attack.c Fri May 26 12:54:04 2000
+++ crossfire-0.95.5-cvs2/server/attack.c Fri May 26 13:16:46 2000
@@ -169,9 +169,17 @@
int hit_map(object *op,int dir,int type) {
object *tmp,*next=NULL;
int retflag=0; /* added this flag.. will return 1 if it hits a monster */
+ tag_t tag;
+
+ if (QUERY_FLAG (op, FLAG_FREED)) {
+ LOG (llevError, "BUG: hit_map(): free object\n");
+ return 0;
+ }
if (op->head) op=op->head;
+ tag = op->count;
+
if (!op->map) {
LOG(llevDebug,"hit_map called, but %s has no map", op->name);
return 0;
@@ -214,6 +222,8 @@
else if(QUERY_FLAG(tmp,FLAG_ALIVE)) {
hit_player(tmp,op->stats.dam,op,type);
retflag |=1;
+ if (was_destroyed (op, tag))
+ break;
} /* It is possible the object has been relocated to know longer be
* on the map (ie, in an icecube.) If we no longer have a map,
* just ignore.
@@ -697,6 +707,13 @@
char buf[MAX_BUF];
object *old_hitter=NULL; /* this is used in case of servant monsters */
int maxdam=0,ndam,attacktype=1,attacknum,magic=(type & AT_MAGIC);
+ tag_t hitter_tag;
+
+ if (QUERY_FLAG (op, FLAG_FREED) || QUERY_FLAG (hitter, FLAG_FREED)) {
+ LOG (llevError, "BUG: hit_player(): freed object\n");
+ return 0;
+ }
+ hitter_tag = hitter->count;
if(op->head!=NULL) {
if(op->head==op) {
@@ -727,18 +744,15 @@
op=op->head;
}
- if(op->type==DOOR && op->inv && op->inv->type==RUNE)
+ if(op->type==DOOR && op->inv && op->inv->type==RUNE) {
spring_trap(op->inv,hitter);
+ if (was_destroyed (hitter, hitter_tag))
+ return 0;
+ }
/* If its already dead, or we're the wizard, don't attack it - no point */
if(QUERY_FLAG(op,FLAG_WIZ)||!QUERY_FLAG(op,FLAG_ALIVE)||op->stats.hp<0)
return 0;
-
- /* If its already dead, or we're the wizard, don't attack it - no point */
- if(hitter->name==NULL) {
- LOG(llevDebug, "hit_player: hitter has no name\n");
- return 0;
- }
#ifdef ATTACK_DEBUG
LOG(llevDebug,"hit player: attacktype %d, dam %d\n", type, dam);
diff -ru orig/crossfire-0.95.5-cvs2-patch15/server/spell_util.c crossfire-0.95.5-cvs2/server/spell_util.c
--- orig/crossfire-0.95.5-cvs2-patch15/server/spell_util.c Fri May 26 13:35:24 2000
+++ crossfire-0.95.5-cvs2/server/spell_util.c Fri May 26 13:30:57 2000
@@ -1094,6 +1094,14 @@
void move_cone(object *op) {
int i;
+ tag_t tag;
+
+ if (op->env) {
+ /* handle flowers in icecubes */
+ op->speed = 0;
+ update_ob_speed (op);
+ return;
+ }
/* if no map then hit_map will crash so just ignore object */
if (! op->map) {
@@ -1118,7 +1126,10 @@
/* Hit map returns 1 if it hits a monster. If it does, set
* food to 1, which will stop the cone from progressing.
*/
+ tag = op->count;
op->stats.food |= hit_map(op,0,op->attacktype);
+ if (was_destroyed (op, tag))
+ return;
if((op->stats.hp-=2)<0) {
if(op->stats.exp) {
diff -ru orig/crossfire-0.95.5-cvs2-patch16/server/apply.c crossfire-0.95.5-cvs2/server/apply.c
--- orig/crossfire-0.95.5-cvs2-patch16/server/apply.c Fri May 26 11:26:51 2000
+++ crossfire-0.95.5-cvs2/server/apply.c Fri May 26 14:07:11 2000
@@ -1093,6 +1093,17 @@
apply_altar (trap, victim, originator);
return;
+ case MMISSILE:
+ if (QUERY_FLAG (victim, FLAG_ALIVE)) {
+ tag_t trap_tag = trap->count;
+ hit_player (victim, trap->stats.dam, trap, AT_MAGIC);
+ if ( ! was_destroyed (trap, trap_tag)) {
+ remove_ob (trap);
+ free_object (trap);
+ }
+ }
+ return;
+
case ARROW:
if(QUERY_FLAG(victim, FLAG_ALIVE)&&trap->speed) {
tag_t trap_tag = trap->count;
diff -ru orig/crossfire-0.95.5-cvs2-patch16/server/rune.c crossfire-0.95.5-cvs2/server/rune.c
--- orig/crossfire-0.95.5-cvs2-patch16/server/rune.c Fri May 26 11:26:52 2000
+++ crossfire-0.95.5-cvs2/server/rune.c Fri May 26 13:54:12 2000
@@ -185,9 +185,10 @@
void rune_attack(object *op,object *victim)
{
if(victim) {
+ tag_t tag = victim->count;
hit_player(victim,op->stats.dam,op,op->attacktype);
- if (QUERY_FLAG (victim, FLAG_FREED))
- return;
+ if (was_destroyed (victim, tag))
+ return;
/* if there's a disease in the needle, put it in the player */
if(op->randomitems!=NULL) create_treasure(op->randomitems,op,GT_INVENTORY,
(victim->map?victim->map->difficulty:1),0);
@@ -207,22 +208,35 @@
void spring_trap(object *trap,object *victim)
{ int spell_in_rune;
object *env;
+ tag_t trap_tag = trap->count;
+
trap->stats.hp--; /*decrement detcount */
/* get the spell number from the name in the slaying field, and set
that as the spell to be cast. */
if((spell_in_rune=look_up_spell_by_name(NULL,trap->slaying))!=-1) trap->stats.sp=spell_in_rune;
if(victim) if(victim->type==PLAYER) new_draw_info(NDI_UNIQUE, 0,victim,trap->msg);
- if(!trap->stats.sp) rune_attack(trap,victim);
- else { /* This is necessary if the trap is inside something else */
+ /* Flash an image of the trap on the map so the poor sod
+ * knows what hit him. */
+ for (env = trap; env->env != NULL; env = env->env)
+ ;
+ trap_show(trap,env);
+
+ if ( ! trap->stats.sp)
+ {
+ rune_attack(trap,victim);
+ if (was_destroyed (trap, trap_tag))
+ return;
+ }
+ else
+ {
+ /* This is necessary if the trap is inside something else */
remove_ob(trap);
trap->x=victim->x;trap->y=victim->y;
insert_ob_in_map(trap,victim->map,trap);
+ if (was_destroyed (trap, trap_tag))
+ return;
cast_spell(trap,trap,trap->direction,trap->stats.sp,1,spellNormal,NULL);
}
- /* Flash an image of the trap on the map so the poor sod
- * knows what hit him. */
- for(env=trap;env!=NULL&&env->env!=NULL;env=env->env);
- trap_show(trap,env);
if(!trap->stats.hp) {
trap->type=98; /* make the trap impotent */
diff -ru orig/crossfire-0.95.5-cvs2-patch16/server/spell_util.c crossfire-0.95.5-cvs2/server/spell_util.c
--- orig/crossfire-0.95.5-cvs2-patch16/server/spell_util.c Fri May 26 14:18:33 2000
+++ crossfire-0.95.5-cvs2/server/spell_util.c Fri May 26 14:07:44 2000
@@ -1403,25 +1403,37 @@
void move_missile(object *op) {
int i;
object *owner;
+ sint16 new_x, new_y;
- remove_ob(op);
owner = get_owner(op);
- if (owner == (object *) NULL) {
+ if (owner == NULL) {
+ remove_ob(op);
free_object(op);
return;
}
- op->x+=DIRX(op),op->y+=DIRY(op);
- if(!op->direction||wall(op->map,op->x,op->y)||
- blocks_view(op->map,op->x,op->y)) {
- free_object(op);
+ new_x = op->x + DIRX(op);
+ new_y = op->y + DIRY(op);
+
+ if (blocked (op->map, new_x, new_y)) {
+ tag_t tag = op->count;
+ hit_map (op, op->direction, AT_MAGIC);
+ if ( ! was_destroyed (op, tag)) {
+ remove_ob (op);
+ free_object(op);
+ }
return;
}
- if(blocked(op->map,op->x,op->y)) {
- hit_map(op,0,AT_MAGIC);
+
+ remove_ob(op);
+ if ( ! op->direction || wall (op->map, new_x, new_y)
+ || blocks_view (op->map, new_x, new_y))
+ {
free_object(op);
return;
}
+ op->x = new_x;
+ op->y = new_y;
i=find_dir(op->map,op->x,op->y,get_owner(op));
if(i&&i!=op->direction){
op->direction=absdir(op->direction+((op->direction-i+8)%8<4?-1:1));