Difference for server/spell_effect.c from version 1.89 to 1.90


version 1.89 version 1.90
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_spell_effect_c =   * static char *rcsid_spell_effect_c =
  *   "$Id: spell_effect.c,v 1.89 2003/01/05 23:50:15 mwedel Exp $";   *   "$Id: spell_effect.c,v 1.90 2003/01/08 08:39:21 mwedel Exp $";
  */   */
   
   
Line 68
 
Line 68
     {       {
  object *tmp;   object *tmp;
  /* Safety check to make sure we don't get any mana storms in scorn */   /* Safety check to make sure we don't get any mana storms in scorn */
  if (blocks_magic(op->map, op->x, op->y)) {   if (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL) & P_NO_MAGIC) {
      new_draw_info(NDI_UNIQUE, 0, op, "The magic warps and you are turned inside out!");       new_draw_info(NDI_UNIQUE, 0, op, "The magic warps and you are turned inside out!");
      hit_player(tmp,9998,op,AT_INTERNAL);       hit_player(tmp,9998,op,AT_INTERNAL);
   
Line 447
 
Line 447
   
 int cast_polymorph(object *op, int dir) {  int cast_polymorph(object *op, int dir) {
     object *tmp, *next;      object *tmp, *next;
     int range;      int range, mflags;
     archetype *poly;      archetype *poly;
       mapstruct *m;
   
     if(dir == 0)      if(dir == 0)
  return 0;   return 0;
Line 456
 
Line 457
     poly = find_archetype("polymorph");      poly = find_archetype("polymorph");
     /* Range is until it hits a wall */      /* Range is until it hits a wall */
     for(range = 1;;range++) {      for(range = 1;;range++) {
  int x=op->x+freearr_x[dir]*range,y=op->y+freearr_y[dir]*range;   sint16 x=op->x+freearr_x[dir]*range,y=op->y+freearr_y[dir]*range;
  object *image;   object *image;
   
  if(wall(op->map,x,y) || blocks_magic(op->map,x,y))   m = op->map;
    mflags = get_map_flags(m, &m, x, y, &x, &y);
   
    if (mflags & (P_WALL | P_NO_MAGIC))
      break;       break;
   
  /* Get the top most object */   /* Get the top most object */
  for(tmp = get_map_ob(op->map,x,y); tmp != NULL && tmp->above != NULL;   for(tmp = get_map_ob(m,x,y); tmp != NULL && tmp->above != NULL;
      tmp = tmp->above);       tmp = tmp->above);
   
  /* Now start polymorphing the objects, top down */   /* Now start polymorphing the objects, top down */
Line 481
 
Line 485
  */   */
  image->stats.food += range;   image->stats.food += range;
  image->speed_left = 0.1;   image->speed_left = 0.1;
  insert_ob_in_map(image,op->map,op,0);   insert_ob_in_map(image,m,op,0);
     }      }
     return 1;      return 1;
 }  }
Line 552
 
Line 556
      
 int cast_speedball(object *op, int dir, int type) {  int cast_speedball(object *op, int dir, int type) {
   object *spb;    object *spb;
   if(blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]))      mapstruct *m;
       sint16 x, y;
   
       x = op->x+freearr_x[dir];
       y = op->y+freearr_y[dir];
       m = op->map;
   
       if (get_map_flags(m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_BLOCKED))
     return 0;      return 0;
   
   spb=clone_arch(SPEEDBALL);    spb=clone_arch(SPEEDBALL);
   spb->x=op->x+freearr_x[dir],spb->y=op->y+freearr_y[dir];      spb->x = x;
       spb->y = y;
   
   spb->speed_left= -0.1;    spb->speed_left= -0.1;
   if(type==SP_LARGE_SPEEDBALL)    if(type==SP_LARGE_SPEEDBALL)
     spb->stats.dam=30;      spb->stats.dam=30;
   insert_ob_in_map(spb,op->map,op,0);  
       insert_ob_in_map(spb,m,op,0);
   return 1;    return 1;
 }  }
   
 int probe(object *op, int dir) {  int probe(object *op, int dir) {
   int r;      int r, mflags;
   object *tmp;    object *tmp;
       mapstruct *m;
   
   
   if(!dir) {    if(!dir) {
     examine_monster(op,op);      examine_monster(op,op);
     return 1;      return 1;
   }    }
   for(r=1;;r++) {    for(r=1;;r++) {
     int x=op->x+r*freearr_x[dir],y=op->y+r*freearr_y[dir];   sint16 x=op->x+r*freearr_x[dir],y=op->y+r*freearr_y[dir];
     if(out_of_map(op->map,x,y))  
       break;   m = op->map;
     if(blocks_magic(op->map,x,y)) {   mflags = get_map_flags(m, &m, x, y, &x, &y);
   
    if (mflags & P_OUT_OF_MAP) break;
   
    if (mflags & P_NO_MAGIC) {
       new_draw_info(NDI_UNIQUE, 0,op,"Something blocks your magic.");        new_draw_info(NDI_UNIQUE, 0,op,"Something blocks your magic.");
       return 0;        return 0;
     }      }
     for(tmp=get_map_ob(op->map,x,y);tmp!=NULL;tmp=tmp->above)   if (mflags & P_IS_ALIVE) {
        for(tmp=get_map_ob(m,x,y);tmp!=NULL;tmp=tmp->above)
       if(QUERY_FLAG(tmp, FLAG_ALIVE)&&(tmp->type==PLAYER||QUERY_FLAG(tmp, FLAG_MONSTER))) {        if(QUERY_FLAG(tmp, FLAG_ALIVE)&&(tmp->type==PLAYER||QUERY_FLAG(tmp, FLAG_MONSTER))) {
         new_draw_info(NDI_UNIQUE, 0,op,"You detect something.");          new_draw_info(NDI_UNIQUE, 0,op,"You detect something.");
         if(tmp->head!=NULL)          if(tmp->head!=NULL)
Line 588
 
Line 610
         return 1;          return 1;
       }        }
   }    }
       }
   new_draw_info(NDI_UNIQUE, 0,op,"You detect nothing.");    new_draw_info(NDI_UNIQUE, 0,op,"You detect nothing.");
   return 1;    return 1;
 }  }
Line 667
 
Line 690
   return 1;    return 1;
 }  }
   
 /* puts a 'WORD_OF_RECALL_' object in player */  /* puts a 'WORD_OF_RECALL_' object in player
 /* modified to work faster for higher level casters -- DAMN */   * modified to work faster for higher level casters -- DAMN
    */
 int cast_wor(object *op, object *caster) {  int cast_wor(object *op, object *caster) {
   object *dummy;    object *dummy;
   
   if(op->type!=PLAYER)    if(op->type!=PLAYER)
     return 0;      return 0;
   if(blocks_magic(op->map,op->x,op->y)) {  
       if(get_map_flags(op->map,NULL, op->x,op->y, NULL, NULL) & P_NO_CLERIC) {
     new_draw_info(NDI_UNIQUE, 0,op,"Something blocks your spell.");      new_draw_info(NDI_UNIQUE, 0,op,"Something blocks your spell.");
     return 0;      return 0;
   }    }
Line 699
 
Line 724
      
   (void) insert_ob_in_ob(dummy,op);    (void) insert_ob_in_ob(dummy,op);
   new_draw_info(NDI_UNIQUE, 0,op,"You feel a force starting to build up inside you.");    new_draw_info(NDI_UNIQUE, 0,op,"You feel a force starting to build up inside you.");
   #if 0
   LOG(llevDebug,"Word of Recall for %s in %f ticks.\n", op->name,    LOG(llevDebug,"Word of Recall for %s in %f ticks.\n", op->name,
       ((-dummy->speed_left)/(dummy->speed==0?0.0001:dummy->speed)));        ((-dummy->speed_left)/(dummy->speed==0?0.0001:dummy->speed)));
   LOG(llevDebug,"Word of Recall for player level %d, caster level %d: 0.002 * %d + %d\n",    LOG(llevDebug,"Word of Recall for player level %d, caster level %d: 0.002 * %d + %d\n",
       SK_level(op), SK_level(caster), SP_PARAMETERS[SP_WOR].bdur, SP_level_strength_adjust(op,caster,SP_WOR));        SK_level(op), SK_level(caster), SP_PARAMETERS[SP_WOR].bdur, SP_level_strength_adjust(op,caster,SP_WOR));
   #endif
   return 1;    return 1;
 }  }
   
Line 1032
 
Line 1059
 int magic_wall(object *op,object *caster,int dir,int spell_type) {  int magic_wall(object *op,object *caster,int dir,int spell_type) {
     object *tmp, *tmp2;        object *tmp, *tmp2; 
     int i,posblocked=0,negblocked=0;      int i,posblocked=0,negblocked=0;
       sint16 x, y;
       mapstruct *m;
   
   
     if(!dir) {      if(!dir) {
  new_draw_info(NDI_UNIQUE, 0,op,"In what direction?");   new_draw_info(NDI_UNIQUE, 0,op,"In what direction?");
  return 0;   return 0;
     }      }
     if(blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {      m = op->map;
       x = op->x+freearr_x[dir];
       y = op->y+freearr_y[dir];
   
       if (get_map_flags(m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_BLOCKED)) {
  new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way.");   new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way.");
  return 0;   return 0;
     }      }
Line 1127
 
Line 1161
      LOG(llevError,"Unimplemented magic_wall spell: %d\n",spell_type);       LOG(llevError,"Unimplemented magic_wall spell: %d\n",spell_type);
      return 0;       return 0;
     }      }
     tmp->x=op->x+freearr_x[dir],tmp->y=op->y+freearr_y[dir];      tmp->x = x;
     if ((tmp = insert_ob_in_map (tmp, op->map, op,0)) == NULL) {      tmp->y = y;
   
       if ((tmp = insert_ob_in_map (tmp, m, op,0)) == NULL) {
  new_draw_info(NDI_UNIQUE, 0,op,"Something destroys your wall");   new_draw_info(NDI_UNIQUE, 0,op,"Something destroys your wall");
  return 0;   return 0;
     }      }
   
   /*  This code causes the wall to extend to a distance of 5 in    /*  This code causes the wall to extend to a distance of 5 in
  each direction, or until an obstruction is encountered.        * each direction, or until an obstruction is encountered.
  posblocked and negblocked help determine how far the       * posblocked and negblocked help determine how far the
  created wall can extend, it won't go extend through       * created wall can extend, it won't go extend through
  blocked spaces.  */       * blocked spaces.
        */
   
     for(i=1;i<5;i++) {      for(i=1;i<5;i++) {
  int x,y,dir2;   int dir2;
    
  dir2 = (dir<4)?(dir+2):dir-2;   dir2 = (dir<4)?(dir+2):dir-2;
    
  x = tmp->x+i*freearr_x[dir2]; y = tmp->y+i*freearr_y[dir2];   x = tmp->x+i*freearr_x[dir2];
  if(!blocked(op->map,x,y)&&!posblocked) {   y = tmp->y+i*freearr_y[dir2];
   
    if(!(get_map_flags(m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_BLOCKED)) && !posblocked) {
  tmp2 = get_object();   tmp2 = get_object();
  copy_object(tmp,tmp2);   copy_object(tmp,tmp2);
  tmp2->x = x; tmp2->y = y;   tmp2->x = x; tmp2->y = y;
  insert_ob_in_map(tmp2,op->map,op,0);       insert_ob_in_map(tmp2,m,op,0);
  } else posblocked=1;   } else posblocked=1;
  x = tmp->x-i*freearr_x[dir2]; y = tmp->y-i*freearr_y[dir2];  
  if(!blocked(op->map,x,y)&&!negblocked) {   x = tmp->x-i*freearr_x[dir2];
    y = tmp->y-i*freearr_y[dir2];
    m = tmp->map;
   
    if(!(get_map_flags(m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_BLOCKED)) && !negblocked) {
  tmp2 = get_object();   tmp2 = get_object();
  copy_object(tmp,tmp2);   copy_object(tmp,tmp2);
  tmp2->x = x; tmp2->y = y;   tmp2->x = x; tmp2->y = y;
  insert_ob_in_map(tmp2,op->map,op,0);       insert_ob_in_map(tmp2,m,op,0);
  } else negblocked=1;   } else negblocked=1;
     }  
   
       }
   
     if(QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))      if(QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))
  update_all_los(op->map, op->x, op->y);   update_all_los(op->map, op->x, op->y);
     if(op->type==PLAYER)  
  draw(op);      if(op->type!=PLAYER)
     else  
  SET_FLAG(op, FLAG_SCARED); /* We don't want them to walk through the wall! */   SET_FLAG(op, FLAG_SCARED); /* We don't want them to walk through the wall! */
     return 1;      return 1;
 }  }
Line 1176
 
Line 1218
   
 int cast_light(object *op,object *caster,int dir) {  int cast_light(object *op,object *caster,int dir) {
   object *target=NULL,*tmp=NULL;    object *target=NULL,*tmp=NULL;
   int x,y,dam=SP_PARAMETERS[SP_LIGHT].bdam          sint16  x,y;
                   +SP_level_dam_adjust(op,caster,SP_LIGHT);;      int     dam, mflags;
       mapstruct *m;
   
       dam = SP_PARAMETERS[SP_LIGHT].bdam + SP_level_dam_adjust(op,caster,SP_LIGHT);
   
   if(!dir) {    if(!dir) {
     new_draw_info(NDI_UNIQUE, 0,op,"In what direction?");      new_draw_info(NDI_UNIQUE, 0,op,"In what direction?");
     return 0;      return 0;
   }    }
   
   x=op->x+freearr_x[dir],y=op->y+freearr_y[dir];      x=op->x+freearr_x[dir];
       y=op->y+freearr_y[dir];
       m = op->map;
   
       mflags = get_map_flags(m, &m, x, y, &x, &y);
   
   if (!out_of_map(op->map,x,y)) {      if (!(mflags & P_OUT_OF_MAP) && (mflags & P_IS_ALIVE)) {
     for(target=get_map_ob(op->map,x,y);target;target=target->above)   for(target=get_map_ob(m,x,y);target;target=target->above)
      if(QUERY_FLAG(target,FLAG_MONSTER)) {       if(QUERY_FLAG(target,FLAG_MONSTER)) {
         /* coky doky. got a target monster. Lets make a blinding attack */   /* oky doky. got a target monster. Lets make a blinding attack */
          if(target->head) target = target->head;           if(target->head) target = target->head;
          (void) hit_player(target,dam,op,(AT_BLIND|AT_MAGIC));           (void) hit_player(target,dam,op,(AT_BLIND|AT_MAGIC));
          return 1; /* one success only! */           return 1; /* one success only! */
Line 1197
 
Line 1246
   }    }
   
   /* no live target, perhaps a wall is in the way? */    /* no live target, perhaps a wall is in the way? */
   if(blocked(op->map,x,y)) {      if(mflags & P_BLOCKED) {
       new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way.");        new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way.");
       return 0;        return 0;
   }    }
   
   /* ok, looks groovy to just insert a new light on the map */    /* ok, looks groovy to just insert a new light on the map */
   tmp=get_archetype("light");    tmp=get_archetype("light");
   if(!tmp) {     if(!tmp) {
Line 1211
 
Line 1261
               - (10*SP_level_strength_adjust(op,caster,SP_LIGHT)));                - (10*SP_level_strength_adjust(op,caster,SP_LIGHT)));
   if (tmp->speed < MIN_ACTIVE_SPEED) tmp->speed = MIN_ACTIVE_SPEED;    if (tmp->speed < MIN_ACTIVE_SPEED) tmp->speed = MIN_ACTIVE_SPEED;
   tmp->glow_radius=dam;    tmp->glow_radius=dam;
   tmp->x=x,tmp->y=y;      tmp->x=x;
   insert_ob_in_map(tmp,op->map,op,0);      tmp->y=y;
       insert_ob_in_map(tmp,m,op,0);
   if(op->type==PLAYER) draw(op);  
   return 1;    return 1;
 }  }
   
 int dimension_door(object *op,int dir) {  int dimension_door(object *op,int dir) {
     int dist;      int dist, maxdist;
   
     if(op->type!=PLAYER)      if(op->type!=PLAYER)
  return 0;   return 0;
Line 1229
 
Line 1278
  return 0;   return 0;
     }      }
   
       /* Given the new outdoor maps, can't let players dimension door for
        * ever, so put limits in.
        */
       maxdist = SP_PARAMETERS[SP_D_DOOR].bdur +
    SP_level_strength_adjust(op, op, SP_D_DOOR);
   
     if(op->contr->count) {      if(op->contr->count) {
    if (op->contr->count > maxdist) {
        new_draw_info(NDI_UNIQUE, 0, op, "You can't dimension door that far!");
        return 0;
    }
   
  for(dist=0;dist<op->contr->count; dist++)   for(dist=0;dist<op->contr->count; dist++)
      if (blocks_magic(op->map,op->x+freearr_x[dir]*(dist+1),       if (get_map_flags(op->map, NULL,
                              op->y+freearr_y[dir]*(dist+1))) break;   op->x+freearr_x[dir]*(dist+1), op->y+freearr_y[dir]*(dist+1),
    NULL, NULL) & P_NO_MAGIC) break;
   
  if(dist<op->contr->count) {   if(dist<op->contr->count) {
      new_draw_info(NDI_UNIQUE, 0,op,"Something blocks your magic.\n");       new_draw_info(NDI_UNIQUE, 0,op,"Something blocks the magic of the spell.\n");
      op->contr->count=0;       op->contr->count=0;
      return 0;       return 0;
  }   }
  op->contr->count=0;   op->contr->count=0;
   
  /* If the player is trying to dimension door to solid rock, choose   /* Remove code that puts player on random space on maps.  IMO,
  * a random place on the map to put the player.   * a lot of maps probably have areas the player should not get to,
  * Changed in 0.94.3 so that the player can not get put in   * but may not be marked as NO_MAGIC (as they may be bounded
  * a no magic spot.   * by such squares).  Also, there are probably treasure rooms and
  */   * lots of other maps that protect areas with no magic, but the
  if(blocked(op->map,op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist)){   * areas themselves don't contain no magic spaces.
      int x=rndm(0, MAP_WIDTH(op->map)-1),y=rndm(0, MAP_HEIGHT(op->map)-1);   */
    if(get_map_flags(op->map, NULL,
      if(blocked(op->map,x,y) || blocks_magic(op->map,x,y)) {       op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist,
        NULL, NULL) & P_BLOCKED) {
  new_draw_info(NDI_UNIQUE, 0,op,"You cast your spell, but nothing happens.\n");   new_draw_info(NDI_UNIQUE, 0,op,"You cast your spell, but nothing happens.\n");
  return 1; /* Maybe the penalty should be more severe... */   return 1; /* Maybe the penalty should be more severe... */
      }       }
       } else {
      remove_ob(op);   /* Player didn't specify a distance, so lets see how far
      op->x=x,op->y=y;   * we can move the player.  Don't know why this stopped on
      if ((op = insert_ob_in_map(op,op->map,op,0)) != NULL) {   * spaces that blocked the players view.
  /* I believe that currently, this will always be true as  
  * only players can use dimension door, but might as  
  * well be safe.  comment out call to draw - the main  
  * update loop will figure it out.  
  */   */
  if( op->type == PLAYER)  
      MapNewmapCmd(op->contr);   for(dist=1; dist <= maxdist; dist++)
 /*         draw(op);*/       if (get_map_flags(op->map, NULL,
      }         op->x+freearr_x[dir] * dist,
      return 1;         op->y+freearr_y[dir] * dist,
          NULL, NULL) & P_NO_MAGIC) {
    dist--;
    break;
  }   }
     } else { /* Player didn't specify a distance, so lets see how far  
        * we can move the player.  
        */  
  for(dist=0;!blocks_view (op->map,op->x+freearr_x[dir]*(dist+1),  
                                      op->y+freearr_y[dir]*(dist+1))&&  
                !blocks_magic(op->map,op->x+freearr_x[dir]*(dist+1),  
                                      op->y+freearr_y[dir]*(dist+1));  
      dist++);  
   
  /* If the destinate is blocked, keep backing up until we   /* If the destinate is blocked, keep backing up until we
  * find a place for the player.   * find a place for the player.
  */   */
  for(;dist>0&&blocked(op->map,op->x+freearr_x[dir]*dist,   for(;dist>0; dist--)
                                  op->y+freearr_y[dir]*dist);dist--);       if ((get_map_flags(op->map,NULL,
          op->x+freearr_x[dir]*dist,
          op->y+freearr_y[dir]*dist,
          NULL, NULL) & P_BLOCKED) ==0)
    break;
   
  if(!dist) {   if(!dist) {
      new_draw_info(NDI_UNIQUE, 0,op,"Your spell failed!\n");       new_draw_info(NDI_UNIQUE, 0,op,"Your spell failed!\n");
Line 1291
 
Line 1348
   
     /* Actually move the player now */      /* Actually move the player now */
     remove_ob(op);      remove_ob(op);
     op->x+=freearr_x[dir]*dist,op->y+=freearr_y[dir]*dist;      op->x+=freearr_x[dir]*dist;
       op->y+=freearr_y[dir]*dist;
     if ((op = insert_ob_in_map(op,op->map,op,0)) == NULL)      if ((op = insert_ob_in_map(op,op->map,op,0)) == NULL)
         return 1;          return 1;
   
     if( op->type == PLAYER)      if( op->type == PLAYER)
  MapNewmapCmd(op->contr);   MapNewmapCmd(op->contr);
 /*    draw(op);*/  
     op->speed_left= -FABS(op->speed)*5; /* Freeze them for a short while */      op->speed_left= -FABS(op->speed)*5; /* Freeze them for a short while */
     return 1;      return 1;
 }  }
Line 1858
 
Line 1915
 int create_bomb(object *op,object *caster,int dir,int spell_type,char *name) {  int create_bomb(object *op,object *caster,int dir,int spell_type,char *name) {
   object *tmp;    object *tmp;
   int dx=op->x+freearr_x[dir],dy=op->y+freearr_y[dir];    int dx=op->x+freearr_x[dir],dy=op->y+freearr_y[dir];
   if(wall(op->map,dx,dy)) {  
       if(get_map_flags(op->map,NULL, dx,dy, NULL,NULL) & (P_OUT_OF_MAP | P_WALL)) {
     new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way.");      new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way.");
     return 0;      return 0;
   }    }
Line 1932
 
Line 1990
   
 void move_cancellation(object *op) {  void move_cancellation(object *op) {
   remove_ob(op);    remove_ob(op);
   
   op->x+=DIRX(op),op->y+=DIRY(op);    op->x+=DIRX(op),op->y+=DIRY(op);
   if(!op->direction||wall(op->map,op->x,op->y)) {      if (!op->direction||
          get_map_flags(op->map,NULL,op->x,op->y,NULL,NULL) & (P_OUT_OF_MAP | P_WALL)) {
     free_object(op);      free_object(op);
     return;      return;
   }    }
   if(reflwall(op->map,op->x,op->y, op)) {    if(reflwall(op->map,op->x,op->y, op)) {
   
     op->direction=absdir(op->direction+4);      op->direction=absdir(op->direction+4);
     insert_ob_in_map(op,op->map,op,0);      insert_ob_in_map(op,op->map,op,0);
     return;      return;
Line 2152
 
Line 2211
   
 int alchemy(object *op)  int alchemy(object *op)
 {  {
     int x,y,weight=0,weight_max,large_nuggets,small_nuggets, nx, ny;      int x,y,weight=0,weight_max,large_nuggets,small_nuggets, mflags;
       sint16 nx, ny;
     object *next,*tmp;      object *next,*tmp;
     mapstruct *mp;      mapstruct *mp;
   
Line 2172
 
Line 2232
      nx = x;       nx = x;
      ny = y;       ny = y;
   
      mp = get_map_from_coord(op->map, &nx, &ny);       mp = op->map;
   
        mflags = get_map_flags(mp, &mp, nx, ny, &nx, &ny);
   
      /* wall checks out of map for us */       if(mflags & (P_OUT_OF_MAP | P_WALL | P_NO_MAGIC))
      if(wall(mp,nx,ny) || blocks_magic(mp, nx, ny))  
  continue;   continue;
   
      small_nuggets=0;       small_nuggets=0;
Line 2559
 
Line 2620
     return 0;      return 0;
   
   for(i=1;i<MIN(2+SP_level_strength_adjust(op,caster,spellnum),SIZEOFFREE);i++) {    for(i=1;i<MIN(2+SP_level_strength_adjust(op,caster,spellnum),SIZEOFFREE);i++) {
    if(get_map_flags(op->map,NULL, dx,dy,NULL,NULL) & (P_OUT_OF_MAP | P_WALL)) {
      if(wall(op->map,dx,dy)) {  
         new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way.");          new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way.");
         return 0;          return 0;
      }       }
Line 2574
 
Line 2634
 #endif  #endif
      insert_ob_in_map(tmp,op->map,op,0);       insert_ob_in_map(tmp,op->map,op,0);
   }    }
   
   return 1;    return 1;
   
 }  }
   
 /*  create_the_feature:  peterm  */  /*  create_the_feature:  peterm  */
Line 2587
 
Line 2645
 {  {
     object *tmp=NULL;      object *tmp=NULL;
     char buf1[20];      char buf1[20];
     int putflag=0;      sint16 x, y;
       mapstruct *m;
   
     if(!dir) dir=op->facing;  
     else putflag=1;  
   
     if(blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {      if(!dir) {
    dir=op->facing;
    x = op->x;
    y = op->y;
       }
       else {
    x = op->x+freearr_x[dir];
    y = op->y+freearr_y[dir];
       }
   
       m = op->map;
   
       if(get_map_flags(m, &m, x, y, &x, &y) & (P_BLOCKED | P_OUT_OF_MAP)) {
  new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way.");   new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way.");
  return 0;   return 0;
     }      }
Line 2648
 
Line 2717
     tmp->level=SK_level(op)/2;  /*  so that the spell that the wall casts      tmp->level=SK_level(op)/2;  /*  so that the spell that the wall casts
  inherit part of the effectiveness of   inherit part of the effectiveness of
  of the wall builder */   of the wall builder */
     tmp->x=op->x;tmp->y=op->y;      tmp->x=x;
     if(putflag) {       tmp->y=y;
  tmp->x+=freearr_x[dir];  
  tmp->y+=freearr_y[dir];      if ((tmp = insert_ob_in_map (tmp, m, op,0)) == NULL)
     }  
     if (out_of_map(op->map, tmp->x, tmp->y)) {  
  free_object(tmp);  
  return 0;  
     }  
     if ((tmp = insert_ob_in_map (tmp, op->map, op,0)) == NULL)  
         return 1;          return 1;
     if(QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))      if(QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))
  update_all_los(op->map, op->x, op->y);   update_all_los(op->map, op->x, op->y);
     if(op->type==PLAYER)      if(op->type!=PLAYER)
  draw(op);  
     else  
  SET_FLAG(op, FLAG_SCARED); /* We don't want them to walk through the wall! */   SET_FLAG(op, FLAG_SCARED); /* We don't want them to walk through the wall! */
     return 1;      return 1;
 }  }
Line 3372
 
Line 3433
  * Generalization of staff_to_snake.  Makes a golem out of the caster's weapon.   * Generalization of staff_to_snake.  Makes a golem out of the caster's weapon.
  * The golem is based on the archetype specified, modified by the caster's level   * The golem is based on the archetype specified, modified by the caster's level
  * and the attributes of the weapon.  The weapon is inserted in the golem's    * and the attributes of the weapon.  The weapon is inserted in the golem's
  * inventory so that it falls to the ground when the golem dies. -- DAMN */   * inventory so that it falls to the ground when the golem dies.
    * This code was very odd - code early on would only let players use the spell,
    * yet the code wass full of player checks.  I've presumed that the code
    * that only let players use it was correct, and removed all the other
    * player checks. MSW 2003-01-06
    */
   
 int animate_weapon(object *op,object *caster,int dir, archetype *at, int spellnum) {  int animate_weapon(object *op,object *caster,int dir, archetype *at, int spellnum) {
   object *weapon, *tmp;    object *weapon, *tmp;
   char buf[MAX_BUF];    char buf[MAX_BUF];
   int a, i, j;    int a, i, j;
       sint16 x, y;
   int magic;    int magic;
       mapstruct *m;
    
   if(!at){    if(!at){
     new_draw_info(NDI_UNIQUE, 0,op,"Oops, program error!");      new_draw_info(NDI_UNIQUE, 0,op,"Oops, program error!");
     LOG(llevError,"animate_weapon failed: missing archetype!\n");      LOG(llevError,"animate_weapon failed: missing archetype!\n");
     return 0;      return 0;
   }    }
       /* exit if it's not a player using this spell. */
       if(op->type!=PLAYER) return 0;
   
   /* if player already has a golem, abort */    /* if player already has a golem, abort */
   if(op->type==PLAYER)      if(op->contr->golem!=NULL && op->contr->golem_count == op->contr->golem->count) {
     if(op->contr->golem!=NULL&&!QUERY_FLAG(op->contr->golem,FLAG_FREED)) {  
       control_golem(op->contr->golem,dir);        control_golem(op->contr->golem,dir);
       return 0;        return 0;
     }       }
   if(op->type!=PLAYER) return 0;  /* exit if it's not a player using this spell. */  
   /* if no direction specified, pick one */    /* if no direction specified, pick one */
   if(!dir)     if(!dir)
     dir=find_free_spot(NULL,op->map,op->x,op->y,1,9);      dir=find_free_spot(NULL,op->map,op->x,op->y,1,9);
   
       m = op->map;
       x = op->x+freearr_x[dir];
       y = op->y+freearr_y[dir];
   
   /* if there's no place to put the golem, abort */    /* if there's no place to put the golem, abort */
   if((dir==-1) || blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {      if((dir==-1) || (get_map_flags(m, &m, x, y, &x, &y) & (P_BLOCKED | P_OUT_OF_MAP))) {
     new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way.");      new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way.");
     return 0;      return 0;
   }    }
Line 3414
 
Line 3489
     /* get the weapon to transform */      /* get the weapon to transform */
     for(weapon = op->inv; weapon; weapon = weapon->below)      for(weapon = op->inv; weapon; weapon = weapon->below)
       if(weapon->type==WEAPON&&QUERY_FLAG(weapon,FLAG_APPLIED)) break;        if(weapon->type==WEAPON&&QUERY_FLAG(weapon,FLAG_APPLIED)) break;
   
     if(!weapon) {      if(!weapon) {
       if(op->type==PLAYER) {   
  new_draw_info(NDI_UNIQUE, 0,op,"You need to wield a weapon to animate it.");   new_draw_info(NDI_UNIQUE, 0,op,"You need to wield a weapon to animate it.");
       }   
       return 0;        return 0;
     } else if (spellnum == SP_STAFF_TO_SNAKE && strcmp(weapon->name,"quarterstaff")) {      } else if (spellnum == SP_STAFF_TO_SNAKE && strcmp(weapon->name,"quarterstaff")) {
       if(op->type==PLAYER) {   
  new_draw_info(NDI_UNIQUE, 0,op,"The spell fails to transform your weapon.");   new_draw_info(NDI_UNIQUE, 0,op,"The spell fails to transform your weapon.");
       }  
       return 0;        return 0;
     } else if(op->type==PLAYER &&    } else if (QUERY_FLAG(weapon,FLAG_CURSED) || QUERY_FLAG(weapon,FLAG_DAMNED)) {
        (QUERY_FLAG(weapon,FLAG_CURSED) || QUERY_FLAG(weapon,FLAG_DAMNED))) {  
       new_draw_info(NDI_UNIQUE, 0,op,"You can't animate it.  It won't let go of your hand.");        new_draw_info(NDI_UNIQUE, 0,op,"You can't animate it.  It won't let go of your hand.");
       return 0;        return 0;
     }      }
   }    }
   
   magic = weapon->magic>0 ? weapon->magic : -1*weapon->magic;    magic = weapon->magic>0 ? weapon->magic : -1*weapon->magic;
   
   /* create the golem object */    /* create the golem object */
   tmp=arch_to_object(at);    tmp=arch_to_object(at);
   
   /* if animated by a player, give the player control of the golem */    /* if animated by a player, give the player control of the golem */
   if(op->type==PLAYER) {  
     CLEAR_FLAG(tmp, FLAG_MONSTER);      CLEAR_FLAG(tmp, FLAG_MONSTER);
     SET_FLAG(tmp, FLAG_FRIENDLY);      SET_FLAG(tmp, FLAG_FRIENDLY);
     tmp->stats.exp=0;      tmp->stats.exp=0;
Line 3446
 
Line 3517
     op->contr->golem=tmp;      op->contr->golem=tmp;
     op->contr->shoottype=range_golem;      op->contr->shoottype=range_golem;
     op->contr->golem_count = tmp->count;      op->contr->golem_count = tmp->count;
   } else {  
   /* If spell is cast by a pet, and the weapon is not cursed, make the animated  
    * weapon a pet. */  
     if(QUERY_FLAG(op, FLAG_FRIENDLY)  
        && !QUERY_FLAG(weapon,FLAG_CURSED)  
        && !QUERY_FLAG(weapon,FLAG_DAMNED)){  
       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);  
       }  
     }  
     /* otherwise, make the golem an enemy */  
     SET_FLAG(tmp, FLAG_MONSTER);  
   }  
   
   /* ok, tailor the golem's characteristics based on the weapon */    /* ok, tailor the golem's characteristics based on the weapon */
   if (spellnum == SP_STAFF_TO_SNAKE || spellnum == SP_ANIMATE_WEAPON) {    if (spellnum == SP_STAFF_TO_SNAKE || spellnum == SP_ANIMATE_WEAPON) {
     if (apply_special (op, weapon,      if (apply_special (op, weapon,
                        AP_UNAPPLY | AP_IGNORE_CURSE | AP_NO_MERGE))                         AP_UNAPPLY | AP_IGNORE_CURSE | AP_NO_MERGE)) {
     {  
       LOG (llevError, "BUG: animate_weapon(): can't unapply weapon\n");        LOG (llevError, "BUG: animate_weapon(): can't unapply weapon\n");
       return 0;        return 0;
     }      }
     remove_ob (weapon);      remove_ob (weapon);
     insert_ob_in_ob (weapon, tmp);      insert_ob_in_ob (weapon, tmp);
     if (op->type == PLAYER)  
       esrv_send_item(op, weapon);        esrv_send_item(op, weapon);
     SET_FLAG (tmp, FLAG_USE_WEAPON);      SET_FLAG (tmp, FLAG_USE_WEAPON);
     if (apply_special (tmp, weapon, AP_APPLY))      if (apply_special (tmp, weapon, AP_APPLY))
Line 3487
 
Line 3539
     - 5 * weapon->stats.Dex      - 5 * weapon->stats.Dex
     - 2 * weapon->stats.Str      - 2 * weapon->stats.Str
     - magic;      - magic;
   
   /* Modify hit points for weapon */    /* Modify hit points for weapon */
   tmp->stats.maxhp = tmp->stats.maxhp    tmp->stats.maxhp = tmp->stats.maxhp
     + SP_PARAMETERS[spellnum].bdur      + SP_PARAMETERS[spellnum].bdur
     + 4 * SP_level_strength_adjust(op,caster,spellnum)      + 4 * SP_level_strength_adjust(op,caster,spellnum)
     + 8 * magic      + 8 * magic
     + 12 * weapon->stats.Con;      + 12 * weapon->stats.Con;
   
   /* Modify weapon's damage */    /* Modify weapon's damage */
   tmp->stats.dam = SP_PARAMETERS[spellnum].bdam    tmp->stats.dam = SP_PARAMETERS[spellnum].bdam
     + weapon->stats.dam      + weapon->stats.dam
     + magic      + magic
     + 2 * SP_level_dam_adjust(op,caster,spellnum)      + 2 * SP_level_dam_adjust(op,caster,spellnum)
     + 5 * weapon->stats.Str;      + 5 * weapon->stats.Str;
   
   /* sanity checks */    /* sanity checks */
   if(tmp->stats.wc<-127) tmp->stats.wc = -127;    if(tmp->stats.wc<-127) tmp->stats.wc = -127;
   if(tmp->stats.maxhp<0) tmp->stats.maxhp=10;    if(tmp->stats.maxhp<0) tmp->stats.maxhp=10;
   tmp->stats.hp = tmp->stats.maxhp;    tmp->stats.hp = tmp->stats.maxhp;
   
   if(tmp->stats.dam<0) tmp->stats.dam=127;    if(tmp->stats.dam<0) tmp->stats.dam=127;
   LOG(llevDebug,"animate_weapon: wc:%d  hp:%d  dam:%d.\n", tmp->stats.wc, tmp->stats.hp, tmp->stats.dam);  
   /*    LOG(llevDebug,"animate_weapon: wc:%d  hp:%d  dam:%d.\n", tmp->stats.wc, tmp->stats.hp, tmp->stats.dam);*/
   
   /* attacktype */    /* attacktype */
   if ( ! tmp->attacktype)    if ( ! tmp->attacktype)
     tmp->attacktype = AT_PHYSICAL;      tmp->attacktype = AT_PHYSICAL;
Line 3539
 
Line 3597
       a = material[i].save[0];        a = material[i].save[0];
     }      }
   }    }
   
   tmp->resist[ATNR_PHYSICAL] = 100 - (int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*(a>14?14.0:(float)a)));    tmp->resist[ATNR_PHYSICAL] = 100 - (int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*(a>14?14.0:(float)a)));
   LOG (llevDebug, "animate_weapon: slaying %s\n",  /*    LOG (llevDebug, "animate_weapon: slaying %s\n", tmp->slaying ? tmp->slaying : "nothing"); */
        tmp->slaying ? tmp->slaying : "nothing");  
   
   /* Determine golem's speed */    /* Determine golem's speed */
   /* This formula is apparently broken.  I write a replacement. */  
   /*  tmp->speed = ((weapon->last_sp>0.1)?weapon->last_sp:0.1) -  
     (((weapon->last_sp>0.1)?weapon->last_sp:0.1)/  
      ( (1.0 * (float)SP_level_dam_adjust(op, caster, spellnum) +  
  1.5 * (float)weapon->stats.Dex +  
  2.0 * (float)weapon->stats.Str +  
  3.0 * (float)magic +  
  5.0 * (float)weapon->stats.exp) )  
      * ((float)((tmp->weight>1000)? tmp->weight : 1000)  
      / ((float)(weapon->weight>1000)? weapon->weight : 1000))); */  
   
   /* replacement  */  
   tmp->speed = 0.4 + 0.1 * SP_level_dam_adjust(op,caster,spellnum);    tmp->speed = 0.4 + 0.1 * SP_level_dam_adjust(op,caster,spellnum);
   
   if(tmp->speed > 3.33) tmp->speed = 3.33;    if(tmp->speed > 3.33) tmp->speed = 3.33;
   LOG(llevDebug,"animate_weapon: armour:%d  speed:%f  exp:%d.\n",  /*  LOG(llevDebug,"animate_weapon: armour:%d  speed:%f  exp:%d.\n",
       tmp->resist[ATNR_PHYSICAL], tmp->speed, tmp->stats.exp);        tmp->resist[ATNR_PHYSICAL], tmp->speed, tmp->stats.exp);
   */
   
   /* spell-dependent finishing touches and descriptive text */    /* spell-dependent finishing touches and descriptive text */
   switch(spellnum) {    switch(spellnum) {
Line 3591
 
Line 3638
   case SP_DANCING_SWORD:    case SP_DANCING_SWORD:
     new_draw_info(NDI_UNIQUE, 0,op,"A magical sword appears in mid air, eager to slay your foes for you!");      new_draw_info(NDI_UNIQUE, 0,op,"A magical sword appears in mid air, eager to slay your foes for you!");
     break;      break;
   
   default:    default:
     break;      break;
   }    }
Line 3598
 
Line 3646
   /*  make experience increase in proportion to the strength of the summoned creature. */    /*  make experience increase in proportion to the strength of the summoned creature. */
   tmp->stats.exp *= SP_level_spellpoint_cost(op,caster,spellnum)/spells[spellnum].sp;    tmp->stats.exp *= SP_level_spellpoint_cost(op,caster,spellnum)/spells[spellnum].sp;
   tmp->speed_left= -1;    tmp->speed_left= -1;
   tmp->x=op->x+freearr_x[dir],tmp->y=op->y+freearr_y[dir];      tmp->x=x;
       tmp->y=y;
   tmp->direction=dir;    tmp->direction=dir;
   insert_ob_in_map(tmp,op->map,op,0);      insert_ob_in_map(tmp,m,op,0);
   return 1;    return 1;
 }  }
   
Line 3755
 
Line 3804
  */   */
   
 int cast_cause_disease(object *op, object *caster, int dir, archetype *disease_arch, int type) {  int cast_cause_disease(object *op, object *caster, int dir, archetype *disease_arch, int type) {
     int x,y,i;      sint16  x,y;
       int i,  mflags;
     object *walk;      object *walk;
       mapstruct *m;
   
     x = op->x;  y = op->y;      x = op->x;
       y = op->y;
   
     /* If casting from a scroll, no direction will be available, so refer to the       /* If casting from a scroll, no direction will be available, so refer to the
      * direction the player is pointing.       * direction the player is pointing.
Line 3767
 
Line 3819
     if (!dir) return 0;     /* won't find anything if casting on ourself, so just return */      if (!dir) return 0;     /* won't find anything if casting on ourself, so just return */
   
     /* search in a line for a victim */      /* search in a line for a victim */
     for(i=0;i<5;i++) {      for(i=1;i<6;i++) {
  x += freearr_x[dir]; y+= freearr_y[dir];   x = op->x + i * freearr_x[dir];
    y = op->y + i * freearr_y[dir];
    m = op->map;
   
  if(out_of_map(op->map,x,y)) return 0;   mflags = get_map_flags(m, &m, x, y, &x, &y);
   
    if (mflags & P_OUT_OF_MAP) return 0;
   
    /* don't go through walls */
    if (mflags & P_NO_PASS) return 0;
   
    /* Only bother looking on this space if there is something living here */
    if (mflags & P_IS_ALIVE) {
  /* search this square for a victim */   /* search this square for a victim */
  for(walk=get_map_ob(op->map,x,y);walk;walk=walk->above)       for(walk=get_map_ob(m,x,y);walk;walk=walk->above)
      if (QUERY_FLAG(walk,FLAG_MONSTER) || (walk->type==PLAYER)) {  /* found a victim */       if (QUERY_FLAG(walk,FLAG_MONSTER) || (walk->type==PLAYER)) {  /* found a victim */
    object *disease = arch_to_object(disease_arch);     object *disease = arch_to_object(disease_arch);
   
Line 3834
 
Line 3895
    if(disease->stats.sp)     if(disease->stats.sp)
  disease->stats.sp -= SP_level_dam_adjust(op,caster,type);   disease->stats.sp -= SP_level_dam_adjust(op,caster,type);
        
   
    if(infect_object(walk,disease,1)) {     if(infect_object(walk,disease,1)) {
  object *flash;  /* visual effect for inflicting disease */   object *flash;  /* visual effect for inflicting disease */
   
Line 3850
 
Line 3910
    }     }
    free_object(disease);     free_object(disease);
      }       }
  /* no more infecting through walls. */   } /* if living creature */
  if(blocked(op->map,x,y)) return 1;      } /* for range of spaces */
     }  
     new_draw_info(NDI_UNIQUE,0,op,"No one caught anything!");      new_draw_info(NDI_UNIQUE,0,op,"No one caught anything!");
     return 1;      return 1;
 }  }
Line 3860
 
Line 3919
   
   
 /* move aura function.  An aura is a part of someone's inventory,  /* move aura function.  An aura is a part of someone's inventory,
 which he carries with him, but which acts on the map immediately   * which he carries with him, but which acts on the map immediately
 around him.   * around him.
 Aura parameters:   * Aura parameters:
 food:  duration counter.      * food:  duration counter.   
 attacktype:  aura's attacktype    * attacktype:  aura's attacktype
 other_arch:  archetype to drop where we attack   * other_arch:  archetype to drop where we attack
   
  */   */
   
 void move_aura(object *aura) {  void move_aura(object *aura) {
Line 3877
 
Line 3935
   env = aura->env;    env = aura->env;
   
   /* no matter what we've gotta remove the aura...    /* no matter what we've gotta remove the aura...
      we'll put it back if its time isn't up.  */       * we'll put it back if its time isn't up. 
        */
   remove_ob(aura);    remove_ob(aura);
   
   /* exit if we're out of gas */    /* exit if we're out of gas */
Line 3885
 
Line 3944
     free_object(aura);      free_object(aura);
     return;      return;
   }    }
   
   /* auras only exist in inventories */    /* auras only exist in inventories */
   if(env == NULL || env->map==NULL) {    if(env == NULL || env->map==NULL) {
     free_object(aura);      free_object(aura);
Line 3894
 
Line 3954
   aura->y = env->y;    aura->y = env->y;
   
     /* we need to jump out of the inventory for a bit      /* we need to jump out of the inventory for a bit
        in order to hit the map conveniently. */       * in order to hit the map conveniently.
        */
   insert_ob_in_map(aura,env->map,aura,0);    insert_ob_in_map(aura,env->map,aura,0);
   
   for(i=1;i<9;i++) {     for(i=1;i<9;i++) {
     hit_map(aura,i,aura->attacktype);  
     if(aura->other_arch) {  
       object *new_ob;  
       int nx, ny;        int nx, ny;
       nx = aura->x + freearr_x[i];        nx = aura->x + freearr_x[i];
       ny = aura->y + freearr_y[i];        ny = aura->y + freearr_y[i];
       /* we're done if the "i" square next to us is full */   if (!(get_map_flags(aura->map, NULL, nx, ny, NULL, NULL) & (P_WALL | P_OUT_OF_MAP)))
       if(out_of_map(aura->map,nx,ny) ||       hit_map(aura,i,aura->attacktype);
  wall(aura->map,nx,ny)) continue;       if(aura->other_arch) {
    object *new_ob;
   
       new_ob = arch_to_object(aura->other_arch);        new_ob = arch_to_object(aura->other_arch);
       new_ob->x = nx;        new_ob->x = nx;
       new_ob->y = ny;        new_ob->y = ny;


Legend:
line(s) removed in v.1.89 
line(s) changed
 line(s) added in v.1.90

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