This class represents a creature within the game.
Inheritance: ACR_CreatureBehavior.GameObject
        public CreatureObject GetNearest(CreatureObject Source, List<CreatureObject> Creatures)
        {
            AreaObject SourceArea = Source.Area;
            Vector3 SourcePos = Source.Position;
            CreatureObject RetValue = null;
            if (Creatures.Count == 0) return RetValue;

            float ShortestDistance = -1.0f;
            foreach (CreatureObject Target in Creatures)
            {
                // Only interested in objects in the same area.
                if (SourceArea != Target.Area)
                    continue;

                Vector3 TargetPos = Target.Position;
                float Distance = MathOps.DistanceSq(SourcePos, TargetPos);

                if ((ShortestDistance < 0) || (Distance < ShortestDistance))
                {
                    ShortestDistance = Distance;
                    RetValue = Target;
                }
            }
            return RetValue;
        }
        public CreatureObject GetFarthest(CreatureObject Source, List<CreatureObject> Creatures)
        {
            AreaObject SourceArea = Source.Area;
            Vector3 SourcePos = Source.Position;
            CreatureObject RetValue = null;
            if (Creatures.Count == 0) return RetValue;

            float LongestDistance = -1.0f;
            foreach (CreatureObject Target in Creatures)
            {
                // Only interested in objects in the same area.
                if (SourceArea != Target.Area)
                    continue;

                Vector3 TargetPos = Target.Position;
                float Distance = MathOps.DistanceSq(SourcePos, TargetPos);

                if ((LongestDistance < 0) || ((Distance > LongestDistance) && (Distance < 100.0f * 100.0f))) // 100 meters is about as far as we'd expect combat to reach.
                {
                    LongestDistance = Distance;
                    RetValue = Target;
                }
            }
            return RetValue;
        }
        public void AddPartyEnemy(CreatureObject PartyEnemy)
        {
            if (PartyEnemy == null)
            {
                throw new ApplicationException("Trying to add party enemy, but that creature does not exist.");
            }
            Enemies.Add(PartyEnemy);

            if (CanPartySee(PartyEnemy))
            {
                int EnemyArmorRank = PartyEnemy.Script.GetArmorRank(PartyEnemy.Script.GetItemInSlot(CLRScriptBase.INVENTORY_SLOT_CARMOUR, PartyEnemy.ObjectId));
                if (EnemyArmorRank == CLRScriptBase.ARMOR_RANK_HEAVY ||
                    EnemyArmorRank == CLRScriptBase.ARMOR_RANK_MEDIUM)
                    EnemyHardTargets.Add(PartyEnemy);
                if (EnemyArmorRank == CLRScriptBase.ARMOR_RANK_LIGHT ||
                    EnemyArmorRank == CLRScriptBase.ARMOR_RANK_NONE)
                    EnemySoftTargets.Add(PartyEnemy);
                if (_LooksLikeSpellcaster(PartyEnemy))
                    EnemySpellcasters.Add(PartyEnemy);
            }
            else
            {
                EnemiesLost.Add(PartyEnemy);
            }
        }
 public void RemovePartyEnemy(CreatureObject PartyEnemy)
 {
     Enemies.Remove(PartyEnemy);
     EnemyHardTargets.Remove(PartyEnemy);
     EnemySoftTargets.Remove(PartyEnemy);
     EnemySpellcasters.Remove(PartyEnemy);
     EnemyHealers.Remove(PartyEnemy);
 }
        /// <summary>
        /// Promote a creature in the party to party leader.
        /// </summary>
        /// <param name="PartyLeader">Supplies the new party leader.</param>
        public void PromotePartyLeader(CreatureObject PartyLeader)
        {
            if (PartyLeader != null)
            {
                if (PartyLeader.Party != this)
                {
                    throw new ApplicationException(String.Format(
                        "Trying to promote creature {0} to party leader, but it is not in this party.",
                        PartyLeader));
                }
            }

            this.PartyLeader = PartyLeader;
        }
        /// <summary>
        /// Add a party member.
        /// </summary>
        /// <param name="Creature">Supplies the creature to add.</param>
        public void AddPartyMember(CreatureObject Creature)
        {
            if (Creature.Party != null)
            {
                throw new ApplicationException(String.Format(
                    "Adding creature {0} to party, but it is already joined to a party."));
            }

            PartyMembers.Add(Creature);
            Creature.Party = this;

            // No party leader defined. Guess it's this guy!
            if (PartyLeader == null)
            {
                PartyLeader = Creature;
            }

            // Existing party leader. Is this guy better at it?
            else
            {
                // If I'm the more charismatic leader, I take over.
                if (Creature.Script.GetAbilityScore(Creature.ObjectId, CLRScriptBase.ABILITY_CHARISMA, CLRScriptBase.TRUE) > PartyLeader.Script.GetAbilityScore(PartyLeader.ObjectId, CLRScriptBase.ABILITY_CHARISMA, CLRScriptBase.TRUE))
                        PartyLeader = Creature;

                // We're equally charismatic, but I'm more experienced. I take over.
                else if (Creature.Script.GetAbilityScore(Creature.ObjectId, CLRScriptBase.ABILITY_CHARISMA, CLRScriptBase.TRUE) == PartyLeader.Script.GetAbilityScore(PartyLeader.ObjectId, CLRScriptBase.ABILITY_CHARISMA, CLRScriptBase.TRUE) &&
                    Creature.Script.GetHitDice(Creature.ObjectId) > PartyLeader.Script.GetHitDice(PartyLeader.ObjectId))
                        PartyLeader = Creature;
            }

            // Now that leadership is established, what sort of guy is this?
            AIParty.AIType TacticsType = (AIParty.AIType)Creature.Script.GetLocalInt(Creature.ObjectId, "ACR_CREATURE_BEHAVIOR");
            if (TacticsType == AIType.BEHAVIOR_TYPE_UNDEFINED)
            {
                string Tactics = Creature.Script.GetLocalString(Creature.ObjectId, "ACR_CREATURE_BEHAVIOR");
                if (!Enum.TryParse<AIParty.AIType>(Tactics.ToUpper(), out TacticsType))
                    TacticsType = AIType.BEHAVIOR_TYPE_UNDEFINED;
            }
            if(TacticsType != AIType.BEHAVIOR_TYPE_UNDEFINED)
            {
                if(TacticsType == AIType.BEHAVIOR_TYPE_ANIMAL)
                {
                    this.PartyAnimals.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_ARCHER)
                {
                    this.PartyArchers.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_BUFFS)
                {
                    this.PartyBuffs.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_CONTROL)
                {
                    this.PartyControls.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_COWARD)
                {
                    this.PartyCowards.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_FLANK)
                {
                    this.PartyFlanks.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_MEDIC)
                {
                    this.PartyMedics.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_MINDLESS)
                {
                    this.PartyMindless.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_NUKE)
                {
                    this.PartyNukes.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_SHOCK)
                {
                    this.PartyShocks.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_SKIRMISH)
                {
                    this.PartySkrimishers.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else if(TacticsType == AIType.BEHAVIOR_TYPE_TANK)
                {
                    this.PartyTanks.Add(Creature);
                    Creature.TacticsType = TacticsType;
                }
                else
                {
                    TacticsType = AIType.BEHAVIOR_TYPE_UNDEFINED;
                    Creature.Script.SendMessageToAllDMs(String.Format("** ERROR ** : {0} has an AI type {1} defined, but that type is not understood by ACR_CreatureBehavior. This creature DOES NOT KNOW HOW TO FIGHT, and needs to be despawned.", Creature, TacticsType));
                    throw new ApplicationException(String.Format("Creature {0} has an AI type {1} defined, but that type is not understood by ACR_CreatureBehavior.", Creature, TacticsType));
                }
            }
            else if (TacticsType == AIType.BEHAVIOR_TYPE_UNDEFINED)
            {
//==================================================================================================================================================
//                                         Maybe this is an easy question. Is the creature stupid?
//==================================================================================================================================================
                // The creature is mindless; that's a simple thing.
                if (Creature.Script.GetAbilityScore(Creature.ObjectId, CLRScriptBase.ABILITY_INTELLIGENCE, CLRScriptBase.TRUE) == 0)
                {
                    Creature.TacticsType = AIType.BEHAVIOR_TYPE_MINDLESS;
                    this.PartyMindless.Add(Creature);
                }
                
                // The creature is too dumb to take more than simple orders.
                else if (Creature.Script.GetAbilityScore(Creature.ObjectId, CLRScriptBase.ABILITY_INTELLIGENCE, CLRScriptBase.TRUE) < 6)
                {
                    Creature.TacticsType = AIType.BEHAVIOR_TYPE_ANIMAL;
                    this.PartyAnimals.Add(Creature);
                }

//==================================================================================================================================================
//                        No such luck. We have to figure out how to make this creature act. Count and categorize classes.
//==================================================================================================================================================
                else
                {
                    int Heal = 0;
                    int Buff = 0;
                    int Blast = 0;
                    int Tank = 0;
                    int Crush = 0;
                    int Flank = 0;
                    int Skirm = 0;
                    int Arch = 0;
                    int Cont = 0;
                    for (int nClassPosition = 0; nClassPosition < 4; nClassPosition++)
                    {
                        int nClass = Creature.Script.GetClassByPosition(nClassPosition, Creature.ObjectId);
                        int nClassLevel = Creature.Script.GetLevelByClass(nClass, Creature.ObjectId);

                        // Members of these classes commonly have and prepare healing spells.
                        if (nClass == CLRScriptBase.CLASS_TYPE_CLERIC ||
                            nClass == CLRScriptBase.CLASS_TYPE_DRUID ||
                            nClass == CLRScriptBase.CLASS_TYPE_FAVORED_SOUL ||
                            nClass == CLRScriptBase.CLASS_TYPE_SPIRIT_SHAMAN)
                        {
                            Heal += nClassLevel;
                        }

                        // Members of these classes commonly have good support magic.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_BARD)
                        {
                            Buff += nClassLevel;
                        }

                        // Members of these classes are usually well-set to focus on aggressive magic.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_SORCERER ||
                                nClass == CLRScriptBase.CLASS_TYPE_WARLOCK)
                        {
                            Blast += nClassLevel;
                        }

                        // Members of these classes tend to have some combination of high AC, good saves, and/or damage reduction.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_FIGHTER ||
                                nClass == CLRScriptBase.CLASS_TYPE_PALADIN ||
                                nClass == 35 ||
                                nClass == CLRScriptBase.CLASS_TYPE_UNDEAD ||
                                nClass == CLRScriptBase.CLASS_TYPE_CONSTRUCT) // CLASS_TYPE_PLANT is undefined.
                        {
                            Tank += nClassLevel;
                        }

                        // Members of these classes tend to do a lot of damage in direct melee combat.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_BARBARIAN ||
                                nClass == CLRScriptBase.CLASS_TYPE_OOZE ||
                                nClass == CLRScriptBase.CLASS_TYPE_VERMIN ||
                                nClass == CLRScriptBase.CLASS_TYPE_OUTSIDER ||
                                nClass == CLRScriptBase.CLASS_TYPE_GIANT ||
                                nClass == CLRScriptBase.CLASS_TYPE_BEAST ||
                                nClass == CLRScriptBase.CLASS_TYPE_ELEMENTAL ||
                                nClass == CLRScriptBase.CLASS_TYPE_MONSTROUS ||
                                nClass == CLRScriptBase.CLASS_TYPE_HUMANOID)
                        {
                            Crush += nClassLevel;
                        }
                        
                        // Members of these classes are typically the most-threatening if they can stab an opponent in the back.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_ROGUE ||
                                nClass == CLRScriptBase.CLASS_TYPE_SWASHBUCKLER)
                        {
                            Flank += nClassLevel;
                        }

                        // Members of these classes are typically highly-mobile.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_MONK ||
                                nClass == CLRScriptBase.CLASS_TYPE_RANGER ||
                                nClass == CLRScriptBase.CLASS_TYPE_SHAPECHANGER ||
                                nClass == CLRScriptBase.CLASS_TYPE_MAGICAL_BEAST ||
                                nClass == CLRScriptBase.CLASS_TYPE_ANIMAL)
                        {
                            Skirm += nClassLevel;
                        }

                        // Members of these classes are typically best at attacking from a distance.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_RANGER)
                        {
                            Arch += nClassLevel;
                        }

                        // Members of these classes typically have or prepare spells which control the battlefield.
                        else if (nClass == CLRScriptBase.CLASS_TYPE_WIZARD ||
                                nClass == CLRScriptBase.CLASS_TYPE_FEY ||
                                nClass == CLRScriptBase.CLASS_TYPE_ABERRATION)
                        {
                            Cont += nClassLevel;
                        }
                    }

//==================================================================================================================================================
//                                    Now that we know classes by their generic type, we compare the varieties.
//==================================================================================================================================================
                    // Spellcasting conters are higher than the others; this person is mostly a spellcaster.
                    if (Heal + Buff + Blast + Cont > Tank + Crush &&
                        Heal + Buff + Blast + Cont > Flank + Skirm + Arch)
                    {
                        // Spellcaster is better at controlling the field than others.
                        if (Cont > Buff &&
                            Cont > Blast &&
                            Cont > Heal)
                        {
                            this.PartyControls.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_CONTROL;
                        }

                        // Spellcaster is better at support magic than others.
                        else if (Buff > Blast &&
                                Buff > Heal)
                        {
                            this.PartyBuffs.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_BUFFS;
                        }

                        // Spellcaster is better at destroying things than not.
                        else if (Blast > Heal)
                        {
                            this.PartyNukes.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_NUKE;
                        }

                        // Spellcaster is either a healer or we don't know. We'll set them to taking care of pals.
                        else
                        {
                            this.PartyMedics.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_MEDIC;
                        }
                    }

                    // Looks like a melee fighter.
                    else if (Tank + Crush > Flank + Skirm + Arch)
                    {
                        if (Tank > Crush)
                        {
                            this.PartyTanks.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_TANK;
                        }
                        else
                        {
                            this.PartyShocks.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_SHOCK;
                        }
                    }

                    // Looks like a skilled character.
                    else if (Flank + Skirm + Arch > 0)
                    {
                        if (Flank > Skirm &&
                            Flank > Arch)
                        {
                            this.PartyFlanks.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_FLANK;
                        }
                        else if (Arch > Skirm)
                        {
                            this.PartyArchers.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_ARCHER;
                        }
                        else
                        {
                            this.PartySkrimishers.Add(Creature);
                            Creature.TacticsType = AIType.BEHAVIOR_TYPE_SKIRMISH;
                        }
                    }

                    // None of them have any value. This guy is probably useless, except that he can run for help.
                    else
                    {
                        this.PartyCowards.Add(Creature);
                        Creature.TacticsType = AIType.BEHAVIOR_TYPE_COWARD;
                    }
                }
            }
        }
 /// <summary>
 /// This serves as a wrapper about calls to ActionAttack, to apply things like the uncanny
 /// dodge modifiers
 /// </summary>
 /// <returns>true if the attack is successfully staged</returns>
 public bool _AttackWrapper(CreatureObject AttackTarget)
 {
     if (Script.GetIsObjectValid(AttackTarget.ObjectId) == CLRScriptBase.TRUE)
     {
         if (Script.GetHasFeat(2179, ObjectId, CLRScriptBase.TRUE) == CLRScriptBase.TRUE) // Shadow touch attack
         {
             Script.ActionUseTalentOnObject(Script.TalentFeat(2179), AttackTarget.ObjectId);
             return true;
         }
         else
         {
             if (Script.GetCurrentAction(ObjectId) == CLRScriptBase.ACTION_ATTACKOBJECT &&
                Script.GetAttackTarget(ObjectId) == AttackTarget.ObjectId)
             {
                 return true;
             }
             else
             {
                 Script.ClearAllActions(CLRScriptBase.FALSE);
                 Script.ActionAttack(AttackTarget.ObjectId, CLRScriptBase.FALSE);
                 return true;
             }
         }
     }
     return false;
 }
        public Int32 ScriptMain([In] object[] ScriptParameters, [In] Int32 DefaultReturnCode)
        {
            Int32 ReturnCode = 0;
            switch ((EVENT_TYPE)ScriptParameters[0])
            {
                case EVENT_TYPE.CREATURE_ON_SPAWN:
                    {
                        CreatureObject Creature = new CreatureObject(OBJECT_SELF, Server.ObjectManager);

                        Creature.OnSpawn();
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_SPELL_CAST_AT:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnSpellCastAt(GetLastSpellCaster(), GetLastSpell());
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_PHYSICALLY_ATTACKED:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnAttacked(GetLastAttacker(OBJECT_SELF));
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_DAMAGED:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnDamaged(GetLastDamager(OBJECT_SELF), GetTotalDamageDealt());
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_DEATH:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnDeath(GetLastKiller());
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_BLOCKED:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnBlocked(GetBlockingDoor());
                    }
                    break;

                case EVENT_TYPE.CREATURE_END_COMBAT_ROUND:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnEndCombatRound();
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_CONVERSATION:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnConversation();
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_INVENTORY_DISTURBED:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnInventoryDisturbed();
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_HEARTBEAT:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnHeartbeat();
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_RESTED:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnRested();
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_PERCEPTION:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                        {
                            Creature.OnPerception(GetLastPerceived(),
                                GetLastPerceptionHeard() != CLRScriptBase.FALSE ? true : false,
                                GetLastPerceptionInaudible() != CLRScriptBase.FALSE ? true : false,
                                GetLastPerceptionSeen() != CLRScriptBase.FALSE ? true : false,
                                GetLastPerceptionVanished() != CLRScriptBase.FALSE ? true : false);
                        }
                    }
                    break;

                case EVENT_TYPE.CREATURE_ON_USER_DEFINED:
                    {
                        CreatureObject Creature = Server.ObjectManager.GetCreatureObject(OBJECT_SELF);

                        if (Creature != null)
                            Creature.OnUserDefined(GetUserDefinedEventNumber());
                    }
                    break;

                case EVENT_TYPE.MODULE_ON_STARTED:
                    {
                        //
                        // Initialize the server subsystem.
                        //

                        Server.Initialize();

                        foreach (AreaObject Area in Server.ObjectManager.GetAreas())
                        {
                            foreach (uint ObjectInAreaId in Area.GetObjectIdsInArea())
                            {
                                if (GetObjectType(ObjectInAreaId) == CLRScriptBase.OBJECT_TYPE_TRIGGER)
                                {
                                    if (GetTransitionTarget(ObjectInAreaId) != OBJECT_INVALID)
                                    {
                                        AreaObject.AreaTransition Transition = new AreaObject.AreaTransition();
                                        Transition.ObjectId = ObjectInAreaId;
                                        Transition.TargetArea = Server.ObjectManager.GetAreaObject(GetArea(GetTransitionTarget(ObjectInAreaId)));
                                        Area.AreaTransitions.Add(Transition);
                                    }
                                }
                            }
                        }
                    }
                    break;

                case EVENT_TYPE.AREA_ON_INSTANCE_CREATE:
                    {
                        if (Server.ObjectManager == null)
                            break;

                        ModuleObject Module = Server.ObjectManager.Module;

                        if (Module == null)
                            break;

                        Module.AddInstancedArea(OBJECT_SELF);
                    }
                    break;
            }

            if (Server.ObjectManager != null)
                Server.ObjectManager.ProcessPendingDeletions();

            return ReturnCode;
        }
 /// <summary>
 /// This will look for status afflictions that need healing.
 /// </summary>
 /// <param name="HealTarget">The target to be healed</param>
 /// <returns>True if an appropriate action is found and assigned</returns>
 public bool TryRemoveStatusAfflictions(CreatureObject HealTarget)
 {
     if (HealTarget.Confused || HealTarget.Insane || HealTarget.Frightened || HealTarget.Paralyzed || HealTarget.AbilityDamaged || HealTarget.Diseased ||
         HealTarget.Blinded || HealTarget.Deaf || HealTarget.Poisoned)
     {
         if (Script.GetHasSpell(CLRScriptBase.SPELL_HEAL, ObjectId) == CLRScriptBase.TRUE)
         {
             Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_HEAL), HealTarget.ObjectId);
             return true;
         }
         else
         {
             if (HealTarget.AbilityDamaged)
             {
                 if (Script.GetHasSpell(CLRScriptBase.SPELL_LESSER_RESTORATION, ObjectId) == CLRScriptBase.TRUE &&
                     Script.GetHasSpell(CLRScriptBase.SPELL_RESTORATION, ObjectId) == CLRScriptBase.FALSE &&
                     Script.GetHasSpell(CLRScriptBase.SPELL_GREATER_RESTORATION, ObjectId) == CLRScriptBase.FALSE)
                 {
                     Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_LESSER_RESTORATION), HealTarget.ObjectId);
                     return true;
                 }
             }
             if (HealTarget.Diseased)
             {
                 if (Script.GetHasSpell(CLRScriptBase.SPELL_LESSER_RESTORATION, ObjectId) == CLRScriptBase.TRUE)
                 {
                     Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_REMOVE_DISEASE), HealTarget.ObjectId);
                     return true;
                 }
             }
             if (HealTarget.Blinded || HealTarget.Deaf)
             {
                 if (Script.GetHasSpell(CLRScriptBase.SPELL_REMOVE_BLINDNESS_AND_DEAFNESS, ObjectId) == CLRScriptBase.TRUE)
                 {
                     Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_REMOVE_BLINDNESS_AND_DEAFNESS), HealTarget.ObjectId);
                     return true;
                 }
             }
             if (HealTarget.Poisoned)
             {
                 if (Script.GetHasSpell(CLRScriptBase.SPELL_NEUTRALIZE_POISON, ObjectId) == CLRScriptBase.TRUE)
                 {
                     Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_NEUTRALIZE_POISON), HealTarget.ObjectId);
                     return true;
                 }
             }
         }
     }
     if (HealTarget.Petrified)
     {
         if (Script.GetHasSpell(CLRScriptBase.SPELL_STONE_TO_FLESH, ObjectId) == CLRScriptBase.TRUE)
         {
             Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_STONE_TO_FLESH), HealTarget.ObjectId);
             return true;
         }
     }
     if ((HealTarget.AbilityDrained || HealTarget.LevelDrain) ||
         (HealTarget.AbilityDamaged && Script.GetHasSpell(CLRScriptBase.SPELL_LESSER_RESTORATION, ObjectId) == CLRScriptBase.FALSE))
     {
         if (Script.GetHasSpell(CLRScriptBase.SPELL_RESTORATION, ObjectId) == CLRScriptBase.TRUE)
         {
             Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_RESTORATION), HealTarget.ObjectId);
             return true;
         }
         else if (Script.GetHasSpell(CLRScriptBase.SPELL_GREATER_RESTORATION, ObjectId) == CLRScriptBase.FALSE)
         {
             Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_GREATER_RESTORATION), HealTarget.ObjectId);
             return true;
         }
     }
     if (HealTarget.Cursed)
     {
         if (Script.GetHasSpell(CLRScriptBase.SPELL_REMOVE_CURSE, ObjectId) == CLRScriptBase.FALSE)
         {
             Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_REMOVE_CURSE), HealTarget.ObjectId);
             return true;
         }
     }
     if (HealTarget.Wounded)
     {
         int nMissingHitPoints = HealTarget.MaxHitPoints - HealTarget.CurrentHitPoints;
         if (nMissingHitPoints == 0) nMissingHitPoints = 1;
         if (TryToHeal(HealTarget, nMissingHitPoints))
             return true;
     }
     return false;
 }
        /// <summary>
        /// This will search for an ability that will directly restore about HitPoints of hit points and use it on HealTarget
        /// </summary>
        /// <param name="HealTarget">The one to receive healing.</param>
        /// <param name="HitPoints">The amount to heal.</param>
        /// <returns>True if an ability is found.</returns>
        public bool TryToHeal(CreatureObject HealTarget, int HitPoints)
        {
            int SpellId = -1;
            NWTalent Healing = null;
            if (HitPoints > 50 && Script.GetHasSpell(CLRScriptBase.SPELL_HEAL, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_HEAL;
            else if(HitPoints > 50 && Script.GetHasSpell(CLRScriptBase.SPELL_MASS_HEAL, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_MASS_HEAL;
            else if (HitPoints > 21 && Script.GetHasSpell(CLRScriptBase.SPELL_CURE_CRITICAL_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_CURE_CRITICAL_WOUNDS;
            else if (HitPoints > 21 && Script.GetHasSpell(CLRScriptBase.SPELL_MASS_CURE_CRITICAL_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_MASS_CURE_CRITICAL_WOUNDS;
            else if (HitPoints > 16 && Script.GetHasSpell(CLRScriptBase.SPELL_CURE_SERIOUS_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_CURE_SERIOUS_WOUNDS;
            else if (HitPoints > 16 && Script.GetHasSpell(CLRScriptBase.SPELL_MASS_CURE_SERIOUS_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_MASS_CURE_SERIOUS_WOUNDS;
            else if (HitPoints > 10 && Script.GetHasSpell(CLRScriptBase.SPELL_CURE_MODERATE_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_CURE_MODERATE_WOUNDS;
            else if (HitPoints > 10 && Script.GetHasSpell(CLRScriptBase.SPELL_MASS_CURE_MODERATE_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_MASS_CURE_MODERATE_WOUNDS;
            else if (Script.GetHasSpell(CLRScriptBase.SPELL_CURE_LIGHT_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_CURE_LIGHT_WOUNDS;
            else if (Script.GetHasSpell(CLRScriptBase.SPELL_MASS_CURE_LIGHT_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_MASS_CURE_LIGHT_WOUNDS;
            else if (Script.GetHasSpell(CLRScriptBase.SPELL_CURE_MODERATE_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_CURE_MODERATE_WOUNDS;
            else if (Script.GetHasSpell(CLRScriptBase.SPELL_CURE_SERIOUS_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_CURE_SERIOUS_WOUNDS;
            else if (Script.GetHasSpell(CLRScriptBase.SPELL_CURE_CRITICAL_WOUNDS, ObjectId) == CLRScriptBase.TRUE) SpellId = CLRScriptBase.SPELL_CURE_CRITICAL_WOUNDS;

            if (SpellId != -1)
            {
                Healing = Script.TalentSpell(SpellId);
                Script.ActionUseTalentOnObject(Healing, HealTarget.ObjectId);
                return true;
            }
            else
            {
                if (HealTarget == this)
                {
                    Healing = Script.GetCreatureTalentBest(CLRScriptBase.TALENT_CATEGORY_BENEFICIAL_HEALING_POTION, 20, ObjectId, 0);
                    if (Script.GetIsTalentValid(Healing) == CLRScriptBase.TRUE)
                    {
                        Script.ActionUseTalentOnObject(Healing, HealTarget.ObjectId);
                        return true;
                    }
                }
            }
            return false;
        }
 /// <summary>
 /// This will look for the most-urgent disabling status afflictions on HealTarget and attempt to cure them.
 /// </summary>
 /// <param name="HealTarget">The target to be healed</param>
 /// <returns>true if an appropriate action is assigned.</returns>
 public bool TryRemoveUrgentStatusAfflictions(CreatureObject HealTarget)
 {
     if (HealTarget.Confused || HealTarget.Insane || HealTarget.Frightened || HealTarget.Paralyzed || HealTarget.Blinded)
     {
         if (Script.GetHasSpell(CLRScriptBase.SPELL_HEAL, ObjectId) == CLRScriptBase.TRUE)
         {
             Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_HEAL), HealTarget.ObjectId);
             return true;
         }
         if (HealTarget.Blinded || HealTarget.Deaf)
         {
             if (Script.GetHasSpell(CLRScriptBase.SPELL_REMOVE_BLINDNESS_AND_DEAFNESS, ObjectId) == CLRScriptBase.TRUE)
             {
                 Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_REMOVE_BLINDNESS_AND_DEAFNESS), HealTarget.ObjectId);
                 return true;
             }
         }
     }
     if (HealTarget.Petrified)
     {
         if (Script.GetHasSpell(CLRScriptBase.SPELL_STONE_TO_FLESH, ObjectId) == CLRScriptBase.TRUE)
         {
             Script.ActionUseTalentOnObject(Script.TalentSpell(CLRScriptBase.SPELL_STONE_TO_FLESH), HealTarget.ObjectId);
             return true;
         }
     }
     if (HealTarget.Wounded)
     {
         int nMissingHitPoints = HealTarget.MaxHitPoints - HealTarget.CurrentHitPoints;
         if (nMissingHitPoints == 0) nMissingHitPoints = 1;
         if (TryToHeal(HealTarget, nMissingHitPoints))
             return true;
     }
     return false;
 }
 public bool CanPartyHear(CreatureObject Creature)
 {
     if (Creature == null) return false;
     if (Creature.ObjectId == null || Creature.ObjectId == 0) return false;
     if (PartyMembers == null) return false; // If there's no one in the party, well, obviously.
     foreach (CreatureObject PartyMember in PartyMembers)
     {
         if (PartyMember != null &&
             PartyMember.Script.GetObjectHeard(PartyMember.ObjectId, Creature.ObjectId) == CLRScriptBase.TRUE)
             return true;
     }
     return false;
 }
        public void RemovePartyEnemy(CreatureObject PartyEnemy)
        {
            if(Enemies.Contains(PartyEnemy))
                Enemies.Remove(PartyEnemy);

            if(EnemyHardTargets.Contains(PartyEnemy))
                EnemyHardTargets.Remove(PartyEnemy);

            if(EnemySoftTargets.Contains(PartyEnemy))
                EnemySoftTargets.Remove(PartyEnemy);

            if(EnemySpellcasters.Contains(PartyEnemy))
                EnemySpellcasters.Remove(PartyEnemy);

            if(EnemyHealers.Contains(PartyEnemy))
                EnemyHealers.Remove(PartyEnemy);
        }
 public bool CanPartyHear(CreatureObject Creature)
 {
     foreach (CreatureObject PartyMember in PartyMembers)
     {
         if (PartyMember.Script.GetObjectHeard(PartyMember.ObjectId, Creature.ObjectId) == CLRScriptBase.TRUE)
             return true;
     }
     return false;
 }
        /// <summary>
        /// Remove a party member.  If the party member was the last in the
        /// party, then the party is dissolved.
        /// </summary>
        /// <param name="Creature">Supplies the creature to remove.</param>
        public void RemovePartyMember(CreatureObject Creature)
        {
            if (Creature.Party != this)
            {
                throw new ApplicationException(String.Format(
                    "Removing creature {0} from party, but it is not in this party."));
            }

            PartyMembers.Remove(Creature);
            Creature.Party = null;

            if (PartyLeader == Creature)
                PartyLeader = null;

            if (PartyMembers.Count == 0)
                PartyManager.RemoveParty(this);

            switch ((AIType)Creature.TacticsType)
            {
                case AIType.BEHAVIOR_TYPE_ANIMAL:
                    PartyAnimals.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_ARCHER:
                    PartyArchers.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_BUFFS:
                    PartyBuffs.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_CONTROL:
                    PartyControls.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_COWARD:
                    PartyCowards.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_FLANK:
                    PartyFlanks.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_MEDIC:
                    PartyMedics.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_MINDLESS:
                    PartyMindless.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_NUKE:
                    PartyNukes.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_SHOCK:
                    PartyShocks.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_SKIRMISH:
                    PartySkrimishers.Remove(Creature);
                    break;
                case AIType.BEHAVIOR_TYPE_TANK:
                    PartyTanks.Remove(Creature);
                    break;
                default:
                    break;
            }

            if (PartyMembers.Count > 0 && PartyLeader == null)
            {
                int nCha = 0;
                foreach (CreatureObject Member in PartyMembers)
                {
                    if (Member.Script.GetAbilityModifier(CLRScriptBase.ABILITY_CHARISMA, Member.ObjectId) > nCha)
                    {
                        nCha = Member.Script.GetAbilityModifier(CLRScriptBase.ABILITY_CHARISMA, Member.ObjectId);
                        PartyLeader = Member;
                    }
                }
            }
        }
 /// <summary>
 /// This function seeks signs of a spellcaster, looking for visible paraphenalia. Visibility is assumed, and should be checked separately.
 /// </summary>
 /// <param name="Creature">The creature to be assessed</param>
 /// <returns>True if there is some visible paraphenalia that suggests spellcasting.</returns>
 private bool _LooksLikeSpellcaster(CreatureObject Creature)
 {
     int VisibleSpellbooks = 0;
     foreach (uint Item in Creature.Script.GetItemsInInventory(Creature.ObjectId))
     {
         if (Creature.Script.GetTag(Item) == "ACR_MOD_SPELLBOOK" ||
             Creature.Script.GetTag(Item) == "ACR_MOD_HOLYSYMBOL")
             VisibleSpellbooks++;
         if (Creature.Script.GetHasInventory(Item) == CLRScriptBase.TRUE)
         {
             foreach (uint ContainerContents in Creature.Script.GetItemsInInventory(Item))
             {
                 if (Creature.Script.GetTag(ContainerContents) == "ACR_MOD_SPELLBOOK" ||
                     Creature.Script.GetTag(ContainerContents) == "ACR_MOD_HOLYSYMBOL")
                     VisibleSpellbooks--;
             }
         }
     }
     if (VisibleSpellbooks > 0)
         return true;
     return false;
 }
 /// <summary>
 /// This serves as a wrapper about calls to ActionAttack, to apply things like the uncanny
 /// dodge modifiers
 /// </summary>
 /// <returns>true if the attack is successfully staged</returns>
 public bool _AttackWrapper(CreatureObject AttackTarget)
 {
     Script.ActionAttack(AttackTarget.ObjectId, CLRScriptBase.FALSE);
     return false;
 }