//:: jw_privates_inc.nss

const int X2_SPELL_AOEBEHAVIOR_FLEE = 0;
const int X2_SPELL_AOEBEHAVIOR_IGNORE = 1;
const int X2_SPELL_AOEBEHAVIOR_GUST = 2;
const int X2_SPELL_AOEBEHAVIOR_DISPEL_L = SPELL_LESSER_DISPEL;
const int X2_SPELL_AOEBEHAVIOR_DISPEL_N = SPELL_DISPEL_MAGIC;
const int X2_SPELL_AOEBEHAVIOR_DISPEL_G = SPELL_GREATER_DISPELLING;
const int X2_SPELL_AOEBEHAVIOR_DISPEL_M = SPELL_MORDENKAINENS_DISJUNCTION;
const int X2_SPELL_AOEBEHAVIOR_DISPEL_C = 727;


#include "x0_inc_generic"
#include "prc_inc_spells"
#include "prc_inc_skills"

//::///////////////////////////////////////////////////////////////////////////////////////////////
//:: Associate Include Functions
//:: NW_I0_ASSOCIATE
//:: Copyright (c) 2001 Bioware Corp.
//:://///////////////////////////////////////////////////////////////////////////////////////////
/*
    Determines and stores the behavior of the
    associates used by the PC
*/
//:://///////////////////////////////////////////////////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: November 16, 2001
//:://////////////////////////////////////////////////////////////////////////////////////////////

//Distance
//Heal when
//Auto AI
//Open Locks on master fail
//Casting power
//ASSOCIATE MASTER VARIABLE FUNCTIONS



//ASSOCIATE FUNCTIONS
int GetAssociateCRMax();
void CheckIsUnlocked(object oLastObject);
//PRIVATE FUNCTION DECLARATIONS



// --------------------------------------------------------------------------------
// GZ: Sept 2003
// Determines the optimal behavior against AoESpell nSpellId for a NPC
// use in OnSpellCastAt
// --------------------------------------------------------------------------------
int GetBestAOEBehavior(int nSpellID);

// Gets the number of wingblast attacks this mob has
int GetWingblast(object oMob=OBJECT_SELF);
// Sets the number of wingblast attacks this mob has (default is zero)
void SetWingblast(int nBlasts=0);
// Returns TRUE if oMob has hp lower than 1, else returns false
int GetIsDeadOrBleeding(object oMob=OBJECT_SELF);
// sets oTarget as a target for oMob for oMob to heal
void SetNeedsHealing(object oTarget, object oMob=OBJECT_SELF);
// gets the last caller for healing that oMob heard
object GetNeedsHealing(object oMob=OBJECT_SELF);
// plays healing call if appropriate, 50 per cent chance
// should ONLY be used with object self
int CheckHeal(object oMob=OBJECT_SELF);
// makes the monster rest if it is damaged
int MonsterRest(object oMob=OBJECT_SELF);
// cycles spell effects when checking victim
int CycleProtections(int nLastChecked);
// checks if oTarget has en effect caused by spell nSpell_ID
int CheckProtection(int nSpell_ID, object oTarget);
// check whether the enemy has a spell on it causing a positive effect
int CheckHasPositiveEffect(object oTarget);
// sets oTarget as a target for oMob for oMob to follow when out of combat
void SetTarget(object oTarget, object oMob=OBJECT_SELF);
// gets the last target that was a target of oMob. THis may not be the best target,
// just the most recent.
object GetTarget(object oMob=OBJECT_SELF);
// returns TRUE if the mob is a custom encounter creature, meaning it was either
// spawned by an encounter and has not had the encounter feature turned of or
// ir was NOT spawned by an encounter but has had the custom encounter features turned on.
int GetisCustomEncounterCreature(object oMob=OBJECT_SELF);
// sets the creature to be an encounter creature or not. Will override whether or not
// the creature was actullay spawned from an encounter. Set nIsEncounter TRUE to
// make it an encouner creature or FALSE to make it not an encounter creature
void SetisCustomEncounterCreature(int nIsEncounter, object oMob=OBJECT_SELF);
// sets the creature's start location
void SetStartLocation(object oMob=OBJECT_SELF);
// Gets the creature's start location
location GetStartLocation(object oMob=OBJECT_SELF);
// return's the Mob's current victim, but if this victim is dead, invalid or
// out of sight, picks the next vistim and sets it too.
object ChooseTarget(object oMob=OBJECT_SELF);
// sets oTarget as a target for oMob for oMob to fight
void SetVictim(object oTarget, object oMob=OBJECT_SELF);
// gets the mob's current victim.
object GetVictim(object oMob=OBJECT_SELF);
//gets the target the caller is currently fighting
object GetTargetFighting();
//Adds all three of the class levels together.  Used before GetHitDice became available
//int GetCharacterLevel(object oTarget);
//Compares the current spell with the last one cast
int CompareLastSpellCast(int nSpell);
//If using ambient sleep this will remove the effect
void RemoveAmbientSleep();
//Searches for the nearest locked object to the master
object GetLockedObject(object oMaster);



int GetWingblast(object oMob=OBJECT_SELF)
{
int nBlasts=GetLocalInt(OBJECT_SELF,"nWingblasts");
return nBlasts;
}


void SetWingblast(int nBlasts=0)
{
SetLocalInt(OBJECT_SELF,"nWingblasts",nBlasts);
}

int GetIsDeadOrBleeding(object oMob=OBJECT_SELF)
{
if (GetIsDead(oMob))
{
return TRUE;
}

if (GetCurrentHitPoints(oMob)<1)
{
return TRUE;
}

return FALSE;

}

void SetNeedsHealing(object oTarget, object oMob=OBJECT_SELF)
{
if (GetObjectType(oTarget)==OBJECT_TYPE_AREA_OF_EFFECT)
  {
   return;
  }
else
  {
   SetLocalObject(oMob,"needshealing",oTarget);
  }
}

object GetNeedsHealing(object oMob=OBJECT_SELF)
{
object oTarget=GetLocalObject(oMob,"needshealing");
return (oTarget);
}


int CycleProtections(int nLastChecked)
{


     if (nLastChecked == 1){return SPELL_PREMONITION;}

    else if(nLastChecked == 2) {return SPELL_SHADOW_SHIELD;}
    else if(nLastChecked == 3) {return SPELL_GREATER_STONESKIN;}

    else if(nLastChecked == 4) {return SPELL_DEATH_WARD;}

    else if(nLastChecked == 5) {return SPELL_STONESKIN;}


    else if(nLastChecked == 6) {return SPELL_MAGE_ARMOR;}

    else if(nLastChecked == 7) {return SPELL_BARKSKIN;}
    else if(nLastChecked == 8) {return SPELL_MIND_BLANK;}

    else if(nLastChecked == 9) {return SPELL_PROTECTION_FROM_EVIL;}
    return nLastChecked;
}
//-------------------------------------------------------------------------
int CheckProtection(int nSpell_ID, object oTarget)
{
    //Declare major variables
    effect eProtection;


    if(GetHasSpellEffect(nSpell_ID, oTarget))
    {
        //Search through the valid effects on the target.
        eProtection = GetFirstEffect(oTarget);
        while (GetIsEffectValid(eProtection))
        {
            //If the effect was created by the spell then remove it
            if(GetEffectSpellId(eProtection) == nSpell_ID)
            {
                return (1);
            }
            //Get next effect on the target
            eProtection = GetNextEffect(oTarget);
        }
    }

    return 0;

}

int MonsterRest(object oMob=OBJECT_SELF)
{

int nHeal = GetMaxHitPoints(oMob);
int nHP=GetCurrentHitPoints(oMob);
if (nHP>(nHeal/2))
   {
    return FALSE;
   }


    int nCurrentHour = (GetCalendarYear()-1)*12*28*24 +
    (GetCalendarMonth()-1)*28*24 +
    (GetCalendarDay()-1)*24 +
    GetTimeHour();
    int nLastSpawnHour = GetLocalInt( oMob, "LastRestHour");
    int nSpawnDelay = 0;

if (nCurrentHour > (nLastSpawnHour + nSpawnDelay))
    {
    }
else
    {
    return FALSE;
    }

PlayVoiceChat(VOICE_CHAT_REST);

int nRace=GetRacialType(oMob);
if ((nRace==RACIAL_TYPE_DWARF)||(nRace==RACIAL_TYPE_ELF)||(nRace==RACIAL_TYPE_GIANT)||
(nRace==RACIAL_TYPE_GNOME)||(nRace==RACIAL_TYPE_HALFELF)||(nRace==RACIAL_TYPE_HALFLING)||
(nRace==RACIAL_TYPE_HALFORC)||(nRace==RACIAL_TYPE_HUMAN)||(nRace==RACIAL_TYPE_HUMANOID_GOBLINOID)||
(nRace==RACIAL_TYPE_HUMANOID_MONSTROUS)|| (nRace==RACIAL_TYPE_HUMANOID_ORC)||(nRace==RACIAL_TYPE_HUMANOID_REPTILIAN)||
(nRace==RACIAL_TYPE_SHAPECHANGER))
  {
   AssignCommand(oMob,ClearAllActions());
   AssignCommand(oMob,ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS));
   effect eSnore = EffectVisualEffect(VFX_IMP_SLEEP);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSnore, oMob, 7.0);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSnore, oMob, 7.0);
  }


      //Set the heal effect
       effect eHeal = EffectHeal(nHeal);
       //Apply the heal effect and the VFX impact
       ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oMob);

      // remove negative effects
      effect eBad = GetFirstEffect(oMob);
    //Search for negative effects
    while(GetIsEffectValid(eBad))
    {
        if (GetEffectType(eBad) == EFFECT_TYPE_ABILITY_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_AC_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_ATTACK_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_SAVING_THROW_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_SKILL_DECREASE ||
            GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS ||
            GetEffectType(eBad) == EFFECT_TYPE_DEAF ||
            GetEffectType(eBad) == EFFECT_TYPE_CURSE ||
            GetEffectType(eBad) == EFFECT_TYPE_DISEASE ||
            GetEffectType(eBad) == EFFECT_TYPE_POISON ||
            GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||
            GetEffectType(eBad) == EFFECT_TYPE_CHARMED ||
            GetEffectType(eBad) == EFFECT_TYPE_DOMINATED ||
            GetEffectType(eBad) == EFFECT_TYPE_DAZED ||
            GetEffectType(eBad) == EFFECT_TYPE_CONFUSED ||
            GetEffectType(eBad) == EFFECT_TYPE_FRIGHTENED ||
            GetEffectType(eBad) == EFFECT_TYPE_NEGATIVELEVEL ||
            GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||
            GetEffectType(eBad) == EFFECT_TYPE_SLOW ||
            GetEffectType(eBad) == EFFECT_TYPE_STUNNED)
        {
            //Remove effect if it is negative.
            RemoveEffect(oMob, eBad);
        }
        eBad = GetNextEffect(oMob);
    }


return 1;
}

int CheckHeal(object oMob=OBJECT_SELF)
{

if (GetRacialType(oMob)==RACIAL_TYPE_UNDEAD)
{
return FALSE;
}

if (d2()==1)
{
// 50 per cent chance of not making the call;
return FALSE;
}

if (GetLocalInt(OBJECT_SELF,"healcall"))
{
// if I have called for help once, just return;
return FALSE;
}

if(GetCurrentHitPoints(oMob)> (GetMaxHitPoints(oMob)/2))
{
// not half dead
return FALSE;
}

// check to see if I need healing and I am not myself a healer
if ((GetLevelByClass(CLASS_TYPE_CLERIC,OBJECT_SELF)>=1)||(GetLevelByClass(CLASS_TYPE_DRUID,OBJECT_SELF)>=1)||(GetLevelByClass(CLASS_TYPE_BARD,OBJECT_SELF)>=1))
{
return FALSE;
}


 if (GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,OBJECT_SELF,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN)))
 {
 // ok everything done, now call for help
PlayVoiceChat(VOICE_CHAT_HEALME);
SpeakString("I_AM_HEALING",TALKVOLUME_SILENT_TALK);
SetLocalInt(OBJECT_SELF,"healcall",1);
 }
return TRUE;

}

int CheckHasPositiveEffect(object oTarget)
{



    int nCnt;
    int nHasEffect=FALSE;


    while(nCnt <= 9)
    {
            nHasEffect=CheckProtection(CycleProtections(nCnt), oTarget);
            if (nHasEffect==TRUE)
            {
            return (nHasEffect);
            }
            nCnt++;
    }

return (FALSE);
}
//------------------------------------------------------------------------


void SetTarget(object oTarget, object oMob=OBJECT_SELF)
{
if (GetObjectType(oTarget)==OBJECT_TYPE_AREA_OF_EFFECT)
  {
   return;
  }
else
  {
   SetLocalObject(oMob,"mytarget",oTarget);
  }
}

object GetTarget(object oMob=OBJECT_SELF)
{
object oTarget=GetLocalObject(oMob,"mytarget");
return (oTarget);
}


int GetisCustomEncounterCreature(object oMob=OBJECT_SELF)
{
int nSpecial=GetLocalInt(oMob,"norw");

if (nSpecial==2)

{
return (1);
}

if (nSpecial==1)

{
return (0);
}

if (GetIsEncounterCreature(oMob))
{
return (1);
}
return (0);
}


void SetisCustomEncounterCreature(int nIsEncounter, object oMob=OBJECT_SELF)
{
 if (nIsEncounter)
 {
  SetLocalInt(oMob,"norw",2);
 }
 else
  {
  SetLocalInt(oMob,"norw",1);
 }
return;
}

void SetStartLocation(object oMob=OBJECT_SELF)

{
 location lLoc=GetLocation(oMob);
 SetLocalLocation(oMob,"startloc",lLoc);

}

location GetStartLocation(object oMob=OBJECT_SELF)

{
 location lLoc=GetLocalLocation(oMob,"startloc");
 return (lLoc);

}



void SetVictim(object oTarget, object oMob=OBJECT_SELF)
{
SetLocalObject(oMob,"myvictim",oTarget);
}

object GetVictim(object oMob=OBJECT_SELF)
{
object oTarget=GetLocalObject(oMob,"myvictim");
return (oTarget);
}


object ChooseTarget(object oMob=OBJECT_SELF)
{
object oTarget=GetVictim();
if (GetIsDeadOrBleeding(oTarget)&&(GetIsObjectValid(oTarget))&&(GetObjectSeen(oTarget))&&(d2()==1))
{
PlayVoiceChat(VOICE_CHAT_CHEER);
}

// if the Target is okay, it simply returns it
if ((GetIsObjectValid(oTarget))&&(!GetIsDeadOrBleeding(oTarget))&&(GetObjectSeen(oTarget)))
{
    if (d20()!=1)
    {
    return (oTarget);
    }
}

// we don't seem to have a target, so let's try to find someone we dislike and then go for it.
// we will get a patsy and then choose which one of his friends we most dislike

// start off by getting whoever we have been following
object oPatsy=GetTarget();
if ((GetIsObjectValid(oPatsy))&&(!GetIsDeadOrBleeding(oPatsy))&&(GetObjectSeen(oPatsy)))
{
// this is ok
}
else
{
// get the last hostile actor
oPatsy=GetLastHostileActor();
}

if ((GetIsObjectValid(oPatsy))&&(!GetIsDeadOrBleeding(oPatsy))&&(GetObjectSeen(oPatsy))&&(GetObjectType(oPatsy)!=OBJECT_TYPE_AREA_OF_EFFECT))
{
// this is ok
}
else
{
// just get the nearest hostile person
oPatsy=GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
}

// if we are very stupid or the players are lucky, just send this
if ((d100()<40)||(GetAbilityScore(OBJECT_SELF,ABILITY_INTELLIGENCE)<7))
{
 SetVictim (oPatsy);
 return (oPatsy);
}


int nDone=0;
object oPartyMember;

// ok we have our patsy, now to choose who to kill

//there are three ways of choosing
int nRandom=Random(3)+1;

if (nRandom==1)
{
oPartyMember=GetFirstFactionMember(oPatsy);
while ((GetIsObjectValid(oPartyMember))&&(nDone==0))
{
 if ((GetLevelByClass(CLASS_TYPE_WIZARD,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 else if ((GetLevelByClass(CLASS_TYPE_SORCERER,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 else if ((GetLevelByClass(CLASS_TYPE_CLERIC,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 if ((GetLevelByClass(CLASS_TYPE_BARD,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 if ((GetLevelByClass(CLASS_TYPE_DRUID,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }

oPartyMember=GetNextFactionMember(oPatsy);
}
}
// end of random 1

else if (nRandom==2)
{
oPartyMember=GetFirstFactionMember(oPatsy);
while ((GetIsObjectValid(oPartyMember))&&(nDone==0))
{
 if ((GetLevelByClass(CLASS_TYPE_CLERIC,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 else if ((GetLevelByClass(CLASS_TYPE_DRUID,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 else if ((GetLevelByClass(CLASS_TYPE_SORCERER,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 if ((GetLevelByClass(CLASS_TYPE_WIZARD,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 if ((GetLevelByClass(CLASS_TYPE_BARD,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }

oPartyMember=GetNextFactionMember(oPatsy);
}
}
// end of random 2

else if (nRandom==3)
{
oPartyMember=GetFirstFactionMember(oPatsy);
while ((GetIsObjectValid(oPartyMember))&&(nDone==0))
{
 if ((GetLevelByClass(CLASS_TYPE_BARD,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 else if ((GetLevelByClass(CLASS_TYPE_SORCERER,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 else if ((GetLevelByClass(CLASS_TYPE_WIZARD,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 if ((GetLevelByClass(CLASS_TYPE_CLERIC,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }
 if ((GetLevelByClass(CLASS_TYPE_DRUID,oPartyMember)>=1)&&(GetObjectSeen(oPartyMember)))
 {
  oTarget=oPartyMember;
  nDone=1;
 }

oPartyMember=GetNextFactionMember(oPatsy);
}
}
// end of random 3

if ((GetIsObjectValid(oTarget))&&(GetObjectSeen(oTarget)))
{
SetVictim (oTarget);
return (oTarget);
}
else
{
oTarget=GetFactionMostDamagedMember(oPatsy);
}

if ((GetIsObjectValid(oTarget))&&(GetObjectSeen(oTarget)))
{
SetVictim (oTarget);
return (oTarget);
}
else if ((GetIsObjectValid(oPatsy))&&(GetObjectSeen(oPatsy)))
{
SetVictim (oPatsy);
return (oPatsy);
}
else
{
return (OBJECT_INVALID);
}

}


object GetTargetFighting()
{
 object oPC;

 oPC=GetAttackTarget();
 if (!GetIsObjectValid(oPC))
 {
  oPC=GetAttemptedSpellTarget();
 }
 if (!GetIsObjectValid(oPC))
 {
  oPC=GetAttemptedAttackTarget();
 }


 return (oPC);

}

//::///////////////////////////////////////////////
//:: Get Character Levels
//:: Copyright (c) 2001 Bioware Corp.
//::///////////////////////////////////////////////
/*
    Returns the combined class levels of the
    target.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 22, 2001
//:://////////////////////////////////////////////

/* int GetCharacterLevel(object oTarget)
{
    return GetLevelByPosition(1, oTarget) + GetLevelByPosition(2, oTarget) + GetLevelByPosition(3, oTarget);
} */




//::///////////////////////////////////////////////
//:: Remove Ambient Sleep
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Checks if the NPC has sleep on them because
    of ambient animations. Sleeping creatures
    must make a DC 15 listen check.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Feb 27, 2002
//:://////////////////////////////////////////////

/* void RemoveAmbientSleep()
{
    if(PRCGetHasEffect(EFFECT_TYPE_SLEEP))
    {
        effect eSleep = GetFirstEffect(OBJECT_SELF);
        while(GetIsEffectValid(eSleep))
        {
            if(GetEffectCreator(eSleep) == OBJECT_SELF)
            {
                int nRoll = d20();
                nRoll += GetSkillRank(SKILL_LISTEN);
                nRoll += GetAbilityModifier(ABILITY_WISDOM);
                if(nRoll > 15)
                {
                    RemoveEffect(OBJECT_SELF, eSleep);
                }
            }
            eSleep = GetNextEffect(OBJECT_SELF);
        }
    }
}

 */

//::///////////////////////////////////////////////
//:: Get Locked Object
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Finds the closest locked object to the object
    passed in up to a maximum of 10 objects.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: March 15, 2002
//:://////////////////////////////////////////////

/* object GetLockedObject(object oMaster)
{
    int nCnt = 1;
    int bValid = TRUE;
    object oLastObject = GetNearestObjectToLocation(OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE, GetLocation(oMaster), nCnt);
    while (GetIsObjectValid(oLastObject) && bValid == TRUE)
    {
        //COMMENT THIS BACK IN WHEN DOOR ACTION WORKS ON PLACABLE.

        //object oItem = GetFirstItemInInventory(oLastObject);
        if(GetLocked(oLastObject))
        {
            return oLastObject;
        }
        nCnt++;
        if(nCnt == 10)
        {
            bValid = FALSE;
        }
        oLastObject = GetNearestObjectToLocation(OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE, GetLocation(oMaster), nCnt);
    }
    return OBJECT_INVALID;
}
 */
//::///////////////////////////////////////////////
//:: Get CR Max for Talents
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Determines the Spell CR to be used in the
    given situation
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Nov 18, 2001
//:://////////////////////////////////////////////

int GetAssociateCRMax()
{
    int nCR;
    /*
    if(GetAssociateState(NW_ASC_HAVE_MASTER))
    {
        object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
        oEnemy = GetFactionStrongestMember(oEnemy);
        int nHD = GetHitDice(oEnemy);
        if(GetAssociateState(NW_ASC_OVERKIll_CASTING))
        {
            nCR = 20;
        }
        else if(GetAssociateState(NW_ASC_POWER_CASTING))
        {
            nCR = nHD * 2;
            if (nCR > 20) {nCR = 20;}
            if (nCR < 5) {nCR = 5;}
        }
        else
        {
            nCR = nHD + 4;
            if (nCR > 20){nCR = 20;}
        }
        return nCR;
    }
    */
    return 20;
}

// --------------------------------------------------------------------------------
// GZ: Sept 2003
// Determines the optimal behavior against AoESpell nSpellId for a NPC
// use in OnSpellCastAt
// --------------------------------------------------------------------------------
int GetBestAOEBehavior(int nSpellID)
{
        if (nSpellID == SPELL_GREASE)
        {
           if (PRCIsFlying(OBJECT_SELF))
           return X2_SPELL_AOEBEHAVIOR_IGNORE;
        }

//        if (GetHasSpell(SPELL_GUST_OF_WIND) == TRUE)
        if (GetHasSpell(SPELL_GUST_OF_WIND))
            return X2_SPELL_AOEBEHAVIOR_GUST;

        if (GetModuleSwitchValue(MODULE_SWITCH_DISABLE_AI_DISPEL_AOE) == 0 )
        {
            if (d100() > GetLocalInt(GetModule(),MODULE_VAR_AI_NO_DISPEL_AOE_CHANCE))
            {
//                if (GetHasSpell(SPELL_LESSER_DISPEL) == TRUE)
                if (GetHasSpell(SPELL_LESSER_DISPEL))
                    return X2_SPELL_AOEBEHAVIOR_DISPEL_L;
//                if (GetHasSpell(SPELL_DISPEL_MAGIC) == TRUE)
                if (GetHasSpell(SPELL_DISPEL_MAGIC))
                    return X2_SPELL_AOEBEHAVIOR_DISPEL_N;
//                if (GetHasSpell(SPELL_GREATER_DISPELLING) == TRUE)
                if (GetHasSpell(SPELL_GREATER_DISPELLING))
                    return X2_SPELL_AOEBEHAVIOR_DISPEL_G;
//                if (GetHasSpell(SPELL_MORDENKAINENS_DISJUNCTION) == TRUE)
                if (GetHasSpell(SPELL_MORDENKAINENS_DISJUNCTION))
                    return X2_SPELL_AOEBEHAVIOR_DISPEL_M;
            }
        }

    return X2_SPELL_AOEBEHAVIOR_FLEE;
}



//::///////////////////////////////////////////////
//:: Check if an item is locked
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Checks that an item was unlocked.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Nov 19, 2001
//:://////////////////////////////////////////////

/* void CheckIsUnlocked(object oLastObject)
{
    if(GetLocked(oLastObject))
    {
        ActionDoCommand(PlayVoiceChat(VOICE_CHAT_CUSS));
    }
    else
    {
        ActionDoCommand(PlayVoiceChat(VOICE_CHAT_CANDO));
    }
}
 */