Abdula_2314124

Untitled

Jun 26th, 2024
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 128.81 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using UnityEngine.UI;
  4. using UnityEngine.AI;
  5. using System.Collections;
  6. using UnityEngine.Events;
  7. using EmeraldAI.Utility;
  8.  
  9. namespace EmeraldAI
  10. {
  11.     [RequireComponent(typeof(BoxCollider))]
  12.     [RequireComponent(typeof(NavMeshAgent))]
  13.     [RequireComponent(typeof(AudioSource))]  
  14.     [RequireComponent(typeof(EmeraldAIDetection))]
  15.     [RequireComponent(typeof(EmeraldAIInitializer))]
  16.     [RequireComponent(typeof(EmeraldAIBehaviors))]
  17.     [RequireComponent(typeof(EmeraldAIEventsManager))]
  18.     [RequireComponent(typeof(EmeraldAILookAtController))]
  19.     [SelectionBase]
  20.  
  21.     public class EmeraldAISystem : MonoBehaviour
  22.     {
  23.         #region Variables
  24.         public float ForceWalkDistance = 2.5f;
  25.         public bool LockTurning;
  26.         public float MovementTurningSensitivity = 2f;
  27.         //3.0 Variables
  28.         public bool NotifiedOfNewVersion = false;
  29.         protected float TimeSinceStart;
  30.         public bool ReachedDestination;
  31.         float DelayTimer;
  32.         Coroutine SwitchWeaponCoroutine;
  33.         public enum SwitchWeaponTypes { Distance, Timed};
  34.         public SwitchWeaponTypes SwitchWeaponType = SwitchWeaponTypes.Timed;
  35.         public int SwitchWeaponTimeMin = 10;
  36.         public int SwitchWeaponTimeMax = 20;
  37.         public float SwitchWeaponTime = 0;
  38.         public float SwitchWeaponTimer = 0;        
  39.         public EmeraldAIHandIK EmeraldHandIKComp;
  40.         public GameObject HeldMeleeWeaponObject;
  41.         public GameObject HeldRangedWeaponObject;
  42.         public GameObject HolsteredMeleeWeaponObject;      
  43.         public GameObject HolsteredRangedWeaponObject;
  44.         public bool TurnDirectionMet;
  45.         public float TurnSpeedTimer;
  46.         public EmeraldAIPlayerDamage PlayerDamageComponent;
  47.         public static List<Transform> IgnoredTargetsList = new List<Transform>();
  48.         public EmeraldAINonAIDamage NonAIDamageComponent;
  49.         public Vector3 LBDImpactPosition;
  50.         public LocationBasedDamage LocationBasedDamageComp;
  51.         public TargetPositionModifier CurrentTargetPositionModifierComp;
  52.         public float CurrentPositionModifier = 0;
  53.  
  54.         //Melee Attacks
  55.         public int MeleeAttackIndex = 0;
  56.         public enum MeleeAttackPickTypeEnum { Odds, Order, Random };
  57.         public MeleeAttackPickTypeEnum MeleeAttackPickType = MeleeAttackPickTypeEnum.Order;
  58.         public List<MeleeAttackClass> MeleeAttacks = new List<MeleeAttackClass>();
  59.         public int MeleeAttacksListIndex = 0;
  60.  
  61.         //Melee Run Attacks
  62.         public int MeleeRunAttackIndex = 0;
  63.         public enum MeleeRunAttackPickTypeEnum { Odds, Order, Random };
  64.         public MeleeRunAttackPickTypeEnum MeleeRunAttackPickType = MeleeRunAttackPickTypeEnum.Order;
  65.         public List<MeleeAttackClass> MeleeRunAttacks = new List<MeleeAttackClass>();
  66.         public int MeleeRunAttacksListIndex = 0;
  67.  
  68.         [System.Serializable]
  69.         public class MeleeAttackClass
  70.         {
  71.             public int AttackAnimaition;
  72.             public int MinDamage = 5;
  73.             public int MaxDamage = 5;
  74.             public int AttackOdds = 25;
  75.             public GameObject AttackImpactEffect;
  76.         }
  77.  
  78.         //Offensive Abilities
  79.         public int OffensiveAbilityIndex = 0;
  80.         public enum OffensiveAbilityPickTypeEnum { Odds, Order, Random };
  81.         public OffensiveAbilityPickTypeEnum OffensiveAbilityPickType = OffensiveAbilityPickTypeEnum.Order;
  82.         public List<OffensiveAbilitiesClass> OffensiveAbilities = new List<OffensiveAbilitiesClass>();
  83.  
  84.         [System.Serializable]
  85.         public class OffensiveAbilitiesClass
  86.         {
  87.             public EmeraldAIAbility OffensiveAbility;
  88.             public int AbilityAnimaition;
  89.             public int AbilityOdds = 25;
  90.         }
  91.  
  92.         //Support Abilities
  93.         public int SupportAbilityIndex = 0;
  94.         public enum SupportAbilityPickTypeEnum { Odds, Order, Random };
  95.         public SupportAbilityPickTypeEnum SupportAbilityPickType = SupportAbilityPickTypeEnum.Order;
  96.         public List<SupportAbilitiesClass> SupportAbilities = new List<SupportAbilitiesClass>();
  97.  
  98.         [System.Serializable]
  99.         public class SupportAbilitiesClass
  100.         {
  101.             public EmeraldAIAbility SupportAbility;
  102.             public int AbilityAnimaition;
  103.             public int AbilityOdds = 25;
  104.         }
  105.  
  106.         //Summoning Abilities
  107.         public int SummoningAbilityIndex = 0;
  108.         public enum SummoningAbilityPickTypeEnum { Odds, Order, Random };
  109.         public SummoningAbilityPickTypeEnum SummoningAbilityPickType = SummoningAbilityPickTypeEnum.Order;
  110.         public List<SummoningAbilitiesClass> SummoningAbilities = new List<SummoningAbilitiesClass>();
  111.  
  112.         [System.Serializable]
  113.         public class SummoningAbilitiesClass
  114.         {
  115.             public EmeraldAIAbility SummoningAbility;
  116.             public int AbilityAnimaition;
  117.             public int AbilityOdds = 25;
  118.         }
  119.  
  120.  
  121.         public AnimatorStateInfo CurrentStateInfo;
  122.         protected float AggroDelay;
  123.         public bool CriticalHit = false;
  124.         public bool TargetInAngleLimit = false;
  125.         public int CurrentAnimationIndex = 0;
  126.         public int CurrentRunAttackAnimationIndex = 0;
  127.         public List<string> ActiveEffects = new List<string>();
  128.         public EmeraldAIProjectile CurrentlyCreatedAbility;        
  129.         public int MaxAllowedSummonedAI = 1;
  130.         public int TotalSummonedAI = 0;
  131.         public EmeraldAISystem CurrentSummoner;
  132.         public Coroutine HealingOverTimeCoroutine;
  133.         public int HealthPercentageToHeal = 30;
  134.         public bool HealingCooldownActive;
  135.         public int HealingCooldownSeconds = 8;
  136.         float HealingCooldownTimer;
  137.         public bool m_AbilityPicked = false;
  138.         public Vector3 m_InitialTargetPosition;
  139.         public bool TargetDetectionActive;
  140.         public bool IdleActivated;
  141.         public float DetectionFrequency = 1;
  142.         public int PlayerDetectionEventCooldown = 5;
  143.         public float RangedAttackOffset = 0;
  144.         public Transform HitPointTransform;
  145.         public int SwitchWeaponTypesCooldown = 10;
  146.         public int SwitchWeaponTypesDistance = 8;
  147.         public string CameraTag = "MainCamera";
  148.         public EmeraldAIHealthBar m_HealthBarComponent;
  149.        
  150.         public float AttackHeight = 5;
  151.         public EmeraldAIAbility m_EmeraldAIAbility;
  152.         public bool RotateTowardsTarget = false;
  153.         public bool m_AttackAnimationClipMissing = false;
  154.         public float ProjectileCollisionPointY = 1.5f;
  155.         public Vector3 m_ProjectileCollisionPoint;
  156.         public float ObstructionTimer;
  157.         public int ObstructionSeconds = 4;
  158.         float m_ObstructedTimer;
  159.  
  160.         //Volumes
  161.         public float IdleVolume = 1;
  162.         public float WalkFootstepVolume = 0.1f;
  163.         public float RunFootstepVolume = 0.1f;
  164.         public float BlockVolume = 0.65f;
  165.         public float ImpactVolume = 1;
  166.         public float CriticalHitVolume = 1;
  167.         public float InjuredVolume = 1;
  168.         public float AttackVolume = 1;
  169.         public float WarningVolume = 1;
  170.         public float DeathVolume = 0.7f;
  171.         public float EquipVolume = 1;
  172.         public float UnequipVolume = 1;
  173.         public float RangedEquipVolume = 1;
  174.         public float RangedUnequipVolume = 1;
  175.  
  176.         //Head Look
  177.         public float HeadLookWeightCombat = 0.75f;
  178.         public float BodyLookWeightCombat = 0.75f;
  179.         public float HeadLookWeightNonCombat = 0.85f;
  180.         public float BodyLookWeightNonCombat = 0.1f;
  181.         public int MaxLookAtDistance = 15;
  182.         public float NonCombatLookSpeedMultiplier = 1f;
  183.         public float CombatLookSpeedMultiplier = 1f;
  184.         public int NonCombatLookAtLimit = 75;
  185.         public int CombatLookAtLimit = 45;
  186.         public float lookWeight;
  187.         public int LookAtLimit;
  188.         public AnimatorStateInfo m_LayerCurrentState;
  189.         public Transform HeadTransform;
  190.         public Vector3 StartingLookAtPosition;
  191.         public List<HumanBodyBones> BoneObjects = new List<HumanBodyBones>();
  192.  
  193.         public int CurrentAggroHits = 0;
  194.         public int TotalAggroHits = 5;
  195.         public enum AggroAction {LastAttacker = 0, RandomAttacker, ClosestAttacker};
  196.         public AggroAction AggroActionRef = AggroAction.LastAttacker;
  197.         public bool ReturnToStationaryPosition;
  198.  
  199.         public EmeraldAIDetection EmeraldDetectionComponent;
  200.         public EmeraldAIInitializer EmeraldInitializerComponent;
  201.         public EmeraldAIEventsManager EmeraldEventsManagerComponent;
  202.         public EmeraldAIBehaviors EmeraldBehaviorsComponent;
  203.         public EmeraldAILookAtController EmeraldLookAtComponent;
  204.  
  205.         //Blocking
  206.         float BlockTimer;
  207.         protected float AdjustedBlockAngle;
  208.         public int MitigationAmount = 50;
  209.         public int MaxBlockAngle = 75;
  210.         public int MaxDamageAngle = 75;
  211.         public int MaxFiringAngle = 45;
  212.         public Vector3 SurfaceNormal;
  213.         Quaternion NormalRotation;
  214.         public float MaxNormalAngle;
  215.         public int MaxNormalAngleEditor = 25;
  216.         public int BlockOdds = 80;
  217.         public int GeneratedBlockOdds;
  218.  
  219.         public bool m_AnimationsChanged = false;
  220.         public int m_LastAnimatorType;
  221.         public int BackupOdds = 50;
  222.         public int GeneratedBackupOdds;
  223.         public int BackupDistance = 12;
  224.         public Vector3 BackupDestination;
  225.  
  226.         //Animation States
  227.         public bool IsEmoting;
  228.         public bool IsIdling;
  229.         public bool IsAttacking;
  230.         public bool IsGettingHit;
  231.         public bool IsEquipping;
  232.         public bool IsBlocking;
  233.         public bool IsBackingUp;
  234.         public bool IsTurning;
  235.         public bool IsTurningLeft, IsTurningRight;
  236.         public bool IsSwitchingWeapons;
  237.         public bool IsMoving;
  238.         public bool IsDead;
  239.  
  240.         //Combat
  241.         public float BackingUpTimer;
  242.         public float BackingUpSeconds;
  243.         public int BackingUpSecondsMin = 3;
  244.         public int BackingUpSecondsMax = 4;
  245.         public float RunAttackTimer;
  246.         public int RunAttackSpeed;
  247.         public int MinMeleeAttackSpeed = 0;
  248.         public int MaxMeleeAttackSpeed = 0;
  249.         public int MinRangedAttackSpeed = 0;
  250.         public int MaxRangedAttackSpeed = 0;
  251.         public float AttackSpeed = 1;
  252.         public int MinimumRunAttackSpeed = 2;
  253.         public int MaximumRunAttackSpeed = 4;
  254.         public float AttackTimer;
  255.         public bool HasTarget;
  256.         public bool SwitchWeaponTypeTriggered = false;
  257.  
  258.         public int TotalIdleAnimations = 1;
  259.         public int TotalHitAnimations = 1;
  260.         public int TotalCombatHitAnimations = 1;
  261.         public int TotalRangedCombatHitAnimations = 1;
  262.         public int TotalEmoteAnimations = 1;
  263.         public int TotalAttackAnimations = 1;
  264.         public int TotalRangedAttackAnimations = 1;
  265.         public int TotalRunAttackAnimations = 1;
  266.         public int TotalRangedRunAttackAnimations = 1;
  267.         public int TotalDeathAnimations = 1;
  268.         public int TotalRangedDeathAnimations = 1;
  269.         public bool m_IdleAnimaionIndexOverride = false;
  270.         public bool MirrorWalkLeft = false;
  271.         public bool MirrorWalkRight = false;
  272.         public bool MirrorRunLeft = false;
  273.         public bool MirrorRunRight = false;
  274.         public bool MirrorCombatWalkLeft = false;
  275.         public bool MirrorCombatWalkRight = false;
  276.         public bool MirrorCombatRunLeft = false;
  277.         public bool MirrorCombatRunRight = false;
  278.         public bool MirrorCombatTurnLeft = false;
  279.         public bool MirrorCombatTurnRight = false;
  280.         public bool MirrorRangedCombatWalkLeft = false;
  281.         public bool MirrorRangedCombatWalkRight = false;
  282.         public bool MirrorRangedCombatRunLeft = false;
  283.         public bool MirrorRangedCombatRunRight = false;
  284.         public bool MirrorRangedCombatTurnLeft = false;
  285.         public bool MirrorRangedCombatTurnRight = false;
  286.         public bool MirrorTurnLeft = false;
  287.         public bool MirrorTurnRight = false;
  288.         public bool ReverseWalkAnimation = false;
  289.         public bool ReverseRangedWalkAnimation = false;
  290.  
  291.         public int AngleToTurn;
  292.         public int NonCombatAngleToTurn = 20;
  293.         public int CombatAngleToTurn = 20;
  294.         public float StationaryTurningSpeedNonCombat = 50;
  295.         public float MovingTurnSpeedNonCombat = 2.5f;
  296.         public int StationaryTurningSpeedCombat = 50;
  297.         public float MovingTurnSpeedCombat = 2.5f;
  298.         public float CurrentMovingTurnSpeed = 2.5f;
  299.         public int BackupTurningSpeed = 100;
  300.         public int MaxSlopeLimit = 30;
  301.         public float Acceleration = 1;
  302.         public float Deceleration = 0.5f;
  303.         public float TurnAngle = 30;
  304.         public int AlignmentSpeed;
  305.         public int NonCombatAlignmentSpeed = 15;
  306.         public int CombatAlignmentSpeed = 25;
  307.         public float DirectionDampTime = 0.25f;
  308.         public NavMeshAgent m_NavMeshAgent;
  309.         public AudioSource m_AudioSource;
  310.         public AudioSource m_SecondaryAudioSource;
  311.         public AudioSource m_EventAudioSource;
  312.         public float WaypointTimer;
  313.         float IdleAnimationTimer;
  314.         public int IdleAnimationSeconds = 3;
  315.         public Vector3 NewDestination;
  316.         float DistanceFromDestination;
  317.         float Velocity;
  318.         float AdjustedSpeed;
  319.         Quaternion TargetQ;
  320.         Quaternion GroundQ;
  321.         float PreviousAngle;
  322.         bool m_WeaponTypeSwitchDelay;
  323.         float AddForceTimer;
  324.         float DeathTimer;
  325.         public Transform ForceTransform;
  326.         public int ReceivedRagdollForceAmount;
  327.         public int SentRagdollForceAmount = 200;
  328.         public Transform HitTransform;
  329.         public Transform RagdollTransform;
  330.         public Vector3 TargetDestination;
  331.         Quaternion AligmentAngle;
  332.         public float DestinationAdjustedAngle;
  333.         protected Vector3 DestinationDirection;
  334.         public GameObject WeaponTrail;
  335.  
  336.         //Emerald AI Events
  337.         public UnityEvent DeathEvent;
  338.         public UnityEvent DamageEvent;
  339.         public UnityEvent OnDoDamageEvent;
  340.         public UnityEvent ReachedDestinationEvent;
  341.         public UnityEvent OnStartEvent;
  342.         public UnityEvent OnEnabledEvent;
  343.         public UnityEvent OnPlayerDetectionEvent;
  344.         public UnityEvent OnDetectTargetEvent;
  345.         public UnityEvent OnAttackEvent;
  346.         public UnityEvent OnAttackEndEvent;
  347.         public UnityEvent OnFleeEvent;
  348.         public UnityEvent OnStartCombatEvent;
  349.         public UnityEvent OnKillTargetEvent;
  350.         public UnityEvent OnHealEvent;
  351.         public UnityEvent OnCriticalHitEvent;
  352.  
  353.         public int IdleSoundsSeconds;
  354.         public int IdleSoundsSecondsMin = 5;
  355.         public int IdleSoundsSecondsMax = 10;
  356.         public float IdleSoundsTimer;
  357.         public int CurrentAttacks = 0;
  358.         public int ExpandedChaseDistance = 80;
  359.         public int StartingChaseDistance;
  360.         public int ExpandedDetectionRadius = 40;
  361.         public int StartingDetectionRadius;
  362.         public bool IsRunAttack = false;
  363.         public int RandomDirection;
  364.         public bool TargetInView = false;
  365.  
  366.         [SerializeField]
  367.         public int CurrentFaction;
  368.         [SerializeField]
  369.         public static List<string> StringFactionList = new List<string>();
  370.         public enum RelationType { Enemy = 0, Neutral = 1, Friendly = 2 };
  371.         public RelationType RelationTypeRef;
  372.         public List<int> FactionRelations = new List<int>();
  373.  
  374.         [SerializeField]
  375.         public List<FactionsList> FactionRelationsList = new List<FactionsList>();
  376.  
  377.         [System.Serializable]
  378.         public class FactionsList
  379.         {
  380.             public int FactionIndex;
  381.             public enum RelationType { Enemy = 0, Neutral = 1, Friendly = 2 };
  382.             public RelationType RelationTypeRef;
  383.  
  384.             public FactionsList(int m_FactionIndex, int m_RelationTypeRef)
  385.             {
  386.                 FactionIndex = m_FactionIndex;
  387.                 RelationTypeRef = (RelationType)m_RelationTypeRef;
  388.             }
  389.         }
  390.  
  391.         [SerializeField]
  392.         public List<PlayerFactionClass> PlayerFaction = new List<PlayerFactionClass> { new PlayerFactionClass("Player", 0) };
  393.  
  394.         [System.Serializable]
  395.         public class PlayerFactionClass
  396.         {
  397.             public string PlayerTag = "Player";
  398.             public enum RelationType { Enemy = 0, Neutral = 1, Friendly = 2 };
  399.             public RelationType RelationTypeRef;
  400.  
  401.             public PlayerFactionClass(string m_PlayerTag, int m_RelationTypeRef)
  402.             {
  403.                 PlayerTag = m_PlayerTag;
  404.                 RelationTypeRef = (RelationType)m_RelationTypeRef;
  405.             }
  406.         }
  407.  
  408.         public static GameObject ObjectPool;
  409.         public static GameObject CombatTextSystemObject;
  410.         public float StartingRunSpeed;
  411.         public float StartingRunAnimationSpeed;
  412.         public float StationaryIdleTimer = 0;
  413.         public int StationaryIdleSeconds;
  414.         public int StationaryIdleSecondsMin = 3;
  415.         public int StationaryIdleSecondsMax = 6;
  416.         public float BloodEffectTimeoutSeconds = 3f;
  417.         public List<GameObject> BloodEffectsList = new List<GameObject>();
  418.         public GameObject CurrentProjectile;
  419.         public Vector3 ProjectileDirection;
  420.  
  421.         public List<GameObject> potentialTargets = new List<GameObject>();
  422.         public List<Collider> LineOfSightTargets = new List<Collider>(); //3.1.2 Updated
  423.         //public List<Transform> LineOfSightTargets = new List<Transform>();
  424.  
  425.         [System.Serializable]
  426.         public class InteractSoundClass
  427.         {
  428.             public int SoundEffectID = 1;
  429.             public AudioClip SoundEffectClip;
  430.         }
  431.         public List<InteractSoundClass> InteractSoundList = new List<InteractSoundClass>();
  432.  
  433.         [System.Serializable]
  434.         public class ItemClass
  435.         {
  436.             public int ItemID = 1;
  437.             public GameObject ItemObject;
  438.         }
  439.         public List<ItemClass> ItemList = new List<ItemClass>();
  440.  
  441.         [System.Serializable]
  442.         public class EmoteAnimationClass
  443.         {
  444.             public EmoteAnimationClass(int NewAnimationID, AnimationClip NewEmoteAnimationClip)
  445.             {
  446.                 AnimationID = NewAnimationID;
  447.                 EmoteAnimationClip = NewEmoteAnimationClip;
  448.             }
  449.  
  450.             public int AnimationID = 1;
  451.             public AnimationClip EmoteAnimationClip;
  452.         }
  453.         public List<EmoteAnimationClass> EmoteAnimationList = new List<EmoteAnimationClass>();
  454.  
  455.         [System.Serializable]
  456.         public class AnimationClass
  457.         {
  458.             public AnimationClass(float NewAnimationSpeed, AnimationClip NewAnimationClip)
  459.             {
  460.                 AnimationSpeed = NewAnimationSpeed;
  461.                 AnimationClip = NewAnimationClip;
  462.             }
  463.  
  464.             public float AnimationSpeed = 1;
  465.             public AnimationClip AnimationClip;
  466.         }
  467.         public List<AnimationClass> IdleAnimationList = new List<AnimationClass>();
  468.         public List<AnimationClass> AttackAnimationList = new List<AnimationClass>();
  469.         public List<AnimationClass> RunAttackAnimationList = new List<AnimationClass>();
  470.         public List<AnimationClass> DeathAnimationList = new List<AnimationClass>();
  471.         public List<AnimationClass> CombatHitAnimationList = new List<AnimationClass>();
  472.         public List<AnimationClass> HitAnimationList = new List<AnimationClass>();
  473.  
  474.         public List<AnimationClass> RangedAttackAnimationList = new List<AnimationClass>();
  475.         public List<AnimationClass> RangedCombatHitAnimationList = new List<AnimationClass>();
  476.         public List<AnimationClass> RangedRunAttackAnimationList = new List<AnimationClass>();
  477.         public List<AnimationClass> RangedDeathAnimationList = new List<AnimationClass>();
  478.  
  479.         public AnimationClip Attack1Animation, Attack2Animation, Attack3Animation, Attack4Animation, Attack5Animation, Attack6Animation, RunAttack1Animation, RunAttack2Animation, RunAttack3Animation;
  480.         public AnimationClip Idle1Animation, Idle2Animation, Idle3Animation, Idle4Animation, Idle5Animation, Idle6Animation, IdleWarningAnimation;
  481.         public AnimationClip NonCombatTurnLeftAnimation, NonCombatTurnRightAnimation, CombatTurnLeftAnimation, CombatTurnRightAnimation;
  482.         public AnimationClip NonCombatIdleAnimation, WalkLeftAnimation, WalkStraightAnimation, WalkRightAnimation, RunLeftAnimation, RunStraightAnimation, RunRightAnimation;
  483.         public AnimationClip Emote1Animation, Emote2Animation, Emote3Animation, Emote4Animation, Emote5Animation, Emote6Animation, Emote7Animation, Emote8Animation, Emote9Animation, Emote10Animation;
  484.         public AnimationClip CombatIdleAnimation, CombatWalkLeftAnimation, CombatWalkStraightAnimation, CombatWalkBackAnimation, CombatWalkRightAnimation, CombatRunLeftAnimation, CombatRunStraightAnimation, CombatRunRightAnimation;
  485.         public AnimationClip Hit1Animation, Hit2Animation, Hit3Animation, Hit4Animation, Hit5Animation, Hit6Animation, CombatHit1Animation, CombatHit2Animation, CombatHit3Animation, CombatHit4Animation,
  486.             CombatHit5Animation, CombatHit6Animation, BlockIdleAnimation, BlockHitAnimation, PutAwayWeaponAnimation, PullOutWeaponAnimation;
  487.         public AnimationClip Death1Animation, Death2Animation, Death3Animation, Death4Animation, Death5Animation, Death6Animation;
  488.  
  489.         public AnimationClip RangedCombatIdleAnimation, RangedCombatWalkLeftAnimation, RangedCombatWalkStraightAnimation, RangedCombatWalkBackAnimation, RangedCombatWalkRightAnimation,
  490.             RangedCombatRunLeftAnimation, RangedCombatRunStraightAnimation, RangedCombatRunRightAnimation, RangedIdleWarningAnimation, RangedPutAwayWeaponAnimation, RangedPullOutWeaponAnimation;
  491.         public AnimationClip RangedAttack1Animation, RangedAttack2Animation, RangedAttack3Animation, RangedAttack4Animation, RangedAttack5Animation, RangedAttack6Animation, RangedRunAttack1Animation,
  492.             RangedRunAttack2Animation, RangedRunAttack3Animation;
  493.         public AnimationClip RangedCombatHit1Animation, RangedCombatHit2Animation, RangedCombatHit3Animation, RangedCombatHit4Animation, RangedCombatHit5Animation, RangedCombatHit6Animation,
  494.             RangedCombatTurnLeftAnimation, RangedCombatTurnRightAnimation;
  495.         public AnimationClip RangedDeath1Animation, RangedDeath2Animation, RangedDeath3Animation, RangedDeath4Animation, RangedDeath5Animation, RangedDeath6Animation;
  496.  
  497.         [SerializeField]
  498.         public bool AnimatorControllerGenerated = false;
  499.         public bool AnimationListsChanged = false;
  500.         public string FilePath;
  501.         public bool MissingRuntimeController = false;
  502.         public string EmeraldTag = "Respawn";
  503.         public string UITag = "Player";
  504.         public string RagdollTag = "Untagged";
  505.         public bool AnimationsUpdated = false;
  506.  
  507.         public float RayCastUpdateSeconds = 0.1f;
  508.         float RayCastUpdateTimer;
  509.         public float ObstructionDetectionUpdateSeconds = 0.1f;
  510.         public float ObstructionDetectionUpdateTimer;
  511.         public int CurrentHealth;
  512.         public int StartingHealth = 15;
  513.         public int DetectionRadius = 18;
  514.         public int CurrentDamageAmount = 5;
  515.  
  516.         public int DamageAmountRun = 5;
  517.         public int WanderRadius = 25;
  518.         public int TabNumber = 0;
  519.         public int TemperamentTabNumber = 0;
  520.         public int DetectionTagsTabNumber = 0;
  521.         public int AnimationTabNumber = 0;
  522.         public int SoundTabNumber = 0;
  523.         public int MovementTabNumber = 0;
  524.         public int WeaponTypeTabNumber = 0;
  525.         public int WeaponTypeCombatTabNumber = 0;
  526.         public int WeaponTypeControlTabNumber = 0;
  527.         public int AttackAnimationNumber = 1;
  528.         public int RunAttackAnimationNumber = 1;
  529.         public int IdleAnimationNumber = 1;
  530.         public int CombatTabNumber = 0;
  531.         public int FactionsAndTagTabNumber = 0;
  532.         public int EventTabNumber = 0;
  533.  
  534.         public int MinimumWaitTime = 3;
  535.         public int MaximumWaitTime = 6;
  536.  
  537.         public int MinimumFollowWaitTime = 1;
  538.         public int MaximumFollowWaitTime = 2;
  539.  
  540.         public float DeathDelay;
  541.         public bool DeathDelayActive;
  542.         public float DeathDelayTimer;
  543.         public int DeathDelayMin = 1;
  544.         public int DeathDelayMax = 3;
  545.         public int MinimumDamageAmountRun = 2;
  546.         public int MaximumDamageAmountRun = 5;
  547.         public int CritChance = 15;
  548.         public float CritMultiplier = 2;
  549.  
  550.         public float WalkBackwardsSpeed = 1;
  551.         public float WalkSpeed = 2;
  552.         public float RunSpeed = 5;
  553.         public int ExpandedFieldOfViewAngle = 300;
  554.         public int fieldOfViewAngle = 180;
  555.         public int fieldOfViewAngleRef;
  556.         public int MaxChaseDistance = 30;
  557.         public int AngleNeededToTurn = 10;
  558.         public int AngleNeededToTurnRunning = 30;
  559.         public float TooCloseDistance = 1;
  560.         public float MeleeTooCloseDistance = 1;
  561.         public float RangedTooCloseDistance = 5;
  562.         public float AttackDistance = 2.5f;
  563.         public float MeleeAttackDistance = 2.5f;
  564.         public float RangedAttackDistance = 25;
  565.         public float RunAttackDistance = 3f;
  566.         public int CautiousSeconds = 8;
  567.         public int DeactivateDelay = 5;
  568.         float DeactivateTimer;
  569.         public int SecondsToDisable = 6;
  570.         public float HealthRegRate = 1;
  571.         public int RegenerateAmount = 1;
  572.         public float RegenerateTimer = 0;
  573.         public int AILevel = 1;
  574.         public string AIName = "AI Name";
  575.         public string AITitle = "AI Title";
  576.  
  577.         public float StoppingDistance = 2;
  578.         public float FollowingStoppingDistance = 5;
  579.         public float DistanceOffset = 1;
  580.         public float DistanceFromTarget;
  581.         public float AgentRadius = 0.5f;
  582.         public float AgentBaseOffset = 0;
  583.         public float AgentAcceleration = 75;
  584.         public float MaxXAngle = 15;
  585.         public float MaxZAngle = 5;
  586.         public int HealthPercentageToFlee = 10;
  587.  
  588.         public float Idle1AnimationSpeed = 1, Idle2AnimationSpeed = 1, Idle3AnimationSpeed = 1, Idle4AnimationSpeed = 1, Idle5AnimationSpeed = 1, Idle6AnimationSpeed = 1;
  589.         public float IdleWarningAnimationSpeed = 1;
  590.         public float RangedIdleWarningAnimationSpeed = 1;
  591.         public float IdleCombatAnimationSpeed = 1;
  592.         public float RangedIdleCombatAnimationSpeed = 1;
  593.         public float IdleNonCombatAnimationSpeed = 1;
  594.         public float Attack1AnimationSpeed = 1, Attack2AnimationSpeed = 1, Attack3AnimationSpeed = 1, Attack4AnimationSpeed = 1, Attack5AnimationSpeed = 1, Attack6AnimationSpeed = 1;
  595.         public float RangedAttack1AnimationSpeed = 1, RangedAttack2AnimationSpeed = 1, RangedAttack3AnimationSpeed = 1, RangedAttack4AnimationSpeed = 1, RangedAttack5AnimationSpeed = 1, RangedAttack6AnimationSpeed = 1;
  596.         public float RunAttack1AnimationSpeed = 1, RunAttack2AnimationSpeed = 1, RunAttack3AnimationSpeed = 1;
  597.         public float RangedRunAttack1AnimationSpeed = 1, RangedRunAttack2AnimationSpeed = 1, RangedRunAttack3AnimationSpeed = 1;
  598.         public float TurnLeftAnimationSpeed = 1;
  599.         public float TurnRightAnimationSpeed = 1;
  600.         public float CombatTurnLeftAnimationSpeed = 1;
  601.         public float CombatTurnRightAnimationSpeed = 1;
  602.         public float RangedCombatTurnLeftAnimationSpeed = 1;
  603.         public float RangedCombatTurnRightAnimationSpeed = 1;
  604.         public float Death1AnimationSpeed = 1, Death2AnimationSpeed = 1, Death3AnimationSpeed = 1, Death4AnimationSpeed = 1, Death5AnimationSpeed = 1, Death6AnimationSpeed = 1;
  605.         public float RangedDeath1AnimationSpeed = 1, RangedDeath2AnimationSpeed = 1, RangedDeath3AnimationSpeed = 1, RangedDeath4AnimationSpeed = 1, RangedDeath5AnimationSpeed = 1, RangedDeath6AnimationSpeed = 1;
  606.         public float Emote1AnimationSpeed = 1, Emote2AnimationSpeed = 1, Emote3AnimationSpeed = 1, Emote4AnimationSpeed = 1, Emote5AnimationSpeed = 1, Emote6AnimationSpeed = 1,
  607.             Emote7AnimationSpeed = 1, Emote8AnimationSpeed = 1, Emote9AnimationSpeed = 1, Emote10AnimationSpeed = 1;
  608.         public float WalkAnimationSpeed = 1;
  609.         public float RunAnimationSpeed = 1;
  610.         public float NonCombatWalkAnimationSpeed = 1;
  611.         public float NonCombatRunAnimationSpeed = 1;
  612.         public float CombatWalkAnimationSpeed = 1;
  613.         public float CombatRunAnimationSpeed = 1;
  614.         public float RangedCombatWalkAnimationSpeed = 1;
  615.         public float RangedCombatRunAnimationSpeed = 1;
  616.         public float Hit1AnimationSpeed = 1, Hit2AnimationSpeed = 1, Hit3AnimationSpeed = 1, Hit4AnimationSpeed = 1, Hit5AnimationSpeed = 1, Hit6AnimationSpeed = 1;
  617.         public float CombatHit1AnimationSpeed = 1, CombatHit2AnimationSpeed = 1, CombatHit3AnimationSpeed = 1, CombatHit4AnimationSpeed = 1, CombatHit5AnimationSpeed = 1, CombatHit6AnimationSpeed = 1;
  618.         public float RangedCombatHit1AnimationSpeed = 1, RangedCombatHit2AnimationSpeed = 1, RangedCombatHit3AnimationSpeed = 1,
  619.             RangedCombatHit4AnimationSpeed = 1, RangedCombatHit5AnimationSpeed = 1, RangedCombatHit6AnimationSpeed = 1;
  620.  
  621.         public int StartingBehaviorRef;
  622.         public int StartingConfidenceRef;
  623.         public int StartingWanderingTypeRef;
  624.  
  625.         public Vector3 SingleDestination;
  626.  
  627.         public Renderer Renderer1;
  628.         public Renderer Renderer2;
  629.         public Renderer Renderer3;
  630.         public Renderer Renderer4;
  631.  
  632.         public enum DeathType {Animation = 0, Ragdoll};
  633.         public DeathType DeathTypeRef = DeathType.Animation;
  634.  
  635.         public enum CurrentBehavior { Passive = 0, Cautious = 1, Companion = 2, Aggressive = 3, Pet = 4 };
  636.         public CurrentBehavior BehaviorRef = CurrentBehavior.Passive;
  637.  
  638.         public enum DetectionType { Trigger = 0, LineOfSight = 1 };
  639.         public DetectionType DetectionTypeRef = DetectionType.Trigger;
  640.  
  641.         public enum MaxChaseDistanceType { TargetDistance = 0, StartingDistance = 1 };
  642.         public MaxChaseDistanceType MaxChaseDistanceTypeRef = MaxChaseDistanceType.TargetDistance;
  643.  
  644.         public enum ConfidenceType { Coward = 0, Brave = 1, Foolhardy = 2 };
  645.         public ConfidenceType ConfidenceRef = ConfidenceType.Brave;
  646.  
  647.         public enum OptimizedState { Active = 0, Inactive = 1 };
  648.         public OptimizedState OptimizedStateRef = OptimizedState.Inactive;
  649.  
  650.         public enum CurrentDetection { Alert = 0, Unaware = 1 };
  651.         public CurrentDetection CurrentDetectionRef = CurrentDetection.Unaware;
  652.  
  653.         public enum TargetType { Player = 0, AI = 1, NonAITarget = 2 };
  654.         public TargetType TargetTypeRef = TargetType.Player;
  655.  
  656.         public enum CombatState { NotActive = 0, Active = 1 };
  657.         public CombatState CombatStateRef = CombatState.NotActive;      
  658.  
  659.         public enum CombatType { Offensive = 0, Defensive = 1 };
  660.         public CombatType CombatTypeRef = CombatType.Offensive;    
  661.  
  662.         public enum RefillHealth {Disable = 0, Instantly = 1, OverTime = 2};
  663.         public RefillHealth RefillHealthType = RefillHealth.OverTime;
  664.  
  665.         public enum WanderType { Dynamic = 0, Waypoints = 1, Stationary = 2, Destination = 3 };
  666.         public WanderType WanderTypeRef = WanderType.Dynamic;
  667.  
  668.         public enum WaypointType { Loop = 0, Reverse = 1, Random = 2 };
  669.         public WaypointType WaypointTypeRef = WaypointType.Loop;        
  670.  
  671.         public enum AlignmentQuality { Low = 0, Medium = 1, High = 2 };
  672.         public AlignmentQuality AlignmentQualityRef = AlignmentQuality.Medium;
  673.  
  674.         public enum ObstructionDetectionQuality { Low = 0, Medium = 1, High = 2 };
  675.         public ObstructionDetectionQuality ObstructionDetectionQualityRef = ObstructionDetectionQuality.Medium;
  676.  
  677.         public enum ActionAnimation { Eat = 0, Sleep = 1, Talk = 2, Work = 3, Interact = 4 };
  678.         public ActionAnimation ActionAnimationRef = ActionAnimation.Talk;
  679.  
  680.         public enum PickTargetMethod { Closest = 0, FirstDetected = 1, Random = 2 };
  681.         public PickTargetMethod PickTargetMethodRef = PickTargetMethod.Closest;
  682.  
  683.         public enum WeaponType { Melee = 0, Ranged = 1, Both = 2};
  684.         public WeaponType WeaponTypeRef = WeaponType.Melee;
  685.  
  686.         public enum StartingWeaponType { Melee = 0, Ranged = 1};
  687.         public StartingWeaponType StartingWeaponTypeRef = StartingWeaponType.Melee;
  688.  
  689.         public enum AvoidanceQuality { None = 0, Low = 1, Medium = 2, Good = 3, High = 4 };
  690.         public AvoidanceQuality AvoidanceQualityRef = AvoidanceQuality.Medium;
  691.  
  692.         public enum TargetObstructedAction { StayStationary = 0, MoveCloserImmediately, MoveCloserAfterSetSeconds };
  693.         public TargetObstructedAction TargetObstructedActionRef = TargetObstructedAction.StayStationary;
  694.  
  695.         public AnimatorTypeState AnimatorType = AnimatorTypeState.NavMeshDriven;
  696.         public enum AnimatorTypeState { RootMotion, NavMeshDriven };
  697.  
  698.         public MovementState StartingMovementState = MovementState.Run;
  699.         public MovementState CurrentMovementState = MovementState.Walk;
  700.         public enum MovementState { Walk = 0, Run };
  701.  
  702.         public BlockingState CurrentBlockingState = BlockingState.NotBlocking;
  703.         public enum BlockingState { Blocking, NotBlocking };
  704.  
  705.         public BackupType BackupTypeRef = BackupType.Instant;
  706.         public enum BackupType { Off = 0, Instant, Odds };
  707.  
  708.         public enum AnimatorCullingModes { AlwaysAnimate, CullUpdateTransforms };
  709.         public AnimatorCullingModes AnimatorCullingMode = AnimatorCullingModes.AlwaysAnimate;
  710.  
  711.         public enum CurrentMeleeAttackTypes { StationaryAttack, RunAttack };
  712.         public CurrentMeleeAttackTypes CurrentMeleeAttackType = CurrentMeleeAttackTypes.StationaryAttack;
  713.  
  714.         public enum TotalLODsEnum { Two = 0, Three = 1, Four = 2 };
  715.         public TotalLODsEnum TotalLODsRef = TotalLODsEnum.Three;
  716.  
  717.         public enum IKTypes { UnityIK, EmeraldIK };
  718.         public IKTypes IKType = IKTypes.UnityIK;
  719.  
  720.         public enum YesOrNo { No = 0, Yes = 1 };
  721.         public YesOrNo UseRandomRotationOnStartRef = YesOrNo.No;
  722.         public YesOrNo DisableAIWhenNotInViewRef = YesOrNo.No;
  723.         public YesOrNo UseDeactivateDelayRef = YesOrNo.No;
  724.         public YesOrNo UseWarningAnimationRef = YesOrNo.No;
  725.         public YesOrNo AlignAIOnStartRef = YesOrNo.No;
  726.         public YesOrNo UseAIAvoidance = YesOrNo.No;
  727.         public YesOrNo UseEquipAnimation = YesOrNo.No;
  728.         public YesOrNo UseHitAnimations = YesOrNo.Yes;
  729.         public YesOrNo UseDroppableWeapon = YesOrNo.No;
  730.         public YesOrNo EnableDebugging = YesOrNo.No;
  731.         public YesOrNo DrawRaycastsEnabled = YesOrNo.Yes;
  732.         public YesOrNo DrawLookAtPointsEnabled = YesOrNo.Yes;
  733.         public YesOrNo DebugLogTargetsEnabled = YesOrNo.Yes;
  734.         public YesOrNo DebugLogObstructionsEnabled = YesOrNo.Yes;
  735.         public YesOrNo DebugLogProjectileCollisionsEnabled = YesOrNo.Yes;
  736.         public YesOrNo UseAggro = YesOrNo.Yes;
  737.         public YesOrNo EnableBothWeaponTypes = YesOrNo.No;
  738.         public YesOrNo UseAINameUIOutlineEffect = YesOrNo.Yes;
  739.         public YesOrNo UseAILevelUIOutlineEffect = YesOrNo.Yes;
  740.         public YesOrNo UseCustomFontAIName = YesOrNo.No;
  741.         public YesOrNo UseCustomFontAILevel = YesOrNo.No;  
  742.         public YesOrNo AlignAIWithGroundRef = YesOrNo.No;
  743.         public YesOrNo CreateHealthBarsRef = YesOrNo.No;
  744.         public YesOrNo UseNonAITagRef = YesOrNo.No;
  745.         public YesOrNo UseMagicEffectsPackRef = YesOrNo.No;
  746.         public YesOrNo RandomizeDamageRef = YesOrNo.Yes;
  747.         public YesOrNo CustomizeHealthBarRef = YesOrNo.No;
  748.         public YesOrNo UseCustomFontRef = YesOrNo.No;
  749.         public YesOrNo DisplayAINameRef = YesOrNo.No;
  750.         public YesOrNo DisplayAITitleRef = YesOrNo.No;
  751.         public YesOrNo DisplayAILevelRef = YesOrNo.No;
  752.         public YesOrNo HasMultipleLODsRef = YesOrNo.No;
  753.         public YesOrNo UseHitEffect = YesOrNo.No;
  754.         public YesOrNo UseRunAttacks = YesOrNo.No;
  755.         public YesOrNo UseHeadLookRef = YesOrNo.No;
  756.         public YesOrNo UseBlockingRef = YesOrNo.No;
  757.         public YesOrNo UseCriticalHits = YesOrNo.No;
  758.         public YesOrNo DebugLogMissingAnimationsRef = YesOrNo.Yes;
  759.         public YesOrNo SummonsMultipleAIRef = YesOrNo.No;
  760.         public YesOrNo AttackOnArrivalRef = YesOrNo.Yes;
  761.         public YesOrNo NonCombatAI = YesOrNo.No;
  762.  
  763.         public Transform RangedAttackTransform;
  764.         public Transform CurrentTarget;
  765.         public Transform CurrentFollowTarget;
  766.  
  767.         public string PlayerTag = "Player";
  768.         public string FollowTag = "Player";
  769.         public string NonAITag = "Water";
  770.  
  771.         public bool ReturningToStartInProgress = false;
  772.         public bool AIReachedDestination = false;
  773.         public bool AIAgentActive = false;
  774.  
  775.         public bool HealthBarsFoldout = true;
  776.         public bool CombatTextFoldout = true;
  777.         public bool NameTextFoldout = true;
  778.         public bool WaypointsFoldout = true;
  779.  
  780.         public bool WalkFoldout = true;
  781.         public bool RunFoldout = true;
  782.         public bool TurnFoldout = true;
  783.         public bool CombatWalkFoldout = true;
  784.         public bool CombatRunFoldout = true;
  785.         public bool CombatTurnFoldout = true;
  786.  
  787.         public bool BehaviorFoldout = true;
  788.         public bool ConfidenceFoldout = true;
  789.         public bool WanderFoldout = true;
  790.         public bool CombatStyleFoldout = true;
  791.         public bool CurrentlyPlayingActionAnimation = false;
  792.         public bool DamageSoundInhibitor = false;
  793.         public bool DamageEffectInhibitor = false;
  794.  
  795.         public AudioClip SheatheWeapon;
  796.         public AudioClip UnsheatheWeapon;
  797.         public AudioClip RangedSheatheWeapon;
  798.         public AudioClip RangedUnsheatheWeapon;
  799.         public List<AudioClip> IdleSounds = new List<AudioClip>();
  800.         public List<AudioClip> AttackSounds = new List<AudioClip>();
  801.         public List<AudioClip> InjuredSounds = new List<AudioClip>();
  802.         public List<AudioClip> WarningSounds = new List<AudioClip>();
  803.         public List<AudioClip> DeathSounds = new List<AudioClip>();
  804.         public List<AudioClip> FootStepSounds = new List<AudioClip>();
  805.         public List<AudioClip> BlockingSounds = new List<AudioClip>();
  806.         public List<AudioClip> ImpactSounds = new List<AudioClip>();
  807.         public List<AudioClip> CriticalHitSounds = new List<AudioClip>();
  808.  
  809.         [SerializeField]
  810.         public List<int> AIFactionsList = new List<int>();
  811.         public int TargetTagsIndex;
  812.  
  813.         public Vector3 BloodPosOffset;
  814.         public enum BloodEffectPositionType {BaseTransform = 0, HitTransform};
  815.         public BloodEffectPositionType BloodEffectPositionTypeRef = BloodEffectPositionType.HitTransform;
  816.  
  817.         public GameObject HealthBarCanvas;
  818.         public Sprite HealthBarImage;
  819.         public Sprite HealthBarBackgroundImage;
  820.         public Vector3 HealthBarPos = new Vector3(0, 1.75f, 0);
  821.         public Vector3 CombatTextPos = new Vector3(0, 1.75f, 0);
  822.         public Color HealthBarColor = new Color32(197, 41, 41, 255);
  823.         public Color HealthBarBackgroundColor = new Color32(36, 36, 36, 255);
  824.         public Color NameTextColor = new Color32(255, 255, 255, 255);
  825.         public Color LevelTextColor = new Color32(255, 255, 255, 255);
  826.         public Vector3 HealthBarScale = new Vector3(0.75f, 1, 1);
  827.         public int NameTextFontSize = 7;
  828.         public GameObject WaypointParent;
  829.         public string WaypointOrigin;
  830.         public Vector3 AINamePos = new Vector3(0, 3, 0);
  831.         public Vector3 AILevelPos = new Vector3(1.5f, 0, 0);
  832.  
  833.         public bool FirstTimeInCombat = true;
  834.         public bool WarningAnimationTriggered = false;
  835.         public bool TargetObstructed = false;
  836.  
  837.         float CurrentHealthFloat;
  838.         float CurrentVelocity;
  839.         public float WaitTime = 5;
  840.         public int DamageReceived;
  841.  
  842.         public GameObject DroppableMeleeWeapon;
  843.         public GameObject DroppableRangedWeapon;
  844.         public Transform LastAttacker;
  845.         public Transform LookAtTarget;
  846.         public Transform LineOfSightRef;
  847.         public Transform PassiveTargetRef;
  848.         public Transform CompanionTargetRef;
  849.         public NavMeshPath AIPath;
  850.         public Animator AIAnimator;
  851.         public Vector3 StartingDestination;
  852.         public float CautiousTimer;
  853.         public BoxCollider AIBoxCollider;
  854.         public Renderer AIRenderer;
  855.         public EmeraldAISystem TargetEmerald;
  856.         public GameObject HealthBar;
  857.         public int MaxUIScaleSize = 16;
  858.         public Text AINameUI;
  859.         public Font AINameFont;
  860.         public float AINameLineSpacing = 0.75f;
  861.         public Vector2 AINameUIOutlineSize = new Vector2(0.35f, -0.35f);
  862.         public Color AINameUIOutlineColor = Color.black;
  863.         public Text AILevelUI;
  864.         public Font AILevelFont;
  865.         public Vector2 AILevelUIOutlineSize = new Vector2(0.35f, -0.35f);
  866.         public Color AILevelUIOutlineColor = Color.black;
  867.         public Canvas HealthBarCanvasRef;
  868.         public List<Vector3> WaypointsList = new List<Vector3>();
  869.         public int WaypointIndex = 0;
  870.         int m_LastWaypointIndex = 0;
  871.         public GameObject WaypointHolder;
  872.         Vector3 TurnDirection;
  873.         Vector3 TurnDirectionOther;
  874.         Quaternion TargetDirection;
  875.         NavMeshHit NMH;
  876.         GameObject HitObject;
  877.         public Collider[] CollidersInArea;
  878.         public int ReceivedFaction;
  879.         public Vector3 distanceBetween;
  880.         public string StartingTag;
  881.         public int StartingLayer;
  882.         public AnimationProfile m_AnimationProfile;
  883.         public EmeraldAIWaypointObject m_WaypointObject;
  884.         public bool FinalImpactSound;
  885.         bool WaypointReverseActive;
  886.  
  887.         public int NonCombatAILayerIndex = 2;
  888.         public LayerMask DetectionLayerMask = 3;
  889.         public LayerMask ObstructionDetectionLayerMask = 4;
  890.         public LayerMask UILayerMask = 0;
  891.         public LayerMask AlignmentLayerMask = 1;
  892.         public LayerMask AIAvoidanceLayerMask;
  893.         public LayerMask DynamicWanderLayerMask = ~0;
  894.         public LayerMask BackupLayerMask = ~0;
  895.         #endregion
  896.  
  897.         //Initialize Emerald AI and its components
  898.         protected virtual void Awake()
  899.         {
  900.             EmeraldInitializerComponent = GetComponent<EmeraldAIInitializer>();
  901.             EmeraldInitializerComponent.Initialize();
  902.         }
  903.  
  904.         /// <summary>
  905.         /// Check our AI's path to ensure if it is reachable. If it isn't, regenerate, depending on the Wander Type.
  906.         /// </summary>
  907.         public void CheckPath(Vector3 Destination)
  908.         {
  909.             NavMeshPath path = new NavMeshPath();
  910.             m_NavMeshAgent.CalculatePath(Destination, path);
  911.             if (path.status == NavMeshPathStatus.PathComplete)
  912.             {
  913.                 //Path is valid
  914.             }
  915.             else if (path.status == NavMeshPathStatus.PathPartial)
  916.             {
  917.                 if (WanderTypeRef == WanderType.Destination)
  918.                 {
  919.                     Debug.LogError("The AI ''" + gameObject.name + "'s'' Destination is not reachable. " +
  920.                         "The AI's Wander Type has been set to Stationary. Please check the Destination and make sure it is on the NavMesh and is reachable.");
  921.                     m_NavMeshAgent.stoppingDistance = StoppingDistance;
  922.                     StartingDestination = transform.position + (transform.forward * StoppingDistance);
  923.                     WanderTypeRef = WanderType.Stationary;
  924.                 }
  925.                 else if (WanderTypeRef == WanderType.Waypoints)
  926.                 {
  927.                     Debug.LogError("The AI ''" + gameObject.name + "'s'' Waypoint #" + (WaypointIndex + 1) + " is not reachable. " +
  928.                         "The AI's Wander Type has been set to Stationary. Please check the Waypoint #" + (WaypointIndex + 1) + " and make sure it is on the NavMesh and is reachable.");
  929.                     m_NavMeshAgent.stoppingDistance = StoppingDistance;
  930.                     StartingDestination = transform.position + (transform.forward * StoppingDistance);
  931.                     WanderTypeRef = WanderType.Stationary;
  932.                 }
  933.             }
  934.             else if (path.status == NavMeshPathStatus.PathInvalid)
  935.             {
  936.                 if (WanderTypeRef == WanderType.Destination)
  937.                 {
  938.                     Debug.LogError("The AI ''" + gameObject.name + "'s'' Destination is not reachable. " +
  939.                         "The AI's Wander Type has been set to Stationary. Please check the Destination and make sure it is on the NavMesh.");
  940.                     m_NavMeshAgent.stoppingDistance = StoppingDistance;
  941.                     StartingDestination = transform.position + (transform.forward * StoppingDistance);
  942.                     WanderTypeRef = WanderType.Stationary;
  943.                 }
  944.                 else if (WanderTypeRef == WanderType.Waypoints)
  945.                 {
  946.                     Debug.LogError("The AI ''" + gameObject.name + "'s'' Waypoint #" + (WaypointIndex + 1) + " is not reachable. " +
  947.                         "The AI's Wander Type has been set to Stationary. Please check the Waypoint #" + (WaypointIndex + 1) + " and make sure it is on the NavMesh and is reachable.");
  948.                     m_NavMeshAgent.stoppingDistance = StoppingDistance;
  949.                     StartingDestination = transform.position + (transform.forward * StoppingDistance);
  950.                     WanderTypeRef = WanderType.Stationary;
  951.                 }
  952.             }
  953.             else
  954.             {
  955.                 Debug.Log("Path Invalid");
  956.             }
  957.         }
  958.  
  959.         void CheckAIRenderers()
  960.         {
  961.             if (OptimizedStateRef == OptimizedState.Inactive)
  962.             {
  963.                 if (!Renderer1.isVisible && !Renderer2.isVisible && TotalLODsRef == TotalLODsEnum.Two)
  964.                 {
  965.                     DeactivateTimer += Time.deltaTime;
  966.  
  967.                     if (UseDeactivateDelayRef == YesOrNo.Yes && DeactivateTimer >= DeactivateDelay || UseDeactivateDelayRef == YesOrNo.No)
  968.                     {
  969.                         Deactivate();
  970.                     }
  971.                 }
  972.                 else if (!Renderer1.isVisible && !Renderer2.isVisible && !Renderer3.isVisible && TotalLODsRef == TotalLODsEnum.Three)
  973.                 {
  974.                     DeactivateTimer += Time.deltaTime;
  975.  
  976.                     if (UseDeactivateDelayRef == YesOrNo.Yes && DeactivateTimer >= DeactivateDelay || UseDeactivateDelayRef == YesOrNo.No)
  977.                     {
  978.                         Deactivate();
  979.                     }
  980.                 }
  981.                 else if (!Renderer1.isVisible && !Renderer2.isVisible && !Renderer3.isVisible && !Renderer4.isVisible && TotalLODsRef == TotalLODsEnum.Four)
  982.                 {
  983.                     DeactivateTimer += Time.deltaTime;
  984.                    
  985.                     if (UseDeactivateDelayRef == YesOrNo.Yes && DeactivateTimer >= DeactivateDelay || UseDeactivateDelayRef == YesOrNo.No)
  986.                     {
  987.                         Deactivate();
  988.                     }
  989.                 }
  990.             }
  991.             else if (OptimizedStateRef == OptimizedState.Active)
  992.             {
  993.                 if (TotalLODsRef == TotalLODsEnum.Two)
  994.                 {
  995.                     if (Renderer1.isVisible || Renderer2.isVisible)
  996.                     {
  997.                         Activate();
  998.                     }
  999.                 }
  1000.                 else if (TotalLODsRef == TotalLODsEnum.Three)
  1001.                 {
  1002.                     if (Renderer1.isVisible || Renderer2.isVisible || Renderer3.isVisible)
  1003.                     {
  1004.                         Activate();
  1005.                     }
  1006.                 }
  1007.                 else if (TotalLODsRef == TotalLODsEnum.Four)
  1008.                 {
  1009.                     if (Renderer1.isVisible || Renderer2.isVisible || Renderer3.isVisible || Renderer4.isVisible)
  1010.                     {
  1011.                         Activate();
  1012.                     }
  1013.                 }
  1014.             }
  1015.         }
  1016.  
  1017.         protected virtual void Update()
  1018.         {
  1019.             TimeSinceStart += Time.deltaTime;
  1020.  
  1021.             if (DisableAIWhenNotInViewRef == YesOrNo.Yes && HasMultipleLODsRef == YesOrNo.Yes)
  1022.             {
  1023.                 CheckAIRenderers();
  1024.             }
  1025.  
  1026.             if (OptimizedStateRef == OptimizedState.Inactive || DisableAIWhenNotInViewRef == YesOrNo.No)
  1027.             {
  1028.                 CurrentStateInfo = AIAnimator.GetCurrentAnimatorStateInfo(0);
  1029.  
  1030.                 //Use CustomRotation
  1031.                 CustomRotation();
  1032.  
  1033.                 if (IsMoving)
  1034.                 {
  1035.                     IsTurning = false;
  1036.                     if (CombatStateRef == CombatState.NotActive)
  1037.                         CurrentMovingTurnSpeed = MovingTurnSpeedNonCombat;
  1038.                     else if (CombatStateRef == CombatState.Active)
  1039.                         CurrentMovingTurnSpeed = MovingTurnSpeedCombat;
  1040.                 }
  1041.                 else
  1042.                 {
  1043.                     m_NavMeshAgent.angularSpeed = StationaryTurningSpeedNonCombat;
  1044.                 }
  1045.  
  1046.                 if (CombatStateRef == CombatState.Active && !DeathDelayActive)
  1047.                 {
  1048.                     UpdateWeaponTypeState();
  1049.                 }
  1050.  
  1051.                 if (DeathDelayActive)
  1052.                 {
  1053.                     DeathDelayTimer += Time.deltaTime;
  1054.  
  1055.                     if (DeathDelayTimer > DeathDelay)
  1056.                     {                      
  1057.                         EmeraldBehaviorsComponent.DefaultState();
  1058.                     }
  1059.                 }
  1060.  
  1061.                 AIAgentActive = m_NavMeshAgent.enabled;
  1062.                 AggroDelay += Time.deltaTime;
  1063.  
  1064.                 EmeraldBehaviorsComponent.CheckAnimationStates();
  1065.  
  1066.                 //If our AI is not in combat, wander according to its Wander Type.
  1067.                 if (AIAgentActive && CombatStateRef == CombatState.NotActive && !DeathDelayActive && BehaviorRef != CurrentBehavior.Companion && BehaviorRef != CurrentBehavior.Pet)
  1068.                 {        
  1069.                     Wander();
  1070.                 }
  1071.                 else if (AIAgentActive && CombatStateRef == CombatState.NotActive && !DeathDelayActive)
  1072.                 {                
  1073.                     if (BehaviorRef == CurrentBehavior.Companion || BehaviorRef == CurrentBehavior.Pet)
  1074.                     {
  1075.                         if (CurrentFollowTarget != null)
  1076.                         {
  1077.                             FollowCompanionTarget();
  1078.                         }
  1079.                         else
  1080.                         {
  1081.                             Wander();
  1082.                         }
  1083.                     }
  1084.                 }
  1085.                 else
  1086.                 {
  1087.                     if (m_NavMeshAgent.hasPath && BehaviorRef == CurrentBehavior.Cautious && ConfidenceRef > 0)
  1088.                     {
  1089.                         m_NavMeshAgent.ResetPath();
  1090.                     }
  1091.                 }
  1092.  
  1093.                 //If our AI is not moving, align it with the current surface
  1094.                 if (!IsMoving && !IsDead && !RotateTowardsTarget)
  1095.                 {
  1096.                     AlignAIStationary();
  1097.                 }
  1098.  
  1099.                 //Healing cool down to avoid an AI healing too often
  1100.                 if (HealingCooldownActive)
  1101.                 {
  1102.                     HealingCooldownTimer += Time.deltaTime;
  1103.  
  1104.                     if (HealingCooldownTimer >= HealingCooldownSeconds && AttackTimer < AttackSpeed)
  1105.                     {
  1106.                         HealingCooldownTimer = 0;
  1107.                         HealingCooldownActive = false;
  1108.                     }
  1109.                 }
  1110.  
  1111.                 //Controls looking angle based on non-combat or during combat
  1112.                 if (AIAgentActive)
  1113.                 {
  1114.                     if (CombatStateRef == CombatState.NotActive)
  1115.                     {
  1116.                         AngleToTurn = NonCombatAngleToTurn;
  1117.                         LookAtLimit = NonCombatLookAtLimit;
  1118.                         AlignmentSpeed = NonCombatAlignmentSpeed;
  1119.                         WalkAnimationSpeed = NonCombatWalkAnimationSpeed;
  1120.                         RunAnimationSpeed = NonCombatRunAnimationSpeed;
  1121.                     }
  1122.                     else if (CombatStateRef == CombatState.Active)
  1123.                     {
  1124.                         AngleToTurn = CombatAngleToTurn;
  1125.                         LookAtLimit = CombatLookAtLimit;
  1126.                         AlignmentSpeed = CombatAlignmentSpeed;
  1127.                         WalkAnimationSpeed = CombatWalkAnimationSpeed;
  1128.                         RunAnimationSpeed = CombatRunAnimationSpeed;
  1129.                     }
  1130.                 }
  1131.  
  1132.                 //Handles our AI's Aggressive Behavior using the EmeraldBehaviorsComponent
  1133.                 if (BehaviorRef == CurrentBehavior.Aggressive && CombatStateRef == CombatState.Active && AIAgentActive)
  1134.                 {
  1135.                     EmeraldBehaviorsComponent.AggressiveBehavior();
  1136.                 }
  1137.                 //Handles our AI's Coward Behavior using the EmeraldBehaviorsComponent
  1138.                 else if (BehaviorRef == CurrentBehavior.Cautious && ConfidenceRef == ConfidenceType.Coward && CombatStateRef == CombatState.Active && AIAgentActive)
  1139.                 {
  1140.                     EmeraldBehaviorsComponent.CowardBehavior();
  1141.                 }
  1142.                 //Handles our AI's Cautious Behavior using the EmeraldBehaviorsComponent
  1143.                 else if (BehaviorRef == CurrentBehavior.Cautious && ConfidenceRef != ConfidenceType.Coward && CombatStateRef == CombatState.Active && AIAgentActive)
  1144.                 {
  1145.                     EmeraldBehaviorsComponent.CautiousBehavior();
  1146.                 }
  1147.                 //Handles our AI's Companion Behavior using the EmeraldBehaviorsComponent
  1148.                 else if (BehaviorRef == CurrentBehavior.Companion && AIAgentActive)
  1149.                 {
  1150.                     EmeraldBehaviorsComponent.CompanionBehavior();
  1151.                 }
  1152.  
  1153.                 //Calculates an AI's movement speed when using Root Motion
  1154.                 if (AnimatorType == AnimatorTypeState.RootMotion && !IsDead)
  1155.                 {
  1156.                     MoveAIRootMotion();
  1157.                 }
  1158.                 //Calculates an AI's movement speed when using NavMesh
  1159.                 else if (AnimatorType == AnimatorTypeState.NavMeshDriven && !IsDead)
  1160.                 {
  1161.                     MoveAINavMesh();
  1162.                 }
  1163.  
  1164.                 //If our target is obstructed for 3 seconds, search for a new closer target which will most likely be the object obstructing the AI's LOS.
  1165.                 if (TargetObstructed && WeaponTypeRef == WeaponType.Ranged && CombatStateRef == CombatState.Active)
  1166.                 {
  1167.                     if (EmeraldDetectionComponent.CurrentObstruction != null && EmeraldDetectionComponent.CurrentObstruction.CompareTag(EmeraldTag))
  1168.                     {
  1169.                         m_ObstructedTimer += Time.deltaTime;
  1170.  
  1171.                         if (m_ObstructedTimer >= 2.5f)
  1172.                         {
  1173.                             int m_ReceivedFaction = EmeraldDetectionComponent.CurrentObstruction.GetComponent<EmeraldAISystem>().CurrentFaction;
  1174.                             if (AIFactionsList.Contains(m_ReceivedFaction) && FactionRelations[AIFactionsList.IndexOf(m_ReceivedFaction)] == 0)
  1175.                             {
  1176.                                 EmeraldDetectionComponent.SearchForTarget();
  1177.                             }
  1178.                             else
  1179.                             {
  1180.                                 EmeraldDetectionComponent.SearchForRandomTarget = true;
  1181.                                 EmeraldDetectionComponent.SearchForTarget();
  1182.                             }                          
  1183.                            
  1184.                             m_ObstructedTimer = 0;
  1185.                         }
  1186.                     }
  1187.                 }
  1188.                 else
  1189.                 {
  1190.                     m_ObstructedTimer = 0;
  1191.                 }
  1192.             }
  1193.         }
  1194.  
  1195.         //Controls the AI's weapon type switching from happening too often
  1196.         void WeaponSwitchCooldown ()
  1197.         {
  1198.             m_WeaponTypeSwitchDelay = false;
  1199.         }
  1200.  
  1201.         /// <summary>
  1202.         /// Updates the AI's weapon type to switch between ranged and melee.
  1203.         /// </summary>
  1204.         void UpdateWeaponTypeState ()
  1205.         {
  1206.             if (SwitchWeaponTypeTriggered && !m_WeaponTypeSwitchDelay)
  1207.             {
  1208.                 SwitchWeaponTypeTriggered = false;
  1209.                 m_WeaponTypeSwitchDelay = true;
  1210.                 Invoke("WeaponSwitchCooldown", SwitchWeaponTypesCooldown);
  1211.             }
  1212.  
  1213.             if (EnableBothWeaponTypes == YesOrNo.Yes)
  1214.             {
  1215.                 //Switches the current weapon type based on distance.
  1216.                 if (SwitchWeaponType == SwitchWeaponTypes.Distance && CurrentTarget != null && !m_WeaponTypeSwitchDelay && !IsSwitchingWeapons && !IsAttacking && !IsMoving && !IsBackingUp && !IsTurning)
  1217.                 {
  1218.                     if (CurrentTarget != null && Vector3.Distance(CurrentTarget.position, transform.position) > SwitchWeaponTypesDistance && WeaponTypeRef == WeaponType.Melee && !SwitchWeaponTypeTriggered)
  1219.                     {
  1220.                         SwitchWeaponCoroutine = StartCoroutine(SwitchCurrentWeaponType("Ranged")); //Switch to the Ranged Weapon Type
  1221.                         SwitchWeaponTypeTriggered = true;
  1222.                     }
  1223.  
  1224.                     if (CurrentTarget != null && Vector3.Distance(CurrentTarget.position, transform.position) <= SwitchWeaponTypesDistance && WeaponTypeRef == WeaponType.Ranged && !SwitchWeaponTypeTriggered)
  1225.                     {
  1226.                         //Fade out the look at controller.
  1227.                         if (UseHeadLookRef == YesOrNo.Yes && EmeraldLookAtComponent.BodyWeight > 0)
  1228.                             EmeraldLookAtComponent.FadeOutBodyIK();
  1229.  
  1230.                         SwitchWeaponCoroutine = StartCoroutine(SwitchCurrentWeaponType("Melee")); //Switch to the Melee Weapon Type
  1231.                         SwitchWeaponTypeTriggered = true;
  1232.                     }
  1233.                 }
  1234.                 //Switches the current weapon type based on a random time of SwitchWeaponTimeMin and SwitchWeaponTimeMax.
  1235.                 else if (SwitchWeaponType == SwitchWeaponTypes.Timed)
  1236.                 {
  1237.                     if (!IsSwitchingWeapons && !IsEquipping && !IsMoving)
  1238.                         SwitchWeaponTimer += Time.deltaTime;
  1239.  
  1240.                     if (CurrentTarget != null && SwitchWeaponTimer >= SwitchWeaponTime && !IsSwitchingWeapons && !IsAttacking && !IsMoving && !IsBackingUp && !IsTurning)
  1241.                     {
  1242.                         if (WeaponTypeRef == WeaponType.Melee)
  1243.                             SwitchWeaponCoroutine = StartCoroutine(SwitchCurrentWeaponType("Ranged")); //Switch to the Ranged Weapon Type
  1244.                         else if (WeaponTypeRef == WeaponType.Ranged)
  1245.                         {
  1246.                             //Fade out the look at controller.
  1247.                             if (UseHeadLookRef == YesOrNo.Yes && EmeraldLookAtComponent.BodyWeight > 0)
  1248.                                 EmeraldLookAtComponent.FadeOutBodyIK();
  1249.                             SwitchWeaponCoroutine = StartCoroutine(SwitchCurrentWeaponType("Melee")); //Switch to the Melee Weapon Type
  1250.                         }
  1251.                     }
  1252.                 }
  1253.             }
  1254.         }
  1255.  
  1256.         /// <summary>
  1257.         /// Switches the Weapon Type based on the WeaponTypeName parameter.
  1258.         /// </summary>
  1259.         IEnumerator SwitchCurrentWeaponType(string WeaponTypeName)
  1260.         {
  1261.             IsSwitchingWeapons = true;
  1262.             yield return new WaitForSeconds(0.5f);
  1263.             EmeraldEventsManagerComponent.CancelAttackAnimation();
  1264.  
  1265.             SwitchWeaponTime = Random.Range((float)SwitchWeaponTimeMin, (float)SwitchWeaponTimeMax +1);
  1266.             SwitchWeaponTimer = 0;
  1267.             BackingUpTimer = 0;
  1268.             AIAnimator.SetBool("Blocking", false);
  1269.             CurrentAnimationIndex = 1;
  1270.             AIAnimator.SetInteger("Attack Index", 1);
  1271.  
  1272.             if (ReverseRangedWalkAnimation || ReverseWalkAnimation)
  1273.                 AIAnimator.SetFloat("Backup Speed", -1);
  1274.             else
  1275.                 AIAnimator.SetFloat("Backup Speed", 1);
  1276.  
  1277.             //Switching to Melee
  1278.             if (WeaponTypeName == "Melee")
  1279.             {
  1280.                 yield return new WaitForSeconds(0.1f);
  1281.  
  1282.                 while (!CurrentStateInfo.IsName("Combat Movement (Ranged)") || IsTurning || IsBackingUp)
  1283.                 {
  1284.                     yield return null;
  1285.                 }
  1286.  
  1287.                 yield return new WaitForSeconds(0.1f);
  1288.  
  1289.                 if (DeathDelayActive)
  1290.                 {
  1291.                     IsSwitchingWeapons = false;
  1292.                     yield break;
  1293.                 }
  1294.  
  1295.                 AIAnimator.SetInteger("Weapon Type State", 0);
  1296.  
  1297.                 //Fade out the AI's hand IK if it was active
  1298.                 if (EmeraldHandIKComp != null && EmeraldHandIKComp.RightHandPosWeight > 0)
  1299.                 {
  1300.                     yield return new WaitForSeconds(0.5f);
  1301.                     EmeraldHandIKComp.FadeOutHandWeights();
  1302.                 }
  1303.  
  1304.                 yield return new WaitForSeconds(1f);
  1305.  
  1306.                 while (IsEquipping)
  1307.                 {
  1308.                     yield return null;
  1309.                 }
  1310.  
  1311.                 yield return new WaitForSeconds(0.1f);
  1312.                 WeaponTypeRef = WeaponType.Melee;
  1313.  
  1314.                 //Add the new weapon type's settings.
  1315.                 AIAnimator.ResetTrigger("Attack");
  1316.                 AttackDistance = MeleeAttackDistance;
  1317.                 AttackSpeed = Random.Range((float)MinMeleeAttackSpeed, MaxMeleeAttackSpeed + 1);
  1318.                 TooCloseDistance = MeleeTooCloseDistance;
  1319.                 m_NavMeshAgent.stoppingDistance = MeleeAttackDistance;
  1320.             }
  1321.             else if (WeaponTypeName == "Ranged")
  1322.             {
  1323.                 yield return new WaitForSeconds(0.1f);
  1324.  
  1325.                 while (!CurrentStateInfo.IsName("Combat Movement") || IsTurning || IsBackingUp)
  1326.                 {
  1327.                     yield return null;
  1328.                 }
  1329.  
  1330.                 yield return new WaitForSeconds(0.1f);
  1331.  
  1332.                 if (DeathDelayActive)
  1333.                 {
  1334.                     IsSwitchingWeapons = false;
  1335.                     yield break;
  1336.                 }
  1337.  
  1338.                 AIAnimator.SetInteger("Weapon Type State", 1);
  1339.  
  1340.                 yield return new WaitForSeconds(1f);
  1341.  
  1342.                 while (IsEquipping)
  1343.                 {
  1344.                     yield return null;
  1345.                 }
  1346.  
  1347.                 yield return new WaitForSeconds(0.1f);
  1348.                 WeaponTypeRef = WeaponType.Ranged;
  1349.  
  1350.                 //Add the new weapon type's settings.
  1351.                 AIAnimator.ResetTrigger("Attack");
  1352.                 AttackDistance = RangedAttackDistance;
  1353.                 AttackSpeed = Random.Range((float)MinRangedAttackSpeed, MaxRangedAttackSpeed + 1);
  1354.                 TooCloseDistance = RangedTooCloseDistance;
  1355.                 m_NavMeshAgent.stoppingDistance = RangedAttackDistance;
  1356.             }
  1357.  
  1358.             IsSwitchingWeapons = false;
  1359.         }
  1360.  
  1361.         /// <summary>
  1362.         /// Moves our AI using Unity's NavMesh Agent
  1363.         /// </summary>
  1364.         void MoveAINavMesh ()
  1365.         {
  1366.             float speed = m_NavMeshAgent.desiredVelocity.magnitude;
  1367.             Vector3 velocity = Quaternion.Inverse(transform.rotation) * m_NavMeshAgent.desiredVelocity;
  1368.             float angle = Mathf.Atan2(velocity.x, velocity.z) * 180.0f / 3.14159f;
  1369.  
  1370.             //Handles all of the AI's movement and speed calculations for NavMesh movement.
  1371.             if (AIAgentActive && !IsBackingUp)
  1372.             {
  1373.                 AIAnimator.SetFloat("Direction", angle, DirectionDampTime, Time.deltaTime);
  1374.                 AlignAIMoving();
  1375.  
  1376.                 if (IsAttacking || IsEquipping || IsEmoting || m_NavMeshAgent.remainingDistance <= m_NavMeshAgent.stoppingDistance && !m_NavMeshAgent.pathPending || IsBlocking || IsTurning)
  1377.                 {
  1378.                     AIAnimator.SetFloat("Speed", 0, 0.3f, Time.deltaTime);
  1379.                     m_NavMeshAgent.speed = 0;
  1380.                 }
  1381.                 else if (m_NavMeshAgent.remainingDistance > m_NavMeshAgent.stoppingDistance && !m_NavMeshAgent.pathPending && !IsGettingHit && !IsAttacking && !IsSwitchingWeapons && !IsBackingUp && !IsEmoting && !IsEquipping && !IsBlocking && !IsTurning)
  1382.                 {
  1383.                     AIAnimator.SetBool("Idle Active", false);
  1384.                     AIAnimator.SetFloat("Speed", speed, 0.3f, Time.deltaTime);
  1385.  
  1386.                     if (CurrentMovementState == MovementState.Run)
  1387.                     {
  1388.                         m_NavMeshAgent.speed = RunSpeed;
  1389.                     }
  1390.                     else if (CurrentMovementState == MovementState.Walk)
  1391.                     {
  1392.                         m_NavMeshAgent.speed = WalkSpeed;
  1393.                     }
  1394.                 }
  1395.             }
  1396.         }
  1397.  
  1398.         /// <summary>
  1399.         /// Moves our AI when using Root Motion
  1400.         /// </summary>
  1401.         void MoveAIRootMotion()
  1402.         {
  1403.             Vector3 velocity = Quaternion.Inverse(transform.rotation) * m_NavMeshAgent.desiredVelocity;
  1404.             float angle = Mathf.Atan2(velocity.x, velocity.z) * 180.0f / 3.14159f;
  1405.  
  1406.             //Handles all of the AI's movement and speed calculations for Root Motion
  1407.             if (AIAgentActive)
  1408.             {
  1409.                 AIAnimator.SetFloat("Direction", angle * MovementTurningSensitivity, DirectionDampTime, Time.deltaTime);
  1410.                 AlignAIMoving();
  1411.  
  1412.                 if (IsAttacking || IsEquipping || IsEmoting || m_NavMeshAgent.remainingDistance <= m_NavMeshAgent.stoppingDistance || IsBlocking || IsTurning)
  1413.                 {
  1414.                     DelayTimer = 0;
  1415.                     AIAnimator.SetFloat("Speed", 0, 0.2f, Time.deltaTime);
  1416.                     m_NavMeshAgent.speed = Mathf.Lerp(m_NavMeshAgent.speed, 0f, Time.deltaTime * 30);
  1417.  
  1418.                     if (!ReachedDestination && !ReturningToStartInProgress && !IsTurning)
  1419.                     {
  1420.                         if (CombatStateRef == CombatState.NotActive && WanderTypeRef == WanderType.Dynamic)
  1421.                         {
  1422.                             m_NavMeshAgent.destination = transform.position;
  1423.                             ReachedDestination = true;
  1424.                         }
  1425.                     }
  1426.                 }
  1427.                 else if (m_NavMeshAgent.remainingDistance > m_NavMeshAgent.stoppingDistance  && !IsGettingHit && !IsAttacking && !IsSwitchingWeapons && !IsBackingUp && !IsEmoting && !IsEquipping && !IsBlocking && !IsTurning)
  1428.                 {
  1429.                     DelayTimer = Mathf.Lerp(DelayTimer, 1, Time.deltaTime);
  1430.  
  1431.                     if (DelayTimer >= 0.2f)
  1432.                     {
  1433.                         ReachedDestination = false;
  1434.                         m_NavMeshAgent.speed = Mathf.Lerp(m_NavMeshAgent.speed, 0.06f, Time.deltaTime * 3);
  1435.                         AIAnimator.SetBool("Idle Active", false);
  1436.  
  1437.                         //Force walk movement if getting close to an AI's destination. This helps prevent the AI from running into its target as Root Motion with NavMesh needs a bit of time to stop.
  1438.                         if (m_NavMeshAgent.remainingDistance < (m_NavMeshAgent.stoppingDistance + ForceWalkDistance) && BehaviorRef != CurrentBehavior.Cautious && ConfidenceRef != ConfidenceType.Coward)
  1439.                         {
  1440.                             AIAnimator.SetFloat("Speed", 0.1f, 0.3f, Time.deltaTime);
  1441.                         }
  1442.                         else
  1443.                         {
  1444.                             if (CurrentMovementState == MovementState.Run)
  1445.                             {
  1446.                                 AIAnimator.SetFloat("Speed", 1f, 2f, Time.deltaTime);
  1447.                             }
  1448.                             else if (CurrentMovementState == MovementState.Walk)
  1449.                             {
  1450.                                 AIAnimator.SetFloat("Speed", 0.1f, 0.4f, Time.deltaTime);
  1451.                             }
  1452.                         }
  1453.                     }
  1454.                 }
  1455.             }
  1456.         }
  1457.  
  1458.         /// <summary>
  1459.         /// Uses a custom solution for rotating the AI while moving as it allows for much better turning control and increased speed if needed.
  1460.         /// </summary>
  1461.         void CustomRotation()
  1462.         {
  1463.             if (!IsMoving)
  1464.                 return;
  1465.  
  1466.             m_NavMeshAgent.updateRotation = false;
  1467.             Vector3 SteeringDirection = (m_NavMeshAgent.steeringTarget - transform.position).normalized;
  1468.  
  1469.             if (SteeringDirection != Vector3.zero)
  1470.             {
  1471.                 Quaternion SteeringRotation = Quaternion.LookRotation(SteeringDirection);
  1472.                 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(transform.rotation.eulerAngles.x, SteeringRotation.eulerAngles.y, transform.rotation.eulerAngles.z), Time.deltaTime * CurrentMovingTurnSpeed);
  1473.             }
  1474.         }
  1475.  
  1476.         /// <summary>
  1477.         /// Aligns our AI to the current surface while moving
  1478.         /// </summary>
  1479.         void AlignAIMoving()
  1480.         {
  1481.             if (m_NavMeshAgent.desiredVelocity.magnitude >= 0.025f)
  1482.             {
  1483.                 if (!IsMoving)
  1484.                 {
  1485.                     AIAnimator.SetBool("Turn Right", false);
  1486.                     AIAnimator.SetBool("Turn Left", false);
  1487.                     AIAnimator.ResetTrigger("Hit");
  1488.                 }
  1489.  
  1490.                 IsMoving = true;
  1491.  
  1492.                 if (AlignAIWithGroundRef == YesOrNo.Yes)
  1493.                 {
  1494.                     RayCastUpdateTimer += Time.deltaTime;
  1495.  
  1496.                     if (RayCastUpdateTimer >= RayCastUpdateSeconds)
  1497.                     {
  1498.                         RaycastHit HitDown;
  1499.                         if (Physics.Raycast(new Vector3(transform.position.x, transform.position.y + 0.25f, transform.position.z), -transform.up, out HitDown, 2, AlignmentLayerMask))
  1500.                         {
  1501.                             if (HitDown.transform != this.transform)
  1502.                             {
  1503.                                 SurfaceNormal = HitDown.normal;
  1504.                                 SurfaceNormal.x = Mathf.Clamp(SurfaceNormal.x, -MaxNormalAngle, MaxNormalAngle);
  1505.                                 SurfaceNormal.z = Mathf.Clamp(SurfaceNormal.z, -MaxNormalAngle, MaxNormalAngle);
  1506.                                 RayCastUpdateTimer = 0;
  1507.                             }
  1508.                         }
  1509.                     }
  1510.  
  1511.                     NormalRotation = Quaternion.FromToRotation(transform.up, SurfaceNormal) * transform.rotation;
  1512.                     float angle = Quaternion.Angle(transform.rotation, NormalRotation);
  1513.  
  1514.                     //Only align the AI if the angle threshold is greater than 1.
  1515.                     if (angle > 1f)
  1516.                     {
  1517.                         transform.rotation = Quaternion.RotateTowards(transform.rotation, NormalRotation, Time.deltaTime * AlignmentSpeed);
  1518.                     }
  1519.                 }
  1520.             }
  1521.             else
  1522.             {
  1523.                 IsMoving = false;
  1524.             }
  1525.         }
  1526.  
  1527.         /// <summary>
  1528.         /// Aligns our AI to the current surface while stationary
  1529.         /// </summary>
  1530.         void AlignAIStationary()
  1531.         {
  1532.             RayCastUpdateTimer += Time.deltaTime;
  1533.  
  1534.             if (CombatStateRef == CombatState.Active && CurrentTarget && ConfidenceRef != ConfidenceType.Coward)
  1535.             {
  1536.                 if (RayCastUpdateTimer >= RayCastUpdateSeconds && AlignAIWithGroundRef == YesOrNo.Yes)
  1537.                 {
  1538.                     RaycastHit HitDown;
  1539.                     if (Physics.Raycast(new Vector3(transform.position.x, transform.position.y + 0.25f, transform.position.z), -transform.up, out HitDown, 2, AlignmentLayerMask))
  1540.                     {
  1541.                         if (HitDown.transform != this.transform)
  1542.                         {
  1543.                             SurfaceNormal = HitDown.normal;
  1544.                             SurfaceNormal.x = Mathf.Clamp(SurfaceNormal.x, -MaxNormalAngle, MaxNormalAngle);
  1545.                             SurfaceNormal.z = Mathf.Clamp(SurfaceNormal.z, -MaxNormalAngle, MaxNormalAngle);
  1546.                             RayCastUpdateTimer = 0;
  1547.                         }
  1548.                     }
  1549.                 }
  1550.                 RotateAIStationary();
  1551.             }
  1552.             else if (CombatStateRef == CombatState.NotActive || ConfidenceRef == ConfidenceType.Coward)
  1553.             {
  1554.                 //Once our AI has returned to its stantionary positon, adjust its position so it rotates to its original rotation.
  1555.                 if (ReturnToStationaryPosition && AIAgentActive && m_NavMeshAgent.remainingDistance <= StoppingDistance)
  1556.                 {
  1557.                     ReturnToStationaryPosition = false;
  1558.                 }
  1559.  
  1560.                 RotateAIStationary();
  1561.             }
  1562.         }
  1563.  
  1564.         /// <summary>
  1565.         /// Rotates our AI towards its target or destination
  1566.         /// </summary>
  1567.         protected virtual void RotateAIStationary()
  1568.         {
  1569.             if (CombatStateRef == CombatState.Active && CurrentTarget && ConfidenceRef != ConfidenceType.Coward && !IsGettingHit)
  1570.             {
  1571.                 //Get the angle between the current target and the AI. If using the alignment feature,
  1572.                 //adjust the angle to include the rotation difference of the AI's current surface angle.
  1573.                 Vector3 Direction = new Vector3(CurrentTarget.position.x, 0, CurrentTarget.position.z) - new Vector3(transform.position.x, 0, transform.position.z);
  1574.                 float angle = Vector3.Angle(transform.forward, Direction);
  1575.                 DestinationDirection = Direction;
  1576.  
  1577.                 if (AlignAIWithGroundRef == YesOrNo.Yes)
  1578.                 {
  1579.                     float RotationDifference = transform.localEulerAngles.x;
  1580.                     RotationDifference = (RotationDifference > 180) ? RotationDifference - 360 : RotationDifference;
  1581.                     DestinationAdjustedAngle = Mathf.Abs(angle) - Mathf.Abs(RotationDifference);
  1582.                 }
  1583.                 else if (AlignAIWithGroundRef == YesOrNo.No)
  1584.                 {
  1585.                     DestinationAdjustedAngle = Mathf.Abs(angle);
  1586.                 }
  1587.  
  1588.                 if (DestinationAdjustedAngle >= AngleToTurn && DestinationDirection != Vector3.zero && !IsAttacking)
  1589.                 {
  1590.                     if (AlignAIWithGroundRef == YesOrNo.Yes)
  1591.                     {
  1592.                         Quaternion qTarget = Quaternion.LookRotation(DestinationDirection, Vector3.up);
  1593.                         Quaternion qGround = Quaternion.FromToRotation(Vector3.up, SurfaceNormal) * qTarget;
  1594.                         transform.rotation = Quaternion.RotateTowards(transform.rotation, qGround, Time.deltaTime * StationaryTurningSpeedCombat);
  1595.                     }
  1596.                     else if (AlignAIWithGroundRef == YesOrNo.No)
  1597.                     {
  1598.                         Quaternion qTarget = Quaternion.LookRotation(DestinationDirection, Vector3.up);
  1599.                         transform.rotation = Quaternion.RotateTowards(transform.rotation, qTarget, Time.deltaTime * StationaryTurningSpeedCombat);
  1600.                     }
  1601.                 }
  1602.             }
  1603.             else //Non-Comabt rotations
  1604.             {
  1605.                 //Get the angle between the current destination and the AI. If using the alignment feature,
  1606.                 //adjust the angle to include the rotation difference of the AI's current surface angle.
  1607.                 Vector3 Direction = new Vector3(m_NavMeshAgent.destination.x, 0, m_NavMeshAgent.destination.z) - new Vector3(transform.position.x, 0, transform.position.z);
  1608.                 float angle = Vector3.Angle(transform.forward, Direction);
  1609.                 DestinationDirection = Direction;
  1610.  
  1611.                 if (AlignAIWithGroundRef == YesOrNo.Yes)
  1612.                 {
  1613.                     float RotationDifference = transform.localEulerAngles.x;
  1614.                     RotationDifference = (RotationDifference > 180) ? RotationDifference - 360 : RotationDifference;
  1615.                     DestinationAdjustedAngle = Mathf.Abs(angle) - Mathf.Abs(RotationDifference);
  1616.                 }
  1617.                 else if (AlignAIWithGroundRef == YesOrNo.No)
  1618.                 {
  1619.                     DestinationAdjustedAngle = Mathf.Abs(angle);
  1620.                 }
  1621.  
  1622.                 if (DestinationAdjustedAngle >= AngleToTurn && DestinationDirection != Vector3.zero && !RotateTowardsTarget && IsTurning && !IsEmoting)
  1623.                 {
  1624.                     if (AlignAIWithGroundRef == YesOrNo.Yes)
  1625.                     {
  1626.                         Quaternion qTarget = Quaternion.LookRotation(DestinationDirection, Vector3.up);
  1627.                         Quaternion qGround = Quaternion.FromToRotation(Vector3.up, SurfaceNormal) * qTarget;
  1628.                         transform.rotation = Quaternion.RotateTowards(transform.rotation, qGround, Time.deltaTime * StationaryTurningSpeedNonCombat);
  1629.                     }
  1630.                     else if (AlignAIWithGroundRef == YesOrNo.No)
  1631.                     {
  1632.                         Quaternion qTarget = Quaternion.LookRotation(DestinationDirection, Vector3.up);
  1633.                         transform.rotation = Quaternion.RotateTowards(transform.rotation, qTarget, Time.deltaTime * StationaryTurningSpeedNonCombat);
  1634.                     }
  1635.  
  1636.                     TurnDirectionMet = false;
  1637.                 }
  1638.                 else
  1639.                 {
  1640.                     if (!TurnDirectionMet && !LockTurning && CombatStateRef == CombatState.NotActive|| !TurnDirectionMet && CombatStateRef == CombatState.Active)
  1641.                     {
  1642.                         IsTurning = false;
  1643.                         IsTurningLeft = false;
  1644.                         IsTurningRight = false;
  1645.                         AIAnimator.SetBool("Idle Active", false);
  1646.                         AIAnimator.SetBool("Turn Left", false);
  1647.                         AIAnimator.SetBool("Turn Right", false);
  1648.                         LockTurning = true;
  1649.                         TurnDirectionMet = true;
  1650.                     }
  1651.                 }
  1652.             }
  1653.  
  1654.             if (CombatStateRef == CombatState.NotActive && DestinationAdjustedAngle >= AngleToTurn && DestinationDirection != Vector3.zero && AIAgentActive &&  m_NavMeshAgent.remainingDistance > m_NavMeshAgent.stoppingDistance
  1655.                 || CombatStateRef == CombatState.Active && DestinationAdjustedAngle >= AngleToTurn && DestinationDirection != Vector3.zero && AIAgentActive && !IsAttacking && !IsGettingHit)
  1656.             {
  1657.                 if (TimeSinceStart < 0.5f || LockTurning && CombatStateRef == CombatState.NotActive)
  1658.                     return;
  1659.  
  1660.                 Vector3 cross = Vector3.Cross(transform.forward, Quaternion.LookRotation(DestinationDirection, Vector3.up) * Vector3.forward);
  1661.  
  1662.                 if (cross.y > 0f) //Right
  1663.                 {
  1664.                     IsTurning = true;
  1665.                     IsTurningRight = true;
  1666.                     IsTurningLeft = false;
  1667.                     AIAnimator.SetBool("Idle Active", false);
  1668.                     AIAnimator.SetBool("Turn Right", true);
  1669.                     AIAnimator.SetBool("Turn Left", false);
  1670.                     m_NavMeshAgent.angularSpeed = StationaryTurningSpeedNonCombat;
  1671.                 }
  1672.                 else if (cross.y < 0f) //Left
  1673.                 {
  1674.                     IsTurning = true;
  1675.                     IsTurningLeft = true;
  1676.                     IsTurningRight = false;
  1677.                     AIAnimator.SetBool("Idle Active", false);
  1678.                     AIAnimator.SetBool("Turn Left", true);
  1679.                     AIAnimator.SetBool("Turn Right", false);
  1680.                     m_NavMeshAgent.angularSpeed = StationaryTurningSpeedNonCombat;
  1681.                 }
  1682.                
  1683.             }
  1684.             else if (CombatStateRef == CombatState.Active)
  1685.             {
  1686.                 IsTurning = false;
  1687.                 IsTurningLeft = false;
  1688.                 IsTurningRight = false;
  1689.                 AIAnimator.SetBool("Turn Left", false);
  1690.                 AIAnimator.SetBool("Turn Right", false);
  1691.             }
  1692.         }
  1693.  
  1694.         /// <summary>
  1695.         /// Generates a random waypoint, once an AI reaches its destination
  1696.         /// </summary>
  1697.         public void Wander ()
  1698.         {
  1699.             if (WanderTypeRef == WanderType.Dynamic && m_NavMeshAgent.remainingDistance <= m_NavMeshAgent.stoppingDistance && !m_NavMeshAgent.pathPending && !IsEquipping)
  1700.             {
  1701.                 if (WaypointTimer == 0)
  1702.                 {
  1703.                     AIAnimator.SetBool("Idle Active", true);
  1704.                 }
  1705.                
  1706.                 WaypointTimer += Time.deltaTime;
  1707.  
  1708.                 if (WaypointTimer >= WaitTime)
  1709.                 {
  1710.                     AIAnimator.SetBool("Idle Active", false);
  1711.                     GenerateWaypoint();
  1712.                     if (!m_IdleAnimaionIndexOverride)
  1713.                     {
  1714.                         AIAnimator.SetInteger("Idle Index", Random.Range(1, TotalIdleAnimations + 1));
  1715.                     }
  1716.  
  1717.                     WaitTime = Random.Range((float)MinimumWaitTime, MaximumWaitTime + 1);
  1718.                     WaypointTimer = 0;
  1719.                 }
  1720.             }
  1721.             else if (WanderTypeRef == WanderType.Destination && m_NavMeshAgent.destination != SingleDestination && !AIReachedDestination && !IsEquipping)
  1722.             {
  1723.                 if (m_NavMeshAgent.remainingDistance <= StoppingDistance && !m_NavMeshAgent.pathPending && m_NavMeshAgent.velocity.magnitude != 0)
  1724.                 {
  1725.                     AIReachedDestination = true;
  1726.                     LockTurning = false;
  1727.                     ReachedDestinationEvent.Invoke();
  1728.                 }
  1729.             }
  1730.             else if (WanderTypeRef == WanderType.Waypoints && !WaypointReverseActive && m_NavMeshAgent.destination != WaypointsList[WaypointIndex] && !IsEquipping)
  1731.             {
  1732.                 if (m_NavMeshAgent.remainingDistance <= m_NavMeshAgent.stoppingDistance+0.1f && !m_NavMeshAgent.pathPending && TimeSinceStart > 1.05f)
  1733.                 {
  1734.                     if (WaypointTypeRef == WaypointType.Random)
  1735.                     {
  1736.                         if (WaypointTimer <= 0.01f)
  1737.                         {
  1738.                             AIAnimator.SetBool("Idle Active", true);
  1739.                         }
  1740.  
  1741.                         WaypointTimer += Time.deltaTime;
  1742.  
  1743.                         if (WaypointTimer >= WaitTime && !IdleActivated)
  1744.                         {
  1745.                             LockTurning = false;
  1746.                             IdleActivated = true;
  1747.                             AIAnimator.SetBool("Idle Active", false);
  1748.                             if (!m_IdleAnimaionIndexOverride)
  1749.                             {
  1750.                                 AIAnimator.SetInteger("Idle Index", Random.Range(1, TotalIdleAnimations + 1));
  1751.                             }
  1752.                             WaitTime = Random.Range((float)MinimumWaitTime, MaximumWaitTime + 1);
  1753.                             Invoke("ResetWanderTimer", 0.1f);
  1754.                             NextWaypoint();
  1755.                         }
  1756.                     }
  1757.                     else if (WaypointTypeRef != WaypointType.Random)
  1758.                     {
  1759.                         NextWaypoint();
  1760.                     }
  1761.                 }
  1762.             }
  1763.             else if (WanderTypeRef == WanderType.Stationary && !IsMoving && !IsEquipping)
  1764.             {
  1765.                 StationaryIdleTimer += Time.deltaTime;
  1766.                 if (StationaryIdleTimer >= StationaryIdleSeconds)
  1767.                 {
  1768.                     AIAnimator.SetBool("Idle Active", true);
  1769.                     if (!m_IdleAnimaionIndexOverride)
  1770.                     {
  1771.                         AIAnimator.SetInteger("Idle Index", Random.Range(1, TotalIdleAnimations + 1));
  1772.                     }
  1773.                     StationaryIdleSeconds = Random.Range(StationaryIdleSecondsMin, StationaryIdleSecondsMax);
  1774.                     StationaryIdleTimer = 0;
  1775.                 }
  1776.             }
  1777.  
  1778.             //Play an idle sound if the AI is not moving and the Idle Seconds have been met.
  1779.             if (!IsMoving)
  1780.             {
  1781.                 IdleSoundsTimer += Time.deltaTime;
  1782.                 if (IdleSoundsTimer >= IdleSoundsSeconds)
  1783.                 {
  1784.                     EmeraldEventsManagerComponent.PlayIdleSound();
  1785.                     IdleSoundsTimer = 0;
  1786.                 }
  1787.             }
  1788.         }
  1789.  
  1790.         void ResetWanderTimer ()
  1791.         {
  1792.             WaypointTimer = 0;
  1793.             IdleActivated = false;
  1794.         }
  1795.  
  1796.         /// <summary>
  1797.         /// Allows our Companion and Pet AI to follow their Follow Target
  1798.         /// </summary>
  1799.         public void FollowCompanionTarget ()
  1800.         {
  1801.             float DistanceFromFollower = Vector3.Distance(CurrentFollowTarget.position, transform.position);
  1802.             if (DistanceFromFollower > FollowingStoppingDistance && !IsEmoting)
  1803.             {
  1804.                 m_NavMeshAgent.destination = CurrentFollowTarget.position;
  1805.             }
  1806.  
  1807.             if (DistanceFromFollower < 7)
  1808.             {
  1809.                 CurrentMovementState = MovementState.Walk;
  1810.             }
  1811.             else
  1812.             {
  1813.                 CurrentMovementState = MovementState.Run;
  1814.             }
  1815.         }
  1816.  
  1817.         void ReverseDelay ()
  1818.         {
  1819.             //If there's a target while in the process of this function, return as the stoppingDistance does not need to be set to 0.1.
  1820.             if (CurrentTarget != null)
  1821.             {
  1822.                 WaypointReverseActive = false;
  1823.                 return;
  1824.             }
  1825.  
  1826.             m_NavMeshAgent.stoppingDistance = 0.1f;
  1827.             WaypointReverseActive = false;
  1828.         }
  1829.  
  1830.         /// <summary>
  1831.         /// Handles our AI's waypoints when using the Waypoint Wander Type
  1832.         /// </summary>
  1833.         public void NextWaypoint()
  1834.         {
  1835.             if (WaypointsList.Count == 0)
  1836.                 return;
  1837.  
  1838.             if (WaypointTypeRef != WaypointType.Random && WaypointsList.Count > 1 && !WaypointReverseActive)
  1839.             {
  1840.                 WaypointIndex++;
  1841.  
  1842.                 if (WaypointIndex == WaypointsList.Count)
  1843.                 {
  1844.                     WaypointIndex = 0;
  1845.                     ReachedDestinationEvent.Invoke();
  1846.  
  1847.                     if (WaypointTypeRef == WaypointType.Reverse)
  1848.                     {                    
  1849.                         m_NavMeshAgent.destination = WaypointsList[WaypointsList.Count-1];
  1850.                         WaypointsList.Reverse();
  1851.                         m_NavMeshAgent.stoppingDistance = 10;
  1852.                         WaypointReverseActive = true;
  1853.                         LockTurning = false;
  1854.                         Invoke("ReverseDelay", 4);
  1855.                     }
  1856.                 }
  1857.  
  1858.                 if (m_NavMeshAgent.enabled && !WaypointReverseActive)
  1859.                 {
  1860.                     m_NavMeshAgent.destination = WaypointsList[WaypointIndex];
  1861.                 }
  1862.             }
  1863.             else if (WaypointTypeRef == WaypointType.Random && WaypointsList.Count > 1)
  1864.             {
  1865.                 m_LastWaypointIndex = WaypointIndex;
  1866.  
  1867.                 do
  1868.                 {                  
  1869.                     WaypointIndex = Random.Range(0, WaypointsList.Count);
  1870.                 } while (m_LastWaypointIndex == WaypointIndex);
  1871.  
  1872.                 if (m_NavMeshAgent.enabled)
  1873.                 {
  1874.                     m_NavMeshAgent.destination = WaypointsList[WaypointIndex];
  1875.                 }
  1876.             }
  1877.  
  1878.             //Check that our AI's path is valid.
  1879.             CheckPath(m_NavMeshAgent.destination);
  1880.         }
  1881.  
  1882.         /// <summary>
  1883.         /// If enabled, checks our dynamically generated waypoint to ensure it is far
  1884.         /// enough way from the AI, as well as ensuring that the angle limit is met
  1885.         /// </summary>
  1886.         public void GenerateWaypoint()
  1887.         {
  1888.             int GenerateIndex = 0;
  1889.             LockTurning = false;
  1890.  
  1891.             while (DistanceFromDestination <= (m_NavMeshAgent.stoppingDistance + 2))
  1892.             {
  1893.                 //Attempt to generate a new destination 10 times, if no new destination can be found, stop trying.
  1894.                 if (GenerateIndex > 10)
  1895.                 {
  1896.                     GenerateIndex = 0;
  1897.                     break;
  1898.                 }
  1899.  
  1900.                 NewDestination = StartingDestination + new Vector3(Random.insideUnitSphere.y, 0, Random.insideUnitSphere.z) * WanderRadius;
  1901.  
  1902.                 RaycastHit HitDown;
  1903.                 if (Physics.Raycast(new Vector3(NewDestination.x, NewDestination.y + 100, NewDestination.z), -transform.up, out HitDown, 200, DynamicWanderLayerMask, QueryTriggerInteraction.Ignore))
  1904.                 {
  1905.                     if (HitDown.transform != this.transform)
  1906.                     {
  1907.                         NewDestination = new Vector3(HitDown.point.x, HitDown.point.y, HitDown.point.z);
  1908.  
  1909.                         if (Vector3.Angle(Vector3.up, HitDown.normal) <= MaxSlopeLimit)
  1910.                         {
  1911.                             NewDestination = new Vector3(HitDown.point.x, HitDown.point.y, HitDown.point.z);
  1912.                             DistanceFromDestination = Vector3.Distance(NewDestination, transform.position);
  1913.  
  1914.                             if (DistanceFromDestination > m_NavMeshAgent.stoppingDistance + 2 && AIAgentActive)
  1915.                             {
  1916.                                 NavMeshHit hit;
  1917.  
  1918.                                 if (NavMesh.SamplePosition(NewDestination, out hit, 4, m_NavMeshAgent.areaMask))
  1919.                                 {
  1920.                                     AIAnimator.SetBool("Idle Active", false);
  1921.                                     m_NavMeshAgent.SetDestination(hit.position);
  1922.                                 }
  1923.  
  1924.                                 DistanceFromDestination = 0;
  1925.                                 GenerateIndex = 0;
  1926.                                 break;
  1927.                             }
  1928.                         }
  1929.                     }
  1930.                 }
  1931.  
  1932.                 GenerateIndex++;
  1933.             }
  1934.         }
  1935.  
  1936.         /// <summary>
  1937.         /// Used for triggering a Ranged Attack. Do NOT call directly, use EmeraldAttackEvent instead.
  1938.         /// </summary>
  1939.         void CreateEmeraldProjectile()
  1940.         {
  1941.             if (CurrentTarget != null && m_EmeraldAIAbility != null)
  1942.             {
  1943.                 float AdjustedAngle = TargetAngle();
  1944.  
  1945.                 if (AdjustedAngle <= 180 && !EmeraldLookAtComponent.LookAtInProgress)
  1946.                 {
  1947.                     if (m_EmeraldAIAbility.AbilityType == EmeraldAIAbility.AbilityTypeEnum.Damage && OffensiveAbilities.Count > 0) //Offensive
  1948.                     {
  1949.                         OnAttackEvent.Invoke(); //Invoke the AttackStart event
  1950.  
  1951.                         if (TargetEmerald == null)
  1952.                             CurrentProjectile = EmeraldAIObjectPool.Spawn(m_EmeraldAIAbility.AbilityEffect, RangedAttackTransform.position, Quaternion.LookRotation((CurrentTarget.position + (CurrentTarget.up * CurrentPositionModifier)) - RangedAttackTransform.position, transform.up));
  1953.                         else
  1954.                             CurrentProjectile = EmeraldAIObjectPool.Spawn(m_EmeraldAIAbility.AbilityEffect, RangedAttackTransform.position, Quaternion.LookRotation(TargetEmerald.HitPointTransform.position - RangedAttackTransform.position, transform.up));
  1955.  
  1956.                         if (m_EmeraldAIAbility.UseCreateEffect == EmeraldAIAbility.Yes_No.Yes)
  1957.                         {
  1958.                             GameObject G = EmeraldAIObjectPool.SpawnEffect(m_EmeraldAIAbility.CreateEffect, RangedAttackTransform.position, RangedAttackTransform.rotation, m_EmeraldAIAbility.CastEffectTimeoutSeconds);
  1959.                             G.transform.SetParent(RangedAttackTransform);
  1960.                         }
  1961.  
  1962.                         if (CurrentProjectile.GetComponent<EmeraldAIProjectile>() == null)
  1963.                         {
  1964.                             CurrentlyCreatedAbility = CurrentProjectile.AddComponent<EmeraldAIProjectile>();
  1965.                         }
  1966.                         else
  1967.                         {
  1968.                             CurrentlyCreatedAbility = CurrentProjectile.GetComponent<EmeraldAIProjectile>();
  1969.                         }
  1970.  
  1971.                         if (m_EmeraldAIAbility.UseCreateSound == EmeraldAIAbility.Yes_No.Yes && m_EmeraldAIAbility.CreateSoundsList.Count > 0)
  1972.                         {
  1973.                             AudioClip RandomCreateSound = m_EmeraldAIAbility.CreateSoundsList[Random.Range(0, m_EmeraldAIAbility.CreateSoundsList.Count)];
  1974.                             if (RandomCreateSound != null)
  1975.                                 EmeraldEventsManagerComponent.PlaySoundClip(RandomCreateSound);
  1976.                         }
  1977.                         InitializeAbility(CurrentlyCreatedAbility, m_EmeraldAIAbility);
  1978.                         CurrentProjectile.transform.SetParent(ObjectPool.transform);
  1979.                         CurrentProjectile.GetComponent<EmeraldAIProjectile>().InitializeProjectile(this, m_EmeraldAIAbility); //Initialize the created projectile with the needed data
  1980.                     }
  1981.                     else if (m_EmeraldAIAbility.AbilityType == EmeraldAIAbility.AbilityTypeEnum.Support && SupportAbilities.Count > 0 && !HealingCooldownActive) //Support
  1982.                     {
  1983.                         GameObject AbilityEffect = EmeraldAIObjectPool.SpawnEffect(m_EmeraldAIAbility.AbilityEffect, HitPointTransform.position, Quaternion.identity, m_EmeraldAIAbility.AbilityEffectTimeoutSeconds);
  1984.                         if (m_EmeraldAIAbility.AbilityType == EmeraldAIAbility.AbilityTypeEnum.Support && m_EmeraldAIAbility.SupportType == EmeraldAIAbility.SupportTypeEnum.OverTime)
  1985.                         {
  1986.                             EmeraldEventsManagerComponent.HealOverTimeAbility(m_EmeraldAIAbility);                          
  1987.                         }
  1988.                         else if (m_EmeraldAIAbility.AbilityType == EmeraldAIAbility.AbilityTypeEnum.Support && m_EmeraldAIAbility.SupportType == EmeraldAIAbility.SupportTypeEnum.Instant)
  1989.                         {
  1990.                             CurrentHealth += m_EmeraldAIAbility.AbilitySupportAmount;
  1991.                            
  1992.                             if (CurrentHealth > StartingHealth)
  1993.                             {
  1994.                                 CurrentHealth = StartingHealth;
  1995.                             }
  1996.  
  1997.                             if (CombatTextSystem.Instance.m_EmeraldAICombatTextData.CombatTextTargets != EmeraldAICombatTextData.CombatTextTargetEnum.PlayerOnly)
  1998.                             {
  1999.                                 CombatTextSystem.Instance.CreateCombatTextAI(m_EmeraldAIAbility.AbilitySupportAmount, HitPointTransform.position, false, true);
  2000.                             }
  2001.                         }
  2002.                         OnHealEvent.Invoke();
  2003.                         AbilityEffect.transform.SetParent(ObjectPool.transform);                        
  2004.                         HealingCooldownSeconds = m_EmeraldAIAbility.AbilityCooldown;
  2005.                         HealingCooldownTimer = 0;
  2006.                         HealingCooldownActive = true;
  2007.                         if (m_EmeraldAIAbility.UseCreateSound == EmeraldAIAbility.Yes_No.Yes && m_EmeraldAIAbility.CreateSoundsList.Count > 0)
  2008.                         {
  2009.                             AudioClip RandomCreateSound = m_EmeraldAIAbility.CreateSoundsList[Random.Range(0, m_EmeraldAIAbility.CreateSoundsList.Count)];
  2010.                             if (RandomCreateSound != null)
  2011.                                 EmeraldEventsManagerComponent.PlaySoundClip(RandomCreateSound);
  2012.                         }
  2013.                     }
  2014.                     else if (m_EmeraldAIAbility.AbilityType == EmeraldAIAbility.AbilityTypeEnum.Summon && SummoningAbilities.Count > 0 && TotalSummonedAI < MaxAllowedSummonedAI) //Summon
  2015.                     {
  2016.                         TotalSummonedAI++;                    
  2017.                         Vector3 m_SummonRadius = transform.position + m_EmeraldAIAbility.SummonRadius * new Vector3(Random.insideUnitSphere.x, 0, Random.insideUnitSphere.z);
  2018.                         GameObject m_SummonedObject = EmeraldAIObjectPool.Spawn(m_EmeraldAIAbility.SummonObject, m_SummonRadius + Vector3.up, Quaternion.identity);                      
  2019.                         EmeraldAISystem m_SummonedAI = m_SummonedObject.GetComponent<EmeraldAISystem>();
  2020.                         m_SummonedAI.m_NavMeshAgent.isStopped = true;
  2021.                         if (m_EmeraldAIAbility.UseCreateSound == EmeraldAIAbility.Yes_No.Yes && m_EmeraldAIAbility.CreateSoundsList.Count > 0)
  2022.                         {
  2023.                             AudioClip RandomCreateSound = m_EmeraldAIAbility.CreateSoundsList[Random.Range(0, m_EmeraldAIAbility.CreateSoundsList.Count)];
  2024.                             if (RandomCreateSound != null)
  2025.                                 m_SummonedAI.EmeraldEventsManagerComponent.PlaySoundClip(RandomCreateSound);
  2026.                         }
  2027.  
  2028.                         if (m_SummonedObject.GetComponent<SummonedAIComponent>() == null)
  2029.                         {
  2030.                             m_SummonedObject.AddComponent<SummonedAIComponent>().IntitializeSummon(m_EmeraldAIAbility.AbilityLength);
  2031.                         }
  2032.                         else
  2033.                         {
  2034.                             m_SummonedObject.GetComponent<SummonedAIComponent>().IntitializeSummon(m_EmeraldAIAbility.AbilityLength);
  2035.                         }
  2036.  
  2037.                         GameObject SummoningEffect = EmeraldAIObjectPool.SpawnEffect(m_EmeraldAIAbility.SummonEffect, m_SummonedAI.transform.position, Quaternion.identity, m_EmeraldAIAbility.AbilityEffectTimeoutSeconds);
  2038.                         SummoningEffect.transform.SetParent(m_SummonedObject.transform);
  2039.                         StartCoroutine(InitializeSummonedAI(m_SummonedAI));
  2040.                     }
  2041.  
  2042.                     m_AbilityPicked = false;
  2043.                 }
  2044.                 else
  2045.                 {
  2046.                     DestinationAdjustedAngle = 100;
  2047.                     AIAnimator.ResetTrigger("Attack");
  2048.                     AIAnimator.SetTrigger("Attack Cancelled");
  2049.                     return;
  2050.                 }
  2051.             }
  2052.             else
  2053.             {
  2054.                 DestinationAdjustedAngle = 100;
  2055.                 AIAnimator.ResetTrigger("Attack");
  2056.                 AIAnimator.SetTrigger("Attack Cancelled");
  2057.                 return;
  2058.             }
  2059.         }
  2060.  
  2061.         IEnumerator InitializeSummonedAI (EmeraldAISystem AIObject)
  2062.         {
  2063.             yield return new WaitForSeconds(0.1f);
  2064.             AIObject.EmeraldEventsManagerComponent.ResetAI(EmeraldInitializerComponent.UseDefaultBoxCollider);
  2065.             AIObject.CurrentSummoner = this;
  2066.             AIObject.EmeraldEventsManagerComponent.SetFollowerTarget(transform);
  2067.             AIObject.AIFactionsList = new List<int>(AIFactionsList);
  2068.             AIObject.CurrentFaction = CurrentFaction;
  2069.             AIObject.PlayerFaction[0].RelationTypeRef = PlayerFaction[0].RelationTypeRef;
  2070.             AIObject.EmeraldDetectionComponent.SearchForRandomTarget = true;
  2071.             AIObject.EmeraldDetectionComponent.SearchForTarget();
  2072.             AIObject.EmeraldDetectionComponent.DetectTargetType(AIObject.CurrentTarget);
  2073.             AIObject.LookAtTarget = AIObject.CurrentTarget;
  2074.             AIObject.CompanionTargetRef = AIObject.CurrentTarget;
  2075.             AIObject.EmeraldBehaviorsComponent.ActivateCombatState();
  2076.             AIObject.m_NavMeshAgent.stoppingDistance = AIObject.AttackDistance;
  2077.             yield return new WaitForSeconds(0.8f);          
  2078.             AIObject.m_NavMeshAgent.isStopped = false;
  2079.         }
  2080.  
  2081.         void InitializeAbility (EmeraldAIProjectile CurrentlyCreatedAbility, EmeraldAIAbility m_EmeraldAIAbility)
  2082.         {
  2083.             CurrentlyCreatedAbility.EmeraldComponent = this;
  2084.         }
  2085.        
  2086.         /// <summary>
  2087.         /// This function is used for creating Attack Events for both Ranged and Melee attacks. See the Emerald AI Tutorial - Attack Animation Events video on YouTube.
  2088.         /// </summary>
  2089.         public void EmeraldAttackEvent()
  2090.         {
  2091.             if (WeaponTypeRef == WeaponType.Melee)
  2092.             {
  2093.                 SendEmeraldDamage();
  2094.             }
  2095.             else if (WeaponTypeRef == WeaponType.Ranged)
  2096.             {
  2097.                 CreateEmeraldProjectile();
  2098.             }
  2099.         }
  2100.  
  2101.         /// <summary>
  2102.         /// Sends damage to the player or another AI. Do NOT call directly, use EmeraldAttackEvent instead.
  2103.         /// </summary>
  2104.         public void SendEmeraldDamage()
  2105.         {
  2106.             AIAnimator.ResetTrigger("Hit");
  2107.  
  2108.             if (CurrentTarget != null && m_NavMeshAgent.enabled)
  2109.             {
  2110.                 if (TargetObstructedActionRef != TargetObstructedAction.StayStationary || WeaponTypeRef == WeaponType.Melee)
  2111.                 {
  2112.                     m_NavMeshAgent.destination = CurrentTarget.position;
  2113.                 }
  2114.  
  2115.                 //Get the distance between the AI and the target. If the distance exceeds the AI's attack distance, do not send damage to the target.
  2116.                 float CurrentAttackDistance = 1;
  2117.                 Vector3 m_TargetPos = CurrentTarget.position;
  2118.                 m_TargetPos.y = 0;
  2119.                 Vector3 m_SelfPos = transform.position;
  2120.                 m_SelfPos.y = 0;
  2121.                 float DistanceCheck = Vector3.Distance(m_TargetPos, m_SelfPos);
  2122.                 float CurrentTargetHeight = 0;
  2123.  
  2124.                 //Get the distance between the target and the AI. Negate the x and z axes to get the y axis height between the two objects.
  2125.                 //This is used to stop AI from being able to trigger attacks that exceed the AI's Attack Height.
  2126.                 Vector3 m_TargetHeight = CurrentTarget.position;
  2127.                 m_TargetHeight.x = 0;
  2128.                 m_TargetHeight.z = 0;
  2129.                 Vector3 m_CurrentHeight = HitPointTransform.position;
  2130.                 m_CurrentHeight.x = 0;
  2131.                 m_CurrentHeight.z = 0;
  2132.                 CurrentTargetHeight = Vector3.Distance(m_TargetHeight, m_CurrentHeight);
  2133.  
  2134.                 GetDamageAmount();
  2135.  
  2136.                 if (WeaponTypeRef == WeaponType.Melee)
  2137.                 {
  2138.                     CurrentAttackDistance = MeleeAttackDistance;                
  2139.                 }
  2140.                 else if (WeaponTypeRef == WeaponType.Ranged)
  2141.                 {
  2142.                     CurrentAttackDistance = RangedAttackDistance;
  2143.                 }
  2144.  
  2145.                 if (WeaponTypeRef == WeaponType.Melee && DistanceCheck <= (CurrentAttackDistance + 0.25f) && !SwitchWeaponTypeTriggered && CurrentTargetHeight <= AttackHeight
  2146.                     || WeaponTypeRef == WeaponType.Ranged && !SwitchWeaponTypeTriggered)
  2147.                 {
  2148.                     float AdjustedAngle = TargetAngle();
  2149.  
  2150.                     if (AdjustedAngle <= MaxDamageAngle || WeaponTypeRef == WeaponType.Ranged)
  2151.                     {
  2152.                         if (TargetTypeRef == TargetType.Player)
  2153.                         {
  2154.                             //If the player attacks without being detected, add the EmeraldAIPlayerDamage script so it can receive damage.
  2155.                             if (PlayerDamageComponent == null)
  2156.                             {
  2157.                                 PlayerDamageComponent = CurrentTarget.gameObject.AddComponent<EmeraldAIPlayerDamage>();
  2158.                             }
  2159.  
  2160.                             if (PlayerDamageComponent != null)
  2161.                             {
  2162.                                 //PlayerDamageComponent.SendPlayerDamage(CurrentDamageAmount, this.transform, GetComponent<EmeraldAISystem>(), CriticalHit);
  2163.                                 PlayerDamageComponent.SendPlayerDamage(CurrentDamageAmount, this.transform, null, CriticalHit);
  2164.                             }
  2165.  
  2166.                             if (CriticalHit)
  2167.                                 OnCriticalHitEvent.Invoke();
  2168.  
  2169.                             OnDoDamageEvent.Invoke();
  2170.                             if (!CriticalHit || CriticalHitSounds.Count == 0)
  2171.                                 EmeraldEventsManagerComponent.PlayImpactSound();
  2172.                             else if (CriticalHit && CriticalHitSounds.Count > 0)
  2173.                                 EmeraldEventsManagerComponent.PlayCriticalHitSound();
  2174.                         }
  2175.                         else if (TargetTypeRef == TargetType.AI && TargetEmerald != null)
  2176.                         {                          
  2177.                             TargetEmerald.Damage(CurrentDamageAmount, TargetType.AI, this.transform, SentRagdollForceAmount, CriticalHit);
  2178.                             OnDoDamageEvent.Invoke();
  2179.  
  2180.                             if (!IsBlocking || TargetEmerald.TransformAngle(TargetEmerald.LastAttacker) > TargetEmerald.MaxBlockAngle)
  2181.                             {
  2182.                                 if (CriticalHit)
  2183.                                     OnCriticalHitEvent.Invoke();
  2184.  
  2185.                                 if (TargetEmerald.FinalImpactSound)
  2186.                                     return;
  2187.  
  2188.                                 if (!CriticalHit || CriticalHitSounds.Count == 0)
  2189.                                     EmeraldEventsManagerComponent.PlayImpactSound();
  2190.                                 else if (CriticalHit && CriticalHitSounds.Count > 0)
  2191.                                     EmeraldEventsManagerComponent.PlayCriticalHitSound();
  2192.  
  2193.                                 if (TargetEmerald.IsDead && !TargetEmerald.FinalImpactSound)
  2194.                                     TargetEmerald.FinalImpactSound = true;
  2195.                             }
  2196.                         }
  2197.                         else if (TargetTypeRef == TargetType.NonAITarget)
  2198.                         {
  2199.                             if (NonAIDamageComponent != null)
  2200.                             {
  2201.                                 NonAIDamageComponent.SendNonAIDamage(CurrentDamageAmount, this.transform, CriticalHit);
  2202.                             }
  2203.  
  2204.                             if (CriticalHit)
  2205.                                 OnCriticalHitEvent.Invoke();
  2206.  
  2207.                             OnDoDamageEvent.Invoke();
  2208.                             if (!CriticalHit || CriticalHitSounds.Count == 0)
  2209.                                 EmeraldEventsManagerComponent.PlayImpactSound();
  2210.                             else if (CriticalHit && CriticalHitSounds.Count > 0)
  2211.                                 EmeraldEventsManagerComponent.PlayCriticalHitSound();                          
  2212.                         }
  2213.  
  2214.                         if (WeaponTypeRef == WeaponType.Melee)
  2215.                         {
  2216.                             if (MeleeAttacks[MeleeAttackIndex].AttackImpactEffect != null && CurrentTarget != null)
  2217.                             {
  2218.                                 if (TargetTypeRef == TargetType.Player)
  2219.                                 {
  2220.                                     GameObject ImpactEffect = EmeraldAIObjectPool.SpawnEffect(MeleeAttacks[MeleeAttackIndex].AttackImpactEffect, CurrentTarget.position + (CurrentTarget.up * CurrentPositionModifier), Quaternion.identity, 2);
  2221.                                     ImpactEffect.transform.SetParent(CurrentTarget.transform);
  2222.                                 }
  2223.                                 else if (TargetTypeRef == TargetType.AI && TargetEmerald != null && !TargetEmerald.IsDead)
  2224.                                 {
  2225.                                     GameObject ImpactEffect = EmeraldAIObjectPool.SpawnEffect(MeleeAttacks[MeleeAttackIndex].AttackImpactEffect, TargetEmerald.HitPointTransform.position, Quaternion.identity, 2);
  2226.                                     ImpactEffect.transform.SetParent(CurrentTarget.transform);
  2227.                                 }
  2228.                                 else if (TargetTypeRef == TargetType.NonAITarget)
  2229.                                 {
  2230.                                     GameObject ImpactEffect = EmeraldAIObjectPool.SpawnEffect(MeleeAttacks[MeleeAttackIndex].AttackImpactEffect, CurrentTarget.position + (CurrentTarget.up * CurrentPositionModifier), CurrentTarget.rotation, 2);
  2231.                                     ImpactEffect.transform.SetParent(CurrentTarget.transform);
  2232.                                 }
  2233.                             }
  2234.                         }  
  2235.                     }
  2236.                 }
  2237.             }
  2238.  
  2239.             Invoke("EndAttackEvent", CurrentStateInfo.length / 2f);
  2240.         }
  2241.  
  2242.         void EndAttackEvent()
  2243.         {
  2244.             OnAttackEndEvent.Invoke();
  2245.         }
  2246.  
  2247.         /// <summary>
  2248.         /// Damages our AI and allows an AI to block and mitigate damage, if enabled. To use the ragdoll feature, all
  2249.         /// parameters need to be used where AttackerTransform is the current attacker.
  2250.         /// </summary>
  2251.         /// <param name="DamageAmount">Amount of damage caused during attack.</param>
  2252.         /// <param name="TypeOfTarget">The type of target who is causing the damage.</param>
  2253.         /// <param name="AttackerTransform">The transform of the current attacker.</param>
  2254.         /// <param name="RagdollForce">The amount of force to apply to this AI when they die. (Use Ragdoll must be enabled on this AI)</param>
  2255.         public virtual void Damage (int DamageAmount, TargetType? TypeOfTarget = null, Transform AttackerTransform = null, int RagdollForce = 100, bool CriticalHit = false)
  2256.         {
  2257.             LastAttacker = AttackerTransform;
  2258.            
  2259.             if (CombatStateRef == CombatState.Active && AttackerTransform != CurrentTarget)
  2260.             {
  2261.                 if (UseAggro == YesOrNo.Yes)
  2262.                 {
  2263.                     if (AggroDelay >= 0.5f)
  2264.                     {
  2265.                         CurrentAggroHits++;
  2266.                         AggroDelay = 0;
  2267.                     }
  2268.  
  2269.                     if (CurrentAggroHits >= TotalAggroHits && !IsAttacking && !IsBackingUp)
  2270.                     {
  2271.                         if (IsBlocking && UseBlockingRef == YesOrNo.Yes || IsMoving || IsIdling && UseBlockingRef == YesOrNo.No)
  2272.                         {
  2273.                             if (AggroActionRef == AggroAction.LastAttacker && AttackerTransform != CurrentTarget)
  2274.                             {
  2275.                                 EmeraldEventsManagerComponent.CancelAttackAnimation();
  2276.                                 EmeraldDetectionComponent.SetDetectedTarget(AttackerTransform);
  2277.                             }
  2278.                             else if (AggroActionRef == AggroAction.RandomAttacker)
  2279.                             {
  2280.                                 EmeraldEventsManagerComponent.CancelAttackAnimation();
  2281.                                 EmeraldEventsManagerComponent.SearchForRandomTarget();
  2282.                             }
  2283.                             else if (AggroActionRef == AggroAction.ClosestAttacker)
  2284.                             {
  2285.                                 EmeraldEventsManagerComponent.CancelAttackAnimation();
  2286.                                 EmeraldDetectionComponent.SearchForTarget();
  2287.                             }
  2288.  
  2289.                             if (CurrentTarget == null)
  2290.                             {
  2291.                                 EmeraldDetectionComponent.SearchForTarget();
  2292.                             }
  2293.  
  2294.                             CurrentAggroHits = 0;
  2295.                         }
  2296.                     }
  2297.                 }
  2298.             }
  2299.  
  2300.             //If our AI is hit and does not have a target, expand its detection to look for the damage source.
  2301.             if (CurrentTarget == null && CombatStateRef == CombatState.NotActive || DeathDelayActive || BehaviorRef == CurrentBehavior.Cautious && CurrentTarget != null && ConfidenceRef != ConfidenceType.Coward)
  2302.             {        
  2303.                 //Return, if our attacker is equal to the AI's follow target.
  2304.                 if (CurrentFollowTarget != null && AttackerTransform == CurrentFollowTarget)
  2305.                 {
  2306.                     if (BehaviorRef == CurrentBehavior.Companion || BehaviorRef == CurrentBehavior.Pet)
  2307.                         return;              
  2308.                 }
  2309.  
  2310.                 if (BehaviorRef == CurrentBehavior.Aggressive ||
  2311.                     BehaviorRef == CurrentBehavior.Cautious && ConfidenceRef != ConfidenceType.Coward ||
  2312.                     BehaviorRef == CurrentBehavior.Passive && ConfidenceRef != ConfidenceType.Coward)
  2313.                 {
  2314.                     if (AttackerTransform && NonCombatAI == YesOrNo.No)
  2315.                     {
  2316.                         if (TypeOfTarget != null)
  2317.                         {                          
  2318.                             TargetTypeRef = (TargetType)TypeOfTarget;
  2319.                         }
  2320.  
  2321.                         if (TargetTypeRef == TargetType.AI || TargetTypeRef == TargetType.Player && PlayerFaction[0].RelationTypeRef != PlayerFactionClass.RelationType.Friendly || TargetTypeRef == TargetType.NonAITarget)
  2322.                         {
  2323.                             DeathDelayActive = false;
  2324.                             CurrentTarget = AttackerTransform;
  2325.                             m_NavMeshAgent.destination = CurrentTarget.position;
  2326.                             m_NavMeshAgent.stoppingDistance = AttackDistance;
  2327.  
  2328.                             if (BehaviorRef == CurrentBehavior.Passive || BehaviorRef == CurrentBehavior.Cautious)
  2329.                             {
  2330.                                 if (ConfidenceRef != ConfidenceType.Coward)
  2331.                                 {
  2332.                                     BehaviorRef = CurrentBehavior.Aggressive;
  2333.                                 }
  2334.                             }
  2335.  
  2336.                             if (EnableDebugging == EmeraldAISystem.YesOrNo.Yes && DebugLogTargetsEnabled == EmeraldAISystem.YesOrNo.Yes && !DeathDelayActive)
  2337.                             {
  2338.                                 if (CurrentTarget != null)
  2339.                                 {
  2340.                                     Debug.Log("<b>" + "<color=green>" + gameObject.name + "'s Current Target: " + "</color>" + "<color=red>" + CurrentTarget.gameObject.name + "</color>" + "</b>");
  2341.                                 }
  2342.                             }
  2343.  
  2344.                             if (TargetTypeRef == TargetType.AI)
  2345.                             {
  2346.                                 TargetEmerald = CurrentTarget.GetComponent<EmeraldAISystem>();
  2347.                             }
  2348.                             else
  2349.                             {
  2350.                                 TargetEmerald = null;
  2351.                             }
  2352.  
  2353.                             MaxChaseDistance = ExpandedChaseDistance;
  2354.                             EmeraldLookAtComponent.SetPreviousLookAtInfo();
  2355.                             EmeraldBehaviorsComponent.ActivateCombatState();
  2356.                         }
  2357.                     }
  2358.                     else
  2359.                     {
  2360.                         MaxChaseDistance = ExpandedChaseDistance;
  2361.                         DetectionRadius = ExpandedDetectionRadius;
  2362.                         fieldOfViewAngle = ExpandedFieldOfViewAngle;
  2363.                         EmeraldDetectionComponent.SearchForTarget();
  2364.                     }
  2365.                 }
  2366.                 else if (BehaviorRef == CurrentBehavior.Cautious && ConfidenceRef == ConfidenceType.Coward || BehaviorRef == CurrentBehavior.Passive && ConfidenceRef == ConfidenceType.Coward)
  2367.                 {
  2368.                     if (AttackerTransform.CompareTag(PlayerTag))
  2369.                     {
  2370.                         PlayerFaction[0].RelationTypeRef = PlayerFactionClass.RelationType.Enemy;
  2371.                     }
  2372.                     BehaviorRef = CurrentBehavior.Cautious;
  2373.                     MaxChaseDistance = ExpandedChaseDistance;
  2374.                     DetectionRadius = ExpandedDetectionRadius;
  2375.                     fieldOfViewAngle = ExpandedFieldOfViewAngle;
  2376.                 }
  2377.             }
  2378.  
  2379.             DamageReceived = DamageAmount;
  2380.  
  2381.             if (AttackerTransform != null)
  2382.             {
  2383.                 ForceTransform = AttackerTransform;
  2384.  
  2385.                 if (CurrentTarget != null)
  2386.                 {
  2387.                     AdjustedBlockAngle = TransformAngle(AttackerTransform);
  2388.                 }
  2389.             }
  2390.  
  2391.             //Don't allow a Companion to receive damage from its own follower
  2392.             if (AttackerTransform != CurrentFollowTarget && BehaviorRef == CurrentBehavior.Companion && !IsDead || BehaviorRef != CurrentBehavior.Companion && BehaviorRef != CurrentBehavior.Pet && !IsDead)
  2393.             {
  2394.                 if (!IsBlocking || AdjustedBlockAngle > MaxBlockAngle)
  2395.                 {
  2396.                     CurrentHealth -= DamageAmount;
  2397.                     if (TypeOfTarget != TargetType.Player)
  2398.                     {
  2399.                         if (CombatTextSystem.Instance.m_EmeraldAICombatTextData.CombatTextTargets != EmeraldAICombatTextData.CombatTextTargetEnum.PlayerOnly && !IsDead)
  2400.                         {
  2401.                             CombatTextSystem.Instance.CreateCombatTextAI(DamageReceived, HitPointTransform.position, CriticalHit, false);
  2402.                         }
  2403.                     }
  2404.                     DamageEvent.Invoke(); //Invoke our AI's Damage Event
  2405.  
  2406.                     if (UseHitEffect == YesOrNo.Yes && !DamageEffectInhibitor && BloodEffectsList.Count > 0 && !IsDead)
  2407.                     {
  2408.                         GameObject RandomBloodEffect = BloodEffectsList[Random.Range(0, BloodEffectsList.Count)];
  2409.                         if (RandomBloodEffect != null)
  2410.                         {
  2411.                             GameObject SpawnedBlood = EmeraldAIObjectPool.SpawnEffect(RandomBloodEffect, Vector3.zero, transform.rotation, BloodEffectTimeoutSeconds) as GameObject;
  2412.                             SpawnedBlood.transform.SetParent(transform);
  2413.  
  2414.                             if (LBDImpactPosition == Vector3.zero)
  2415.                             {
  2416.                                 if (BloodEffectPositionTypeRef == BloodEffectPositionType.BaseTransform)
  2417.                                 {
  2418.                                     SpawnedBlood.transform.position = transform.position + BloodPosOffset;
  2419.                                 }
  2420.                                 else if (BloodEffectPositionTypeRef == BloodEffectPositionType.HitTransform)
  2421.                                 {
  2422.                                     SpawnedBlood.transform.position = HitPointTransform.position + BloodPosOffset;
  2423.                                 }
  2424.                             }
  2425.  
  2426.                             LBDImpactPosition = Vector3.zero;
  2427.                         }
  2428.                     }
  2429.  
  2430.                     EmeraldEventsManagerComponent.PlayInjuredSound();
  2431.  
  2432.                     if (CombatStateRef == CombatState.NotActive || ConfidenceRef == ConfidenceType.Coward)
  2433.                     {
  2434.                         AIAnimator.SetInteger("Hit Index", Random.Range(1, TotalHitAnimations + 1));
  2435.                     }
  2436.                     else if (CombatStateRef == CombatState.Active && ConfidenceRef != ConfidenceType.Coward)
  2437.                     {
  2438.                         if (WeaponTypeRef == WeaponType.Melee)
  2439.                         {
  2440.                             AIAnimator.SetInteger("Hit Index", Random.Range(1, TotalCombatHitAnimations + 1));
  2441.                         }
  2442.                         else if (WeaponTypeRef == WeaponType.Ranged)
  2443.                         {
  2444.                             AIAnimator.SetInteger("Hit Index", Random.Range(1, TotalRangedCombatHitAnimations + 1));
  2445.                         }
  2446.                     }
  2447.  
  2448.                     if (UseHitAnimations == YesOrNo.Yes && !IsGettingHit && !IsMoving && !IsBackingUp && !IsAttacking
  2449.                         && !IsTurning && !IsEquipping && AdjustedBlockAngle <= MaxBlockAngle)
  2450.                     {
  2451.                         AIAnimator.SetTrigger("Hit");
  2452.                         EmeraldEventsManagerComponent.Invoke("CancelAttackAnimation", 0.25f);
  2453.                     }
  2454.                     else
  2455.                         AIAnimator.ResetTrigger("Hit");
  2456.                 }
  2457.                 else if (IsBlocking && AdjustedBlockAngle <= MaxBlockAngle)
  2458.                 {
  2459.                     float BlockDamage = Mathf.Abs((DamageAmount * ((MitigationAmount - 1) * 0.01f)) - DamageAmount);
  2460.                     CurrentHealth -= (int)BlockDamage;
  2461.                     if (TypeOfTarget != TargetType.Player)
  2462.                     {
  2463.                         CombatTextSystem.Instance.CreateCombatTextAI((int)BlockDamage, HitPointTransform.position, CriticalHit, false);
  2464.                     }
  2465.  
  2466.                     EmeraldEventsManagerComponent.PlayBlockSound();
  2467.                     EmeraldEventsManagerComponent.Invoke("CancelAttackAnimation", 0.25f);
  2468.                     AIAnimator.SetTrigger("Hit");
  2469.                 }
  2470.             }
  2471.  
  2472.             //Make our Brave AI flee if its health reaches the proper amount
  2473.             if (BehaviorRef == CurrentBehavior.Aggressive && ConfidenceRef == ConfidenceType.Brave)
  2474.             {
  2475.                 if (((float)CurrentHealth / (float)StartingHealth) <= ((float)HealthPercentageToFlee * 0.01f))
  2476.                 {
  2477.                     m_NavMeshAgent.updateRotation = true;
  2478.                     m_NavMeshAgent.ResetPath();
  2479.                     m_NavMeshAgent.stoppingDistance = StoppingDistance;
  2480.                     IsBackingUp = false;
  2481.                     AIAnimator.SetBool("Walk Backwards", false);
  2482.                     EmeraldEventsManagerComponent.ChangeBehavior(CurrentBehavior.Cautious);
  2483.                     EmeraldEventsManagerComponent.ChangeConfidence(ConfidenceType.Coward);
  2484.                 }
  2485.             }
  2486.  
  2487.             //The AI has died, initialize its death state.
  2488.             if (CurrentHealth <= 0 && !IsDead)
  2489.             {
  2490.                 ReceivedRagdollForceAmount = RagdollForce;
  2491.                 EmeraldBehaviorsComponent.DeadState();
  2492.             }
  2493.         }
  2494.  
  2495.         /// <summary>
  2496.         /// Controls when an AI is deactivated while using the optimization system
  2497.         /// </summary>
  2498.         public void Deactivate()
  2499.         {
  2500.             if (CurrentTarget == null && !ReturningToStartInProgress &&
  2501.                 BehaviorRef != CurrentBehavior.Companion && BehaviorRef != CurrentBehavior.Pet && CurrentDetectionRef == CurrentDetection.Unaware)
  2502.             {
  2503.                 TargetDetectionActive = false;
  2504.                 AIBoxCollider.enabled = false;
  2505.                 EmeraldDetectionComponent.enabled = false;
  2506.                 OptimizedStateRef = OptimizedState.Active;
  2507.                 DeactivateTimer = 0;
  2508.  
  2509.                 if (HealthBarCanvas != null && BehaviorRef != CurrentBehavior.Companion && BehaviorRef != CurrentBehavior.Pet)
  2510.                 {
  2511.                     SetUI(false);
  2512.                 }
  2513.             }
  2514.         }
  2515.  
  2516.         /// <summary>
  2517.         /// Controls when an AI is activated while using the optimization system
  2518.         /// </summary>
  2519.         public void Activate()
  2520.         {
  2521.             if (CurrentHealth > 0)
  2522.             {
  2523.                 TargetDetectionActive = true;
  2524.  
  2525.                 if(EmeraldInitializerComponent.UseDefaultBoxCollider)
  2526.                 AIBoxCollider.enabled = true;
  2527.                 else
  2528.                 AIBoxCollider.enabled = false;
  2529.  
  2530.                 EmeraldDetectionComponent.enabled = true;
  2531.                 OptimizedStateRef = OptimizedState.Inactive;
  2532.             }
  2533.         }
  2534.  
  2535.         /// <summary>
  2536.         /// Gets our AI's damage amount depending on the current attack animation
  2537.         /// </summary>
  2538.         public void GetDamageAmount()
  2539.         {
  2540.             if (RandomizeDamageRef == YesOrNo.Yes)
  2541.             {
  2542.                 if (CurrentMeleeAttackType == CurrentMeleeAttackTypes.StationaryAttack)
  2543.                 {
  2544.                     CurrentDamageAmount = Random.Range(MeleeAttacks[MeleeAttacksListIndex].MinDamage, MeleeAttacks[MeleeAttacksListIndex].MaxDamage);
  2545.                 }
  2546.                 else if (CurrentMeleeAttackType == CurrentMeleeAttackTypes.RunAttack)
  2547.                 {
  2548.                     CurrentDamageAmount = Random.Range(MeleeRunAttacks[MeleeRunAttacksListIndex].MinDamage, MeleeRunAttacks[MeleeRunAttacksListIndex].MaxDamage);
  2549.                 }
  2550.             }
  2551.             else if (RandomizeDamageRef == YesOrNo.No)
  2552.             {
  2553.                 if (CurrentMeleeAttackType == CurrentMeleeAttackTypes.StationaryAttack)
  2554.                 {
  2555.                     CurrentDamageAmount = MeleeAttacks[MeleeAttacksListIndex].MinDamage;
  2556.                 }
  2557.                 else if (CurrentMeleeAttackType == CurrentMeleeAttackTypes.RunAttack)
  2558.                 {
  2559.                     CurrentDamageAmount = MeleeRunAttacks[MeleeRunAttacksListIndex].MinDamage;
  2560.                 }
  2561.             }
  2562.  
  2563.             //Calculates the AI's critical hits
  2564.             if (UseCriticalHits == YesOrNo.Yes && WeaponTypeRef == WeaponType.Melee)
  2565.             {
  2566.                 CriticalHit = GenerateCritOdds();
  2567.                 if (CriticalHit)
  2568.                 {
  2569.                     CurrentDamageAmount = Mathf.RoundToInt(CurrentDamageAmount * CritMultiplier);
  2570.                 }
  2571.             }
  2572.         }
  2573.  
  2574.         bool GenerateCritOdds()
  2575.         {
  2576.             bool CriticalHit = false;
  2577.             float m_GeneratedOdds = Random.Range(0.0f, 1.0f);
  2578.             m_GeneratedOdds = Mathf.RoundToInt(m_GeneratedOdds * 100);
  2579.  
  2580.             if (m_GeneratedOdds <= CritChance)
  2581.             {
  2582.                 CriticalHit = true;
  2583.             }
  2584.  
  2585.             return CriticalHit;
  2586.         }
  2587.  
  2588.         public void SetUI(bool Enabled)
  2589.         {
  2590.             m_HealthBarComponent.CalculateUI();
  2591.  
  2592.             if (IsDead)
  2593.                 return;
  2594.  
  2595.             HealthBarCanvasRef.enabled = Enabled;
  2596.             if (CreateHealthBarsRef == YesOrNo.Yes)
  2597.             {
  2598.                 HealthBar.SetActive(Enabled);
  2599.  
  2600.                 if (DisplayAILevelRef == YesOrNo.Yes)
  2601.                 {
  2602.                     AILevelUI.gameObject.SetActive(Enabled);
  2603.                 }
  2604.             }
  2605.  
  2606.             if (DisplayAINameRef == YesOrNo.Yes)
  2607.             {
  2608.                 AINameUI.gameObject.SetActive(Enabled);
  2609.             }
  2610.         }
  2611.  
  2612.         /// <summary>
  2613.         /// Returns the current angle from the AI's target.
  2614.         /// </summary>
  2615.         public virtual float TargetAngle ()
  2616.         {
  2617.             Debug.Log("Target Angle");
  2618.  
  2619.             if (CurrentTarget == null)
  2620.             {
  2621.                 return 360;
  2622.             }
  2623.  
  2624.             Vector3 Direction = new Vector3(CurrentTarget.position.x, 0, CurrentTarget.position.z) - new Vector3(transform.position.x, 0, transform.position.z);
  2625.             float angle = Vector3.Angle(transform.forward, Direction);
  2626.             float RotationDifference = transform.localEulerAngles.x;
  2627.             RotationDifference = (RotationDifference > 180) ? RotationDifference - 360 : RotationDifference;
  2628.             float AdjustedAngle = Mathf.Abs(angle) - Mathf.Abs(RotationDifference);
  2629.  
  2630.             if (WeaponTypeRef == WeaponType.Ranged)
  2631.             {
  2632.                 if (AdjustedAngle <= MaxFiringAngle)
  2633.                 {
  2634.                     TargetInAngleLimit = true;
  2635.                 }
  2636.                 else
  2637.                 {
  2638.                     TargetInAngleLimit = false;
  2639.                 }
  2640.             }
  2641.  
  2642.             return AdjustedAngle;
  2643.         }
  2644.  
  2645.         /// <summary>
  2646.         /// Returns the current angle from the AI's destination.
  2647.         /// </summary>
  2648.         public float DestinationAngle ()
  2649.         {
  2650.             Vector3 Direction = new Vector3(m_NavMeshAgent.steeringTarget.x, 0, m_NavMeshAgent.steeringTarget.z) - new Vector3(transform.position.x, 0, transform.position.z);
  2651.             float angle = Vector3.Angle(transform.forward, Direction);
  2652.             float RotationDifference = transform.localEulerAngles.x;
  2653.             RotationDifference = (RotationDifference > 180) ? RotationDifference - 360 : RotationDifference;
  2654.             float AdjustedAngle = Mathf.Abs(angle) - Mathf.Abs(RotationDifference);
  2655.             return AdjustedAngle;
  2656.         }
  2657.  
  2658.         /// <summary>
  2659.         /// Returns the current angle from the passed Transform.
  2660.         /// </summary>
  2661.         public float TransformAngle(Transform Target)
  2662.         {
  2663.             if (Target == null)
  2664.                 return 180;
  2665.  
  2666.             Vector3 Direction = new Vector3(Target.position.x, 0, Target.position.z) - new Vector3(transform.position.x, 0, transform.position.z);
  2667.             float angle = Vector3.Angle(transform.forward, Direction);
  2668.             float RotationDifference = transform.localEulerAngles.x;
  2669.             RotationDifference = (RotationDifference > 180) ? RotationDifference - 360 : RotationDifference;
  2670.             float AdjustedAngle = Mathf.Abs(angle) - Mathf.Abs(RotationDifference);
  2671.             return AdjustedAngle;
  2672.         }
  2673.  
  2674.         /// <summary>
  2675.         /// Returns the current angle from the AI's head look target. (Player Targets Only)
  2676.         /// </summary>
  2677.         public float HeadLookAngle()
  2678.         {
  2679.             if (LookAtTarget == null)
  2680.                 return 180;
  2681.  
  2682.             Vector3 Direction = new Vector3(LookAtTarget.position.x, 0, LookAtTarget.position.z) - new Vector3(transform.position.x, 0, transform.position.z);
  2683.             float angle = Vector3.Angle(transform.forward, Direction);
  2684.             float RotationDifference = transform.localEulerAngles.x;
  2685.             RotationDifference = (RotationDifference > 180) ? RotationDifference - 360 : RotationDifference;
  2686.             float AdjustedAngle = Mathf.Abs(angle) - Mathf.Abs(RotationDifference);
  2687.             return AdjustedAngle;
  2688.         }
  2689.     }
  2690. }
  2691.  
Add Comment
Please, Sign In to add comment