Difference for server/spell_util.c from version 1.72 to 1.73


version 1.72 version 1.73
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_spell_util_c =   * static char *rcsid_spell_util_c =
  *   "$Id: spell_util.c,v 1.72 2003/01/04 00:28:52 mwedel Exp $";   *   "$Id: spell_util.c,v 1.73 2003/01/08 08:39:21 mwedel Exp $";
  */   */
   
   
Line 156
 
Line 156
 int cast_spell(object *op,object *caster,int dir,int type,int ability,SpellTypeFrom item,char *stringarg) {  int cast_spell(object *op,object *caster,int dir,int type,int ability,SpellTypeFrom item,char *stringarg) {
   char *godname;    char *godname;
   spell *s=find_spell(type);    spell *s=find_spell(type);
   int success=0,bonus;      int success=0,bonus, mflags;
   int duration=SP_PARAMETERS[type].bdur;  /*  get the base duration */    int duration=SP_PARAMETERS[type].bdur;  /*  get the base duration */
   
   if(!strcmp((godname=determine_god(op)),"none")) godname="A random spirit";     if(!strcmp((godname=determine_god(op)),"none")) godname="A random spirit";
Line 176
 
Line 176
  if( spells[type].onself) dir = 0;   if( spells[type].onself) dir = 0;
   }    }
   
       /* Do a bunch of sanity checks to see if the player can cast the spell.
        * wizards bypass these checks.  If your using a wand or potion, these
        * checks don't apply either.  If your doing a summon spell and
        * have a golem, special work is needed there also.
        */
   
   if(!(QUERY_FLAG(op, FLAG_WIZ))&& (op->type==PLAYER) && (op->contr->shoottype==range_magic) &&    if(!(QUERY_FLAG(op, FLAG_WIZ))&& (op->type==PLAYER) && (op->contr->shoottype==range_magic) &&
      (item!=spellPotion)&&  (!(IS_SUMMON_SPELL(type)&&op->contr->golem!=NULL))) {       (item!=spellPotion)&&  (!(IS_SUMMON_SPELL(type)&&op->contr->golem!=NULL))) {
  if( !spells[type].cleric && op->stats.sp<SP_level_spellpoint_cost(op,caster,type)) {   if( !spells[type].cleric && op->stats.sp<SP_level_spellpoint_cost(op,caster,type)) {
Line 184
 
Line 190
  }   }
  else if(spells[type].cleric && op->stats.grace<SP_level_spellpoint_cost(op,caster,type))   else if(spells[type].cleric && op->stats.grace<SP_level_spellpoint_cost(op,caster,type))
  {   {
    /* it's possible for grace to go negative */       /* it's possible for grace to go negative
    /* Fine - let grace go negative, but how negative it is should really        * Fine - let grace go negative, but how negative it is should really
     * put a limit on things - in the old method, chance was the same      * put a limit on things - in the old method, chance was the same
     * no matter how negative it was.      * no matter how negative it was.
     * Instead of subtracting 10 from the roll, add in grace (which is      * Instead of subtracting 10 from the roll, add in grace (which is
Line 196
 
Line 202
  new_draw_info_format(NDI_UNIQUE, 0,op,    new_draw_info_format(NDI_UNIQUE, 0,op,
      "%s grants your prayer, though you are unworthy.",godname);       "%s grants your prayer, though you are unworthy.",godname);
    }     }
    else       else {
    {  
    prayer_failure(op,op->stats.grace,SP_level_spellpoint_cost(op,caster,type));     prayer_failure(op,op->stats.grace,SP_level_spellpoint_cost(op,caster,type));
    new_draw_info_format(NDI_UNIQUE, 0,op,"%s ignores your prayer.",godname);     new_draw_info_format(NDI_UNIQUE, 0,op,"%s ignores your prayer.",godname);
    return 0;     return 0;
Line 209
 
Line 214
     new_draw_info(NDI_UNIQUE, 0,op, "You are unable to cast that spell.");      new_draw_info(NDI_UNIQUE, 0,op, "You are unable to cast that spell.");
     return 0;      return 0;
   }    }
   
   /* If it is an ability, assume that the designer of the archetype knows    /* If it is an ability, assume that the designer of the archetype knows
    * what they are doing.     * what they are doing.
    */     */
Line 226
 
Line 232
        op->spelltype = type;         op->spelltype = type;
        op->spell_state = 1;         op->spell_state = 1;
        /*  put the stringarg into the object struct so that when the         /*  put the stringarg into the object struct so that when the
    spell is actually cast, it knows about the stringarg.   * spell is actually cast, it knows about the stringarg.
    necessary for the invoke command spells.  */   * necessary for the invoke command spells. 
    */
        if(stringarg) {         if(stringarg) {
    op->spellarg = strdup_local(stringarg);       op->spellarg = strdup_local(stringarg); 
        }         }
Line 242
 
Line 249
   }    }
   
   /*  ban removed on clerical spells in no-magic areas */    /*  ban removed on clerical spells in no-magic areas */
       mflags = get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL);
   
   if (!ability && item != spellPotion &&     if (!ability && item != spellPotion &&
  ( ((!s->cleric)&&blocks_magic(op->map,op->x,op->y))||   ( (!s->cleric && (mflags & P_NO_MAGIC)) ||
    (( s->cleric)&&blocks_cleric(op->map,op->x,op->y)))) {      (s->cleric && (mflags & P_NO_CLERIC)))) {
   
     if (op->type!=PLAYER)      if (op->type!=PLAYER)
       return 0;        return 0;
   
     if(s->cleric)       if(s->cleric)
       new_draw_info_format(NDI_UNIQUE, 0,op,"This ground is unholy!  %s ignores you.",godname);        new_draw_info_format(NDI_UNIQUE, 0,op,"This ground is unholy!  %s ignores you.",godname);
     else      else
Line 277
 
Line 288
     }      }
     if(s->sp==0) /* Shouldn't happen... */      if(s->sp==0) /* Shouldn't happen... */
       return 0;        return 0;
     return(random_roll(1, SP_level_spellpoint_cost(op,caster,type), op,    return(random_roll(1, SP_level_spellpoint_cost(op,caster,type), op, PREFER_LOW));
  PREFER_LOW));  
   }    }
   if(settings.spell_encumbrance == TRUE && item == spellNormal &&    if(settings.spell_encumbrance == TRUE && item == spellNormal &&
      op->type==PLAYER && (!s->cleric) ) {       op->type==PLAYER && (!s->cleric) ) {
   
     int failure = random_roll(0, 199, op, PREFER_LOW) -      int failure = random_roll(0, 199, op, PREFER_LOW) -
  op->contr->encumbrance +op->level -s->level +35;   op->contr->encumbrance +op->level -s->level +35;
   
Line 314
 
Line 325
        */         */
       op->speed_left -= (s->time*PATH_TIME_MULT(op,s) / 10) * FABS(op->speed);        op->speed_left -= (s->time*PATH_TIME_MULT(op,s) / 10) * FABS(op->speed);
   }    }
   
   switch((enum spellnrs) type) {    switch((enum spellnrs) type) {
   case SP_BULLET:    case SP_BULLET:
   case SP_LARGE_BULLET:    case SP_LARGE_BULLET:
    case SP_CAUSE_LIGHT:
    case SP_CAUSE_HEAVY:
    case SP_CAUSE_MEDIUM:
    case SP_CAUSE_CRITICAL:
     success = fire_arch(op,caster,dir,spellarch[type],type,1);      success = fire_arch(op,caster,dir,spellarch[type],type,1);
     break;      break;
   
   case SP_HOLY_ORB:    case SP_HOLY_ORB:
     success = fire_arch(op,caster,dir,spellarch[type],type,0);      success = fire_arch(op,caster,dir,spellarch[type],type,0);
     break;      break;
   
   case SP_S_FIREBALL:    case SP_S_FIREBALL:
   case SP_M_FIREBALL:    case SP_M_FIREBALL:
   case SP_L_FIREBALL:    case SP_L_FIREBALL:
Line 334
 
Line 352
   case SP_S_MANABALL:    case SP_S_MANABALL:
   case SP_M_MANABALL:    case SP_M_MANABALL:
   case SP_L_MANABALL:    case SP_L_MANABALL:
    case SP_BALL_LIGHTNING:
    case SP_DIVINE_SHOCK:
    case SP_POISON_FOG:
     success = fire_arch(op,caster,dir,spellarch[type],type, !ability);      success = fire_arch(op,caster,dir,spellarch[type],type, !ability);
     break;      break;
   
   case SP_VITRIOL:    case SP_VITRIOL:
     success = fire_arch(op,caster,dir,spellarch[type],type,0);      success = fire_arch(op,caster,dir,spellarch[type],type,0);
     break;      break;
   
   case SP_MASS_CONFUSION:    case SP_MASS_CONFUSION:
   case SP_SHOCKWAVE:    case SP_SHOCKWAVE:
   case SP_COLOR_SPRAY:    case SP_COLOR_SPRAY:
Line 359
 
Line 382
   case SP_WRATHFUL_EYE:    case SP_WRATHFUL_EYE:
     success = cast_cone(op,caster,dir,duration,type,spellarch[type],!ability);      success = cast_cone(op,caster,dir,duration,type,spellarch[type],!ability);
     break;      break;
   
   case SP_TURN_UNDEAD:    case SP_TURN_UNDEAD:
     if(QUERY_FLAG(op,FLAG_UNDEAD)) { /* the undead *don't* cast this */      if(QUERY_FLAG(op,FLAG_UNDEAD)) { /* the undead *don't* cast this */
        new_draw_info(NDI_UNIQUE, 0,op,"Your undead nature prevents you from turning undead!");         new_draw_info(NDI_UNIQUE, 0,op,"Your undead nature prevents you from turning undead!");
        success=0; break;   success=0;
    break;
     }      }
        /* else fall through to holy word below */
   case SP_HOLY_WORD:    case SP_HOLY_WORD:
     success = cast_cone(op,caster,dir,duration+(turn_bonus[op->stats.Wis]/5),type,      success = cast_cone(op,caster,dir,duration+(turn_bonus[op->stats.Wis]/5),type,
  spellarch[type],0);   spellarch[type],0);
     break;      break;
   
   case SP_HOLY_WRATH:    case SP_HOLY_WRATH:
   case SP_INSECT_PLAGUE:    case SP_INSECT_PLAGUE:
   case SP_RETRIBUTION:    case SP_RETRIBUTION:
     success = cast_smite_spell(op,caster,dir,type);      success = cast_smite_spell(op,caster,dir,type);
     break;      break;
   
   case SP_SUNSPEAR:    case SP_SUNSPEAR:
   case SP_FIREBOLT:    case SP_FIREBOLT:
   case SP_FROSTBOLT:    case SP_FROSTBOLT:
Line 383
 
Line 411
   case SP_MANA_BOLT:    case SP_MANA_BOLT:
     success = fire_bolt(op,caster,dir,type,!ability);      success = fire_bolt(op,caster,dir,type,!ability);
     break;      break;
   
   case SP_BOMB:    case SP_BOMB:
     success = create_bomb(op,caster,dir,type,"bomb");      success = create_bomb(op,caster,dir,type,"bomb");
     break;      break;
   
   case SP_GOLEM:    case SP_GOLEM:
   case SP_FIRE_ELEM:    case SP_FIRE_ELEM:
   case SP_WATER_ELEM:    case SP_WATER_ELEM:
   case SP_EARTH_ELEM:    case SP_EARTH_ELEM:
   case SP_AIR_ELEM:    case SP_AIR_ELEM:
    case SP_MYSTIC_FIST:
     success = summon_monster(op,caster,dir,spellarch[type],type);      success = summon_monster(op,caster,dir,spellarch[type],type);
     break;      break;
   
   case SP_FINGER_DEATH:     case SP_FINGER_DEATH:
     success = finger_of_death(op,caster,dir);      success = finger_of_death(op,caster,dir);
     break;      break;
   
   case SP_SUMMON_AVATAR:     case SP_SUMMON_AVATAR:
   case SP_HOLY_SERVANT: {    case SP_HOLY_SERVANT: {
     archetype *spat = find_archetype((type==SP_SUMMON_AVATAR)?"avatar":"holy_servant");      archetype *spat = find_archetype((type==SP_SUMMON_AVATAR)?"avatar":"holy_servant");
     success = summon_avatar(op,caster,dir,spat,type);      success = summon_avatar(op,caster,dir,spat,type);
     break; }        break;
        }
   
   case SP_CONSECRATE:     case SP_CONSECRATE:
     success = cast_consecrate(op);       success = cast_consecrate(op);
     break;      break;
   
   case SP_SUMMON_CULT:    case SP_SUMMON_CULT:
     success = summon_cult_monsters(op,dir);      success = summon_cult_monsters(op,dir);
     break;      break;
   
   case SP_PET:    case SP_PET:
     success = summon_pet(op,dir, item);      success = summon_pet(op,dir, item);
     break;      break;
   
   case SP_D_DOOR:    case SP_D_DOOR:
     /* dimension door needs the actual caster, because that is what is      /* dimension door needs the actual caster, because that is what is
      * moved.       * moved.
      */       */
     success = dimension_door(op,dir);      success = dimension_door(op,dir);
     break;      break;
   
   case SP_DARKNESS:    case SP_DARKNESS:
   case SP_WALL_OF_THORNS:    case SP_WALL_OF_THORNS:
   case SP_CHAOS_POOL:    case SP_CHAOS_POOL:
Line 425
 
Line 464
   case SP_EARTH_WALL:    case SP_EARTH_WALL:
     success = magic_wall(op,caster,dir,type);      success = magic_wall(op,caster,dir,type);
     break;      break;
   
   case SP_MAGIC_MAPPING:    case SP_MAGIC_MAPPING:
     if(op->type==PLAYER) {      if(op->type==PLAYER) {
       spell_effect(SP_MAGIC_MAPPING, op->x, op->y, op->map, op);        spell_effect(SP_MAGIC_MAPPING, op->x, op->y, op->map, op);
Line 432
 
Line 472
       success=1;        success=1;
     }      }
     break;      break;
   
   case SP_FEAR:    case SP_FEAR:
     if(op->type==PLAYER)      if(op->type==PLAYER)
       bonus=fear_bonus[op->stats.Cha];        bonus=fear_bonus[op->stats.Cha];
Line 439
 
Line 480
       bonus=caster->head==NULL?caster->level/3+1:caster->head->level/3+1;        bonus=caster->head==NULL?caster->level/3+1:caster->head->level/3+1;
     success = cast_cone(op,caster,dir,duration+bonus,SP_FEAR,spellarch[type],!ability);      success = cast_cone(op,caster,dir,duration+bonus,SP_FEAR,spellarch[type],!ability);
     break;      break;
   
   case SP_WOW:    case SP_WOW:
     success = cast_wow(op,dir,ability, item);      success = cast_wow(op,dir,ability, item);
     break;      break;
   
   case SP_DESTRUCTION:    case SP_DESTRUCTION:
     success = cast_destruction(op,caster,5+op->stats.Int,AT_MAGIC);      success = cast_destruction(op,caster,5+op->stats.Int,AT_MAGIC);
     break;      break;
   
   case SP_PERCEIVE:    case SP_PERCEIVE:
     success = perceive_self(op);      success = perceive_self(op);
     break;      break;
   
   case SP_WOR:    case SP_WOR:
     success = cast_wor(op,caster);      success = cast_wor(op,caster);
     break;      break;
   
   case SP_INVIS:    case SP_INVIS:
   case SP_INVIS_UNDEAD:    case SP_INVIS_UNDEAD:
   case SP_IMPROVED_INVIS:    case SP_IMPROVED_INVIS:
     success = cast_invisible(op,caster,type);      success = cast_invisible(op,caster,type);
     break;      break;
   
   case SP_PROBE:    case SP_PROBE:
     success = probe(op,dir);      success = probe(op,dir);
     break;      break;
   
   case SP_CREATE_FOOD:    case SP_CREATE_FOOD:
     success = cast_create_food(op,caster,dir,stringarg);      success = cast_create_food(op,caster,dir,stringarg);
     break;      break;
   
   case SP_EARTH_DUST:    case SP_EARTH_DUST:
     success = cast_earth2dust(op,caster);      success = cast_earth2dust(op,caster);
     break;      break;
   
   case SP_REGENERATION:     case SP_REGENERATION:
   case SP_BLESS:    case SP_BLESS:
   case SP_CURSE:    case SP_CURSE:
Line 495
 
Line 545
   case SP_RAGE:    case SP_RAGE:
     success = cast_change_attr(op,caster,dir,type);      success = cast_change_attr(op,caster,dir,type);
     break;      break;
   
   case SP_RESTORATION:    case SP_RESTORATION:
   case SP_HEAL:    case SP_HEAL:
   case SP_MINOR_HEAL:    case SP_MINOR_HEAL:
Line 506
 
Line 557
   case SP_CURE_DISEASE:    case SP_CURE_DISEASE:
     success = cast_heal(op,dir,type);      success = cast_heal(op,dir,type);
     break;      break;
   
   case SP_REGENERATE_SPELLPOINTS:    case SP_REGENERATE_SPELLPOINTS:
     success = cast_regenerate_spellpoints(op);      success = cast_regenerate_spellpoints(op);
     break;      break;
   
   case SP_SMALL_SPEEDBALL:    case SP_SMALL_SPEEDBALL:
   case SP_LARGE_SPEEDBALL:    case SP_LARGE_SPEEDBALL:
     success = cast_speedball(op,dir,type);      success = cast_speedball(op,dir,type);
     break;      break;
   
   case SP_POLYMORPH:    case SP_POLYMORPH:
 #ifdef NO_POLYMORPH  #ifdef NO_POLYMORPH
     /* Not great, but at least provide feedback so if players do have      /* Not great, but at least provide feedback so if players do have
Line 525
 
Line 579
     success = cast_polymorph(op,dir);      success = cast_polymorph(op,dir);
 #endif  #endif
     break;      break;
   
   case SP_CHARGING:    case SP_CHARGING:
     success = recharge(op);      success = recharge(op);
     break;      break;
   
   case SP_CANCELLATION:    case SP_CANCELLATION:
     success = fire_cancellation(op,dir,spellarch[type],!ability);      success = fire_cancellation(op,dir,spellarch[type],!ability);
     break;      break;
   
   case SP_ALCHEMY:    case SP_ALCHEMY:
     success = alchemy(op);      success = alchemy(op);
     break;      break;
   
   case SP_REMOVE_CURSE:    case SP_REMOVE_CURSE:
   case SP_REMOVE_DAMNATION:    case SP_REMOVE_DAMNATION:
     success = remove_curse(op, type, item);      success = remove_curse(op, type, item);
     break;      break;
   
   case SP_IDENTIFY:    case SP_IDENTIFY:
     success = cast_identify(op);      success = cast_identify(op);
     break;      break;
   
   case SP_DETECT_MAGIC:    case SP_DETECT_MAGIC:
   case SP_DETECT_MONSTER:    case SP_DETECT_MONSTER:
   case SP_DETECT_EVIL:    case SP_DETECT_EVIL:
Line 548
 
Line 608
   case SP_SHOW_INVIS:    case SP_SHOW_INVIS:
     success = cast_detection(op, type);      success = cast_detection(op, type);
     break;      break;
   
   case SP_AGGRAVATION:    case SP_AGGRAVATION:
     aggravate_monsters(op);      aggravate_monsters(op);
     success = 1;      success = 1;
     break;      break;
   case SP_BALL_LIGHTNING:  
   case SP_DIVINE_SHOCK:   case SP_METEOR_SWARM:
   case SP_POISON_FOG:  
     success = fire_arch(op,caster,dir,spellarch[type],type,!ability);  
     break;  
   case SP_METEOR_SWARM: {  
     success = 1;      success = 1;
     fire_swarm(op, caster, dir, spellarch[type], SP_METEOR,      fire_swarm(op, caster, dir, spellarch[type], SP_METEOR,
  die_roll(3, 3, op, PREFER_HIGH) +   die_roll(3, 3, op, PREFER_HIGH) +
      SP_level_strength_adjust(op,caster, type), 0);       SP_level_strength_adjust(op,caster, type), 0);
     break;      break;
   }  
   case SP_BULLET_SWARM: {   case SP_BULLET_SWARM:
     success = 1;      success = 1;
     fire_swarm(op, caster, dir, spellarch[type], SP_BULLET,      fire_swarm(op, caster, dir, spellarch[type], SP_BULLET,
  die_roll(3, 3, op, PREFER_HIGH) +   die_roll(3, 3, op, PREFER_HIGH) +
      SP_level_strength_adjust(op,caster, type), 0);       SP_level_strength_adjust(op,caster, type), 0);
     break;      break;
   }  
   case SP_BULLET_STORM: {   case SP_BULLET_STORM:
     success = 1;      success = 1;
     fire_swarm(op, caster, dir, spellarch[type], SP_LARGE_BULLET,      fire_swarm(op, caster, dir, spellarch[type], SP_LARGE_BULLET,
  die_roll(3, 3, op, PREFER_HIGH) +   die_roll(3, 3, op, PREFER_HIGH) +
      SP_level_strength_adjust(op,caster, type), 0);       SP_level_strength_adjust(op,caster, type), 0);
     break;      break;
   }  
   case SP_CAUSE_MANY: {   case SP_CAUSE_MANY:
     success = 1;      success = 1;
     fire_swarm(op, caster, dir, spellarch[type], SP_CAUSE_HEAVY,      fire_swarm(op, caster, dir, spellarch[type], SP_CAUSE_HEAVY,
  die_roll(3, 3, op, PREFER_HIGH) +   die_roll(3, 3, op, PREFER_HIGH) +
      SP_level_strength_adjust(op,caster, type), 0);       SP_level_strength_adjust(op,caster, type), 0);
     break;      break;
   }  
    case SP_MISSILE_SWARM:
        success = 1;
        fire_swarm(op, caster, dir, spellarch[type], SP_M_MISSILE,
           die_roll(3, 3, op, PREFER_HIGH) +
           SP_level_strength_adjust(op,caster, type), 0);
        break;
   
   case SP_METEOR:    case SP_METEOR:
     success = fire_arch(op,caster,dir,find_archetype("meteor"),type,0);      success = fire_arch(op,caster,dir,find_archetype("meteor"),type,0);
     break;      break;
   case SP_MYSTIC_FIST:  
     success = summon_monster(op,caster,dir,spellarch[type],type);  
     break;  
   case SP_RAISE_DEAD:    case SP_RAISE_DEAD:
   case SP_RESURRECTION:    case SP_RESURRECTION:
     success = cast_raise_dead_spell(op,dir,type, NULL);      success = cast_raise_dead_spell(op,dir,type, NULL);
     break;      break;
   /* mlee */  
   case SP_IMMUNE_COLD:    case SP_IMMUNE_COLD:
   case SP_IMMUNE_FIRE:    case SP_IMMUNE_FIRE:
   case SP_IMMUNE_ELEC:    case SP_IMMUNE_ELEC:
Line 610
 
Line 672
   case SP_HASTE:    case SP_HASTE:
     success=cast_change_attr(op,caster,dir,type);      success=cast_change_attr(op,caster,dir,type);
     break;      break;
   /* peterm, additional spells added */  
   
   case SP_BUILD_DIRECTOR:    case SP_BUILD_DIRECTOR:
   case SP_BUILD_BWALL:    case SP_BUILD_BWALL:
   case SP_BUILD_LWALL:    case SP_BUILD_LWALL:
   case SP_BUILD_FWALL:    case SP_BUILD_FWALL:
     success=create_the_feature(op,caster,dir,type);      success=create_the_feature(op,caster,dir,type);
     break;      break;
   
   case SP_RUNE_FIRE:     case SP_RUNE_FIRE:
   case SP_RUNE_FROST:    case SP_RUNE_FROST:
   case SP_RUNE_SHOCK:     case SP_RUNE_SHOCK:
Line 625
 
Line 689
   case SP_RUNE_ANTIMAGIC:    case SP_RUNE_ANTIMAGIC:
     success = write_rune(op,dir,0,caster->level,s->archname);      success = write_rune(op,dir,0,caster->level,s->archname);
     break;      break;
   
   case SP_RUNE_DRAINSP:    case SP_RUNE_DRAINSP:
     success = write_rune(op,dir,SP_MAGIC_DRAIN,caster->level,s->archname);      success = write_rune(op,dir,SP_MAGIC_DRAIN,caster->level,s->archname);
     break;      break;
   
   case SP_RUNE_TRANSFER:    case SP_RUNE_TRANSFER:
     success= write_rune(op,dir,SP_TRANSFER,caster->level,s->archname);      success= write_rune(op,dir,SP_TRANSFER,caster->level,s->archname);
     break;      break;
   
   case SP_TRANSFER:    case SP_TRANSFER:
     success = cast_transfer(op,dir);      success = cast_transfer(op,dir);
     break;      break;
   
   case SP_MAGIC_DRAIN:    case SP_MAGIC_DRAIN:
     success= drain_magic(op,dir);      success= drain_magic(op,dir);
     break;      break;
   
   case SP_DISPEL_RUNE:    case SP_DISPEL_RUNE:
     success = dispel_rune(op,dir,0);  /* 0 means no risk of detonating rune */      success = dispel_rune(op,dir,0);  /* 0 means no risk of detonating rune */
     break;      break;
   
   case SP_SUMMON_EVIL_MONST:    case SP_SUMMON_EVIL_MONST:
  if(op->type==PLAYER) return 0;   if(op->type==PLAYER) return 0;
     success = summon_hostile_monsters(op,op->stats.maxhp,op->race);      success = summon_hostile_monsters(op,op->stats.maxhp,op->race);
     break;      break;
   
   case SP_REINCARNATION:   case SP_REINCARNATION: {
     {  
       object * dummy;        object * dummy;
       if(stringarg==NULL) {        if(stringarg==NULL) {
  new_draw_info(NDI_UNIQUE, 0,op,"Reincarnate WHO?");   new_draw_info(NDI_UNIQUE, 0,op,"Reincarnate WHO?");
Line 659
 
Line 728
       free_object(dummy);        free_object(dummy);
     }      }
     break;      break;
   
   case SP_RUNE_MAGIC:    case SP_RUNE_MAGIC:
   case SP_GLYPH:    case SP_GLYPH:
     return cast_generic_rune(op, caster, dir, stringarg, type);      return cast_generic_rune(op, caster, dir, stringarg, type);
Line 674
 
Line 744
  stringarg=NULL;   stringarg=NULL;
     }      }
     break;      break;
   
   case SP_LIGHT:    case SP_LIGHT:
     success = cast_light(op,caster,dir);      success = cast_light(op,caster,dir);
     break;      break;
   
   case SP_DAYLIGHT:    case SP_DAYLIGHT:
     success = cast_daylight(op);       success = cast_daylight(op);
     break;       break;
   
   case SP_NIGHTFALL:    case SP_NIGHTFALL:
     success = cast_nightfall(op);      success = cast_nightfall(op);
     break;      break;
   
   case SP_FAERY_FIRE:    case SP_FAERY_FIRE:
     success = cast_faery_fire(op,caster);      success = cast_faery_fire(op,caster);
     break;      break;
   case SP_CAUSE_LIGHT:  
   case SP_CAUSE_HEAVY:  
   case SP_CAUSE_MEDIUM:  
   case SP_CAUSE_CRITICAL:  
  success = fire_arch(op,caster,dir,spellarch[type],type,1); /* don't want to OR magic */  
   break;  
   case SP_SUMMON_FOG:    case SP_SUMMON_FOG:
  success = summon_fog(op,caster,dir,type);   success = summon_fog(op,caster,dir,type);
  break;   break;
   
   case SP_PACIFY:    case SP_PACIFY:
  cast_pacify(op,caster,spellarch[type],type);   cast_pacify(op,caster,spellarch[type],type);
  success = 1;   success = 1;
   break;    break;
   
   case SP_COMMAND_UNDEAD:    case SP_COMMAND_UNDEAD:
  cast_charm_undead(op,caster,spellarch[type],type);   cast_charm_undead(op,caster,spellarch[type],type);
  success = 1;   success = 1;
   break;    break;
   
   case SP_CHARM:    case SP_CHARM:
  cast_charm(op,caster,spellarch[type],type);   cast_charm(op,caster,spellarch[type],type);
  success = 1;   success = 1;
  break;   break;
   /* huma */  
   case SP_CREATE_MISSILE:    case SP_CREATE_MISSILE:
     success = cast_create_missile(op,caster,dir,stringarg);      success = cast_create_missile(op,caster,dir,stringarg);
     break;      break;
   
   case SP_CAUSE_COLD:    case SP_CAUSE_COLD:
   case SP_CAUSE_EBOLA:    case SP_CAUSE_EBOLA:
   case SP_CAUSE_FLU:    case SP_CAUSE_FLU:
Line 723
 
Line 796
   case SP_CAUSE_RABIES:    case SP_CAUSE_RABIES:
     success = cast_cause_disease(op,caster,dir,spellarch[type],type);      success = cast_cause_disease(op,caster,dir,spellarch[type],type);
     break;      break;
     /* DAMN */  
   case SP_DANCING_SWORD:    case SP_DANCING_SWORD:
   case SP_STAFF_TO_SNAKE:     case SP_STAFF_TO_SNAKE:
   case SP_ANIMATE_WEAPON:    case SP_ANIMATE_WEAPON:
     success = animate_weapon(op,caster,dir,spellarch[type],type);      success = animate_weapon(op,caster,dir,spellarch[type],type);
     break;      break;
   
   case SP_SANCTUARY:    case SP_SANCTUARY:
   case SP_FLAME_AURA:    case SP_FLAME_AURA:
     success = create_aura(op,caster,spellarch[type],type,0);      success = create_aura(op,caster,spellarch[type],type,0);
     break;      break;
   
   case SP_CONFLICT:    case SP_CONFLICT:
     success = cast_cause_conflict(op,caster,spellarch[type],type);      success = cast_cause_conflict(op,caster,spellarch[type],type);
     break;      break;
   
   case SP_TOWN_PORTAL:    case SP_TOWN_PORTAL:
     success= cast_create_town_portal (op,caster,dir);      success= cast_create_town_portal (op,caster,dir);
     break;      break;
   case SP_MISSILE_SWARM: {  
     success = 1;  
     fire_swarm(op, caster, dir, spellarch[type], SP_M_MISSILE,  
  die_roll(3, 3, op, PREFER_HIGH) +  
      SP_level_strength_adjust(op,caster, type), 0);  
     break;  
   }  
   }    }
   
   play_sound_map(op->map, op->x, op->y, SOUND_CAST_SPELL_0 + type);    play_sound_map(op->map, op->x, op->y, SOUND_CAST_SPELL_0 + type);
Line 763
 
Line 832
   
 int cast_create_obj(object *op,object *caster,object *new_op, int dir)  int cast_create_obj(object *op,object *caster,object *new_op, int dir)
 {  {
   if(dir && blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {      if(dir &&
          (get_map_flags(op->map,NULL, op->x+freearr_x[dir],op->y+freearr_y[dir], NULL, NULL) & (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.");
     new_draw_info(NDI_UNIQUE, 0,op,"You cast it at your feet.");      new_draw_info(NDI_UNIQUE, 0,op,"You cast it at your feet.");
     dir = 0;      dir = 0;
Line 776
 
Line 846
   
 int summon_monster(object *op,object *caster,int dir,archetype *at,int spellnum) {  int summon_monster(object *op,object *caster,int dir,archetype *at,int spellnum) {
   object *tmp;    object *tmp;
       sint16 x, y;
       mapstruct *m;
   
   if(op->type==PLAYER)    if(op->type==PLAYER)
     if(op->contr->golem!=NULL&&!QUERY_FLAG(op->contr->golem,FLAG_FREED)) {   if (op->contr->golem!=NULL && op->contr->golem_count == op->contr->golem->count) {
       control_golem(op->contr->golem,dir);        control_golem(op->contr->golem,dir);
       return 0;        return 0;
     }      }
   
   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);
   if((dir==-1) || 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((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;
   }    }
   
   tmp=arch_to_object(at);    tmp=arch_to_object(at);
   if(op->type==PLAYER) {    if(op->type==PLAYER) {
     CLEAR_FLAG(tmp, FLAG_MONSTER);      CLEAR_FLAG(tmp, FLAG_MONSTER);
Line 814
 
Line 894
   }    }
   
   /* make the speed positive.*/    /* make the speed positive.*/
       tmp->speed = FABS(tmp->speed);
   if(tmp->speed < 0) tmp->speed = -tmp->speed;  
   
   /*  This sets the level dependencies on dam and hp for monsters */    /*  This sets the level dependencies on dam and hp for monsters */
   if(op->type==PLAYER) {  /* players can't cope with too strong summonings. */      /* players can't cope with too strong summonings. */
     /* but monsters can.  reserve these for players. */      /* but monsters can.  reserve these for players. */
       if(op->type==PLAYER) {
     tmp->stats.hp = SP_PARAMETERS[spellnum].bdur +      tmp->stats.hp = SP_PARAMETERS[spellnum].bdur +
                     10 * SP_level_strength_adjust(op,caster,spellnum);                      10 * SP_level_strength_adjust(op,caster,spellnum);
     tmp->stats.dam= SP_PARAMETERS[spellnum].bdam +      tmp->stats.dam= SP_PARAMETERS[spellnum].bdam +
Line 835
 
Line 915
  /*  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 855
 
Line 936
  * function doing so.   * function doing so.
  */   */
   
 static int ok_to_put_more(mapstruct *m,int x,int y,object *op,int immune_stop) {  static int ok_to_put_more(mapstruct *m,sint16 x,sint16 y,object *op,int immune_stop) {
     object *tmp;      object *tmp;
       int mflags;
       mapstruct *mp;
   
     /* No check for out of map was here before - probably caught when the      mp = m;
      * calling function tries to insert the object.  But a check here      mflags = get_map_flags(m, &mp, x, y, &x, &y);
      * should only be a minor performance hit, and is a good thing.  
      */  
   
     if (out_of_map(m,x,y)) return 0;  
   
     if (OUT_OF_REAL_MAP(m,x,y))      if (mflags & P_OUT_OF_MAP) return 0;
  m = get_map_from_coord(m,&x,&y);  
   
     /* if there is a wall, certainly can't put the spell there.  The blocks      if(mflags & P_WALL) return 0;
      * view check is historic from the old calling functions - my personal  
      * view is that blocks view should not affect spells in any way, but  
      * I will leave it in for now.  
      */  
     if(wall(m,x,y) || blocks_view(m,x,y)) return 0;  
   
     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 there is a counterspell on the space, and this   /* If there is a counterspell on the space, and this
Line 918
 
Line 991
   
 int fire_bolt(object *op,object *caster,int dir,int type,int magic) {  int fire_bolt(object *op,object *caster,int dir,int type,int magic) {
   object *tmp=NULL;    object *tmp=NULL;
       int mflags;
   
   if (!spellarch[type])    if (!spellarch[type])
     return 0;      return 0;
   
   tmp=arch_to_object(spellarch[type]);    tmp=arch_to_object(spellarch[type]);
   if(tmp==NULL)    if(tmp==NULL)
     return 0;      return 0;
   
   /*  peterm:  level dependency for bolts  */    /*  peterm:  level dependency for bolts  */
   tmp->stats.dam = SP_PARAMETERS[type].bdam + SP_level_dam_adjust(op,caster,type);    tmp->stats.dam = SP_PARAMETERS[type].bdam + SP_level_dam_adjust(op,caster,type);
   tmp->stats.hp = SP_PARAMETERS[type].bdur + SP_level_strength_adjust(op,caster,type);    tmp->stats.hp = SP_PARAMETERS[type].bdur + SP_level_strength_adjust(op,caster,type);
   if(magic)    if(magic)
     tmp->attacktype|=AT_MAGIC;      tmp->attacktype|=AT_MAGIC;
   
   tmp->x=op->x,tmp->y=op->y;    tmp->x=op->x,tmp->y=op->y;
   tmp->direction=dir;    tmp->direction=dir;
   if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE))    if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE))
     SET_ANIMATION(tmp, dir);      SET_ANIMATION(tmp, dir);
   set_owner(tmp,op);    set_owner(tmp,op);
   tmp->level = SK_level (caster);    tmp->level = SK_level (caster);
   tmp->x+=DIRX(tmp),tmp->y+=DIRY(tmp);      tmp->x+=DIRX(tmp);
   if(wall(op->map,tmp->x,tmp->y)) {      tmp->y+=DIRY(tmp);
       tmp->map = op->map;
   
       mflags = get_map_flags(tmp->map, &tmp->map, tmp->x, tmp->y, &tmp->x, &tmp->y);
       if (mflags & P_OUT_OF_MAP) {
    free_object(tmp);
    return 0;
       }
       if (mflags & P_WALL) {
     if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) {      if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) {
       free_object(tmp);        free_object(tmp);
       return 0;        return 0;
     }      }
     tmp->x=op->x,tmp->y=op->y;      tmp->x=op->x,tmp->y=op->y;
     tmp->direction=absdir(tmp->direction+4);      tmp->direction=absdir(tmp->direction+4);
    tmp->map = op->map;
   }    }
   if ((tmp = insert_ob_in_map(tmp,op->map,op,0)) != NULL)      if ((tmp = insert_ob_in_map(tmp,tmp->map,op,0)) != NULL)
     move_bolt (tmp);      move_bolt (tmp);
   return 1;    return 1;
 }  }
Line 1023
 
Line 1110
   object *tmp;    object *tmp;
   int i,success=0,range_min= -1,range_max=1;    int i,success=0,range_min= -1,range_max=1;
   
   if(!dir)      if(!dir) {
     range_min= -3,range_max=4,strength/=2;   range_min= -3;
    range_max=4;
    strength/=2;
       }
   
   for(i=range_min;i<=range_max;i++) {    for(i=range_min;i<=range_max;i++) {
     int x=op->x+freearr_x[absdir(dir+i)],      int x=op->x+freearr_x[absdir(dir+i)],
         y=op->y+freearr_y[absdir(dir+i)];          y=op->y+freearr_y[absdir(dir+i)];
     if(wall(op->map,x,y))  
    if(get_map_flags(op->map,NULL, x,y, NULL, NULL) & P_WALL)
       continue;        continue;
   
     success=1;      success=1;
     tmp=arch_to_object(spell_arch);      tmp=arch_to_object(spell_arch);
     set_owner(tmp,op);      set_owner(tmp,op);
Line 1042
 
Line 1134
     if((tmp->attacktype&AT_HOLYWORD)||(tmp->attacktype&AT_GODPOWER)) {      if((tmp->attacktype&AT_HOLYWORD)||(tmp->attacktype&AT_GODPOWER)) {
             if(!tailor_god_spell(tmp,op)) return 0;                if(!tailor_god_spell(tmp,op)) return 0; 
     } else /* god/holy word isnt really 'magic' */      } else /* god/holy word isnt really 'magic' */
   
     if(magic)      if(magic)
       tmp->attacktype|=AT_MAGIC;  /* JWI cone attacks should be considered        tmp->attacktype|=AT_MAGIC;  /* JWI cone attacks should be considered
                                      magical in nature ;) */                                       magical in nature ;) */
Line 1050
 
Line 1141
       tmp->stats.sp=dir;        tmp->stats.sp=dir;
     else      else
       tmp->stats.sp=i;        tmp->stats.sp=i;
   
     tmp->stats.hp=strength+SP_level_strength_adjust(op,caster,spell_type);      tmp->stats.hp=strength+SP_level_strength_adjust(op,caster,spell_type);
     tmp->stats.dam=SP_PARAMETERS[spell_type].bdam +      tmp->stats.dam=SP_PARAMETERS[spell_type].bdam +
                   SP_level_dam_adjust(op,caster,spell_type);                     SP_level_dam_adjust(op,caster,spell_type);
     tmp->stats.maxhp=tmp->count;      tmp->stats.maxhp=tmp->count;
   
     if ( ! QUERY_FLAG (tmp, FLAG_FLYING))      if ( ! QUERY_FLAG (tmp, FLAG_FLYING))
       LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n",        LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n",
            spell_arch->name);             spell_arch->name);
   
     if (( ! QUERY_FLAG (tmp, FLAG_WALK_ON) || ! QUERY_FLAG (tmp, FLAG_FLY_ON))      if (( ! QUERY_FLAG (tmp, FLAG_WALK_ON) || ! QUERY_FLAG (tmp, FLAG_FLY_ON))
         && tmp->stats.dam)          && tmp->stats.dam)
   
       LOG (llevDebug, "cast_cone(): arch %s doesn't have walk_on 1 and "        LOG (llevDebug, "cast_cone(): arch %s doesn't have walk_on 1 and "
            "fly_on 1\n", spell_arch->name);             "fly_on 1\n", spell_arch->name);
   
     insert_ob_in_map(tmp,op->map,op,0);      insert_ob_in_map(tmp,op->map,op,0);
     if(tmp->other_arch) cone_drop(tmp);      if(tmp->other_arch) cone_drop(tmp);
   }    }
Line 1101
 
Line 1197
      move_object(tmp, absdir(op->stats.sp));       move_object(tmp, absdir(op->stats.sp));
  }   }
   
 #if 0  
  int nx,ny;  
  /* This block of code doesn't work for multispaced monsters (or potentially  
  * other multispaced objects).  Since we already have move_ob which will  
  * do most of this work for us, might as well use that.  
  */  
         
  nx = op->x + freearr_x[absdir(op->stats.sp)];  
  ny = op->y + freearr_y[absdir(op->stats.sp)];  
   
  /* don't try to move something someplace where it can't go */  
  if(arch_blocked(tmp->arch,op->map,nx,ny)) continue;  
         
  /* OK, now we decide if we're going to move it */  
  /* assume a weightless thing is a spell or whatever */  
  if(tmp->weight==0) continue;  
   
  /* count the object's sections */  
  for(tmp2 = tmp; tmp2!=NULL;tmp2=tmp2->more) num_sections++;  
         
  if(rndm(0, weight_move-1) > tmp->weight/num_sections) {  /* move it. */  
      remove_ob(tmp);  
      tmp->x = nx;  
      tmp->y = ny;  
      insert_ob_in_map(tmp,op->map,op,0);  
  }  
 #endif  
     }      }
 }  }
   
Line 1265
 
Line 1334
     free_object(op);      free_object(op);
     return;      return;
   }    }
   if(op->above!=NULL&&op->above->type!=PLAYER) {  
     SET_FLAG (op, FLAG_NO_APPLY);  
     remove_ob(op);  
     insert_ob_in_map(op,op->map,op,0);  
     CLEAR_FLAG (op, FLAG_NO_APPLY);  
   }  
   hit_map(op,0,op->attacktype);    hit_map(op,0,op->attacktype);
   
   if(op->stats.hp>2&&!op->value) {    if(op->stats.hp>2&&!op->value) {
     op->value=1;      op->value=1;
     for(i=1;i<9;i++) {      for(i=1;i<9;i++) {
       int dx,dy;        int dx,dy;
       if(wall(op->map,dx=op->x+freearr_x[i],dy=op->y+freearr_y[i]))  
         continue;       dx=op->x+freearr_x[i];
       if(blocks_view(op->map, dx, dy))       dy=op->y+freearr_y[i];
         continue;       /* ok_to_put_more already does things like checks for walls,
         * out of map, etc.
         */
       if(ok_to_put_more(op->map,dx,dy,op,op->attacktype)) {        if(ok_to_put_more(op->map,dx,dy,op,op->attacktype)) {
         tmp=get_object();          tmp=get_object();
         copy_object(op,tmp); /* This is probably overkill on slow computers.. */          copy_object(op,tmp); /* This is probably overkill on slow computers.. */
Line 1287
 
Line 1353
         tmp->speed_left= -0.21;          tmp->speed_left= -0.21;
         tmp->stats.hp--;          tmp->stats.hp--;
         tmp->value=0;          tmp->value=0;
         tmp->x=dx,tmp->y=dy;   tmp->x=dx;
    tmp->y=dy;
         insert_ob_in_map(tmp,m,op,0);          insert_ob_in_map(tmp,m,op,0);
       }        }
     }      }
Line 1300
 
Line 1367
   int t_dir; /* stores temporary dir calculation */    int t_dir; /* stores temporary dir calculation */
   
   /* pick a fork direction.  tmp->stats.Con is the left bias    /* pick a fork direction.  tmp->stats.Con is the left bias
       i.e., the chance in 100 of forking LEFT       * i.e., the chance in 100 of forking LEFT
    Should start out at 50, down to 25 for one already going left       * Should start out at 50, down to 25 for one already going left
       down to 0 for one going 90 degrees left off original path*/       * down to 0 for one going 90 degrees left off original path
        */
        
   if(rndm(0, 99) < tmp->stats.Con)  /* fork left */    if(rndm(0, 99) < tmp->stats.Con)  /* fork left */
  new_dir = -1;   new_dir = -1;
        
    /* check the new dir for a wall and in the map*/     /* check the new dir for a wall and in the map*/
   t_dir = absdir(tmp->direction + new_dir);    t_dir = absdir(tmp->direction + new_dir);
   if(wall(tmp->map,tmp->x + freearr_x[t_dir],tmp->y + freearr_y[t_dir])  
    || out_of_map(tmp->map,tmp->x + freearr_x[t_dir],tmp->y + freearr_y[t_dir]))      if(get_map_flags(tmp->map,NULL, tmp->x + freearr_x[t_dir],tmp->y + freearr_y[t_dir],
         NULL, NULL) & (P_WALL | P_OUT_OF_MAP))
  new_dir = 0;   new_dir = 0;
   
   if(new_dir) { /* OK, we made a fork */    if(new_dir) { /* OK, we made a fork */
  object *new_bolt = get_object();   object *new_bolt = get_object();
   
  copy_object(tmp,new_bolt);   copy_object(tmp,new_bolt);
   
  /* reduce chances of subsequent forking */   /* reduce chances of subsequent forking */
Line 1339
 
Line 1409
  * be reflected from the given mapsquare. Returns 1 if true.   * be reflected from the given mapsquare. Returns 1 if true.
  * (Note that for living creatures there is a small chance that   * (Note that for living creatures there is a small chance that
  * reflect_spell fails.)   * reflect_spell fails.)
    * Caller should be sure it passes us valid map coordinates
    * eg, updated for tiled maps.
  */   */
 int reflwall(mapstruct *m,int x,int y, object *sp_op) {  int reflwall(mapstruct *m,int x,int y, object *sp_op) {
   object *op;    object *op;
   if(out_of_map(m,x,y)) return 0;  
       if(OUT_OF_REAL_MAP(m,x,y)) return 0;
   for(op=get_map_ob(m,x,y);op!=NULL;op=op->above)    for(op=get_map_ob(m,x,y);op!=NULL;op=op->above)
     if(QUERY_FLAG(op, FLAG_REFL_SPELL) && (!QUERY_FLAG(op, FLAG_ALIVE) ||      if(QUERY_FLAG(op, FLAG_REFL_SPELL) && (!QUERY_FLAG(op, FLAG_ALIVE) ||
        sp_op->type==LIGHTNING || (rndm(0, 99)) < 90-sp_op->level/10))         sp_op->type==LIGHTNING || (rndm(0, 99)) < 90-sp_op->level/10))
       return 1;        return 1;
   
   return 0;    return 0;
 }  }
   
 void move_bolt(object *op) {  void move_bolt(object *op) {
   object *tmp;    object *tmp;
   int w,r;      int r, mflags;
       sint16 x, y;
       mapstruct *m;
   
   if(--(op->stats.hp)<0) {    if(--(op->stats.hp)<0) {
     remove_ob(op);      remove_ob(op);
     free_object(op);      free_object(op);
     return;      return;
   }    }
   hit_map(op,0,op->attacktype);    hit_map(op,0,op->attacktype);
   
   if(!op->value&&--(op->stats.exp)>0) {    if(!op->value&&--(op->stats.exp)>0) {
     op->value=1;      op->value=1;
     if(!op->direction)      if(!op->direction)
       return;        return;
   
     if(blocks_view(op->map,op->x+DIRX(op),op->y+DIRY(op)))   x = op->x+DIRX(op);
       return;   y = op->y+DIRY(op);
     w=wall(op->map,op->x+DIRX(op),op->y+DIRY(op));   m = op->map;
     r=reflwall(op->map,op->x+DIRX(op),op->y+DIRY(op), op);   mflags = get_map_flags(op->map, &m, x, y, &x, &y);
     if(w&&!QUERY_FLAG(op, FLAG_REFLECTING))  
       return;   r=reflwall(m, x, y, op);
     if(w||r) { /* We're about to bounce */   /* We are about to run into something - we may bounce */
    if((mflags & P_WALL) || r ) { /* We're about to bounce */
       if(!QUERY_FLAG(op, FLAG_REFLECTING))        if(!QUERY_FLAG(op, FLAG_REFLECTING))
         return;          return;
   
       op->value=0;        op->value=0;
        /* Since walls don't run diagonal, if the bolt is in
         * one of 4 main directions, it just reflects back in the
         * opposite direction.  However, if the bolt is travelling
         * on the diagonal, it is trickier - eg, a bolt travelling
         * northwest bounces different if it hits a north/south
         * wall (bounces to northeast) vs an east/west (bounces
         * to the southwest.
         */
       if(op->direction&1)        if(op->direction&1)
         op->direction=absdir(op->direction+4);          op->direction=absdir(op->direction+4);
       else {        else {
         int left= wall(op->map,op->x+freearr_x[absdir(op->direction-1)],   int left, right;
                               op->y+freearr_y[absdir(op->direction-1)]),  
             right=wall(op->map,op->x+freearr_x[absdir(op->direction+1)],   left = get_map_flags(op->map, NULL, op->x+freearr_x[absdir(op->direction-1)],
                               op->y+freearr_y[absdir(op->direction+1)]);          op->y+freearr_y[absdir(op->direction-1)], NULL, NULL) & P_WALL;
   
    right = get_map_flags(op->map,NULL, op->x+freearr_x[absdir(op->direction+1)],
                                 op->y+freearr_y[absdir(op->direction+1)], NULL, NULL) & P_WALL;
   
         if(left==right)          if(left==right)
           op->direction=absdir(op->direction+4);            op->direction=absdir(op->direction+4);
         else if(left)          else if(left)
Line 1401
 
Line 1493
       tmp = insert_ob_in_map(tmp,op->map,op,0);        tmp = insert_ob_in_map(tmp,op->map,op,0);
   
  /* New forking code.  Possibly create forks of this object   /* New forking code.  Possibly create forks of this object
  going off in other directions. */        * going off in other directions.
         */
   
       if(rndm(0, 99)< tmp->stats.Dex) {  /* stats.Dex % of forking */        if(rndm(0, 99)< tmp->stats.Dex) {  /* stats.Dex % of forking */
  forklightning(op,tmp);   forklightning(op,tmp);
Line 1413
 
Line 1506
         } else {          } else {
           tmp->stats.food = 0;            tmp->stats.food = 0;
         }          }
       }       } /* if tmp */
     }   } /* copy object and move it along */
   }      } /* if move bolt along */
 }  }
   
   
Line 1519
 
Line 1612
   
   
 void move_missile(object *op) {  void move_missile(object *op) {
   int i;      int i, mflags;
   object *owner;    object *owner;
   sint16 new_x, new_y;    sint16 new_x, new_y;
   
   owner = get_owner(op);    owner = get_owner(op);
       /* It'd make things nastier if this wasn't here - spells cast by
        * monster that are then killed would continue to survive
        */
   if (owner == NULL) {    if (owner == NULL) {
     remove_ob(op);      remove_ob(op);
     free_object(op);      free_object(op);
Line 1533
 
Line 1629
   new_x = op->x + DIRX(op);    new_x = op->x + DIRX(op);
   new_y = op->y + DIRY(op);    new_y = op->y + DIRY(op);
   
   if (blocked (op->map, new_x, new_y)) {      mflags = get_map_flags(op->map, NULL, new_x, new_y, NULL, NULL);
   
       if (mflags & P_BLOCKED) {
     tag_t tag = op->count;      tag_t tag = op->count;
     hit_map (op, op->direction, AT_MAGIC);      hit_map (op, op->direction, AT_MAGIC);
     if ( ! was_destroyed (op, tag)) {      if ( ! was_destroyed (op, tag)) {
Line 1544
 
Line 1642
   }    }
   
   remove_ob(op);    remove_ob(op);
   if ( ! op->direction || wall (op->map, new_x, new_y)      if ( ! op->direction || (mflags & P_WALL)) {
       || blocks_view (op->map, new_x, new_y))  
   {  
     free_object(op);      free_object(op);
     return;      return;
   }    }
Line 1657
 
Line 1753
 {  {
     tag_t op_tag = op->count, tmp_tag;      tag_t op_tag = op->count, tmp_tag;
     object *tmp;      object *tmp;
     int dam;      int dam, mflags;
   
       mflags = get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL);
   
     if ( ! blocked (op->map, op->x, op->y))      if ( ! (mflags & P_BLOCKED))
         return;          return;
   
     if (op->other_arch) {      if (op->other_arch) {
Line 1667
 
Line 1765
         return;          return;
     }      }
   
       /* If nothing alive on this space, no reason to do anything further */
       if (!(mflags & P_IS_ALIVE)) return;
   
     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 (QUERY_FLAG (tmp, FLAG_ALIVE)) {          if (QUERY_FLAG (tmp, FLAG_ALIVE)) {
Line 1691
 
Line 1792
 void move_fired_arch (object *op)  void move_fired_arch (object *op)
 {  {
     tag_t op_tag = op->count;      tag_t op_tag = op->count;
     int new_x, new_y;      sint16 new_x, new_y;
       int mflags;
       mapstruct *m;
   
   
     /* peterm:  added to make comet leave a trail of burnouts       /* peterm:  added to make comet leave a trail of burnouts
  it's an unadulterated hack, but the effect is cool. */   it's an unadulterated hack, but the effect is cool. */
Line 1703
 
Line 1807
   
     new_x = op->x + DIRX(op);      new_x = op->x + DIRX(op);
     new_y = op->y + DIRY(op);      new_y = op->y + DIRY(op);
     if (out_of_map (op->map, new_x, new_y)) {      m = op->map;
       mflags = get_map_flags(m, &m, new_x, new_y, &new_x, &new_y);
   
       if (mflags & P_OUT_OF_MAP) {
         remove_ob (op);          remove_ob (op);
         free_object (op);          free_object (op);
         return;          return;
     }      }
   
     if ( ! op->direction || wall (op->map, new_x, new_y)) {      if ( ! op->direction || (mflags & P_WALL)) {
         if (op->other_arch) {          if (op->other_arch) {
             explode_object (op);              explode_object (op);
         } else {          } else {
Line 1722
 
Line 1829
     remove_ob (op);      remove_ob (op);
     op->x = new_x;      op->x = new_x;
     op->y = new_y;      op->y = new_y;
     if ((op = insert_ob_in_map (op, op->map, op,0)) == NULL)      if ((op = insert_ob_in_map (op, m, op,0)) == NULL)
         return;          return;
   
     if (reflwall (op->map, op->x, op->y, op)) {      if (reflwall (op->map, op->x, op->y, op)) {
Line 1780
 
Line 1887
 }  }
   
   
 /*  peterm: ball lightning mover.  */  /*  peterm: ball lightning mover.
 /*  ball lightning automatically seeks out a victim, if   *  ball lightning automatically seeks out a victim, if
     it sees any monsters close enough.  */   *  it sees any monsters close enough.
    */
 void move_ball_lightning(object *op) {  void move_ball_lightning(object *op) {
   int i,nx,ny,j,dam_save,dir;      int i,nx,ny,j,dam_save,dir, mflags;
   object *owner;    object *owner;
       mapstruct *m;
    
   owner = get_owner(op);    owner = get_owner(op);
   
Line 1798
 
Line 1907
   }    }
   
   /*  the following logic makes sure that the ball    /*  the following logic makes sure that the ball
       doesn't move into a wall, and makes       * doesn't move into a wall, and makes
       sure that it will move along a wall to try and       * sure that it will move along a wall to try and
       get at it's victim.  */       * get at it's victim. 
        */
   
   dir = 0;    dir = 0;
   
   if(!(rndm(0, 3)))    if(!(rndm(0, 3)))
     j = rndm(0, 1);      j = rndm(0, 1);
   else j=0; /* ? j wasn't being assigned to anything before */    else j=0; /* ? j wasn't being assigned to anything before */
   
   for(i = 1; i < 9; i++) {    for(i = 1; i < 9; i++) {
     /* i bit 0: alters sign of offset      /* i bit 0: alters sign of offset
      * otther bits (i / 2): absolute value of offset       * otther bits (i / 2): absolute value of offset
Line 1813
 
Line 1925
   
     int offset = ((i ^ j) & 1) ? (i / 2) : - (i / 2);      int offset = ((i ^ j) & 1) ? (i / 2) : - (i / 2);
     int tmpdir = absdir (op->direction + offset);      int tmpdir = absdir (op->direction + offset);
   
     nx = op->x + freearr_x[tmpdir];      nx = op->x + freearr_x[tmpdir];
     ny = op->y + freearr_y[tmpdir];      ny = op->y + freearr_y[tmpdir];
     if ( ! wall (op->map, nx, ny) ) {   if ( ! (get_map_flags(op->map, NULL, nx, ny, NULL, NULL) & P_WALL)) {
       dir = tmpdir;        dir = tmpdir;
       break;        break;
     }      }
Line 1835
 
Line 1948
   
   /* loop over current square and neighbors to hit. */    /* loop over current square and neighbors to hit. */
   for(j=0;j<9;j++) {    for(j=0;j<9;j++) {
     int hx,hy;  /* hit these squares */   sint16 hx,hy;  /* hit these squares */
     object *new_ob;      object *new_ob;
   
     hx = nx+freearr_x[j]; hy = ny+freearr_y[j];   hx = nx+freearr_x[j];
    hy = ny+freearr_y[j];
   
    m = op->map;
    mflags = get_map_flags(m, &m, hx, hy, &hx, &hy);
   
    if (mflags & P_OUT_OF_MAP) continue;
               
     /* first, don't ever, ever hit the owner.  Don't hit out      /* first, don't ever, ever hit the owner.  Don't hit out
        of the map either.*/   * of the map either.
     if(! (owner && owner->x==hx && owner->y==hy) && !out_of_map(op->map,hx,hy)) {   */
       if(j) op->stats.dam = dam_save/2;  
        
       if(blocked(op->map,hx,hy)) hit_map(op,j,op->attacktype);   if((mflags & P_IS_ALIVE) && (!owner || owner->x!=hx || owner->y!=hy || owner->map != m)) {
        if(j) op->stats.dam = dam_save/2;
        hit_map(op,j,op->attacktype);
   
     }      }
     if(out_of_map(op->map,hx,hy) ||   if(!(mflags & P_WALL) && op->other_arch) { /* insert the other arch */
        wall(op->map,hx,hy)) continue;  
     if(op->other_arch) { /* insert the other arch */  
       new_ob = arch_to_object(op->other_arch);        new_ob = arch_to_object(op->other_arch);
       new_ob->x = hx;        new_ob->x = hx;
       new_ob->y = hy;        new_ob->y = hy;
       insert_ob_in_map(new_ob,op->map,op,0);       insert_ob_in_map(new_ob,m,op,0);
     }      }
   }    }
   
   /* restore to the center location and damage*/    /* restore to the center location and damage*/
   op->stats.dam = dam_save;    op->stats.dam = dam_save;
   i=spell_find_dir(op->map,op->x,op->y,get_owner(op));    i=spell_find_dir(op->map,op->x,op->y,get_owner(op));
   
   if(i>=0) { /* we have a preferred direction!  */    if(i>=0) { /* we have a preferred direction!  */
     /* pick another direction if the preferred dir is blocked. */      /* pick another direction if the preferred dir is blocked. */
     if(wall(op->map,nx + freearr_x[i], ny + freearr_y[i])) {   if(get_map_flags(op->map,NULL, nx + freearr_x[i], ny + freearr_y[i],NULL,NULL) & P_WALL) {
       i+= rndm(0, 2)-1;  /* -1, 0, +1 */       i= absdir(i + rndm(0, 2) -1);  /* -1, 0, +1 */
       if(i==0) i=8;  
       if(i==9) i=1;  
     }      }
     op->direction=i;      op->direction=i;
   }    }
Line 1941
 
Line 2058
    
   
 int can_see_monsterP(mapstruct *m, int x, int y,int dir) {  int can_see_monsterP(mapstruct *m, int x, int y,int dir) {
     int dx, dy;  /* delta (dx)  */      sint16 dx, dy;
       int mflags;
   
     if(dir<0) return 0;  /* exit condition:  invalid direction */      if(dir<0) return 0;  /* exit condition:  invalid direction */
   
     dx = x + freearr_x[dir];      dx = x + freearr_x[dir];
     dy = y + freearr_y[dir];      dy = y + freearr_y[dir];
   
     if (out_of_map(m, dx, dy)) return 0;      mflags = get_map_flags(m, &m, dx, dy, &dx, &dy);
   
     m = get_map_from_coord(m, &dx, &dy);      if (mflags & (P_OUT_OF_MAP | P_WALL)) return 0;
   
     if(wall(m,dx,dy)) return 0;  
   
     /* yes, can see. */      /* yes, can see. */
     if(dir < 9) return 1;      if(dir < 9) return 1;
Line 1967
 
Line 2083
  * spell_find_dir(map, x, y, exclude) will search first the center square   * spell_find_dir(map, x, y, exclude) will search first the center square
  * then some close squares in the given map at the given coordinates for   * then some close squares in the given map at the given coordinates for
  * live objects.   * live objects.
  * It will not consider the object given as exlude (= caster) among possible   * It will not consider the object given as exclude (= caster) among possible
  * live objects. If the caster is a player, the spell will go after   * live objects. If the caster is a player, the spell will go after
  * monsters/generators only. If not, the spell will hunt players only.   * monsters/generators only. If not, the spell will hunt players only.
  * It returns the direction toward the first/closest live object if it finds   * It returns the direction toward the first/closest live object if it finds
Line 1976
 
Line 2092
   
 int spell_find_dir(mapstruct *m, int x, int y, object *exclude) {  int spell_find_dir(mapstruct *m, int x, int y, object *exclude) {
   int i,max=SIZEOFFREE;    int i,max=SIZEOFFREE;
   int nx,ny;      sint16 nx,ny;
   int owner_type=0;      int owner_type=0, mflags;
   object *tmp;    object *tmp;
       mapstruct *mp;
   
   if (exclude && exclude->head)    if (exclude && exclude->head)
     exclude = exclude->head;      exclude = exclude->head;
Line 1988
 
Line 2105
   for(i=rndm(1, 8);i<max;i++) {    for(i=rndm(1, 8);i<max;i++) {
     nx = x + freearr_x[i];      nx = x + freearr_x[i];
     ny = y + freearr_y[i];      ny = y + freearr_y[i];
     if(!out_of_map(m,nx,ny)) {   mp = m;
       tmp=get_map_ob(m,nx,ny);   mflags = get_map_flags(m, &mp, nx, ny, &nx, &ny);
    if (mflags & P_OUT_OF_MAP) continue;
   
    tmp=get_map_ob(mp,nx,ny);
   
       while(tmp!=NULL && (((owner_type==PLAYER &&        while(tmp!=NULL && (((owner_type==PLAYER &&
      !QUERY_FLAG(tmp,FLAG_MONSTER) && !QUERY_FLAG(tmp,FLAG_GENERATOR)) ||       !QUERY_FLAG(tmp,FLAG_MONSTER) && !QUERY_FLAG(tmp,FLAG_GENERATOR)) ||
             (owner_type!=PLAYER && tmp->type!=PLAYER)) ||              (owner_type!=PLAYER && tmp->type!=PLAYER)) ||
      (tmp == exclude || (tmp->head && tmp->head == exclude))))       (tmp == exclude || (tmp->head && tmp->head == exclude))))
  tmp=tmp->above;   tmp=tmp->above;
       if(tmp!=NULL && can_see_monsterP(m,x,y,i) && !blocks_view(m,nx,ny))  
    if(tmp!=NULL && can_see_monsterP(m,x,y,i) && !(mflags & P_BLOCKSVIEW))
         return freedir[i];          return freedir[i];
     }      }
   }  
   return -1;  /* flag for "keep going the way you were" */    return -1;  /* flag for "keep going the way you were" */
 }  }
   
Line 2089
 
Line 2210
   
   
   
 /*  move_swarm_spell:  peterm  */  /*  move_swarm_spell:  peterm
 /*  This is an implementation of the swarm spell.  It was written for   *  This is an implementation of the swarm spell.  It was written for
 meteor swarm, but it could be used for any swarm.  A swarm spell   * meteor swarm, but it could be used for any swarm.  A swarm spell
 is a special type of object that casts swarms of other types   * is a special type of object that casts swarms of other types
 of spells.  Which spell it casts is flexible.  It fires the spells   * of spells.  Which spell it casts is flexible.  It fires the spells
 from a set of squares surrounding the caster, in a given direction. */   * from a set of squares surrounding the caster, in a given direction.
    */
   
 void move_swarm_spell(object *op)  void move_swarm_spell(object *op)
 {  {
Line 2117
 
Line 2239
     }      }
   
     /* new offset calculation to make swarm element distribution      /* new offset calculation to make swarm element distribution
        more uniform */       * more uniform
        */
     if(op->stats.hp) {      if(op->stats.hp) {
         if(basedir & 1) {           if(basedir & 1) {
             adjustdir = cardinal_adjust[rndm(0, 8)];              adjustdir = cardinal_adjust[rndm(0, 8)];
Line 2132
 
Line 2255
     target_y = op->y + freearr_y[absdir(basedir + adjustdir)];      target_y = op->y + freearr_y[absdir(basedir + adjustdir)];
   
     /* back up one space so we can hit point-blank targets, but this      /* back up one space so we can hit point-blank targets, but this
        necessitates extra out_of_map check below */       * necessitates extra out_of_map check below
        */
     origin_x = target_x - freearr_x[basedir];      origin_x = target_x - freearr_x[basedir];
     origin_y = target_y - freearr_y[basedir];      origin_y = target_y - freearr_y[basedir];
   
    /*  for level dependence, we need to know what spell is fired.  */     /*  for level dependence, we need to know what spell is fired.  */
    /*  that's stored in op->stats.sp  by fire_swarm  */     /*  that's stored in op->stats.sp  by fire_swarm  */
    if ( ! wall (op->map, target_x, target_y)     if ( !(get_map_flags(op->map, NULL, target_x, target_y, NULL, NULL) & P_WALL)
         && ! out_of_map(op->map, origin_x, origin_y))          && ! out_of_map(op->map, origin_x, origin_y))
        fire_arch_from_position (op, op, origin_x, origin_y, basedir,         fire_arch_from_position (op, op, origin_x, origin_y, basedir,
                                 op->other_arch, op->stats.sp, op->magic);                                  op->other_arch, op->stats.sp, op->magic);
Line 2395
 
Line 2519
    
 object *get_pointed_target(object *op, int dir) {  object *get_pointed_target(object *op, int dir) {
   object *target;    object *target;
   int x,y;      sint16 x,y;
       int dist, mflags;
       mapstruct *mp;
   
   if (dir==0) return NULL;    if (dir==0) return NULL;
   for(x=op->x+freearr_x[dir],y=op->y+freearr_y[dir]      /* limit of 20 is arbitrary - really, we should get this
      ;!out_of_map(op->map,x,y)&&!blocks_view(op->map,x,y)       * from spell parameter or something.  But there has to be
      &&!wall(op->map,x,y);x+=freearr_x[dir],y+=freearr_y[dir])       * some upper limit due to the nature of tiled maps.
         for(target=get_map_ob(op->map,x,y);target;target=target->above) {       * Note also that the check for no magic is perhaps bogus
        * if this function is also used for cleric spells.
        */
       for (dist=1; dist<20; dist++) {
    x = op->x + freearr_x[dir] * dist;
    y = op->y + freearr_y[dir] * dist;
    mp = op->map;
    mflags = get_map_flags(op->map, &mp, x, y, &x, &y);
   
    if (mflags & (P_OUT_OF_MAP | P_WALL | P_NO_MAGIC)) return NULL;
    if (mflags & P_IS_ALIVE) {
        for(target=get_map_ob(mp,x,y); target; target=target->above) {
               if(QUERY_FLAG(target->head?target->head:target,FLAG_MONSTER)) {                if(QUERY_FLAG(target->head?target->head:target,FLAG_MONSTER)) {
                    if(!blocks_magic(op->map,x,y))  
                           return target;                            return target;
                    else break;  
        }         }
         }          }
     }
   return ((object *) NULL);      }
       return NULL;
 }  }
   
 /* cast_smite_arch() - the priest points to a creature and causes  /* cast_smite_arch() - the priest points to a creature and causes


Legend:
line(s) removed in v.1.72 
line(s) changed
 line(s) added in v.1.73

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