//::///////////////////////////////////////////////
//:: Wild Mage Spell - Dysmorphigation
//::///////////////////////////////////////////////
/*
Dysmorphigation

Caster Level(s): Wizard / Sorcerer 6
Innate Level: 6
School: Transmutaion 
Descriptor(s): Wild Magic
Component(s): Verbal, Somatic
Range: Medium
Area of Effect / Target: One Creature
Duration: 1d4 + level/2 rounds
Save: Fortitude Negates
Spell Resistance: Yes

!!! This is a Wild Magic Spell and can only be cast by a Wild Mage !!!

     This spell severely disrupts the structure of the weave that binds the target creature
to its current shape.  This attack to the most basic elements of their form forces the 
creature’s essence into a primordial state similar to when their form was originally chosen 
for them.  No creature can remain in this state for more than a fraction of an instant and a 
new form is hastily taken as determined by the powers that be.
     There is no way to predict the shape the target will take.  Those who have witnessed a 
Dysmorphigation report a wide variety of shapes including common livestock, dire animals, 
outsiders, and even dragons.
     Dysmorphigation differs in several ways to self-imposed polymorph.  The target creature 
is will be disoriented and clumsy in their new form suffering -2 to attack rolls, saving 
throws, and to all skills.  Their hit points will be determined by their level and the 
constitution of their new shape.  Additionally, if they happen to become a creature that is 
frailer than themselves their hit point total will be adjusted accordingly.  For example, 
the ingenious Wild Mage Shazbotian casts Dysmorphigation on a level 9 fighter.  Shazbotion 
is extremely lucky and the fighter dysmorphs into a dire rat. Instead of gaining a hit point 
bonus from the transformation, as typical in self-imposed polymorphs, his hit point total 
lowers from 108 to 14.  If the target manages to live through the duration of the spell they 
regain their lost hit points upon reformation.
     Dysmorphigation is will transform the target creature into form of power manageable, 
but still dangerous, to a level 11 caster approximately 40 percent of the time.  Another 40 
percent of the time the form will be of a power level anywhere from slightly annoying to 
pathetically weak.  However, the other 20 percent of the time an extremely powerful and 
deadly form will take shape.  This risk must be weighed against the advantages of 
dysmorphing a creature which include a typically lowered AC, no equipment, and inability to 
cast spells.

2d2f_sp_dysmorphigation.nss
*/
//::///////////////////////////////////////////////
//:: Created By: 2DruNk2Frag
//:: Created On: 03-31-2008
//:: Last Update: 04-04-2008
//::///////////////////////////////////////////////

#include "2d2f_includes"
#include "jx_inc_magic"
#include "x2_inc_spellhook" 
#include "jx_inc_magic_info"
#include "nwn2_inc_spells"
#include "nw_i0_spells"
#include "NW_I0_GENERIC"



//:: 2d2f need to be called after a short delay
void SetHitPointsToCreature(object oTarget, int nBase, int nGoal, float fDuration);

void mainSpell();
void main()
{
	AssignCommand(JXGetCaster(), mainSpell());
}

void mainSpell()
{
	object oCaster = JXGetCaster();
	int nWMLvl = GetLevelByClass(CLASS_WILDMAGE, oCaster);
	if(nWMLvl >= 9)
	{
/* 
  Spellcast Hook Code 
  Added 2003-06-23 by GeorgZ
  If you want to make changes to all spells,
  check x2_inc_spellhook.nss to find out more
  
*/

    if (!X2PreSpellCastCode())
    {
	// If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        { JXPostSpellCastCode(); return; }
    }
	//:://////////////////////////////////////////
	
	object oTarget = JXGetSpellTargetObject();
	int nLvl = JXGetCasterLevel();
	int nDur = d4(1) + (nLvl/2);
	float fDuration = RoundsToSeconds(nDur);

	//Check for metamagic extend
    fDuration = ApplyMetamagicDurationMods(fDuration);
    int nDurType = ApplyMetamagicDurationTypeMods(DURATION_TYPE_TEMPORARY);
	
	// check if polyporphed
	if(GetHasEffect(EFFECT_TYPE_POLYMORPH,oTarget) != TRUE)
	{
	
	if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))
	{
        //Fire cast spell at event for the specified target
        SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_DYSMORPHIGATION));
       //Make SR check
       if (!MyResistSpell(OBJECT_SELF, oTarget))
	   {
            //Make Fort save
            if (!/*Fort Save*/ MySavingThrow(SAVING_THROW_FORT, oTarget, JXGetSpellSaveDC(),SAVING_THROW_TYPE_SPELL ))
            {		
				
				int 	iPolyRand = Random(20);
				int		iPolyIndex;
				int		nCreatureHitPoints;
				int nRand;
				
				switch(iPolyRand) {
					case 0: // cr < .5
						nRand = d3(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_CHICKEN;
						nCreatureHitPoints = 1;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_COW;
						nCreatureHitPoints = 1;
						}
						else if(nRand == 3)
						{
						iPolyIndex = POLYMORPH_TYPE_DIRE_RAT;
						nCreatureHitPoints = 5;
						}			
						break;
					case 1: // cr .5 - 1
						nRand = d3(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_ZOMBIE;
						nCreatureHitPoints = 14;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_BADGER;
						nCreatureHitPoints = 6;
						}
						else if(nRand == 3)
						{
						iPolyIndex = POLYMORPH_TYPE_WOLF;
						nCreatureHitPoints = 13;
						}			
						break;
					case 2: // cr 2
						nRand = d3(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_GIANT_SPIDER;
						nCreatureHitPoints = 22;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_PANTHER;
						nCreatureHitPoints = 19;
						}
						else if(nRand == 3)
						{
						iPolyIndex = POLYMORPH_TYPE_BOAR;
						nCreatureHitPoints = 25;
						}			
						break;
					case 3: // cr 2
						nRand = d3(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_IMP;
						nCreatureHitPoints = 13;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_DIRE_BADGER;
						nCreatureHitPoints = 13;
						}
						else if(nRand == 3)
						{
						iPolyIndex = POLYMORPH_TYPE_CELESTIAL_LEOPARD;
						nCreatureHitPoints = 19;
						}			
						break;
					case 4: // cr 3
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_WEREWOLF;
						nCreatureHitPoints = 20;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_DIRE_WOLF;
						nCreatureHitPoints = 45;
						}
						break;
					case 5: // cr 4
						nRand = Random(5);
						if(nRand == 0)
						{
						iPolyIndex = POLYMORPH_TYPE_PIXIE;
						nCreatureHitPoints = 3;
						}
						else if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_BROWN_BEAR;
						nCreatureHitPoints = 60;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_DIRE_BOAR;
						nCreatureHitPoints = 63;
						}
						else if(nRand == 3)
						{
						iPolyIndex = POLYMORPH_TYPE_GARGOYLE;
						nCreatureHitPoints = 32;
						}
						else if(nRand == 4)
						{
						iPolyIndex = POLYMORPH_TYPE_SWORD_SPIDER;
						nCreatureHitPoints = 32;
						}				
						break;
					case 6: //cr 5
						nRand = d3(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_PHASE_SPIDER;
						nCreatureHitPoints = 45;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_WINTER_WOLF;
						nCreatureHitPoints = 51;
						}
						else if(nRand == 3)
						{
						iPolyIndex = POLYMORPH_TYPE_TROLL;
						nCreatureHitPoints = 63;
						}						
						break;
					case 7: //cr 6.5
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_SHAMBLING_MOUND;
						nCreatureHitPoints = 60;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_UMBER_HULK;
						nCreatureHitPoints = 71;
						}
						break;
					case 8:// cr 7
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_HUGE_FIRE_ELEMENTAL;
						nCreatureHitPoints = 136;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_HUGE_WATER_ELEMENTAL;
						nCreatureHitPoints = 152;
						}						
						break;
					case 9: //  cr 7
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_HUGE_EARTH_ELEMENTAL;
						nCreatureHitPoints = 152;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_HUGE_AIR_ELEMENTAL;
						nCreatureHitPoints = 136;
						}						
						break;
					case 10: // cr 7
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_SUCCUBUS;
						nCreatureHitPoints = 33;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_DIRE_BROWN_BEAR;
						nCreatureHitPoints = 120;
						}						
						break;
					case 11: // cr 7.5
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_MINDFLAYER;
						nCreatureHitPoints = 44;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_TREANT;
						nCreatureHitPoints = 66;
						}						
						break;
					case 12: // cr 9.5
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_FROST_GIANT_MALE;
						nCreatureHitPoints = 133;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_FIRE_GIANT;
						nCreatureHitPoints = 142;
						}						
						break;
					case 13: // cr 11
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_ELDER_FIRE_ELEMENTAL;
						nCreatureHitPoints = 204;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_ELDER_WATER_ELEMENTAL;
						nCreatureHitPoints = 228;
						}						
						break;
					case 14: // cr 11
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_ELDER_EARTH_ELEMENTAL;
						nCreatureHitPoints = 228;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_ELDER_AIR_ELEMENTAL;
						nCreatureHitPoints = 204;
						}						
						break;
					case 15: // cr 12.5
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_DOOM_KNIGHT;
						nCreatureHitPoints = 180;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_IRON_GOLEM;
						nCreatureHitPoints = 129;
						}						
						break;
					case 16: // cr 16
						iPolyIndex = POLYMORPH_TYPE_HORNED_DEVIL;
						nCreatureHitPoints = 172;						
						break;
					case 17: // cr 16
						iPolyIndex = POLYMORPH_TYPE_NIGHTWALKER;
						nCreatureHitPoints = 178;						
						break;
					case 18: // cr 17.5
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_BLUE_DRAGON;
						nCreatureHitPoints = 387;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_BLACK_DRAGON;
						nCreatureHitPoints = 276;
						}						
						break;
					case 19: // cr 20
						nRand = d2(1);
						if(nRand == 1)
						{
						iPolyIndex = POLYMORPH_TYPE_RED_DRAGON;
						nCreatureHitPoints = 449;
						}
						else if(nRand == 2)
						{
						iPolyIndex = POLYMORPH_TYPE_BALOR;
						nCreatureHitPoints = 280;
						}						
						break;
					default:
						iPolyIndex = POLYMORPH_TYPE_CHICKEN;
				}
				
				// Shaz: there are several things about the implementation of this effect I really don't like.
				//	#1: the natural armor is simply added to the creatures previous armor. Unacceptable! A red dragon changed into a boar would *increase* its AC!!!
				effect	eAC = EffectACDecrease(GetAC(oTarget) - 10);
				//	#2: the players handbook states that being changed into an unfamiliar form makes the victim suffer penalties in "stressful situations" we'll just make those permanent ;-)
				effect	eAttack = EffectAttackDecrease(2);
				effect	eSkill = EffectSkillDecrease(SKILL_ALL_SKILLS, 2);
				effect	eSaves = EffectSavingThrowDecrease(SAVING_THROW_ALL, 2, SAVING_THROW_TYPE_ALL);
				//effect	eDamage = EffectDamageDecrease(2);	// this one is my own doing; player's handbook doesn't say anything about it
				effect	eLink;
				
				effect ePoly = EffectPolymorph(iPolyIndex, TRUE);
				effect ePolyFX = EffectVisualEffect(VFX_IMP_POLYMORPH);
				
				// 2d2f: When testing I found that casters could still cast when polymorphed.
				// apparently only PC when polymorphed can't cast spells.
				// to hell with that!
				effect eSilence = EffectSilence();
				effect eFail = EffectSpellFailure();
			   
				eLink = EffectLinkEffects(eLink, ePoly);
				eLink = EffectLinkEffects(eLink, eAC);
				eLink = EffectLinkEffects(eLink, eAttack);
				eLink = EffectLinkEffects(eLink, eSkill);
				eLink = EffectLinkEffects(eLink, eSaves);
				eLink = EffectLinkEffects(eLink, eSilence);
				eLink = EffectLinkEffects(eLink, eFail);
				eLink = SetEffectSpellId(eLink, SPELL_DYSMORPHIGATION);	
				
				// get hitpoints before transformation		
				int nBaseHitPoints = GetCurrentHitPoints(oTarget);
						 		
    			ApplyEffectToObject(DURATION_TYPE_INSTANT, ePolyFX, oTarget);
			    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDuration);
				SetHitPointsToCreature(oTarget,nBaseHitPoints, nCreatureHitPoints, fDuration);
						
			}
        }
    }
	}//end effect poly check
	else // curtesy message
	{
		SendMessageToPC(oCaster, "The target is already polymorphed.");	
	}

	
	}
	else
	{
	SendMessageToPC(oCaster, "You must be at least a level 9 Wild Mage to use this spell");
	}
	
	
	JXPostSpellCastCode();
	return;
}
//:2d2f this function lowers the targets hit points if the creature they polymorph
//: into (eg a chicken) typically has less than their current hit point total. They 
//: they get these hit points back if they survive for the duration.
void SetHitPointsToCreature(object oTarget, int nBase, int nGoal, float fDuration)
{	
	int nDam;
	int nTempHit;
	effect eDam;
	effect eHeal;
		
	//int nCurrent = GetCurrentHitPoints(oTarget);
	//SendMessageToPC(GetFirstPC(),"current hit points = " + IntToString(nCurrent));
	
	// here we want to bring down hit points to where we want them
	if(nBase > nGoal) 
	{			
		nDam = (nBase - nGoal);
		eHeal = EffectHeal(nDam);
		eDam = EffectDamage(nDam,DAMAGE_TYPE_MAGICAL,DAMAGE_POWER_ENERGY,TRUE);
		ApplyEffectToObject(DURATION_TYPE_INSTANT,eDam,oTarget);
		DelayCommand(fDuration,ApplyEffectToObject(DURATION_TYPE_INSTANT,eHeal,oTarget));
	}
}