//::///////////////////////////////////////////////
//:: Wildmage Spellhook script
//::///////////////////////////////////////////////
/*
This scrip controlls all events related to Wild Mages and Wild Magic.
*/
//::///////////////////////////////////////////////
//:: Created By: 2DruNk2Frag & Shazbotian
//:: Created On: 02-06-2008
//:: 02-26-08: Shaz: added haste, slow, stink cloud, charm monster, blind, fireball, lightning bolt, darkness, enlarge, and reduce surges
//:: 02-26-08: 2d2f: added code to handle baneful deflector and spellshape
//:: 03-02-08: 2d2f: added code to handle wildfire
//:: 03-08-08: 2d2f: added code to handle Stabilize
//:: 03-10-08: Shaz: added itchy, hiccup, weakened, gemspray, petrify, and "Target everyone in 60" surges
//:: 03-13-08: Shaz: Dweomer and wildfire spells should now get the appropriate spell save DC if they cast the intended spell 
//::					- added dizzy, "everyone around target", and "no save" surges
//::					- added "Spell effects caster & target", ethereal, and heal surges
//:: 03-14-08: 2d2f - Changed wildMageLevelVariation to use caster level instead of spell level as per TOM.  I guess I misunderstood the TOM all along. opps!
//:: 03-14-08: Shaz: added plant growth & "delay spell" surges
//:: 03-16-08: 2d2f - Changed code to handle baneful deflector
//::				-Modified the Spell shape code
//:: 03-19-08: Shaz: added deafening bang, refreshing, and gate random extra-planar surges
//:: 03-20-08: Shaz: modified dweomer spells to properly carry over their caster level
//:: 03-25-08: 2d2f -Added a visual effect to surge spell failure and changed the effect for stabilize/dweomer damage
//:: 03-27-08: Shaz: added polymorph self and other surges, attempted levitate surge, destroy cloth surge
//:: 03-28-08: 2d2f -Added the following surges 17,34,37,43,96,98
//:: 03-28-08: 2d2f -changed the code that determins surge modifyer for wildstrike to use a local int instead of a global
//:: 04-04-08: Shaz: added fire encircle, explosion on caster, and door opening surges
//:: 04-05-08: 2d2f - Added code to modify the surge roll if target has an effect from Paithan's spells
//:: 04-10-08: 2d2f - Added the following surges 40,41,42,59,62.
//:: 04-14-08: 2d2f - Added code to handle Nahal's Magical Propensity Modifier and Mass Propensity Modifier
//::				-Fixed the sprouts leaves surge (96) to not go away when resting (harsh!)
//:: 04-16-08: 2d2f - Added the feet enlarge surges (20 & 81). Holy shit it works!. added suge 9, and 55
//:: 04-18-08: 2d2f - Added the grow extra limb surge (97)
//:: 04-19-08: 2d2f - Adjusted the change skin color, random limb, and sprouts leaves functions to be ... well better.
//:: 				- the sprouts leaves surge now gives you a feat "Self-Pruning" which the player can use, as soon as they realize they have it, to remove the effect.
//:: 04-20-08: 2d2f - Added the rain cloud surge (86), AOE knockdown(1), and exchange places(80) surges
//:: 04-22-08: 2d2f - added the raindbow and leprichaun surge (7).
//::04-22-08: 2d2f - added the change weather  surge (51)
//:: 04-28-08: shaz: added "spell reverse", magic allergy, "spell failed but retained", and uncontrollable sneezing surges
//::				- fixed a bug in surge 81 "their feet enlarge" which only applied it to the caster
//::04-31-08: 2d2f - removed surge 80 (duplicate exchange places), changed surges 40 and 41 item naming schemes - not working right however
//::04-31-08: 2d2f - Added the streamers surge(30)
//::05-06-08: 2d2f - added the zombified surge and code to reverse cure spells
//:: 05-08-08:shaz: Implemented new spell "Wall of Force", made surge #1 use it, moved knockdown surge to #15, made surge #10's fireball explode just in front of caster
//::05-09-08: 2d2f - added the fireworks surge inplace of the streamers surge (30)
//:: 05-19-08: 2d2f - removed excessive includes that also exist in 2d2f_inc_magic_wild
//:: 05-22-08: 2d2f - Added the clone target surge (70). Also, changed the racial check for the undead surge, seems to be working.
//:: 05-30-08 : 2d2f - Modified the sprouts leaves surge for increased supernatural effect removal reliability (again)
//:: 05-31-08:Shaz: added levitate caster, levitate target, "cat herder", and "cow drop" surges
//:: 06-02-08:2d2f - Added the summon DM surge (63)
//:: 06-02-08:2d2f - Added the rust monster surge (82)
//:: 06-10-08:2d2f - added the Sex change surge (85)
//:: 06-11-08:2d2f - added the race change and two dimensional surge.
//:: 06-15-08:2d2f - added code to handle hornungs surge selector.  Also, fixed a bug cause by reckless dweomer, wildfire, and dosurgeno spell using the same spellid.
//::///////////////////////////////////////////////

#include "nwn2_inc_spells"
#include "x2_inc_switches"
//#include "2d2f_includes"
#include "2d2f_inc_magic_wild"
//#include "jx_inc_magic"
//#include "jx_inc_magic_info"
//#include "x0_i0_position"
//#include "x0_i0_spells"
//#include "x2_inc_itemprop"
#include "ginc_crafting"
#include "shaz_inc_math"
#include "shaz_inc_forcewall"

// PROTOTYPES
// Shaz: sets the caster level of the spell to CasterLevel+LevelVariation and prints to the caster about it
void CastSpellNormalWithVariation(object oCaster, int iCasterLevel, int iLevelVariation);

// Shaz: looks up the surge and carries out its effects. Returns 1 if a chaos shield prevented an effect.
int DoSurge(int iSurgeIndex, object oCaster, int iSpellID);

void main()
{
	int nSpellId;
	object oCaster = OBJECT_SELF;
	object oTarget = JXGetSpellTargetObject();
	
	int iRangeType;
	int nReckless = GetLocalInt(oCaster, "nReckless"); // for Reckless Dweomer
	int nHasWildstrike = GetHasSpellEffect(SPELL_WILDSTRIKE, oCaster); // checks if has wildstrike effect
	int nHasWildzone = GetHasSpellEffect(SPELL_WILDZONE, oCaster); // checks if has wildzone effect
	int nHasBaneful = GetHasSpellEffect(SPELL_BANEFUL_DEFLECTOR, oTarget);
	int nHasSpellShape = GetHasSpellEffect(SPELL_SPELL_SHAPE, oTarget);
	int nWildfire = GetLocalInt(oCaster, "nWildfire"); // for Wildfire
	int nStabilize = GetHasSpellEffect(SPELL_STABILIZE, oCaster);
	int nDoSurgeNoSpell = GetLocalInt(oCaster,"nDoSurgeNoSpell");
	int nHasLuckyStreak = GetHasSpellEffect(SPELL_LUCKY_STREAK, oTarget);
	int nHasFiasco = GetHasSpellEffect(SPELL_FIASCO, oTarget);
	int nHasMassPropensityModifier = GetHasSpellEffect(SPELL_MASS_PROPENSITY_MODIFIER, oTarget);
	int nHasSurgeSelector = GetHasSpellEffect(SPELL_SURGE_SELECTOR, oCaster);
	int nHornungsSurgeSelectionMade = GetLocalInt(oCaster,"nHornungsSurgeSelectionMade");
	int nSpellFromItem = GetIsObjectValid(GetSpellCastItem());
	
	// This will check for existing Walls of Force and check to see if the spell goes thru them
	// if it does, it will create a new target object at the wall and make it target that instead
	if(GetGlobalInt("ShazForceWall") > 0) {
		ShazForceWallSpellDeflect();
	}
	
	// Shaz: This is an attempt to try and make spells look a little better
	//  with the levitation effect - note since we can't change the target object,
	//  most spells will be completely unaffected, visually
	if(GetLocalInt(oTarget, "LevitationRoundsLeft") > 0) {
		vector vTarget = GetPosition(oTarget);
		vTarget.z += 2.0f;
		location lTarget = Location(GetArea(OBJECT_SELF), vTarget, IntToFloat(Random(360)));
		JXSetSpellTargetLocation(lTarget);
	}
	
/*	
	if(nHasWildzone == 1) {
		object oPC = GetFirstPC();
		SendMessageToPC(oPC, GetName(OBJECT_SELF) + " has wildzone effect!");
	}
	
	if(nHasWildstrike == 1) {
		object oPC = GetFirstPC();
		SendMessageToPC(oPC, GetName(OBJECT_SELF) + " has wildSTRIKE effect!");
	}
*/	
	int nCasterLvl = JXGetCasterLevel(oCaster);
	
	// use spellid from local int if Reckless dweomer is being used
	//:: 2d2f I'm just going to lump wildfire in here
	//:: 2d2f adding code for doSurgeNoSpell
	if(nReckless == 1 || nWildfire == 1 || nDoSurgeNoSpell == 1)	{
   	    if(nReckless == 1)
   	    {
            nSpellId = GetLocalInt(oCaster, "nRecklessSpellId");
        }
        else if(nWildfire == 1 )
        {
            nSpellId = GetLocalInt(oCaster, "nWildfireSpellId");
        }
        else if(nDoSurgeNoSpell == 1)
        {
            nSpellId = GetLocalInt(oCaster, "nDoSurgeNoSpellSpellId");
        }
		//nSpellId = GetLocalInt(oCaster, "nSpellId");
		//SendMessageToPC(oCaster, "Dweomer spell ID: " + IntToString(nSpellId)); // DEBUG
		// note about spell save DC: normally save DC is 10 + spell level + caster's attribute modifier
		// Shaz: for some reason, dweomer spells (and I suspect, any spells cast with JXCastSpellFromObjectAtXXX) always get a dc as if you had a modifier of +3. This is obviously not always the case, so I'll correct that here:
		// Shaz: the bioware/obisidian function GetCasterAbilityModifier() assumes the caster is either a wizard or a sorc. 
		//   This works for almost all possible entry points to this script, and for the rare others (a cleric in a wildzone, for example), they will use their charisma modifier, but they probably won't care all that much about their DC...
		int iSpellSaveDC = JXGetSpellSaveDC(oCaster) - 3 + GetCasterAbilityModifier(oCaster);
		JXSetSpellSaveDC(iSpellSaveDC, oCaster);
		// also, it appears that casting a spell with dweomer always sets the caster lvl to 10, even the JXCasterLvl
		// so this is an attempt to fix that
		nCasterLvl = GetLocalInt(oCaster, "shazCasterLevel");
		JXSetCasterLevel(nCasterLvl);
	}
	else 
	{
		nSpellId = GetSpellId();
	}
	
	//object oPC = GetFirstPC();
	//SendMessageToPC(oPC, "Spell ID: " + IntToString(nSpellId) + " name: " + JXGetSpellName(nSpellId));
	
	//:debug
	/*
	if(nDoSurgeNoSpell == 1) {
		object oPC = GetFirstPC();
		SendMessageToPC(oPC, GetName(oCaster) + " is casting the spell id " + IntToString(nSpellId) + " from doSurgeNoSpell!");
	}
	*/
	
	if(nHasBaneful == 1)
	{
		handleBanefulDeflector(oCaster, oTarget, nSpellId);
		//SetModuleOverrideSpellScriptFinished();
		return;
	}
	
	//2d2f: check if has spellshape and check for AOE spell
	if(nHasSpellShape == 1 && JXGetHasSpellTargetTypeArea(nSpellId) == FALSE)
		{
		//2d2f: Make the save for spell shape to work
		if(MySavingThrow(SAVING_THROW_WILL, oTarget, JXGetSpellSaveDC(),SAVING_THROW_TYPE_SPELL))
		{
			//2d2f: get the innate level. hopefully this is adiquate else I'll write a function to do a better job.
			int nSpellLvl = JXGetBaseSpellLevel(nSpellId); 
			//2d2f: I think its better just to have unlimited absorbtion but limit it to the spell school.
			int nSpellSchool = JXGetSpellSchool(nSpellId); 
			effect eAbsorb = EffectSpellLevelAbsorption(9,0,nSpellSchool); //2d2f: absorb the spell
			JXApplyEffectToObject(DURATION_TYPE_TEMPORARY,eAbsorb,oTarget,RoundsToSeconds(1));
			
			//2d2f: set the spell shape switch. Usedin the conversations scripts
			SetLocalInt(oTarget,"nSpellShapeSwitch", 1);
			//2d2f: remember the spell level for later 
			SetLocalInt(oTarget, "nSpellShapeLevel", nSpellLvl); 
			//2d2f: remember the caster for later
			SetLocalObject(oTarget, "oSpellShapeTarget", oCaster);
			//2d2f: reset the switches in two rounds
			DelayCommand(RoundsToSeconds(2), SetLocalInt(oTarget, "nSpellShapeSwitch", 0)); 
			DelayCommand(RoundsToSeconds(2), SendMessageToPC(oTarget, "Spell Shape has faded")); 
			
			//2d2f: create and name the speaker			
		    object oSpeaker = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_ipspeaker", GetLocation(oTarget), FALSE, "Spell Shape");
			SetFirstName(oSpeaker, "Spell Shape");
			SetLastName(oSpeaker, "");
			
			//2d2f: start the conv
			AssignCommand(oTarget, ActionStartConversation(oSpeaker,"2d2f_conv_spell_shape"));
			//2d2f: kill the speaker in 2 rounds
			DestroyObject(oSpeaker,RoundsToSeconds(2));
		}
	}
	
	if(nStabilize == 1 && nReckless != 1 && nWildfire != 1) //Stabilize does not work with reckless - OP
	{
		return; // directly cast spell, do not pass go, do not collect 200 dollars
	}
	else if(nStabilize == 1 && nReckless == 1) // not good for you 
	{
		RemoveSpellEffects(SPELL_STABILIZE, oCaster, oCaster);
		int nDam = d10(1);
		effect eDam = EffectDamage(nDam);
		effect eVis = EffectVisualEffect(VFX_HIT_SPELL_MAGIC);
		effect eLink = EffectLinkEffects(eDam,eVis);
		JXApplyEffectToObject(DURATION_TYPE_INSTANT,eLink,oCaster);
	}	
	else if(nStabilize == 1 && nWildfire == 1) // really hazardous to your health
	{
		RemoveSpellEffects(SPELL_STABILIZE, oCaster, oCaster);
		int nDam = d10(9);
		effect eDam = EffectDamage(nDam);
		effect eVis = EffectVisualEffect(VFX_HIT_SPELL_MAGIC);
		effect eLink = EffectLinkEffects(eDam,eVis);
		JXApplyEffectToObject(DURATION_TYPE_INSTANT,eLink,oCaster);
	}
	
	if(GetHasSpellEffect(SPELL_PROPENSITY_MODIFIER_FRIENDLY, oTarget) == 1 ||
	GetHasSpellEffect(SPELL_PROPENSITY_MODIFIER_HOSTILE, oTarget) == 1)
	//if(nHasPropensityModifier == 1) //2d2f - check if target has propensity modifier
	{
		int nDC = JXGetSpellSaveDC(oCaster);
		int nPropensityModifier = GetLocalInt(oTarget, "nPropensityModifier");
		object oPropensityCaster = GetLocalObject(oTarget, "oPropensityCaster");
		
		//SendMessageToPC(
		//GetFirstPC(),
		//"base dc = "
		// + IntToString(nDC));
		nDC = nDC + nPropensityModifier;
		//SendMessageToPC(GetFirstPC(),"modifier = " + IntToString(nPropensityModifier));
		//SendMessageToPC(GetFirstPC(),"propensity dc = " + IntToString(nDC));
		JXSetSpellSaveDC(nDC, oCaster);
		RemoveSpellEffects(SPELL_PROPENSITY_MODIFIER, oPropensityCaster, oTarget);
		DeleteLocalInt(oTarget,"nPropensityModifier");
		DeleteLocalObject(oTarget,"oPropensityCaster");
	}
	
	if(nHasMassPropensityModifier == 1) //2d2f - check if target has mass propensity modifier
	{
		int nDC = JXGetSpellSaveDC(oCaster);
		int nPropensityModifier = GetLocalInt(oTarget, "nPropensityModifier");
		object oPropensityCaster = GetLocalObject(oTarget, "oPropensityCaster");
		JXSetSpellSaveDC(nDC + nPropensityModifier, oCaster);
	}

	
	if((GetLevelByClass(CLASS_WILDMAGE) > 0 && !nSpellFromItem) || nHasWildstrike == 1 || nHasWildzone == 1 || nDoSurgeNoSpell == 1 || nHornungsSurgeSelectionMade == 1) // other entrance conditions coming
	{
		int nLvlVar = wildMageLevelVariation(nCasterLvl);
		
		if(nLvlVar == 777 || nReckless == 1 || nHasWildstrike == 1 || nHasWildzone == 1 || nWildfire == 1 || nDoSurgeNoSpell == 1 || nHornungsSurgeSelectionMade == 1)
		{	
			// A surge occurs!!!!
			int iSurgeModifier = 0;	// for shifing the roll up or down; some spells change this
			
			// switches off the Reckless dweomer local int
			//:2d2f: again I'm going to lump wildfire in here
			if(nReckless == 1 || nWildfire == 1) 
			{
				//nRand = nRand + GetLevelByClass(CLASS_WILDMAGE) + 1; // this will be included once the table is full
				SetLocalInt(oCaster, "nReckless", 0);
				SetLocalInt(oCaster, "nWildfire", 0);
				// reckless dweomer is supposed to add your caster level
				iSurgeModifier += GetLevelByClass(CLASS_WILDMAGE);
			}
			
			//:2d2f reset the switch variable
			if(nDoSurgeNoSpell == 1)
			{
				SetLocalInt(oCaster,"nDoSurgeNoSpell",0);
			}
			
			if(nHasWildstrike == 1) // applies negative level mod
			{
			int nWildstrikeCasterLvl = GetLocalInt(oCaster,"nWildstrikeCasterLvl");
			iSurgeModifier -= nWildstrikeCasterLvl;
			}
			
			//2d2f: add surge modifier from Piathan's spells
			if(nHasLuckyStreak == 1 || nHasFiasco == 1)
			{
				int nPiathansModifier = GetLocalInt(oTarget,"nPiathansModifier");
				iSurgeModifier += nPiathansModifier;
			}

            //Cancel the spell and do Hornung's surge selector
            if(nHasSurgeSelector == 1 && nHornungsSurgeSelectionMade != 1)
            {
                HandleSurgeSelector(   oCaster,
                                       oTarget,
                                       JXGetSpellTargetLocation(oCaster), 
                                       nSpellId,
                                       JXGetMetaMagicFeat(oCaster),
                                       JXGetSpellRangeType(nSpellId),
                                       JXGetCasterLevel(oCaster),
                                       JXGetSpellSaveDC(oCaster),
                                       iSurgeModifier);                
                SetModuleOverrideSpellScriptFinished();
                return;
            }
                        
			
			// Determine the index of the wild surge
			int nRand;
			// This next_surge_index exists for debuggin purposes 
			//  (you can set it from the console with "rs shaz_set_surge X")
			int iForcedSurgeIndex = GetGlobalInt("next_surge_index");
			if(iForcedSurgeIndex > 0) {
				nRand = iForcedSurgeIndex;
				SetGlobalInt("next_surge_index", 0); // reset the var so as to not change any more surges (use up arrow at console if you want to)
			} else {
				// surge occurs!
				nRand = d100() + iSurgeModifier;                                                                                             
			}
			
			// debug
			//SendMessageToPC(oCaster, "Surge index is " + IntToString(nRand));
			
			if(nRand < 0) {
				// automatic failure
				SendMessageToPC(oCaster, "Your spell fizzles! The feedback damages you!");
				effect eEffectDamage = EffectDamage(nCasterLvl, DAMAGE_TYPE_MAGICAL);
				effect eVis = EffectVisualEffect(VFX_HIT_SPELL_MAGIC);
				effect eLink = EffectLinkEffects(eEffectDamage,eVis);
				// shaz: maybe able a little "puff" visual effect here too? cool to see it happen to enemy mages
				// 2d2f: added a visual effect, should look good
				ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oCaster);
				
				if(GetLocalInt(oCaster,"nHornungsSurgeSelectionMade") == 1)
            	{
            	   int nCount = GetLocalInt(oCaster,"nSurgeSelectorCount");
            	   SetLocalInt(oCaster,"nSurgeSelectorCount", nCount + 1);
            	   SetLocalInt(oCaster,"nHornungsSurgeSelectionMade",0);
            	   RemoveSurgeSelector(oCaster);
            	}
				
				
				SetModuleOverrideSpellScriptFinished();
				return;
			} else if(nRand > 100) {
				// automatic success
				SendMessageToPC(oCaster, "Your spell is successful!");
				CastSpellNormalWithVariation(oCaster, nCasterLvl, nLvlVar);
			} else {
				DoSurge(nRand, oCaster, nSpellId);
				// Shaz: it seems that after a wild surge occurs, the next successful dweomer will target the last target position
				//  isntead of where the PC is currently aiming. This is an attempt to fix that.
				//location lZero;
				//SendMessageToPC(oCaster, "Setting JXTarget Loc");
				//SetLocalLocation(oCaster, JX_SPELL_TARGET_LOCATION, lZero);
				//Shaz: this fix did not work. I have no idea why, dweomers after a rebound would keep going to a wrong position
				// so i fixed it in the dweomer_area spell script...
			}
		}
		else	// there is no surge, spell cast normally (with lvl variation of course)
		{
			CastSpellNormalWithVariation(oCaster, nCasterLvl, nLvlVar);
		}
	}
	else // caster not a wildmage (or other conditions which haven't been implemented yet)
	{
		return;
	}
	
	return;

}

void CastSpellNormalWithVariation(object oCaster, int iCasterLevel, int iLevelVariation)
{
	// shaz: modidied this to put a plus sign in front of additive ones, to make that a bit clearer
	if(iLevelVariation > 0) {
		SendMessageToPC(oCaster, "Wild Mage spell level variation: +" + IntToString(iLevelVariation));		
	} else {
		SendMessageToPC(oCaster, "Wild Mage spell level variation: " + IntToString(iLevelVariation));		
	}

    if(GetLocalInt(oCaster,"nHornungsSurgeSelectionMade") == 1)
	{
	   int nCount = GetLocalInt(oCaster,"nSurgeSelectorCount");
	   SetLocalInt(oCaster,"nSurgeSelectorCount", nCount + 1);
	   SetLocalInt(oCaster,"nHornungsSurgeSelectionMade",0);
   
	}
	
	int nModLvl = iCasterLevel + iLevelVariation;
	JXSetCasterLevel(nModLvl);
	return;
}

// Shaz: looks up the surge and carries out its effects. Returns 1 if a chaos shield prevented an effect.
int DoSurge(int iSurgeIndex, object oCaster, int iSpellID)
{
	object oTarget = GetSpellTargetObject();
	
	location lTarget = GetSpellTargetLocation();
	location lCaster = GetLocation(oCaster);
	float fDuration = 0.0f;	// only used by surge 61 atm
	int iRangeType = JXGetSpellRangeType(iSpellID);
	int iCasterLevel = JXGetCasterLevel(oCaster);
	int iSpellSaveDC = JXGetSpellSaveDC(oCaster);
	int iNumCreaturesInArea;
	int iOverrideOriginal = 1;	// set to 0 if someone doesn't want to override the original spell
	
	if(GetLocalInt(oCaster,"nHornungsSurgeSelectionMade") == 1)
	{
	    oTarget = GetLocalObject(oCaster,"oSurgeSelectorTarget");
        iSpellID = GetLocalInt(oCaster,"nSurgeSelectorSpellId");
        //GetLocalInt(oCaster,"nSurgeSelectorMeta");
        iCasterLevel = GetLocalInt(oCaster,"nSurgeSelectorCasterLvl");
        lTarget = GetLocalLocation(oCaster,"nSurgeSelectorLocation");
        iRangeType = GetLocalInt(oCaster,"nSurgeSelectorRangeType");
        iSpellSaveDC = GetLocalInt(oCaster,"nSurgeSelectorSpellSaveDC");
        
        int nCount = GetLocalInt(oCaster,"nSurgeSelectorCount");
	    SetLocalInt(oCaster,"nSurgeSelectorCount", nCount + 1);
        
        SetLocalInt(oCaster,"nHornungsSurgeSelectionMade",0);
        RemoveSurgeSelector(oCaster);
    }

	
	
	//SendMessageToPC(oCaster, "JXCasterLevel: " + IntToString(iCasterLevel) + " NWN caster level: " + IntToString(GetCasterLevel(oCaster)));
	
	int iDebug;
	
	if(iRangeType == JX_SPELLRANGE_PERSONAL) {
		// Shaz: I think that, when casting a personal spell, its possible to not have a target at all,
		//  or to be targeting someone else. In this case I'm gona try setting target to caster
		//  so I don't have to check all over the place for personal range spells
		oTarget = oCaster;
	}
		
	// first, check for and establish the effects of a Chaos Shield on the caster
	int nHasChaosShield = GetHasSpellEffect(SPELL_CHAOS_SHIELD,oCaster); // checks is has chaos sheild effect
	int iShieldSuccess = 0;	// default to false
	int iShieldPreventedSurge = 0;	// set to true as the surge is determined if the surge targets a player that had a successful shield
	
	// if they have a shield, check now if it will do them any good
	if(nHasChaosShield == 1) 
	{
		if(MySavingThrow(SAVING_THROW_WILL, oCaster, JXGetSpellSaveDC(),SAVING_THROW_TYPE_SPELL))
		{
			iShieldSuccess = 1;
			SendMessageToPC(oCaster, "CHAOS shield success!!!");
		} else {
			SendMessageToPC(oCaster, "Chaos shield save FAILED");
		}
	}
	
	//SpeakString("WiLd sURgE!!!", oCaster);
	SpeakString("WiLd sURgE!!!");
	
	// Shaz: I changed this thing to always do 1-100 and just fall thru to written effects
	//  this will have the side effect of making effects that come after lots of unwritten effects far more likely to occur
	//  but, I don't think thats much of a problem; I did it this way so the number-picking can stay the same until the end of the project
	
	switch(iSurgeIndex) // Wild Surge Table
	{
		case 1 :	// wall of force appears in front of caster
			// since the spell doesn't directly affect you, chaos shield won't help
			lTarget = GetAheadLocation(oCaster);
			
			JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_WALL_OF_FORCE, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);
			SpeakString("An invisble wall forms in front of you!");
			break;
		case 2 :	// skunk smell
			// two parts to this spell: the visual effect, and the npc reactions
			
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				SpeakString("You smell like a skunk!");
				
				// first, the visual
				effect	eVis = EffectVisualEffect(868);	// VFX_DUR_GHAST_STENCH
				// the charisma down is my own invention - if you smell like a skunk, it should really hurt your charisma!
				effect	eChaDown = EffectAbilityDecrease(ABILITY_CHARISMA, 2);
				effect	eLink = EffectLinkEffects(eVis, eChaDown);
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oCaster, RoundsToSeconds(iCasterLevel));
				// and here is the reaction part
				SetLocalInt(oCaster, "StinkRoundsLeft", iCasterLevel);
				ShazDoStinkReactions();
			}
			break;
		case 3 :	// -Summons a menagerie
			if((oTarget != oCaster) || (iShieldSuccess == 0))
			{
				// insert Wild Surge Visual effect here.
				SpeakString("A menagerie appears!");
				WmMenagerieLocation(lTarget);
			} else {
				iShieldPreventedSurge = 1;
			}
			break;
			
		case 4 :	// caster's clothes itch
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				SpeakString("Your clothes itch!");
				SetLocalInt(oCaster, "ItchRoundsLeft", d6(4));
				ShazDoItchyClothing(oCaster);
			}
			
			break;
		case 5 :	// light spell on caster
			if(iShieldSuccess == 0)
			{
				SpeakString("You begin to glow!");
				ShazCastSpellOnObject(oCaster, SPELL_LIGHT);
			} else {
				iShieldPreventedSurge = 1;
			}
			
			break;
		case 6 :	// every creature in 60' suffers spell effect
			// although it isn't true to the letter of the ToM, we're just gona re-cast the spell at everyone in 60'
			oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lCaster, TRUE, OBJECT_TYPE_CREATURE);
			iDebug=0;	// just a sanity check, to prevent infinite loops
			while (GetIsObjectValid(oTarget) && iDebug < 40)
	        {	
				if(oTarget == oCaster) {
					if(iShieldSuccess == 1) {
						iShieldPreventedSurge = 1;
						// also... provide some level of spell absorbtion... because you'll probably have like 5 fireballs exploding around you...
						effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID)*3, GetSpellLevel(iSpellID)*3);
						// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
						JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 3.0f);
					} else {
						DelayCommand(0.5f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), JXGetCasterLevel(), JXGetSpellSaveDC(), TRUE, oCaster));
					}
				} else {
					DelayCommand(0.5f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), JXGetCasterLevel(), JXGetSpellSaveDC(), TRUE, oCaster));
				}
				
				iDebug++;
	            //Get the next target in the shape
	            oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lCaster, TRUE, OBJECT_TYPE_CREATURE);
	        }
			SpeakString("Cast at everyone nearby!!!");
			break;
		case 7 ://2d2f - a rainbow apears with its own feisty leprichaun
				// no chaos shield
				ARainbowAndALeprichaun(oCaster);
				SpeakString("A rainbow forms!");
			break;
		case 8 :	// shoulb be caster's hair grows 1', but we can't get that to work, so,
			// instead we'll do... DEATH! for one creature around you
			if(TRUE) {	// Shaz: did this so i could declare variables, as i need effect stuff
				effect eVFX1 = EffectVisualEffect(VFX_IMP_HARM);
				effect eVFX2 = EffectVisualEffect(VFX_IMP_DEATH);
				effect eDeath = EffectDeath(TRUE, TRUE, TRUE, TRUE);
				effect eLink = EffectLinkEffects(eVFX1, eDeath);
				eLink = EffectLinkEffects(eLink, eVFX2);
				
				SpeakString("Death!");
				
				if(iShieldSuccess == 1) {
					iShieldPreventedSurge = 1;
					oTarget = GetRandomCreatureInArea(oCaster, oTarget, RADIUS_SIZE_VAST, FALSE, TRUE);
				} else {
					oTarget = GetRandomCreatureInArea(oCaster, oTarget, RADIUS_SIZE_VAST, TRUE, TRUE);
				}
				
				JXApplyEffectToObject(DURATION_TYPE_INSTANT,eLink,oTarget);
			}

			break;
		case 9 ://2d2f - all creatures in area pivot 180 degrees
		
			if(iShieldSuccess == 1) // surge happens even if chaos shield stops it on caster.
			{					
				iShieldPreventedSurge = 1;
			}
			AboutFace(oCaster,iShieldSuccess);		
			SpeakString("Everybody turns around!");
			break;
		case 10 :	// small explosion in front of caster's face
			// I don't really have any idea how to create a "small explosion"
			// cast a weak fireball at the caster
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				// we'll make the caster immune to the next spell, which is this spell
				effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
			}
			
			SpeakString("Your spell explodes in your face!!");
			lTarget = GetAheadLocation(oCaster, 1.0f);
		
			JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_FIREBALL, METAMAGIC_NONE, 1, iSpellSaveDC, TRUE, oCaster);
			break;
		case 11 :	// caster becomes allergic to magic items
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				SpeakString("You become allergic to magic items!");
				
				if(iShieldSuccess == 1) {
					iShieldPreventedSurge = 1;
				} else {
					// note im not checking if the caster is undead or a construct... should i?
					SetLocalInt(oCaster, "AllergyRoundsLeft", d6(1) * 10);
					//AssignCommand( oCaster, ClearAllActions(TRUE) );
					AssignCommand( oCaster, ShazDoMagicAllergy() );
				}
			}
			break;
		case 12 :	// should be "Head enlarges" but we can't do that so
			// its "Destroy all gold on caster"!
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				TakeGoldFromCreature(GetGold(oCaster) / (60 + Random(40)), oCaster, TRUE, FALSE);
				SpeakString("Your pockets feel lighter!");
			}
			break;
		case 13 :	// caster "reduced" (reveresed enlarge)
			// if the target is you, you might be shielded
			if((iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				effect eLink = ShazEffectReduce();
				// using caster lvl for duration can be a really long time. Rethink it? (normal haste uses caster lvl)
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oCaster, RoundsToSeconds(JXGetCasterLevel(oCaster)));
				SpeakString("You shrink!!");
			}
			break;
		case 14 :	// the caster falls madly in love with the target
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				// the ToM states it lasts until dispelled. I think that might be a bit harsh? Or not?
				//iDuration = 
				if(GetIsObjectValid(oTarget)) {
					SpeakString("You fall in love!");
					if(oTarget == oCaster) {
						// stun em - they fell in love with themselves! wierd.
						effect eStun = EffectStunned();
						ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eStun, oCaster, RoundsToSeconds(d6(1)+2));
						SendMessageToPC(oCaster, "Your newfound infatuation with yourself makes it impossible to take any other action!");
					} else {
						// mindless creatures like undead and elementals can't fall in love
						if(GetRacialType(oCaster) == RACIAL_TYPE_ELEMENTAL || GetRacialType(oCaster) == RACIAL_TYPE_INCORPOREAL || 
							GetRacialType(oCaster) == RACIAL_TYPE_OOZE || GetRacialType(oCaster) == RACIAL_TYPE_UNDEAD || 
							GetRacialType(oCaster) == RACIAL_TYPE_CONSTRUCT) {
							SendMessageToPC(oTarget, "But unfortunately it is incappable of such an emotion...");
							// nothing happens
						} else {
							ShazFallInLove(oCaster, oTarget);
						}
					}
				} else {
					SpeakString("You get a strange feeling, but it passes...");
				}
			}
			break;
		case 15 :	//2d2f - all creatures except caster are knocked down
			// no chaos shield
			AOEKnockdown(oCaster);
			SpeakString("Everyone around you is knocked down!");
			break;
		case 16 :	// caster polymorphs randomly
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				effect ePoly = ShazEffectRandomPolymorph(oCaster);
				effect ePolyFX = EffectVisualEffect(VFX_IMP_POLYMORPH);
				
    			ApplyEffectToObject(DURATION_TYPE_INSTANT, ePolyFX, oCaster);
			    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePoly, oCaster, RoundsToSeconds(4+(iCasterLevel/2)));
				SpeakString("You transform!");
			}
			break;
		case 17 : //:2d2f Colored bubbles come out of your mouth
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				effect eVis = EffectVisualEffect(VFX_DUR_MOUTH_BUBBLES);
				effect eSilence = EffectSilence();
				effect eLink = EffectLinkEffects(eVis,eSilence);
				ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eLink,oCaster,TurnsToSeconds(1));
						
				SpeakString("Colorful bubbles surround your words!");
			}
			break;
		case 18 :	// should be "reveresed tounges" but we'll replace it with... CAT HERDER!!!
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				// a nice visual "burst"
				effect eVis = EffectVisualEffect(VFX_HIT_AOE_CONJURATION);
				ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lCaster);
				
				// create some cats
				int iNumCats = Random(8) + 3;
				int iCounter=0;
				while(iCounter < iNumCats) {
					object oNewCat = CreateObject(OBJECT_TYPE_CREATURE, "c_cat", lCaster);
					// make them do the "pulse" function
					AssignCommand(oNewCat, ShazFollowObjectAnnoying(oCaster, 6.0f));
					iCounter++;
				}
				
				SpeakString("Cat herder!");
			}
			break;
		case 19 :	// "wall of fire" encircles target
			// we can't do circles, unfortuantely. But we can do squares! muahahah
//			if(iShieldSuccess == 1) {
				// since this spell doesn't actually immediatley affect the caster, I'm not sure we should shield them?
//				iShieldPreventedSurge = 1;
//			} else {
				ShazEncloseTargetInFire(oCaster,lCaster);
				SpeakString("Flames leap up all around you!!");
//			}
			break;
		case 20 : //2d2f: casters feet enlarge
			if((iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				int nDur = d3(1);
				float fDur = TurnsToSeconds(nDur);
				effect eVis = EffectVisualEffect(VFX_DUR_BIG_FEET);
				effect eMove = EffectMovementSpeedDecrease(50);
				effect eDex = EffectAbilityDecrease(ABILITY_DEXTERITY,2);
				effect eLink = EffectLinkEffects(eVis,eMove);
				eLink = EffectLinkEffects(eLink,eDex);
								
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY,eLink,oCaster,fDur);
				SpeakString("Your feet drastically enlarge. Your movements are severly hampered!");
			}
			break;
		case 21 :	// caster suffers same effect as target
			// this surge is meaningless if the caster is the target
			if(oCaster == oTarget) {
				SpeakString("You get a strange feeling for a moment but it passes");
			} else if(iShieldSuccess == 1) {
				// unlike the rebound one, I'll completely cancel the return spell if you have a chaos shield success,
				//   since the ToM only asks for you to suffer the same "effect" as the target
				iShieldPreventedSurge = 1;
			} else {
				// cast the spell at the caster from the target's pos
				if (GetIsObjectValid(oTarget))
				{
					JXWZTurnSpell(oCaster, GetLocation(oTarget), iSpellID);
				}
				else
				{
					JXWZTurnSpell(oCaster, lTarget, iSpellID);
				}
				SpeakString("Share their fate!");
			}
			// original spell always goes off with this surge
			iOverrideOriginal = 0;
			break;
		case 22 :	// caster levitates
			// Shazbotian: you cannot move a creature off a walkmesh
			//  so, what we will attempt to do instead, is make it *look* like they are levitating with crazy effects
			if(iShieldSuccess == 1)	{
				iShieldPreventedSurge = 1;
			} else {
				if(spellsIsFlying(oCaster)) {
					SendMessageToPC(oCaster, "Levitation does not affect flying creatuers!");
				} else {
					int iDurRounds = d6(3);
					float fDuration = RoundsToSeconds(iDurRounds);
					effect eImmobilize = EffectCutsceneImmobilize();
					effect eVis;
					if(GetIsPlayableRacialType(oCaster)) {
						if(GetGender(oCaster) == GENDER_FEMALE) {
							eVis = EffectVisualEffect(1580);
						} else {
							eVis = EffectVisualEffect(1581);
						}
					} else if(GetRacialType(oCaster) == RACIAL_TYPE_UNDEAD) {
						eVis = EffectVisualEffect(1583);
					} else if(GetCreatureSize(oTarget) < CREATURE_SIZE_LARGE) {
						// just the orc one for now
						eVis = EffectVisualEffect(1582);
					} else if(GetCreatureSize(oTarget) < CREATURE_SIZE_HUGE) {
						// use the floating ogre
						eVis = EffectVisualEffect(1584);
					} else {
						SendMessageToPC(oCaster, "The target was too big to levitate!");
					}
					effect eLink = EffectLinkEffects(eImmobilize, eVis);
					DelayCommand(0.1f, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oCaster, fDuration));
	//				DelayCommand(fDuration+0.2f, JumpToLocation(lCaster));
					SetLocalInt(oCaster, "LevitationRoundsLeft", iDurRounds);
					AssignCommand( oCaster, ClearAllActions(TRUE) );
					AssignCommand( oCaster, ShazDoLevitation() );
				}
				// Try to let them know they've been immobilized
				DelayCommand(0.1f, SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_ENTANGLE, FALSE)));
				SpeakString("You begin to levitate!");
			}
			break;
		case 23 :	// fear on caster
			if(iShieldSuccess == 0)
			{
				SpeakString("Terror!!");
				location lCaster = GetLocation(oCaster);
				int iCasterLevel = JXGetCasterLevel(oCaster);
				int iSpellSaveDC = 20 + iCasterLevel; // shaz: I don't think you should be able to resist this!	
				iCasterLevel = iCasterLevel / 2; // this fear effect last for WAY too long. this'll cut it down a bit.
			
				JXCastSpellFromLocationAtObject(lCaster, oCaster, SPELL_FEAR, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);
			} else {
				iShieldPreventedSurge = 1;
			}
			break;
		case 24 : //2d2f - Caster becomes 2-dimensional
		    if((iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
			 TwoDimensions(oCaster);
			 SpeakString("You feel thin.");
			 }		
		    break;
		case 25 : //2d2f - Caster gains a phobia to random creature. 
					//If the creature type is within 30 feet of caster, 
					//save vs fear (DC 12) or flee (3-6 rounds) and suffer -4 to hit, ac, skills, 
					//50% spell failure untell the creature moves out of range or is destroyed. 
					//On save still suffer negative effects except fear. 
					//Phobia lasts 1-4 days or untell the phobic object is encountered 3-6 times.
					
			if(iShieldSuccess == 0)
			{
				string sPhobia = Phobia(oCaster,iSpellID);
				SpeakString("You are suddenly irrationally terrified of " + sPhobia + ".");
				
			} else {
				iShieldPreventedSurge = 1;
			}
			break;		
		case 26 :	// should be "caster ages 10 years" but since thats lame, well do "Voracious Dispelling!"
			// which means that for every creature within 60, we make all their buffs go "boom"
			SpeakString("All magic around you explodes!");
			// go thru everyone in a large area around caster, blowing up their buffs
			oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GINORMOUS, lCaster, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_AREA_OF_EFFECT);
			iNumCreaturesInArea=0;	// im kind of re-using this variable, since you can't declare in case statements for some reason
			while (GetIsObjectValid(oTarget) && iNumCreaturesInArea < 40)
	        {	
				if(oTarget == oCaster) {
					if(iShieldSuccess == 1) {
						iShieldPreventedSurge = 1;
						// also... provide some level of spell absorbtion... because you'll probably have like 5 fireballs exploding around you...
						effect eAbsorbEffect = EffectSpellImmunity();
						JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 3.0f);
					} else {
						DelayCommand(0.4f*IntToFloat(iNumCreaturesInArea), ShazExplodeMagicOnTarget(oTarget));
					}
				} else {
					DelayCommand(0.4f*IntToFloat(iNumCreaturesInArea), ShazExplodeMagicOnTarget(oTarget));
				}
				//DelayCommand(0.4f*IntToFloat(iNumCreaturesInArea), SendMessageToPC(oCaster, "Exploding buffs on: " + GetName(oTarget) + " tag: " + GetTag(oTarget)));
				
				iNumCreaturesInArea++;
	            //Get the next target in the shape
	            oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GINORMOUS, lCaster, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_AREA_OF_EFFECT);
	        }
			
			break;
		case 27 :	// silence 15' on caster
			if(iShieldSuccess == 0)
			{
				SpeakString("Silence!");
				ShazCastSpellOnObject(oCaster, SPELL_SILENCE);
			} else {
				iShieldPreventedSurge = 1;
			}
			break;
		case 28 :	// supposed to be "pit appears in front of caster" but since we cant...
			// TIME STOP! with a new person allowed to move each round for 1 turn (10 rounds)
			// if the caster is shielded, they get to keep moving for the whole thing (lucky them!)
			SpeakString("Tick, tock, take your turn!");
			if(iShieldSuccess == 0) {
				ShazTimeStopWithTurns(lCaster);
			} else {
				ShazTimeStopWithTurns(lCaster, oCaster);
				iShieldPreventedSurge = 1;
			}
			break;
		case 29 :	// should be "Reverse Gravity" but since that isn't very do-able,
			// we'll do a "magic weakens!" where we put spell mantles on everyone
			oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 60.0f, lCaster);
			while(GetIsObjectValid(oTarget)) {
				effect eAbsorb = EffectSpellLevelAbsorption(9, d8(1) + 8);
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY,eAbsorb,oTarget,RoundsToSeconds(d10(1) + 8));
				oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_ASTRONOMIC, lCaster);
			}
			SpeakString("All magic weakens!");
			break;
		case 30 :// 2d2f fireworks
				// no shield
			Fireworks(oCaster);
			SpeakString("Fireworks erupt over your head!");
			break;
		case 31 : // -Spell turns back on you
			// Shaz: I've tested this surge rigirously but there might be a few that don't work with it, let me know.
			// The spell doesn't turn back if its range is personal
			//iRangeType = JXGetSpellRangeType(nSpellId);
			if ((iRangeType == JX_SPELLRANGE_PERSONAL)
				|| (iRangeType == JX_SPELLRANGE_INVALID))
			{
				SpeakString("You get a strange feeling for a moment but it passes.");
				return 0;
			}
			
			if(iShieldSuccess == 1)
			{
				iShieldPreventedSurge = 1;
				if(iSpellID == SPELL_EVARDS_BLACK_TENTACLES || iSpellID == SPELL_GREASE) {
					// these spells are unresisitable, so the absorbtion affect below won't work on them. So, we'll just have to cancel them (don't know what else to do)
				} else {
					// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
					// we'll make the caster immune to the next spell, which is this spell, cause we're gona shoot it back at them
					effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
					// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
					JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
				}
			}
			if(iShieldSuccess == 0 || ((iSpellID != SPELL_EVARDS_BLACK_TENTACLES) && (iSpellID != SPELL_GREASE))) {
				if (GetIsObjectValid(oTarget))
				{
					JXWZTurnSpell(oCaster, GetLocation(oTarget), iSpellID);
				}
				else
				{
					JXWZTurnSpell(oCaster, lTarget, iSpellID);
				}
			}
				
			SpeakString("Your spell turns against you!");
			break;
			
		case 32 :	// caster becomes invisible (permanent until broken)
			if(iShieldSuccess > 0) {
				iShieldPreventedSurge = 1;
			} else {
				// just apply the invisiblity effect to caster
				effect eVis = EffectVisualEffect( VFX_DUR_INVISIBILITY );
	    		effect eInvis = EffectInvisibility(INVISIBILITY_TYPE_NORMAL);
				effect eLink = EffectLinkEffects( eInvis, eVis );
				ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oCaster);
				SpeakString("You vanish from sight!");
			}
			break;
			
		case 33 :	// caster does color spray instead
			// no shield prevention; doesn't do anything to caster
			if(GetIsObjectValid(oTarget) && (oTarget != oCaster)) {
				JXCastSpellFromLocationAtObject(GetLocation(oCaster), oTarget, SPELL_COLOR_SPRAY, METAMAGIC_NONE, JXGetCasterLevel(oCaster), (10 + JXGetCasterLevel(oCaster)), TRUE);
			} else if ((iRangeType == JX_SPELLRANGE_PERSONAL)
				|| (iRangeType == JX_SPELLRANGE_TOUCH)
				|| (iRangeType == JX_SPELLRANGE_INVALID))
			{
				float fRange = JXGetSpellRange(SPELL_COLOR_SPRAY);
				location lTo = GetRandomLocation(GetArea(oCaster), oCaster, fRange);
				JXCastSpellFromLocationAtLocation(GetLocation(oCaster), lTo, SPELL_COLOR_SPRAY, METAMAGIC_NONE, JXGetCasterLevel(oCaster), (10 + JXGetCasterLevel(oCaster)), TRUE);
			} else {
				JXCastSpellFromLocationAtLocation(GetLocation(oCaster), lTarget, SPELL_COLOR_SPRAY, METAMAGIC_NONE, JXGetCasterLevel(oCaster), (10 + JXGetCasterLevel(oCaster)), TRUE);
			}
			SpeakString("Colors!");
			break;
		case 34 : //:2d2f Butterflies pour from casters mouth
			if(iShieldSuccess > 0) {
				iShieldPreventedSurge = 1;
			} else {
				float fDur = 6.0 + IntToFloat(d6(1));// effect lasts between 1 and 2 rounds
				effect eDaze = EffectDazed(); // target dazed, I mean freakin butterflies are coming out of their mouth.
				effect eVis = EffectVisualEffect(VFX_DUR_BUTTERFLIES);
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDaze,oCaster,fDur);//can be immune to daze, not butterflies
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY,eVis,oCaster,fDur);
				SpeakString("A stream of butterflies pours from your mouth!");
			}
		
			break;
		case 35 :	// should be "caster leaves monster-shaped footprints" but thats lame so,
			// its "Create gold on target" instead!!
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				SpeakString("The target is enriched!");
				GiveGoldToCreature(oTarget, d100(1) * 100);
			}
			break;
		case 36 :	// shoot gems from fingertips
			// no shield, this is all good
			ShazDoFlyingGems(oCaster, lTarget);
			SpeakString("Gems shoot from your fingertips!");
			break;
		case 37 :  //2d2f: Music fills the air
			MusicFillsAir(oCaster);
			SpeakString("Music fills the air!");
			break;
		case 38 :	// "Create food and water" the ToM doesn't specify on whom...
			if(iShieldSuccess > 0) {
				iShieldPreventedSurge = 1;
			} else {
				SpeakString("Create food and water!");
				ClearAllActions();
				JXCastSpellFromLocationAtObject(lCaster, oTarget, SPELL_CREATE_FOOD_AND_WATER, METAMAGIC_NONE, JXGetCasterLevel(oCaster), (10 + JXGetCasterLevel(oCaster)), TRUE);
			}
			break;
		case 39 :// caster becomes and undead creature!
			if(iShieldSuccess > 0) {
				iShieldPreventedSurge = 1;
			}else if(GetLocalInt(oCaster,"nZombified") > 0 || GetRacialType(oCaster) == RACIAL_TYPE_VERMIN ||
			GetRacialType(oCaster) == RACIAL_TYPE_ABERRATION || GetRacialType(oCaster) == RACIAL_TYPE_ANIMAL ||
			GetRacialType(oCaster) == RACIAL_TYPE_BEAST || GetRacialType(oCaster) == RACIAL_TYPE_BEAST ||
			GetRacialType(oCaster) == RACIAL_TYPE_CONSTRUCT || GetRacialType(oCaster) == RACIAL_TYPE_DRAGON ||
			GetRacialType(oCaster) == RACIAL_TYPE_ELEMENTAL || GetRacialType(oCaster) == RACIAL_TYPE_FEY ||
			GetRacialType(oCaster) == RACIAL_TYPE_HUMANOID_MONSTROUS || GetRacialType(oCaster) == RACIAL_TYPE_INCORPOREAL ||
			GetRacialType(oCaster) == RACIAL_TYPE_INVALID || GetRacialType(oCaster) == RACIAL_TYPE_MAGICAL_BEAST ||
			GetRacialType(oCaster) == RACIAL_TYPE_OOZE || GetRacialType(oCaster) == RACIAL_TYPE_OUTSIDER ||
			GetRacialType(oCaster) == RACIAL_TYPE_SHAPECHANGER || GetRacialType(oCaster) == RACIAL_TYPE_UNDEAD)
			{	
				SpeakString("You get a strange feeling for a moment... but it passes.");
							
			} else {
				YouHaveStoppedBreathing(oCaster);
				SpeakString("You have stopped breathing!");
			}
			break;
		case 40 : //2d2f: One magic item on the caster is permanently drained of all properties
				// I changed this from the TOM to only effect items that can be equiped (excluding ammunition and plot items)
				// and only on the caster
			if(iShieldSuccess == 0)
			{
				object oItem = DrainItem(oCaster);
				if(oItem != OBJECT_INVALID)
				{
					string sName = GetName(oItem);
					SpeakString("Your " + sName + " has been permanently drained of it's magic!");
					//SetEnchantedItemName(oCaster,oItem);
					string sDrained = "Drained ";
					string sNew = InsertString(sName,sDrained,0);
					SetFirstName(oItem,sNew);
				}
				else
				{
					SpeakString("You get a strange feeling for a moment but it passes");
				}
				
			} else {
				iShieldPreventedSurge = 1;
			}
			break;
		case 41 : //2d2f - One item gains a bonus of 1-3 to enhancement (for melee weapons,
				// to attack (for ranged weapons), or to AC (for equipable stuff besides weapons).
				// I changed this from the TOM to only effect items that can be equiped (excluding ammunition and plot items)
				// and only on the caster
				if(iShieldSuccess == 0)
				{
					object oItem = EnhanceItem(oCaster);
					if(oItem != OBJECT_INVALID)
					{
						string sName = GetName(oItem);
						SpeakString("Your " + sName + " has been permanently magically enhanced!");
						//SetEnchantedItemName(oCaster,oItem);
						string sEnchanted = "Enchanted ";
						string sNew = InsertString(sName,sEnchanted,0);
						SetFirstName(oItem,sNew);
						
					}
					else
					{
						SpeakString("You get a strange feeling for a moment but it passes");
					}
				
				} else {
					iShieldPreventedSurge = 1;
				}
				break;
		case 42 : 	//2d2f- all nearby weapons gain a +2 bonus.
					// Again I have deviated from the TOM.  All I did was check the righ hand and left hand slots
					// for meele or ranged weapons and added a bonus to them if their.
					// I figured it was unnecessary to put the effect on items in inventory for this as that 
					// would probably go unnoticed anyway.
					// also, made it effect all weapons even non-magical
				EnhanceAllNearWeapons(oCaster,iShieldSuccess);
				SpeakString("All nearby weapons are enhanced!");	
				if(iShieldSuccess == 1) // surge happens even if chaos shield stops it on caster.
				{					
					iShieldPreventedSurge = 1;
				}
			break;
		case 43 ://:2d2f smoke pours from the ears of nearby creatures
			SmokeyEars(oCaster,iShieldSuccess);
			SpeakString("Smoke trickles from the ears of all nearby creatures!");
			if(iShieldSuccess > 0) { //2d2f overrides even if chaos shield successful
				iShieldPreventedSurge = 1;
				}
			break;
		case 44 : //-Shimmering Lights	
			if(iShieldSuccess == 0)
			{
				// insert Wild Surge Visual effect here.
				SpeakString("Lights shimmer around you!");
				JXWZCastShimmeringLights(oCaster);
			} else {
				iShieldPreventedSurge = 1;
			}
			break;
		
		case 45 :	// everyone within 30' of caster begins to hiccup
			// the ToM doesn't specifically mention the caster being affected... should we?
			oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lCaster);
			while (GetIsObjectValid(oTarget))
	        {
				if(oTarget == oCaster) {
					if(iShieldSuccess == 1) {
						iShieldPreventedSurge = 1;
					} else {
						// note im not checking if the caster is undead or a construct... should i?
						SetLocalInt(oCaster, "HiccupRoundsLeft", d6(4));
						AssignCommand( oCaster, ClearAllActions(TRUE) );
						AssignCommand( oCaster, ShazDoHiccups() );
					}
				} else {
					// don't make dead people or hidden people hiccup, and certainly don't make non-creatures do it
					if(GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && GetIsDead(oTarget) == FALSE && GetScriptHidden(oTarget) == FALSE) {
			            // don't make undead, constructs, or elementals hiccup... they don't breath
			        	if (GetRacialType(oTarget) != RACIAL_TYPE_CONSTRUCT && GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD && GetRacialType(oTarget) != RACIAL_TYPE_ELEMENTAL)
			        	{
							SetLocalInt(oTarget, "HiccupRoundsLeft", d6(4));
		                    AssignCommand( oTarget, ClearAllActions(TRUE) );
							AssignCommand( oTarget, ShazDoHiccups() );
		            	}
					}
				}
	            //Get the next target in the shape
	            oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lCaster);
	        }
			SpeakString("Hiccups!!!");
			break;
		case 46 :	// all normal, secret, and magic doors open nearby
			// no shield for this one, doesn't do anythign to the caster
			//JXCastSpellFromObjectAtLocation(oCaster, lCaster, SPELL_KNOCK,METAMAGIC_NONE, JXGetCasterLevel(), JXGetSpellSaveDC(), TRUE);
			ShazOpenAllNearbyDoors(lCaster, 35.0f);	// large than the ToM calls for, but 60' seems pretty small ingame
			SpeakString("Open Sesame!");
			break;
		case 47 :	// caster and target exchange places
			if(GetIsObjectValid(oTarget) == TRUE && (oTarget != oCaster)) {
				if(iShieldSuccess == 1) {
					iShieldPreventedSurge = 1;
				} else {
					float fCasterFacing = GetFacing(oCaster);
					float fTargetFacing = GetFacing(oTarget);
					
					// Shaz: coppied these from 2d2f's "swap" surge since i asked him to
					// remove that one thought i'd take his cue and put some VFX on this one
					location lCaster = GetLocation(oCaster);
					location lTarget = GetLocation(oTarget);
					effect eVis = EffectVisualEffect(VFX_DUR_SCATTERPORT);
						
					JXApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis,lCaster);
					JXApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis,lTarget);
					
					AssignCommand(oCaster, ClearAllActions());
					AssignCommand(oCaster, ActionJumpToLocation(lTarget));
					AssignCommand(oCaster, SetFacing(fTargetFacing));	// this doesn't appear to work, I don't know why
					AssignCommand(oTarget, ClearAllActions());
					AssignCommand(oTarget, ActionJumpToLocation(lCaster));
					AssignCommand(oTarget, SetFacing(fCasterFacing));	// this does work.. must be something to do with a PC?
					
					// Shaz: we should really let the target know that its been teleported
        			SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_TELEPORT));
					
					SpeakString("Swap!");
				}
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 48 :  //-Spell Chooses random target besides the caster
			// Shaz note: This is supposed to only pick among possible targets within 60' of caster! but this implementation probably works alright.
			// The spell doesn't change if its range is personal or touch
			// Shaz: although, wouldn't it be cool if personal spells randomly went to someone else in the area? hehe...
			if ((iRangeType == JX_SPELLRANGE_PERSONAL)
				|| (iRangeType == JX_SPELLRANGE_TOUCH)
				|| (iRangeType == JX_SPELLRANGE_INVALID))
			{
				SpeakString("You get a strange feeling for a moment but it passes");
				return 0;
			}
			
			if (GetIsObjectValid(oTarget))
			{
				JXWZCastAtRandomTarget(oCaster, oTarget, iSpellID);
			}
			else
			{
				JXWZCastAtRandomLocation(oCaster, iSpellID);
			}
			
			// insert Wild Surge Visual effect here.
			SpeakString("Your spell wants a different target!");
			// Cancel spell effects
			break;
			
		case 49 :	// spell fails but is not wiped from memory
			// because we can't restore a single spell, we'll force rest the player, which gives him all his spells.
			// this is pretty powerful, but a neat surge to get. Actually not so great, rest removes your buffs!
			// Shaz: I copied this from the "spell succeededs but is not wiped" and just let the spell get ovverriden
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				ForceRest(oCaster);
				SpeakString("Your spell fails, but you feel refreshed!!");
			}
			break;
		case 50 :	// summon monster 2
				// no shield prevention; this isn't bad
				ShazSummonRandomCreaturesAtLocation(lTarget);
				
				SpeakString("New Allies appear!");
			break;
			
		case 51 : //2d2f - a change in weather
			if(GetIsAreaInterior(GetArea(oCaster)) == TRUE)
			{
				SpeakString("You get a strange feeling for a moment, but it passes.");
			}
			else
			{
				ChangeWeather();
				SpeakString("The weather suddenly changes!");
			}
			break;
		case 52 :	// defeaning bang effects all within 60'
			// note: the ToM doesn't specific what this effect is centered on;
			//   I'm going to assume the target, to keep things interesting ;-)
			SpeakString("BANG!!!");
			if(iShieldSuccess == 1) {
				if(ShazDoDeafeningBang(lTarget, oCaster) == 1) {
					iShieldPreventedSurge = 1;
				}
			} else {
				ShazDoDeafeningBang(lTarget);
			}
			
			break;
		case 53 :	// SHAZBOTIAN REPLACEMENT: cast completely random spell at completely random target
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				// we'll make the caster immune to the next spell, which is this spell
				effect eAbsorbEffect = EffectSpellLevelAbsorption(9, 9);
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
			}
			iSpellID = ShazCastRandomSpellAtRandomTarget();
			SpeakString("From the chaos of the weave, a spell forms: " + JXGetSpellName(iSpellID) + "!");
			break;
		case 54 :	// "Gate" opens, 50% chance of summoning a creature from another plane
			// although the creature can turn after a random period of time, i'm not going to let chaos shield stop that,
			// because the creature *will* fight for you for at least a little while.
			ShazGateRandomOutsider(iCasterLevel, lTarget);
			SpeakString("A gate to another plane opens!!");
			break;
		case 55 ://2d2f-Spell functions but shrieks allerting all monsters in a super huge area
			if(iShieldSuccess == 1) // surge happens even if chaos shield stops it on caster.
			{					
				iShieldPreventedSurge = 1;
			}
			Shrieker(lTarget,oCaster,iShieldSuccess);		
			SpeakString("Spell functions but there is a terrible shriek!");
			iOverrideOriginal = 0;
			break;
		case 56 :	// spell effectiveness decreases
			// if you were casting a spell on yourself and were shieled, it gets stopped
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				//SendMessageToPC(oCaster, "Your caster level is set to " + IntToString(iCasterLevel/2) + "!");
				JXSetCasterLevel(iCasterLevel/2);
				JXSetSpellSaveDC(JXGetSpellSaveDC() - 2);
				//return 0;
				iOverrideOriginal = 0;
				SpeakString("You feel your magic weaken!");
			}
			
			break;
		case 57 :	// spell reversed
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				int iNewSpell = ShazGetReversedSpellID(iSpellID);
				if(iNewSpell >= 0){
					SpeakString("Your spell is reversed!");
					SendMessageToPC(oCaster, "Your spell changes into " + JXGetSpellName(iNewSpell)+ "!");
					if(GetIsObjectValid(oTarget) == TRUE) {
						DelayCommand(fDuration, JXCastSpellFromLocationAtObject(lCaster, oTarget, iNewSpell, JXGetMetaMagicFeat(oCaster), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					} else {
						DelayCommand(fDuration, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iNewSpell, JXGetMetaMagicFeat(oCaster), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					}
				}
			}
			break;
		case 58 :	// spell takes free-willed elemental form, hits cause spell effect
			// if you were the target, the shields gota stop it
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				//SendMessageToPC(oCaster, "Spell id passed to summonspellelem: " + IntToString(iSpellID));
				ShazSummonSpellElemental(lTarget, iSpellID);
				SpeakString("Your spell takes free-willed physical form!");
			}
			break;
		case 59 : //2d2f - all nearby weapons glow.
					// no chaos shield
					AllWeaponsGlow(oCaster);
					SpeakString("Every weapon around you begins to glow!");
			break;
		case 60 :	// deny target a saving throw
			// if you were the target, the shields gota stop it
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				JXSetSpellSaveDC(50);	// there we go, nothing on earth (or err... Faerun) should save against that
				// this effect should cancel out most spell resistance (very temporarily)
				effect eResistEffect = EffectSpellResistanceDecrease(20);
				ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eResistEffect, oTarget, 2.0f);
				iOverrideOriginal = 0;	// allow the spell to be cast normally
				SpeakString("Your magic is irresistable!");
				if(iShieldSuccess && JXGetHasSpellTargetTypeArea(iSpellID) == TRUE) {
					// chances are you might hit yourself with an aoe; so we'll give you a very short spell immunity
					effect eImmuneEffect = EffectSpellImmunity();
					ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eImmuneEffect, oCaster, 1.0f);
					// note the shield doesn't go away when hit... if it protects you.. we'll you're just lucky ;-)
				}
			}
			break;
		case 61 :	// Spell appears to fail, occurs later
			fDuration = RoundsToSeconds(d4());	// this is when the spell will go off
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
				// since you could walk over into an aoe effect that you hadn't intended to get hit by...
				// i'll try giving you immunity just before the spell goes off
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				DelayCommand(fDuration - 1.0, JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 3.0f));
			}
			SpeakString("Your spell appears to have failed...");
			if(GetIsObjectValid(oTarget) == TRUE) {
				DelayCommand(fDuration, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(oCaster), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
			} else {
				DelayCommand(fDuration, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(oCaster), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
			}
			break;
		case 62 ://2d2f - All nearby items glow for a long ass time
					// I made this a one time effect because we do not want a heartbeat script
					// that serched through every item on every person within 60' for 2d8 days.
					// no chaos shield
				AllMagicItemsGlow(oCaster);
				SpeakString("All magic items around you begin to glow!");
			break;
		case 63 :  // The Dungeon Master appears with a proposition
		        SummonDM(oTarget);
		        SpeakString("The Dungeon Master materalizes.");
		        break;
		case 64 :	// slow on target
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				// we'll make the caster immune to the next spell, which is this spell
				effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
			}
			
			SpeakString("Slow!!");
		
			JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_SLOW, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);

			break;
		case 65 :	// should be "target deluded" but thats pretty lame, so instead we'll do "voracious dispelling" on target
			// which means that for every creature within 60, we make all their buffs go "boom"
			SpeakString("All magic around them explodes!");
			// go thru everyone in a large area around caster, blowing up their buffs
			oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GINORMOUS, lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_AREA_OF_EFFECT);
			iNumCreaturesInArea=0;	// im kind of re-using this variable, since you can't declare in case statements for some reason
			while (GetIsObjectValid(oTarget) && iNumCreaturesInArea < 40)
	        {	
				if(oTarget == oCaster) {
					if(iShieldSuccess == 1) {
						iShieldPreventedSurge = 1;
						// also... provide some level of spell absorbtion... because you'll probably have like 5 fireballs exploding around you...
						effect eAbsorbEffect = EffectSpellImmunity();
						JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 3.0f);
					} else {
						DelayCommand(0.4f*IntToFloat(iNumCreaturesInArea), ShazExplodeMagicOnTarget(oTarget));
					}
				} else {
					DelayCommand(0.4f*IntToFloat(iNumCreaturesInArea), ShazExplodeMagicOnTarget(oTarget));
				}
				//DelayCommand(0.4f*IntToFloat(iNumCreaturesInArea), SendMessageToPC(oCaster, "Exploding buffs on: " + GetName(oTarget) + " tag: " + GetTag(oTarget)));
				
				iNumCreaturesInArea++;
	            //Get the next target in the shape
	            oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GINORMOUS, lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_AREA_OF_EFFECT);
	        }
			
			break;
		case 66 :	// lightning bolt target
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				// we'll make the caster immune to the next spell, which is this spell
				effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
			}
			
			SpeakString("Lightning!!");
		
			JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_LIGHTNING_BOLT, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);

			break;
		case 67 :	// target "enlarged"
			// if the target is you, you might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				effect eLink = ShazEffectEnlarge();
				// using caster lvl for duration can be a really long time. Rethink it? (normal haste uses caster lvl)
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(JXGetCasterLevel(oCaster)));
				SpeakString("Target Grows!");
				
				// Shaz: we should really let the target know that its been blinded
        			SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_ENLARGE_PERSON));
			} else {
				SpeakString("You get a strange feeling, but it passes...");
			}
			break;
		case 68 :	// darkness on target
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
				// absorbtion levels apparently do nothing against darkness (I guess its a buff?!?! Who knew!!), so we have to just cancel it
			} else {
				SpeakString("Darkness!!");
			
				JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_DARKNESS, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);
			}

			break;
		case 69 :	// plant growth on target
			// since PlantGrowth doesn't exist in NWN2, we'll use the "hamper movement" version of vine mine, which does pretty much the same thing
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				// we'll make the caster immune to the next spell, which is this spell
				effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
			}
			
			SpeakString("Plant Growth!");
			
			JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_VINE_MINE_HAMPER_MOVEMENT, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);
			
			break;
		case 70 : //2d2f - create 1-4 clones of the target
					// clones will exist for 1 turn and be the faction of the target
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetPlotFlag(oTarget) == TRUE) {
				SpeakString("You get a funny feeling, but it passes...");
			} else {
				CloneTarget(oTarget, oCaster);
				SpeakString("Clones appear!!!");
			}		
			break;
		case 71 :	// fireball on target
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				// we'll make the caster immune to the next spell, which is this spell
				effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
			}
			
			SpeakString("FIREBALL!!");
		
			JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_FIREBALL, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);

			break;
		case 72 :	// target turned to stone
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				// the 40 should prevent anyone from sucessfully saving against it
				DoPetrification(iCasterLevel, oCaster, oTarget, SPELL_FLESH_TO_STONE, 40);
				SpeakString("Petrify!");
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 73 :	// spell cast, memory & components retained
			// their are no components in NWN2
			// because we can't restore a single spell, we'll force rest the player, which gives him all his spells.
			// this is pretty powerful, but a neat surge to get. Actually not so great, rest removes your buffs!
			if(iShieldSuccess == 1) {
				iShieldPreventedSurge = 1;
			} else {
				ForceRest(oCaster);
				SpeakString("You feel refreshed!!");
			}
			iOverrideOriginal = 0;	// let the original spell go off
			break;
		case 74 :	// everyone in 10' of caster recives heal (as the spell)
			oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, lCaster, TRUE, OBJECT_TYPE_CREATURE);
			iDebug=0;	// just a sanity check, to prevent infinite loops
			while (GetIsObjectValid(oTarget) && iDebug < 40)
	        {	
				if(oTarget == oCaster) {
					if(iShieldSuccess == 1) {
						// hahaha blocked a heal spell, sucks for you! muhahahah
						iShieldPreventedSurge = 1;
					} else {
						DelayCommand(0.5f, JXCastSpellFromLocationAtObject(lCaster, oTarget, SPELL_HEAL, JXGetMetaMagicFeat(), JXGetCasterLevel(), JXGetSpellSaveDC(), TRUE, oCaster));
					}
				} else {
					DelayCommand(0.5f, JXCastSpellFromLocationAtObject(lCaster, oTarget, SPELL_HEAL, JXGetMetaMagicFeat(), JXGetCasterLevel(), JXGetSpellSaveDC(), TRUE, oCaster));
				}
				
				iDebug++;
	            //Get the next target in the shape
	            oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, lCaster);
	        }
			SpeakString("Healing!!!");
			break;
		case 75 :	// target dizzy
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				effect eDizzy = ShazEffectDizzy();	// we could maybe just use a daze here, whatever. This Dizzy effect is "truer" to the ToM
				ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDizzy, oTarget, RoundsToSeconds(d4(2)));
				SpeakString("Dizzy!");
				SendMessageToPC(oTarget, "You feel dizzy!!");
				
				// Shaz: we should really let the target know that its been dizzified
        		SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_DAZE));
			}
			break;
		case 76 :	//"wall of fire" encircles target
			// we can't do circles, unfortuantely. But we can do squares! muahahah
//			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				// since this spell doesn't actually immediatley affect the target, I'm not sure we should shield them?
//				iShieldPreventedSurge = 1;
//			} else {
				ShazEncloseTargetInFire(oCaster, lTarget);
				SpeakString("Flames leap up all around your target!");
//			}
			break;
		case 77 :	// target levitates
		// if the target is you, you might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				if(spellsIsFlying(oTarget)) {
					SendMessageToPC(oCaster, "Levitation does not affect flying creatures!");
				} else {
					int iDurRounds = d6(3);
					float fDuration = RoundsToSeconds(iDurRounds);
					effect eImmobilize = EffectCutsceneImmobilize();
					effect eVis;
					if(GetIsPlayableRacialType(oTarget)) {
						if(GetGender(oTarget) == GENDER_FEMALE) {
							eVis = EffectVisualEffect(1580);
						} else {
							eVis = EffectVisualEffect(1581);
						}
					} else if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD) {
						eVis = EffectVisualEffect(1583);
					} else if(GetCreatureSize(oTarget) < CREATURE_SIZE_LARGE) {
						// just the orc one for now
						eVis = EffectVisualEffect(1582);
					} else if(GetCreatureSize(oTarget) < CREATURE_SIZE_HUGE) {
						eVis = EffectVisualEffect(1584);
					} else {
						SendMessageToPC(oCaster, "The target was too big to levitate!");
					}
					effect eLink = EffectLinkEffects(eImmobilize, eVis);
					DelayCommand(0.1f, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDuration));
	//				DelayCommand(fDuration+0.2f, JumpToLocation(lCaster));
					SetLocalInt(oTarget, "LevitationRoundsLeft", iDurRounds);
					AssignCommand( oTarget, ClearAllActions(TRUE) );
					AssignCommand( oTarget, ShazDoLevitation() );
				}
				// try to let them know they've been immobilized
				DelayCommand(0.1f, SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_ENTANGLE)));
				SpeakString("Your target begins to levitate!");
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 78 :	// target suffers blindness
			// Shaz: Should we allow a saving throw against this? or resistances?
			// if the target is you, you might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				if( GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
				{
					FloatingTextStrRefOnCreature(40105, OBJECT_SELF, FALSE);
				} else {
					effect eHaste = EffectBlindness();
	    			effect eVis = EffectVisualEffect(VFX_DUR_SPELL_BLIND_DEAF);
	    			effect eLink = EffectLinkEffects(eHaste, eVis);
					// using caster lvl for duration can be a really long time. Rethink it? (normal haste uses caster lvl)
					JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(JXGetCasterLevel(oCaster)));
					SpeakString("Target Blinded!");
					
					// Shaz: we should really let the target know that its been blinded
        			SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_BLINDNESS_AND_DEAFNESS));
				}
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 79 :	// "Charm Monster" on target
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)){
		
				JXCastSpellFromLocationAtObject(lCaster, oTarget, SPELL_CHARM_MONSTER, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);
				SpeakString("Charm Monster!!");
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 80 : // every within 60' of target becomes drunk
		          //effects everyone except caster in case of chaos shield
                if(iShieldSuccess == 1) // surge happens even if chaos shield stops it on caster.
        		{					
        		  iShieldPreventedSurge = 1;
        		}
		        DrunkBomb(oTarget,oCaster,iShieldSuccess);
		        SpeakString("Everyone around gets drunk!");
		    break;
		case 81 ://2d2f: targets feet enlarge
			if((oTarget == oCaster && iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				int nDur = d3(1);
				float fDur = TurnsToSeconds(nDur);
				effect eVis = EffectVisualEffect(VFX_DUR_BIG_FEET);
				effect eMove = EffectMovementSpeedDecrease(50);
				effect eDex = EffectAbilityDecrease(ABILITY_DEXTERITY,2);
				effect eLink = EffectLinkEffects(eVis,eMove);
				eLink = EffectLinkEffects(eLink,eDex);
								
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY,eLink,oTarget,fDur);
				SpeakString("Their feet drastically enlarge. Their movements are severly hampered!");
			}
			break;
		case 82 : // A rust monster appears
		        SummonRustMonster(oTarget);
                SpeakString("A Rust Monster Appears!");
		    break;
		case 83 :	// target polymorphs randomly
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				effect ePoly = ShazEffectRandomPolymorph(oTarget);
				effect ePolyFX = EffectVisualEffect(VFX_IMP_POLYMORPH);
				
    			ApplyEffectToObject(DURATION_TYPE_INSTANT, ePolyFX, oTarget);
			    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePoly, oTarget, RoundsToSeconds(4+(iCasterLevel/2)));
				SpeakString("The target transforms!");
			}
			break;
		case 84 :	// target falls madly in love with caster
			// if the target is the caster, we'll just stun them for awhile (unless they are shielded)
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				// the ToM states it lasts until dispelled. I think that might be a bit harsh? Or not?
				//iDuration = 
				SpeakString("The target falls in love!");
				if(oTarget == oCaster) {
					// stun em - they fell in love with themselves! wierd.
					effect eStun = EffectStunned();
					ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eStun, oCaster, RoundsToSeconds(d6(1)+2));
					SendMessageToPC(oCaster, "Your newfound infatuation with yourself makes it impossible to take any other action!");
				} else {
					// mindless creatures like undead and elementals can't fall in love
					if(GetRacialType(oTarget) == RACIAL_TYPE_ELEMENTAL || GetRacialType(oTarget) == RACIAL_TYPE_INCORPOREAL || 
						GetRacialType(oTarget) == RACIAL_TYPE_OOZE || GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD || 
						GetRacialType(oTarget) == RACIAL_TYPE_CONSTRUCT) {
						SendMessageToPC(oCaster, "But unfortunately it is incappable of such an emotion...");
						// nothing happens
					} else {
						ShazFallInLove(oTarget, oCaster);
					}
				}
			} else {
				SpeakString("You get a strange feeling, but it passes...");
			}
			break;
		case 85 : //2d2f - Target changes sex
		    if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
			     int nSexChanged = SexChange(oTarget);
			     if(nSexChanged == 1)
			     {
                    SpeakString("The target changes sex!");
                 }
			     else
			     {
			        // lets be sneaky and target the caster if the target's race is invalid
			        // Gender bending will run amok! Muahahaha
                    int nSexChanged1 = SexChange(oCaster);
                    if(nSexChanged1 == 1)
			        {
                        SpeakString("Something feels different!");
                    }
			        else
			        {
                        SpeakString("You get an odd sensation, but it goes away.");
                    }
		        }
		    }
            break;
		case 86 : //2d2f - A small and  slightly dangerous raincloud forms above target
					// no chaos shield
				SmallRainCloud(oTarget);
				SpeakString("A small raincloud forms");
			break;
		case 87 :	// "Stinking Cloud" on target
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
				// since the shield only protects you from the EFFECT of the surge (it doesn't actually PREVENT the surge)
				// we'll make the caster immune to the next spell, which is this spell
				effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID), GetSpellLevel(iSpellID));
				// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 5.0f);
			}
			
			SpeakString("Stinky!!");
		
			JXCastSpellFromLocationAtLocation(lCaster, lTarget, SPELL_STINKING_CLOUD, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);

			break;
		case 88 :	// Heavy object falls on the target for 2d20 damage
			// well, this is just asking for a cow to fall on someone
			// so, thats what we'll do!!!
			// if the target is the caster, they might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				//lCast = GetRandomLocation(GetArea(OBJECT_SELF), OBJECT_SELF, 10.0f);
				vector vCast = GetPositionFromLocation(lTarget);
				//vCast.x += 5.0f;
				vCast.z += 15.0f;
				lCaster = Location(GetArea(OBJECT_SELF), vCast, IntToFloat(Random(360)));
				JXCastSpellFromLocationAtObject(lCaster, oTarget, 3679, METAMAGIC_NONE, iCasterLevel, iSpellSaveDC, TRUE, oCaster);
				SpeakString("A heavy object falls on the target!");
			}
			break;
		case 89 :	// target begins sneezing
			// the ToM has this as a regular silence. I'm going to do that... with a little extra ;-)
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				SpeakString("The target sneezes uncontrollably!");
				
				// only apply sneezing to non-dead creatures
				if(GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && GetIsDead(oTarget) == FALSE && GetScriptHidden(oTarget) == FALSE) {
					// don't make undead, constructs, or elementals sneeze - they don't breath
					if (GetRacialType(oTarget) != RACIAL_TYPE_CONSTRUCT && GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD && GetRacialType(oTarget) != RACIAL_TYPE_ELEMENTAL)
		        	{
						int iSneezeRounds = d6(1);
						SetLocalInt(oTarget, "SneezeRoundsLeft", iSneezeRounds);
	                    AssignCommand( oTarget, ClearAllActions(TRUE) );
						AssignCommand( oTarget, ShazDoSneezing() );
						
						effect eSilence = EffectSilence();
						JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSilence, oTarget, RoundsToSeconds(iSneezeRounds));
	            	}
				}
			}
			break;
		case 90 :	// target everyone within 60' of target
			// although it isn't true to the letter of the ToM, we're just gona re-cast the spell at everyone in 60'
			oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lTarget, TRUE, OBJECT_TYPE_CREATURE);
			iDebug=0;	// just a sanity check, to prevent infinite loops
			while (GetIsObjectValid(oTarget) && iDebug < 40)
	        {	
				if(oTarget == oCaster) {
					if(iShieldSuccess == 1) {
						iShieldPreventedSurge = 1;
						// also... provide some level of spell absorbtion... because you'll probably have like 5 fireballs exploding around you...
						effect eAbsorbEffect = EffectSpellLevelAbsorption(GetSpellLevel(iSpellID)*3, GetSpellLevel(iSpellID)*3);
						// duration does matter - for some reason magic missile reports lvl 9 - which is okay, since it hits like 7 times. but the leftover absorbtion, we want to wear off ASAP
						JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAbsorbEffect, oCaster, 3.0f);
					} else {
						DelayCommand(0.5f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), JXGetCasterLevel(), JXGetSpellSaveDC(), TRUE, oCaster));
					}
				} else {
					DelayCommand(0.5f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), JXGetCasterLevel(), JXGetSpellSaveDC(), TRUE, oCaster));
				}
				
				iDebug++;
	            //Get the next target in the shape
	            oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lTarget);
	        }
			SpeakString("Cast at them all!!!");
			break;
		case 91 :	// target's clothes itch (as 4)
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				SpeakString("Target's clothes itch!");
				SetLocalInt(oTarget, "ItchRoundsLeft", d6(4));
				ShazDoItchyClothing(oTarget);
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 92 : //Target changes races
		      if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
			     int nRaceChanged = RaceChange(oTarget);
			     if(nRaceChanged == 1)
			     {
                    SpeakString("The target changes Race!");
                 }
			     else
			     {
			        // I'm being sneaky again, like in the sex change surge
                    int nRaceChanged1 = RaceChange(oCaster);
                    if(nRaceChanged1 == 1)
			        {
                        SpeakString("You have become a diffrent race!");
                    }
			        else
			        {
                        SpeakString("You get an odd sensation, but it goes away.");
                    }
		        }
		    }
		    break;
		case 93 :	// target becomes "ethereal"
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				effect eEthereal = EffectEthereal();
				DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEthereal, oTarget, RoundsToSeconds(d4(2))));
				SpeakString("Ethereal!");
				SendMessageToPC(oTarget, "You become ethereal!!");
				
				// Shaz: we should really let the target know that its been dizzified
        		SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_ETHEREALNESS));
			}
			break;
		case 94 :	// target "hasted" (just target)
			// if the target is you, you might be shielded
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				effect eHaste = EffectHaste();
    			effect eDur = EffectVisualEffect( VFX_DUR_SPELL_HASTE );
    			effect eLink = EffectLinkEffects(eHaste, eDur);
				// using caster lvl for duration can be a really long time. Rethink it? (normal haste uses caster lvl)
				JXApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(JXGetCasterLevel(oCaster)));
				SpeakString("Target Hasted!");
				
				// Shaz: we should really let the target know that its been blinded
        			SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_HASTE));
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 95 :	// all cloth on target crumbles to dust
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				effect ePolyFX = EffectVisualEffect(VFX_IMP_POLYMORPH);
				
    			ApplyEffectToObject(DURATION_TYPE_INSTANT, ePolyFX, oTarget);
				// delaying the destruction of the clothing a bit so the effect has time to engulf them
				DelayCommand(0.75f, ShazDestroyAllClothOnTarget(oTarget));
				SpeakString("All cloth on the target crumbles to dust!");
			} else {
				SpeakString("You get a funny feeling, but it passes...");
			}
			break;
		case 96 ://2d2f: Target sprouts leaves
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
				//2d2f: duration 1- 4 days
				float fDur = HoursToSeconds(Random(36) + 24);
				effect eVis = EffectVisualEffect(VFX_DUR_SPROUTS_LEAVES);
				eVis = SupernaturalEffect(eVis);
				//eVis = SetEffectSpellId(eVis,iSpellID);
				ApplyEffectToObject(DURATION_TYPE_PERMANENT,SetEffectSpellId(eVis,SURGE_TEMP_SPELLID_LEAVES),oTarget);
				SetLocalInt(oTarget,"nSproutsLeavesId",SURGE_TEMP_SPELLID_LEAVES);
				if(GetHasFeat(FEAT_SELF_PRUNING,oTarget) != TRUE)
				{
					FeatAdd(oTarget,FEAT_SELF_PRUNING,FALSE);
				}
				//DelayCommand(fDur,RemoveSupernaturalEffectWithSpellId(oTarget,SURGE_TEMP_SPELLID_SPROUTS_LEAVES));
				SpeakString("Leaves rapidly sprout from their skin!");
			}
			break;
		case 97 : //2d2f: Target grows a new but useless appendage
				// I set the duration to 2-8 days
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
			RandomLimb(oTarget);
			SpeakString("A new but useless bodily feature grows!");
			}
				break;
		case 98 : //2d2f: Target's skin changes color
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else if(GetIsObjectValid(oTarget)) {
			ChangeSkinColor(oTarget);
			SpeakString("Their skin changes color!");
			
			}
			break;
		case 99 :	// spell lasts one turn minimum
			// Shaz: okay so i'm going to royally cheat here: Im just going to cast the spell over and over for 10 rounds
			//  note that this gets pretty close to what the ToM suggests in most cases
			
			// okay, casting it every round for 10 rounds was lame. Now I'll do every half round for five rounds...
			if((oTarget == oCaster) && (iShieldSuccess == 1)) {
				iShieldPreventedSurge = 1;
			} else {
				SpeakString("Your spell persists!!!");
				iOverrideOriginal = 0;	// so the original spell goes off
				//SendMessageToPC(oCaster, "SpellID: " + IntToString(iSpellID));
				if(JXGetHasSpellTargetTypeArea(iSpellID) == TRUE) {	
					//SendMessageToPC(oCaster, "Castin AOE from PErsist!!");
					DelayCommand(3.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(6.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(9.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(12.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(15.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(18.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(21.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(24.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(27.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
				} else {
					//SendMessageToPC(oCaster, "Casting non AOE from persist");
					//DelayCommand(2.0f, JXCastSpellFromLocationAtLocation(lCaster, lTarget, iSpellID, JXGetMetaMagicFeat(oCaster), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(3.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(6.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(9.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(12.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(15.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(18.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(21.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(24.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
					DelayCommand(27.0f, JXCastSpellFromLocationAtObject(lCaster, oTarget, iSpellID, JXGetMetaMagicFeat(), iCasterLevel, iSpellSaveDC, TRUE, oCaster));
				}
			}
			break;
		case 100 : //----Spell effectiveness increases 200%--//
			if((oTarget != oCaster) || (iShieldSuccess == 0))
			{
				// insert Wild Surge Visual effect here.
				SpeakString("You feel an incredible burst of POWER!");
				ShazIncreaseSpellStrength(oCaster);
				//return 0;	
				iOverrideOriginal = 0;
			} else {
				iShieldPreventedSurge = 1;
				// if you were casting a spell on yourself, and you surge, the spell gets stopped
			}
			break;

		default : 
			break;
	} // end of the huge switch on surge index
	
	if(iOverrideOriginal == 1) {
		SetModuleOverrideSpellScriptFinished();	// stop the current spell from going off!
	}

	if(iShieldPreventedSurge == 1)
	{
		SpeakString("Chaos Shield has prevented a Wild Surge from affecting you!");
		RemoveSpellEffects( SPELL_CHAOS_SHIELD , oCaster,  oCaster);
		// insert Wild Surge cancled visual effect here
		return 1;
	}
	
	doWildSurgeEffect(oCaster); // 2d2f: I think putting this here will cause the effct on a successful surge.
	
	return 0;
}