/
ScryMUD/mud/
ScryMUD/mud/grrmud/Boards/
ScryMUD/mud/grrmud/Help/
ScryMUD/mud/grrmud/Pfiles/
ScryMUD/mud/grrmud/PlayerSacks/
ScryMUD/mud/grrmud/PlayerShops/
ScryMUD/mud/grrmud/help_filter/
ScryMUD/mud/hegemon/
ScryMUD/mud/hegemon/data/
ScryMUD/mud/hegemon/data/help/battle/
ScryMUD/mud/hegemon/data/help/client/
ScryMUD/mud/hegemon/data/help/communications/
ScryMUD/mud/hegemon/data/help/skills/
ScryMUD/mud/hegemon/data/help/spells/
ScryMUD/mud/include/
ScryMUD/mud/lib/
ScryMUD/mud/lib/bitfield/
ScryMUD/mud/lib/log/
ScryMUD/mud/lib/string2/
// $Id: trv_spll.cc,v 1.7.2.3 2000/02/19 17:44:47 justin Exp $
// $Revision: 1.7.2.3 $  $Author: justin $ $Date: 2000/02/19 17:44:47 $

//
//ScryMUD Server Code
//Copyright (C) 1998  Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// To contact the Author, Ben Greear:  greear@cyberhighway.net, (preferred)
//                                     greearb@agcs.com
//

#include "trv_spll.h"
#include "commands.h"
#include "command2.h"
#include <stdio.h>
#include "misc.h"
#include "misc2.h"
#include "battle.h"
#include "classes.h"
#include "spells.h"
#include "skills.h"
#include <PtrArray.h>



void cast_group_heal(critter& pc) {
   int spell_num = GROUP_HEAL_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSN", spell_num, pc)) {
     return;
   }//if

   do_cast_group_heal(pc, FALSE, 0);

}//cast_group_heal



void do_cast_group_heal(critter& agg, int is_canned, int lvl) {
   String buf(100);
   short do_affects = FALSE;
   int spell_num = GROUP_HEAL_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);


   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE); 
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned

   if (do_affects) {

      show("You heal the group.\n", agg);
      Cell<critter*> cll(room_list[agg.getCurRoomNum()].getCrits());
      critter* ptr;
      
      while ((ptr = cll.next())) {
         if (!is_grouped(*ptr, agg)) {
            continue;
         }//if
         
         ptr->HP += (d(8, (40 + lvl/2)));
         if (ptr->HP > ptr->HP_MAX)
            ptr->HP = ptr->HP_MAX;
         
         Sprintf(buf, "%S heals you and your companions.\n",
                 name_of_crit(agg, ptr->SEE_BIT));
         show(buf, *ptr);
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_group_heal


void cast_flame_strike(critter& pc) {
   int spell_num = FLAME_STRIKE_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
     return;
   }//if

   do_cast_flame_strike(pc, FALSE, 0);

}//cast_flame_strike



void do_cast_flame_strike(critter& agg, int is_canned, int lvl) {
   String buf(100);
   short do_affects = FALSE;
   int spell_num = FLAME_STRIKE_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);


   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE); 
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned

   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show_all("Pillars of crimson fire spurt up from below!!\n", 
               room_list[agg.getCurRoomNum()]);

      while ((ptr = rm->findNextSpellCritter())) {
         if ((ptr == &agg) || is_grouped(*ptr, agg)) {
            continue;
         }//if
       
         if (ptr->isMob()) {
            mudlog << "ERROR:  was MOB in do_cast_flame_strike, mob: "
                   << ptr->getName() << " agg: " << agg.getName() << endl;
            continue;
         }//if

         if (TRUE) { 
            exact_raw_damage(d(4, lvl), FIRE, *ptr, agg);
            if (ptr->HP < 0) {
               Sprintf(buf, "You are consumed by %S's pillar of flames.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is consumed by %S's pillar of flames!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               agg_kills_vict(&agg, *ptr);
            }//if
            else {
               Sprintf(buf, "You are burned by %S's pillar of flames.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is burned by %S's pillar of fire!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               if (!HaveData(&agg, ptr->IS_FIGHTING)) {
                  join_in_battle(*ptr, agg);
               }//if
            }//else
         }//if TRUE
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_flame_strike



void cast_meteorstorm(critter& pc) {
   int spell_num = METEORSTORM_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
     return;
   }//if

   do_cast_meteorstorm(pc, FALSE, 0);  //does no error checking
}//cast_meteorstorm



void do_cast_meteorstorm(critter& agg, int is_canned, int lvl) {
   String buf(100);
   short do_affects = FALSE;
   int spell_num = METEORSTORM_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);


   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE); 
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned

   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show_all("Sonic booms rend the air asunder!!\n", 
               room_list[agg.getCurRoomNum()]);

      while ((ptr = rm->findNextSpellCritter())) {
         if ((ptr == &agg) || is_grouped(*ptr, agg)) {
            continue;
         }//if
         
         
         if (ptr->isMob()) {
            mudlog << "ERROR:  was MOB in do_cast_meteor_storm, mob: "
              << ptr->getName() << " agg: " << agg.getName() << endl;
            continue;
         }//if

         if (TRUE) { 
            exact_raw_damage(d(5, lvl), NORMAL, *ptr, agg);
            if (ptr->HP < 0) {
               Sprintf(buf, "You are crushed beyond repair by %S's meteor.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is crushed by %S's meteor!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               agg_kills_vict(&agg, *ptr);
            }//if
            else {
               Sprintf(buf, "You are struck by %S's meteor.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is struck by %S's meteor!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               if (!HaveData(&agg, ptr->IS_FIGHTING)) {
                  join_in_battle(*ptr, agg);
               }//if
            }//else
         }//if TRUE
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_meteorstorm



void cast_icestorm(critter& pc) {
   int spell_num = ICESTORM_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
     return;
   }//if

   do_cast_icestorm(pc, FALSE, 0);  //does no error checking
}//cast_icestorm



void do_cast_icestorm(critter& agg, int is_canned, int lvl) {
   String buf(100);
   short do_affects = FALSE;
   int spell_num = ICESTORM_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);


   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE); 
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned

   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show_all("Large shards of ice start falling from the sky!!\n", 
               room_list[agg.getCurRoomNum()]);

      while ((ptr = rm->findNextSpellCritter())) {
         if ((ptr == &agg) || is_grouped(*ptr, agg)) {
            continue;
         }//if

         if (ptr->isMob()) {
            mudlog << "ERROR:  was MOB in do_cast_meteor_storm, mob: "
                   << ptr->getName() << " agg: " << agg.getName() << endl;
            continue;
         }//if
         
         if (TRUE) { 
            exact_raw_damage(d(4, lvl), NORMAL, *ptr, agg);
            if (ptr->HP < 0) {
               Sprintf(buf,
                       "You are crushed beyond repair by %S's ice shard.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is crushed by %S's ice shard!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               agg_kills_vict(&agg, *ptr);
            }//if
            else {
               Sprintf(buf, "You are struck by %S's ice shard.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is struck by %S's ice shard!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               if (!HaveData(&agg, ptr->IS_FIGHTING)) {
                  join_in_battle(*ptr, agg);
               }//if
            }//else
         }//if TRUE
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_icestorm



void cast_firestorm(critter& pc) {
   int spell_num = FIRESTORM_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
      return;
   }//if

   do_cast_firestorm(pc, FALSE, 0);  //does no error checking
}//cast_firestorm



void do_cast_firestorm(critter& agg, int is_canned, int lvl) {
   String buf(100);
   short do_affects = FALSE;
   int spell_num = FIRESTORM_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);


   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE); 
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned

   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show_all("Globs of flaming vitrol start falling from the sky!!\n", 
               room_list[agg.getCurRoomNum()]);
      
      while ((ptr = rm->findNextSpellCritter())) {
         if ((ptr == &agg) || is_grouped(*ptr, agg)) {
            continue;
         }//if
       
         if (ptr->isMob()) {
            mudlog << "ERROR:  was MOB in do_cast_fire_storm, mob: "
              << ptr->getName() << " agg: " << agg.getName() << endl;
            continue;
         }//if
         
         if (TRUE) { 
            exact_raw_damage(d(4, lvl), FIRE, *ptr, agg);
            if (ptr->HP < 0) {
               Sprintf(buf, "You are burned to a crisp by %S's fire storm.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is burned to a crisp by %S's fire storm!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               agg_kills_vict(&agg, *ptr);
            }//if
            else {
               Sprintf(buf, "You are burned by %S's fire storm.\n",
                       name_of_crit(agg, ptr->SEE_BIT));
               show(buf, *ptr);
               Sprintf(buf, "is burned by %S's fire storm!", 
                       name_of_crit(agg, ~0));
               emote(buf, *ptr, room_list[agg.getCurRoomNum()], TRUE);
               if (!HaveData(&agg, ptr->IS_FIGHTING)) {
                  join_in_battle(*ptr, agg);
               }//if
            }//else
         }//if TRUE
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_firestorm



void do_cast_lightning_storm(critter& agg, int is_canned, int lvl) {
   String buf(100);
   short do_affects = FALSE;
   int spell_num = LIGHTNING_STORM_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);

   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE); 
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned

   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show("A huge broiling cloud gathers overhead!!\n", agg);
      
      while ((ptr = rm->findNextSpellCritter())) {
         if ((ptr == &agg) || is_grouped(*ptr, agg)) {
            continue;
         }//if
       
         if (ptr->isMob()) {
            mudlog << "ERROR:  was MOB in do_cast_lightning_storm, mob: "
                   << ptr->getName() << " agg: " << agg.getName() << endl;
            continue;
         }//if
         
         if (TRUE) { 
            emote("is toasted by a blinding bolt of lightning!", *ptr, 
                  room_list[agg.getCurRoomNum()], TRUE);
            exact_raw_damage(d(5, lvl), ELECTRICITY, *ptr, agg);
            if (ptr->HP < 0) {
               show("You are exploded by the bolt of lightning.\n", *ptr);
               emote("explodes in the bolt of lightning.", *ptr, 
                     room_list[ptr->getCurRoomNum()], TRUE);
               agg_kills_vict(&agg, *ptr);
            }//if
            else {
               show("You are fried by the bolt of lightning!\n", *ptr);
               emote("is struck by the lightning bolt.", *ptr,
                     room_list[ptr->getCurRoomNum()], TRUE);
               if (!HaveData(&agg, ptr->IS_FIGHTING)) {
                  join_in_battle(*ptr, agg);
               }//if
            }//else
         }//if TRUE
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_lightning_storm
 

void cast_lightning_storm(critter& pc) {
   int spell_num = LIGHTNING_STORM_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
     return;
   }//if

   do_cast_lightning_storm(pc, FALSE, 0);  //does no error checking
}//cast_lightning_storm


void do_cast_quake(critter& agg, int is_canned, int lvl) {
   String buf(100);
   short do_affects = FALSE;
   int spell_num = QUAKE_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);

   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE);
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
         return;
      }//else lost concentration
   }//else !canned

   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show_all("The earth heaves violently!!\n",
               room_list[agg.getCurRoomNum()]);
      
      while ((ptr = rm->findNextSpellCritter())) {
         if ((ptr == &agg) || is_grouped(*ptr, agg)) {
            continue;
         }//if

         if (ptr->isMob()) {
            mudlog << "ERROR:  was MOB in do_cast_lightning_storm, mob: "
                   << ptr->getName() << " agg: " << agg.getName() << endl;
            continue;
         }//if
         
         if (!ptr->CRIT_FLAGS.get(3)) { //if not flying
            exact_raw_damage(d(5, lvl), NORMAL, *ptr, agg);
            if (ptr->HP < 0) {
               show("You are mortally injured by the heaving earth.\n", *ptr);
               emote("is mortally injured by the heaving earth.", *ptr, 
                     room_list[ptr->getCurRoomNum()], TRUE);
               agg_kills_vict(&agg, *ptr);
            }//if
            else {
               show("You are injured by the earthquake!\n", *ptr);
               emote("is injured by the earthquake.", *ptr,
                     room_list[ptr->getCurRoomNum()], TRUE);
               if (!HaveData(&agg, ptr->IS_FIGHTING)) {
                  join_in_battle(*ptr, agg);
               }//if
            }//else
         }//if flying
         else {
            show("You fly lightly over the tossing ground.\n", *ptr);
            emote("flies clear of the heaving ground.", *ptr,
                  room_list[ptr->getCurRoomNum()], TRUE);
         }//else
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_quake
 

void cast_quake(critter& pc) {
   int spell_num = QUAKE_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
     return;
   }//if

   if (ROOM.isSmallWater() || ROOM.isBigWater()) {
      show("Earthquakes don't work on open water.\n", pc);
      return;
   }//if
                 /* all checks have been passed, lets do it */

   do_cast_quake(pc, FALSE, 0);  //does no error checking
}//cast_quake


void do_cast_typhoon(critter& agg, int is_canned, int lvl) {
   String buf(100);
   int new_room_num = FALSE;
   short done = FALSE, do_affects = FALSE;
   int spell_num = TYPHOON_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);
   
   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE);
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned
   
   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show_all("The skies grow dark and the wind begins to howl!\n", 
               room_list[agg.getCurRoomNum()]);
      
      short count = 0;
      
      int begin_rm, end_rm;
      int zon = room_list[agg.getCurRoomNum()].getZoneNum();
      begin_rm = ZoneCollection::instance().elementAt(zon).getBeginRoomNum();
      end_rm = ZoneCollection::instance().elementAt(zon).getEndRoomNum();

      while ((ptr = rm->findNextSpellCritter())) {
         if (ptr == &agg) {
            if (d(1,50) > 25) {
               continue;
            }//if
         }//if
       
         done = FALSE;
         int sanity = 0;
         while (!done) {

            if (sanity++ > 10)
               break;
            
            new_room_num = begin_rm + d(1, (end_rm - begin_rm));
            
            if (!room_list.elementAtNoCreate(new_room_num) ||
                (!room_list[new_room_num].hasWeather())) {
               continue;
            }
            
            if (mob_can_enter(*ptr, room_list[new_room_num], FALSE)) {
               done = TRUE;
               if ((ptr->POS == POS_PRONE) ||
                   (d(1, (ptr->CRIT_WT_CARRIED - lvl)) > 50)) {
                  break; //do nothing
               }//if
               if (ptr->isMob()) {
                  mudlog << "ERROR:  was MOB in do_cast_typhoon, mob: "
                         << ptr->getName() << " agg: " << agg.getName() << endl;
                  break;
               }//if
               
               emote("is hurled into the sky out of sight!", *ptr, 
                     room_list[agg.getCurRoomNum()], TRUE);
               
               int is_dead;
               ptr->doGoToRoom(new_room_num, NULL, NULL, is_dead,
                               ptr->getCurRoomNum(), 1);
               if (is_dead)
                  return;
               
               if (!ptr->CRIT_FLAGS.get(3)) { //if not flying
                  exact_raw_damage(abs(agg.getCurRoomNum() -
                                       ptr->getCurRoomNum()),
                                   NORMAL, *ptr, agg);
                  if (ptr->HP < 0) {
                     show("You are crushed as you are once more reunited with the earth.\n",
                          *ptr);
                     emote("is crushed into the earth.", *ptr, 
                           room_list[ptr->getCurRoomNum()], TRUE);
                     agg_kills_vict(&agg, *ptr);
                  }//if
                  else {
                     show("You land painfully on the ground.\n", *ptr);
                     emote("lands painfully on the ground.", *ptr,
                           room_list[ptr->getCurRoomNum()], TRUE);
                  }//else
               }//if
               else {
                  show("You land lightly on the ground.\n", *ptr);
                  emote("lands lightly on the ground.", *ptr,
                        room_list[ptr->getCurRoomNum()], TRUE);
               }//else
               look(1, &NULL_STRING, *ptr, TRUE);
            }//if
            if (count++ > 9) { //can't spin for too long
               break;
            }//if
         }//while
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_typhoon
 

void cast_typhoon(critter& pc) {
   int spell_num = TYPHOON_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
     return;
   }//if

   if (!ROOM.isBigWater()) {
      show("Typhoons only work on open water.\n", pc);
      return;
   }//if
                 /* all checks have been passed, lets do it */

   do_cast_typhoon(pc, FALSE, 0);  //does no error checking
}//cast_typhoon



void do_cast_tornado(critter& agg, int is_canned, int lvl) {
   String buf(100);
   int new_room_num = FALSE;
   short done = FALSE, do_affects = FALSE;
   int spell_num = TORNADO_SKILL_NUM;
   int spell_mana = get_mana_cost(spell_num, agg);

   if (is_canned) {
      do_affects = TRUE;
   }//if is_canned
   else { //not canned
      lvl = agg.LEVEL; 
      if (!lost_concentration(agg, spell_num)) { 
         do_affects = TRUE;
         agg.MANA -= spell_mana;
      }//if !lost concentration
      else { //lost concentration
         show(LOST_CONCENTRATION_MSG_SELF, agg);
         emote(LOST_CONCENTRATION_MSG_OTHER, agg, 
               room_list[agg.getCurRoomNum()], FALSE);
         agg.MANA -= spell_mana / 2;
         agg.PAUSE += 1; 
      }//else lost concentration
   }//else !canned
   
   if (do_affects) {
      critter* ptr;
      room* rm = room_list.elementAt(agg.getCurRoomNum());

      rm->makeReadyForAreaSpell();

      show_all("The skies grow dark and the wind begins to howl!\n",
               room_list[agg.getCurRoomNum()]);
      
      int begin_rm, end_rm;
      int zon = room_list[agg.getCurRoomNum()].getZoneNum();
      begin_rm = ZoneCollection::instance().elementAt(zon).getBeginRoomNum();
      end_rm = ZoneCollection::instance().elementAt(zon).getEndRoomNum();
      
      while ((ptr = rm->findNextSpellCritter())) {
         if (ptr == &agg) {
            if (d(1,50) > 25) {
               continue;
            }//if
         }//if
         
         done = FALSE;
         int sanity = 0;
         while (!done) {
            if (sanity++ > 10) {
               break;
            }

            new_room_num = begin_rm + d(1, (end_rm - begin_rm));

            if (!room_list.elementAtNoCreate(new_room_num) ||
                (!room_list[new_room_num].hasWeather())) {
               continue;
            }

            if (mob_can_enter(*ptr, room_list[new_room_num], FALSE)) {
               done = TRUE;
               if ((ptr->POS == POS_PRONE) ||
                   (d(1, ptr->CRIT_WT_CARRIED - lvl) > 50)) {
                  break; //do nothing
               }//if
               if (ptr->isMob()) {
                  mudlog << "ERROR:  was MOB in do_cast_lightning_storm, mob: "
                         << ptr->getName() << " agg: " << agg.getName() << endl;
                  break;
               }//if

               emote("is hurled into the sky out of sight!", *ptr, 
                     room_list[agg.getCurRoomNum()], TRUE);

               int is_dead;
               ptr->doGoToRoom(new_room_num, NULL, NULL, is_dead,
                               ptr->getCurRoomNum(), 1);
               if (is_dead) {
                  return;
               }

               if (!ptr->CRIT_FLAGS.get(3)) { //if not flying
                  exact_raw_damage(abs(agg.getCurRoomNum() 
                                       - ptr->getCurRoomNum()),
                                   NORMAL, *ptr, agg);
                  if (ptr->HP < 0) {
                     show("You are crushed as you are once more reunited with the earth.\n",
                          *ptr);
                     emote("is crushed into the earth.", *ptr, 
                           room_list[ptr->getCurRoomNum()], TRUE);
                     agg_kills_vict(&agg, *ptr);
                  }//if
                  else {
                     show("You land painfully on the ground.\n", *ptr);
                     emote("lands painfully on the ground.", *ptr,
                           room_list[ptr->getCurRoomNum()], TRUE);
                  }//else
               }//if
               else {
                  show("You land lightly on the ground.\n", *ptr);
                  emote("lands lightly on the ground.", *ptr,
                        room_list[ptr->getCurRoomNum()], TRUE);
               }//else
               look(1, &NULL_STRING, *ptr, TRUE);
            }//if
         }//while
      }//while
      agg.PAUSE += 1;   // increment pause_count
   }//if do_affects
}//do_cast_tornado
 

void cast_tornado(critter& pc) {
   int spell_num = TORNADO_SKILL_NUM;

   if (!ok_to_do_action(NULL, "KMSNV", spell_num, pc)) {
     return;
   }//if

   if (ROOM.isBigWater()) {
      show("Tornado's don't work on open water.\n", pc);
      return;
   }//if
                 /* all checks have been passed, lets do it */

   do_cast_tornado(pc, FALSE, 0);  //does no error checking
}//cast_tornado