Difference for server/attack.c from version 1.17 to 1.18


version 1.17 version 1.18
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_attack_c =   * static char *rcsid_attack_c =
  *   "$Id: attack.c,v 1.17 2000/10/31 12:04:58 peterm Exp $";   *   "$Id: attack.c,v 1.18 2000/11/06 23:06:47 jec Exp $";
  */   */
 /*  /*
     CrossFire, A Multiplayer game for X-windows      CrossFire, A Multiplayer game for X-windows
Line 86
 
Line 86
  * calling cancellation, etc.)   * calling cancellation, etc.)
  */   */
   
 void save_throw_object(object *op, int type) {  void save_throw_object (object *op, int type, object *originator)
   {
     if (!did_make_save_item(op, type)) {      if ( ! did_make_save_item (op, type))
       {
  object *env=op->env;   object *env=op->env;
  int x=op->x,y=op->y;   int x=op->x,y=op->y;
  mapstruct *m=op->map;   mapstruct *m=op->map;
   
           op = stop_item (op);
           if (op == NULL)
               return;
   
  /* Hacked the following so that type LIGHTER will work.    /* Hacked the following so that type LIGHTER will work.
  * Also, objects which are potenital "lights" that are hit by    * Also, objects which are potenital "lights" that are hit by
  * flame/elect attacks will be set to glow. "lights" are any    * flame/elect attacks will be set to glow. "lights" are any
Line 105
 
Line 110
            &&op->other_arch&&op->glow_radius) {              &&op->other_arch&&op->glow_radius) {
  char *arch=op->other_arch->name;   char *arch=op->other_arch->name;
   
  decrease_ob_nr(op,1);   op = decrease_ob_nr (op, 1);
                   if (op)
                       fix_stopped_item (op, m, originator);
  if((op = get_archetype(arch))!=NULL) {   if((op = get_archetype(arch))!=NULL) {
                    if(env) {                       if(env) { 
  op->x=env->x,op->y=env->y;   op->x=env->x,op->y=env->y;
Line 114
 
Line 121
      esrv_send_item(env, op);       esrv_send_item(env, op);
                    } else {                      } else {
                       op->x=x,op->y=y;                        op->x=x,op->y=y;
                       insert_ob_in_map(op,m,NULL);                        insert_ob_in_map(op,m,originator);
     }      }
  }   }
  return;   return;
         }          }
         if(type&AT_CANCELLATION) {          /* Cancellation. */          if(type&AT_CANCELLATION) {          /* Cancellation. */
               cancellation(op);                cancellation(op);
                 fix_stopped_item (op, m, originator);
               return;                  return; 
         }          }
  if(op->nrof>1)   if(op->nrof>1) {
        decrease_ob_nr(op,RANDOM()%op->nrof);         op = decrease_ob_nr(op,RANDOM()%op->nrof);
  else {                if (op)
                     fix_stopped_item (op, m, originator);
    } else {
      if (op->env) {       if (op->env) {
  object *tmp= is_player_inv(op->env);   object *tmp= is_player_inv(op->env);
   
Line 134
 
Line 144
      esrv_update_item(UPD_WEIGHT, tmp, tmp);       esrv_update_item(UPD_WEIGHT, tmp, tmp);
  }   }
      }       }
        if ( ! QUERY_FLAG (op, FLAG_REMOVED))
      remove_ob(op);       remove_ob(op);
      free_object(op);       free_object(op);
  }   }
Line 144
 
Line 155
                 insert_ob_in_ob(op,env);                  insert_ob_in_ob(op,env);
        } else {          } else {
  op->x=x,op->y=y;   op->x=x,op->y=y;
         insert_ob_in_map(op,m,NULL);          insert_ob_in_map(op,m,originator);
        }         }
  }   }
  return;   return;
Line 155
 
Line 166
         archetype *at = find_archetype("icecube");          archetype *at = find_archetype("icecube");
         if (at == NULL)          if (at == NULL)
           return;            return;
           op = stop_item (op);
           if (op == NULL)
               return;
         if ((tmp = present_arch(at,op->map,op->x,op->y)) == NULL) {          if ((tmp = present_arch(at,op->map,op->x,op->y)) == NULL) {
           tmp = arch_to_object(at);            tmp = arch_to_object(at);
           tmp->x=op->x,tmp->y=op->y;            tmp->x=op->x,tmp->y=op->y;
           insert_ob_in_map(tmp,op->map,NULL);            insert_ob_in_map(tmp,op->map,originator);
         }          }
           if ( ! QUERY_FLAG (op, FLAG_REMOVED))
         remove_ob(op);          remove_ob(op);
         (void) insert_ob_in_ob(op,tmp);          (void) insert_ob_in_ob(op,tmp);
         return;          return;
Line 178
 
Line 193
     return 0;      return 0;
   }    }
      
     if (QUERY_FLAG (op, FLAG_REMOVED) || op->env != NULL) {
       LOG (llevError, "BUG: hit_map(): hitter (arch %s, name %s) not on a map\n",
            op->arch->name, op->name);
       return 0;
     }
   
   if (op->head) op=op->head;    if (op->head) op=op->head;
   
   op_tag = op->count;    op_tag = op->count;
Line 232
 
Line 253
       next_tag = next->count;        next_tag = next->count;
   
     if (QUERY_FLAG (tmp, FLAG_FREED)) {      if (QUERY_FLAG (tmp, FLAG_FREED)) {
  LOG (llevError, "BUG: hit_map(): found free object\n");   LOG (llevError, "BUG: hit_map(): found freed object\n");
  break;   break;
     }      }
   
Line 248
 
Line 269
       if (was_destroyed (op, op_tag))        if (was_destroyed (op, op_tag))
         break;          break;
     } else if (tmp->material) {      } else if (tmp->material) {
       save_throw_object(tmp,type);        save_throw_object(tmp,type,op);
         if (was_destroyed (op, op_tag))
           break;
     }      }
   }    }
 #ifdef NO_CONE_PROPOGATE  #ifdef NO_CONE_PROPOGATE
Line 308
 
Line 331
   return &messages;    return &messages;
 }  }
   
 /*  
  * attack_ob() returns 1 on a hit, and 0 on a miss.  static int get_attack_mode (object **target, object **hitter,
  * op is what is being attacked, hitter is what is hitting (Arrow, player,   int *simple_attack)
  * whatever)  {
       if (QUERY_FLAG (*target, FLAG_FREED) || QUERY_FLAG (*hitter, FLAG_FREED)) {
           LOG (llevError, "BUG: get_attack_mode(): freed object\n");
           return 1;
       }
       if ((*target)->head)
           *target = (*target)->head;
       if ((*hitter)->head)
           *hitter = (*hitter)->head;
       if ((*hitter)->env != NULL || (*target)->env != NULL) {
           *simple_attack = 1;
           return 0;
       }
       if (QUERY_FLAG (*target, FLAG_REMOVED)
           || QUERY_FLAG (*hitter, FLAG_REMOVED)
           || (*hitter)->map == NULL || (*hitter)->map != (*target)->map)
       {
           LOG (llevError, "BUG: hitter (arch %s, name %s) with no relation to "
                "target\n", (*hitter)->arch->name, (*hitter)->name);
           return 1;
       }
       *simple_attack = 0;
       return 0;
   }
   
   static int abort_attack (object *target, object *hitter, int simple_attack)
   {
   /* Check if target and hitter are still in a relation similar to the one
    * determined by get_attack_mode().  Returns true if the relation has changed.
  */   */
       int new_mode;
   
       if (hitter->env == target || target->env == hitter)
           new_mode = 1;
       else if (QUERY_FLAG (hitter, FLAG_REMOVED)
                || QUERY_FLAG (target, FLAG_REMOVED)
                || hitter->map == NULL || hitter->map != target->map)
           return 1;
       else
           new_mode = 0;
       return new_mode != simple_attack;
   }
   
 int attack_ob(object *op,object *hitter) {  static void thrown_item_effect (object *, object *);
     int roll,dam=0;  
   static int attack_ob_simple (object *op, object *hitter, int base_dam,
    int base_wc)
   {
       int simple_attack, roll, dam=0;
     char buf[MAX_BUF];      char buf[MAX_BUF];
     uint32 type;      uint32 type;
     att_msg *msg;      att_msg *msg;
     char *op_name;      char *op_name = NULL;
     signed char luck=0;      signed char luck=0;
       tag_t op_tag, hitter_tag;
   
     if(op->head!=NULL)      if (get_attack_mode (&op, &hitter, &simple_attack))
  op=op->head;          goto error;
     if(op->name==NULL) {  
  if(settings.debug >= llevDebug) {  
      dump_object(op);  
      LOG(llevDebug,"Object without name tried to attack.\n%s\n",errmsg);  
      /* we don't NEED to print this a zillion times, so GIVE IT A NAME. */  
      op->name = add_string(op->arch->name);  
            
  }      op_tag = op->count;
  if (QUERY_FLAG(op, FLAG_REMOVED) && !QUERY_FLAG(op, FLAG_FREED))      hitter_tag = hitter->count;
      free_object(op);  
  return 1;  
     }  
   
     /*      /*
      * A little check to make it more difficult to dance forward and back       * A little check to make it more difficult to dance forward and back
      * to avoid ever being hit by monsters.       * to avoid ever being hit by monsters.
      */       */
     if (QUERY_FLAG(op, FLAG_MONSTER) && op->speed_left > -(FABS(op->speed))*0.3) {      if ( ! simple_attack && QUERY_FLAG (op, FLAG_MONSTER)
           && op->speed_left > -(FABS(op->speed))*0.3)
       {
  /* Decrease speed BEFORE calling process_object.  Otherwise, an   /* Decrease speed BEFORE calling process_object.  Otherwise, an
  * infinite loop occurs, with process_object calling move_monster,   * infinite loop occurs, with process_object calling move_monster,
  * which then gets here again.  By decreasing the speed before   * which then gets here again.  By decreasing the speed before
Line 350
 
Line 410
  */   */
  op->speed_left--;   op->speed_left--;
  process_object(op);   process_object(op);
  if (QUERY_FLAG(op, FLAG_FREED))   if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag)
  return 1;              || abort_attack (op, hitter, simple_attack))
    goto error;
     }      }
   
     add_refcount(op_name = op->name);      add_refcount(op_name = op->name);
     if(hitter->head!=NULL)  
  hitter=hitter->head;  
   
     if (hitter->name==NULL) {  
  if(settings.debug >= llevDebug) {  
      dump_object(hitter);  
      LOG(llevDebug,"Object without name tried to attack.\n%s\n",errmsg);  
  }  
  return 1;  
     }  
   
     /*  BROKEN:  the luck code.  If you look carefully, luck has these effects:      /*  BROKEN:  the luck code.  If you look carefully, luck has these effects:
  positive luck adds to the damage YOU take and to YOUR likelihood   positive luck adds to the damage YOU take and to YOUR likelihood
Line 382
 
Line 433
  roll=RANDOM()%20+1+luck;   roll=RANDOM()%20+1+luck;
   
     /* Adjust roll for various situations. */      /* Adjust roll for various situations. */
       if ( ! simple_attack)
     roll += adj_attackroll(hitter,op);       roll += adj_attackroll(hitter,op);
   
     /* See if we hit the creature */      /* See if we hit the creature */
     if(roll==(20+luck)||op->stats.ac>=hitter->stats.wc-roll) {      if(roll==(20+luck)||op->stats.ac>=base_wc-roll) {
  int hitdam=hitter->stats.dam+luck;   int hitdam = base_dam + luck;
 #ifdef CASTING_TIME  #ifdef CASTING_TIME
  if ((hitter->type == PLAYER)&&(hitter->casting > -1)){   if ((hitter->type == PLAYER)&&(hitter->casting > -1)){
      hitter->casting = -1;       hitter->casting = -1;
Line 399
 
Line 451
      if (op->type == PLAYER)  {       if (op->type == PLAYER)  {
  new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost your spell!");   new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost your spell!");
  new_draw_info_format(NDI_ALL|NDI_UNIQUE,5,NULL,   new_draw_info_format(NDI_ALL|NDI_UNIQUE,5,NULL,
      "%s was hit by %s and lost a spell.",op->name,hitter->name);       "%s was hit by %s and lost a spell.",op_name,hitter->name);
      }       }
  }   }
 #endif  #endif
    if ( ! simple_attack)
           {
  /* If you hit something, the victim should *always* wake up.   /* If you hit something, the victim should *always* wake up.
  * Before, invisible hitters could avoid doing this.    * Before, invisible hitters could avoid doing this.
  * -b.t. */   * -b.t. */
  if(QUERY_FLAG(op,FLAG_SLEEP)) CLEAR_FLAG(op,FLAG_SLEEP);              if (QUERY_FLAG (op, FLAG_SLEEP))
                   CLEAR_FLAG(op,FLAG_SLEEP);
   
  /* If the victim can't see the attacker, it may alert others   /* If the victim can't see the attacker, it may alert others
  * for help. */   * for help. */
Line 417
 
Line 472
  /* if you were hidden and hit by a creature, you are discovered*/   /* if you were hidden and hit by a creature, you are discovered*/
  if(op->hide && QUERY_FLAG(hitter,FLAG_ALIVE)) {   if(op->hide && QUERY_FLAG(hitter,FLAG_ALIVE)) {
      make_visible(op);       make_visible(op);
      if(op->type==PLAYER) new_draw_info(NDI_UNIQUE, 0,op,                  if (op->type == PLAYER)
  "You were hit by a wild attack. You are no longer hidden!");                      new_draw_info (NDI_UNIQUE, 0, op,
                                      "You were hit by a wild attack. "
                                      "You are no longer hidden!");
  }   }
   
  /* thrown items (hitter) will have various effects   /* thrown items (hitter) will have various effects
Line 426
 
Line 483
  * this sets 'hitter' to the actual dagger, and not the   * this sets 'hitter' to the actual dagger, and not the
  * wrapper object.   * wrapper object.
  */   */
  if((hitter=thrown_item_effect(hitter,op))==NULL) goto leave;              thrown_item_effect (hitter, op);
               if (was_destroyed (hitter, hitter_tag)
                   || was_destroyed (op, op_tag)
                   || abort_attack (op, hitter, simple_attack))
                   goto leave;
           }
   
  /* Need to do at least 1 damage, otherwise there is no point   /* Need to do at least 1 damage, otherwise there is no point
  * to go further and it will cause FPE's below.   * to go further and it will cause FPE's below.
Line 436
 
Line 498
  type=hitter->attacktype;   type=hitter->attacktype;
  if(!type) type=AT_PHYSICAL;   if(!type) type=AT_PHYSICAL;
  /* Handle monsters that hit back */   /* Handle monsters that hit back */
  if (QUERY_FLAG(op, FLAG_HITBACK) && QUERY_FLAG(hitter, FLAG_ALIVE)) {   if ( ! simple_attack && QUERY_FLAG (op, FLAG_HITBACK)
        && QUERY_FLAG (hitter, FLAG_ALIVE))
    {
      if (op->attacktype & AT_ACID && hitter->type==PLAYER)       if (op->attacktype & AT_ACID && hitter->type==PLAYER)
  new_draw_info(NDI_UNIQUE, 0,hitter,"You are splashed by acid!\n");   new_draw_info(NDI_UNIQUE, 0,hitter,"You are splashed by acid!\n");
      hit_player(hitter, RANDOM()%(op->stats.dam+1), op, op->attacktype);       hit_player(hitter, RANDOM()%(op->stats.dam+1), op, op->attacktype);
      if (QUERY_FLAG(op, FLAG_FREED)) goto leave;       if (was_destroyed (op, op_tag)
                   || was_destroyed (hitter, hitter_tag)
                   || abort_attack (op, hitter, simple_attack))
                   goto leave;
  }   }
   
  /* In the new attack code, it should handle multiple attack   /* In the new attack code, it should handle multiple attack
  * types in its area, so remove it from here.   * types in its area, so remove it from here.
  */   */
  dam=hit_player(op, (RANDOM()%hitdam)+1, hitter, type);   dam=hit_player(op, (RANDOM()%hitdam)+1, hitter, type);
  if (QUERY_FLAG(op, FLAG_FREED))   if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag)
               || abort_attack (op, hitter, simple_attack))
      goto leave;       goto leave;
     } /* end of if hitter hit op */      } /* end of if hitter hit op */
     /* if we missed, dam=0 */      /* if we missed, dam=0 */
Line 492
 
Line 560
  new_draw_info(NDI_BLACK, 0, hitter->owner, buf);   new_draw_info(NDI_BLACK, 0, hitter->owner, buf);
     }      }
   
       goto leave;
   
     error:
       dam = 1;
       goto leave;
   
 leave:  leave:
       if (op_name)
     free_string(op_name);      free_string(op_name);
     return dam;      return dam;
 }  }
   
   int attack_ob (object *op, object *hitter)
   {
       if (hitter->head)
           hitter = hitter->head;
       return attack_ob_simple (op, hitter, hitter->stats.dam, hitter->stats.wc);
   }
   
   /* op is the arrow, tmp is what is stopping the arrow.
    *
    * Returns 1 if op was inserted into tmp's inventory, 0 otherwise.
    */
   static int stick_arrow (object *op, object *tmp)
   {
       /* If the missile hit a player, we insert it in their inventory.
        * However, if the missile is heavy, we don't do so (assume it falls
        * to the ground after a hit).  What a good value for this is up to
        * debate - 5000 is 5 kg, so arrows, knives, and other light weapons
        * stick around.
        */
       if (op->weight <= 5000 && tmp->stats.hp >= 0) {
    if(tmp->head != NULL)
        tmp = tmp->head;
           remove_ob (op);
    op = insert_ob_in_ob(op,tmp);
    if (tmp->type== PLAYER)
        esrv_send_item (tmp, op);
           return 1;
       } else
    return 0;
   }
   
   /* hit_with_arrow() disassembles the missile, attacks the victim and
    * reassembles the missile.
    *
    * It returns a pointer to the reassembled missile, or NULL if the missile
    * isn't available anymore.
    */
   object *hit_with_arrow (object *op, object *victim)
   {
       object *container, *hitter;
       int hit_something;
       tag_t victim_tag, hitter_tag;
       sint16 victim_x, victim_y;
   
       /* Disassemble missile */
       if (op->inv) {
           container = op;
           hitter = op->inv;
           remove_ob (hitter);
           insert_ob_in_map_simple (hitter, container->map);
           /* Note that we now have an empty THROWN_OBJ on the map.  Code that
            * might be called until this THROWN_OBJ is either reassembled or
            * removed at the end of this function must be able to deal with empty
            * THROWN_OBJs. */
       } else {
           container = NULL;
           hitter = op;
       }
   
       /* Try to hit victim */
       victim_x = victim->x;
       victim_y = victim->y;
       victim_tag = victim->count;
       hitter_tag = hitter->count;
       hit_something = attack_ob_simple (victim, hitter, op->stats.dam,
                                         op->stats.wc);
       /* Arrow attacks door, rune of summoning is triggered, demon is put on
        * arrow, move_apply() calls this function, arrow sticks in demon,
        * attack_ob_simple() returns, and we've got an arrow that still exists
        * but is no longer on the map. Ugh. (Beware: Such things can happen at
        * other places as well!) */
       if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) {
           if (container) {
               remove_ob (container);
               free_object (container);
           }
           return NULL;
       }
   
       /* Missile hit victim */
       if (hit_something)
       {
           /* Stop arrow */
           if (container == NULL) {
               hitter = fix_stopped_arrow (hitter);
               if (hitter == NULL)
                   return NULL;
           } else {
               remove_ob (container);
               free_object (container);
           }
   
           /* Try to stick arrow into victim */
           if ( ! was_destroyed (victim, victim_tag)
                && stick_arrow (hitter, victim))
               return NULL;
   
           /* Else try to put arrow on victim's map square */
           if ((victim_x != hitter->x || victim_y != hitter->y)
               && ! wall (hitter->map, victim_x, victim_y))
           {
               remove_ob (hitter);
               hitter->x = victim_x;
               hitter->y = victim_y;
               insert_ob_in_map (hitter, hitter->map, hitter);
           } else {
               /* Else leave arrow where it is */
               merge_ob (hitter, NULL);
           }
           return NULL;
       }
   
       /* Missile missed victim - reassemble missile */
       if (container) {
           remove_ob (hitter);
           insert_ob_in_ob (hitter, container);
       }
       return op;
   }
   
   
 void tear_down_wall(object *op)  void tear_down_wall(object *op)
 {  {
     int perc=0;      int perc=0;
Line 743
 
Line 939
     char buf[MAX_BUF];      char buf[MAX_BUF];
     object *old_hitter=NULL; /* this is used in case of servant monsters */       object *old_hitter=NULL; /* this is used in case of servant monsters */
     int maxdam=0,ndam,attacktype=1,attacknum,magic=(type & AT_MAGIC);      int maxdam=0,ndam,attacktype=1,attacknum,magic=(type & AT_MAGIC);
     tag_t hitter_tag;      int body_attack = op && op->head;   /* Did we hit op's head? */
       int simple_attack;
       tag_t op_tag, hitter_tag;
   
     if (QUERY_FLAG (op, FLAG_FREED) || QUERY_FLAG (hitter, FLAG_FREED)) {      if (get_attack_mode (&op, &hitter, &simple_attack))
         LOG (llevError, "BUG: hit_player(): freed object\n");  
         return 0;          return 0;
     }  
     hitter_tag = hitter->count;  
   
     if(op->head!=NULL) {      if (QUERY_FLAG (op, FLAG_WIZ))
  if(op->head==op) {  
      LOG(llevError,"Recursive head error!\n");  
      return 0;       return 0;
  }  
 #if 0      op_tag = op->count;
  /* To paralyze/slow a creature, we must hit its head with the attacktype.      hitter_tag = hitter->count;
  * If we are going to do this, this should probably be expanded.  
  */      if (body_attack) {
  if(type&AT_PARALYZE || type&AT_SLOW)  
      return 0;  
 #else  
  /* slow and paralyze must hit the head.  But we don't want to just   /* slow and paralyze must hit the head.  But we don't want to just
  * return - we still need to process other attacks the spell still   * return - we still need to process other attacks the spell still
  * might have.  So just remove the paralyze and slow attacktypes,   * might have.  So just remove the paralyze and slow attacktypes,
Line 776
 
Line 966
      type &= ~(AT_PARALYZE | AT_SLOW);       type &= ~(AT_PARALYZE | AT_SLOW);
      if (!type || type==AT_MAGIC) return 0;       if (!type || type==AT_MAGIC) return 0;
  }   }
 #endif  
  op=op->head;  
     }      }
   
     if(op->type==DOOR && op->inv && op->inv->type==RUNE) {      if ( ! simple_attack && op->type == DOOR) {
  spring_trap(op->inv,hitter);          object *tmp;
         if (was_destroyed (hitter, hitter_tag))          for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
               if (tmp->type == RUNE) {
                   spring_trap (tmp, hitter);
                   if (was_destroyed (hitter, hitter_tag)
                       || was_destroyed (op, op_tag)
                       || abort_attack (op, hitter, simple_attack))
             return 0;              return 0;
                   break;
               }
     }      }
   
     /* If its already dead, or we're the wizard, don't attack it - no point */      if ( ! QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) {
     if(QUERY_FLAG(op,FLAG_WIZ)||!QUERY_FLAG(op,FLAG_ALIVE)||op->stats.hp<0)          /* FIXME: If a player is killed by a rune in a door, the
            * was_destroyed() check above doesn't return, and might get here.
            */
           LOG (llevDebug, "victim (arch %s, name %s) already dead in "
                "hit_player()\n", op->arch->name, op->name);
  return 0;   return 0;
       }
   
 #ifdef ATTACK_DEBUG  #ifdef ATTACK_DEBUG
     LOG(llevDebug,"hit player: attacktype %d, dam %d\n", type, dam);      LOG(llevDebug,"hit player: attacktype %d, dam %d\n", type, dam);
Line 1212
 
Line 1412
     if((tmp=present(PARAIMAGE,op->map,op->x,op->y))==NULL) {      if((tmp=present(PARAIMAGE,op->map,op->x,op->y))==NULL) {
       tmp=clone_arch(PARAIMAGE);        tmp=clone_arch(PARAIMAGE);
       tmp->x=op->x,tmp->y=op->y;        tmp->x=op->x,tmp->y=op->y;
       insert_ob_in_map(tmp,op->map,NULL);        /* We can't use insert_ob_in_map() (which can trigger various things)
          * unless a lot of was_destroyed() checks are added in our callers.
          * But this is just a simple visual effect anyway.
          */
         insert_ob_in_map_simple(tmp,op->map);
     }      }
     op->speed_left-=(float)FABS(op->speed)*(dam*3);      op->speed_left-=(float)FABS(op->speed)*(dam*3);
     tmp->stats.food+=(signed short) (dam*3)/op->speed;      tmp->stats.food+=(signed short) (dam*3)/op->speed;
Line 1274
 
Line 1478
   
 /* thrown_item_effect() - handles any special effects of thrown  /* thrown_item_effect() - handles any special effects of thrown
  * items (like attacking living creatures--a potion thrown at a   * items (like attacking living creatures--a potion thrown at a
  * monster). We return the hitter item for further   * monster).
  * possible (ie physical) attacks. Other posibilities  
  * include spilling containers, and lighting stuff on fire  
  * with thrown torches.  
  */   */
 object *thrown_item_effect( object *hitter, object *victim) {  static void thrown_item_effect (object *hitter, object *victim)
   object *tmp=hitter;  {
      tag_t tag = hitter->count;
   if(hitter->type==THROWN_OBJ) tmp = hitter->inv;  
   if(!tmp) return hitter;  
    
   if(!QUERY_FLAG(hitter,FLAG_ALIVE)) {    if(!QUERY_FLAG(hitter,FLAG_ALIVE)) {
     switch (tmp->type) {      switch (hitter->type) {
       case POTION:        case POTION:
         if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD)          if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD)
    &&!(victim->immune&AT_MAGIC)) (void) apply_potion(victim,tmp);     &&!(victim->immune&AT_MAGIC)) (void) apply_potion(victim,hitter);
         break;          break;
       case FOOD:        case FOOD:
  /* cursed food is (often) poisonous....but it won't 'explode'   /* cursed food is (often) poisonous....but it won't 'explode'
Line 1299
 
Line 1498
         break;          break;
       case POISON: /* poison drinks */        case POISON: /* poison drinks */
         if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD)          if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD)
    &&!(victim->immune&AT_POISON)) apply_poison(victim,tmp);     &&!(victim->immune&AT_POISON)) apply_poison(victim,hitter);
         break;          break;
       case CONTAINER:         case CONTAINER:
         /* spill_container(victim,RANDOM()%(hitter->stats.dam+1)); */          /* spill_container(victim,RANDOM()%(hitter->stats.dam+1)); */
         break;          break;
       default:  
         break;  
     }      }
 #if 0  
     /* glow objects (torches) are on fire.. */  
     if(!tmp->type&&tmp->glow_radius>0) {  
     }      }
 #endif  
   }  
    
   return tmp;  
 }  }
   
 /* adj_attackroll() - adjustments to attacks by various conditions */  /* adj_attackroll() - adjustments to attacks by various conditions */
Line 1324
 
Line 1514
   int adjust=0;    int adjust=0;
   
   /* safety */    /* safety */
   if(!target||!hitter||!hitter->map||!target->map||hitter->map!=target->map)    if(!target||!hitter||!hitter->map||!target->map||hitter->map!=target->map) {
       LOG (llevError, "BUG: adj_attackroll(): hitter and target not on same "
            "map\n");
     return 0;      return 0;
     }
   
   /* aimed missiles use the owning object's sight */    /* aimed missiles use the owning object's sight */
   if(is_aimed_missile(hitter)) {    if(is_aimed_missile(hitter)) {


Legend:
line(s) removed in v.1.17 
line(s) changed
 line(s) added in v.1.18

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