Difference for common/object.c from version 1.31 to 1.32


version 1.31 version 1.32
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_object_c =   * static char *rcsid_object_c =
  *   "$Id: object.c,v 1.31 2001/06/29 05:59:46 mwedel Exp $";   *   "$Id: object.c,v 1.32 2001/07/14 04:04:53 mwedel Exp $";
  */   */
   
 /*  /*
Line 317
 
Line 317
 }  }
   
 void free_all_object_data() {  void free_all_object_data() {
   
 #if 0  
   
     /* Don't clean these up, so that properly allocated but 'lost' objects  
      * still show up in memory debugging output.  This is things like  
      * a function doing a get_ob, but not freeing it.  
      */  
     for (op=objects; op!=NULL; op=next) {  
  next=op->next;  
  if (!op->head && !QUERY_FLAG(op,FLAG_REMOVED))  
  remove_ob(op);  
  if (!op->head && !QUERY_FLAG(op,FLAG_FREED))  
  free_object(op);  
     }  
 #endif  
   
 #ifdef MEMORY_DEBUG  #ifdef MEMORY_DEBUG
     object *op, *next;      object *op, *next;
   
Line 722
 
Line 706
     if(!QUERY_FLAG(op,FLAG_IS_TURNABLE)||op->arch==NULL)      if(!QUERY_FLAG(op,FLAG_IS_TURNABLE)||op->arch==NULL)
  return;   return;
     SET_ANIMATION(op, op->direction);      SET_ANIMATION(op, op->direction);
     update_object(op);      update_object(op,UP_OBJ_FACE);
 }  }
   
 /*  /*
Line 789
 
Line 773
  * If the object being updated is beneath a player, the look-window   * If the object being updated is beneath a player, the look-window
  * of that player is updated (this might be a suboptimal way of   * of that player is updated (this might be a suboptimal way of
  * updating that window, though, since update_object() is called _often_)   * updating that window, though, since update_object() is called _often_)
    *
    * action is a hint of what the caller believes need to be done.
    * For example, if the only thing that has changed is the face (due to
    * an animation), we don't need to call update_position until that actually
    * comes into view of a player.  OTOH, many other things, like addition/removal
    * of walls or living creatures may need us to update the flags now.
    * current action are:
    * UP_OBJ_INSERT: op was inserted
    * UP_OBJ_REMOVE: op was removed
    * UP_OBJ_CHANGE: object has somehow changed.  In this case, we always update
    *  as that is easier than trying to look at what may have changed.
    * UP_OBJ_FACE: only the objects face has changed.
  */   */
   
 void update_object(object *op) {  void update_object(object *op, int action) {
     object *player;      int update_now, flags;
   
     if(op->env!=NULL) {      if(op->env!=NULL) {
  /* Animation is currently handled by client, so nothing   /* Animation is currently handled by client, so nothing
Line 801
 
Line 797
  return;   return;
     }      }
   
     /* Can be null if the player has quit but window still exists. */      /* If the map is saving, don't do anything as everything is
     if (op->map->map != NULL) {       * going to get freed anyways.
  object *tmp;  
  player=update_position (op->map, op->x, op->y);  
   
  /* Special check here.  If a player is on this space, and the   
  * player is not the object that has changed, and the object is  
  * not normally animated (ie, buttons) and not invisible, mark this  
  * space to be updated.  
  */  
  if (player && player!=op && op->speed<MIN_ACTIVE_SPEED && !op->invisible &&  
      op->animation_id) {  
      for (tmp=op; tmp!=NULL; tmp=tmp->above)  
  if (QUERY_FLAG(tmp,FLAG_IS_FLOOR) && !tmp->invisible) break;  
   
      if (!tmp) esrv_update_item_func(UPD_FACE, player, op);  
  }  
        
     }  
   
     if(op->more!=NULL)  
  update_object(op->more);  
 }  
   
   
 /* This updates how the map looks at a specified space.  We use  
  * some time saving techniques instead of space - each map has 2 or  
  * 3 arrays - one for floors, one for top object, and one for an  
  * additional object (if DOUBLE_FLOOR patch).  Changed things around  
  * so that we now have a visibility flag, and if that is set, then the  
  * highest object with that visibility gets put into the addition object  
  * slot.  
  *  
  * Return player object ifwe find one.  
  * update_object (which calls this) needs to know if it should send an   
  * update to the client.  Update object could check for that, but  
  * since this looks through the space anyways, might as well this function  
  * return it for us.  
  */   */
 object *update_position (mapstruct *m, int x, int y) {      if (!op->map || op->map->in_memory == MAP_SAVING) return;
     object *tmp, *last = NULL, *player=NULL;  
     unsigned int flags = 0;  
     MapLook top,floor, f1;  
   
       flags = GET_MAP_FLAGS(op->map, op->x, op->y);
       SET_MAP_FLAGS(op->map, op->x, op->y, flags | P_NEED_UPDATE);
   
     f1=blank_look;      if (action == UP_OBJ_INSERT) {
     top=blank_look;          if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) && !(flags & P_BLOCKSVIEW))
     floor=blank_look;              update_now=1;
   
     for (tmp = get_map_ob (m, x, y); tmp; last = tmp, tmp = tmp->above) {          if (QUERY_FLAG(op, FLAG_NO_MAGIC) && !(flags & P_NO_MAGIC))
               update_now=1;
   
  /* This call is needed in order to update objects the player          if (QUERY_FLAG(op, FLAG_DAMNED) && !(flags & P_NO_CLERIC))
  * is standign in that have animations (ie, grass, fire, etc).              update_now=1;
  * However, it also causes the look window to be re-drawn  
  * 3 times each time the player moves, because many of the  
  * functions the move_player calls eventualy call this.  
  *  
  * Always put the player down for drawing.  
  */  
  if (tmp->type==PLAYER && !tmp->invisible) {  
      top.face = tmp->face;  
      player=tmp;  
  }  
  else if (QUERY_FLAG(tmp,FLAG_IS_FLOOR)) {  
      f1=blank_look;  
      if (!tmp->invisible)  
  floor.face = tmp->face;  
  }  
  /* Find the highest visible face around */  
  if (tmp->face->visibility > f1.face->visibility && !tmp->invisible)   
      f1.face = tmp->face;  
   
  if (tmp==tmp->above) {          if (QUERY_FLAG(op, FLAG_NO_PASS) && !(flags & P_NO_PASS))
      LOG(llevError, "Error in structure of map\n");              update_now=1;
      exit (-1);  
  }  
         
  if (QUERY_FLAG(tmp,FLAG_ALIVE))  
      flags |= P_IS_ALIVE;  
  if (QUERY_FLAG(tmp,FLAG_NO_PASS))  
      flags |= P_NO_PASS;  
  if (QUERY_FLAG(tmp,FLAG_NO_MAGIC))  
      flags |= P_NO_MAGIC;  
  if (QUERY_FLAG(tmp,FLAG_DAMNED))  
      flags |= P_NO_CLERIC;  
  if (QUERY_FLAG(tmp,FLAG_PASS_THRU))  
      flags |= P_PASS_THRU;  
  if (QUERY_FLAG(tmp,FLAG_BLOCKSVIEW))  
      flags |= P_BLOCKSVIEW;  
   
     } /* for stack of objects */          if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE))
               update_now=1;
   
     top.flags = flags;      } else if (action == UP_OBJ_REMOVE) {
           if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) && (flags & P_BLOCKSVIEW))
               update_now=1;
   
     /* At this point, we have a floor.face (if there is a floor),          if (QUERY_FLAG(op, FLAG_NO_MAGIC) && (flags & P_NO_MAGIC))
      * and the floor is set - we are not going to touch it at              update_now=1;
      * this point.  
      * f1 contains the highest visibility face.   
      * top contains a player face, if there is one.  
      *  
      * We now need to fill in top.face and/or f1.face.  
      */  
   
     /* If the top face also happens to be high visibility, re-do our          if (QUERY_FLAG(op, FLAG_DAMNED) && (flags & P_NO_CLERIC))
      * middle face.  This only happens when top.face is a player.              update_now=1;
      */  
     if (top.face == f1.face) f1.face=blank_look.face;  
   
     /* There are three posibilities at this point:  
      * 1) top face is set, need f1 to be set.  
      * 2) f1 is set, need to set top.  
      * 3) neither f1 or top is set - need to set both.  
      */  
   
     for (tmp=last; tmp; tmp=tmp->below) {          if (QUERY_FLAG(op, FLAG_NO_PASS) && (flags & P_NO_PASS))
  /* Once we get to a floor, stop, since we already have a floor object */              update_now=1;
  if (QUERY_FLAG(tmp,FLAG_IS_FLOOR)) break;  
   
  /* If two top faces are already set, quit processing */          if (QUERY_FLAG(op, FLAG_ALIVE) && (flags & P_IS_ALIVE))
  if ((top.face != blank_look.face) && (f1.face != blank_look.face)) break;              update_now=1;
   
  /* Only show visible faces, unless its the editor - show all */      } else if (action == UP_OBJ_CHANGE) {
  if (!tmp->invisible || editor) {   update_now=1;
      /* Fill in top if needed */      } else if (action == UP_OBJ_FACE) {
      if (top.face == blank_look.face) {   /* Nothing to do for that case */
  top.face = tmp->face;  
      } else {  
  /* top is already set - we should only get here if  
  * f1 is not set  
  *  
  * Set the middle face and break out, since there is nothing  
  * more to fill in.  We don't check visiblity here, since  
  *   
  */  
  if (tmp->face  != top.face ) {  
      f1.face = tmp->face;  
      break;  
  }  
      }       }
       else {
    LOG(llevError,"update_object called with invalid action: %d\n", action);
  }   }
   
       if (update_now) {
           SET_MAP_FLAGS(op->map, op->x, op->y, flags | P_NO_ERROR | P_NEED_UPDATE);
           update_position(op->map, op->x, op->y);
     }      }
     if (f1.face == floor.face) f1.face = blank_face;  
     if (top.face == f1.face) f1.face = blank_face;  
     set_map (m, x, y, &top);  
     set_map_floor2(m, x, y, &f1);  
     set_map_floor(m,x,y,&floor);  
   
     return player;      if(op->more!=NULL)
    update_object(op->more, action);
 }  }
   
   
 /*  /*
  * free_object() frees everything allocated by an object, removes   * free_object() frees everything allocated by an object, removes
  * it from the list of used objects, and puts it on the list of   * it from the list of used objects, and puts it on the list of
Line 1004
 
Line 909
           free_object(op);            free_object(op);
         else {          else {
           op->x=ob->x,op->y=ob->y;            op->x=ob->x,op->y=ob->y;
           insert_ob_in_map(op,ob->map,NULL); /* Insert in same map as the envir */            insert_ob_in_map(op,ob->map,NULL,0); /* Insert in same map as the envir */
         }          }
         op=tmp;          op=tmp;
       }        }
Line 1138
 
Line 1043
   object *otmp;    object *otmp;
   tag_t tag;    tag_t tag;
   int check_walk_off;    int check_walk_off;
       mapstruct *m;
       int x,y;
      
   
   if(QUERY_FLAG(op,FLAG_REMOVED)) {    if(QUERY_FLAG(op,FLAG_REMOVED)) {
     dump_object(op);      dump_object(op);
     LOG(llevError,"Trying to remove removed object.\n%s\n",errmsg);      LOG(llevError,"Trying to remove removed object.\n%s\n",errmsg);
   
 /* Might as well dump core here.  In most cases, the function calling   /* Changed it to always dump core in this case.  As has been learned
  * remove_ob makes assumptions about success, and the validity of the   * in the past, trying to recover from errors almost always
  * next, above, and below pointers, and a core dump would probably result   * make things worse, and this is a real error here - something
  * shortly anyways.   * that should not happen.
    * Yes, if this was a mission critical app, trying to do something
    * to recover may make sense, but that is because failure of the app   
    * may have other disastrous problems.  Cf runs out of a script
    * so is easily enough restarted without any real problems.
    * MSW 2001-07-01
  */   */
 #ifdef MANY_CORES  
     abort();      abort();
 #else  
     if(op->map!=NULL && op->map->in_memory == MAP_IN_MEMORY) {  
       op->map->need_refresh=1;  
       LOG(llevDebug,"Marked map %s for refresh.\n",op->map->path);  
     }  
 #endif  
     if(get_map_ob(op->map,op->x,op->y)==op)  
     { /* we are at bottom [Smart! -Frank] */  
        if (op->below)  
    set_map_ob(op->map,op->x,op->y,op->below);  
        else if (op->above)  
    set_map_ob(op->map,op->x,op->y,op->above);  
        else   
    set_map_ob(op->map,op->x,op->y,NULL);  
     }  
     return; /* Why did you comment this away at DoCS?? It just makes it worse */  
   }    }
   if(op->more!=NULL)    if(op->more!=NULL)
     remove_ob(op->more);      remove_ob(op->more);
   
   SET_FLAG(op, FLAG_REMOVED);    SET_FLAG(op, FLAG_REMOVED);
   
       /*
        * In this case, the object to be removed is in someones
        * inventory.
        */
   if(op->env!=NULL) {    if(op->env!=NULL) {
     if(op->nrof)      if(op->nrof)
       sub_weight(op->env, op->weight*op->nrof);        sub_weight(op->env, op->weight*op->nrof);
     else      else
       sub_weight(op->env, op->weight+op->carrying);        sub_weight(op->env, op->weight+op->carrying);
   
    /* NO_FIX_PLAYER is set when a great many changes are being
    * made to players inventory.  If set, avoiding the call
    * to save cpu time.
    */
     if ((otmp=is_player_inv(op->env))!=NULL && otmp->contr &&       if ((otmp=is_player_inv(op->env))!=NULL && otmp->contr &&
  !QUERY_FLAG(otmp,FLAG_NO_FIX_PLAYER))   !QUERY_FLAG(otmp,FLAG_NO_FIX_PLAYER))
       fix_player(otmp);        fix_player(otmp);
   
     if(op->above!=NULL)      if(op->above!=NULL)
       op->above->below=op->below;        op->above->below=op->below;
     else      else
       op->env->inv=op->below;        op->env->inv=op->below;
   
     if(op->below!=NULL)      if(op->below!=NULL)
       op->below->above=op->above;        op->below->above=op->above;
   
    /* we set up values so that it could be inserted into
    * the map, but we don't actually do that - it is up
    * to the caller to decide what we want to do.
    */
     op->x=op->env->x,op->y=op->env->y;      op->x=op->env->x,op->y=op->env->y;
     op->ox=op->x,op->oy=op->y;      op->ox=op->x,op->oy=op->y;
     op->map=op->env->map;      op->map=op->env->map;
Line 1191
 
Line 1105
     op->env=NULL;      op->env=NULL;
     return;      return;
   }    }
   
       /* If we get here, we are removing it from a map */
   if (op->map == NULL) return;    if (op->map == NULL) return;
   if(out_of_map(op->map,op->x,op->y))  
     op->x=0,op->y=0,op->ox=0,op->oy=0;      x = op->x;
   if(op->above!=NULL) {                /* Don't change map, we're not on top */      y = op->y;
     op->above->below=op->below;        /* Link above with below */      m = get_map_from_coord(op->map, &x, &y);
     if(op->below!=NULL) {              /* Something below us? */  
       op->below->above=op->above;      /* Yes, link above with below */      if (!m) {
       op->below=NULL;   LOG(llevError,"remove_ob called when object was on map but appears to not be within valid coordinates? %s (%d,%d)\n",
     }       op->map->path, op->x, op->y);
     else {                             /* Nothing below, tell the floor what */   /* in old days, we used to set x and y to 0 and continue.
       if(get_map_ob(op->map,op->x,op->y)!=op) {   * it seems if we get into this case, something is probablye
         dump_object(op);   * screwed up and should be fixed.
         LOG(llevError,"Object squizez another object:\n%s\n",errmsg);   */
         dump_object(get_map_ob(op->map,op->x,op->y));   abort();
         LOG(llevError,"%s\n",errmsg);  
       }        }
       set_map_ob(op->map,op->x,op->y,op->above);  /* goes on above it. */      if (op->map != m) {
    LOG(llevDebug,"remove_ob: Object not really on map it claimed to be on? %s != %s, %d,%d != %d,%d\n",
        op->map->path, m->path, op->x, op->y, x, y);
     }      }
     op->above=NULL;                        
   }      /* Re did the following section of code - it looks like it had
   else if(op->below!=NULL) {       * lots of logic for things we no longer care about
     op->below->above=NULL,             /* It is now on top */       */
     op->below=NULL;  
       /* link the object above us */
       if (op->above)
    op->above->below=op->below;
   
       /* Relink the object below us, if there is one */
       if(op->below) {
    op->below->above=op->above;
   } else {    } else {
       if(get_map_ob(op->map,op->x,op->y)!=op) {   /* Nothing below, which means we need to relink map object for this space
         LOG(llevError,"Object squizez another object:\n");   * use translated coordinates in case some oddness with map tiling is
    * evident
    */
    if(GET_MAP_OB(m,x,y)!=op) {
         dump_object(op);          dump_object(op);
         LOG(llevError,"%s\n",errmsg);       LOG(llevError,"remove_ob: GET_MAP_OB does not return object to be removed even though it appears to be on the bottom?\n%s\n", errmsg);
         dump_object(get_map_ob(op->map,op->x,op->y));       dump_object(GET_MAP_OB(m,x,y));
         LOG(llevError,"%s\n",errmsg);          LOG(llevError,"%s\n",errmsg);
       }        }
     set_map_ob(op->map,op->x,op->y,NULL);           /* No more objects here */   SET_MAP_OB(m,x,y,op->above);  /* goes on above it. */
   }    }
       op->above=NULL;                     
       op->below=NULL;
   
   if (op->map->in_memory == MAP_SAVING)    if (op->map->in_memory == MAP_SAVING)
     return;      return;
   
   tag = op->count;    tag = op->count;
   check_walk_off = ! QUERY_FLAG (op, FLAG_NO_APPLY);    check_walk_off = ! QUERY_FLAG (op, FLAG_NO_APPLY);
   for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) {      for(tmp=GET_MAP_OB(m,x,y);tmp!=NULL;tmp=tmp->above) {
     /* No point updating the players look faces if he is the object      /* No point updating the players look faces if he is the object
      * being removed.       * being removed.
      */       */
   
     if(tmp->type==PLAYER && tmp!=op) {      if(tmp->type==PLAYER && tmp!=op) {
  /* If a container that the player is currently using somehow gets   /* If a container that the player is currently using somehow gets
  * removed (most likely destroyed), update the player view   * removed (most likely destroyed), update the player view
Line 1244
 
Line 1176
  tmp->contr->socket.update_look=1;   tmp->contr->socket.update_look=1;
     }      }
     if (check_walk_off && (QUERY_FLAG (op, FLAG_FLYING) ?      if (check_walk_off && (QUERY_FLAG (op, FLAG_FLYING) ?
         QUERY_FLAG (tmp, FLAG_FLY_OFF) : QUERY_FLAG (tmp, FLAG_WALK_OFF)))       QUERY_FLAG (tmp, FLAG_FLY_OFF) : QUERY_FLAG (tmp, FLAG_WALK_OFF))) {
     {      
         move_apply_func (tmp, op, NULL);          move_apply_func (tmp, op, NULL);
         if (was_destroyed (op, tag)) {          if (was_destroyed (op, tag)) {
           LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed "            LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed "
Line 1259
 
Line 1191
       tmp->above = NULL;        tmp->above = NULL;
     last=tmp;      last=tmp;
   }    }
       /* last == NULL of there are no objects on this space */
   if (last==NULL)    if (last==NULL)
     update_position(op->map, op->x, op->y);      update_position(op->map, op->x, op->y);
   else    else
     update_object(last);   update_object(last, UP_OBJ_REMOVE);
   
   if(QUERY_FLAG(op,FLAG_BLOCKSVIEW) /* Should be harmless from editor, */      if(QUERY_FLAG(op,FLAG_BLOCKSVIEW)|| (op->glow_radius>0))
 #ifdef USE_LIGHTING   update_all_los(op->map, op->x, op->y);
      ||(op->glow_radius>0)   
 #endif  
   )   
     update_all_los(op->map); /* first_player is no longer set there */  
   
 }  }
   
Line 1304
 
Line 1233
 }  }
   
   
 /* This is a simple version of the insert_ob_in_map function below.   
  * We do stuff similar to insert_ob_in_map, but don't merge objects  
  * or check apply.  This is needed by at least the polymorph function -  
  * it expects the next object below it to still be around, and if the  
  * object gets merged, it gets removed  
  */  
   
 void insert_ob_in_map_simple(object *op, mapstruct *m)  
 {  
   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);  
     return;  
   }  
   if(out_of_map(m,op->x,op->y)) {  
     dump_object(op);  
     LOG(llevError,"Trying to insert object outside the map.\n%s\n", errmsg);  
     return;  
   }  
   if(!QUERY_FLAG(op,FLAG_REMOVED)) {  
     dump_object(op);  
     LOG(llevError,"Trying to insert (map) inserted object.\n%s\n", errmsg);  
     return;  
   }  
   if(op->more!=NULL)  
     insert_ob_in_map_simple(op->more,m);  
   CLEAR_FLAG(op,FLAG_REMOVED);  
   op->ox=op->x,op->oy=op->y;  
   op->map=m;  
   CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */  
   CLEAR_FLAG(op, FLAG_INV_LOCKED);  
   CLEAR_FLAG(op, FLAG_NO_STEAL);  
   /* If anything below then */  
   if((top=get_map_ob(op->map,op->x,op->y))!=NULL) {  
     /*      /*
      * There is at least one object present, so we must figure out the order.   * insert_ob_in_map (op, map, originator, flag):
      * First figure out what is on top;  
      */  
   
     while (top->above != NULL)  
       top = top->above;  
   
     tmp = top;  
   
     /*  
      * Rule 0: SEE_ANYWHERE() objects stay on top of the top.  
      */  
     while(tmp != NULL && QUERY_FLAG(tmp,FLAG_SEE_ANYWHERE) &&  
        !QUERY_FLAG(op,FLAG_SEE_ANYWHERE))  
           top = tmp, tmp = tmp->below;  
   
     /*  
      * Rule 1: Alive objects stay on top.  
      */  
     while(tmp != NULL && QUERY_FLAG(tmp,FLAG_ALIVE) &&  
  !QUERY_FLAG(op,FLAG_ALIVE) && !QUERY_FLAG(op,FLAG_FLYING) &&  
           !QUERY_FLAG(op,FLAG_SEE_ANYWHERE))  
       top = tmp, tmp = tmp->below;  
   
     /*  
      * Link the new object in the two-way list:  
      */  
   
     if (top == tmp) {  
       /*  
        * Simple case, insert new object above tmp.  
        */  
       if (tmp->above != NULL)  
         LOG(llevError, "insert_ob_in_map_simple: top == tmp && tmp->above != NULL.\n");  
       else {  
         tmp->above = op;  
         op->below = tmp;  
         op->above = (object *) NULL;  
       }  
     } else {  
       /*  
        * Not so simple case, insert between top and tmp.  
        */  
       if (tmp == NULL) { /* Insert at bottom of map */  
         top->below = op;  
         op->above = top;  
         op->below = (object *) NULL;  
         set_map_ob(op->map, op->x, op->y, op);  
       } else { /* Insert between top and tmp */  
         top->below = op;  
         op->above = top;  
         tmp->above = op;  
         op->below = tmp;  
       }  
     }  
   }  
   else  
     set_map_ob(op->map,op->x,op->y,op);   /* Tell the map that we're here */  
   
   /* build up linked list of light sources in each map. We do  
    * this even for non-dark maps, as down the line we might make  
    * a spell/effect which effects the global light of any map.  
    * -b.t.  
    */  
 #ifdef USE_LIGHTING  
         if(op->glow_radius>0&&light_not_listed(op)) {  
  add_light_to_map(op,m);  
  update_all_los(m);  
  } else if(m->darkness&&(op->glow_radius>0||op->lights)) /* a light moved, check los */  
  update_all_los(m);  
 #endif   
     
   if(op->type==PLAYER)  
     op->contr->do_los=1;  
   for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)  
     switch(tmp->type) {  
     case PLAYER:  
  tmp->contr->socket.update_look=1;  
  break;  
     }  
     update_object(op);  
 }  
   
 /*  
  * insert_ob_in_map (op, map, originator):  
  * This function inserts the object in the two-way linked list   * This function inserts the object in the two-way linked list
  * which represents what is on a map.   * which represents what is on a map.
  * The second argument specifies the map, and the x and y variables   * The second argument specifies the map, and the x and y variables
Line 1438
 
Line 1243
  * originator: Player, monster or other object that caused 'op' to be inserted   * originator: Player, monster or other object that caused 'op' to be inserted
  * into 'map'.  May be NULL.   * into 'map'.  May be NULL.
  *   *
    * flag is a bitmask about special things to do (or not do) when this
    * function is called.  see the object.h file for the INS_ values.
    * Passing 0 for flag gives proper default values, so flag really only needs
    * to be set if special handling is needed.
    *
  * Return value:   * Return value:
  *   new object if 'op' was merged with other object   *   new object if 'op' was merged with other object
  *   NULL if 'op' was destroyed   *   NULL if 'op' was destroyed
  *   just 'op' otherwise   *   just 'op' otherwise
  */   */
   
 object *insert_ob_in_map (object *op, mapstruct *m, object *originator)  object *insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag)
 {  {
   object *tmp, *top;      object *tmp, *top, *floor=NULL;
       int x,y;
   
   if (QUERY_FLAG (op, FLAG_FREED)) {    if (QUERY_FLAG (op, FLAG_FREED)) {
     LOG (llevError, "Trying to insert freed object!\n");      LOG (llevError, "Trying to insert freed object!\n");
Line 1468
 
Line 1279
     return op;      return op;
   }    }
   if(op->more!=NULL) {    if(op->more!=NULL) {
     if (insert_ob_in_map(op->more,m,originator) == NULL) {   if (insert_ob_in_map(op->more,m,originator,flag) == NULL) {
       if ( ! op->head)        if ( ! op->head)
         LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more "   LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n");
              "killed op\n");  
       return NULL;        return NULL;
     }      }
   }    }
   CLEAR_FLAG(op,FLAG_REMOVED);    CLEAR_FLAG(op,FLAG_REMOVED);
   if(op->nrof)  
     for(tmp=get_map_ob(m,op->x,op->y);tmp!=NULL;tmp=tmp->above)      if(op->nrof && !(flag & INS_NO_MERGE)) {
       if (CAN_MERGE(op,tmp))   for(tmp=GET_MAP_OB(m,op->x,op->y);tmp!=NULL;tmp=tmp->above)
       {       if (CAN_MERGE(op,tmp)) {
         op->nrof+=tmp->nrof;          op->nrof+=tmp->nrof;
 /*        CLEAR_FLAG(op,FLAG_STARTEQUIP);*/  
         remove_ob(tmp);          remove_ob(tmp);
         free_object(tmp);          free_object(tmp);
       }        }
   op->ox=op->x,op->oy=op->y;      }
   op->map=m;      /* Debugging information so you can see the last coordinates this object had */
       op->ox=op->x;
       op->oy=op->y;
       x = op->x;
       y = op->y;
       op->map=get_map_from_coord(m, &x, &y);
       /* Ideally, the caller figures this out */
       if (op->map != m) {
    /* coordinates should not change unless map also changes */
    op->x = x;
    op->y = y;
   #if 0
    LOG(llevDebug,"insert_ob_in_map not called with proper tiled map: %s != %s, orig coord = %d, %d\n",
        op->map->path, m->path, op->ox, op->oy);
   #endif
       }
   
   CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */    CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
   CLEAR_FLAG(op, FLAG_INV_LOCKED);    CLEAR_FLAG(op, FLAG_INV_LOCKED);
   if (!QUERY_FLAG(op, FLAG_ALIVE))    if (!QUERY_FLAG(op, FLAG_ALIVE))
     CLEAR_FLAG(op, FLAG_NO_STEAL);      CLEAR_FLAG(op, FLAG_NO_STEAL);
   
   /* If there are other objects, then */    /* If there are other objects, then */
   if((top=get_map_ob(op->map,op->x,op->y))!=NULL) {      if((top=GET_MAP_OB(op->map,op->x,op->y))!=NULL) {
    object *last;
     /*      /*
      * There is at least one object present, so we must figure out the order.   * If there are multiple objects on this space, we do some trickier handling.
      * First figure out what is on top;   * We've already dealt with merging if appropriate.
      */   * Generally, we want to put the new object on top. But if
    * flag contains INS_ABOVE_FLOOR_ONLY, once we find the lastt
     while (top->above != NULL)   * floor, we want to insert above that and no further.
    * Also, if there are spell objects on this space, we stop processing
    * once we get to them.  This reduces the need to traverse over all of
    * them when adding another one - this saves quite a bit of cpu time
    * when lots of spells are cast in one area.  Currently, it is presumed
    * that flying non pickable objects are spell objects.
    */
   
    while (top != NULL) {
        if (QUERY_FLAG(top, FLAG_IS_FLOOR)) floor = top;
        if (QUERY_FLAG(top, FLAG_NO_PICK) && QUERY_FLAG(top, FLAG_FLYING)) {
    /* We insert above top, so we want this object below this */
    top=top->below;
    break;
        }
        last = top;
       top = top->above;        top = top->above;
    }
    /* Don't want top to be NULL, so set it to the last valid object */
    top = last;
   
     tmp = top;   /* We let update_position deal with figuring out what the space
    * looks like instead of lots of conditions here.
     /* Re-did this with nested if statements.  In this way, each check does   * makes things faster, and effectively the same result.
      * not need to check for the previous state - to me, it makes the code  
      * cleaner, and perhaps faster.  
      */       */
     if (!QUERY_FLAG(op, FLAG_SEE_ANYWHERE)) {  
       /* See anywhere objects stay on top. */  
       while(tmp != NULL && QUERY_FLAG(tmp,FLAG_SEE_ANYWHERE))  
           top = tmp, tmp = tmp->below;  
   
       if (!QUERY_FLAG(op, FLAG_ALIVE) && !QUERY_FLAG(op,FLAG_FLYING)) {          /* Have object 'fall below' other objects that block view.
  /* Alive objects also stay on to. */   * We take simple approach - instead of dumping it below the object that
  while(tmp != NULL && QUERY_FLAG(tmp,FLAG_ALIVE))   * blocks the view, we just dump it right above the floor.  Saves
    top = tmp, tmp = tmp->below;   * us the effort of trying to find the object that blocks the view.
   
         /* Have object 'fall below' other objects that block view, except in  
          * cases where the object has a high visibility (high meaning >0)  
          */           */
         if (blocks_view(op->map, op->x, op->y) && (op->face &&          if (blocks_view(op->map, op->x, op->y) &&
                 !op->face->visibility)) {      (op->face && !op->face->visibility)) {
    while (tmp != NULL && QUERY_FLAG(tmp, FLAG_BLOCKSVIEW) &&       top = floor;
      !QUERY_FLAG(op, FLAG_BLOCKSVIEW))  
        top = tmp, tmp = tmp->below;  
  }  
       }  
     }      }
       } /* If objects on this space */
   
     /*      if (flag & INS_ABOVE_FLOOR_ONLY) top = floor;
      * Link the new object in the two-way list:  
      */  
   
     if (top == tmp) {      /* Top is the object that our object (op) is going to get inserted above.
       /*  
        * Simple case, insert new object above tmp.  
        */         */
       if (tmp->above != NULL)  
         LOG(llevError, "insert_ob_in_map: top == tmp && tmp->above != NULL.\n");      /* First object on this space */
       else {      if (!top) {
         tmp->above = op;   op->above = GET_MAP_OB(op->map, op->x, op->y);
         op->below = tmp;   if (op->above) op->above->below = op;
         op->above = (object *) NULL;   op->below = NULL;
       }          SET_MAP_OB(op->map, op->x, op->y, op);
     } else {      } else { /* get inserted into the stack above top */
       /*   op->above = top->above;
        * Not so simple case, insert between top and tmp.   if (op->above) op->above->below = op;
        */   op->below = top;
       if (tmp == NULL) { /* Insert at bottom of map */   top->above = op;
         top->below = op;  
         op->above = top;  
         op->below = (object *) NULL;  
         set_map_ob(op->map, op->x, op->y, op);  
       } else { /* Insert between top and tmp */  
         top->below = op;  
         op->above = top;  
         tmp->above = op;  
         op->below = tmp;  
       }  
     }  
   }    }
   else  
     set_map_ob(op->map,op->x,op->y,op);   /* Tell the map that we're here */  
   
   if(op->type==PLAYER)    if(op->type==PLAYER)
     op->contr->do_los=1;      op->contr->do_los=1;
   for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)      /* If we have a floor, we know the player, if any, will be above
     switch(tmp->type) {       * it, so save a few ticks and start from there.
     case PLAYER:       */
       for(tmp=floor?floor:GET_MAP_OB(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) {
    if (tmp->type == PLAYER)
  tmp->contr->socket.update_look=1;   tmp->contr->socket.update_look=1;
  break;  
     }      }
   /* build up linked list of light sources in each map. We do  
    * this even for non-dark maps, as down the line we might make      /* If this object glows, it may affect lighting conditions that are
    * a spell/effect which effects the global light of any map.       * visible to others on this map.  But update_all_los is really
    * -b.t.       * an inefficient way to do this, as it means los for all players
    */       * on the map will get recalculated.  The players could very well
 #ifdef USE_LIGHTING       * be far away from this change and not affected in any way -
         if(op->glow_radius>0&&light_not_listed(op)) {       * this should get redone to only look for players within range,
  add_light_to_map(op,m);       * or just updating the P_NEED_UPDATE for spaces within this area
  update_all_los(m);       * of effect may be sufficient.
  } else if(m->darkness&&(op->glow_radius>0||op->lights)) /* a light moved, check los */       */
  update_all_los(m);      if(MAP_DARKNESS(op->map) && op->glow_radius>0)
 #endif    update_all_los(op->map, op->x, op->y);
   
   
       /* updates flags (blocked, alive, no magic, etc) for this map space */
       update_object(op,UP_OBJ_INSERT);
   
   
     /* Don't know if moving this to the end will break anything.  However,      /* Don't know if moving this to the end will break anything.  However,
      * we want to have update_look set above before calling this.       * we want to have update_look set above before calling this.
      *       *
Line 1592
 
Line 1415
      * blocked() and wall() work properly), and these flags are updated by       * blocked() and wall() work properly), and these flags are updated by
      * update_object().       * update_object().
      */       */
     update_object(op);  
   
     /* Only check this if we are the head of the object */      /* if this is not the head or flag has been passed, don't check walk on status */
     if ( ! op->head) {  
       if (!(flag & INS_NO_WALK_ON) && !op->head) {
         if (check_walk_on(op, originator))          if (check_walk_on(op, originator))
           return NULL;            return NULL;
   
Line 1606
 
Line 1429
             if (check_walk_on (op, originator))              if (check_walk_on (op, originator))
               return NULL;                return NULL;
     }      }
   
     return op;      return op;
 }  }
   
 /* this function inserts an object in the map, but if it  /* this function inserts an object in the map, but if it
    finds an object of its own type, it'll remove that one first.    *  finds an object of its own type, it'll remove that one first.
    op is the object to insert it under:  supplies x and the map.*/   *  op is the object to insert it under:  supplies x and the map.
    */
 void replace_insert_ob_in_map(char *arch_string, object *op) {  void replace_insert_ob_in_map(char *arch_string, object *op) {
   object *tmp;    object *tmp;
   object *tmp1;    object *tmp1;
   
   /* first search for itself and remove any old instances */    /* first search for itself and remove any old instances */
   
   for(tmp=get_map_ob(op->map,op->x,op->y); tmp!=NULL; tmp=tmp->above) {      for(tmp=GET_MAP_OB(op->map,op->x,op->y); tmp!=NULL; tmp=tmp->above) {
     if(!strcmp(tmp->arch->name,arch_string)) /* same archetype */ {      if(!strcmp(tmp->arch->name,arch_string)) /* same archetype */ {
       remove_ob(tmp);        remove_ob(tmp);
       free_object(tmp);        free_object(tmp);
Line 1630
 
Line 1453
   
      
   tmp1->x = op->x; tmp1->y = op->y;    tmp1->x = op->x; tmp1->y = op->y;
   insert_ob_in_map(tmp1,op->map,op);      insert_ob_in_map(tmp1,op->map,op,0);
   
   
 }          }       
   
 /*  /*
Line 1836
 
Line 1657
   op->x=0,op->y=0;    op->x=0,op->y=0;
   op->ox=0,op->oy=0;    op->ox=0,op->oy=0;
   
 #ifdef USE_LIGHTING /* reset the light list and los of the players on the map */    /* reset the light list and los of the players on the map */
   if(op->glow_radius>0&&where->map)    if(op->glow_radius>0&&where->map)
   {    {
 #ifdef DEBUG_LIGHTS  #ifdef DEBUG_LIGHTS
       LOG(llevDebug, " insert_ob_in_ob(): got %s to insert in map/op\n",        LOG(llevDebug, " insert_ob_in_ob(): got %s to insert in map/op\n",
  op->name);   op->name);
 #endif /* DEBUG_LIGHTS */   #endif /* DEBUG_LIGHTS */
       add_light_to_list(op,where);        if (MAP_DARKNESS(where->map)) update_all_los(where->map, where->x, where->y);
       if(light_not_listed(op)) add_light_to_map(op,where->map);  
       if(where->map->darkness&&where->map->players) update_all_los(where->map);  
   }    }
 #endif /* USE_LIGHTING */   
   
   /* Client has no idea of ordering so lets not bother ordering it here.    /* Client has no idea of ordering so lets not bother ordering it here.
    * It sure simplifies this function...     * It sure simplifies this function...
Line 1873
 
Line 1691
  * into 'map'.  May be NULL.   * into 'map'.  May be NULL.
  *   *
  * Return value: 1 if 'op' was destroyed, 0 otherwise.   * Return value: 1 if 'op' was destroyed, 0 otherwise.
  */   *
  /* 4-21-95 added code to check if appropriate skill was readied - this will   * 4-21-95 added code to check if appropriate skill was readied - this will
   * permit faster movement by the player through this terrain. -b.t.    * permit faster movement by the player through this terrain. -b.t.
    *
    * MSW 2001-07-08: Check all objects on space, not just those below
    * object being inserted.  insert_ob_in_map may not put new objects
    * on top.
   */    */
   
 int check_walk_on (object *op, object *originator)  int check_walk_on (object *op, object *originator)
 {  {
     object *tmp;      object *tmp;
     tag_t tag;      tag_t tag;
       mapstruct *m=op->map;
       int x=op->x, y=op->y;
   
     if(QUERY_FLAG(op,FLAG_NO_APPLY))      if(QUERY_FLAG(op,FLAG_NO_APPLY))
  return 0;   return 0;
   
       /* Spell effects are immune to these checks - this
        * helps performance a lot on maps with lots of spell activity
        */
       if (QUERY_FLAG(op, FLAG_FLYING) && QUERY_FLAG(op, FLAG_NO_PICK)) return 0;
   
     tag = op->count;      tag = op->count;
     for(tmp=op->below;tmp!=NULL;tmp=tmp->below) {      for(tmp=GET_MAP_OB(op->map, op->x, op->y);tmp!=NULL;tmp=tmp->above) {
  if (tmp==tmp->below) /* if we have a map loop, exit */   if (tmp == op) continue;    /* Can't apply yourself */
      break;  
    /* Slow down creatures moving over rough terrain */
  if(QUERY_FLAG(tmp,FLAG_SLOW_MOVE)&&!QUERY_FLAG(op,FLAG_FLYING)) {   if(QUERY_FLAG(tmp,FLAG_SLOW_MOVE)&&!QUERY_FLAG(op,FLAG_FLYING)) {
      float diff;       float diff;
   
Line 1906
 
Line 1737
      move_apply_func (tmp, op, originator);       move_apply_func (tmp, op, originator);
             if (was_destroyed (op, tag))              if (was_destroyed (op, tag))
               return 1;                return 1;
        /* what the person/creature stepped onto has moved the object
         * someplace new.  Don't process any further - if we did,
         * have a feeling strange problems would result.
         */
        if (op->map != m || op->x != x || op->y != y) return 0;
  }   }
     }      }
     return 0;      return 0;
Line 1923
 
Line 1759
     LOG(llevError,"Present_arch called outside map.\n");      LOG(llevError,"Present_arch called outside map.\n");
     return NULL;      return NULL;
   }    }
   for(tmp=get_map_ob(m,x,y); tmp != NULL; tmp = tmp->above)    for(tmp=GET_MAP_OB(m,x,y); tmp != NULL; tmp = tmp->above)
     if(tmp->arch == at)      if(tmp->arch == at)
       return tmp;        return tmp;
   return NULL;    return NULL;
Line 1941
 
Line 1777
     LOG(llevError,"Present called outside map.\n");      LOG(llevError,"Present called outside map.\n");
     return NULL;      return NULL;
   }    }
   for(tmp=get_map_ob(m,x,y);tmp!=NULL;tmp=tmp->above)    for(tmp=GET_MAP_OB(m,x,y);tmp!=NULL;tmp=tmp->above)
     if(tmp->type==type)      if(tmp->type==type)
       return tmp;        return tmp;
   return NULL;    return NULL;
Line 2057
 
Line 1893
     if(wall(m, x+freearr_x[i],y+freearr_y[i]))      if(wall(m, x+freearr_x[i],y+freearr_y[i]))
       max=maxfree[i];        max=maxfree[i];
     else {      else {
       tmp=get_map_ob(m,x+freearr_x[i],y+freearr_y[i]);        tmp=GET_MAP_OB(m,x+freearr_x[i],y+freearr_y[i]);
       while(tmp!=NULL && ((tmp!=NULL&&!QUERY_FLAG(tmp,FLAG_MONSTER)&&        while(tmp!=NULL && ((tmp!=NULL&&!QUERY_FLAG(tmp,FLAG_MONSTER)&&
  tmp->type!=PLAYER) || (tmp == exclude ||    tmp->type!=PLAYER) || (tmp == exclude ||
  (tmp->head && tmp->head == exclude))))   (tmp->head && tmp->head == exclude))))


Legend:
line(s) removed in v.1.31 
line(s) changed
 line(s) added in v.1.32

File made using version 1.98 of cvs2html by leaf at 2011-07-21 17:15