Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CF: Misc. crash fixes



These patches are already in the CVS tree.  They fix some more crashes
I've seen on the MwizardG map.  From the CHANGES file:

common/button.c: do_mood_floor():  Bugfixes: Only players can have pets.
Call add_friendly_object() for friendly monsters.

server/spell_effect.c and server/spell_util.c: Several functions:  Only
add a pet if there really is a pet's owner, and it's a player.

server/spell_effect.c: cast_charm() and cast_charm_undead():  Bugfixes:
Only players can cast these spells.  This fixes server crash if
a monster casted a charm spell, and the charmed pet was killed.
Call add_friendly_object for friendly monsters.

common/friend.c: remove_friendly_object():  Use llevError for error
messages.  

common/living.c: fix_player(); server/gods.c: tailor_god_spell();
server/spell_effect.c: summon_avatar() and animate_weapon(): Bugfix: Set
a string to NULL after calling free_string().  This fixes a nasty bug
that caused the string's reference count drop below 0, which resulted
in corruption of malloc()'s internal data structures (and possibly
server crashes).  

server/time.c: move_creator():  Bugfix: Call free_string() to free old
values of op->name and op->title before overwriting them with new values.

common/object.c: insert_ob_in_map_simple() and insert_ob_in_map():
Check that we don't insert freed objects.  

server/attack.c: hit_player_attacktype() and hit_player():  Bugfix: Check
that find_god() really found a god, and that 'god->slaying' is not NULL.
Fixes crash if a monster casted turn undead and actually hit something.

server/attack.c: hit_player():  Check that a pet's owner is a player.
Prevents server crashes if a monster has a pet monster due to a bug
somewhere.  Use llevError for error message.  

server/time.c: move_arrow():  Use llevDebug level for "Arrow had no
map" message.  

server/c_object.c, server/spell_effect.c, server/spell_util.c:  Bugfixes:
Added some missing checks for destroyed objects.  Use was_destroyed()
or return value of insert_ob_in_map() to check for destroyed objects,
not FLAG_FREED or FLAG_REMOVED.  Don't use op->count of destroyed objects.

server/shop.c: get_payment2():  Type of tag is 'tag_t', not 'long'.

server/spell_effect.c: animate_bomb():  Fix environment checks.

server/spell_util.c: fire_bolt():  Bugfix: Set level of bolt.

server/spell_util.c: explosion():  Bugfix: Set FLAG_NO_APPLY before
moving the exploding object to the top.  

server/spell_util.c: put_a_monster():  First create the monster
completely, then just insert its head.  

server/time.c: generate_monster():  Bugfix: Don't free generators that
are used up in this function.  process_object() already does this.
This fixes steambolt (which is a generator but must not used up here -
generate_monster() wasn't looking at FLAG_IS_USED_UP) and all generators
which should really be used up (because process_object() didn't expect
generate_monster() to destroy the object).  

-- 
Jan
diff -ru orig/crossfire-0.95.5-cvs3-patch20/server/c_object.c crossfire-0.95.5-cvs3/server/c_object.c
--- orig/crossfire-0.95.5-cvs3-patch20/server/c_object.c	Fri May 26 11:50:49 2000
+++ crossfire-0.95.5-cvs3/server/c_object.c	Thu Jun  8 03:15:48 2000
@@ -322,6 +322,7 @@
 
     if(nrof != tmp->nrof && !(nrof == 1 && tmp->nrof == 0)) {
 	object *tmp2 = tmp;
+        tag_t tmp2_tag = tmp2->count;
 	tmp = get_split_ob (tmp, nrof);
 	if(!tmp) {
 	    new_draw_info(NDI_UNIQUE, 0,pl, errmsg);
@@ -329,8 +330,8 @@
 	}
 	/* Tell a client what happened rest of objects */
 	if (pl->type == PLAYER) {
-	    if (QUERY_FLAG(tmp2, FLAG_REMOVED))
-		esrv_del_item (pl->contr, tmp2->count);
+            if (was_destroyed (tmp2, tmp2_tag))
+		esrv_del_item (pl->contr, tmp2_tag);
 	    else
 		esrv_send_item (pl, tmp2);
 	}
@@ -483,6 +484,7 @@
  */
 void put_object_in_sack (object *op, object *sack, object *tmp, long nrof) 
 {
+    tag_t tmp_tag, tmp2_tag;
     object *tmp2, *sack2;
     char buf[MAX_BUF];
 
@@ -536,6 +538,7 @@
     /* we want to put some portion of the item into the container */
     if (nrof && tmp->nrof != nrof) {
 	object *tmp2 = tmp;
+        tmp2_tag = tmp2->count;
 	tmp = get_split_ob (tmp, nrof);
 
 	if(!tmp) {
@@ -543,8 +546,8 @@
 	    return;
 	}
 	/* Tell a client what happened other objects */ 
-	if (QUERY_FLAG(tmp2, FLAG_FREED))
-	      esrv_del_item (op->contr, tmp2->count);
+	if (was_destroyed (tmp2, tmp2_tag))
+	      esrv_del_item (op->contr, tmp2_tag);
 	else	/* this can proably be replaced with an update */
 	      esrv_send_item (op, tmp2);
     } else
@@ -553,6 +556,7 @@
     sprintf(buf, "You put %s in ", query_name(tmp));
     strcat (buf, query_name(sack));
     strcat (buf, ".");
+    tmp_tag = tmp->count;
     tmp2 = insert_ob_in_ob(tmp, sack);
     new_draw_info(NDI_UNIQUE, 0,op,buf);
     fix_player(op); /* This is overkill, fix_player() is called somewhere */ 
@@ -562,7 +566,7 @@
      * delete the original.
      */
     if (tmp2 != tmp) 
-	esrv_del_item (op->contr, tmp->count);
+	esrv_del_item (op->contr, tmp_tag);
 	    
     esrv_send_item (op, tmp2);
     /* update the sacks and players weight */
@@ -604,6 +608,7 @@
      */
     if(nrof && tmp->nrof != nrof) {
 	object *tmp2 = tmp;
+        tag_t tmp2_tag = tmp2->count;
 	tmp = get_split_ob (tmp, nrof);
 	if(!tmp) {
 	    new_draw_info(NDI_UNIQUE, 0,op, errmsg);
@@ -612,8 +617,8 @@
 	/* Tell a client what happened rest of objects.  tmp2 is now the
 	 * original object
 	 */ 
-	if (QUERY_FLAG(tmp2, FLAG_FREED))
-	      esrv_del_item (op->contr, tmp2->count);
+	if (was_destroyed (tmp2, tmp2_tag))
+	      esrv_del_item (op->contr, tmp2_tag);
 	else
 	      esrv_send_item (op, tmp2);
     } else
diff -ru orig/crossfire-0.95.5-cvs3-patch20/server/shop.c crossfire-0.95.5-cvs3/server/shop.c
--- orig/crossfire-0.95.5-cvs3-patch20/server/shop.c	Fri Sep 17 21:11:24 1999
+++ crossfire-0.95.5-cvs3/server/shop.c	Thu Jun  8 03:17:23 2000
@@ -467,7 +467,7 @@
             return 0;
         } else {
 	    object *tmp;
-	    long c = op->count;
+	    tag_t c = op->count;
 
 	    CLEAR_FLAG(op, FLAG_UNPAID);
 	    new_draw_info_format(NDI_UNIQUE, 0, op,
diff -ru orig/crossfire-0.95.5-cvs3-patch20/server/spell_effect.c crossfire-0.95.5-cvs3/server/spell_effect.c
--- orig/crossfire-0.95.5-cvs3-patch20/server/spell_effect.c	Tue Jun  6 17:03:07 2000
+++ crossfire-0.95.5-cvs3/server/spell_effect.c	Thu Jun  8 11:52:41 2000
@@ -294,14 +294,8 @@
 
     /* Put the new creature on the map */
     op->x = x; op->y = y;
-    insert_ob_in_map(op,map,owner);
-
-    /* It is possible that there is something on the map that kills
-     * the object when inserted.  Unlikely, but worth checking. */
-    if (QUERY_FLAG(op, FLAG_FREED)) return;
-
-    /*update_object(op);*/ /*I believe insert_ob_in_map already does this */
-
+    if ((op = insert_ob_in_map (op, map, owner)) == NULL)
+        return;
 
     if(op->randomitems != NULL)
 	create_treasure(op->randomitems,op,GT_INVISIBLE,map->difficulty,0);
@@ -872,9 +866,7 @@
     return 0;
   }
   tmp->x=op->x+freearr_x[dir],tmp->y=op->y+freearr_y[dir];
-  insert_ob_in_map(tmp,op->map,op);
-
-  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
+  if ((tmp = insert_ob_in_map (tmp, op->map, op)) == NULL) {
     new_draw_info(NDI_UNIQUE, 0,op,"Something destroys your wall");
     return 0;
   }
@@ -1003,8 +995,8 @@
 
 	    remove_ob(op);
 	    op->x=x,op->y=y;
-	    insert_ob_in_map(op,op->map,op);
-	    draw(op);
+	    if ((op = insert_ob_in_map(op,op->map,op)) != NULL)
+	        draw(op);
 	    return 1;
 	}
     } else { /* Player didn't specify a distance, so lets see how far
@@ -1031,7 +1023,8 @@
     /* Actually move the player now */
     remove_ob(op);
     op->x+=freearr_x[dir]*dist,op->y+=freearr_y[dir]*dist;
-    insert_ob_in_map(op,op->map,op);
+    if ((op = insert_ob_in_map(op,op->map,op)) == NULL)
+        return 1;
     draw(op);
     op->speed_left= -FABS(op->speed)*5; /* Freeze them for a short while */
     return 1;
@@ -1482,8 +1475,8 @@
       prev = tmp;
     }
     head->direction = dir;
-    insert_ob_in_map(head, op->map, op);
-    if (!QUERY_FLAG(head, FLAG_FREED) && head->randomitems != NULL) {
+    head = insert_ob_in_map (head, op->map, op);
+    if (head != NULL && head->randomitems != NULL) {
       object *tmp;
       create_treasure(head->randomitems,head,GT_INVENTORY,6,0);
       for(tmp = head->inv; tmp != NULL; tmp = tmp->below)
@@ -1542,10 +1535,12 @@
   at = find_archetype("splint");
   for(env=op;env->env!=NULL;env=env->env);
   if (op->env) {
-	if (op->type==PLAYER) drop(env,op);
+	if (env->type==PLAYER) drop(env,op);
 	else {
+            SET_FLAG (op, FLAG_NO_APPLY);
 	    remove_ob(op);
 	    insert_ob_in_map(op, env->map, op);
+            CLEAR_FLAG (op, FLAG_NO_APPLY);
 	}
   }
   if (env->map == NULL)
@@ -1647,6 +1642,7 @@
   int missile_plus=0;
   char *missile_name;
   object *tmp, *missile;
+  tag_t tag;
 
   missile_name = "arrow";
 
@@ -1685,7 +1681,10 @@
 			arrows +4 and selling them, even with value = 1 */
 
   SET_FLAG(missile, FLAG_IDENTIFIED);
-  if (!cast_create_obj(op,caster,missile,dir) && op->type==PLAYER) {
+  tag = missile->count;
+  if ( ! cast_create_obj (op, caster, missile, dir) && op->type == PLAYER
+      && ! was_destroyed (missile, tag))
+  {
     tmp= get_owner(op);
     if (!tmp)
       pick_up(op, missile);
@@ -2265,7 +2264,8 @@
 	free_object(tmp);
 	return 0;
     }
-    insert_ob_in_map(tmp,op->map,op);
+    if ((tmp = insert_ob_in_map (tmp, op->map, op)) == NULL)
+        return 1;
     if(QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))
 	update_all_los(op->map);
     if(op->type==PLAYER)
@@ -2706,8 +2706,8 @@
 	    }
 	} /* if monster level is much less than character level */
 
-	insert_ob_in_map(head, op->map, op);
-	if (!QUERY_FLAG(head, FLAG_FREED) && head->randomitems != NULL) {
+	head = insert_ob_in_map (head, op->map, op);
+	if (head != NULL && head->randomitems != NULL) {
 	    object *tmp;
 	    create_treasure(head->randomitems,head,GT_INVENTORY,6,0);
 	    for(tmp = head->inv; tmp != NULL; tmp = tmp->below)
diff -ru orig/crossfire-0.95.5-cvs3-patch20/server/spell_util.c crossfire-0.95.5-cvs3/server/spell_util.c
--- orig/crossfire-0.95.5-cvs3-patch20/server/spell_util.c	Mon May 29 18:31:26 2000
+++ crossfire-0.95.5-cvs3/server/spell_util.c	Thu Jun  8 02:31:55 2000
@@ -954,6 +954,7 @@
   if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE))
     SET_ANIMATION(tmp, dir);
   set_owner(tmp,op);
+  tmp->level = SK_level (caster);
 #if 0
   if(op->type==PLAYER)
     tmp->stats.wc=5+(op->contr->shootstrength-5)/5,
@@ -969,8 +970,8 @@
     tmp->x=op->x,tmp->y=op->y;
     tmp->direction=absdir(tmp->direction+4);
   }
-  insert_ob_in_map(tmp,op->map,op);
-  move_bolt(tmp);
+  if ((tmp = insert_ob_in_map(tmp,op->map,op)) != NULL)
+    move_bolt (tmp);
   return 1;
 }
 
@@ -1026,11 +1027,8 @@
   if(op->type==PLAYER)
     tmp->stats.hp=(op->contr->shootstrength-10)/10+10;
 #endif
-  insert_ob_in_map(tmp,op->map,op);
-  /* object was used when it was inserted into the map - don't do anything
-   * more
-   */
-  if (QUERY_FLAG(tmp, FLAG_FREED)) return 1;
+  if ((tmp = insert_ob_in_map (tmp, op->map, op)) == NULL)
+    return 1;
   switch(type) {
     case SP_M_MISSILE:
     move_missile(tmp);
@@ -1210,8 +1208,10 @@
     return;
   }
   if(op->above!=NULL&&op->above->type!=PLAYER) {
+    SET_FLAG (op, FLAG_NO_APPLY);
     remove_ob(op);
     insert_ob_in_map(op,op->map,op);
+    CLEAR_FLAG (op, FLAG_NO_APPLY);
   }
   hit_map(op,0,op->attacktype);
   if(op->stats.hp>2&&!op->value) {
@@ -1303,12 +1303,15 @@
       tmp->value=0;
       tmp->stats.hp++;
       tmp->x+=DIRX(tmp),tmp->y+=DIRY(tmp);
-      insert_ob_in_map(tmp,op->map,op);
-      if (!tmp->stats.food) {
-        tmp->stats.food = 1;
-        move_bolt(tmp);
-      } else
-        tmp->stats.food = 0;
+      tmp = insert_ob_in_map(tmp,op->map,op);
+      if (tmp) {
+        if ( ! tmp->stats.food) {
+          tmp->stats.food = 1;
+          move_bolt (tmp);
+        } else {
+          tmp->stats.food = 0;
+        }
+      }
     }
   }
 }
@@ -1320,6 +1323,7 @@
 void move_golem(object *op) {
     int made_attack=0;
     object *tmp;
+    tag_t tag;
 
     if(QUERY_FLAG(op, FLAG_MONSTER))
 	return; /* Has already been moved */
@@ -1358,7 +1362,10 @@
      * move_ob (makes recursive calls to other parts) 
      * move_ob returns 0 if the creature was not able to move.
      */
+    tag = op->count;
     if(move_ob(op,op->direction,op)) return;
+    if (was_destroyed (op, tag))
+        return;
 
     for(tmp=op;tmp;tmp=tmp->more) { 
 	int x=tmp->x+freearr_x[op->direction],y=tmp->y+freearr_y[op->direction];
@@ -1560,8 +1567,8 @@
 
     if(reflwall(op->map,op->x,op->y)) {
 	op->direction=absdir(op->direction+4);
-	insert_ob_in_map(op,op->map,op);
-	update_turn_face(op);
+	if ((op = insert_ob_in_map(op,op->map,op)) != NULL)
+	    update_turn_face(op);
 	return;
     }
     if(blocked(op->map,op->x,op->y)) {
@@ -1942,13 +1949,12 @@
 	    tmp->head=head;
 	    prev->more=tmp;
 	}
-	insert_ob_in_map(tmp,op->map,op);
-	/* If something happens on the insert, don't insert anymore parts */
-	if (QUERY_FLAG(tmp,FLAG_FREED)) break;
 	if (!head) head=tmp;
 	prev=tmp;
 	at=at->more;
     }
+
+    insert_ob_in_map(head,op->map,op);
 
     /* thought it'd be cool to insert a burnout, too.*/
     tmp=get_archetype("burnout");
diff -ru orig/crossfire-0.95.5-cvs3-patch20/server/time.c crossfire-0.95.5-cvs3/server/time.c
--- orig/crossfire-0.95.5-cvs3-patch20/server/time.c	Tue Jun  6 17:03:07 2000
+++ crossfire-0.95.5-cvs3/server/time.c	Thu Jun  8 11:38:02 2000
@@ -100,10 +100,6 @@
     prev=op;
     at=at->more;
   }
-  if(gen->stats.food&&!--(gen->stats.food)) {
-    remove_ob(gen);
-    free_object(gen);
-  }
 }
 
 void regenerate_rod(object *rod) {
diff -ru orig/crossfire-0.95.5-cvs3-patch21/common/button.c crossfire-0.95.5-cvs3/common/button.c
--- orig/crossfire-0.95.5-cvs3-patch21/common/button.c	Fri May 26 11:50:45 2000
+++ crossfire-0.95.5-cvs3/common/button.c	Thu Jun  8 12:18:03 2000
@@ -552,11 +552,14 @@
 		for(tmp2=get_map_ob(op2->map,op2->x,op2->y); /* finding an owner */ 
                    tmp2->type!=PLAYER;tmp2=tmp2->above)	
                 	if(tmp2->above==NULL) break;
-		
+
+                if (tmp2->type != PLAYER)
+                    break;
 		set_owner(tmp,tmp2);
 		SET_FLAG(tmp,FLAG_MONSTER);
 		tmp->stats.exp = 0;
 		SET_FLAG(tmp, FLAG_FRIENDLY);
+                add_friendly_object (tmp);
 		tmp->move_type = PETMOVE;
 		break;		
 
diff -ru orig/crossfire-0.95.5-cvs3-patch21/common/friend.c crossfire-0.95.5-cvs3/common/friend.c
--- orig/crossfire-0.95.5-cvs3-patch21/common/friend.c	Tue Jul 13 08:02:41 1999
+++ crossfire-0.95.5-cvs3/common/friend.c	Thu Jun  8 12:13:12 2000
@@ -54,7 +54,7 @@
       prev=prev->next;
     if(prev==NULL||prev->next==NULL||
        prev->next->ob!=op||prev->next->id!=op->count) {
-      LOG(llevDebug,"Remove_friendly_object: Can't find object %s (%d).\n",
+      LOG(llevError,"Remove_friendly_object: Can't find object %s (%d).\n",
           op->name,op->count);
       return;
     }
diff -ru orig/crossfire-0.95.5-cvs3-patch21/common/living.c crossfire-0.95.5-cvs3/common/living.c
--- orig/crossfire-0.95.5-cvs3-patch21/common/living.c	Sun May 28 20:27:00 2000
+++ crossfire-0.95.5-cvs3/common/living.c	Thu Jun  8 15:29:03 2000
@@ -1052,8 +1052,11 @@
           if(tmp->armour)
             op->armour+=((100-op->armour)*tmp->armour)/100;
 
-          if(tmp->slaying!=NULL)
+          if(tmp->slaying!=NULL) {
+            if (op->slaying != NULL)
+              free_string (op->slaying);
             add_refcount(op->slaying = tmp->slaying);
+          }
 
 	  if(tmp->stats.ac)
             op->stats.ac-=(tmp->stats.ac+tmp->magic);
@@ -1094,8 +1097,11 @@
         weapon_weight=tmp->weight;
         weapon_speed=((int)WEAPON_SPEED(tmp)*2-tmp->magic)/2;
         if(weapon_speed<0) weapon_speed=0;
-        if(tmp->slaying!=NULL)
+        if(tmp->slaying!=NULL) {
+          if (op->slaying != NULL)
+            free_string (op->slaying);
           add_refcount(op->slaying = tmp->slaying);
+        }
 #ifdef SPELL_ENCUMBRANCE
 	if(op->type==PLAYER) op->contr->encumbrance+=(int)3*tmp->weight/1000;
 #endif
diff -ru orig/crossfire-0.95.5-cvs3-patch21/common/object.c crossfire-0.95.5-cvs3/common/object.c
--- orig/crossfire-0.95.5-cvs3-patch21/common/object.c	Sun May 28 20:27:00 2000
+++ crossfire-0.95.5-cvs3/common/object.c	Thu Jun  8 13:26:04 2000
@@ -1227,6 +1227,10 @@
 {
   object *tmp, *top;
 
+  if (QUERY_FLAG (op, FLAG_FREED)) {
+    LOG (llevError, "Trying to insert freed object!\n");
+    return;
+  }
   if(m==NULL) {
     dump_object(op);
     LOG(llevError,"Trying to insert in null-map!\n%s\n",errmsg);
@@ -1343,6 +1347,10 @@
 {
   object *tmp, *top;
 
+  if (QUERY_FLAG (op, FLAG_FREED)) {
+    LOG (llevError, "Trying to insert freed object!\n");
+    return;
+  }
   if(m==NULL) {
     dump_object(op);
     LOG(llevError,"Trying to insert in null-map!\n%s\n",errmsg);
diff -ru orig/crossfire-0.95.5-cvs3-patch21/server/attack.c crossfire-0.95.5-cvs3/server/attack.c
--- orig/crossfire-0.95.5-cvs3-patch21/server/attack.c	Thu Jun  8 01:21:56 2000
+++ crossfire-0.95.5-cvs3/server/attack.c	Thu Jun  8 14:15:41 2000
@@ -670,10 +670,15 @@
     } else if (attacktype & AT_TURN_UNDEAD) {
 	if (QUERY_FLAG(op,FLAG_UNDEAD)) {
 	    object *owner=get_owner(hitter)==NULL?hitter:get_owner(hitter);
-	    /* if undead are not an enemy of your god, you turn them at half strength */
-	    if(op->level<((turn_bonus[owner->stats.Wis]+owner->level) /
-			  (strstr(find_god(determine_god(owner))->slaying,undead_name)?1:2)))
-		SET_FLAG(op, FLAG_SCARED);
+            object *god = find_god (determine_god (owner));
+            int div = 1;
+	    /* if undead are not an enemy of your god, you turn them at half
+             * strength */
+            if ( ! god || ! god->slaying
+                || strstr (god->slaying, undead_name) == NULL)
+                div = 2;
+	    if (op->level < (turn_bonus[owner->stats.Wis]+owner->level) / div)
+	        SET_FLAG(op, FLAG_SCARED);
 	}
 	else dam=0; /*don't damage non undead - should we damage undead? */
     /* fear, cancelleation, deplete handled above */
@@ -800,12 +805,15 @@
      * a proper match, otherwise no damage.
      */
     if (type & AT_HOLYWORD) {
+        object *god;
 	if ((!hitter->slaying || 
 	     (!(op->race && strstr(hitter->slaying,op->race)) &&
 	     !(op->name && strstr(hitter->slaying,op->name)))) &&
 	    (!QUERY_FLAG(op,FLAG_UNDEAD) ||
-	     (hitter->title != NULL &&
-	      (strstr(find_god(determine_god(hitter))->race,undead_name)!=NULL))))
+	     (hitter->title != NULL
+              && (god = find_god(determine_god(hitter))) != NULL
+              && god->race != NULL
+	      && strstr(god->race,undead_name) != NULL)))
 	    return 0;
     }
 
@@ -885,10 +893,11 @@
 	}
 	if(QUERY_FLAG (op, FLAG_FRIENDLY)) {
 	    remove_friendly_object(op);
-	    if(get_owner(op)!=NULL)
+	    if (get_owner (op) != NULL && op->owner->type == PLAYER)
 		op->owner->contr->golem=NULL;
 	    else
-		LOG(llevDebug,"Encountered golem without owner.\n");
+		LOG (llevError, "BUG: hit_player(): Encountered golem "
+		     "without owner.\n");
 	    remove_ob(op);
 	    free_object(op);
 	    return maxdam;
diff -ru orig/crossfire-0.95.5-cvs3-patch21/server/gods.c crossfire-0.95.5-cvs3/server/gods.c
--- orig/crossfire-0.95.5-cvs3-patch21/server/gods.c	Fri May 26 11:50:49 2000
+++ crossfire-0.95.5-cvs3/server/gods.c	Thu Jun  8 16:50:52 2000
@@ -658,7 +658,10 @@
 
     /* either holy word or godpower attacks will set the slaying field */
     if(spellop->attacktype&AT_HOLYWORD||spellop->attacktype&AT_GODPOWER) { 
-         if(spellop->slaying) free_string(spellop->slaying);
+         if (spellop->slaying) {
+             free_string(spellop->slaying);
+             spellop->slaying = NULL;
+         }
          if(!caster_is_spell)
             spellop->slaying = add_string(god->slaying);
 	 else if(caster->slaying) 
diff -ru orig/crossfire-0.95.5-cvs3-patch21/server/spell_effect.c crossfire-0.95.5-cvs3/server/spell_effect.c
--- orig/crossfire-0.95.5-cvs3-patch21/server/spell_effect.c	Thu Jun  8 13:01:20 2000
+++ crossfire-0.95.5-cvs3/server/spell_effect.c	Thu Jun  8 15:37:40 2000
@@ -771,16 +771,6 @@
                   10* SP_level_strength_adjust(op,caster,spell_type);
 	/* More solid, since they can be torn down */
     tmp->stats.maxhp = tmp->stats.hp;
-#if 0
-    /* Don't make them friendly - ends up making them too hard hard for other
-     * players to kill
-     */
-    /*
-     *  Now, make agressive monsters tear down the walls:
-     */
-    SET_FLAG(tmp, FLAG_FRIENDLY);
-    add_friendly_object(tmp);
-#endif
     break;
   case SP_FIRE_WALL:
     tmp=get_archetype("firebreath");
@@ -1455,12 +1445,15 @@
           add_friendly_object(tmp);
           SET_FLAG(tmp, FLAG_FRIENDLY);
           tmp->move_type = PETMOVE;
-        } else
-          if(QUERY_FLAG(op, FLAG_FRIENDLY)) {
-            add_friendly_object(tmp);
-            SET_FLAG(tmp, FLAG_FRIENDLY);
-            tmp->move_type = PETMOVE;
-          } else
+        } else if (QUERY_FLAG (op, FLAG_FRIENDLY)) {
+      	    object *owner = get_owner(op);
+            if (owner != NULL) {
+               set_owner (tmp, owner);
+               tmp->move_type = PETMOVE;
+               add_friendly_object (tmp);
+               SET_FLAG (tmp, FLAG_FRIENDLY);
+	    }
+	}
         tmp->speed_left = -1;
         tmp->enemy = op->enemy;
         tmp->type = 0;
@@ -2457,6 +2450,8 @@
   int i;
   object *tmp,*effect;
   
+  if (op->type != PLAYER)
+    return 0;
   for(i=1;i<MIN(9+SP_level_strength_adjust(op,caster,spellnum),SIZEOFFREE);i++) {
 	if (out_of_map(op->map,op->x+freearr_x[i],op->y+freearr_y[i]))
 	    continue;
@@ -2477,9 +2472,9 @@
 	}
 	set_owner(tmp,op);
 	SET_FLAG(tmp,FLAG_MONSTER);
-	if(op->type==PLAYER)
-	tmp->stats.exp = 0;
 	SET_FLAG(tmp,FLAG_FRIENDLY);
+        add_friendly_object (tmp);
+	tmp->stats.exp = 0;
 	tmp->move_type = PETMOVE;
   }
   return 1;
@@ -2488,7 +2483,9 @@
 int cast_charm_undead(object *op, object *caster,archetype *arch,int spellnum) {
   int i,bonus;
   object *tmp,*effect;
- 
+
+  if (op->type != PLAYER)
+    return 0; 
   if (QUERY_FLAG(caster,FLAG_UNDEAD) || strstr(find_god(determine_god(op))->race,undead_name)!=NULL) {
     bonus = 5;
   } else if (strstr(find_god(determine_god(op))->slaying,undead_name)!=NULL) {
@@ -2515,9 +2512,9 @@
         }
         set_owner(tmp,op);
         SET_FLAG(tmp,FLAG_MONSTER);
-        if(op->type==PLAYER)
-        tmp->stats.exp = 0;
         SET_FLAG(tmp,FLAG_FRIENDLY);
+        add_friendly_object (tmp);
+	tmp->stats.exp = 0;
         tmp->move_type = PETMOVE;
   }
   return 1;
@@ -2798,8 +2795,14 @@
   tmp->vulnerable|=god->vulnerable;
   tmp->immune|=god->immune;
   tmp->protected|=god->protected;
-  if(tmp->race) free_string(tmp->race);
-  if(tmp->slaying) free_string(tmp->slaying);
+  if (tmp->race) {
+    free_string (tmp->race);
+    tmp->race = NULL;
+  }
+  if (tmp->slaying) {
+    free_string (tmp->slaying);
+    tmp->slaying = NULL;
+  }
   if(god->race) tmp->race = add_string(god->race);
   if(god->slaying) tmp->slaying = add_string(god->slaying);
   /* safety, we must allow a god's servants some reasonable attack */
@@ -2839,11 +2842,12 @@
         } else { 
           if(QUERY_FLAG(op, FLAG_FRIENDLY)) {
       	    object *owner = get_owner(op);
-            if(owner != NULL) /* For now, we transfer ownership */
+            if(owner != NULL) {/* For now, we transfer ownership */
                set_owner(tmp,owner);
-      	    tmp->move_type = PETMOVE;
-            add_friendly_object(tmp);
-            SET_FLAG(tmp, FLAG_FRIENDLY);
+               tmp->move_type = PETMOVE;
+               add_friendly_object(tmp);
+               SET_FLAG(tmp, FLAG_FRIENDLY);
+	    }
           }
         }
         if(op->type!=PLAYER||type!=GOLEM) { 
@@ -3058,11 +3062,12 @@
        && !QUERY_FLAG(weapon,FLAG_CURSED)
        && !QUERY_FLAG(weapon,FLAG_DAMNED)){
       object *owner = get_owner(op);
-      if(owner != NULL)
+      if(owner != NULL) {
         set_owner(tmp,owner);
-      tmp->move_type = PETMOVE;
-      add_friendly_object(tmp);
-      SET_FLAG(tmp, FLAG_FRIENDLY);
+        tmp->move_type = PETMOVE;
+        add_friendly_object(tmp);
+        SET_FLAG(tmp, FLAG_FRIENDLY);
+      }
     }
     /* otherwise, make the golem an enemy */
     SET_FLAG(tmp, FLAG_MONSTER);
@@ -3135,7 +3140,10 @@
   }
   tmp->armour = 100 - (int)((100.0-(float)tmp->armour)/(30.0-2.0*(a>14?14.0:(float)a)));
   /* If the weapon has a Slaying list, so does the golem */
-  if(tmp->slaying) free_string(tmp->slaying);
+  if (tmp->slaying) {
+    free_string (tmp->slaying);
+    tmp->slaying = NULL;
+  }
   if(weapon->slaying) tmp->slaying = add_string(weapon->slaying);
 
   /* Determine golem's speed */
diff -ru orig/crossfire-0.95.5-cvs3-patch21/server/spell_util.c crossfire-0.95.5-cvs3/server/spell_util.c
--- orig/crossfire-0.95.5-cvs3-patch21/server/spell_util.c	Thu Jun  8 13:01:20 2000
+++ crossfire-0.95.5-cvs3/server/spell_util.c	Thu Jun  8 12:49:22 2000
@@ -834,11 +834,12 @@
   } else {
     if(QUERY_FLAG(op, FLAG_FRIENDLY)) {
       object *owner = get_owner(op);
-      if(owner != NULL) /* For now, we transfer ownership */
-        set_owner(tmp,owner);
-      tmp->move_type = PETMOVE;
-      add_friendly_object(tmp);
-      SET_FLAG(tmp, FLAG_FRIENDLY);
+      if (owner != NULL) { /* For now, we transfer ownership */
+        set_owner (tmp, owner);
+        tmp->move_type = PETMOVE;
+        add_friendly_object (tmp);
+        SET_FLAG (tmp, FLAG_FRIENDLY);
+      }
     }
     SET_FLAG(tmp, FLAG_MONSTER);
   }
diff -ru orig/crossfire-0.95.5-cvs3-patch21/server/time.c crossfire-0.95.5-cvs3/server/time.c
--- orig/crossfire-0.95.5-cvs3-patch21/server/time.c	Thu Jun  8 13:01:20 2000
+++ crossfire-0.95.5-cvs3/server/time.c	Thu Jun  8 15:39:48 2000
@@ -511,7 +511,7 @@
     object *tmp;
 
     if(op->map==NULL) {
-	LOG(llevError,"Arrow had no map.\n");
+	LOG(llevDebug,"Arrow had no map.\n");
 	remove_ob(op);
 	free_object(op);
 	return;
@@ -773,6 +773,8 @@
 	{ op->stats.hp=-1;return;}
   tmp=arch_to_object(op->other_arch);
   if(op->slaying) {
+	 if (tmp->name) free_string (tmp->name);
+	 if (tmp->title) free_string (tmp->title);
 	 tmp->name = add_string(op->slaying);
 	 tmp->title = add_string(op->slaying);
   }
diff -ru orig/crossfire-0.95.5-cvs3-patch22/server/spell_effect.c crossfire-0.95.5-cvs3/server/spell_effect.c
--- orig/crossfire-0.95.5-cvs3-patch22/server/spell_effect.c	Thu Jun  8 17:23:54 2000
+++ crossfire-0.95.5-cvs3/server/spell_effect.c	Thu Jun  8 17:23:13 2000
@@ -1528,16 +1528,15 @@
   at = find_archetype("splint");
   for(env=op;env->env!=NULL;env=env->env);
   if (op->env) {
+        if (env->map == NULL)
+            return;
 	if (env->type==PLAYER) drop(env,op);
 	else {
-            SET_FLAG (op, FLAG_NO_APPLY);
 	    remove_ob(op);
-	    insert_ob_in_map(op, env->map, op);
-            CLEAR_FLAG (op, FLAG_NO_APPLY);
+	    if ((op = insert_ob_in_map (op, env->map, op)) == NULL)
+                return;
 	}
   }
-  if (env->map == NULL)
-    return;
   if (at)
     for(i=1;i<9;i++)
       fire_arch(op,op,i,at,0,0);