//::///////////////////////////////////////////////
//:: Analyze Dweomer : On Enter
//:: jx_sp_anadweomer.nss
//:://////////////////////////////////////////////
/*
	The caster analyzes 1 item or creature per
	round. If the object analyzed is a magical
	item, it is identified. If it's a creature,
	all active spells are revealed except if the
	target creature succeeds a Will check.
*/
//:://////////////////////////////////////////////
//:: Created By: jallaix
//:: Created On: Aug 17, 2007
//:://////////////////////////////////////////////

#include "nw_i0_spells"
#include "jx_inc_magic_ident"
#include "ginc_companion"



void AnalyzeDweomerIdentify(object oCaster);
void AnalyzeDweomerByRound(int iRoundCount, object oCaster, location lCaster);


const string JX_ANALYZEDWEOMER_RESISTED = "JX_ANALYZEDWEOMER_RESISTED";

string MSG_ITEM_NOT_MAGICAL				= GetStringByStrRef(17079431);
string MSG_ITEM_ALREADY_IDENTIFIED		= GetStringByStrRef(17079432);
string MSG_ITEM_IDENTIFIED				= GetStringByStrRef(17079433);
string MSG_CREATURE_NOSPELL				= GetStringByStrRef(17079434);
string MSG_CREATURE_SPELL				= GetStringByStrRef(17079435);
string MSG_CREATURE_RESISTED			= GetStringByStrRef(17079436);
string MSG_CREATURE_ALREADY_RESISTED	= GetStringByStrRef(17079437);

string sObjectsDetected;		// Saved objects
int iPosition;					// Current object to analyze
int iObjectsNumber;				// Number of objects to analyze


//-----------------------------------------
// Analyze Dweomer : Perform identification
//-----------------------------------------
void AnalyzeDweomerIdentify(object oCaster)
{
	string sObject;
	object oDetected;
	string sMessage;

	// Get the object previously saved
	sObject = JXStringSplit(sObjectsDetected, ";", iPosition);
	oDetected = IntToObject(StringToInt(sObject));

	if (GetObjectType(oDetected) == OBJECT_TYPE_ITEM)
	{
		// Identify the item
		string sItemProperties = JXGetHiddenItemProperties(oDetected);
		if (JXGetIsItemMagical(oDetected, sItemProperties))
		{
			if (JXGetIsItemIdentified(oDetected))
				sMessage = JXStringReplaceToken(MSG_ITEM_ALREADY_IDENTIFIED, 850, GetName(oDetected));
			else
			{
				JXIdentifyItem(oDetected);
				sMessage = JXStringReplaceToken(MSG_ITEM_IDENTIFIED, 850, GetName(oDetected));
			}
		}
		else
			sMessage = JXStringReplaceToken(MSG_ITEM_NOT_MAGICAL, 850, GetName(oDetected));

		AssignCommand(oDetected, SpeakString(sMessage));
	}
	else if (GetObjectType(oDetected) == OBJECT_TYPE_CREATURE)
	{
		// The creature already resisted the spell
		if (GetLocalInt(oDetected, JX_ANALYZEDWEOMER_RESISTED) == 1)
			AssignCommand(oDetected, SpeakString(MSG_CREATURE_ALREADY_RESISTED));
		//Make a Will Save to avoid the active spells to be detected.
		else if (!MySavingThrow(SAVING_THROW_WILL,
						   oDetected,
						   JXGetSpellSaveDC(),
						   SAVING_THROW_TYPE_SPELL,
						   GetAreaOfEffectCreator()))
		{
			string sActiveSpells = JXGetActiveSpells(oDetected);
			int bSpellDetected = FALSE;
	
			int iSpellId;
			int iSpellCasterLevel;
	
			// Loop all active spells on the creature
			int iCount = JXStringSplitCount(sActiveSpells, ";");
			int iLoop;
			for (iLoop = 0; iLoop < iCount; iLoop++)
			{
				//Fire cast spell at event for the target
				SignalEvent(oDetected, EventSpellCastAt(oCaster, JX_SPELL_ANALYZEDWEOMER, FALSE));
	
				// Find a spell informations
				iSpellId = StringToInt(JXStringSplit(sActiveSpells, ";", iLoop));
				iSpellCasterLevel = JXGetSpellCasterLevel(oDetected, iSpellId);
				if ((iSpellCasterLevel > 0) && (JXGetIsSpellMagical(iSpellId)))
				{
					// Print a message : Spell name and caster level
					sMessage = JXStringReplaceToken(MSG_CREATURE_SPELL, 850, JXGetSpellName(iSpellId));
					sMessage = JXStringReplaceToken(sMessage, 851, IntToString(iSpellCasterLevel));
					AssignCommand(oDetected, SpeakString(sMessage));
	
					bSpellDetected = TRUE;
				}
			}
	
			// Print a message : No spell detected
			if (!bSpellDetected)
				AssignCommand(oDetected, SpeakString(MSG_CREATURE_NOSPELL));
		}
		else
		{
			SetLocalInt(oDetected, JX_ANALYZEDWEOMER_RESISTED, 1);
			AssignCommand(oDetected, DelayCommand(HoursToSeconds(24), DeleteLocalInt(oDetected, JX_ANALYZEDWEOMER_RESISTED)));
			AssignCommand(oDetected, SpeakString(MSG_CREATURE_RESISTED));
		}
	}
}


//---------------------------------------------
// Analyze Dweomer : Search items and creatures
//---------------------------------------------
void AnalyzeDweomerByRound(int iRoundCount, object oCaster, location lCaster)
{
	// If the caster is not concentrating or if his position has changed, wait for the next round
	if ((GetCurrentAction(oCaster) != ACTION_INVALID) || (GetLocation(oCaster) != lCaster))
	{
		DelayCommand(6.0f, AnalyzeDweomerByRound(1, oCaster, GetLocation(oCaster)));
		return;
	}

	// Do nothing
	if (iRoundCount == 0)
		DelayCommand(6.0f, AnalyzeDweomerByRound(0, oCaster, lCaster));

	// Locate objects to analyze
	else if (iRoundCount == 1)
	{
		sObjectsDetected = "";
		iPosition = 0;

		// Compute the maximum distance of items to identify
		int iCasterLevel = JXGetCasterLevel();
		float iMaxDistance = 7.6 + 1.5 * (iCasterLevel / 2);

		// Loop items in the sphere area
		object oDetected = GetFirstObjectInShape(SHAPE_SPHERE, iMaxDistance, GetLocation(oCaster), TRUE, OBJECT_TYPE_ITEM);
		while (GetIsObjectValid(oDetected))
		{
			// Add the item to the detected objects list
			if (sObjectsDetected != "") sObjectsDetected += ";";
			sObjectsDetected += IntToString(ObjectToInt(oDetected));

			oDetected = GetNextObjectInShape(SHAPE_SPHERE, iMaxDistance, GetLocation(oCaster), TRUE, OBJECT_TYPE_ITEM);
		}

		// Loop creatures in the sphere area
		oDetected = GetFirstObjectInShape(SHAPE_SPHERE, iMaxDistance, GetLocation(oCaster), TRUE, OBJECT_TYPE_CREATURE);
		while (GetIsObjectValid(oDetected))
		{
			if (!GetIsObjectInParty(oDetected))
			{
				// Add the creature to the detected objects list
				if (sObjectsDetected != "") sObjectsDetected += ";";
				sObjectsDetected += IntToString(ObjectToInt(oDetected));
			}

			oDetected = GetNextObjectInShape(SHAPE_SPHERE, iMaxDistance, GetLocation(oCaster), TRUE, OBJECT_TYPE_CREATURE);
		}

		// Write down the number of objects to analyze
		iObjectsNumber = JXStringSplitCount(sObjectsDetected, ";");

		AnalyzeDweomerByRound(2, oCaster, lCaster);
	}

	// Analyze an object
	else if (iRoundCount == 2)
	{
		// Perform the identification of objects
		AnalyzeDweomerIdentify(oCaster);
		if (++iPosition < iObjectsNumber)
			DelayCommand(6.0, AnalyzeDweomerByRound(2, oCaster, lCaster));
		else
			DelayCommand(6.0, AnalyzeDweomerByRound(0, oCaster, lCaster));
	}
}


//--------------------------------------------------
// Analyze Dweomer (main function) : Start detection
//--------------------------------------------------
void main()
{
	object oCaster = GetEnteringObject();

	// Test if the entering object is the caster
	object oAOECreator = JXGetAOERealCreator();
	if (oAOECreator != oCaster) return;

	// Look for items and creatures
	AnalyzeDweomerByRound(1, oCaster, GetLocation(oCaster));
}