//::///////////////////////////////////////////////
//:: Wild Mage Spell - Hornung's Baneful Deflector On-Hit IP
//::///////////////////////////////////////////////
/*

Hornung's Baneful Deflector On-Hit IP

2d2f_sp_baneful_d_onhit.nss
*/
//::///////////////////////////////////////////////
//:: Created By: 2DruNk2Frag
//:: Created On: 02-18-2008
//:: Last Update: 05-19-2008
//::///////////////////////////////////////////////

//#include "2d2f_includes"
#include "2d2f_misc_functions"
//#include "jx_inc_magic"
//#include "x2_inc_spellhook" 
//#include "jx_inc_magic_info"
//#include "nwn2_inc_spells"
//#include "nw_i0_spells"

//:: prototypes

int BanefullGetNumberOfCreaturesInArea(location oCenter, float fRadius);

object BanefulGetRandomCreatureInArea(object oCaster, object oInitialTarget, float fRadius, int nCasterValidTarget = FALSE, int nInitialValidTarget = FALSE);

int getWeaponDamageType(object oItem);

int getWeaponDamage(object oItem);

int getLauncher(int nItem);

void main()
{
	object oPC = GetFirstPC();
	object oTarget = GetSpellTargetObject();
  	object oCaster = GetSpellCastItem();
	int nItem = GetBaseItemType(oCaster);
	int nHasBaneful = GetLocalInt(oPC,"nHasBanefulD");//GetHasSpellEffect(SPELL_BANEFUL_DEFLECTOR, oTarget);
	float fDelay;
		
	int nProjectTileHitType = OVERRIDE_ATTACK_RESULT_HIT_SUCCESSFUL;
	int nProjectileEffect = 0;
	int nWpEnhance;
	itemproperty ip1;
	int ipDamageBonus1 = 0;
	int ipDamageType1;
	effect eIp1;
	effect eWpDamBase;
	effect eLink;
			
	//SendMessageToPC(oPC,"Baneful D onhit fired");
		
	if(nHasBaneful == 1)
	{
		ip1 = GetFirstItemProperty(oCaster);
		if(GetItemPropertyType(ip1) == ITEM_PROPERTY_DAMAGE_BONUS && 
		GetIsItemPropertyValid(ip1))
		{
			ipDamageBonus1 = GetIPDamageBonus(ip1);
			ipDamageType1 = GetItemPropertySubType(ip1);
			eIp1 = EffectDamage(GetDamageFromReferenceNumber(ipDamageBonus1), convertIpDamTypeToEffectDamType(ipDamageType1));
			nProjectileEffect = convertIpDamTypeToEffectDamType(ipDamageType1);					
		}
						
		//SendMessageToPC(oPC,"ipdamagebonus1 = " + IntToString(ipDamageBonus1));
		//SendMessageToPC(oPC,"ipdamagetype1 = " + IntToString(convertIpDamTypeToEffectDamType(ipDamageType1)));
					
		if(ipDamageBonus1 != 0)
		{
			eLink = EffectLinkEffects(eIp1, eLink);
		}
					
		object oRandom = BanefulGetRandomCreatureInArea(oTarget,oTarget, RADIUS_SIZE_LARGE,TRUE,TRUE);
		
		int nDC = 13 + GetAbilityModifier(ABILITY_INTELLIGENCE,oTarget);
		
		if(GetHasFeat(FEAT_SPELL_FOCUS_EVOCATION,oTarget,TRUE) == TRUE)
		{
			nDC = nDC+1;
		}
		else if(GetHasFeat(FEAT_GREATER_SPELL_FOCUS_EVOCATION,oTarget,TRUE) == TRUE)
		{
			nDC = nDC+2;
		}
		else if(GetHasFeat(FEAT_EPIC_SPELL_FOCUS_EVOCATION,oTarget,TRUE) == TRUE)
		{
			nDC = nDC+3;
		}
		if(GetHasFeat(FEAT_SPELLCASTING_PRODIGY,oTarget,TRUE) == TRUE)
		{
			nDC = nDC+1;
		}
		
		SignalEvent(oRandom, EventSpellCastAt(oTarget,SPELL_BANEFUL_DEFLECTOR,TRUE));	
		
		//if (!/*Reflex Save*/ MySavingThrow(SAVING_THROW_REFLEX, oRandom, JXGetSpellSaveDC(oTarget),SAVING_THROW_TYPE_SPELL ))
        if (ReflexSave(oRandom, nDC,SAVING_THROW_TYPE_SPELL,oTarget ) == 0)
     	{			
			nWpEnhance = IPGetWeaponEnhancementBonus(oCaster);
			eWpDamBase = EffectDamage(getWeaponDamage(oCaster) + nWpEnhance, getWeaponDamageType(oCaster));
			eLink = EffectLinkEffects(eWpDamBase,eLink);
				
			nProjectTileHitType = OVERRIDE_ATTACK_RESULT_HIT_SUCCESSFUL;
			
			fDelay = GetProjectileTravelTime(GetLocation(oTarget),GetLocation(oRandom),PROJECTILE_PATH_TYPE_DEFAULT);
			DelayCommand(fDelay, JXApplyEffectToObject(DURATION_TYPE_INSTANT,eLink,oRandom));
		}
		else if(ReflexSave(oRandom, nDC,SAVING_THROW_TYPE_SPELL,oTarget ) != 0)
     	{		
			nProjectTileHitType = OVERRIDE_ATTACK_RESULT_MISS;
		}
						
			SpawnItemProjectile(oTarget,
								oRandom,
								GetLocation(oTarget),
								GetLocation(oRandom),
								getLauncher(nItem),// longbow. later function result
								PROJECTILE_PATH_TYPE_HOMING,
								nProjectTileHitType,
								nProjectileEffect); 
		
		} // if baneful close

}// main

int BanefullGetNumberOfCreaturesInArea(location oCenter, float fRadius)
{
	int iNumberOfCreatures = 0;
	// Iterate through all creatures
	object oCreature = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, oCenter, TRUE, OBJECT_TYPE_CREATURE);
	while (GetIsObjectValid(oCreature))
	{
		if((GetIsDead(oCreature) != TRUE) && (GetScriptHidden(oCreature) != TRUE)) {
			iNumberOfCreatures++;
		} else {
			//object oPC = GetFirstPC();
			//SendMessageToPC(oPC, "Avoid counting creature " + GetName(oCreature));
		}

		oCreature = GetNextObjectInShape(SHAPE_SPHERE, fRadius, oCenter, TRUE, OBJECT_TYPE_CREATURE);
	}

	return iNumberOfCreatures;
}

//::///////////////////////////////////////////////

object BanefulGetRandomCreatureInArea(object oCaster, object oInitialTarget, float fRadius, int nCasterValidTarget = FALSE, int nInitialValidTarget = FALSE)
{
	 object oPC = GetFirstPC();	// for debuggind purposes only
	int iNumberOfTargets;
	 // Find the possible number of targets 
	if(nCasterValidTarget == FALSE && nInitialValidTarget == FALSE) // (Caster and initial target are not a valid target)
	{
		iNumberOfTargets = BanefullGetNumberOfCreaturesInArea(GetLocation(oCaster), fRadius) - 2;
	}
	else if(nCasterValidTarget == FALSE && nInitialValidTarget == TRUE) // (Caster is not a valid target)
	{
		iNumberOfTargets = BanefullGetNumberOfCreaturesInArea(GetLocation(oCaster), fRadius) - 1;
	}
	else if(nCasterValidTarget == TRUE && nInitialValidTarget == FALSE) // (Initial target is not a valid target)
	{
		iNumberOfTargets = BanefullGetNumberOfCreaturesInArea(GetLocation(oCaster), fRadius) - 1;
	}
	else // (Caster and initial target ARE valid target)
	{
		iNumberOfTargets = BanefullGetNumberOfCreaturesInArea(GetLocation(oCaster), fRadius);
	}
	
	//SendMessageToPC(oPC, IntToString(iNumberOfTargets) + " valid targets found by GetRandomCreature");
	
	// Shaz: It seems to me, if the caster was alone and this was called with 
	//  caster & target invalid, you'd get -1
	//if (iNumberOfTargets == 0)
	if(iNumberOfTargets <= 0) {
		return OBJECT_INVALID;
	}

	// Randomly choose a target
	int iRandomTarget = Random(iNumberOfTargets)+ 1;
	int iTargetsLoop = 0;
	// Iterate through all creatures
	object oRandomTarget = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, GetLocation(oCaster), TRUE, OBJECT_TYPE_CREATURE);
	while (GetIsObjectValid(oRandomTarget))
	{
		if((GetIsDead(oRandomTarget) != TRUE) && (GetScriptHidden(oRandomTarget) != TRUE))
		{
			if(nCasterValidTarget == FALSE && nInitialValidTarget == FALSE) // Caster and initial target are not a valid target valid target
			{			
				if ((oRandomTarget != oCaster)
				&& (oRandomTarget != oInitialTarget))
				{
					iTargetsLoop++;
					if (iTargetsLoop == iRandomTarget)	// Random target found
					return oRandomTarget;
				}
			}
			else if(nCasterValidTarget == FALSE && nInitialValidTarget == TRUE) // (Caster is not a valid target)
			{			
				if ((oRandomTarget != oCaster)
				)
				{
					iTargetsLoop++;
					if (iTargetsLoop == iRandomTarget)	// Random target found
					return oRandomTarget;
				}
			}
			else if(nCasterValidTarget == TRUE && nInitialValidTarget == FALSE) // (Initial target is not a valid target)
			{			
				if ((oRandomTarget != oInitialTarget)
				)
				{
					iTargetsLoop++;
					if (iTargetsLoop == iRandomTarget)	// Random target found
					return oRandomTarget;
				}
			}
			else // caster and initial target are valid 
			{
				iTargetsLoop++;
				if (iTargetsLoop == iRandomTarget)	// Random target found
				return oRandomTarget;
			}
		}
	oRandomTarget = GetNextObjectInShape(SHAPE_SPHERE, fRadius, GetLocation(oCaster), TRUE, OBJECT_TYPE_CREATURE);
	}
		

	// Should not be called
	SendMessageToPC(oPC, "Reached bottom of GetRandomCreatureInArea");
	return OBJECT_INVALID;

}

int getWeaponDamageType(object oItem)
{
object oPC = OBJECT_SELF;
int nBaseItem = GetBaseItemType(oItem);

	if(GetIsObjectValid(oItem))
	{
	
	int nWeaponType =  ( StringToInt(Get2DAString("baseitems","WeaponType",nBaseItem)));
		if(nWeaponType == 3 || nWeaponType == 4)
		{
		return DAMAGE_TYPE_SLASHING;
		}
		else if(nWeaponType == 2)
		{
		return DAMAGE_TYPE_BLUDGEONING;
		}
		else if(nWeaponType == 1)
		{
		return DAMAGE_TYPE_PIERCING;
		}
		else
		{
		return FALSE;
		}	
	}
	else
	{
	return FALSE;
	}
}

int getWeaponDamage(object oItem)
{
int nBaseItem = GetBaseItemType(oItem);

	if(GetIsObjectValid(oItem))
	{
	
	int nNumDice =  ( StringToInt(Get2DAString("baseitems","NumDice",nBaseItem)));
	int nDieToRoll =  ( StringToInt(Get2DAString("baseitems","DieToRoll",nBaseItem)));
		if(nNumDice == 1 && nDieToRoll == 3)
		{
		return d3(1);//DAMAGE_BONUS_1d4;
		}	
		if(nNumDice == 1 && nDieToRoll == 4)
		{
		return d4(1);//DAMAGE_BONUS_1d4;
		}
		else if(nNumDice == 1 && nDieToRoll == 6)
		{
		return d6(1);//DAMAGE_BONUS_1d6;
		}
		else if(nNumDice == 1 && nDieToRoll == 8)
		{
		return d8(1);//DAMAGE_BONUS_1d8;
		}
		else if(nNumDice == 1 && nDieToRoll == 10)
		{
		return d10(1);//DAMAGE_BONUS_1d10;
		}
		else if(nNumDice == 1 && nDieToRoll == 12)
		{
		return d12(1);//DAMAGE_BONUS_1d12;
		}
		else if(nNumDice == 2 && nDieToRoll == 4)
		{
		return d4(2);//DAMAGE_BONUS_2d4;
		}
		else if(nNumDice == 2 && nDieToRoll == 6)
		{
		return d6(2);//DAMAGE_BONUS_2d6;
		}
		else
		{
		return 0;
		}	
	}
	else
	{
	return 0;
	}
}

int getLauncher(int nItem)
{
	if(nItem == BASE_ITEM_ARROW)
	{
		return BASE_ITEM_LONGBOW;
	}
	else if(nItem == BASE_ITEM_BOLT)
	{
		return BASE_ITEM_HEAVYCROSSBOW;
	}
	else if(nItem == BASE_ITEM_BULLET)
	{
		return BASE_ITEM_SLING;
	}
	else
	{
		return nItem;
	}
}