Библиотека VJ Base
July 11

VJ-Base - npc_vj_human_base - init

Путь к файлу «VJ-Base/lua/entities/npc_vj_human_base/init.lua»

Код файла init.lua

AddCSLuaFile("shared.lua")
include("vj_base/ai/core.lua")
include("vj_base/ai/schedules.lua")
include("vj_base/ai/base_aa.lua")
include("shared.lua")
/*--------------------------------------------------
	*** Copyright (c) 2012-2025 by DrVrej, All rights reserved. ***
	No parts of this code or any of its contents may be reproduced, copied, modified or adapted,
	without the prior written consent of the author, unless otherwise indicated for stand-alone materials.
--------------------------------------------------*/
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Main & Misc ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.Model = false -- Model(s) to spawn with | Picks a random one if it's a table
ENT.CanChatMessage = true -- Is it allowed to post in a player's chat? | Example: "Blank no longer likes you."
	-- ====== Health ====== --
ENT.StartHealth = 50
ENT.HealthRegenParams = {
	Enabled = false, -- Can it regenerate its health?
	Amount = 4, -- How much should the health increase after every delay?
	Delay = VJ.SET(2, 4), -- How much time until the health increases
	ResetOnDmg = true, -- Should the delay reset when it receives damage?
}
	-- ====== Collision ====== --
ENT.HullType = HULL_HUMAN -- List of Hull types: https://wiki.facepunch.com/gmod/Enums/HULL
ENT.EntitiesToNoCollide = false -- Set to a table of entity class names for it to not collide with otherwise leave it to false
	-- ====== NPC Controller ====== --
ENT.ControllerParams = {
	CameraMode = 1, -- Sets the default camera mode | 1 = Third Person, 2 = First Person
	ThirdP_Offset = Vector(0, 0, 0), -- The offset for the controller when the camera is in third person
	FirstP_Bone = "ValveBiped.Bip01_Head1", -- If left empty, the base will attempt to calculate a position for first person
	FirstP_Offset = Vector(0, 0, 5), -- The offset for the controller when the camera is in first person
	FirstP_ShrinkBone = true, -- Should the bone shrink? Useful if the bone is obscuring the player's view
	FirstP_CameraBoneAng = 0, -- Should the camera's angle be affected by the bone's angle? | 0 = No, 1 = Pitch, 2 = Yaw, 3 = Roll
	FirstP_CameraBoneAng_Offset = 0, -- How much should the camera's angle be rotated by? | Useful for weird bone angles
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Movement ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.SightDistance = 6500 -- Initial sight distance | To retrieve: "self:GetMaxLookDistance()" | To change: "self:SetMaxLookDistance(distance)"
ENT.SightAngle = 177 -- Initial field of view | To retrieve: "self:GetFOV()" | To change: "self:SetFOV(degree)" | 360 = See all around
ENT.TurningSpeed = 20 -- Initial turning speed | To retrieve: "self:GetMaxYawSpeed()" | To change: "self:SetMaxYawSpeed(speed)"
ENT.TurningUseAllAxis = false -- If set to true, angles will not be restricted to y-axis, it will change all axes (plural axis)
ENT.CanTurnWhileMoving = true -- Can it turn while moving? | EX: GoldSrc NPCs, Facing enemy while running to cover, Facing the player while moving out of the way
ENT.MovementType = VJ_MOVETYPE_GROUND -- Types: VJ_MOVETYPE_GROUND | VJ_MOVETYPE_AERIAL | VJ_MOVETYPE_AQUATIC | VJ_MOVETYPE_STATIONARY | VJ_MOVETYPE_PHYSICS
ENT.UsePoseParameterMovement = false -- Sets the model's "move_x" and "move_y" pose parameters while moving | Required for player models to move properly!
	-- ====== JUMPING ====== --
	-- Requires "CAP_MOVE_JUMP" capability
	-- Applied automatically by the base if "ACT_JUMP" is valid on the NPC's model
	-- Example scenario:
	--      [A]       <- Apex
	--     /   \
	--    /     [S]   <- Start
	--  [E]           <- End
ENT.JumpParams = {
	Enabled = true, -- Can it do movement jumps?
	MaxRise = 80, -- How high it can jump up ((S -> A) AND (S -> E))
	MaxDrop = 230, -- How low it can jump down (E -> S)
	MaxDistance = 275, -- Maximum distance between Start and End
}
	-- ====== STATIONARY ====== --
ENT.CanTurnWhileStationary = true -- Can it turn while using stationary move type?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ AI & Relationship ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.Behavior = VJ_BEHAVIOR_AGGRESSIVE -- What type of AI behavior is it?
ENT.IsGuard = false -- Should it guard its position? | Will attempt to stay around its guarding position
ENT.NextProcessTime = 1 -- Time until it runs the essential performance-heavy AI components
ENT.EnemyDetection = true -- Can it search and detect for enemies?
ENT.EnemyTouchDetection = true -- Can it turn and detect enemies that collide with it?
ENT.EnemyXRayDetection = false -- Can it detect enemies through walls & objects?
ENT.EnemyTimeout = 15 -- Time until the enemy target is reset if it's not visible
ENT.AlertTimeout = VJ.SET(14, 16) -- Time until it transitions from alerted state to idle state assuming it has no enemy
ENT.IdleAlwaysWander = false -- Should it constantly wander while idle?
ENT.DisableWandering = false
ENT.DisableChasingEnemy = false
ENT.CanOpenDoors = true -- Can it open doors?
	-- ====== Alliances ====== --
ENT.CanAlly = true -- Can it ally with other entities?
ENT.VJ_NPC_Class = {} -- Relationship classes, any entity with the same class will be seen as an ally
	-- Common Classes:
		-- Players / Resistance / Black Mesa = "CLASS_PLAYER_ALLY" || HECU = "CLASS_UNITED_STATES" || Portal = "CLASS_APERTURE"
		-- Combine = "CLASS_COMBINE" || Zombie = "CLASS_ZOMBIE" || Antlions = "CLASS_ANTLION" || Xen = "CLASS_XEN" || Black-Ops = "CLASS_BLACKOPS"
ENT.AlliedWithPlayerAllies = false -- Should it be allied with other player allies? | Both entities must have "CLASS_PLAYER_ALLY"
ENT.YieldToAlliedPlayers = true -- Should it give space to allied players?
ENT.BecomeEnemyToPlayer = false -- Should it become enemy towards an allied player if it's damaged by them or it witnesses another ally killed by them?
	-- false = Don't turn hostile to allied players | number = Threshold, where each negative event increases it by 1, if it passes this number it will become hostile
ENT.CanReceiveOrders = true -- Can it receive orders from allies? | Ex: Allies calling for help, allies requesting backup on damage, etc.
	-- false = Will not receive the following: "CallForHelp", "DamageAllyResponse", "DeathAllyResponse", "Passive_AlliesRunOnDamage"
	-- ====== Passive Behaviors ====== --
ENT.Passive_RunOnTouch = true -- Should it run and make a alert sound when something collides with it?
ENT.Passive_AlliesRunOnDamage = true -- Should its allies (other passive NPCs) also run when it's damaged?
	-- ====== On Player Sight ====== --
ENT.HasOnPlayerSight = false -- Should do something when it a player?
ENT.OnPlayerSightDistance = 200 -- How close should the player be until it runs the code?
ENT.OnPlayerSightDispositionLevel = 1 -- 0 = Run it every time | 1 = Run it only when friendly to player | 2 = Run it only when enemy to player
ENT.OnPlayerSightOnlyOnce = true -- If true, it will only run it once | Sets "self.HasOnPlayerSight" to false after it runs!
ENT.OnPlayerSightNextTime = VJ.SET(15, 20) -- How much time should it pass until it runs the code again?
	-- ====== Call For Help ====== --
ENT.CallForHelp = true -- Can it request allies for help while in combat?
ENT.CallForHelpDistance = 2000 -- Max distance its request for help travels
ENT.CallForHelpCooldown = 4 -- Time until it calls for help again
ENT.AnimTbl_CallForHelp = {ACT_SIGNAL_ADVANCE, ACT_SIGNAL_FORWARD} -- Call for help animations | false = Don't play an animation
ENT.CallForHelpAnimFaceEnemy = true -- Should it face the enemy while playing the animation?
ENT.CallForHelpAnimCooldown = 30 -- How much time until it can play an animation again?
	-- ====== Medic ====== --
	-- Medics only heal allied entities that are tagged with "self.VJ_ID_Healable", by default it includes VJ NPCs and players
ENT.IsMedic = false -- Should it heal allied entities?
ENT.Medic_CheckDistance = 600 -- Max distance to check for injured allies
ENT.Medic_HealDistance = 30 -- How close does it have to be until it stops moving and heals its ally?
ENT.Medic_TimeUntilHeal = false -- Time until the ally receives health | false = Base auto calculates the duration
ENT.AnimTbl_Medic_GiveHealth = ACT_SPECIAL_ATTACK1 -- Animations to play when it heals an ally | false = Don't play an animation
ENT.Medic_HealAmount = 25 -- How health does it give?
ENT.Medic_NextHealTime = VJ.SET(10, 15) -- How much time until it can give health to an ally again
ENT.Medic_SpawnPropOnHeal = true -- Should it spawn a prop, such as small health vial at a attachment when healing an ally?
ENT.Medic_SpawnPropOnHealModel = "models/healthvial.mdl" -- The model that it spawns
ENT.Medic_SpawnPropOnHealAttachment = "anim_attachment_LH" -- The attachment it spawns on
	-- ====== Follow System ====== --
	-- Associated variables: self.FollowData, self.IsFollowing
	-- NOTE: Stationary NPCs can't use follow system!
ENT.FollowPlayer = true -- Should it follow allied players when the player presses the USE key?
ENT.FollowMinDistance = 100 -- Minimum distance it should come when following something | The base automatically adds the NPC's size to this variable to account for different sizes!
	-- ====== Constantly Face Enemy ====== --
ENT.ConstantlyFaceEnemy = false -- Should it face the enemy constantly?
ENT.ConstantlyFaceEnemy_IfVisible = true -- Should it only face the enemy if it's visible?
ENT.ConstantlyFaceEnemy_IfAttacking = false -- Should it face the enemy when attacking?
ENT.ConstantlyFaceEnemy_Postures = "Both" -- "Both" = Moving or standing | "Moving" = Only when moving | "Standing" = Only when standing
ENT.ConstantlyFaceEnemy_MinDistance = 2500 -- How close does it have to be until it starts to face the enemy?
	-- ====== Pose Parameter Tracking ====== --
ENT.HasPoseParameterLooking = true -- Does it look at its enemy using pose parameters?
ENT.PoseParameterLooking_Names = {pitch = {}, yaw = {}, roll = {}} -- Custom pose parameters to use, can put as many as needed
ENT.PoseParameterLooking_InvertPitch = false -- Inverts the pitch pose parameters (X)
ENT.PoseParameterLooking_InvertYaw = false -- Inverts the yaw pose parameters (Y)
ENT.PoseParameterLooking_InvertRoll = false -- Inverts the roll pose parameters (Z)
ENT.PoseParameterLooking_TurningSpeed = 10 -- How fast does the parameter turn?
ENT.PoseParameterLooking_CanReset = true -- Should it reset its pose parameters if there is no enemies?
	-- ====== Investigation ====== --
	-- Showcase: https://www.youtube.com/watch?v=cCqoqSDFyC4
ENT.CanInvestigate = true -- Can it detect and investigate disturbances? | EX: Sounds, movement, flashlight, bullet hits
ENT.InvestigateSoundMultiplier = 9 -- Max sound hearing distance multiplier | This multiplies the calculated volume of the sound
	-- ====== Danger & Grenade Detection ====== --
	-- Showcase: https://www.youtube.com/watch?v=XuaMWPTe6rA
	-- EXAMPLES: Props that are one fire, especially objects like barrels that are about to explode, Combine mine that is triggered and about to explode, The location that the Antlion Worker's spit is going to hit, Combine Flechette that is about to explode,
	-- Antlion Guard that is charging towards the NPC, Player that is driving a vehicle at high speed towards the NPC, Manhack that has opened its blades, Rollermine that is about to self-destruct, Combine Helicopter that is about to drop bombs or is firing a turret near the NPC,
	-- Combine Gunship's is about to fire its belly cannon near the NPC, Turret impact locations fired by Combine Gunships, or Combine Dropships, or Striders, The location that a Combine Dropship is going to deploy soldiers, Strider is moving on top of the NPC,
	-- The location that the Combine or HECU mortar is going to hit, SMG1 grenades that are flying close by, A Combine soldier that is rappelling on top of the NPC, Stalker's laser impact location, Combine APC that is driving towards the NPC
ENT.CanDetectDangers = true -- Can it detect dangers? | Ex: Grenades, fire, bombs, explosives, etc.
ENT.DangerDetectionDistance = 400 -- Max danger detection distance | WARNING: Most of the non-grenade dangers ignore this max value
ENT.CanRedirectGrenades = true -- Can it pick up detected grenades and throw it away or to the enemy?
	-- NOTE: Can only throw grenades away if it has a grenade attack AND can detect dangers
	-- ====== Taking Cover ====== --
ENT.AnimTbl_TakingCover = ACT_COVER_LOW -- Animations it plays when hiding behind a covered position
ENT.AnimTbl_MoveToCover = ACT_RUN_CROUCH -- Movement animations it plays when moving to a covered position
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Damaged / Injured ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	-- ====== Blood ====== --
	-- Leave blood tables empty to let the base decide depending on the blood type
ENT.Bleeds = true -- Can it bleed? Controls all bleeding related components such blood decal, particle, pool, etc.
ENT.BloodColor = VJ.BLOOD_COLOR_NONE -- Its blood type, this will determine the blood decal, particle, etc.
ENT.HasBloodDecal = true -- Should it spawn a decal when damaged?
ENT.BloodDecal = {} -- Decals to spawn when it's damaged
ENT.BloodDecalUseGMod = false -- Should it use the current default decals defined by Garry's Mod? | Only applies for certain blood types!
ENT.BloodDecalDistance = 150 -- Max distance blood decals can splatter
ENT.HasBloodParticle = true -- Should it spawn a particle when damaged?
ENT.BloodParticle = {} -- Particles to spawn when it's damaged
ENT.HasBloodPool = true -- Should a blood pool spawn by its corpse?
ENT.BloodPool = {} -- Blood pools to be spawned by the corpse
	-- ====== Immunity ====== --
ENT.GodMode = false -- Immune to everything
ENT.ForceDamageFromBosses = false -- Should it receive damage by bosses regardless of its immunities? | Bosses are attackers tagged with "VJ_ID_Boss"
ENT.AllowIgnition = true -- Can it be set on fire?
ENT.Immune_Bullet = false -- Immune to bullet damages
ENT.Immune_Melee = false -- Immune to melee damages (Ex: Slashes, stabs, punches, claws, crowbar, blunt attacks)
ENT.Immune_Explosive = false -- Immune to explosive damages (Ex: Grenades, rockets, bombs, missiles)
ENT.Immune_Dissolve = false -- Immune to dissolving damage (Ex: Combine ball)
ENT.Immune_Toxic = false -- Immune to toxic effect damages (Ex: Acid, poison, radiation, gas)
ENT.Immune_Fire = false -- Immune to fire / flame damages
ENT.Immune_Electricity = false -- Immune to electrical damages (Ex: Shocks, lasers, gravity gun)
ENT.Immune_Sonic = false -- Immune to sonic damages (Ex: Sound blasts)
	-- ====== Flinching ====== --
ENT.CanFlinch = false -- Can it flinch? | false = Don't flinch | true = Always flinch | "DamageTypes" = Flinch only from certain damages types
ENT.FlinchDamageTypes = {DMG_BLAST} -- Which types of damage types should it flinch from when "DamageTypes" is used?
ENT.FlinchChance = 16 -- Chance of flinching from 1 to x | 1 = Always flinch
ENT.FlinchCooldown = 5 -- How much time until it can flinch again? | false = Base auto calculates the duration
ENT.AnimTbl_Flinch = ACT_FLINCH_PHYSICS
ENT.FlinchHitGroupMap = false -- EXAMPLE: {{HitGroup = HITGROUP_HEAD, Animation = ACT_FLINCH_HEAD}, {HitGroup = HITGROUP_LEFTARM, Animation = ACT_FLINCH_LEFTARM}, {HitGroup = HITGROUP_RIGHTARM, Animation = ACT_FLINCH_RIGHTARM}, {HitGroup = HITGROUP_LEFTLEG, Animation = ACT_FLINCH_LEFTLEG}, {HitGroup = HITGROUP_RIGHTLEG, Animation = ACT_FLINCH_RIGHTLEG}}
ENT.FlinchHitGroupPlayDefault = true -- Should it play "self.AnimTbl_Flinch" when none of the mapped hit groups hit?
	-- ====== Non-Combat Damage Response Behaviors ====== --
	-- For passive behavior NPC, these responses will run regardless if it has an active enemy or not
ENT.DamageResponse = true -- Should it respond to damages while it has no enemy?
	-- true = Search for enemies or run to a covered position | "OnlyMove" = Will only run to a covered position | "OnlySearch" = Will only search for enemies
ENT.DamageAllyResponse = true -- Should allies respond when it's damaged while it has no enemy?
ENT.AnimTbl_DamageAllyResponse = ACT_SIGNAL_GROUP -- Animations to play when it calls allies to respond | false = Don't play an animation
ENT.DamageAllyResponse_Cooldown = VJ.SET(9, 12) -- How long until it can call allies again?
	-- ====== Combat Damage Response Behaviors ====== --
	-- Hiding behind objects uses "self.AnimTbl_TakingCover"
ENT.CombatDamageResponse = true -- Should it respond to damages while it has an active enemy? | true = Hide behind an object if possible otherwise run to a covered position
ENT.CombatDamageResponse_CoverTime = VJ.SET(3, 5) -- If it found an object to hide behind, how long should it stay hidden?
ENT.CombatDamageResponse_Cooldown = VJ.SET(3, 3.5) -- How long until it can do any combat damage response?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Death & Corpse ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.DeathDelayTime = 0 -- Time until it spawns the corpse, removes itself, etc.
	-- ====== Ally Responses ====== --
	-- An ally must have "self.CanReceiveOrders" enabled to respond!
ENT.DeathAllyResponse = "OnlyAlert" -- How should allies response when it dies?
	-- false = No reactions | true = Allies respond by becoming alert and moving to its location | "OnlyAlert" = Allies respond by becoming alert
ENT.DeathAllyResponse_MoveLimit = 4 -- Max number of allies that can move to its location when responding to its death
	-- ====== Death Animation ====== --
	-- NOTE: This is added on top of "self.DeathDelayTime"
ENT.HasDeathAnimation = false -- Should it play death animations?
ENT.AnimTbl_Death = {}
ENT.DeathAnimationTime = false -- How long should the death animation play? | false = Base auto calculates the duration
ENT.DeathAnimationChance = 1 -- Put 1 if you want it to play the animation all the time
ENT.DeathAnimationDecreaseLengthAmount = 0 -- This will decrease the time until it turns into a corpse
	-- ====== Corpse ====== --
ENT.HasDeathCorpse = true -- Should a corpse spawn when it's killed?
ENT.DeathCorpseEntityClass = false -- Corpse's class | false = Let the base automatically detect the class
ENT.DeathCorpseModel = false -- Model(s) to use as the corpse | false = Use its current model | Can be a string or a table of strings
ENT.DeathCorpseCollisionType = COLLISION_GROUP_DEBRIS -- Collision type for the corpse | NPC Options Menu can only override this value if it's set to COLLISION_GROUP_DEBRIS!
ENT.DeathCorpseFade = false -- Should the corpse fade after the given amount of seconds? | false = Don't fade | number = Fade out time
ENT.DeathCorpseSetBoneAngles = true -- This can be used to stop the corpse glitching or flying on death
ENT.DeathCorpseApplyForce = true -- Should the force of the damage be applied to the corpse?
ENT.DeathCorpseSubMaterials = nil -- Apply a table of indexes that correspond to a sub material index, this will cause the base to copy the NPC's sub material to the corpse.
	-- ====== Dismemberment / Gib ====== --
ENT.CanGib = true -- Can it dismember? | Makes "CreateGibEntity" fail and overrides "CanGibOnDeath" to false
ENT.CanGibOnDeath = true -- Can it dismember on death?
ENT.GibOnDeathFilter = true -- Should it only gib and call "self:HandleGibOnDeath" when it's killed by a specific damage types? | false = Call "self:HandleGibOnDeath" from any damage type
ENT.HasGibOnDeathSounds = true -- Does it have gib sounds? | Mostly used for the settings menu
ENT.HasGibOnDeathEffects = true -- Does it spawn particles on death or when it gibs? | Mostly used for the settings menu
	-- ====== Drops On Death ====== --
ENT.DropWeaponOnDeath = true -- Should it drop its weapon on death?
ENT.DropDeathLoot = true -- Should it drop loot on death?
ENT.DeathLoot = {"weapon_frag", "item_healthvial"} -- List of entities it will randomly pick to drop | Leave it empty to drop nothing
ENT.DeathLootChance = 14 -- If set to 1, it will always drop loot
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Melee Attack ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.HasMeleeAttack = true
ENT.MeleeAttackDamage = 10
ENT.MeleeAttackDamageType = DMG_CLUB
ENT.HasMeleeAttackKnockBack = true -- Should knockback be applied on melee hit? | Use "MeleeAttackKnockbackVelocity" function to edit the velocity
ENT.DisableDefaultMeleeAttackDamageCode = false -- Disables the default melee attack damage code
	-- ====== Animation ====== --
ENT.AnimTbl_MeleeAttack = ACT_MELEE_ATTACK1 -- Animations to play when it melee attacks | false = Don't play an animation
ENT.MeleeAttackAnimationFaceEnemy = true -- Should it face the enemy while playing the melee attack animation?
ENT.MeleeAttackAnimationDecreaseLengthAmount = 0 -- Decreases animation time | Use it to fix animations that have extra frames at the end
	-- ====== Distance ====== --
ENT.MeleeAttackDistance = false -- How close an enemy has to be to trigger a melee attack | false = Auto calculate on initialize based on its collision bounds
ENT.MeleeAttackAngleRadius = 100 -- What is the attack angle radius? | 100 = In front of it | 180 = All around it
ENT.MeleeAttackDamageDistance = false -- How far does the damage go? | false = Auto calculate on initialize based on its collision bounds
ENT.MeleeAttackDamageAngleRadius = 100 -- What is the damage angle radius? | 100 = In front of it | 180 = All around it
	-- ====== Timer ====== --
ENT.TimeUntilMeleeAttackDamage = 0.5 -- How much time until it executes the damage? | false = Make the attack event-based
ENT.NextMeleeAttackTime = 0 -- How much time until it can use a melee attack? | number = Specific time | VJ.SET = Randomized between the 2 numbers
ENT.NextAnyAttackTime_Melee = false -- How much time until it can do any attack again? | false = Base auto calculates the duration | number = Specific time | VJ.SET = Randomized between the 2 numbers
ENT.MeleeAttackReps = 1 -- How many times does it run the melee attack code?
ENT.MeleeAttackExtraTimers = false -- Extra melee attack timers | EX: {1, 1.4}
ENT.MeleeAttackStopOnHit = false -- Should it stop executing the melee attack after it hits an enemy?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Grenade Attack ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.HasGrenadeAttack = false
ENT.GrenadeAttackEntity = "obj_vj_grenade" -- Entities that it can spawn when throwing a grenade | If set as a table, it picks a random entity | VJ: "obj_vj_grenade" | HL2: "npc_grenade_frag"
ENT.GrenadeAttackMinDistance = 400 -- Min distance it can throw a grenade
ENT.GrenadeAttackMaxDistance = 1500 -- Max distance it can throw a grenade
ENT.GrenadeAttackChance = 4 -- 1 in x chance that it will throw a grenade when all the requirements are met | 1 = Throw it every time
ENT.GrenadeAttackModel = false -- Overrides the grenade model | Can be string or table | Does NOT apply to picked up grenades and forced grenade attacks with custom entity
ENT.GrenadeAttackAttachment = "anim_attachment_LH" -- The attachment that the grenade will be set to | -1 = Skip to use "self.GrenadeAttackBone" instead
ENT.GrenadeAttackBone = "ValveBiped.Bip01_L_Finger1" -- The bone that the grenade will be set to | -1 = Skip to use fail safe instead
	-- ====== Animation ====== --
ENT.AnimTbl_GrenadeAttack = "grenThrow" -- Animations to play when it throws a grenade | false = Don't play an animation
ENT.GrenadeAttackAnimationFaceEnemy = true -- Should it face the enemy while playing the grenade attack animation?
	-- ====== Timer ====== --
ENT.GrenadeAttackThrowTime = 0.72 -- Time until the grenade is thrown | false = Make the attack event-based
ENT.NextGrenadeAttackTime = VJ.SET(10, 15) -- Time until it can do a grenade attack again | number = Specific time | VJ.SET = Randomized between the 2 numbers
ENT.NextAnyAttackTime_Grenade = false -- How much time until it can do any attack again? | false = Base auto calculates the duration | number = Specific time | VJ.SET = Randomized between the 2 numbers
ENT.GrenadeAttackFuseTime = 3 -- Grenade's fuse time after it's thrown
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Weapon Attack ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.Weapon_Disabled = false -- Disable the ability for it to use weapons
ENT.Weapon_IgnoreSpawnMenu = false -- Should it ignore weapon overrides from the spawn menu?
ENT.Weapon_UnarmedBehavior = true -- Should it flee from enemies when it's unarmed?
ENT.Weapon_Accuracy = 1 -- Its accuracy with weapons, affects bullet spread! | x < 1 = Better accuracy | x > 1 = Worse accuracy
ENT.Weapon_CanMoveFire = true -- Can it fire its weapon while it's moving?
ENT.Weapon_Strafe = true -- Should it strafe around while firing a weapon?
ENT.Weapon_StrafeCooldown = VJ.SET(3, 6) -- How much time until it can strafe again?
ENT.Weapon_OcclusionDelay = true -- Should it wait before leaving its position to pursue the enemy after its been occluded?
ENT.Weapon_OcclusionDelayTime = VJ.SET(3, 5) -- How long should it wait before it starts to pursue?
ENT.Weapon_OcclusionDelayMinDist = 100 -- Skip this behavior if the occluded enemy is within this distance
	-- ====== Distance ====== --
ENT.Weapon_MinDistance = 10 -- Min distance it can fire a weapon
ENT.Weapon_MaxDistance = 3000 -- Max distance it can fire a weapon
ENT.Weapon_RetreatDistance = 150 -- Minimum distance an enemy has to be for it to retreat back | 0 = Never retreat
ENT.Weapon_AimTurnDiff = false -- Weapon aim turning threshold between 0 and 1 | "self.HasPoseParameterLooking" must be set to true!
	-- EXAMPLES: 0.707106781187 = 45 degrees | 0.866025403784 = 30 degrees | 1 = 0 degrees, always turn!
	-- false = Let base decide based on animation set and weapon hold type
	-- ====== Primary Fire ====== --
ENT.AnimTbl_WeaponAttack = ACT_RANGE_ATTACK1 -- Animations to play while firing a weapon
ENT.AnimTbl_WeaponAttackGesture = ACT_GESTURE_RANGE_ATTACK1 -- Gesture animations to play while firing a weapon | false = Don't play an animation
ENT.Weapon_CanCrouchAttack = true -- Can it crouch while firing a weapon?
ENT.Weapon_CrouchAttackChance = 2 -- What is the chance of it crouching? | 1 = Crouch whenever possible
ENT.AnimTbl_WeaponAttackCrouch = ACT_RANGE_ATTACK1_LOW -- Animations to play while firing a weapon in crouched position
	-- ====== Secondary Fire ====== --
ENT.Weapon_CanSecondaryFire = true -- Can it use a weapon's secondary fire if it's available?
ENT.Weapon_SecondaryFireTime = false -- How much time until the secondary fire's projectile is released | false = Base auto calculates the duration
ENT.AnimTbl_WeaponAttackSecondary = ACT_RANGE_ATTACK2 -- Animations to play while firing the weapon's secondary attack
	-- ====== Reloading ====== --
ENT.Weapon_CanReload = true -- Can it reload weapons?
ENT.Weapon_FindCoverOnReload = true -- Should it attempt to find cover before proceeding to reload?
ENT.AnimTbl_WeaponReload = ACT_RELOAD
ENT.AnimTbl_WeaponReloadCovered = ACT_RELOAD_LOW
ENT.DisableWeaponReloadAnimation = false -- Disables the default reload animation code
	-- ====== Weapon Inventory ====== --
	-- Weapons are given on spawn and it will only switch to those if the requirements are met
	-- All are stored in "self.WeaponInventory" with the following keys:
		-- Primary		: Default weapon
		-- AntiArmor	: Enemy is an armored tank/vehicle or a boss
		-- Melee		: Enemy is (very close and the NPC is out of ammo) OR (in melee attack distance) + NPC must have more than 25% health
ENT.WeaponInventory_AntiArmorList = false -- Anti-armor weapons to give on spawn | Can be table or string
ENT.WeaponInventory_MeleeList = false -- Melee weapons to give on spawn | Can be table or string
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Sound ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.HasSounds = true -- Can it play sounds? | false = Disable ALL sounds
ENT.DamageByPlayerDispositionLevel = 1 -- When should it play "DamageByPlayer" sounds? | 0 = Always | 1 = ONLY when friendly to player | 2 = ONLY when enemy to player
	-- ====== Footstep Sound ====== --
ENT.HasFootstepSounds = true -- Can it play footstep sounds?
ENT.DisableFootStepSoundTimer = false -- Disables the timer system, allowing to utilize model events
ENT.FootstepSoundTimerWalk = 0.5 -- Delay between footstep sounds while it is walking | false = Disable while walking
ENT.FootstepSoundTimerRun = 0.25 -- Delay between footstep sounds while it is running | false = Disable while running
	-- ====== Idle Sound ====== --
ENT.HasIdleSounds = true -- Can it play idle sounds? | Controls "self.SoundTbl_Idle", "self.SoundTbl_IdleDialogue", "self.SoundTbl_CombatIdle"
ENT.IdleSoundsWhileAttacking = false -- Can it play idle sounds while performing an attack?
ENT.IdleSoundsRegWhileAlert = false -- Should it disable playing regular idle sounds when combat idle sound is empty?
	-- ====== Idle Dialogue Sound ====== --
	-- When an allied NPC or player is within range, it will play these sounds rather than regular idle sounds
	-- If the ally is a VJ NPC and has dialogue answer sounds, it will respond back
ENT.HasIdleDialogueSounds = true -- Can it play idle dialogue sounds?
ENT.HasIdleDialogueAnswerSounds = true -- Can it play idle dialogue answer sounds?
ENT.IdleDialogueDistance = 400 -- How close should an ally be for it to initiate a dialogue
ENT.IdleDialogueCanTurn = true -- Should it turn to to face its dialogue target?
	-- ====== On Killed Enemy ====== --
ENT.HasKilledEnemySounds = true -- Can it play sounds when it kills an enemy?
ENT.KilledEnemySoundLast = true -- Should it only play "self.SoundTbl_KilledEnemy" if there is no enemies left?
	-- ====== Sound Track ====== --
ENT.HasSoundTrack = false -- Can it play sound tracks?
ENT.SoundTrackVolume = 1 -- Volume of the sound track | 1 = Normal | 2 = 200% | 0.5 = 50%
ENT.SoundTrackPlaybackRate = 1 -- Playback speed of sound tracks | 1 = Normal | 2 = Twice the speed | 0.5 = Half the speed
	-- ====== Other Sound Controls ====== --
ENT.HasBreathSound = true -- Can it play breathing sounds?
ENT.HasReceiveOrderSounds = true -- Can it play sounds when it receives an order?
ENT.HasFollowPlayerSounds = true -- Can it play follow and unfollow player sounds? | Controls "self.SoundTbl_FollowPlayer", "self.SoundTbl_UnFollowPlayer"
ENT.HasYieldToPlayerSounds = true -- Can it play sounds when it yields to an allied player?
ENT.HasMedicSounds = true -- Can it play medic sounds? | Controls "self.SoundTbl_MedicBeforeHeal", "self.SoundTbl_MedicOnHeal", "self.SoundTbl_MedicReceiveHeal"
ENT.HasOnPlayerSightSounds = true -- Can it play sounds when it sees a player?
ENT.HasInvestigateSounds = true -- Can it play sounds when it investigates something?
ENT.HasLostEnemySounds = true -- Can it play sounds when it looses its enemy?
ENT.HasAlertSounds = true -- Can it play alert sounds?
ENT.HasCallForHelpSounds = true -- Can it play sounds when it call allies for help?
ENT.HasBecomeEnemyToPlayerSounds = true -- Can it play sounds when it becomes hostile to an allied player?
ENT.HasSuppressingSounds = true -- Can it play weapon suppressing sounds?
ENT.HasWeaponReloadSounds = true -- Can it play weapon reload sounds?
ENT.HasMeleeAttackSounds = true -- Can it play melee attack sounds? | Controls "self.SoundTbl_BeforeMeleeAttack", "self.SoundTbl_MeleeAttack", "self.SoundTbl_MeleeAttackExtra"
ENT.HasExtraMeleeAttackSounds = true -- Can it play extra melee attack sound effects?
ENT.HasMeleeAttackMissSounds = true -- Can it play melee attack miss sounds?
ENT.HasGrenadeAttackSounds = true -- Can it play grenade attack sounds?
ENT.HasDangerSightSounds = true -- Can it play sounds with detects a danger? | Controls "self.SoundTbl_DangerSight", "self.SoundTbl_GrenadeSight"
ENT.HasAllyDeathSounds = true -- Can it play sounds when an ally dies?
ENT.HasPainSounds = true -- Can it play pain sounds?
ENT.HasImpactSounds = true -- Can it play impact sound effects?
ENT.HasDamageByPlayerSounds = true -- Can it play sounds when it's damaged by a player?
ENT.HasDeathSounds = true -- Can it play death sounds?
	-- ====== Sound Paths ====== --
	-- There are 2 types of sounds: "Speech" and "EFFECT" | Most sound tables are "SPEECH" unless stated
		-- SPEECH : Mostly play speech sounds | Will stop when another speech sound is played
		-- EFFECT : Mostly play sound effects | EX: Movement sound, impact sound, attack swipe sound, etc.
ENT.SoundTbl_SoundTrack = false
ENT.SoundTbl_FootStep = "VJ.Footstep.Human" -- EFFECT
ENT.SoundTbl_Breath = false -- EFFECT
ENT.SoundTbl_Idle = false
ENT.SoundTbl_IdleDialogue = false
ENT.SoundTbl_IdleDialogueAnswer = false
ENT.SoundTbl_CombatIdle = false
ENT.SoundTbl_ReceiveOrder = false
ENT.SoundTbl_FollowPlayer = false
ENT.SoundTbl_UnFollowPlayer = false
ENT.SoundTbl_YieldToPlayer = false
ENT.SoundTbl_MedicBeforeHeal = false
ENT.SoundTbl_MedicOnHeal = "items/smallmedkit1.wav" -- EFFECT
ENT.SoundTbl_MedicReceiveHeal = false
ENT.SoundTbl_OnPlayerSight = false
ENT.SoundTbl_Investigate = false
ENT.SoundTbl_LostEnemy = false
ENT.SoundTbl_Alert = false
ENT.SoundTbl_CallForHelp = false
ENT.SoundTbl_BecomeEnemyToPlayer = false
ENT.SoundTbl_Suppressing = false
ENT.SoundTbl_WeaponReload = false
ENT.SoundTbl_BeforeMeleeAttack = false
ENT.SoundTbl_MeleeAttack = false
ENT.SoundTbl_MeleeAttackExtra = "Flesh.ImpactHard" -- EFFECT
ENT.SoundTbl_MeleeAttackMiss = "Zombie.AttackMiss" -- EFFECT
ENT.SoundTbl_GrenadeAttack = false
ENT.SoundTbl_DangerSight = false
ENT.SoundTbl_GrenadeSight = false -- If empty it will play "self.SoundTbl_DangerSight"
ENT.SoundTbl_KilledEnemy = false
ENT.SoundTbl_AllyDeath = false
ENT.SoundTbl_Pain = false
ENT.SoundTbl_Impact = "Flesh.BulletImpact" -- EFFECT
ENT.SoundTbl_DamageByPlayer = false
ENT.SoundTbl_Death = false
	-- ====== Sound Chance ====== --
	-- Higher number = less chance of playing | 1 = Always play
ENT.IdleSoundChance = 3
ENT.IdleDialogueAnswerSoundChance = 1
ENT.CombatIdleSoundChance = 1
ENT.ReceiveOrderSoundChance = 1
ENT.FollowPlayerSoundChance = 1 -- Controls "self.SoundTbl_FollowPlayer", "self.SoundTbl_UnFollowPlayer"
ENT.YieldToPlayerSoundChance = 2
ENT.MedicBeforeHealSoundChance = 1
ENT.MedicOnHealSoundChance = 1
ENT.MedicReceiveHealSoundChance = 1
ENT.OnPlayerSightSoundChance = 1
ENT.InvestigateSoundChance = 1
ENT.LostEnemySoundChance = 1
ENT.AlertSoundChance = 1
ENT.CallForHelpSoundChance = 1
ENT.BecomeEnemyToPlayerChance = 1
ENT.BeforeMeleeAttackSoundChance = 1
ENT.MeleeAttackSoundChance = 1
ENT.ExtraMeleeSoundChance = 1
ENT.MeleeAttackMissSoundChance = 1
ENT.GrenadeAttackSoundChance = 1
ENT.DangerSightSoundChance = 1 -- Controls "self.SoundTbl_DangerSight", "self.SoundTbl_GrenadeSight"
ENT.SuppressingSoundChance = 2
ENT.WeaponReloadSoundChance = 1
ENT.KilledEnemySoundChance = 1
ENT.AllyDeathSoundChance = 4
ENT.PainSoundChance = 1
ENT.ImpactSoundChance = 1
ENT.DamageByPlayerSoundChance = 1
ENT.DeathSoundChance = 1
ENT.SoundTrackChance = 1
	-- ====== Timer ====== --
	-- Randomized time between the two variables, x amount of time has to pass for the sound to play again | Counted in seconds
	-- false = Base will decide the time
ENT.NextSoundTime_Breath = false
ENT.NextSoundTime_Idle = VJ.SET(8, 25)
ENT.NextSoundTime_Investigate = VJ.SET(5, 5)
ENT.NextSoundTime_LostEnemy = VJ.SET(5, 6)
ENT.NextSoundTime_Alert = VJ.SET(2, 3)
ENT.NextSoundTime_Suppressing = VJ.SET(7, 15)
ENT.NextSoundTime_KilledEnemy = VJ.SET(3, 5)
ENT.NextSoundTime_AllyDeath = VJ.SET(3, 5)
	-- ====== Sound Level ====== --
	-- The proper number are usually range from 0 to 180, though it can go as high as 511
	-- More Information: https://developer.valvesoftware.com/wiki/Soundscripts#SoundLevel_Flags
ENT.FootstepSoundLevel = 70
ENT.BreathSoundLevel = 60
ENT.IdleSoundLevel = 75
ENT.IdleDialogueSoundLevel = 75 -- Controls "self.SoundTbl_IdleDialogue", "self.SoundTbl_IdleDialogueAnswer"
ENT.CombatIdleSoundLevel = 80
ENT.ReceiveOrderSoundLevel = 80
ENT.FollowPlayerSoundLevel = 75 -- Controls "self.SoundTbl_FollowPlayer", "self.SoundTbl_UnFollowPlayer"
ENT.YieldToPlayerSoundLevel = 75
ENT.MedicBeforeHealSoundLevel = 75
ENT.MedicOnHealSoundLevel = 75
ENT.MedicReceiveHealSoundLevel = 75
ENT.OnPlayerSightSoundLevel = 75
ENT.InvestigateSoundLevel = 80
ENT.LostEnemySoundLevel = 75
ENT.AlertSoundLevel = 80
ENT.CallForHelpSoundLevel = 80
ENT.BecomeEnemyToPlayerSoundLevel = 75
ENT.BeforeMeleeAttackSoundLevel = 75
ENT.MeleeAttackSoundLevel = 75
ENT.ExtraMeleeAttackSoundLevel = 75
ENT.MeleeAttackMissSoundLevel = 75
ENT.SuppressingSoundLevel = 80
ENT.WeaponReloadSoundLevel = 80
ENT.GrenadeAttackSoundLevel = 80
ENT.DangerSightSoundLevel = 80 -- Controls "self.SoundTbl_DangerSight", "self.SoundTbl_GrenadeSight"
ENT.KilledEnemySoundLevel = 80
ENT.AllyDeathSoundLevel = 80
ENT.PainSoundLevel = 80
ENT.ImpactSoundLevel = 60
ENT.DamageByPlayerSoundLevel = 75
ENT.DeathSoundLevel = 80
	-- ====== Sound Pitch ====== --
	-- Range: 0 - 255 | Lower pitch < x > Higher pitch
ENT.MainSoundPitch = VJ.SET(90, 100) -- Can be a number or VJ.SET
ENT.MainSoundPitchStatic = true -- Should it decide a number on spawn and use it as the main pitch?
-- false = Use main pitch | number = Use a specific pitch | VJ.SET = Pick randomly between numbers every time it plays
ENT.FootstepSoundPitch = VJ.SET(80, 100)
ENT.BreathSoundPitch = 100
ENT.IdleSoundPitch = false
ENT.IdleDialogueSoundPitch = false -- Controls "self.SoundTbl_IdleDialogue", "self.SoundTbl_IdleDialogueAnswer"
ENT.CombatIdleSoundPitch = false
ENT.ReceiveOrderSoundPitch = false
ENT.FollowPlayerPitch = false -- Controls "self.SoundTbl_FollowPlayer", "self.SoundTbl_UnFollowPlayer"
ENT.YieldToPlayerSoundPitch = false
ENT.MedicBeforeHealSoundPitch = false
ENT.MedicOnHealSoundPitch = 100
ENT.MedicReceiveHealSoundPitch = false
ENT.OnPlayerSightSoundPitch = false
ENT.InvestigateSoundPitch = false
ENT.LostEnemySoundPitch = false
ENT.AlertSoundPitch = false
ENT.CallForHelpSoundPitch = false
ENT.BecomeEnemyToPlayerPitch = false
ENT.BeforeMeleeAttackSoundPitch = false
ENT.MeleeAttackSoundPitch = VJ.SET(95, 100)
ENT.ExtraMeleeSoundPitch = VJ.SET(80, 100)
ENT.MeleeAttackMissSoundPitch = VJ.SET(90, 100)
ENT.SuppressingPitch = false
ENT.WeaponReloadSoundPitch = false
ENT.GrenadeAttackSoundPitch = false
ENT.DangerSightSoundPitch = false -- Controls "self.SoundTbl_DangerSight", "self.SoundTbl_GrenadeSight"
ENT.KilledEnemySoundPitch = false
ENT.AllyDeathSoundPitch = false
ENT.PainSoundPitch = false
ENT.ImpactSoundPitch = VJ.SET(80, 100)
ENT.DamageByPlayerPitch = false
ENT.DeathSoundPitch = false
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Customization Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Use the functions below to customize parts of the NPC or add new systems without overriding parts of the base
-- Some base functions don't have a hook because you can simply override them | Call "self.BaseClass.FuncName(self)" or "baseclass.Get(baseName)" to run the base code as well
local PICK = VJ.PICK
--
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:PreInit() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:Init()
	-- Collision bounds of the NPC | NOTE: Both Xs and Ys should be the same! | To view: "cl_ent_bbox"
	-- self:SetCollisionBounds(Vector(50, 50, 100), Vector(-50, -50, 0))
	
	-- Damage bounds of the NPC | NOTE: Both Xs and Ys should be the same! | To view: "cl_ent_absbox"
	-- self:SetSurroundingBounds(Vector(150, 150, 200), Vector(-150, -150, 0))
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnThink() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnThinkActive() end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called at the end of every entity it checks every process time
-- NOTE: "calculatedDisp" can in some cases be nil
-- function ENT:OnMaintainRelationships(ent, calculatedDisp, entDist) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE
-- function ENT:OnUpdatePoseParamTracking(pitch, yaw, roll) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called from the engine
-- function ENT:ExpressionFinished(strExp) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called whenever "VJ.CreateSound" or "VJ.EmitSound" is called | return a new file path to replace the one that is about to play
-- function ENT:OnPlaySound(sdFile) return "example/sound.wav" end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called whenever a sound starts playing through "VJ.CreateSound"
-- function ENT:OnCreateSound(sdData, sdFile) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called whenever a sound starts playing through "VJ.EmitSound"
-- function ENT:OnEmitSound(sdFile) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called every time "self:FireBullets" is called
-- function ENT:OnFireBullet(data) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called whenever something collides with the NPC
-- function ENT:OnTouch(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called from the engine
-- function ENT:OnCondition(cond) VJ.DEBUG_Print(self, "OnCondition", cond, " = ", self:ConditionName(cond)) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE
-- function ENT:OnInput(key, activator, caller, data) VJ.DEBUG_Print(self, "OnInput", key, activator, caller, data) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE
-- local getEventName = util.GetAnimEventNameByID
-- --
-- function ENT:OnAnimEvent(ev, evTime, evCycle, evType, evOptions)
-- 	local eventName = getEventName(ev)
-- 	VJ.DEBUG_Print(self, "OnAnimEvent", eventName, ev, evTime, evCycle, evType, evOptions)
-- end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Called whenever the NPC begins following or stops following an entity
		- status = Type of call:
			- "Start"	= NPC is now following the given entity
			- "Stop"	= NPC is now unfollowing the given entity
		- ent = The entity that the NPC is now following or unfollowing
-----------------------------------------------------------]]
function ENT:OnFollow(status, ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Called every time a change occurs in the eating system
		- ent = The entity that it is checking OR speaking with
		- status = Type of update that is occurring, holds one of the following states:
			- "CheckEnt"	= Possible friendly entity found, should we speak to it? | return anything other than true to skip and not speak to this entity!
			- "Speak"		= Everything passed, start speaking
			- "Answer"		= Another entity has spoken to me, answer back! | return anything other than true to not play an answer back dialogue!
		- statusData = Some status may have extra info, possible infos:
			- For "CheckEnt"	= Boolean value, whether or not the entity can answer back
			- For "Speak"		= Duration of our sentence
	Returns
		- ONLY used for "CheckEnt" & "Answer" | Check above for what each status return does
-----------------------------------------------------------]]
function ENT:OnIdleDialogue(ent, status, statusData) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called whenever the medic behavior updates

=-=-=| PARAMETERS |=-=-=
	1. status [string] : Type of update that is occurring, holds one of the following states:
		-> "BeforeHeal" : Right before it's about to heal an entity
				USAGE EXAMPLES -> Play chain of animations | Additional sound effect
				PARAMETERS
					2. statusData [nil]
				RETURNS
					-> [nil]
		-> "OnHeal" : When the timer expires and is about to give health
				USAGE EXAMPLES -> Override healing code | Play an after heal animation
				PARAMETERS
					2. statusData [entity] : The entity that it's about to heal
				RETURNS
					-> [bool] : Returning false will NOT update entity's health and will NOT clear its decals (Useful for custom code)
		-> "OnReset" : When the behavior ends OR has to move because entity moved
				USAGE EXAMPLES -> Cleanup bodygroups | Play a sound
				PARAMETERS
					2. statusData [string] : Holds one of the following states:
						--> "Retry" : When it attempts to retry healing the entity, such as when the entity moved away so it has to chase again
						--> "End" : When the medic behavior exits completely
				RETURNS
					-> [nil]
	2. statusData [nil | entity | string] : Depends on `status` value, refer to it for more details

=-=-=| RETURNS |=-=-=
	-> [nil | bool] : Depends on `status` value, refer to it for more details
--]]
function ENT:OnMedicBehavior(status, statusData) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnPlayerSight(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	UNCOMMENT TO USE | Called every time footstep sound plays
		- moveType = Type of movement | Types: "Walk", "Run", "Event"
		- sdFile = Sound that it just played
-----------------------------------------------------------]]
-- function ENT:OnFootstepSound(moveType, sdFile) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	UNCOMMENT TO USE | Called when the NPC detects a danger
		- dangerType = Type of danger detected | Enum: VJ.NPC_DANGER_TYPE_*
		- data = Danger / grenade entity for types "DANGER_TYPE_ENTITY" and "DANGER_TYPE_GRENADE"
			-- Currently empty for danger type "DANGER_TYPE_HINT"
-----------------------------------------------------------]]
-- function ENT:OnDangerDetected(dangerType, data) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnInvestigate(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnResetEnemy() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnAlert(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- "ally" = Ally that we called for help
-- "isFirst" = Is this the first ally that received this call? Use this to avoid running certain multiple times when many allies are around!
function ENT:OnCallForHelp(ally, isFirst) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	UNCOMMENT TO USE | Called constantly on think as long as it can attack and has an enemy
	This can be used to create a completely new attack system OR switch between multiple attacks (such as multiple melee attacks with varying distances)
		1. isAttacking [boolean] : Whether or not the base has detected that performing an attacking
		2. enemy [entity] : Current active enemy
-----------------------------------------------------------]]
function ENT:OnThinkAttack(isAttacking, enemy) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when melee attack is triggered

=-=-=| PARAMETERS |=-=-=
	1. status [string] : Type of update that is occurring, holds one of the following states:
		-> "PreInit" : Before the attack is initialized | Before anything is set, useful to prevent the attack completely
			RETURNS
				-> [nil | boolean] : Return true to prevent the attack from being triggered
		-> "Init" : When the attack initially starts | Before sound, timers, and animations are set!
			RETURNS
				-> [nil]
		-> "PostInit" : After the sound, timers, and animations are set!
			RETURNS
				-> [nil]
	2. enemy [entity] : Enemy that caused the attack to trigger

=-=-=| RETURNS |=-=-=
	-> [nil | boolean] : Depends on `status` value, refer to it for more details
--]]
function ENT:OnMeleeAttack(status, enemy) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:MeleeAttackTraceOrigin()
	return (IsValid(self:GetEnemy()) and VJ.GetNearestPositions(self, self:GetEnemy(), true)) or self:GetPos() + self:GetForward()
end
---------------------------------------------------------------------------------------------------------------------------------------------
-- "self.MeleeAttackDamageAngleRadius" uses this to determine the direction of the attack and if something is within the angle radius
function ENT:MeleeAttackTraceDirection()
	return self:GetHeadDirection()
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:MeleeAttackKnockbackVelocity(ent)
	return self:GetForward() * math.random(100, 140) + self:GetUp() * 10
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when melee attack is executed

=-=-=| PARAMETERS |=-=-=
	1. status [string] : Type of update that is occurring, holds one of the following states:
		-> "Init" : When the attack initially executed | Before entities are checked and damaged
			RETURNS
				-> [nil | boolean] : Return true to skip running the default execution (Useful for custom code)
		-> "PreDamage" : Right before the damage is applied to an entity
			PARAMETERS
				2. ent [entity] : The entity that is about to be damaged
				3. isProp [entity] : Is the entity detected as a prop?
			RETURNS
				-> [nil | boolean] : Return true to skip hitting this entity
		-> "Miss" : When the attack misses and doesn't hit anything
			RETURNS
				-> [nil]
	2. ent [nil | entity] : Depends on `status` value, refer to it for more details
	3. isProp [nil | entity] : Depends on `status` value, refer to it for more details

=-=-=| RETURNS |=-=-=
	-> [nil | boolean] : Depends on `status` value, refer to it for more details
--]]
function ENT:OnMeleeAttackExecute(status, ent, isProp) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnWeaponChange(newWeapon, oldWeapon, invSwitch) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnWeaponCanFire() end -- Return false to disallow firing the weapon
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnWeaponAttack() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnWeaponStrafe() end -- Return false to disable default behavior, cooldown will still apply!
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnWeaponReload() end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when grenade attack is triggered or grenade position is requested

=-=-=| PARAMETERS |=-=-=
	1. status [string] : Type of update that is occurring, holds one of the following states:
		-> "Init" : When the attack initially starts | Before sound, timers, and animations are set!
			USAGE EXAMPLES -> Change grenade attack sounds or make changes to "self.GrenadeAttackThrowTime"
			RETURNS
				-> [nil | boolean] : Return true to disallow throwing a grenade
		-> "PostInit" : After the sound, timers, and animations are set!
			RETURNS
				-> [nil]
		-> "SpawnPos" : When the spawn position is requested
			USAGE EXAMPLES -> Override the spawn position if needed by returning a vector
			RETURNS
				-> [nil] : Do NOT override the spawn position
				-> [vector] : Override the spawn position
	2. overrideEnt [nil | string | entity] : string or entity if the grenade attack was triggered through an override
		-> [nil] : Using the default grenade class set by "self.GrenadeAttackEntity" | DEFAULT
		-> [string] : Using the given class name as an override
		-> [entity] : Using an existing entity as an override | EX: When the NPC is throwing back an enemy grenade
	3. landDir [string | vector] : Direction the grenade should land, used to align where the grenade should land
		-> "Enemy" : Use enemy's position
		-> "EnemyLastVis" : Use enemy's last visible position
		-> "FindBest" : Find the best random position
		-> [vector] : Use given vector

=-=-=| RETURNS |=-=-=
	-> [nil | vector | boolean] : Depends on `status` value, refer to it for more details
--]]
function ENT:OnGrenadeAttack(status, overrideEnt, landDir) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when grenade attack is executed

=-=-=| PARAMETERS |=-=-=
	1. status [string] : Type of update that is occurring, holds one of the following states:
		-> "PreSpawn" : Right before "Spawn()" is called on the grenade | Not called for grenade entity overrides, such as throwing back an enemy grenade
			RETURNS
				-> [nil]
		-> "PostSpawn" : After "Spawn()" is called on the grenade | Can be used to override the throw velocity or not apply it at all
			RETURNS
				-> [nil] : Apply the default velocity
				-> [vector] : Override the velocity to the given vector
				-> [boolean] : Return true to not apply any velocity
	2. grenade [nil | entity] : The grenade entity that is being thrown
	3. overrideEnt [nil | string | entity] : string or entity if the grenade attack was triggered through an override
		-> [nil] : Using the default grenade class set by "self.GrenadeAttackEntity" | DEFAULT
		-> [string] : Using the given class name as an override
		-> [entity] : Using an existing entity as an override | EX: When the NPC is throwing back an enemy grenade
	4. landDir [string | vector] : Direction the grenade should land, used to align where the grenade should land
		-> "Enemy" : Use enemy's position
		-> "EnemyLastVis" : Use enemy's last visible position
		-> "FindBest" : Find the best random position
		-> [vector] : Use given vector
	5. landingPos [nil | vector] : The position the grenade is aimed to land

=-=-=| RETURNS |=-=-=
	-> [nil | vector | boolean] : Depends on `status` value, refer to it for more details
--]]
function ENT:OnGrenadeAttackExecute(status, grenade, overrideEnt, landDir, landingPos) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnKilledEnemy(ent, inflictor, wasLast) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnAllyKilled(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
 Called whenever the NPC takes damage

=-=-=| PARAMETERS |=-=-=
	1. dmginfo [object] = CTakeDamageInfo object
	2. hitgroup [number] = The hitgroup that it hit
	3. status [string] : Type of update that is occurring, holds one of the following states:
		-> "Init" : First call on take damage, even before immune checks
		-> "PreDamage" : Right before the damage is applied to the NPC
		-> "PostDamage" : Right after the damage is applied to the NPC
--]]
function ENT:OnDamaged(dmginfo, hitgroup, status) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnBleed(dmginfo, hitgroup) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
 Called whenever the NPC attempts to play flinch

=-=-=| PARAMETERS |=-=-=
	1. dmginfo [object] = CTakeDamageInfo object
	2. hitgroup [number] = The hitgroup that it hit
	3. status [string] : Type of update that is occurring, holds one of the following states:
		-> "Init" : Before the animation is played or any values are set
				USAGE EXAMPLES -> Disallow flinch | Override the animation | Add a extra check
				RETURNS
					-> [nil | bool] : Return true to disallow the flinch from playing
		-> "Execute" : Right after the flinch animation starts playing and all the values are set
				RETURNS
					-> [nil]

=-=-=| RETURNS |=-=-=
	-> [nil | bool] : Depends on `status` value, refer to it for more details
--]]
function ENT:OnFlinch(dmginfo, hitgroup, status) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnBecomeEnemyToPlayer(dmginfo, hitgroup) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnSetEnemyFromDamage(dmginfo, hitgroup) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
 Called on death when the NPC is supposed to gib

=-=-=| PARAMETERS |=-=-=
	1. dmginfo [object] = CTakeDamageInfo object
	2. hitgroup [number] = The hitgroup that it hit

=-=-=| RETURNS |=-=-=
	-> [bool] : Notifies the base if the NPC gibbed or not
		- false : Spawns death corpse | Plays death animations | Does NOT play gib sounds
		- true : Disallows death corpse | Disallows death animations | Plays gib sounds
	-> [nil | table] : Overrides default actions, first return must be "true" for this to apply!
		- AllowCorpse : Allows death corpse to spawn | DEFAULT: false
		- AllowAnim : Allows death animations to play | DEFAULT: false
		- AllowSound : Allows default gib sounds to play | DEFAULT: true
		EXAMPLE:
			- {AllowCorpse = true} : Will spawn death corpse
--]]
function ENT:HandleGibOnDeath(dmginfo, hitgroup) return false end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
 Called when the NPC dies

=-=-=| PARAMETERS |=-=-=
	1. dmginfo [object] = CTakeDamageInfo object
	2. hitgroup [number] = The hitgroup that it hit
	3. status [string] : Type of update that is occurring, holds one of the following states:
		-> "Init" : First call when it dies before anything is changed or reset
		-> "DeathAnim" : Right before the death animation plays
		-> "Finish" : Right before the corpse is spawned, the active weapon is dropped and the NPC is removed
--]]
function ENT:OnDeath(dmginfo, hitgroup, status) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnDeathWeaponDrop(dmginfo, hitgroup, wepEnt) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnCreateDeathCorpse(dmginfo, hitgroup, corpse) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:CustomOnRemove() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:Controller_Initialize(ply, controlEnt)
	//ply:ChatPrint("CTRL + MOUSE2: Rocket Attack") -- Example key binding message
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:SetAnimationTranslations(wepHoldType)
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------ Combine ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	if self.AnimModelSet == VJ.ANIM_SET_COMBINE then
		if !self.Weapon_AimTurnDiff then self.Weapon_AimTurnDiff_Def = 0.71120220422745 end
		self.AnimationTranslations[ACT_RANGE_ATTACK2] 				= VJ.SequenceToActivity(self, "shootAR2alt")
		
		self.AnimationTranslations[ACT_COVER_LOW] 					= {ACT_COVER, "vjseq_Leanwall_CrouchLeft_A_idle", "vjseq_Leanwall_CrouchLeft_B_idle", "vjseq_Leanwall_CrouchLeft_C_idle", "vjseq_Leanwall_CrouchLeft_D_idle"}
		//self.AnimationTranslations[ACT_RELOAD] 					= ACT_RELOAD_SMG1 -- No need to translate, it's already the correct animation
		//self.AnimationTranslations[ACT_RELOAD_LOW] 				= ACT_RELOAD_SMG1_LOW -- No need to translate, it's already the correct animation
		
		self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RIFLE
		self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
		
		self.AnimationTranslations[ACT_RUN] 						= ACT_RUN_RIFLE
		self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_RUN_RIFLE
		self.AnimationTranslations[ACT_RUN_PROTECTED] 				= ACT_RUN_CROUCH_RIFLE
		self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RIFLE
		self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		
		if wepHoldType == "ar2" or wepHoldType == "smg" or wepHoldType == "rpg" then
			if wepHoldType == "ar2" then
				self.AnimationTranslations[ACT_RANGE_ATTACK1] 			= ACT_RANGE_ATTACK_AR2
				self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 	= ACT_GESTURE_RANGE_ATTACK_AR2
				self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 		= ACT_RANGE_ATTACK_AR2_LOW
				//self.AnimationTranslations[ACT_IDLE_ANGRY] 			= ACT_IDLE_ANGRY -- No need to translate, it's already the correct animation
			elseif wepHoldType == "smg" or wepHoldType == "rpg" then
				self.AnimationTranslations[ACT_RANGE_ATTACK1] 			= ACT_RANGE_ATTACK_SMG1
				self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 	= ACT_GESTURE_RANGE_ATTACK_SMG1
				self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 		= ACT_RANGE_ATTACK_SMG1_LOW
				self.AnimationTranslations[ACT_IDLE_ANGRY] 				= ACT_IDLE_ANGRY_SMG1
			end
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_IDLE_SMG1
			
			self.AnimationTranslations[ACT_WALK] 						= VJ.SequenceToActivity(self, "walkeasy_all")
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_WALK_RIFLE
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_RIFLE
		elseif wepHoldType == "pistol" or wepHoldType == "revolver" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_AR2
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_AR2
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_AR2_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= VJ.SequenceToActivity(self, "idle_unarmed")
			//self.AnimationTranslations[ACT_IDLE_ANGRY] 				= ACT_IDLE_ANGRY -- No need to translate, it's already the correct animation
			
			self.AnimationTranslations[ACT_WALK] 						= VJ.SequenceToActivity(self, "walkunarmed_all")
			//self.AnimationTranslations[ACT_WALK_AGITATED] 			= ACT_WALK_RIFLE -- No need uses same as ACT_WALK
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_RIFLE
		elseif wepHoldType == "crossbow" or wepHoldType == "shotgun" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_SHOTGUN
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= wepHoldType == "crossbow" and ACT_GESTURE_RANGE_ATTACK_AR2 or ACT_GESTURE_RANGE_ATTACK_SHOTGUN
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_SHOTGUN_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_IDLE_SMG1
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_IDLE_ANGRY_SHOTGUN
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_WALK_AIM_SHOTGUN
			//self.AnimationTranslations[ACT_WALK_AGITATED] 			= ACT_WALK_AIM_SHOTGUN -- No need uses same as ACT_WALK
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_SHOTGUN
			
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_SHOTGUN
		elseif wepHoldType == "melee" or wepHoldType == "melee2" or wepHoldType == "knife" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_MELEE_ATTACK1
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= false -- Don't play anything for melee!
			//self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 		= ACT_RANGE_ATTACK_SMG1_LOW -- Not used for melee
			
			self.AnimationTranslations[ACT_IDLE] 						= VJ.SequenceToActivity(self, "idle_unarmed")
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= VJ.SequenceToActivity(self, "idle_unarmed")
			
			self.AnimationTranslations[ACT_WALK] 						= VJ.SequenceToActivity(self, "walkunarmed_all")
			//self.AnimationTranslations[ACT_WALK_AGITATED] 			= ACT_WALK_AIM_SHOTGUN -- No need uses same as ACT_WALK
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_RIFLE
		else -- Unarmed!
			self.AnimationTranslations[ACT_IDLE] 						= VJ.SequenceToActivity(self, "idle_unarmed")
			self.AnimationTranslations[ACT_WALK] 						= VJ.SequenceToActivity(self, "walkunarmed_all")
			//self.AnimationTranslations[ACT_WALK_AGITATED] 			= ACT_WALK_AIM_SHOTGUN -- No need uses same as ACT_WALK
		end
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------ Metrocop ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	elseif self.AnimModelSet == VJ.ANIM_SET_METROCOP then
		if !self.Weapon_AimTurnDiff then self.Weapon_AimTurnDiff_Def = 0.71120220422745 end
		
		//self.AnimationTranslations[ACT_RANGE_ATTACK2] 					= VJ.SequenceToActivity(self, "shootAR2alt") -- They don't have secondary animation!
		
		-- Do not translate crouch walking and also make the crouch running a walking one instead
		self.AnimationTranslations[ACT_RUN_CROUCH] 						= ACT_WALK_CROUCH
		
		if wepHoldType == "smg" or wepHoldType == "rpg" or wepHoldType == "ar2" or wepHoldType == "crossbow" or wepHoldType == "shotgun" then
			-- Note: Metrocops must use smg animation, they don't have any animations for AR2!
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_SMG1
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_SMG1
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_SMG1_LOW
			self.AnimationTranslations[ACT_RELOAD] 						= ACT_RELOAD_SMG1
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_COVER_SMG1_LOW
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= ACT_RELOAD_SMG1_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_IDLE_SMG1
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_IDLE_ANGRY_SMG1
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_WALK_RIFLE
			//self.AnimationTranslations[ACT_WALK_AGITATED] 			= ACT_WALK_RIFLE -- No need uses same as ACT_WALK
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_RIFLE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_RUN_RIFLE
			//self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_RUN_RIFLE -- No need uses same as ACT_RUN
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_RIFLE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == "pistol" or wepHoldType == "revolver" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_PISTOL
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_PISTOL
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_PISTOL_LOW
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_COVER_PISTOL_LOW
			self.AnimationTranslations[ACT_RELOAD] 						= ACT_RELOAD_PISTOL
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= ACT_RELOAD_PISTOL_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_IDLE_PISTOL
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_IDLE_ANGRY_PISTOL
			
			//self.AnimationTranslations[ACT_WALK] 						= ACT_WALK -- No need to translate
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_WALK_PISTOL
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_PISTOL
			//self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RIFLE -- No need to translate
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
			
			//self.AnimationTranslations[ACT_RUN] 						= ACT_RUN -- No need to translate
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_RUN_PISTOL
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_PISTOL
			//self.AnimationTranslations[ACT_RUN_CROUCH] 				= ACT_RUN_CROUCH_RIFLE -- No need to translate
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == "melee" or wepHoldType == "melee2" or wepHoldType == "knife" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_MELEE_ATTACK_SWING
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= false //ACT_MELEE_ATTACK_SWING_GESTURE -- Don't play anything!
			//self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 		= ACT_RANGE_ATTACK_SMG1_LOW -- Not used for melee
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_COWER
			//self.AnimationTranslations[ACT_RELOAD] 					= ACT_RELOAD_SMG1 -- Not used for melee
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= ACT_RELOAD_SMG1_LOW -- Not used for melee
			
			self.AnimationTranslations[ACT_IDLE] 						= {ACT_IDLE, ACT_IDLE, ACT_IDLE, ACT_IDLE, VJ.SequenceToActivity(self, "plazathreat1")}
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_IDLE_ANGRY_MELEE
			
			//self.AnimationTranslations[ACT_WALK] 						= ACT_WALK -- No need to translate
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_WALK_ANGRY
			//self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_RIFLE -- Not used for melee
			//self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RIFLE -- No need to translate
			//self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE -- Not used for melee
			
			//self.AnimationTranslations[ACT_RUN] 						= ACT_RUN -- No need to translate
			//self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_RUN -- No need to translate
			//self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_RIFLE -- Not used for melee
			//self.AnimationTranslations[ACT_RUN_CROUCH] 				= ACT_RUN_CROUCH_RIFLE -- No need to translate
			//self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 			= ACT_RUN_CROUCH_AIM_RIFLE -- Not used for melee
		end
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------ Rebel / Citizen ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	elseif self.AnimModelSet == VJ.ANIM_SET_REBEL then
		local isFemale = VJ.AnimExists(self, ACT_IDLE_ANGRY_PISTOL)
		if !self.Weapon_AimTurnDiff then self.Weapon_AimTurnDiff_Def = 0.78187280893326 end
		
		self.AnimationTranslations[ACT_RANGE_ATTACK2] 					= VJ.SequenceToActivity(self, "shoot_ar2_alt")
		
		-- Handguns use a different set!
		self.AnimationTranslations[ACT_COVER_LOW] 						= {ACT_COVER_LOW_RPG, ACT_COVER_LOW, "vjseq_coverlow_l", "vjseq_coverlow_r"}
		
		if wepHoldType == "ar2" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_AR2
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_AR2
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_AR2_LOW
			self.AnimationTranslations[ACT_RELOAD] 						= VJ.SequenceToActivity(self, "reload_ar2")
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= ACT_RELOAD_SMG1_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= PICK({VJ.SequenceToActivity(self, "idle_relaxed_ar2_1"), VJ.SequenceToActivity(self, "idle_alert_ar2_1"), VJ.SequenceToActivity(self, "idle_angry_ar2")})
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= VJ.SequenceToActivity(self, "idle_ar2_aim")
			
			self.AnimationTranslations[ACT_WALK] 						= PICK({VJ.SequenceToActivity(self, "walk_ar2_relaxed_all"), VJ.SequenceToActivity(self, "walkalerthold_ar2_all1"), VJ.SequenceToActivity(self, "walkholdall1_ar2")})
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= VJ.SequenceToActivity(self, "walkalerthold_ar2_all1")
			self.AnimationTranslations[ACT_WALK_AIM] 					= PICK({VJ.SequenceToActivity(self, "walkaimall1_ar2"), VJ.SequenceToActivity(self, "walkalertaim_ar2_all1")})
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RPG
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN] 						= PICK({VJ.SequenceToActivity(self, "run_alert_holding_ar2_all"), VJ.SequenceToActivity(self, "run_ar2_relaxed_all"), VJ.SequenceToActivity(self, "run_holding_ar2_all")})
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= PICK({VJ.SequenceToActivity(self, "run_alert_holding_ar2_all"), VJ.SequenceToActivity(self, "run_holding_ar2_all")})
			self.AnimationTranslations[ACT_RUN_AIM] 					= PICK({ACT_RUN_AIM_RIFLE, VJ.SequenceToActivity(self, "run_alert_aiming_ar2_all")})
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RPG
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == "smg" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_SMG1
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_SMG1
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_SMG1_LOW
			self.AnimationTranslations[ACT_RELOAD] 						= ACT_RELOAD_SMG1
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= ACT_RELOAD_SMG1_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= PICK({ACT_IDLE_SMG1_RELAXED, ACT_IDLE_SMG1_STIMULATED, ACT_IDLE_SMG1, VJ.SequenceToActivity(self, "idle_smg1_relaxed")})
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_IDLE_ANGRY_SMG1
			
			self.AnimationTranslations[ACT_WALK] 						= PICK({ACT_WALK_RIFLE_RELAXED, ACT_WALK_RIFLE_STIMULATED})
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_WALK_RIFLE
			self.AnimationTranslations[ACT_WALK_AIM] 					= PICK({ACT_WALK_AIM_RIFLE, ACT_WALK_AIM_RIFLE_STIMULATED})
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RIFLE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN] 						= PICK({ACT_RUN_RIFLE, ACT_RUN_RIFLE_STIMULATED, ACT_RUN_RIFLE_RELAXED})
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= PICK({ACT_RUN_RIFLE, ACT_RUN_RIFLE_STIMULATED})
			self.AnimationTranslations[ACT_RUN_AIM] 					= PICK({ACT_RUN_AIM_RIFLE, ACT_RUN_AIM_RIFLE_STIMULATED})
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RIFLE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == "crossbow" or wepHoldType == "shotgun" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_SHOTGUN
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_SHOTGUN
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_SMG1_LOW
			self.AnimationTranslations[ACT_RELOAD] 						= ACT_RELOAD_SHOTGUN
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= ACT_RELOAD_SMG1_LOW //ACT_RELOAD_SHOTGUN_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= PICK({ACT_IDLE_SHOTGUN_RELAXED, ACT_IDLE_SHOTGUN_STIMULATED})
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= VJ.SequenceToActivity(self, "idle_ar2_aim")
			
			self.AnimationTranslations[ACT_WALK] 						= PICK({VJ.SequenceToActivity(self, "walk_ar2_relaxed_all"), VJ.SequenceToActivity(self, "walkalerthold_ar2_all1"), VJ.SequenceToActivity(self, "walkholdall1_ar2")})
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= VJ.SequenceToActivity(self, "walkalerthold_ar2_all1")
			self.AnimationTranslations[ACT_WALK_AIM] 					= PICK({VJ.SequenceToActivity(self, "walkaimall1_ar2"), VJ.SequenceToActivity(self, "walkalertaim_ar2_all1")})
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RPG
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN] 						= PICK({VJ.SequenceToActivity(self, "run_alert_holding_ar2_all"), VJ.SequenceToActivity(self, "run_ar2_relaxed_all"), VJ.SequenceToActivity(self, "run_holding_ar2_all")})
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= PICK({VJ.SequenceToActivity(self, "run_alert_holding_ar2_all"), VJ.SequenceToActivity(self, "run_holding_ar2_all")})
			self.AnimationTranslations[ACT_RUN_AIM] 					= PICK({ACT_RUN_AIM_RIFLE, VJ.SequenceToActivity(self, "run_alert_aiming_ar2_all")})
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RPG
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == "rpg" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_RPG
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_RPG
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_SMG1_LOW
			self.AnimationTranslations[ACT_RELOAD] 						= ACT_RELOAD_SMG1
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= ACT_RELOAD_SMG1_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= PICK({ACT_IDLE_RPG, ACT_IDLE_RPG_RELAXED})
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_IDLE_ANGRY_RPG
			
			self.AnimationTranslations[ACT_WALK] 						= PICK({ACT_WALK_RPG, ACT_WALK_RPG_RELAXED})
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_WALK_RPG
			self.AnimationTranslations[ACT_WALK_AIM] 					= PICK({VJ.SequenceToActivity(self, "walkaimall1_ar2"), VJ.SequenceToActivity(self, "walkalertaim_ar2_all1")})
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RPG
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
			
			self.AnimationTranslations[ACT_RUN] 						= PICK({ACT_RUN_RPG, ACT_RUN_RPG_RELAXED})
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_RUN_RPG
			self.AnimationTranslations[ACT_RUN_AIM] 					= PICK({ACT_RUN_AIM_RIFLE, VJ.SequenceToActivity(self, "run_alert_aiming_ar2_all")})
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RPG
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == "pistol" or wepHoldType == "revolver" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_PISTOL
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_GESTURE_RANGE_ATTACK_PISTOL
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_RANGE_ATTACK_PISTOL_LOW
			self.AnimationTranslations[ACT_COVER_LOW] 					= {"crouchidle_panicked4", "vjseq_crouchidlehide"}
			self.AnimationTranslations[ACT_RELOAD] 						= ACT_RELOAD_PISTOL
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= isFemale and ACT_RELOAD_SMG1_LOW or ACT_RELOAD_PISTOL_LOW -- Only males have covered pistol reload
			
			self.AnimationTranslations[ACT_IDLE] 						= isFemale and ACT_IDLE_PISTOL or ACT_IDLE -- Only females have pistol idle animation
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= isFemale and ACT_IDLE_ANGRY_PISTOL or VJ.SequenceToActivity(self, "idle_ar2_aim") -- Only females have angry pistol animation
			
			//self.AnimationTranslations[ACT_WALK] 						= ACT_WALK -- No need to translate
			//self.AnimationTranslations[ACT_WALK_AGITATED] 			= ACT_WALK -- No need, same as ACT_WALK
			self.AnimationTranslations[ACT_WALK_AIM] 					= isFemale and ACT_WALK_AIM_PISTOL or PICK({VJ.SequenceToActivity(self, "walkaimall1_ar2"), VJ.SequenceToActivity(self, "walkalertaim_ar2_all1")})
			//self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RIFLE -- No need to translate
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE
			
			//self.AnimationTranslations[ACT_RUN] 						= ACT_RUN -- No need to translate
			//self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_RUN -- No need, same as ACT_RUN
			self.AnimationTranslations[ACT_RUN_AIM] 					= isFemale and ACT_RUN_AIM_PISTOL or VJ.SequenceToActivity(self, "run_alert_aiming_ar2_all")
			//self.AnimationTranslations[ACT_RUN_CROUCH] 				= ACT_RUN_CROUCH_RIFLE -- No need to translate
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == "melee" or wepHoldType == "melee2" or wepHoldType == "knife" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_MELEE_ATTACK_SWING
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= false -- Don't play anything!
			//self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 		= ACT_RANGE_ATTACK_SMG1_LOW -- Not used for melee
			self.AnimationTranslations[ACT_COVER_LOW] 					= {"crouchidle_panicked4", "vjseq_crouchidlehide"}
			//self.AnimationTranslations[ACT_RELOAD] 					= ACT_RELOAD_SMG1 -- Not used for melee
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= ACT_RELOAD_SMG1_LOW -- Not used for melee
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= isFemale and ACT_IDLE_ANGRY or ACT_IDLE_ANGRY_MELEE -- Only males have unique idle angry for melee weapons!
			
			//self.AnimationTranslations[ACT_WALK] 						= ACT_WALK -- No need to translate
			//self.AnimationTranslations[ACT_WALK_AGITATED] 			= ACT_WALK -- No need, same as ACT_WALK
			//self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_WALK_AIM_RIFLE -- Not used for melee
			//self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_WALK_CROUCH_RIFLE -- No need to translate
			//self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_WALK_CROUCH_AIM_RIFLE -- Not used for melee
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_RUN
			if !isFemale then -- Females don't have this sequence
				self.AnimationTranslations[ACT_RUN_AGITATED] 			= VJ.SequenceToActivity(self, "run_all_panicked")
			end
			//self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_RUN_AIM_RIFLE -- Not used for melee
			//self.AnimationTranslations[ACT_RUN_CROUCH] 				= ACT_RUN_CROUCH_RIFLE -- No need to translate
			//self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 			= ACT_RUN_CROUCH_AIM_RIFLE -- Not used for melee
		end
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------ Player ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	elseif self.AnimModelSet == VJ.ANIM_SET_PLAYER then
		if !self.Weapon_AimTurnDiff then self.Weapon_AimTurnDiff_Def = 0.61155587434769	end
		self.AnimationTranslations[ACT_COWER] 							= ACT_HL2MP_IDLE_COWER
		self.AnimationTranslations[ACT_RUN_PROTECTED] 					= ACT_HL2MP_RUN_PROTECTED
		
		if wepHoldType == "ar2" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_AR2
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_AR2
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_AR2
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE_PASSIVE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_AR2
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_AR2
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_AR2
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_AR2
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK_PASSIVE
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_AR2
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_AR2
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_AR2
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_PASSIVE
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_AR2
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_AR2
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_AR2
		elseif wepHoldType == "pistol" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_PISTOL
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_PISTOL
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_PISTOL
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_PISTOL
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_PISTOL
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_PISTOL
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_PISTOL
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_PISTOL
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_PISTOL
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_PISTOL
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_FAST
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_PISTOL
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_PISTOL
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_PISTOL
		elseif wepHoldType == "smg" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_SMG1
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_SMG1
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_smg1"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_smg1"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_SMG1
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE_PASSIVE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_SMG1
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_SMG1
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_SMG1
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_SMG1
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK_PASSIVE
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_SMG1
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_SMG1
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_SMG1
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_PASSIVE
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_SMG1
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_SMG1
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_SMG1
		elseif wepHoldType == "shotgun" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_SHOTGUN
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_SHOTGUN
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_shotgun"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_shotgun"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_SHOTGUN
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE_PASSIVE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_SHOTGUN
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_SHOTGUN
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_SHOTGUN
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_SHOTGUN
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK_PASSIVE
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_SHOTGUN
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_SHOTGUN
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_SHOTGUN
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_PASSIVE
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_SHOTGUN
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_SHOTGUN
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_SHOTGUN
		elseif wepHoldType == "rpg" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_RPG
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_RPG
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_RPG
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE_PASSIVE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_RPG
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_RPG
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_RPG
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_RPG
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK_PASSIVE
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_RPG
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_RPG
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_RPG
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_PASSIVE
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_RPG
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_RPG
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_RPG
		elseif wepHoldType == "physgun" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_PHYSGUN
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_PHYSGUN
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_PHYSGUN
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE_PASSIVE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_PHYSGUN
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_PHYSGUN
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_PHYSGUN
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_PHYSGUN
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK_PASSIVE
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_PHYSGUN
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_PHYSGUN
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_PHYSGUN
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_PASSIVE
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_PHYSGUN
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_PHYSGUN
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_PHYSGUN
		elseif wepHoldType == "crossbow" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_CROSSBOW
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_CROSSBOW
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_ar2"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_CROSSBOW
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE_PASSIVE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_CROSSBOW
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_CROSSBOW
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_CROSSBOW
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_CROSSBOW
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK_PASSIVE
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_CROSSBOW
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_CROSSBOW
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_CROSSBOW
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_PASSIVE
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_CROSSBOW
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_CROSSBOW
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH_PASSIVE
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_CROSSBOW
		elseif wepHoldType == "slam" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_SLAM
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_SLAM
			//self.AnimationTranslations[ACT_RELOAD] 					= "vjges_reload_pistol"
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_SLAM
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_SLAM
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_SLAM
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_SLAM
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_SLAM
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_SLAM
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_SLAM
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_SLAM
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_SLAM
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_SLAM
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_SLAM
		elseif wepHoldType == "duel" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_DUEL
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_DUEL
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_DUEL
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_duel"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_duel"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_DUEL
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_DUEL
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_DUEL
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_DUEL
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_DUEL
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_DUEL
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_DUEL
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_DUEL
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_DUEL
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_DUEL
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_DUEL
		elseif wepHoldType == "revolver" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_REVOLVER
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_REVOLVER
			self.AnimationTranslations[ACT_RELOAD] 						= "vjges_reload_revolver"
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= "vjges_reload_revolver"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_REVOLVER
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_REVOLVER
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_REVOLVER
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_REVOLVER
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_REVOLVER
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_REVOLVER
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_REVOLVER
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_REVOLVER
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_REVOLVER
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_REVOLVER
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_REVOLVER
		elseif wepHoldType == "melee" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_MELEE
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_MELEE
			//self.AnimationTranslations[ACT_RELOAD] 					= "vjges_reload_pistol"
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_MELEE
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_MELEE
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_MELEE
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_MELEE
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_MELEE
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_MELEE
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_MELEE
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_MELEE
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_MELEE
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_MELEE
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_MELEE
		elseif wepHoldType == "melee2" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_MELEE2
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE2
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_MELEE2
			//self.AnimationTranslations[ACT_RELOAD] 					= "vjges_reload_pistol"
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_MELEE2
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_MELEE2
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_MELEE2
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_MELEE2
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_MELEE2
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_MELEE2
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_MELEE2
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_MELEE2
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_MELEE2
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_MELEE2
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_MELEE2
		elseif wepHoldType == "knife" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_KNIFE
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_KNIFE
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_KNIFE
			//self.AnimationTranslations[ACT_RELOAD] 					= "vjges_reload_pistol"
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_KNIFE
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_KNIFE
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_KNIFE
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_KNIFE
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_KNIFE
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_KNIFE
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_KNIFE
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_KNIFE
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_KNIFE
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_KNIFE
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_KNIFE
		elseif wepHoldType == "grenade" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_GRENADE
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_GRENADE
			//self.AnimationTranslations[ACT_RELOAD] 					= "vjges_reload_pistol"
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_GRENADE
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_GRENADE
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_GRENADE
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_GRENADE
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_GRENADE
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_GRENADE
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_GRENADE
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_GRENADE
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_GRENADE
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_GRENADE
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_GRENADE
		elseif wepHoldType == "camera" then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_HL2MP_IDLE_CAMERA
			//self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= ACT_HL2MP_GESTURE_RANGE_ATTACK_CAMERA
			self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 			= ACT_HL2MP_IDLE_CROUCH_CAMERA
			//self.AnimationTranslations[ACT_RELOAD] 					= "vjges_reload_pistol"
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= "vjges_reload_pistol"
			self.AnimationTranslations[ACT_COVER_LOW] 					= ACT_HL2MP_IDLE_CROUCH_CAMERA
			
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_CAMERA
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_CAMERA
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_CAMERA
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_CAMERA
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= ACT_HL2MP_WALK_CAMERA
			self.AnimationTranslations[ACT_WALK_AIM] 					= ACT_HL2MP_WALK_CAMERA
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_WALK_CROUCH_AIM] 			= ACT_HL2MP_WALK_CROUCH_CAMERA
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= ACT_HL2MP_RUN_CAMERA
			self.AnimationTranslations[ACT_RUN_AIM] 					= ACT_HL2MP_RUN_CAMERA
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_HL2MP_WALK_CROUCH_CAMERA
		else -- Unarmed!
			self.AnimationTranslations[ACT_IDLE] 						= ACT_HL2MP_IDLE
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= ACT_HL2MP_IDLE_ANGRY
			self.AnimationTranslations[ACT_JUMP] 						= ACT_HL2MP_JUMP_PISTOL
			self.AnimationTranslations[ACT_GLIDE] 						= ACT_HL2MP_JUMP_PISTOL
			self.AnimationTranslations[ACT_LAND] 						= ACT_HL2MP_IDLE_PISTOL
			
			self.AnimationTranslations[ACT_WALK] 						= ACT_HL2MP_WALK
			self.AnimationTranslations[ACT_WALK_CROUCH] 				= ACT_HL2MP_WALK_CROUCH
			
			self.AnimationTranslations[ACT_RUN] 						= ACT_HL2MP_RUN_FAST
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_HL2MP_WALK_CROUCH
		end
	end
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ ///// WARNING: Don't touch anything below this line! \\\\\ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local defPos = Vector(0, 0, 0)

local StopSD = VJ.STOPSOUND
local CurTime = CurTime
local IsValid = IsValid
local GetConVar = GetConVar
local math_min = math.min
local math_max = math.max
local math_rad = math.rad
local math_cos = math.cos
local math_angApproach = math.ApproachAngle
local VJ_STATE_FREEZE = VJ_STATE_FREEZE
local VJ_STATE_ONLY_ANIMATION = VJ_STATE_ONLY_ANIMATION
local VJ_STATE_ONLY_ANIMATION_CONSTANT = VJ_STATE_ONLY_ANIMATION_CONSTANT
local VJ_STATE_ONLY_ANIMATION_NOATTACK = VJ_STATE_ONLY_ANIMATION_NOATTACK
local VJ_BEHAVIOR_PASSIVE = VJ_BEHAVIOR_PASSIVE
local VJ_BEHAVIOR_PASSIVE_NATURE = VJ_BEHAVIOR_PASSIVE_NATURE
local VJ_MOVETYPE_GROUND = VJ_MOVETYPE_GROUND
local VJ_MOVETYPE_AERIAL = VJ_MOVETYPE_AERIAL
local VJ_MOVETYPE_AQUATIC = VJ_MOVETYPE_AQUATIC
local VJ_MOVETYPE_STATIONARY = VJ_MOVETYPE_STATIONARY
local VJ_MOVETYPE_PHYSICS = VJ_MOVETYPE_PHYSICS
local ANIM_TYPE_GESTURE = VJ.ANIM_TYPE_GESTURE

local metaEntity = FindMetaTable("Entity")
local funcGetPoseParameter = metaEntity.GetPoseParameter
local funcSetPoseParameter = metaEntity.SetPoseParameter
--
local metaNPC = FindMetaTable("NPC")
local funcHasCondition = metaNPC.HasCondition

ENT.UpdatedPoseParam = false
ENT.Weapon_UnarmedBehavior_Active = false
ENT.WeaponEntity = NULL
ENT.WeaponState = VJ.WEP_STATE_READY
ENT.WeaponInventoryStatus = VJ.WEP_INVENTORY_NONE
ENT.AllowWeaponOcclusionDelay = true
ENT.WeaponLastShotTime = 0
ENT.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
ENT.WeaponAttackAnim = ACT_INVALID
ENT.Weapon_AimTurnDiff_Def = 1 -- Default value to use when "self.Weapon_AimTurnDiff" false, this is auto calculated depending on anim set and weapon hold type
ENT.NextWeaponAttackT = 0
ENT.NextWeaponAttackT_Base = 0 -- Handled by the base, used to avoid running shoot animation twice
ENT.NextWeaponStrafeT = 0
ENT.NextMeleeWeaponAttackT = 0
ENT.NextMoveOnGunCoveredT = 0
ENT.NextThrowGrenadeT = 0
ENT.NextGrenadeAttackSoundT = 0
ENT.NextSuppressingSoundT = 0
ENT.NextDangerDetectionT = 0
ENT.NextDangerSightSoundT = 0
ENT.NextCombatDamageResponseT = 0

local vj_npc_debug = GetConVar("vj_npc_debug")
local vj_npc_processtime = GetConVar("vj_npc_processtime")
local vj_npc_poseparams = GetConVar("vj_npc_poseparams")
local vj_npc_shadows = GetConVar("vj_npc_shadows")
local vj_npc_snd = GetConVar("vj_npc_snd")
local vj_npc_fri_base = GetConVar("vj_npc_fri_base")
local vj_npc_fri_player = GetConVar("vj_npc_fri_player")
local vj_npc_fri_antlion = GetConVar("vj_npc_fri_antlion")
local vj_npc_fri_combine = GetConVar("vj_npc_fri_combine")
local vj_npc_fri_zombie = GetConVar("vj_npc_fri_zombie")
local vj_npc_allies = GetConVar("vj_npc_allies")
local vj_npc_anim_death = GetConVar("vj_npc_anim_death")
local vj_npc_corpse = GetConVar("vj_npc_corpse")
local vj_npc_loot = GetConVar("vj_npc_loot")
local vj_npc_wander = GetConVar("vj_npc_wander")
local vj_npc_chase = GetConVar("vj_npc_chase")
local vj_npc_flinch = GetConVar("vj_npc_flinch")
local vj_npc_melee = GetConVar("vj_npc_melee")
local vj_npc_blood = GetConVar("vj_npc_blood")
local vj_npc_god = GetConVar("vj_npc_god")
local vj_npc_wep_reload = GetConVar("vj_npc_wep_reload")
local vj_npc_ply_betray = GetConVar("vj_npc_ply_betray")
local vj_npc_callhelp = GetConVar("vj_npc_callhelp")
local vj_npc_investigate = GetConVar("vj_npc_investigate")
local vj_npc_eat = GetConVar("vj_npc_eat")
local vj_npc_ply_follow = GetConVar("vj_npc_ply_follow")
local vj_npc_ply_chat = GetConVar("vj_npc_ply_chat")
local vj_npc_medic = GetConVar("vj_npc_medic")
local vj_npc_wep = GetConVar("vj_npc_wep")
local vj_npc_grenade = GetConVar("vj_npc_grenade")
local vj_npc_dangerdetection = GetConVar("vj_npc_dangerdetection")
local vj_npc_wep_drop = GetConVar("vj_npc_wep_drop")
local vj_npc_gib_vfx = GetConVar("vj_npc_gib_vfx")
local vj_npc_gib = GetConVar("vj_npc_gib")
local vj_npc_blood_gmod = GetConVar("vj_npc_blood_gmod")
local vj_npc_sight_xray = GetConVar("vj_npc_sight_xray")
local vj_npc_snd_gib = GetConVar("vj_npc_snd_gib")
local vj_npc_snd_track = GetConVar("vj_npc_snd_track")
local vj_npc_snd_footstep = GetConVar("vj_npc_snd_footstep")
local vj_npc_snd_idle = GetConVar("vj_npc_snd_idle")
local vj_npc_snd_breath = GetConVar("vj_npc_snd_breath")
local vj_npc_snd_alert = GetConVar("vj_npc_snd_alert")
local vj_npc_snd_danger = GetConVar("vj_npc_snd_danger")
local vj_npc_snd_melee = GetConVar("vj_npc_snd_melee")
local vj_npc_snd_pain = GetConVar("vj_npc_snd_pain")
local vj_npc_snd_death = GetConVar("vj_npc_snd_death")
local vj_npc_snd_plyfollow = GetConVar("vj_npc_snd_plyfollow")
local vj_npc_snd_plybetrayal = GetConVar("vj_npc_snd_plybetrayal")
local vj_npc_snd_plydamage = GetConVar("vj_npc_snd_plydamage")
local vj_npc_snd_plysight = GetConVar("vj_npc_snd_plysight")
local vj_npc_snd_medic = GetConVar("vj_npc_snd_medic")
local vj_npc_snd_wep_reload = GetConVar("vj_npc_snd_wep_reload")
local vj_npc_snd_grenade = GetConVar("vj_npc_snd_grenade")
local vj_npc_snd_wep_suppressing = GetConVar("vj_npc_snd_wep_suppressing")
local vj_npc_snd_callhelp = GetConVar("vj_npc_snd_callhelp")
local vj_npc_snd_receiveorder = GetConVar("vj_npc_snd_receiveorder")
local vj_npc_corpse_collision = GetConVar("vj_npc_corpse_collision")
local vj_npc_debug_engine = GetConVar("vj_npc_debug_engine")
local vj_npc_difficulty = GetConVar("vj_npc_difficulty")
local vj_npc_sight_distance = GetConVar("vj_npc_sight_distance")
local vj_npc_health = GetConVar("vj_npc_health")
local vj_npc_human_jump = GetConVar("vj_npc_human_jump")
local vj_npc_ply_frag = GetConVar("vj_npc_ply_frag")
local vj_npc_blood_pool = GetConVar("vj_npc_blood_pool")
local vj_npc_corpse_undo = GetConVar("vj_npc_corpse_undo")
local vj_npc_corpse_fade = GetConVar("vj_npc_corpse_fade")
local vj_npc_corpse_fadetime = GetConVar("vj_npc_corpse_fadetime")
local ai_serverragdolls = GetConVar("ai_serverragdolls")

---------------------------------------------------------------------------------------------------------------------------------------------
local function InitConvars(self)
	if vj_npc_debug:GetInt() == 1 then self.VJ_DEBUG = true end
	if vj_npc_poseparams:GetInt() == 0 && !self.OnUpdatePoseParamTracking then self.HasPoseParameterLooking = false end
	if vj_npc_shadows:GetInt() == 0 then self:DrawShadow(false) end
	if vj_npc_snd:GetInt() == 0 then self.HasSounds = false end
	if vj_npc_fri_base:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = "CLASS_VJ_BASE" end
	if vj_npc_fri_player:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = "CLASS_PLAYER_ALLY" end
	if vj_npc_fri_antlion:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = "CLASS_ANTLION" end
	if vj_npc_fri_combine:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = "CLASS_COMBINE" end
	if vj_npc_fri_zombie:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = "CLASS_ZOMBIE" end
	if vj_npc_allies:GetInt() == 0 then self.CanAlly = false end
	if vj_npc_anim_death:GetInt() == 0 then self.HasDeathAnimation = false end
	if vj_npc_corpse:GetInt() == 0 then self.HasDeathCorpse = false end
	if vj_npc_loot:GetInt() == 0 then self.DropDeathLoot = false end
	if vj_npc_wander:GetInt() == 0 then self.DisableWandering = true end
	if vj_npc_chase:GetInt() == 0 then self.DisableChasingEnemy = true end
	if vj_npc_flinch:GetInt() == 0 then self.CanFlinch = false end
	if vj_npc_melee:GetInt() == 0 then self.HasMeleeAttack = false end
	if vj_npc_blood:GetInt() == 0 then self.Bleeds = false end
	if vj_npc_god:GetInt() == 1 then self.GodMode = true end
	if vj_npc_wep_reload:GetInt() == 0 then self.Weapon_CanReload = false end
	if vj_npc_ply_betray:GetInt() == 0 then self.BecomeEnemyToPlayer = false end
	if vj_npc_callhelp:GetInt() == 0 then self.CallForHelp = false end
	if vj_npc_investigate:GetInt() == 0 then self.CanInvestigate = false end
	if vj_npc_eat:GetInt() == 0 then self.CanEat = false end
	if vj_npc_ply_follow:GetInt() == 0 then self.FollowPlayer = false end
	if vj_npc_ply_chat:GetInt() == 0 then self.CanChatMessage = false end
	if vj_npc_medic:GetInt() == 0 then self.IsMedic = false end
	if vj_npc_wep:GetInt() == 0 then self.Weapon_Disabled = true end
	if vj_npc_grenade:GetInt() == 0 then self.HasGrenadeAttack = false end
	if vj_npc_dangerdetection:GetInt() == 0 then self.CanDetectDangers = false end
	if vj_npc_wep_drop:GetInt() == 0 then self.DropWeaponOnDeath = false end
	if vj_npc_gib_vfx:GetInt() == 0 then self.HasGibOnDeathEffects = false end
	if vj_npc_gib:GetInt() == 0 then self.CanGib = false self.CanGibOnDeath = false end
	if vj_npc_blood_gmod:GetInt() == 1 then self.BloodDecalUseGMod = true end
	if vj_npc_sight_xray:GetInt() == 1 then self.SightAngle = 360 self.EnemyXRayDetection = true end
	if vj_npc_snd_gib:GetInt() == 0 then self.HasGibOnDeathSounds = false end
	if vj_npc_snd_track:GetInt() == 0 then self.HasSoundTrack = false end
	if vj_npc_snd_footstep:GetInt() == 0 then self.HasFootstepSounds = false end
	if vj_npc_snd_idle:GetInt() == 0 then self.HasIdleSounds = false end
	if vj_npc_snd_breath:GetInt() == 0 then self.HasBreathSound = false end
	if vj_npc_snd_alert:GetInt() == 0 then self.HasAlertSounds = false end
	if vj_npc_snd_danger:GetInt() == 0 then self.HasDangerSightSounds = false end
	if vj_npc_snd_melee:GetInt() == 0 then self.HasMeleeAttackSounds = false self.HasExtraMeleeAttackSounds = false self.HasMeleeAttackMissSounds = false end
	if vj_npc_snd_pain:GetInt() == 0 then self.HasPainSounds = false end
	if vj_npc_snd_death:GetInt() == 0 then self.HasDeathSounds = false end
	if vj_npc_snd_plyfollow:GetInt() == 0 then self.HasFollowPlayerSounds = false end
	if vj_npc_snd_plybetrayal:GetInt() == 0 then self.HasBecomeEnemyToPlayerSounds = false end
	if vj_npc_snd_plydamage:GetInt() == 0 then self.HasDamageByPlayerSounds = false end
	if vj_npc_snd_plysight:GetInt() == 0 then self.HasOnPlayerSightSounds = false end
	if vj_npc_snd_medic:GetInt() == 0 then self.HasMedicSounds = false end
	if vj_npc_snd_wep_reload:GetInt() == 0 then self.HasWeaponReloadSounds = false end
	if vj_npc_snd_grenade:GetInt() == 0 then self.HasGrenadeAttackSounds = false end
	if vj_npc_snd_wep_suppressing:GetInt() == 0 then self.HasSuppressingSounds = false end
	if vj_npc_snd_callhelp:GetInt() == 0 then self.HasCallForHelpSounds = false end
	if vj_npc_snd_receiveorder:GetInt() == 0 then self.HasReceiveOrderSounds = false end
	local corpseCollision = vj_npc_corpse_collision:GetInt()
	if corpseCollision != 0 && self.DeathCorpseCollisionType == COLLISION_GROUP_DEBRIS then
		if corpseCollision == 1 then
			self.DeathCorpseCollisionType = COLLISION_GROUP_NONE
		elseif corpseCollision == 2 then
			self.DeathCorpseCollisionType = COLLISION_GROUP_WORLD
		elseif corpseCollision == 3 then
			self.DeathCorpseCollisionType = COLLISION_GROUP_INTERACTIVE
		elseif corpseCollision == 4 then
			self.DeathCorpseCollisionType = COLLISION_GROUP_WEAPON
		elseif corpseCollision == 5 then
			self.DeathCorpseCollisionType = COLLISION_GROUP_PASSABLE_DOOR
		elseif corpseCollision == 6 then
			self.DeathCorpseCollisionType = COLLISION_GROUP_NONE
		end
	end
	-- Enables source engine debug overlays (some commands like 'npc_conditions' need it)
	if self.VJ_DEBUG && vj_npc_debug_engine:GetInt() == 1 then
		self:SetSaveValue("m_debugOverlays", bit.bor(0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000))
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
local function ApplyBackwardsCompatibility(self)
	-- !!!!!!!!!!!!!! DO NOT USE ANY OF THESE !!!!!!!!!!!!!! [Backwards Compatibility!]
	-- Most of these are pre-revamp variables & functions
	if self.CustomOnInitialize then self:CustomOnInitialize() end
	if self.CustomInitialize then self:CustomInitialize() end
	if self.CustomOn_PoseParameterLookingCode then self.OnUpdatePoseParamTracking = function(_, pitch, yaw, roll) self:CustomOn_PoseParameterLookingCode(pitch, yaw, roll) end end
	if self.CustomOnAlert then self.OnAlert = function(_, ent) self:CustomOnAlert(ent) end end
	if self.CustomOnInvestigate then self.OnInvestigate = function(_, ent) self:CustomOnInvestigate(ent) end end
	if self.CustomOnFootStepSound then self.OnFootstepSound = function(_, moveType, sdFile) self:CustomOnFootStepSound(moveType, sdFile) end end
	if self.CustomOnCallForHelp then self.OnCallForHelp = function(_, ally, isFirst) self:CustomOnCallForHelp(ally, isFirst) end end
	if self.CustomOnPlayerSight then self.OnPlayerSight = function(_, ent) self:CustomOnPlayerSight(ent) end end
	if self.CustomOnThink then self.OnThink = function() self:CustomOnThink() end end
	if self.CustomOnThink_AIEnabled then self.OnThinkActive = function() self:CustomOnThink_AIEnabled() end end
	if self.CustomOnTakeDamage_OnBleed then self.OnBleed = function(_, dmginfo, hitgroup) self:CustomOnTakeDamage_OnBleed(dmginfo, hitgroup) end end
	if self.CustomOnMoveRandomlyWhenShooting then self.OnWeaponStrafe = function() return self:CustomOnMoveRandomlyWhenShooting() end end
	if self.CustomOnAcceptInput then self.OnInput = function(_, key, activator, caller, data) self:CustomOnAcceptInput(key, activator, caller, data) end end
	if self.CustomOnHandleAnimEvent then self.OnAnimEvent = function(_, ev, evTime, evCycle, evType, evOptions) self:CustomOnHandleAnimEvent(ev, evTime, evCycle, evType, evOptions) end end
	if self.CustomOnWeaponReload then self.OnWeaponReload = function() self:CustomOnWeaponReload() end end
	if self.CustomOnWeaponAttack then self.OnWeaponAttack = function() self:CustomOnWeaponAttack() end end
	if self.CustomOnDropWeapon then self.OnDeathWeaponDrop = function(_, dmginfo, hitgroup, wepEnt) self:CustomOnDropWeapon(dmginfo, hitgroup, wepEnt) end end
	if self.CustomOnDeath_AfterCorpseSpawned then self.OnCreateDeathCorpse = function(_, dmginfo, hitgroup, corpse) self:CustomOnDeath_AfterCorpseSpawned(dmginfo, hitgroup, corpse) end end
	if self.PlayerFriendly == true then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = "CLASS_PLAYER_ALLY" end
	if self.HasHealthRegeneration then self.HealthRegenParams.Enabled = true end
	if self.HealthRegenerationAmount then self.HealthRegenParams.Amount = self.HealthRegenerationAmount end
	if self.HealthRegenerationDelay then self.HealthRegenParams.Delay = self.HealthRegenerationDelay end
	if self.HealthRegenerationResetOnDmg then self.HealthRegenParams.ResetOnDmg = self.HealthRegenerationResetOnDmg end
	if self.FriendsWithAllPlayerAllies != nil then self.AlliedWithPlayerAllies = self.FriendsWithAllPlayerAllies end
	if self.MoveRandomlyWhenShooting != nil then self.Weapon_Strafe = self.MoveRandomlyWhenShooting end
	if self.GrenadeAttackThrowDistance then self.GrenadeAttackMaxDistance = self.GrenadeAttackThrowDistance end
	if self.GrenadeAttackThrowDistanceClose then self.GrenadeAttackMinDistance = self.GrenadeAttackThrowDistanceClose end
	if self.NextThrowGrenadeTime != nil then self.NextGrenadeAttackTime = self.NextThrowGrenadeTime end
	if self.TimeUntilGrenadeIsReleased != nil then self.GrenadeAttackThrowTime = self.TimeUntilGrenadeIsReleased end
	if self.NextMoveRandomlyWhenShootingTime1 or self.NextMoveRandomlyWhenShootingTime2 then self.Weapon_StrafeCooldown = VJ.SET(self.NextMoveRandomlyWhenShootingTime1 or 3, self.NextMoveRandomlyWhenShootingTime2 or 6) end
	if self.WaitForEnemyToComeOut != nil then self.Weapon_OcclusionDelay = self.WaitForEnemyToComeOut end
	if self.WaitForEnemyToComeOutTime then self.Weapon_OcclusionDelayTime = self.WaitForEnemyToComeOutTime end
	if self.MoveOrHideOnDamageByEnemy != nil then self.CombatDamageResponse = self.MoveOrHideOnDamageByEnemy end
	if self.MoveOrHideOnDamageByEnemy_HideTime then self.CombatDamageResponse_CoverTime = self.MoveOrHideOnDamageByEnemy_HideTime end
	if self.Medic_CanBeHealed == false then self.VJ_ID_Healable = false end
	if self.DisableWeaponFiringGesture == true then self.AnimTbl_WeaponAttackGesture = false end
	if self.Immune_AcidPoisonRadiation != nil then self.Immune_Toxic = self.Immune_AcidPoisonRadiation end
	if self.Immune_Blast != nil then self.Immune_Explosive = self.Immune_Blast end
	if self.FindEnemy_CanSeeThroughWalls == true then self.EnemyXRayDetection = true end
	if self.DisableFindEnemy == true then self.EnemyDetection = false end
	if self.DisableTouchFindEnemy == true then self.EnemyTouchDetection = false end
	if self.HasFootStepSound then self.HasFootstepSounds = self.HasFootStepSound end
	if self.FootStepPitch then self.FootstepSoundPitch = self.FootStepPitch end
	if self.FootStepSoundLevel then self.FootstepSoundLevel = self.FootStepSoundLevel end
	if self.FootStepTimeWalk then self.FootstepSoundTimerWalk = self.FootStepTimeWalk end
	if self.FootStepTimeRun then self.FootstepSoundTimerRun = self.FootStepTimeRun end
	if self.HitGroupFlinching_Values then self.FlinchHitGroupMap = self.HitGroupFlinching_Values end
	if self.HitGroupFlinching_DefaultWhenNotHit != nil then self.FlinchHitGroupPlayDefault = self.HitGroupFlinching_DefaultWhenNotHit end
	if self.NextFlinchTime != nil then self.FlinchCooldown = self.NextFlinchTime end
	if self.NextCallForHelpTime then self.CallForHelpCooldown = self.NextCallForHelpTime end
	if self.CallForHelpAnimationFaceEnemy != nil then self.CallForHelpAnimFaceEnemy = self.CallForHelpAnimationFaceEnemy end
	if self.NextCallForHelpAnimationTime != nil then self.CallForHelpAnimCooldown = self.NextCallForHelpAnimationTime end
	if self.InvestigateSoundDistance != nil then self.InvestigateSoundMultiplier = self.InvestigateSoundDistance end
	if self.CanThrowBackDetectedGrenades != nil then self.CanRedirectGrenades = self.CanThrowBackDetectedGrenades end
	if self.SoundTbl_OnKilledEnemy != nil then self.SoundTbl_KilledEnemy = self.SoundTbl_OnKilledEnemy end
	if self.HasOnKilledEnemySounds != nil then self.HasKilledEnemySounds = self.HasOnKilledEnemySounds end
	if self.OnKilledEnemySoundChance then self.OnKilledEnemySoundChance = self.OnKilledEnemySoundChance end
	if self.NextSoundTime_OnKilledEnemy then self.NextSoundTime_KilledEnemy = self.NextSoundTime_OnKilledEnemy end
	if self.OnKilledEnemySoundLevel then self.KilledEnemySoundLevel = self.OnKilledEnemySoundLevel end
	if self.OnKilledEnemySoundPitch != nil then self.KilledEnemySoundPitch = self.OnKilledEnemySoundPitch end
	if self.IdleSounds_PlayOnAttacks != nil then self.IdleSoundsWhileAttacking = self.IdleSounds_PlayOnAttacks end
	if self.IdleSounds_NoRegularIdleOnAlerted != nil then self.IdleSoundsRegWhileAlert = self.IdleSounds_NoRegularIdleOnAlerted end
	if self.HasOnReceiveOrderSounds != nil then self.HasReceiveOrderSounds = self.HasOnReceiveOrderSounds end
	if self.SoundTbl_OnReceiveOrder != nil then self.SoundTbl_ReceiveOrder = self.SoundTbl_OnReceiveOrder end
	if self.OnReceiveOrderSoundChance != nil then self.ReceiveOrderSoundChance = self.OnReceiveOrderSoundChance end
	if self.OnReceiveOrderSoundLevel != nil then self.ReceiveOrderSoundLevel = self.OnReceiveOrderSoundLevel end
	if self.OnReceiveOrderSoundPitch != nil then self.ReceiveOrderSoundPitch = self.OnReceiveOrderSoundPitch end
	if self.OnGrenadeSightSoundLevel != nil then self.DangerSightSoundLevel = self.OnGrenadeSightSoundLevel end
	if self.SoundTbl_OnDangerSight != nil then self.SoundTbl_DangerSight = self.SoundTbl_OnDangerSight end
	if self.SoundTbl_OnGrenadeSight != nil then self.SoundTbl_GrenadeSight = self.SoundTbl_OnGrenadeSight end
	if self.SoundTbl_MedicAfterHeal != nil then self.SoundTbl_MedicOnHeal = self.SoundTbl_MedicAfterHeal end
	if self.MedicAfterHealSoundChance != nil then self.MedicOnHealSoundChance = self.MedicAfterHealSoundChance end
	if self.BeforeHealSoundLevel != nil then self.MedicBeforeHealSoundLevel = self.BeforeHealSoundLevel end
	if self.AfterHealSoundLevel != nil then self.MedicOnHealSoundLevel = self.AfterHealSoundLevel end
	if self.BeforeHealSoundPitch != nil then self.MedicBeforeHealSoundPitch = self.BeforeHealSoundPitch end
	if self.AfterHealSoundPitch != nil then self.MedicOnHealSoundPitch = self.AfterHealSoundPitch end
	if self.Immune_Physics then self:SetPhysicsDamageScale(0) end
	if self.StopMeleeAttackAfterFirstHit != nil then self.MeleeAttackStopOnHit = self.StopMeleeAttackAfterFirstHit end
	if self.DisableMeleeAttackAnimation == true then self.AnimTbl_MeleeAttack = false end
	if self.Weapon_FiringDistanceClose then self.Weapon_MinDistance = self.Weapon_FiringDistanceClose end
	if self.Weapon_FiringDistanceFar then self.Weapon_MaxDistance = self.Weapon_FiringDistanceFar end
	if self.DisableWeapons != nil then self.Weapon_Disabled = self.DisableWeapons end
	if self.Passive_RunOnDamage == false then self.DamageResponse = false end
	if self.HideOnUnknownDamage == false then self.DamageResponse = "OnlySearch" end
	if self.DisableTakeDamageFindEnemy == true then if self.HideOnUnknownDamage == false then self.DamageResponse = false else self.DamageResponse = "OnlyMove" end end
	if self.CanFlinch == 0 then self.CanFlinch = false end
	if self.CanFlinch == 1 then self.CanFlinch = true end
	if self.CanFlinch == 2 then self.CanFlinch = "DamageTypes" end
	if self.BringFriendsOnDeath != nil or self.AlertFriendsOnDeath != nil then
		if self.AlertFriendsOnDeath == true && (self.BringFriendsOnDeath == false or self.BringFriendsOnDeath == nil) then
			self.DeathAllyResponse = "OnlyAlert"
		elseif self.BringFriendsOnDeath == false && self.AlertFriendsOnDeath == false then
			self.DeathAllyResponse = false
		end
	end
	if self.BringFriendsOnDeathLimit then self.DeathAllyResponse_MoveLimit = self.BringFriendsOnDeathLimit end
	if self.VJC_Data then self.ControllerParams = self.VJC_Data end
	if self.HasCallForHelpAnimation == false then self.AnimTbl_CallForHelp = false end
	if self.Medic_DisableAnimation == true then self.AnimTbl_Medic_GiveHealth = false end
	if self.ConstantlyFaceEnemyDistance then self.ConstantlyFaceEnemy_MinDistance = self.ConstantlyFaceEnemyDistance end
	if self.CallForBackUpOnDamage != nil then self.DamageAllyResponse = self.CallForBackUpOnDamage end
	if self.NextCallForBackUpOnDamageTime then self.DamageAllyResponse_Cooldown = self.NextCallForBackUpOnDamageTime end
	if self.CallForBackUpOnDamageAnimation then self.AnimTbl_DamageAllyResponse = self.CallForBackUpOnDamageAnimation end
	if self.UseTheSameGeneralSoundPitch != nil then self.MainSoundPitchStatic = self.UseTheSameGeneralSoundPitch end
	if self.GeneralSoundPitch1 or self.GeneralSoundPitch2 then self.MainSoundPitch = VJ.SET(self.GeneralSoundPitch1 or 90, self.GeneralSoundPitch2 or 100) end
	if self.AlertedToIdleTime then self.AlertTimeout = self.AlertedToIdleTime end
	if self.SoundTbl_MoveOutOfPlayersWay then self.SoundTbl_YieldToPlayer = self.SoundTbl_MoveOutOfPlayersWay end
	if self.MaxJumpLegalDistance then self.JumpParams.MaxRise = self.MaxJumpLegalDistance.a; self.JumpParams.MaxDrop = self.MaxJumpLegalDistance.b end
	if self.VJ_IsHugeMonster then self.VJ_ID_Boss = self.VJ_IsHugeMonster end
	if self.Medic_HealthAmount then self.Medic_HealAmount = self.Medic_HealthAmount end
	if self.UsePlayerModelMovement then self.UsePoseParameterMovement = true end
	if self.MoveOutOfFriendlyPlayersWay != nil then self.YieldToAlliedPlayers = self.MoveOutOfFriendlyPlayersWay end
	if self.WaitBeforeDeathTime then self.DeathDelayTime = self.WaitBeforeDeathTime end
	if self.HasDeathRagdoll != nil then self.HasDeathCorpse = self.HasDeathRagdoll end
	if self.AllowedToGib != nil then self.CanGib = self.AllowedToGib end
	if self.HasGibOnDeath != nil then self.CanGibOnDeath = self.HasGibOnDeath end
	if self.HasGibDeathParticles != nil then self.HasGibOnDeathEffects = self.HasGibDeathParticles else self.HasGibDeathParticles = self.HasGibOnDeathEffects end
	if self.HasItemDropsOnDeath != nil then self.DropDeathLoot = self.HasItemDropsOnDeath end
	if self.ItemDropsOnDeathChance != nil then self.DeathLootChance = self.ItemDropsOnDeathChance end
	if self.ItemDropsOnDeath_EntityList != nil then self.DeathLoot = self.ItemDropsOnDeath_EntityList end
	if self.AllowMovementJumping != nil then self.JumpParams.Enabled = self.AllowMovementJumping end
	if self.HasShootWhileMoving == false then self.Weapon_CanMoveFire = false end
	if self.HasWeaponBackAway == false then self.Weapon_RetreatDistance = 0 end
	if self.WeaponBackAway_Distance then self.Weapon_RetreatDistance = self.WeaponBackAway_Distance end
	if self.WeaponSpread then self.Weapon_Accuracy = self.WeaponSpread end
	if self.AllowWeaponReloading != nil then self.Weapon_CanReload = self.AllowWeaponReloading end
	if self.WeaponReload_FindCover != nil then self.Weapon_FindCoverOnReload = self.WeaponReload_FindCover end
	if self.ThrowGrenadeChance then self.GrenadeAttackChance = self.ThrowGrenadeChance end
	if self.OnlyDoKillEnemyWhenClear != nil then self.KilledEnemySoundLast = self.OnlyDoKillEnemyWhenClear end
	if self.NoWeapon_UseScaredBehavior != nil then self.Weapon_UnarmedBehavior = self.NoWeapon_UseScaredBehavior end
	if self.CanCrouchOnWeaponAttack != nil then self.Weapon_CanCrouchAttack = self.CanCrouchOnWeaponAttack end
	if self.CanCrouchOnWeaponAttackChance != nil then self.Weapon_CrouchAttackChance = self.CanCrouchOnWeaponAttackChance end
	if self.AnimTbl_WeaponAttackFiringGesture != nil then self.AnimTbl_WeaponAttackGesture = self.AnimTbl_WeaponAttackFiringGesture end
	if self.CanUseSecondaryOnWeaponAttack != nil then self.Weapon_CanSecondaryFire = self.CanUseSecondaryOnWeaponAttack end
	if self.WeaponAttackSecondaryTimeUntilFire != nil then self.Weapon_SecondaryFireTime = self.WeaponAttackSecondaryTimeUntilFire end
	if self.DisableFootStepOnWalk then self.FootstepSoundTimerWalk = false end
	if self.DisableFootStepOnRun then self.FootstepSoundTimerRun = false end
	if self.FindEnemy_UseSphere then self.SightAngle = 360 end
	if self.IsMedicSNPC then self.IsMedic = self.IsMedicSNPC end
	if self.BecomeEnemyToPlayer == true then self.BecomeEnemyToPlayer = self.BecomeEnemyToPlayerLevel or 2 end
	if self.CustomBlood_Particle then self.BloodParticle = self.CustomBlood_Particle end
	if self.CustomBlood_Pool then self.BloodPool = self.CustomBlood_Pool end
	if self.CustomBlood_Decal then self.BloodDecal = self.CustomBlood_Decal end
	if self.GibOnDeathDamagesTable then
		for _, v in ipairs(self.GibOnDeathDamagesTable) do
			if v == "All" then
				self.GibOnDeathFilter = false
			end
		end
	end
	if self.SetUpGibesOnDeath then
		self.HandleGibOnDeath = function(_, dmginfo, hitgroup)
			local gibbed, overrides = self:SetUpGibesOnDeath(dmginfo, hitgroup)
			local tbl = {}
			if overrides then
				if overrides.AllowCorpse then tbl.AllowCorpse = true end
				if overrides.DeathAnim then tbl.AllowAnim = true end
			end
			if self.CustomGibOnDeathSounds && !self:CustomGibOnDeathSounds(dmginfo, hitgroup) then
				tbl.AllowSound = false
			end
			return gibbed, tbl
		end
	end
	if self.CustomOnDoKilledEnemy then
		self.OnKilledEnemy = function(_, ent, inflictor, wasLast)
			if (self.KilledEnemySoundLast == false) or (self.KilledEnemySoundLast == true && wasLast) then
				self:CustomOnDoKilledEnemy(ent, self, inflictor)
			end
		end
	end
	if self.CustomOnMedic_BeforeHeal or self.CustomOnMedic_OnHeal or self.CustomOnMedic_OnReset then
		self.OnMedicBehavior = function(_, status, statusData)
			if status == "BeforeHeal" && self.CustomOnMedic_BeforeHeal then
				self:CustomOnMedic_BeforeHeal()
			elseif status == "OnHeal" && self.CustomOnMedic_OnHeal then
				return self:CustomOnMedic_OnHeal(statusData)
			elseif status == "OnReset" && self.CustomOnMedic_OnReset then
				self:CustomOnMedic_OnReset()
			end
		end
	end
	if self.CustomOnTakeDamage_BeforeImmuneChecks or self.CustomOnTakeDamage_BeforeDamage or self.CustomOnTakeDamage_AfterDamage then
		self.OnDamaged = function(_, dmginfo, hitgroup, status)
			if status == "Init" && self.CustomOnTakeDamage_BeforeImmuneChecks then
				self:CustomOnTakeDamage_BeforeImmuneChecks(dmginfo, hitgroup)
			elseif status == "PreDamage" && self.CustomOnTakeDamage_BeforeDamage then
				self:CustomOnTakeDamage_BeforeDamage(dmginfo, hitgroup)
			elseif status == "PostDamage" && self.CustomOnTakeDamage_AfterDamage then
				self:CustomOnTakeDamage_AfterDamage(dmginfo, hitgroup)
			end
		end
	end
	if self.CustomOnFlinch_BeforeFlinch or self.CustomOnFlinch_AfterFlinch then
		self.OnFlinch = function(_, dmginfo, hitgroup, status)
			if status == "Init" then
				if self.CustomOnFlinch_BeforeFlinch then
					return !self:CustomOnFlinch_BeforeFlinch(dmginfo, hitgroup)
				end
			elseif status == "Execute" then
				if self.CustomOnFlinch_AfterFlinch then
					self:CustomOnFlinch_AfterFlinch(dmginfo, hitgroup)
				end
			end
		end
	end
	if self.CustomOnInitialKilled or self.CustomOnPriorToKilled or self.CustomDeathAnimationCode or self.CustomOnKilled or self.CustomOnDeath_BeforeCorpseSpawned then
		self.OnDeath = function(_, dmginfo, hitgroup, status)
			if status == "Init" then
				if self.CustomOnInitialKilled then
					self:CustomOnInitialKilled(dmginfo, hitgroup)
				end
				if self.CustomOnPriorToKilled then
					self:CustomOnPriorToKilled(dmginfo, hitgroup)
				end
			elseif status == "DeathAnim" && self.CustomDeathAnimationCode then
				self:CustomDeathAnimationCode(dmginfo, hitgroup)
			elseif status == "Finish" then
				if self.CustomOnKilled then
					self:CustomOnKilled(dmginfo, hitgroup)
				end
				if self.CustomOnDeath_BeforeCorpseSpawned then
					self:CustomOnDeath_BeforeCorpseSpawned(dmginfo, hitgroup)
				end
			end
		end
	end
	if self.HasWorldShakeOnMove && !self.OnFootstepSound then
		self.OnFootstepSound = function()
			util.ScreenShake(self:GetPos(), self.WorldShakeOnMoveAmplitude or 10, self.WorldShakeOnMoveFrequency or 100, self.WorldShakeOnMoveDuration or 0.4, self.WorldShakeOnMoveRadius or 1000)
		end
	end
	if self.DeathCorpseSkin && self.DeathCorpseSkin != -1 then
		local orgFunc = self.OnCreateDeathCorpse
		self.OnCreateDeathCorpse = function(_, dmginfo, hitgroup, corpse)
			orgFunc(self, dmginfo, hitgroup, corpse)
			corpse:SetSkin(self.DeathCorpseSkin)
		end
	end
	if self.CustomOnTouch then
		self.OnTouch = function(_, ent)
			self:CustomOnTouch(ent)
		end
	end
	if self.CustomAttack then
		self.OnThinkAttack = function(_, isAttacking, enemy)
			if self.CustomAttack then self:CustomAttack(enemy, self.EnemyData.Visible) end
		end
	end
	if self.CustomAttackCheck_MeleeAttack or self.CustomOnMeleeAttack_BeforeStartTimer or self.CustomOnMeleeAttack_AfterStartTimer then
		self.OnMeleeAttack = function(_, status, enemy)
			if status == "PreInit" && self.CustomAttackCheck_MeleeAttack then
				return !self:CustomAttackCheck_MeleeAttack(enemy)
			elseif status == "Init" && self.CustomOnMeleeAttack_BeforeStartTimer then
				self:CustomOnMeleeAttack_BeforeStartTimer(self.AttackSeed)
			elseif status == "PostInit" && self.CustomOnMeleeAttack_AfterStartTimer then
				self:CustomOnMeleeAttack_AfterStartTimer(self.AttackSeed)
			end
		end
	end
	if self.DisableDefaultMeleeAttackCode or self.MeleeAttackWorldShakeOnMiss or self.CustomOnMeleeAttack_BeforeChecks or self.CustomOnMeleeAttack_AfterChecks or self.CustomOnMeleeAttack_Miss then
		self.OnMeleeAttackExecute = function(_, status, ent, isProp)
			if status == "Init" && (self.CustomOnMeleeAttack_BeforeChecks or self.DisableDefaultMeleeAttackCode) then
				if self.CustomOnMeleeAttack_BeforeChecks then
					self:CustomOnMeleeAttack_BeforeChecks()
				end
				if self.DisableDefaultMeleeAttackCode then
					return true
				end
			elseif status == "PreDamage" && self.CustomOnMeleeAttack_AfterChecks then
				return self:CustomOnMeleeAttack_AfterChecks(ent, isProp)
			elseif status == "Miss" && (self.CustomOnMeleeAttack_Miss or self.MeleeAttackWorldShakeOnMiss) then
				if self.CustomOnMeleeAttack_Miss then
					self:CustomOnMeleeAttack_Miss()
				end
				if self.MeleeAttackWorldShakeOnMiss then
					util.ScreenShake(self:GetPos(), self.MeleeAttackWorldShakeOnMissAmplitude or 16, 100, self.MeleeAttackWorldShakeOnMissDuration or 1, self.MeleeAttackWorldShakeOnMissRadius or 2000)
				end
			end
		end
	end
	if self.GetMeleeAttackDamageOrigin then
		self.MeleeAttackTraceOrigin = function()
			return self:GetMeleeAttackDamageOrigin()
		end
	end
	-- !!!!!!!!!!!!!! DO NOT USE ANY OF THESE !!!!!!!!!!!!!! [Backwards Compatibility!]
end
---------------------------------------------------------------------------------------------------------------------------------------------
local defShootVec = Vector(0, 0, 55)
local capBitsDefault = bit.bor(CAP_SKIP_NAV_GROUND_CHECK, CAP_TURN_HEAD, CAP_DUCK)
local capBitsDoors = bit.bor(CAP_OPEN_DOORS, CAP_AUTO_DOORS, CAP_USE)
local capBitsWeapons = bit.bor(CAP_USE_WEAPONS, CAP_WEAPON_RANGE_ATTACK1)
--
function ENT:Initialize()
	self:PreInit()
	if self.CustomOnPreInitialize then self:CustomOnPreInitialize() end -- !!!!!!!!!!!!!! DO NOT USE !!!!!!!!!!!!!! [Backwards Compatibility!]
	
	self:SetSpawnEffect(false)
	self:SetRenderMode(RENDERMODE_NORMAL)
	self:AddEFlags(EFL_NO_DISSOLVE)
	self:SetUseType(SIMPLE_USE)
	if !self:GetModel() then
		local models = PICK(self.Model)
		if models then
			self:SetModel(models)
		end
	end
	self:SetHullType(self.HullType)
	self:SetHullSizeNormal()
	self:SetSolid(SOLID_BBOX)
	self:SetCollisionGroup(COLLISION_GROUP_NPC)
	self:SetMaxYawSpeed(self.TurningSpeed)
	self:SetSaveValue("m_HackedGunPos", defShootVec) -- Overrides the location of self:GetShootPos()
	
	-- Set a name if it doesn't have one
	if self:GetName() == "" then
		local findListing = list.Get("NPC")[self:GetClass()]
		if findListing then
			self:SetName((self.PrintName == "" and findListing.Name) or self.PrintName)
		end
	end
	
	-- Initialize variables
	InitConvars(self)
	self.NextProcessTime = vj_npc_processtime:GetInt()
	self.SelectedDifficulty = vj_npc_difficulty:GetInt()
	if !self.RelationshipEnts then self.RelationshipEnts = {} end
	if !self.RelationshipMemory then self.RelationshipMemory = {} end
	self.AnimationTranslations = {}
	self.WeaponInventory = {}
	self.NextIdleSoundT_Reg = CurTime() + math.random(0.3, 6)
	self.MainSoundPitchValue = (self.MainSoundPitchStatic and (istable(self.MainSoundPitch) and math.random(self.MainSoundPitch.a, self.MainSoundPitch.b) or self.MainSoundPitch)) or 0
	local sightConvar = vj_npc_sight_distance:GetInt(); if sightConvar > 0 then self.SightDistance = sightConvar end
	
	-- Capabilities & Movement
	self:DoChangeMovementType(self.MovementType)
	self:CapabilitiesAdd(capBitsDefault)
	if self.CanOpenDoors then self:CapabilitiesAdd(capBitsDoors) end
	-- Both of these attachments have to be valid for "ai_baseactor" to work properly!
	if self:LookupAttachment("eyes") > 0 && self:LookupAttachment("forward") > 0 then
		self:CapabilitiesAdd(CAP_ANIMATEDFACE)
	end
	if self.Behavior == VJ_BEHAVIOR_PASSIVE or self.Behavior == VJ_BEHAVIOR_PASSIVE_NATURE then
		self.Weapon_Disabled = true
		self.Weapon_IgnoreSpawnMenu = true
	elseif !self.Weapon_Disabled && !self.Weapon_IgnoreSpawnMenu then
		self:CapabilitiesAdd(capBitsWeapons)
	end
	
	-- Health
	local hpConvar = vj_npc_health:GetInt()
	local hp = hpConvar > 0 && hpConvar or self:ScaleByDifficulty(self.StartHealth)
	self:SetHealth(hp)
	self.StartHealth = hp
	
	self:Init()
	ApplyBackwardsCompatibility(self)
	
	-- Collision-based computations
	//self:SetSurroundingBoundsType(BOUNDS_HITBOXES) -- AVOID! Has to constantly recompute the bounds! | Issues: Entities get stuck inside the NPC, movements failing, unable to grab the NPC with physgun
	local collisionMin, collisionMax = self:GetCollisionBounds()
	-- Auto compute damage bounds if the damage bounds == collision bounds then the developer has NOT changed it | Call after "Init"
	if self:GetSurroundingBounds() == self:WorldSpaceAABB() then
		self:SetSurroundingBounds(Vector(collisionMin.x * 2, collisionMin.y * 2, collisionMin.z * 1.2), Vector(collisionMax.x * 2, collisionMax.y * 2, collisionMax.z * 1.2))
	end
	if !self.MeleeAttackDistance then self.MeleeAttackDistance = math.abs(collisionMax.x) + 30 end
	if !self.MeleeAttackDamageDistance then self.MeleeAttackDamageDistance = math.abs(collisionMax.x) + 60 end
	self:SetupBloodColor(self.BloodColor) -- Collision bounds dependent
	
	self.NextWanderTime = ((self.NextWanderTime != 0) and self.NextWanderTime) or (CurTime() + (self.IdleAlwaysWander and 0 or 1)) -- If self.NextWanderTime isn't given a value THEN if self.IdleAlwaysWander isn't true, wait at least 1 sec before wandering
	duplicator.RegisterEntityClass(self:GetClass(), VJ.CreateDupe_NPC, "Model", "Class", "Equipment", "SpawnFlags", "Data")
	
	-- Delayed init
	timer.Simple(0.1, function()
		if IsValid(self) then
			self:SetMaxLookDistance(self.SightDistance)
			self:SetFOV(self.SightAngle)
			if self:GetNPCState() <= NPC_STATE_NONE then self:SetNPCState(NPC_STATE_IDLE) end
			if IsValid(self:GetCreator()) && self:GetCreator():GetInfoNum("vj_npc_spawn_guard", 0) == 1 then self.IsGuard = true end
			self:StartSoundTrack()
			
			-- Setup common default pose parameters
			if self:LookupPoseParameter("aim_pitch") != -1 then
				self.PoseParameterLooking_Names.pitch[#self.PoseParameterLooking_Names.pitch + 1] = "aim_pitch"
			end
			if self:LookupPoseParameter("head_pitch") != -1 then
				self.PoseParameterLooking_Names.pitch[#self.PoseParameterLooking_Names.pitch + 1] = "head_pitch"
			end
			if self:LookupPoseParameter("aim_yaw") != -1 then
				self.PoseParameterLooking_Names.yaw[#self.PoseParameterLooking_Names.yaw + 1] = "aim_yaw"
			end
			if self:LookupPoseParameter("head_yaw") != -1 then
				self.PoseParameterLooking_Names.yaw[#self.PoseParameterLooking_Names.yaw + 1] = "head_yaw"
			end
			if self:LookupPoseParameter("aim_roll") != -1 then
				self.PoseParameterLooking_Names.roll[#self.PoseParameterLooking_Names.roll + 1] = "aim_roll"
			end
			if self:LookupPoseParameter("head_roll") != -1 then
				self.PoseParameterLooking_Names.roll[#self.PoseParameterLooking_Names.roll + 1] = "head_roll"
			end
			if self.Weapon_Disabled then
				self:UpdateAnimationTranslations()
			else
				local wep = self:GetActiveWeapon()
				if IsValid(wep) then
					self.WeaponEntity = self:DoChangeWeapon() -- Setup the weapon
					self.WeaponInventory.Primary = wep
					if !wep.IsVJBaseWeapon && self.CanChatMessage && IsValid(self:GetCreator()) then
						self:GetCreator():PrintMessage(HUD_PRINTTALK, "WARNING: " .. self:GetName() .. " requires a VJ Base weapon to work properly!")
					end
					local antiArmor = PICK(self.WeaponInventory_AntiArmorList)
					if antiArmor && wep:GetClass() != antiArmor then -- If the list isn't empty and it's not the current active weapon
						self.WeaponInventory.AntiArmor = self:Give(antiArmor)
						self:SelectWeapon(wep) -- Change the weapon back to the primary weapon
						wep:Equip(self)
					end
					local melee = PICK(self.WeaponInventory_MeleeList)
					if melee && wep:GetClass() != melee then -- If the list isn't empty and it's not the current active weapon
						self.WeaponInventory.Melee = self:Give(melee)
						self:SelectWeapon(wep) -- Change the weapon back to the primary weapon
						wep:Equip(self)
					end
				else
					self:UpdateAnimationTranslations()
					if IsValid(self:GetCreator()) && self.CanChatMessage && !self.Weapon_IgnoreSpawnMenu then
						self:GetCreator():PrintMessage(HUD_PRINTTALK, "WARNING: " .. self:GetName() .. " requires a weapon!")
					end
				end
			end
			if self:GetIdealActivity() == ACT_IDLE then -- Reset the idle animation in case animation translations changed it!
				self:MaintainIdleAnimation(true)
			end
			-- This is needed as setting "NextThink" to CurTime will cause performance drops, so we set the idle maintain in a separate hook that runs every tick
			local thinkHook = hook.GetTable()["Think"]
			if (thinkHook && !thinkHook[self]) or (!thinkHook) then
				local idleFunc = self.MaintainIdleAnimation
				if #self:GetBoneFollowers() > 0 then
					hook.Add("Think", self, function()
						if VJ_CVAR_AI_ENABLED then
							idleFunc(self)
						end
						self:UpdateBoneFollowers()
					end)
				else
					hook.Add("Think", self, function()
						if VJ_CVAR_AI_ENABLED then
							idleFunc(self)
						end
					end)
				end
			else
				VJ.DEBUG_Print(self, false, "warn", "has an existing embedded \"Think\" hook already, which is disallowing the default base hook from assigning. Make sure to handle \"MaintainIdleAnimation\" in the overridden hook!")
			end
		end
	end)
end
---------------------------------------------------------------------------------------------------------------------------------------------
local capBitsGround = bit.bor(CAP_MOVE_GROUND, CAP_MOVE_JUMP, CAP_MOVE_CLIMB, CAP_MOVE_SHOOT)
local capBitsShared = bit.bor(CAP_MOVE_GROUND, CAP_MOVE_JUMP, CAP_MOVE_CLIMB, CAP_MOVE_SHOOT, CAP_MOVE_FLY)
--
function ENT:DoChangeMovementType(movType)
	if movType then
		self.MovementType = movType
		if movType == VJ_MOVETYPE_GROUND then
			self:RemoveFlags(FL_FLY)
			self:CapabilitiesRemove(CAP_MOVE_FLY)
			self:SetNavType(NAV_GROUND)
			self:SetMoveType(MOVETYPE_STEP)
			self:CapabilitiesAdd(CAP_MOVE_GROUND)
			if (VJ.AnimExists(self, ACT_JUMP) && vj_npc_human_jump:GetInt() == 1) or self.UsePoseParameterMovement then self:CapabilitiesAdd(CAP_MOVE_JUMP) end
			//if VJ.AnimExists(self, ACT_CLIMB_UP) then self:CapabilitiesAdd(bit.bor(CAP_MOVE_CLIMB)) end
			if !self.Weapon_Disabled && self.Weapon_CanMoveFire then self:CapabilitiesAdd(CAP_MOVE_SHOOT) end
		elseif movType == VJ_MOVETYPE_AERIAL or movType == VJ_MOVETYPE_AQUATIC then
			self:CapabilitiesRemove(capBitsGround)
			self:SetGroundEntity(NULL)
			self:AddFlags(FL_FLY)
			self:SetNavType(NAV_FLY)
			self:SetMoveType(MOVETYPE_STEP) // MOVETYPE_FLY = causes issues like Lerp functions not being smooth
			self:CapabilitiesAdd(CAP_MOVE_FLY)
		elseif movType == VJ_MOVETYPE_STATIONARY then
			self:RemoveFlags(FL_FLY)
			self:CapabilitiesRemove(capBitsShared)
			self:SetNavType(NAV_NONE)
			if !IsValid(self:GetParent()) then -- Only set move type if it does NOT have a parent!
				self:SetMoveType(MOVETYPE_FLY)
			end
		elseif movType == VJ_MOVETYPE_PHYSICS then
			self:RemoveFlags(FL_FLY)
			self:CapabilitiesRemove(capBitsShared)
			self:SetNavType(NAV_NONE)
			self:SetMoveType(MOVETYPE_VPHYSICS)
		end
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
local schedule_alert_chaseLOS = vj_ai_schedule.New("SCHEDULE_ALERT_CHASE_LOS")
	schedule_alert_chaseLOS:EngTask("TASK_GET_PATH_TO_ENEMY_LOS", 0)
	//schedule_alert_chaseLOS:EngTask("TASK_RUN_PATH", 0)
	schedule_alert_chaseLOS:EngTask("TASK_WAIT_FOR_MOVEMENT", 0)
	//schedule_alert_chaseLOS:EngTask("TASK_FACE_ENEMY", 0)
	//schedule_alert_chaseLOS.ResetOnFail = true
	schedule_alert_chaseLOS.CanShootWhenMoving = true
	schedule_alert_chaseLOS.CanBeInterrupted = true
--
local schedule_alert_chase = vj_ai_schedule.New("SCHEDULE_ALERT_CHASE")
	schedule_alert_chase:EngTask("TASK_GET_PATH_TO_ENEMY", 0)
	schedule_alert_chase:EngTask("TASK_RUN_PATH", 0)
	schedule_alert_chase:EngTask("TASK_WAIT_FOR_MOVEMENT", 0)
	//schedule_alert_chase:EngTask("TASK_FACE_ENEMY", 0)
	//schedule_alert_chase.ResetOnFail = true
	schedule_alert_chase.CanShootWhenMoving = true
	schedule_alert_chase.CanBeInterrupted = true
--
function ENT:SCHEDULE_ALERT_CHASE(doLOSChase)
	self:ClearCondition(COND_ENEMY_UNREACHABLE)
	local moveType = self.MovementType; if moveType == VJ_MOVETYPE_AERIAL or moveType == VJ_MOVETYPE_AQUATIC then self:AA_ChaseEnemy() return end
	if self.CurrentScheduleName == "SCHEDULE_ALERT_CHASE" then return end // && (self:GetEnemyLastKnownPos():Distance(self:GetEnemy():GetPos()) <= 12)
	local navType = self:GetNavType(); if navType == NAV_JUMP or navType == NAV_CLIMB then return end
	if doLOSChase then
		schedule_alert_chaseLOS.RunCode_OnFinish = function()
			local ene = self:GetEnemy()
			if IsValid(ene) then
				self:RememberUnreachable(ene, 0)
				self:SCHEDULE_ALERT_CHASE(false)
			end
		end
		self:StartSchedule(schedule_alert_chaseLOS)
	else
		self:StartSchedule(schedule_alert_chase)
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:MaintainAlertBehavior(alwaysChase) -- alwaysChase = Override to always make the NPC chase
	local curTime = CurTime()
	local selfData = self:GetTable()
	if selfData.NextChaseTime > curTime or selfData.Dead or selfData.VJ_IsBeingControlled or selfData.Flinching or self:GetState() == VJ_STATE_ONLY_ANIMATION_CONSTANT then return end
	local eneData = selfData.EnemyData
	local ene = eneData.Target
	local moveType = selfData.MovementType
	if !IsValid(ene) or selfData.TakingCoverT > curTime or (selfData.AttackAnimTime > curTime && moveType != VJ_MOVETYPE_AERIAL && moveType != VJ_MOVETYPE_AQUATIC) then return end
	
	-- Not melee attacking yet but it is in range, so don't chase the enemy!
	if selfData.HasMeleeAttack && eneData.DistanceNearest < selfData.MeleeAttackDistance && eneData.Visible && (self:GetHeadDirection():Dot((ene:GetPos() - self:GetPos()):GetNormalized()) > math_cos(math_rad(selfData.MeleeAttackAngleRadius))) then
		if moveType == VJ_MOVETYPE_AERIAL or moveType == VJ_MOVETYPE_AQUATIC then
			self:AA_StopMoving()
		end
		self:SCHEDULE_IDLE_STAND()
		return
	end
	
	-- Things that override can't bypass, Forces the NPC to ONLY idle stand!
	if moveType == VJ_MOVETYPE_STATIONARY or selfData.IsFollowing or selfData.MedicData.Status or self:GetState() == VJ_STATE_ONLY_ANIMATION then
		self:SCHEDULE_IDLE_STAND()
		return
	end
	
	-- Non-aggressive NPCs
	local behaviorType = selfData.Behavior
	if behaviorType == VJ_BEHAVIOR_PASSIVE or behaviorType == VJ_BEHAVIOR_PASSIVE_NATURE then
		self:SCHEDULE_COVER_ENEMY("TASK_RUN_PATH")
		selfData.NextChaseTime = curTime + 3
		return
	end
	
	if !alwaysChase && (selfData.DisableChasingEnemy or selfData.IsGuard) then self:SCHEDULE_IDLE_STAND() return end
	
	-- If the enemy is not reachable
	if (funcHasCondition(self, COND_ENEMY_UNREACHABLE) or self:IsUnreachable(ene)) && (IsValid(self:GetActiveWeapon()) && (!self:GetActiveWeapon().IsMeleeWeapon)) then
		self:SCHEDULE_ALERT_CHASE(true)
		self:RememberUnreachable(ene, 2)
	else -- Is reachable, so chase the enemy!
		self:SCHEDULE_ALERT_CHASE(false)
	end
	
	-- Set the next chase time
	if selfData.NextChaseTime > curTime then return end -- Don't set it if it's already set!
	selfData.NextChaseTime = curTime + (((eneData.Distance > 2000) and 1) or 0.1) -- If the enemy is far, increase the delay!
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Overrides any activity by returning another activity
		- act = Activity that is being called to be translated
	Returns
		- Activity, the translated activity, otherwise it will return the given activity back
	RULES
		1. Always return an activity, never return nothing or a table!
			- Suggested to call `return self.BaseClass.TranslateActivity(self, act)` at the end of the function
		2. If you are replacing ACT_IDLE from a randomized table, then you must call `self:ResolveAnimation`
			- This is to ensure the idle animation system properly detects if it should be setting a new idle animation
-----------------------------------------------------------]]
function ENT:TranslateActivity(act)
	//VJ.DEBUG_Print(self, "TranslateActivity", act)
	local selfData = self:GetTable()
	-- Handle idle scared and angry animations
	if act == ACT_IDLE then
		if selfData.Weapon_UnarmedBehavior_Active then
			//return PICK(selfData.AnimTbl_ScaredBehaviorStand)
			return ACT_COWER
		elseif selfData.Alerted && self:GetWeaponState() != VJ.WEP_STATE_HOLSTERED && IsValid(self:GetActiveWeapon()) then
			//return PICK(selfData.AnimTbl_WeaponAim)
			return ACT_IDLE_ANGRY
		end
	-- Handle running while scared animation
	elseif act == ACT_RUN && selfData.Weapon_UnarmedBehavior_Active && !selfData.VJ_IsBeingControlled then
		// PICK(selfData.AnimTbl_ScaredBehaviorMovement)
		return ACT_RUN_PROTECTED
	elseif (act == ACT_RUN or act == ACT_WALK) && selfData.Alerted then
		-- Handle aiming while moving animations
		local eneData = selfData.EnemyData
		if selfData.Weapon_CanMoveFire && IsValid(eneData.Target) && (eneData.Visible or (eneData.VisibleTime + 5) > CurTime()) && selfData.CurrentSchedule && selfData.CurrentSchedule.CanShootWhenMoving && self:CanFireWeapon(true, false) then
			local anim = self:TranslateActivity(act == ACT_RUN and ACT_RUN_AIM or ACT_WALK_AIM)
			if VJ.AnimExists(self, anim) then
				if eneData.Visible then
					selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_FIRE
				else -- Not visible but keep aiming
					selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_AIM_MOVE
				end
				return anim
			end
		end
		-- Handle walk/run angry animations
		local anim = self:TranslateActivity(act == ACT_RUN and ACT_RUN_AGITATED or ACT_WALK_AGITATED)
		if VJ.AnimExists(self, anim) then
			return anim
		end
	end
	
	-- Handle translations table
	local translation = selfData.AnimationTranslations[act]
	if translation then
		if istable(translation) then
			if act == ACT_IDLE then
				return self:ResolveAnimation(translation)
			end
			return translation[math.random(1, #translation)] or act -- "or act" = To make sure it doesn't return nil when the table is empty!
		end
		return translation
	end
	return act
end
---------------------------------------------------------------------------------------------------------------------------------------------
local sdWepSwitch = {"physics/metal/weapon_impact_soft1.wav", "physics/metal/weapon_impact_soft2.wav", "physics/metal/weapon_impact_soft3.wav"}
--
function ENT:DoChangeWeapon(wep, invSwitch)
	wep = wep or nil -- The weapon to give or setup | Setting it nil will only setup the current active weapon
	invSwitch = invSwitch or false -- If true, it will not delete the previous weapon!
	local curWep = self:GetActiveWeapon()
	
	-- If not supposed to have a weapon, then return!
	if self.Weapon_Disabled && IsValid(curWep) then
		curWep:Remove()
		return NULL
	end
	
	-- Only remove and actually give the weapon if the function is given a weapon class to set
	if wep != nil then
		if invSwitch then
			self:SelectWeapon(wep)
			VJ.EmitSound(self, sdWepSwitch, 70)
			curWep = wep
		else
			if IsValid(curWep) && self.WeaponInventoryStatus <= VJ.WEP_INVENTORY_PRIMARY then
				curWep:Remove()
			end
			curWep = self:Give(wep)
			self.WeaponInventory.Primary = curWep
		end
	end
	
	-- If we are given a new weapon or switching weapon, then do all of the necessary set up
	if IsValid(curWep) then
		self.WeaponAttackAnim = ACT_INVALID
		self:SetWeaponState() -- Reset the weapon state because we do NOT want previous weapon's state to be used!
		if invSwitch then
			if curWep.IsVJBaseWeapon then curWep:Equip(self) end
		else -- If we are not switching weapons, then we know curWep is the primary weapon
			self.WeaponInventoryStatus = VJ.WEP_INVENTORY_PRIMARY
			-- If this is completely new weapon, then set the weapon inventory's primary to this weapon
			local curPrimary = self.WeaponInventory.Primary
			if curWep != self.WeaponInventory.Primary then
				if IsValid(curPrimary) then curPrimary:Remove() end -- Remove the old primary weapon
				self.WeaponInventory.Primary = curWep
			end
		end
		self:UpdateAnimationTranslations(curWep:GetHoldType())
		self:OnWeaponChange(curWep, self.WeaponEntity, invSwitch)
		self.WeaponEntity = curWep
	else
		self.WeaponInventoryStatus = VJ.WEP_INVENTORY_NONE
	end
	return curWep
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:SetWeaponState(state, time)
	time = time or -1
	self.WeaponState = state or VJ.WEP_STATE_READY
	if time >= 0 then
		timer.Create("wep_state_reset" .. self:EntIndex(), time, 1, function()
			self:SetWeaponState()
		end)
	else
		timer.Remove("wep_state_reset" .. self:EntIndex())
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:GetWeaponState()
	return self.WeaponState
end
---------------------------------------------------------------------------------------------------------------------------------------------
local attackTimers = {
	[VJ.ATTACK_TYPE_MELEE] = function(self, skipStopAttacks)
		if !skipStopAttacks then
			timer.Create("attack_melee_reset" .. self:EntIndex(), self:GetAttackTimer(self.NextAnyAttackTime_Melee, self.TimeUntilMeleeAttackDamage, self.AttackAnimDuration), 1, function()
				self:StopAttacks()
				self:MaintainAlertBehavior()
			end)
		end
		timer.Create("attack_melee_reset_able" .. self:EntIndex(), self:GetAttackTimer(self.NextMeleeAttackTime), 1, function()
			self.IsAbleToMeleeAttack = true
		end)
	end,
	[VJ.ATTACK_TYPE_GRENADE] = function(self, skipStopAttacks)
		if !skipStopAttacks then
			timer.Create("attack_grenade_reset" .. self:EntIndex(), self:GetAttackTimer(self.NextAnyAttackTime_Grenade, self.GrenadeAttackThrowTime, self.AttackAnimDuration), 1, function()
				self:StopAttacks()
				self:MaintainAlertBehavior()
			end)
		end
		//timer.Create("attack_grenade_reset_able" .. self:EntIndex(), self:GetAttackTimer(self.NextGrenadeAttackTime), 1, function()
			//self.IsAbleToGrenadeAttack = true
		//end)
		self.NextThrowGrenadeT = CurTime() + self:GetAttackTimer(self.NextGrenadeAttackTime)
	end
}
---------------------------------------------------------------------------------------------------------------------------------------------
local function playReloadAnimation(self, anims)
	local anim, animDur, animType = self:PlayAnim(anims, true, false, "Visible")
	if anim != ACT_INVALID then
		local wep = self.WeaponEntity
		if wep.IsVJBaseWeapon then wep:NPC_Reload() end
		timer.Create("wep_reload_reset" .. self:EntIndex(), animDur, 1, function()
			if IsValid(self) && IsValid(wep) && self:GetWeaponState() == VJ.WEP_STATE_RELOADING then
				wep:SetClip1(wep:GetMaxClip1())
				if wep.IsVJBaseWeapon then wep:OnReload("Finish") end
				self:SetWeaponState()
			end
		end)
		self.AllowWeaponOcclusionDelay = false
		-- If NOT controlled by a player AND is a gesture make it stop moving so it doesn't run after the enemy right away
		if !self.VJ_IsBeingControlled && animType == ANIM_TYPE_GESTURE then
			self:StopMoving()
		end
		return true -- We have successfully ran the reload animation!
	end
	return false -- The given animation was invalid!
end
---------------------------------------------------------------------------------------------------------------------------------------------
//function ENT:OnActiveWeaponChanged(old, new) print(old, new) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:Think()
	//if self.NextActualThink <= CurTime() then
		//self.NextActualThink = CurTime() + 0.065
	
	-- Schedule debug
	//if self.CurrentSchedule then PrintTable(self.CurrentSchedule) end
	//if self.CurrentTask then PrintTable(self.CurrentTask) end
	
	//self:SetCondition(1) -- Probably not needed as "sv_pvsskipanimation" handles it | Fix attachments, bones, positions, angles etc. being broken in NPCs! This condition is used as a backup in case "sv_pvsskipanimation" isn't disabled!
	//if self.MovementType == VJ_MOVETYPE_GROUND && self:GetVelocity():Length() <= 0 && !self:IsEFlagSet(EFL_IS_BEING_LIFTED_BY_BARNACLE) /*&& curSchedule.IsMovingTask*/ then self:DropToFloor() end -- No need, already handled by the engine
	
	local curTime = CurTime()
	local selfData = self:GetTable()
	
	-- This is here to make sure the initialized process time stays in place...
	-- otherwise if AI is disabled then reenabled, all the NPCs will now start processing at the same exact CurTime!
	local doHeavyProcesses = curTime > selfData.NextProcessT
	if doHeavyProcesses then
		selfData.NextProcessT = curTime + selfData.NextProcessTime
	end
	
	if !selfData.Dead then
		-- Detect any weapon change, unless the NPC is dead because the variable is used by self:DeathWeaponDrop()
		if selfData.WeaponEntity != self:GetActiveWeapon() then
			selfData.WeaponEntity = self:DoChangeWeapon()
		end
		
		-- Breath sound system
		if selfData.HasBreathSound && selfData.HasSounds && curTime > selfData.NextBreathSoundT then
			local pickedSD = PICK(selfData.SoundTbl_Breath)
			local dur = 10 -- Make the default value large so we don't check it too much!
			if pickedSD then
				StopSD(selfData.CurrentBreathSound)
				dur = (selfData.NextSoundTime_Breath == false and SoundDuration(pickedSD)) or math.Rand(selfData.NextSoundTime_Breath.a, selfData.NextSoundTime_Breath.b)
				selfData.CurrentBreathSound = VJ.CreateSound(self, pickedSD, selfData.BreathSoundLevel, self:GetSoundPitch(selfData.BreathSoundPitch))
			end
			selfData.NextBreathSoundT = curTime + dur
		end
	end
	
	self:OnThink()
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	if VJ_CVAR_AI_ENABLED && self:GetState() != VJ_STATE_FREEZE && !self:IsEFlagSet(EFL_IS_BEING_LIFTED_BY_BARNACLE) then
		if selfData.VJ_DEBUG then
			if GetConVar("vj_npc_debug_enemy"):GetInt() == 1 then VJ.DEBUG_Print(self, false, "Enemy -> " .. tostring(self:GetEnemy() or "NULL") .. " | Alerted? " .. tostring(selfData.Alerted))  end
			if GetConVar("vj_npc_debug_takingcover"):GetInt() == 1 then if curTime > selfData.TakingCoverT then VJ.DEBUG_Print(self, false, "NOT taking cover") else VJ.DEBUG_Print(self, false, "Taking cover (" .. selfData.TakingCoverT - curTime .. ")") end end
			if GetConVar("vj_npc_debug_lastseenenemytime"):GetInt() == 1 then PrintMessage(HUD_PRINTTALK, (curTime - selfData.EnemyData.VisibleTime) .. " (" .. self:GetName() .. ")") end
			if IsValid(selfData.WeaponEntity) && GetConVar("vj_npc_debug_weapon"):GetInt() == 1 then VJ.DEBUG_Print(self, false, " : Weapon -> " .. tostring(selfData.WeaponEntity) .. " | Ammo: " .. selfData.WeaponEntity:Clip1() .. " / " .. selfData.WeaponEntity:GetMaxClip1() .. " | Accuracy: " .. selfData.Weapon_Accuracy) end
		end
		
		//self:SetPlaybackRate(self.AnimationPlaybackRate)
		self:OnThinkActive()
		
		-- Update follow system's data
		//print("------------------")
		//PrintTable(selfData.FollowData)
		if selfData.IsFollowing && self:GetNavType() != NAV_JUMP && self:GetNavType() != NAV_CLIMB then
			local followData = selfData.FollowData
			local followEnt = followData.Target
			local followIsLiving = followEnt.VJ_ID_Living
			//print(self:GetTarget())
			if IsValid(followEnt) && (!followIsLiving or (followIsLiving && (self:Disposition(followEnt) == D_LI or self:GetClass() == followEnt:GetClass()) && followEnt:Alive())) then
				if curTime > followData.NextUpdateT && !selfData.VJ_ST_Healing then
					local distToPly = self:GetPos():Distance(followEnt:GetPos())
					local busy = self:IsBusy("Activities")
					self:SetTarget(followEnt)
					followData.StopAct = false
					if distToPly > followData.MinDist then -- Entity is far away, move towards it!
						local isFar = distToPly > (followData.MinDist * 4)
						-- IF (we are busy but far) OR (not busy) THEN move
						if (busy && isFar) or (!busy) then
							followData.Moving = true
							-- If we are far then stop all activities (ex: attacks) and just go there already!
							if isFar then
								followData.StopAct = true
							end
							if selfData.MovementType == VJ_MOVETYPE_AERIAL or selfData.MovementType == VJ_MOVETYPE_AQUATIC then
								self:AA_MoveTo(self:GetTarget(), true, (distToPly < (followData.MinDist * 1.5) and "Calm") or "Alert", {FaceDestTarget = true})
							elseif !self:IsMoving() or self:GetCurGoalType() != 1 then
								//self:NavSetGoalTarget(followEnt) // local goalTarget = -- No longer works, a recent GMod commit broke it
								-- Do NOT check for validity! Let it be sent to "OnTaskFailed" so an NPC can capture it! (Ex: HL1 scientist complaining to the player)
								//if goalTarget then
								local schedule = vj_ai_schedule.New("SCHEDULE_FOLLOW")
								schedule:EngTask("TASK_GET_PATH_TO_TARGET", 0) -- Required to generate the path!
								schedule:EngTask("TASK_MOVE_TO_TARGET_RANGE", followData.MinDist * 0.8)
								schedule:EngTask("TASK_WAIT_FOR_MOVEMENT", 0)
								schedule:EngTask("TASK_FACE_TARGET", 1)
								schedule.CanShootWhenMoving = true
								if IsValid(self:GetActiveWeapon()) then
									schedule.TurnData = {Type = VJ.FACE_ENEMY_VISIBLE}
								end
								self:StartSchedule(schedule)
								//else
								//	self:ClearGoal()
								//end
								/*self:SCHEDULE_GOTO_TARGET((distToPly < (followData.MinDist * 1.5) and "TASK_WALK_PATH") or "TASK_RUN_PATH", function(schedule)
									schedule.CanShootWhenMoving = true
									if IsValid(self:GetActiveWeapon()) then
										schedule.TurnData = {Type = VJ.FACE_ENEMY_VISIBLE}
									end
								end)*/
							end
						end
					elseif followData.Moving == true then -- Entity is very close, stop moving!
						if !busy then -- If not busy then make it stop moving and do something
							self:TaskComplete()
							self:StopMoving(false)
							self:SelectSchedule()
						end
						followData.Moving = false
					end
					followData.NextUpdateT = curTime + 0.5
				end
			else
				self:ResetFollowBehavior()
			end
		end
		
		//print("MAX CLIP: ", selfData.WeaponEntity:GetMaxClip1())
		//print("CLIP: ", selfData.WeaponEntity:Clip1())
			
		if !selfData.Dead then
			-- Health Regeneration System
			local healthRegen = selfData.HealthRegenParams
			if healthRegen.Enabled && curTime > selfData.HealthRegenDelayT then
				local myHP = self:Health()
				self:SetHealth(math_min(math_max(myHP + healthRegen.Amount, myHP), self:GetMaxHealth()))
				selfData.HealthRegenDelayT = curTime + math.Rand(healthRegen.Delay.a, healthRegen.Delay.b)
			end
			
			-- Run the heavy processes
			if doHeavyProcesses then
				self:MaintainRelationships()
				self:CheckForDangers()
				if selfData.IsMedic then self:MaintainMedicBehavior() end
				//selfData.NextProcessT = curTime + selfData.NextProcessTime
			end
			
			local plyControlled = selfData.VJ_IsBeingControlled
			local myPos = self:GetPos()
			local ene = self:GetEnemy()
			local eneValid = IsValid(ene)
			local eneData = selfData.EnemyData
			if !eneData.Reset then
				-- Reset enemy if it doesn't exist or it's dead
				if !eneValid then
					self:ResetEnemy(true, true)
					ene = self:GetEnemy()
					eneValid = IsValid(ene)
				-- Reset enemy if it has been unseen for a while
				elseif (curTime - eneData.VisibleTime) > ((eneData.Distance < 4000 and selfData.EnemyTimeout) or (selfData.EnemyTimeout / 2)) && !selfData.IsVJBaseSNPC_Tank then
					self:PlaySoundSystem("LostEnemy")
					self:ResetEnemy(true, true)
					ene = self:GetEnemy()
					eneValid = IsValid(ene)
				end
			end
			
			local curWep = selfData.WeaponEntity
			//if selfData.WeaponAttackState then self:CapabilitiesRemove(CAP_TURN_HEAD) else self:CapabilitiesAdd(CAP_TURN_HEAD) end -- Fixes their heads breaking
			-- If we have a valid weapon...
			if IsValid(curWep) && !self:IsBusy("Activities") then
				-- Weapon Inventory System
				if !plyControlled then
					if eneValid then
						-- Switch to melee
						if !selfData.IsGuard && IsValid(selfData.WeaponInventory.Melee) && ((eneData.Distance < selfData.MeleeAttackDistance) or (eneData.Distance < 300 && curWep:Clip1() <= 0)) && (self:Health() > self:GetMaxHealth() * 0.25) && curWep != selfData.WeaponInventory.Melee then
							if self:GetWeaponState() == VJ.WEP_STATE_RELOADING then self:SetWeaponState() end -- Since the reloading can be cut off, reset it back to false, or else it can mess up its behavior!
							//timer.Remove("wep_reload_reset" .. self:EntIndex()) -- No longer needed
							selfData.WeaponInventoryStatus = VJ.WEP_INVENTORY_MELEE
							self:DoChangeWeapon(selfData.WeaponInventory.Melee, true)
							curWep = selfData.WeaponEntity
						-- Switch to anti-armor
						elseif self:GetWeaponState() != VJ.WEP_STATE_RELOADING && IsValid(selfData.WeaponInventory.AntiArmor) && (ene.IsVJBaseSNPC_Tank or ene.VJ_ID_Boss) && curWep != selfData.WeaponInventory.AntiArmor then
							selfData.WeaponInventoryStatus = VJ.WEP_INVENTORY_ANTI_ARMOR
							self:DoChangeWeapon(selfData.WeaponInventory.AntiArmor, true)
							curWep = selfData.WeaponEntity
						end
					end
					if self:GetWeaponState() != VJ.WEP_STATE_RELOADING then
						-- Reset weapon status from melee to primary
						if selfData.WeaponInventoryStatus == VJ.WEP_INVENTORY_MELEE && (!eneValid or (eneValid && eneData.Distance >= 300)) then
							selfData.WeaponInventoryStatus = VJ.WEP_INVENTORY_PRIMARY
							self:DoChangeWeapon(selfData.WeaponInventory.Primary, true)
							curWep = selfData.WeaponEntity
						-- Reset weapon status from anti-armor to primary
						elseif selfData.WeaponInventoryStatus == VJ.WEP_INVENTORY_ANTI_ARMOR && (!eneValid or (eneValid && !ene.IsVJBaseSNPC_Tank && !ene.VJ_ID_Boss)) then
							selfData.WeaponInventoryStatus = VJ.WEP_INVENTORY_PRIMARY
							self:DoChangeWeapon(selfData.WeaponInventory.Primary, true)
							curWep = selfData.WeaponEntity
						end
					end
				end
				
				-- Weapon Reloading
				if selfData.Weapon_CanReload && !selfData.AttackType && !curWep.IsMeleeWeapon && self:GetWeaponState() == VJ.WEP_STATE_READY && ((!plyControlled && ((!eneValid && curWep:GetMaxClip1() > curWep:Clip1() && (curTime - eneData.TimeSet) > math.random(3, 8) && !self:IsMoving()) or (eneValid && curWep:Clip1() <= 0))) or (plyControlled && selfData.VJ_TheController:KeyDown(IN_RELOAD) && curWep:GetMaxClip1() > curWep:Clip1())) then
					selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
					selfData.NextChaseTime = curTime + 2
					if !plyControlled then self:SetWeaponState(VJ.WEP_STATE_RELOADING) end
					if eneValid then self:PlaySoundSystem("WeaponReload") end -- tsayn han e minag yete teshnami ga!
					self:OnWeaponReload()
					if selfData.DisableWeaponReloadAnimation then -- Reload animation is disabled
						if self:GetWeaponState() == VJ.WEP_STATE_RELOADING then self:SetWeaponState() end
						curWep:SetClip1(curWep:GetMaxClip1())
						if curWep.IsVJBaseWeapon then curWep:NPC_Reload() end
					else
						-- Controlled by a player...
						if plyControlled then
							self:SetWeaponState(VJ.WEP_STATE_RELOADING)
							playReloadAnimation(self, self:TranslateActivity(PICK(selfData.AnimTbl_WeaponReload)))
						-- NOT controlled by a player...
						else
							-- NPC is hidden, so attempt to crouch reload
							if eneValid && self:DoCoverTrace(myPos + self:OBBCenter(), ene:EyePos(), false, {SetLastHiddenTime = true}) then
								-- if It does NOT have a cover reload animation, then just play the regular standing reload animation
								if !playReloadAnimation(self, self:TranslateActivity(PICK(selfData.AnimTbl_WeaponReloadCovered))) then
									playReloadAnimation(self, self:TranslateActivity(PICK(selfData.AnimTbl_WeaponReload)))
								end
							-- NPC is NOT hidden...
							else
								-- Under certain situations, simply do standing reload without running to a hiding spot
								if !selfData.Weapon_FindCoverOnReload or selfData.IsGuard or selfData.IsFollowing or selfData.VJ_IsBeingControlled_Tool or !eneValid or selfData.MovementType == VJ_MOVETYPE_STATIONARY or eneData.Distance < 650 then
									playReloadAnimation(self, self:TranslateActivity(PICK(selfData.AnimTbl_WeaponReload)))
								else -- If all is good, then run to a hiding spot and reload!
									local schedule = vj_ai_schedule.New("SCHEDULE_COVER_RELOAD")
									schedule:EngTask("TASK_FIND_COVER_FROM_ENEMY", 0)
									schedule:EngTask("TASK_RUN_PATH", 0)
									schedule:EngTask("TASK_WAIT_FOR_MOVEMENT", 0)
									schedule.RunCode_OnFinish = function()
										if self:GetWeaponState() == VJ.WEP_STATE_RELOADING then
											-- If the current situation isn't favorable, then abandon the current reload, and try again!
											if self.AttackType or (IsValid(self:GetEnemy()) && eneData.Distance <= self.Weapon_RetreatDistance) then
												self:SetWeaponState()
												//timer.Remove("wep_reload_reset" .. self:EntIndex()) -- Remove the timer to make sure it doesn't set reloading to false at a random time (later on)
											else -- Our hiding spot is good, so reload!
												playReloadAnimation(self, self:TranslateActivity(PICK(self.AnimTbl_WeaponReload)))
											end
										end
									end
									self:StartSchedule(schedule)
								end
							end
						end
					end
				end
			end
		
			if eneValid then
				local enePos = ene:GetPos()
				local eneDist = myPos:Distance(enePos)
				local eneDistNear = VJ.GetNearestDistance(self, ene, true)
				local eneIsVisible = plyControlled and true or self:Visible(ene)
				
				-- Set latest enemy information
				self:UpdateEnemyMemory(ene, enePos)
				eneData.Target = ene
				eneData.Reset = false
				eneData.Visible = eneIsVisible
				eneData.Distance = eneDist
				eneData.DistanceNearest = eneDistNear
				local firingWep = selfData.WeaponAttackState && selfData.WeaponAttackState >= VJ.WEP_ATTACK_STATE_FIRE
				if eneIsVisible then
					if self:IsInViewCone(enePos) && (eneDist < self:GetMaxLookDistance()) then
						eneData.VisibleTime = curTime
						-- Why 2 vars? Because the last "Visible" tick is usually not updated in time, causing the engine to give false positive, thinking the enemy IS visible
						eneData.VisiblePos = eneData.VisiblePosReal
						eneData.VisiblePosReal = ene:EyePos() -- Use EyePos because "Visible" uses it to run the trace in the engine! | For origin, use "self:GetEnemyLastSeenPos()"
					end
					if firingWep then self:PlaySoundSystem("Suppressing") end
				elseif firingWep then
					selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
				end

				-- Call for help
				if selfData.CallForHelp && curTime > selfData.NextCallForHelpT && !selfData.AttackType then
					self:Allies_CallHelp(selfData.CallForHelpDistance)
					selfData.NextCallForHelpT = curTime + selfData.CallForHelpCooldown
				end
				
				self:UpdatePoseParamTracking()
				
				-- Attacks
				if !selfData.PauseAttacks && !selfData.Flinching && !selfData.FollowData.StopAct && curTime > selfData.NextDoAnyAttackT && self:GetState() != VJ_STATE_ONLY_ANIMATION_NOATTACK && selfData.Behavior != VJ_BEHAVIOR_PASSIVE && selfData.Behavior != VJ_BEHAVIOR_PASSIVE_NATURE then
					-- Attack priority in order: Custom --> Melee --> Grenade
					local funcThinkAtk = self.OnThinkAttack; if funcThinkAtk then funcThinkAtk(self, !!selfData.AttackType, ene) end
					
					-- Melee Attack
					if selfData.HasMeleeAttack && selfData.IsAbleToMeleeAttack && !selfData.AttackType && (!IsValid(curWep) or (IsValid(curWep) && (!curWep.IsMeleeWeapon))) && ((plyControlled && selfData.VJ_TheController:KeyDown(IN_ATTACK)) or (!plyControlled && (eneDistNear < selfData.MeleeAttackDistance && eneIsVisible) && (self:GetHeadDirection():Dot((enePos - myPos):GetNormalized()) > math_cos(math_rad(selfData.MeleeAttackAngleRadius))))) && self:OnMeleeAttack("PreInit", ene) != true then
						local seed = curTime; selfData.AttackSeed = seed
						selfData.IsAbleToMeleeAttack = false
						selfData.AttackType = VJ.ATTACK_TYPE_MELEE
						selfData.AttackState = VJ.ATTACK_STATE_STARTED
						selfData.AttackAnim = ACT_INVALID
						selfData.AttackAnimDuration = 0
						selfData.AttackAnimTime = 0
						self:SetTurnTarget("Enemy") -- Always turn towards the enemy at the start
						self:OnMeleeAttack("Init", ene)
						self:PlaySoundSystem("BeforeMeleeAttack")
						selfData.NextAlertSoundT = curTime + 0.4
						if selfData.AnimTbl_MeleeAttack then
							local anim, animDur, animType = self:PlayAnim(selfData.AnimTbl_MeleeAttack, false, 0, false)
							if anim != ACT_INVALID then
								selfData.AttackAnim = anim
								selfData.AttackAnimDuration = animDur - (selfData.MeleeAttackAnimationDecreaseLengthAmount / selfData.AnimPlaybackRate)
								if animType != ANIM_TYPE_GESTURE then -- Allow things like chasing to continue for gestures
									selfData.AttackAnimTime = curTime + selfData.AttackAnimDuration
								end
							end
						end
						if !selfData.TimeUntilMeleeAttackDamage then
							attackTimers[VJ.ATTACK_TYPE_MELEE](self)
						else -- NOT event based...
							timer.Create("attack_melee_start" .. self:EntIndex(), selfData.TimeUntilMeleeAttackDamage / selfData.AnimPlaybackRate, selfData.MeleeAttackReps, function() if selfData.AttackSeed == seed then self:ExecuteMeleeAttack() end end)
							if selfData.MeleeAttackExtraTimers then
								for k, t in ipairs(selfData.MeleeAttackExtraTimers) do
									self:AddExtraAttackTimer("attack_melee_start" .. curTime + k, t, function() if selfData.AttackSeed == seed then self:ExecuteMeleeAttack() end end)
								end
							end
						end
						self:OnMeleeAttack("PostInit", ene)
					end
					
					-- Grenade attack
					if selfData.HasGrenadeAttack && curTime > selfData.NextThrowGrenadeT && curTime > selfData.TakingCoverT && self:GetWeaponState() != VJ.WEP_STATE_RELOADING && !self:IsBusy("Activities") then
						if plyControlled then
							if selfData.VJ_TheController:KeyDown(IN_JUMP) then
								self:GrenadeAttack()
								selfData.NextThrowGrenadeT = curTime + self:GetAttackTimer(selfData.NextGrenadeAttackTime)
							end
						else
							local chance = selfData.GrenadeAttackChance
							-- If chance is above 4, then half it by 2 if the enemy is a tank OR not visible
							if math.random(1, (chance > 3 && (ene.IsVJBaseSNPC_Tank or !eneIsVisible) and math.floor(chance / 2)) or chance) == 1 && eneDist < selfData.GrenadeAttackMaxDistance && eneDist > selfData.GrenadeAttackMinDistance then
								self:GrenadeAttack()
							end
							selfData.NextThrowGrenadeT = curTime + self:GetAttackTimer(selfData.NextGrenadeAttackTime)
						end
					end
				end
			else -- No Enemy
				selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
				if !selfData.Alerted && selfData.UpdatedPoseParam && !plyControlled then
					self:ClearPoseParameters()
					selfData.UpdatedPoseParam = false
				end
				eneData.TimeAcquired = 0
			end
			
			-- Guarding Behavior
			if selfData.IsGuard && !selfData.IsFollowing && !selfData.IsVJBaseSNPC_Tank then
				local guardData = selfData.GuardData
				if !guardData.Position then -- If we don't have a position, then set it!
					guardData.Position = myPos
					guardData.Direction = myPos + self:GetForward() * 51
				end
				-- If it's far from the guarding position, then go there!
				if !self:IsMoving() && !self:IsBusy("Activities") then
					local dist = myPos:Distance(guardData.Position) -- Distance to the guard position
					if dist > 50 then
						self:SetLastPosition(guardData.Position)
						self:SCHEDULE_GOTO_POSITION(dist <= 800 and "TASK_WALK_PATH" or "TASK_RUN_PATH", function(x)
							x.CanShootWhenMoving = true
							x.TurnData = {Type = VJ.FACE_ENEMY}
							x.RunCode_OnFinish = function()
								timer.Simple(0.01, function()
									if IsValid(self) && !self:IsMoving() && !self:IsBusy("Activities") && selfData.IsGuard && guardData.Position then
										self:SetLastPosition(guardData.Direction)
										self:SCHEDULE_FACE("TASK_FACE_LASTPOSITION")
									end
								end)
							end
						end)
					end
				end
			end
		end
		-- Handle the unique movement system for player models
		if selfData.UsePoseParameterMovement && selfData.MovementType == VJ_MOVETYPE_GROUND then
			local moveDir = VJ.GetMoveDirection(self, true)
			if moveDir then
				funcSetPoseParameter(self, "move_x", moveDir.x)
				funcSetPoseParameter(self, "move_y", moveDir.y)
			else -- I am not moving, reset the pose parameters, otherwise I will run in place!
				funcSetPoseParameter(self, "move_x", 0)
				funcSetPoseParameter(self, "move_y", 0)
			end
		end
	else -- AI Not enabled
		selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
	end
	
	//if aiEnabled then
		//self:MaintainIdleAnimation()
	//end
	
	-- Maintain turning when needed otherwise Engine will take over during movements!
	-- No longer needed as "OverrideMoveFacing" now handles it!
	/*if !didTurn then
		local curTurnData = self.TurnData
		if curTurnData.Type && curTurnData.LastYaw != 0 then
			self:SetIdealYawAndUpdate(curTurnData.LastYaw)
			didTurn = true
		end
	end*/
	
	self:NextThink(curTime + 0.065)
	return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:ExecuteMeleeAttack()
	local selfData = self:GetTable()
	if selfData.Dead or selfData.PauseAttacks or selfData.Flinching or selfData.AttackType == VJ.ATTACK_TYPE_GRENADE or (selfData.MeleeAttackStopOnHit && selfData.AttackState == VJ.ATTACK_STATE_EXECUTED_HIT) then return end
	local skip = self:OnMeleeAttackExecute("Init")
	local hitRegistered = false
	if !skip then
	local myPos = self:GetPos()
	local myClass = self:GetClass()
		for _, ent in ipairs(ents.FindInSphere(self:MeleeAttackTraceOrigin(), selfData.MeleeAttackDamageDistance)) do
			if ent == self or ent:GetClass() == myClass or (ent.IsVJBaseBullseye && ent.VJ_IsBeingControlled) then continue end
			if ent:IsPlayer() && (ent.VJ_IsControllingNPC or !ent:Alive() or VJ_CVAR_IGNOREPLAYERS) then continue end
			if ((ent.VJ_ID_Living && self:Disposition(ent) != D_LI) or ent.VJ_ID_Attackable or ent.VJ_ID_Destructible) && self:MeleeAttackTraceDirection():Dot((Vector(ent:GetPos().x, ent:GetPos().y, 0) - Vector(myPos.x, myPos.y, 0)):GetNormalized()) > math_cos(math_rad(selfData.MeleeAttackDamageAngleRadius)) then
				local isProp = ent.VJ_ID_Attackable
				if self:OnMeleeAttackExecute("PreDamage", ent, isProp) == true then continue end
				local dmgAmount = self:ScaleByDifficulty(selfData.MeleeAttackDamage)
				-- Knockback (Don't push things like doors, trains, elevators as it will make them fly when activated)
				if selfData.HasMeleeAttackKnockBack && ent:GetMoveType() != MOVETYPE_PUSH && ent.MovementType != VJ_MOVETYPE_STATIONARY && (!ent.VJ_ID_Boss or ent.IsVJBaseSNPC_Tank) then
					local isNextBot = ent:IsNextBot()
						if !isNextBot then
							ent:SetGroundEntity(NULL)
						end
						local vel = self:MeleeAttackKnockbackVelocity(ent)
						ent:SetVelocity(vel)
						if isNextBot then
							ent.loco:Approach(vel, 1)
							ent.loco:Jump()
							ent.loco:SetVelocity(vel)
						end
				end
				-- Apply actual damage
				if !selfData.DisableDefaultMeleeAttackDamageCode then
					local applyDmg = DamageInfo()
					applyDmg:SetDamage(dmgAmount)
					applyDmg:SetDamageType(selfData.MeleeAttackDamageType)
					if ent.VJ_ID_Living then applyDmg:SetDamageForce(self:GetForward() * ((applyDmg:GetDamage() + 100) * 70)) end
					applyDmg:SetInflictor(self)
					applyDmg:SetAttacker(self)
					VJ.DamageSpecialEnts(self, ent, applyDmg)
					ent:TakeDamageInfo(applyDmg, self)
				end
				if ent:IsPlayer() then
					ent:ViewPunch(Angle(math.random(-1, 1) * dmgAmount, math.random(-1, 1) * dmgAmount, math.random(-1, 1) * dmgAmount))
				end
				if !isProp then -- Only for non-props...
					hitRegistered = true
					if selfData.MeleeAttackStopOnHit then break end
				end
			end
		end
	end
	if selfData.AttackState < VJ.ATTACK_STATE_EXECUTED then
		selfData.AttackState = VJ.ATTACK_STATE_EXECUTED
		if selfData.TimeUntilMeleeAttackDamage then
			attackTimers[VJ.ATTACK_TYPE_MELEE](self)
		end
	end
	if !skip then
		if hitRegistered then
			self:PlaySoundSystem("MeleeAttack")
			selfData.AttackState = VJ.ATTACK_STATE_EXECUTED_HIT
		else
			self:OnMeleeAttackExecute("Miss")
			self:PlaySoundSystem("MeleeAttackMiss")
		end
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Triggers a grenade attack
		- customEnt = What entity it should throw | DEFAULT: nil
			- nil = Spawn the NPC's default grenade class usually set by "self.GrenadeAttackEntity"
			- string = Override to use given entity class
			- entity = Override to use the given entity as the grenade by changing its parent to the NPC and altering its position
		- disableOwner = If true, the NPC will not be set as the owner of the grenade, allowing it to damage itself and its allies when applicable!
	Returns
		- [boolean] = Whether or not it successfully triggered the attack
-----------------------------------------------------------]]
function ENT:GrenadeAttack(customEnt, disableOwner)
	if self.Dead or self.Flinching or self.AttackType == VJ.ATTACK_TYPE_MELEE then return false end
	local eneData = self.EnemyData
	local ene = eneData.Target
	local isLiveEnt = IsValid(customEnt)
	local landDir = "FindBest"

	-- Handle possible destinations:
		-- Enemy not valid --> Best position away from the NPC and allies
		-- Enemy valid AND Enemy visible --> Enemy's position
		-- Enemy valid AND Enemy not visible AND last seen position is visible --> Enemy's last visible position
		-- Enemy valid AND Enemy not visible AND last seen position is not visible --> Cancel attack
		-- Enemy valid AND Enemy not visible AND last seen position is not visible AND grenade is live throw back --> Best position away from the NPC and allies
	if IsValid(ene) then
		-- If enemy is visible then face them!
		if eneData.Visible then
			landDir = "Enemy" -- Do NOT face random pos, even if "self.GrenadeAttackAnimationFaceEnemy" is disabled!
		else -- We have a hidden enemy...
			-- Attempt to flush the enemy out of hiding
			if self:VisibleVec(eneData.VisiblePos) && ene:GetPos():Distance(eneData.VisiblePos) <= self.GrenadeAttackMaxDistance then // self.GrenadeAttackMaxDistance
				landDir = "EnemyLastVis" -- We are going to face flush position, do NOT face random pos!
			-- If can't flush the enemy, then face random open position ONLY if we are given a live entity, otherwise...
			-- If live entity is NOT given and it's allowed to continue, it will cause the NPC to throw a grenade when both the enemy and its flush position are hidden!
			elseif !isLiveEnt then
				return false
			end
		end
	end
	
	if self:OnGrenadeAttack("Init", customEnt) then return false end
	local seed = CurTime(); self.AttackSeed = seed
	
	-- Handle animations
	self.AttackAnim = ACT_INVALID
	self.AttackAnimDuration = 0
	self.AttackAnimTime = 0
	if self.AnimTbl_GrenadeAttack then
		local anim, animDur = self:PlayAnim(self.AnimTbl_GrenadeAttack, false, 0, false)
		if anim != ACT_INVALID then
			self.AttackAnim = anim
			self.AttackAnimDuration = animDur
			self.AttackAnimTime = seed + self.AttackAnimDuration
		end
	end
	
	if landDir == "Enemy" then -- Face enemy
		if self.GrenadeAttackAnimationFaceEnemy then
			self:SetTurnTarget("Enemy")
		end
	elseif landDir == "EnemyLastVis" then -- Face enemy's last visible pos
		self:SetTurnTarget(eneData.VisiblePos, self.AttackAnimDuration or 1.5)
	else -- Face best pos
		local bestPos = PICK(VJ.TraceDirections(self, "Quick", 200, true, false, 8))
		if bestPos then
			landDir = bestPos -- Save the position so it can be used when it's thrown
			self:SetTurnTarget(bestPos, self.AttackAnimDuration or 1.5)
		end
	end
	
	-- Handle situation where already spawned entity is given | EX: Grenade picked up by the NPC
	if isLiveEnt then
		customEnt.VJ_ST_Grabbed = true
		customEnt.VJ_ST_GrabOrgMoveType = customEnt:GetMoveType()
		-- Change the grenade's position so the NPC is actively holding it, in order with priority:
			-- 1. CUSTOM 		If custom position is given then use that, otherwise...
			-- 2. ATTACHMENT 	If a valid attachment is given then use that, otherwise...
			-- 3. BONE 			If a valid bone is given then use that, otherwise...
			-- 4. FAIL 			Use the NPC's shoot position (fail safe)
		local customPos = self:OnGrenadeAttack("SpawnPos", customEnt, landDir)
		if !customPos then -- If no custom position is given...
			local getAttach = self:LookupAttachment(self.GrenadeAttackAttachment)
			if !getAttach or getAttach == 0 or getAttach == -1 then -- Attachment invalid, try bone...
				local getBone = self:LookupBone(self.GrenadeAttackBone)
				if getBone then -- Bone valid
					local bonePos, boneAng = self:GetBonePosition(getBone)
					customEnt:SetPos(bonePos)
					customEnt:SetAngles(boneAng)
					customEnt:FollowBone(self, getBone) -- Calls SetParent internally
				else -- Fail safe! (All cases failed)
					customEnt:SetPos(self:GetShootPos())
					//customEnt:SetAngles(self:GetShootPos():Angle()) -- No need as this is a fail safe anyway
					customEnt:SetParent(self)
				end
			else -- Attachment valid
				local attachData = self:GetAttachment(getAttach)
				customEnt:SetMoveType(MOVETYPE_NONE) -- Must set this for attachments to have any effect!
				customEnt:SetParent(self, getAttach)
				customEnt:SetPos(attachData.Pos)
				customEnt:SetAngles(attachData.Ang)
			end
		else -- Custom position valid
			customEnt:SetPos(customPos)
			customEnt:SetAngles(customPos:Angle())
			customEnt:SetParent(self)
		end
	end

	self.AttackType = VJ.ATTACK_TYPE_GRENADE
	self.AttackState = VJ.ATTACK_STATE_STARTED
	self:PlaySoundSystem("GrenadeAttack")
	
	local releaseTime = self.GrenadeAttackThrowTime
	if !releaseTime then -- Call this right away for event-based attacks!
		attackTimers[VJ.ATTACK_TYPE_GRENADE](self)
	end
	-- "attack_grenade_start" is still called on event-based attacks unlike other attacks because we need to retain the data (customEnt, disableOwner, landDir)...
	-- ...But the timer will be based off of "attack_grenade_reset" to be used as a fail safe in case the animation is cut off!
	-- Call "timer.Adjust("attack_grenade_start" .. self:EntIndex(), 0)" in the event code to make it throw the grenade
	timer.Create("attack_grenade_start" .. self:EntIndex(), (!releaseTime and timer.TimeLeft("attack_grenade_reset" .. self:EntIndex())) or releaseTime / self.AnimPlaybackRate, 1, function()
		if self.AttackSeed == seed then
			if isLiveEnt && !IsValid(customEnt) then return end
			self:ExecuteGrenadeAttack(customEnt, disableOwner, landDir)
		end
	end)
	self:OnGrenadeAttack("PostInit", customEnt, landDir)
	return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Performs a grenade attack
		- customEnt = What entity it should throw | DEFAULT: nil
			- nil = Spawn the NPC's default grenade class usually set by "self.GrenadeAttackEntity"
			- string = Spawn the given entity class as the grenade
			- entity = Use the given entity as the grenade by changing its parent to the NPC and altering its position
		- disableOwner = If set to true, the NPC will not be set as the owner of the grenade, allowing it to damage itself and its allies when applicable!
		- landDir = Direction the grenade should land | Used by the base to align where the grenade is gonna land
			- "Enemy" = Use enemy's position
			- "EnemyLastVis" = Use enemy's last visible position
			- vector = Use given vector's position
			- "FindBest" or nil = Find a best random position
	Returns
		- false, Grenade attack was canceled
		- entity, Grenade entity that was thrown
-----------------------------------------------------------]]
function ENT:ExecuteGrenadeAttack(customEnt, disableOwner, landDir)
	if self.Dead or self.PauseAttacks or self.Flinching or self.AttackType == VJ.ATTACK_TYPE_MELEE then return false end
	local grenade;
	local isLiveEnt = IsValid(customEnt) -- Whether or not the given custom entity is live
	local fuseTime = self.GrenadeAttackFuseTime
	
	-- Handle the grenade's spawn position and angle, in order with priority:
		-- 1. CUSTOM 		If custom position is given then use that, otherwise...
		-- 2. ATTACHMENT 	If a valid attachment is given then use that, otherwise...
		-- 3. BONE 			If a valid bone is given then use that, otherwise...
		-- 4. FAIL 			Use the NPC's shoot position (fail safe)
	local spawnPos = self:OnGrenadeAttack("SpawnPos", customEnt, landDir)
	local spawnAng;
	if !spawnPos then -- If no custom position is given...
		local getAttach = self:LookupAttachment(self.GrenadeAttackAttachment)
		if !getAttach or getAttach == 0 or getAttach == -1 then -- Attachment invalid, try bone...
			local getBone = self:LookupBone(self.GrenadeAttackBone)
			if getBone then -- Bone valid
				spawnPos, spawnAng = self:GetBonePosition(getBone)
			else -- Fail safe! (All cases failed)
				spawnPos = self:GetShootPos()
				spawnAng = self:GetAngles()
			end
		else -- Attachment valid
			local attachData = self:GetAttachment(getAttach)
			spawnPos = attachData.Pos
			spawnAng = attachData.Ang
		end
	else -- Custom position valid
		spawnAng = spawnPos:Angle()
	end
	
	-- Handle NPC turning and grenade landing position
	-- Do NOT set it to actually turn & face because it's pointless at this point since the grenade is already being released!
	local landingPos = self:GetPos() + self:GetForward()*200
	if landDir == "Enemy" then -- Use enemy's position
		landingPos = self:GetEnemyLastKnownPos()
		//if self.GrenadeAttackAnimationFaceEnemy then self:SetTurnTarget("Enemy") end
	elseif landDir == "EnemyLastVis" then -- Use enemy's last visible position
		local eneData = self.EnemyData
		landingPos = eneData.VisiblePos
		//self:SetTurnTarget(eneData.VisiblePos, self.AttackAnimDuration - self.GrenadeAttackThrowTime)
	elseif isvector(landDir) then -- Use given vector's position
		landingPos = landDir
	else -- Find a best random position | Includes "FindBest"
		local bestPos = PICK(VJ.TraceDirections(self, "Quick", 200, true, false, 8))
		if bestPos then
			landingPos = bestPos
			//self:SetTurnTarget(bestPos, self.AttackAnimDuration - self.GrenadeAttackThrowTime)
		end
	end
	
	-- If its a live entity then clean it up and set it as the grenade...
	-- Otherwise, create a new entity with the given custom entity name OR one of NPC's default grenades
	if isLiveEnt then -- It's an existing entity
		customEnt.VJ_ST_Grabbed = false -- Set this to false, as we are no longer holding it!
		-- Clean up by removing the parent, move type, and follow bone effect
		customEnt:SetParent(NULL)
		if customEnt:GetMoveType() == MOVETYPE_NONE && customEnt.VJ_ST_GrabOrgMoveType then customEnt:SetMoveType(customEnt.VJ_ST_GrabOrgMoveType) end
		customEnt:RemoveEffects(EF_FOLLOWBONE)
		grenade = customEnt
		//customEnt:Remove()
	else
		grenade = ents.Create(customEnt or PICK(self.GrenadeAttackEntity))
		if !customEnt then -- Skip model override if function is called with a custom entity string
			local setModel = PICK(self.GrenadeAttackModel)
			if setModel then
				grenade:SetModel(setModel)
			end
		end
	end
	
	if !disableOwner then grenade:SetOwner(self) end
	grenade:SetPos(spawnPos)
	grenade:SetAngles(spawnAng)
	
	if !isLiveEnt then
		-- Set the fuse timers for all the different grenade entities
		local gerClass = grenade:GetClass()
		if gerClass == "obj_vj_grenade" then
			grenade.FuseTime = fuseTime
		elseif gerClass == "npc_grenade_frag" then
			grenade:Input("SetTimer", grenade:GetOwner(), grenade:GetOwner(), fuseTime)
		elseif gerClass == "obj_cpt_grenade" then
			grenade:SetTimer(fuseTime)
		elseif gerClass == "obj_spore" then
			grenade:SetGrenade(true)
		elseif gerClass == "ent_hl1_grenade" then
			grenade:ShootTimed(grenade:GetOwner(), defPos, fuseTime)
		elseif gerClass == "doom3_grenade" or gerClass == "obj_handgrenade" then
			grenade:SetExplodeDelay(fuseTime)
		elseif gerClass == "cw_grenade_thrown" or gerClass == "cw_flash_thrown" or gerClass == "cw_smoke_thrown" then
			grenade:SetOwner(self)
			grenade:Fuse(fuseTime)
		end
		
		self:OnGrenadeAttackExecute("PreSpawn", grenade, customEnt, landDir, landingPos)
		grenade:Spawn()
		grenade:Activate()
	end
	
	-- Handle throw velocity
	local postSpawnResult = self:OnGrenadeAttackExecute("PostSpawn", grenade, customEnt, landDir, landingPos)
	if postSpawnResult != true then
		local vel = postSpawnResult or ((landingPos - grenade:GetPos()) + (self:GetUp()*200 + self:GetForward()*500 + self:GetRight()*math.Rand(-20, 20)))
		local phys = grenade:GetPhysicsObject()
		if IsValid(phys) then
			phys:Wake()
			phys:AddAngleVelocity(Vector(math.Rand(500, 500), math.Rand(500, 500), math.Rand(500, 500)))
			phys:SetVelocity(vel)
		else -- If we don't have a physics object, then attempt to set the entity's velocity directly
			grenade:SetVelocity(vel)
		end
	end
	
	if self.AttackState < VJ.ATTACK_STATE_EXECUTED then
		self.AttackState = VJ.ATTACK_STATE_EXECUTED
		if self.GrenadeAttackThrowTime then
			attackTimers[VJ.ATTACK_TYPE_GRENADE](self)
		end
	end
	return grenade
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
local sdBitSource = bit.bor(SOUND_DANGER, SOUND_CONTEXT_REACT_TO_SOURCE) ---> Combine dropship impact position, Combine gunship turret impact position, Strider minigun impact position
local sdBitCombine = bit.bor(SOUND_DANGER, SOUND_CONTEXT_EXCLUDE_COMBINE) ---> Flechette impact position, Strider foot impact position
local sdBitPlyVehicle = bit.bor(SOUND_DANGER, SOUND_CONTEXT_PLAYER_VEHICLE) ---> Player driving a vehicle
local sdBitMortar = bit.bor(SOUND_DANGER, SOUND_CONTEXT_MORTAR) ---> Combine mortars impact position

3 types of danger detections:
- ent.VJ_ID_Grenade
	- Detected as a grenade
	- Distance based on self.DangerDetectionDistance
	- Ignores grenades from allies
	- BEST USE: Grenade type of entities
- ent.VJ_ID_Danger
	- Detected as a danger
	- Distance based on self.DangerDetectionDistance
	- Ignores dangers from allies
	- BEST USE: Entities that should NOT scare the owner's allies, commonly used for projectiles
- NPC Conditions
	- Detected as a danger
	- Distance based on the sound hint's volume/distance
	- Does NOT ignore, is detected by everyone that catches the hint, including allies
	- BEST USE: Sounds that should scare the owner's allies
-----------------------------------------------------------]]
function ENT:CheckForDangers()
	local selfData = self:GetTable()
	if !selfData.CanDetectDangers or selfData.AttackType == VJ.ATTACK_TYPE_GRENADE or selfData.NextDangerDetectionT > CurTime() then return end
	local regDangerDetected = false -- A regular non-grenade danger has been found (This is done to make sure grenades take priority over other dangers!)
	for _, ent in ipairs(ents.FindInSphere(self:GetPos(), selfData.DangerDetectionDistance)) do
		if (ent.VJ_ID_Danger or ent.VJ_ID_Grenade) && self:Visible(ent) then
			local owner = ent:GetOwner()
			if !(IsValid(owner) && owner.IsVJBaseSNPC && ((self:GetClass() == owner:GetClass()) or (self:Disposition(owner) == D_LI))) then
				if ent.VJ_ID_Danger then regDangerDetected = ent continue end -- If it's a regular danger then just skip it for now
				local funcCustom = self.OnDangerDetected; if funcCustom then funcCustom(self, VJ.DANGER_TYPE_GRENADE, ent) end
				local curTime = CurTime()
				if !self:PlaySoundSystem("GrenadeSight") then self:PlaySoundSystem("DangerSight") end -- No grenade sight sounds? See if we have danger sight sounds
				selfData.NextDangerDetectionT = curTime + 4
				selfData.TakingCoverT = curTime + 4
				-- If has the ability to throw it back, then throw the grenade!
				if selfData.CanRedirectGrenades && selfData.HasGrenadeAttack && ent.VJ_ID_Grabbable && !ent.VJ_ST_Grabbed && ent:GetVelocity():Length() < 400 && VJ.GetNearestDistance(self, ent) < 100 && self:GrenadeAttack(ent, true) then
					selfData.NextGrenadeAttackSoundT = curTime + 3
					return
				end
				-- Was not able to throw back the grenade, so take cover instead!
				self:SCHEDULE_COVER_ORIGIN("TASK_RUN_PATH", function(x)
					x.CanShootWhenMoving = true
					x.TurnData = {Type = VJ.FACE_ENEMY}
				end)
				return
			end
		end
	end
	if regDangerDetected or funcHasCondition(self, COND_HEAR_DANGER) or funcHasCondition(self, COND_HEAR_PHYSICS_DANGER) or funcHasCondition(self, COND_HEAR_MOVE_AWAY) then
		local funcCustom = self.OnDangerDetected
		if funcCustom then
			if regDangerDetected then
				funcCustom(self, VJ.DANGER_TYPE_ENTITY, regDangerDetected)
			else
				funcCustom(self, VJ.DANGER_TYPE_HINT, nil)
			end
		end
		self:PlaySoundSystem("DangerSight")
		local curTime = CurTime()
		selfData.NextDangerDetectionT = curTime + 4
		selfData.TakingCoverT = curTime + 4
		self:SCHEDULE_COVER_ORIGIN("TASK_RUN_PATH", function(x)
			x.CanShootWhenMoving = true
			x.TurnData = {Type = VJ.FACE_ENEMY}
		end)
		return
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:StopAttacks(checkTimers)
	if !self:Alive() then return end
	local selfData = self:GetTable()
	if selfData.VJ_DEBUG && GetConVar("vj_npc_debug_attack"):GetInt() == 1 then VJ.DEBUG_Print(self, "StopAttacks", "Attack type = " .. selfData.AttackType) end
	
	if checkTimers && selfData.AttackType == VJ.ATTACK_TYPE_MELEE && selfData.AttackState < VJ.ATTACK_STATE_EXECUTED then
		attackTimers[VJ.ATTACK_TYPE_MELEE](self, true)
	end
	
	selfData.AttackType = VJ.ATTACK_TYPE_NONE
	selfData.AttackState = VJ.ATTACK_STATE_DONE
	selfData.AttackSeed = 0
	
	self:MaintainAlertBehavior()
end
---------------------------------------------------------------------------------------------------------------------------------------------
local function math_angDif(diff)
    diff = diff % 360
    return diff > 180 and (diff - 360) or diff
end
--
function ENT:UpdatePoseParamTracking(resetPoses)
	local selfData = self:GetTable()
	if !selfData.HasPoseParameterLooking or (!selfData.VJ_IsBeingControlled && (!selfData.WeaponAttackState or (!selfData.EnemyData.Visible && selfData.WeaponAttackState < VJ.WEP_ATTACK_STATE_FIRE))) then return end
	//VJ.GetPoseParameters(self)
	local ene = self:GetEnemy()
	local newPitch = 0
	local newYaw = 0
	local newRoll = 0
	if !resetPoses && IsValid(ene) then
		local myEyePos = self:EyePos()
		local myAng = self:GetAngles()
		local eneAng = (self:GetAimPosition(ene, myEyePos) - myEyePos):Angle()
		newPitch = math_angDif(eneAng.p - myAng.p)
		if selfData.PoseParameterLooking_InvertPitch then newPitch = -newPitch end
		newYaw = math_angDif(eneAng.y - myAng.y)
		if selfData.PoseParameterLooking_InvertYaw then newYaw = -newYaw end
		newRoll = math_angDif(eneAng.z - myAng.z)
		if selfData.PoseParameterLooking_InvertRoll then newRoll = -newRoll end
	elseif !selfData.PoseParameterLooking_CanReset then
		return -- Should it reset its pose parameters if there is no enemies?
	end
	
	local funcCustom = self.OnUpdatePoseParamTracking; if funcCustom then funcCustom(self, newPitch, newYaw, newRoll) end
	local names = selfData.PoseParameterLooking_Names
	local namesPitch = names.pitch
	local namesYaw = names.yaw
	local namesRoll = names.roll
	local speed = selfData.PoseParameterLooking_TurningSpeed
	for x = 1, #namesPitch do
		local pose = namesPitch[x]
		funcSetPoseParameter(self, pose, math_angApproach(funcGetPoseParameter(self, pose), newPitch, speed))
	end
	for x = 1, #namesYaw do
		local pose = namesYaw[x]
		funcSetPoseParameter(self, pose, math_angApproach(funcGetPoseParameter(self, pose), newYaw, speed))
	end
	for x = 1, #namesRoll do
		local pose = namesRoll[x]
		funcSetPoseParameter(self, pose, math_angApproach(funcGetPoseParameter(self, pose), newRoll, speed))
	end
	selfData.UpdatedPoseParam = true
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Determines whether it's about to fire its current weapon
		- checkDistance = Should it check for distance and weapon time too? | DEFAULT = false
		- checkDistanceOnly = Should it only check the above statement? | DEFAULT = false
	Returns
		- Boolean, Whether or not it can fire its active weapon
-----------------------------------------------------------]]
function ENT:CanFireWeapon(checkDistance, checkDistanceOnly)
	if self:OnWeaponCanFire() == false then return false end
	local hasDist = false
	local hasChecks = false
	local selfData = self:GetTable()
	local curWep = selfData.WeaponEntity
	
	if selfData.PauseAttacks or !IsValid(curWep) or self:GetWeaponState() != VJ.WEP_STATE_READY then return false end
	if selfData.VJ_IsBeingControlled then
		checkDistance = false
	else
		local enemyDist = selfData.EnemyData.Distance
		if checkDistance && CurTime() > selfData.NextWeaponAttackT && enemyDist < selfData.Weapon_MaxDistance && ((enemyDist > selfData.Weapon_MinDistance) or curWep.IsMeleeWeapon) then
			hasDist = true
		end
		if checkDistanceOnly then
			return hasDist
		end
	end
	if !selfData.AttackType && !self:IsBusy("Activities") then
		hasChecks = true
		if !checkDistance then return true end
	end
	return hasDist && hasChecks
end
---------------------------------------------------------------------------------------------------------------------------------------------
local schedule_yield_player = vj_ai_schedule.New("SCHEDULE_YIELD_PLAYER")
	schedule_yield_player:EngTask("TASK_MOVE_AWAY_PATH", 120)
	schedule_yield_player:EngTask("TASK_RUN_PATH", 0)
	schedule_yield_player:EngTask("TASK_WAIT_FOR_MOVEMENT", 0)
	schedule_yield_player.CanShootWhenMoving = true
	schedule_yield_player.TurnData = {} -- This is constantly edited!
local bitsDanger = bit.bor(SOUND_BULLET_IMPACT, SOUND_COMBAT, SOUND_WORLD, SOUND_DANGER) // SOUND_PLAYER, SOUND_PLAYER_VEHICLE
--
function ENT:SelectSchedule()
	local selfData = self:GetTable()
	if selfData.VJ_IsBeingControlled or selfData.Dead then return end
	
	local curTime = CurTime()
	local ene = self:GetEnemy()
	local eneValid = IsValid(ene)
	self:PlayIdleSound(nil, nil, eneValid)
	
	-- Idle Behavior --
	if !eneValid then
		if selfData.AttackType != VJ.ATTACK_TYPE_GRENADE then
			self:MaintainIdleBehavior()
		end
		if !selfData.Alerted then
			selfData.TakingCoverT = 0
		end
		selfData.Weapon_UnarmedBehavior_Active = false
		
		-- Investigation: Conditions // funcHasCondition(self, COND_HEAR_PLAYER)
		if selfData.CanInvestigate && (funcHasCondition(self, COND_HEAR_BULLET_IMPACT) or funcHasCondition(self, COND_HEAR_COMBAT) or funcHasCondition(self, COND_HEAR_WORLD) or funcHasCondition(self, COND_HEAR_DANGER)) && selfData.NextInvestigationMove < curTime && selfData.TakingCoverT < curTime && !self:IsBusy() then
			local sdSrc = self:GetBestSoundHint(bitsDanger)
			if sdSrc then
				//PrintTable(sdSrc)
				local allowed = true
				local sdOwner = sdSrc.owner
				if IsValid(sdOwner) then
					-- Ignore dangers produced by vehicles driven by an allies
					if sdSrc.type == SOUND_DANGER && sdOwner:IsVehicle() && IsValid(sdOwner:GetDriver()) && self:Disposition(sdOwner:GetDriver()) == D_LI then
						allowed = false
					-- Ignore dangers by allies and combat sounds (such as death sounds) from dead NPCs
					elseif self:Disposition(sdOwner) == D_LI or (sdSrc.type == SOUND_COMBAT && sdOwner:IsNPC() && !sdOwner:Alive()) then
						allowed = false
					end
				end
				-- For now ignore player sounds because friendly NPCs also see it since the sound owner is NULL
				//if sdSrc.type == SOUND_PLAYER then
				//	if VJ_CVAR_IGNOREPLAYERS or self:IsMoving() or self.IsGuard then
				//		skip = true
				//	end
				//end
				if allowed then
					self:DoReadyAlert()
					self:StopMoving()
					self:SetLastPosition(sdSrc.origin)
					self:SCHEDULE_FACE("TASK_FACE_LASTPOSITION")
					-- Works but just faces the enemy that fired at
					//local sched = vj_ai_schedule.New("SCHEDULE_HEAR_SOUND")
					//sched:EngTask("TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION", 0)
					//sched:EngTask("TASK_STOP_MOVING", 0)
					//sched:EngTask("TASK_FACE_SAVEPOSITION", 0)
					//self:StartSchedule(sched)
					self:OnInvestigate(sdOwner)
					self:PlaySoundSystem("Investigate")
					selfData.TakingCoverT = curTime + 1
				end
			end
		end
		
	-- Combat Behavior --
	else
		local wep = self:GetActiveWeapon()
		local eneData = selfData.EnemyData
		
		-- Check for weapon validity
		if !IsValid(wep) then
			-- Scared behavior system
			if selfData.Weapon_UnarmedBehavior then
				if !self:IsBusy() && curTime > selfData.NextChaseTime then
					selfData.Weapon_UnarmedBehavior_Active = true -- Tells the idle system to use the scared behavior animation
					if !selfData.IsFollowing && eneData.Visible then
						self:SCHEDULE_COVER_ENEMY("TASK_RUN_PATH")
						return
					end
				end
			-- If it doesn't do scared behavior, then make it chase the enemy if it can melee!
			elseif selfData.HasMeleeAttack then
				selfData.Weapon_UnarmedBehavior_Active = false -- In case it was scared, return it back to normal
				selfData.NextDangerDetectionT = curTime + 4 -- Ignore dangers while chasing!
				self:MaintainAlertBehavior()
				return
			end
			self:MaintainIdleBehavior(2)
			//return -- Allow other behaviors like "COND_PLAYER_PUSHING", etc to run
		else
			selfData.Weapon_UnarmedBehavior_Active = false -- In case it was scared, return it back to normal
			
			local enePos_Eye = ene:EyePos()
			local myPos = self:GetPos()
			local myPosCentered = myPos + self:OBBCenter()
			
			-- Retreat from enemy if it's to close
			if eneData.Distance <= selfData.Weapon_RetreatDistance && !wep.IsMeleeWeapon && curTime > selfData.TakingCoverT && curTime > selfData.NextChaseTime && !selfData.AttackType && !selfData.IsFollowing && ene.Behavior != VJ_BEHAVIOR_PASSIVE && !self:DoCoverTrace(myPosCentered, enePos_Eye) then
				local moveCheck = PICK(VJ.TraceDirections(self, "Quick", 200, true, false, 8, true))
				if moveCheck then
					self:SetLastPosition(moveCheck)
					if self:GetWeaponState() == VJ.WEP_STATE_RELOADING then self:SetWeaponState() end
					selfData.TakingCoverT = curTime + 2
					self:SCHEDULE_GOTO_POSITION("TASK_RUN_PATH", function(x) x:EngTask("TASK_FACE_ENEMY", 0) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
					goto goto_conditions
				end
			end
			
			if self:CanFireWeapon(false, false) && self:GetState() != VJ_STATE_ONLY_ANIMATION_NOATTACK then
				-- Enemy to far away or not allowed to fire a weapon
				if eneData.Distance > selfData.Weapon_MaxDistance or curTime < selfData.NextWeaponAttackT then
					self:MaintainAlertBehavior()
					selfData.AllowWeaponOcclusionDelay = false
				-- Check if enemy is in sight, then continue...
				elseif self:CanFireWeapon(true, true) then
					-- I can't see the enemy from my eyes
					if self:DoCoverTrace(self:EyePos(), enePos_Eye, true) then // or (!eneData.Visible)
						if selfData.TakingCoverT > curTime then return end -- Do NOT interrupt when taking cover (such as "CombatDamageResponse")
						if self:GetWeaponState() != VJ.WEP_STATE_RELOADING then
							-- Wait when enemy is occluded
							if selfData.Weapon_OcclusionDelay && selfData.WeaponAttackState != VJ.WEP_ATTACK_STATE_AIM_OCCLUSION && !wep.IsMeleeWeapon && selfData.AllowWeaponOcclusionDelay && (curTime - selfData.WeaponLastShotTime) <= 4.5 && eneData.Distance > selfData.Weapon_OcclusionDelayMinDist then
								selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_AIM_OCCLUSION
								self:MaintainIdleBehavior(2) -- Make it play idle stand (Which will turn into ACT_IDLE_ANGRY)
								selfData.NextChaseTime = curTime + math.Rand(selfData.Weapon_OcclusionDelayTime.a, selfData.Weapon_OcclusionDelayTime.b)
							-- I am hidden, so stand up in case I am crouching if I had detected to be in a hidden position and the enemy may be visible!
							elseif curTime < selfData.LastHiddenZoneT && !self:DoCoverTrace(myPosCentered + self:GetUp()*30, enePos_Eye + self:GetUp()*30, true) then
								self:MaintainIdleBehavior(2) -- Make it play idle stand (Which will turn into ACT_IDLE_ANGRY)
								goto goto_checkwep
							else
								-- Everything failed, go after the enemy!
								if selfData.WeaponAttackState && selfData.WeaponAttackState >= VJ.WEP_ATTACK_STATE_FIRE && selfData.CurrentScheduleName != "SCHEDULE_ALERT_CHASE" && selfData.CurrentScheduleName != "SCHEDULE_ALERT_CHASE_LOS" then
									selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
								end
								self:MaintainAlertBehavior()
							end
						end
						goto goto_conditions
					end
					-- I can see the enemy...
					::goto_checkwep::
					if wep.IsVJBaseWeapon then -- VJ Base weapons
						-- Do proper weapon aim turning, based on "FInAimCone" - https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/server/ai_basenpc.cpp#L2584
						if !selfData.HasPoseParameterLooking then -- Pose parameter looking is disabled then always face
							self:SetTurnTarget("Enemy")
						else
							local wepDif = selfData.Weapon_AimTurnDiff or selfData.Weapon_AimTurnDiff_Def
							local los = ene:GetPos() - myPos
							los.z = 0
							local facingDir = self:GetAngles():Forward() -- Do NOT use sight dir bec some NPCs use their eyes as the dir, it will trick the system to think the NPC is facing the enemy
							facingDir.z = 0
							local coneCalc = facingDir:Dot((los):GetNormalized())
							if coneCalc < wepDif then
								self:SetTurnTarget("Enemy")
								self:UpdatePoseParamTracking(true) -- Reset pose parameters to help with turning snaps
							end
						end
						// self:MaintainAlertBehavior()
						-- if covered, try to move forward by calculating the distance between the prop and the NPC
						local inCover, inCoverTrace = self:DoCoverTrace(myPosCentered, enePos_Eye, false, {SetLastHiddenTime = true})
						local inCoverEnt = inCoverTrace.Entity
						local wepInCover, wepInCoverTrace = self:DoCoverTrace(wep:GetBulletPos(), enePos_Eye, false)
						local wepInCoverEnt = wepInCoverTrace.Entity
						//print("Is covered? ", inCover)
						//print("Is gun covered? ", wepInCover)
						local inCoverEntLiving = false -- The covered entity is NOT a living entity
						if IsValid(inCoverEnt) && inCoverEnt.VJ_ID_Living then
							inCoverEntLiving = true
						end
						if !wep.IsMeleeWeapon then
							-- If friendly in line of fire, then move!
							if inCoverEntLiving && selfData.WeaponAttackState == VJ.WEP_ATTACK_STATE_FIRE_STAND && curTime > selfData.TakingCoverT && IsValid(wepInCoverEnt) && wepInCoverEnt:IsNPC() && wepInCoverEnt != self && (self:Disposition(wepInCoverEnt) == D_LI or self:Disposition(wepInCoverEnt) == D_NU) && wepInCoverTrace.HitPos:Distance(wepInCoverTrace.StartPos) <= 3000 then
								local moveCheck = PICK(VJ.TraceDirections(self, "Quick", 50, true, false, 4, true, true))
								if moveCheck then
									self:StopMoving()
									if selfData.IsGuard then self.GuardData.Position = moveCheck; self.GuardData.Direction = moveCheck + self:GetForward() * 51 end -- Set the guard position to this new position that avoids friendly fire
									self:SetLastPosition(moveCheck)
									selfData.NextChaseTime = curTime + 1
									self:SCHEDULE_GOTO_POSITION("TASK_WALK_PATH", function(x) x:EngTask("TASK_FACE_ENEMY", 0) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
								end
							end
							
							-- NPC is behind cover...
							if inCover then
								-- Behind cover and I am taking cover, don't fire!
								if curTime < selfData.TakingCoverT then
									goto goto_conditions
								elseif curTime > selfData.NextMoveOnGunCoveredT && ((inCoverTrace.HitPos:Distance(myPos) > 150 && !inCoverEntLiving) or (wepInCover && !wepInCoverEnt.VJ_ID_Living)) then
									selfData.AllowWeaponOcclusionDelay = false
									local nearestPos;
									local nearestEntPos;
									if IsValid(inCoverEnt) then
										nearestPos, nearestEntPos = VJ.GetNearestPositions(self, inCoverEnt)
										nearestPos.z = myPos.z; nearestEntPos.z = myPos.z -- Floor the Z-axis as it can be used for a movement position!
									else
										nearestPos, nearestEntPos = self:NearestPoint(inCoverTrace.HitPos), inCoverTrace.HitPos
									end
									nearestEntPos = nearestEntPos - self:GetForward()*15
									if nearestPos:Distance(nearestEntPos) <= (selfData.IsGuard and 100 or 1000) then
										if selfData.IsGuard then self.GuardData.Position = nearestEntPos; self.GuardData.Direction = nearestEntPos + self:GetForward() * 51 end -- Set the guard position to this new position that provides cover
										self:SetLastPosition(nearestEntPos)
										//VJ.DEBUG_TempEnt(nearestEntPos, self:GetAngles(), Color(0, 255, 255))
										local schedule = vj_ai_schedule.New("SCHEDULE_GOTO_POSITION")
										schedule:EngTask("TASK_GET_PATH_TO_LASTPOSITION", 0)
										local coverRunAnim = self:TranslateActivity(PICK(selfData.AnimTbl_MoveToCover))
										if VJ.AnimExists(self, coverRunAnim) then
											self:SetMovementActivity(coverRunAnim)
										else -- Only shoot if we aren't crouching running!
											schedule.CanShootWhenMoving = true
										end
										schedule:EngTask("TASK_WAIT_FOR_MOVEMENT", 0)
										schedule.TurnData = {Type = VJ.FACE_ENEMY}
										//schedule.StopScheduleIfNotMoving_Any = true
										self:StartSchedule(schedule)
										//self:SCHEDULE_GOTO_POSITION("TASK_WALK_PATH", function(x) x:EngTask("TASK_FACE_ENEMY", 0) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
									end
									selfData.NextMoveOnGunCoveredT = curTime + 2
									return
								end
							//else -- NPC is NOT behind cover
							end
						end
						
						if curTime > selfData.NextWeaponAttackT && curTime > selfData.NextWeaponAttackT_Base then
							-- Melee weapons
							if wep.IsMeleeWeapon then
								self:OnWeaponAttack()
								local finalAnim = self:TranslateActivity(PICK(selfData.AnimTbl_WeaponAttack))
								if curTime > selfData.NextMeleeWeaponAttackT && VJ.AnimExists(self, finalAnim) then // && !VJ.IsCurrentAnim(self, finalAnim)
									local animDur = VJ.AnimDuration(self, finalAnim)
									wep.NPC_NextPrimaryFire = animDur -- Make melee weapons dynamically change the next primary fire
									wep:NPCShoot_Primary()
									VJ.EmitSound(self, wep.NPC_BeforeFireSound, wep.NPC_BeforeFireSoundLevel, math.Rand(wep.NPC_BeforeFireSoundPitch.a, wep.NPC_BeforeFireSoundPitch.b))
									selfData.NextMeleeWeaponAttackT = curTime + animDur
									selfData.WeaponAttackAnim = finalAnim
									self:PlayAnim(finalAnim, false, false, true)
									selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_FIRE_STAND
								end
							-- Ranged weapons
							else
								selfData.AllowWeaponOcclusionDelay = true
								local hasAmmo = wep:Clip1() > 0 -- Does it have ammo?
								if !hasAmmo && selfData.WeaponAttackState != VJ.WEP_ATTACK_STATE_AIM then
									selfData.WeaponAttackAnim = ACT_INVALID
								end
								-- If it's already doing a firing animation, then do NOT restart the animation
								if VJ.IsCurrentAnim(self, self:TranslateActivity(selfData.WeaponAttackAnim)) then
									selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_FIRE_STAND
								-- If the current activity isn't the last weapon animation and it's not a transition, then continue
								elseif self:GetActivity() != selfData.WeaponAttackAnim && self:GetActivity() != ACT_TRANSITION then
									self:OnWeaponAttack()
									if selfData.WeaponAttackState == VJ.WEP_ATTACK_STATE_AIM_OCCLUSION then
										selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
									end
									selfData.WeaponLastShotTime = curTime
									//selfData.NextWeaponStrafeT = curTime + 2
									local finalAnim = false
									-- Check if the NPC has ammo
									if !hasAmmo then
										self:MaintainIdleBehavior(2) -- Make it play idle stand (Which will turn into ACT_IDLE_ANGRY)
										//finalAnim = self:TranslateActivity(PICK(selfData.AnimTbl_WeaponAim))
										selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_AIM
									else
										-- Crouch fire
										local anim_crouch = self:TranslateActivity(PICK(selfData.AnimTbl_WeaponAttackCrouch))
										if selfData.Weapon_CanCrouchAttack && !inCover && !wepInCover && eneData.Distance > 500 && VJ.AnimExists(self, anim_crouch) && math.random(1, selfData.Weapon_CrouchAttackChance) == 1 && !self:DoCoverTrace(wep:GetBulletPos() + self:GetUp() * -18, enePos_Eye, true) then
											finalAnim = anim_crouch
										-- Standing fire
										else
											finalAnim = self:TranslateActivity(PICK(selfData.AnimTbl_WeaponAttack))
										end
									end
									if finalAnim && VJ.AnimExists(self, finalAnim) && (!VJ.IsCurrentAnim(self, finalAnim) or !selfData.WeaponAttackState) then
										VJ.EmitSound(self, wep.NPC_BeforeFireSound, wep.NPC_BeforeFireSoundLevel, math.Rand(wep.NPC_BeforeFireSoundPitch.a, wep.NPC_BeforeFireSoundPitch.b))
										self:PlayAnim(finalAnim, false, 0, true)
										selfData.WeaponAttackAnim = finalAnim
										selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_FIRE_STAND
										selfData.NextWeaponAttackT_Base = curTime + 0.2
									end
								end
							end
						end
						-- Move randomly when shooting
						if selfData.Weapon_Strafe && !inCover && !selfData.IsGuard && !selfData.IsFollowing && !wep.IsMeleeWeapon && (!wep.NPC_StandingOnly) && selfData.WeaponAttackState == VJ.WEP_ATTACK_STATE_FIRE_STAND && curTime > selfData.NextWeaponStrafeT && (curTime - eneData.TimeAcquired) > 2 && (eneData.Distance < (selfData.Weapon_MaxDistance / 1.25)) then
							if self:OnWeaponStrafe() != false then
								local moveCheck = PICK(VJ.TraceDirections(self, "Radial", math.random(150, 400), true, false, 12, true))
								if moveCheck then
									self:StopMoving()
									self:SetLastPosition(moveCheck)
									self:SCHEDULE_GOTO_POSITION(math.random(1, 2) == 1 and "TASK_RUN_PATH" or "TASK_WALK_PATH", function(x) x:EngTask("TASK_FACE_ENEMY", 0) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
								end
							end
							selfData.NextWeaponStrafeT = curTime + math.Rand(selfData.Weapon_StrafeCooldown.a, selfData.Weapon_StrafeCooldown.b)
						end
					else -- None VJ Base weapons
						self:SetTurnTarget("Enemy")
						selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_FIRE_STAND
						self:OnWeaponAttack()
						selfData.WeaponLastShotTime = curTime
						//wep:SetClip1(99999)
						self:SetSchedule(SCHED_RANGE_ATTACK1)
					end
				end
			end
		end
	end
	
	::goto_conditions::
	-- Handle move away behavior
	if funcHasCondition(self, COND_PLAYER_PUSHING) && curTime > selfData.TakingCoverT && !self:IsBusy("Activities") then
		self:PlaySoundSystem("YieldToPlayer")
		if eneValid then -- Face current enemy
			schedule_yield_player.TurnData.Type = VJ.FACE_ENEMY_VISIBLE
			schedule_yield_player.TurnData.Target = nil
		elseif IsValid(self:GetTarget()) then -- Face current target
			schedule_yield_player.TurnData.Type = VJ.FACE_ENTITY_VISIBLE
			schedule_yield_player.TurnData.Target = self:GetTarget()
		else -- Reset if both others fail! (Remember this is a localized table shared between all NPCs!)
			schedule_yield_player.TurnData.Type = nil
			schedule_yield_player.TurnData.Target = nil
		end
		self:StartSchedule(schedule_yield_player)
		selfData.TakingCoverT = curTime + 2
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:ResetEnemy(checkAllies, checkVis)
	local selfData = self:GetTable()
	if selfData.Dead or (selfData.VJ_IsBeingControlled && selfData.VJ_TheControllerBullseye == self:GetEnemy()) then selfData.EnemyData.Reset = false return false end
	local ene = self:GetEnemy()
	local eneValid = IsValid(ene)
	local eneData = selfData.EnemyData
	local curTime = CurTime()
	if checkAllies then
		local getAllies = self:Allies_Check(1000)
		if getAllies then
			for _, ally in ipairs(getAllies) do
				local allyEne = ally:GetEnemy()
				if IsValid(allyEne) && (curTime - ally.EnemyData.VisibleTime) < selfData.EnemyTimeout && allyEne:Alive() && self:GetPos():Distance(allyEne:GetPos()) <= self:GetMaxLookDistance() && self:CheckRelationship(allyEne) == D_HT then
					selfData.AllowWeaponOcclusionDelay = false
					self:ForceSetEnemy(allyEne, false)
					eneData.VisibleTime = curTime -- Reset the time otherwise it will run "ResetEnemy" none-stop!
					eneData.Reset = false
					return false
				end
			end
		end
	end
	if checkVis then
		-- If the current number of reachable enemies is higher then 1, then don't reset
		local curEnemies = eneData.VisibleCount //selfData.CurrentReachableEnemies
		if (eneValid && (curEnemies - 1) >= 1) or (!eneValid && curEnemies >= 1) then
			self:MaintainRelationships() -- Select a new enemy
			-- Check that the reset enemy wasn't the only visible enemy
			-- If we don't this, it will call "ResetEnemy" again!
			if eneData.VisibleCount > 0 then
				eneData.Reset = false
				return false
			end
		end
	end
	
	if selfData.VJ_DEBUG && GetConVar("vj_npc_debug_resetenemy"):GetInt() == 1 then VJ.DEBUG_Print(self, "ResetEnemy", tostring(ene)) end
	eneData.Reset = true
	self:SetNPCState(NPC_STATE_ALERT)
	timer.Create("alert_reset" .. self:EntIndex(), math.Rand(selfData.AlertTimeout.a, selfData.AlertTimeout.b), 1, function() if !IsValid(self:GetEnemy()) then selfData.Alerted = false self:SetNPCState(NPC_STATE_IDLE) end end)
	self:OnResetEnemy()
	local moveToEnemy = false
	if eneValid then
		if !selfData.IsFollowing && !selfData.IsGuard && !selfData.IsVJBaseSNPC_Tank && !selfData.VJ_IsBeingControlled && selfData.LastHiddenZone_CanWander == true && !selfData.Weapon_UnarmedBehavior_Active && selfData.Behavior != VJ_BEHAVIOR_PASSIVE && selfData.Behavior != VJ_BEHAVIOR_PASSIVE_NATURE && !self:IsBusy() && !self:Visible(ene) && self:GetEnemyLastKnownPos() != defPos then
			moveToEnemy = self:GetEnemyLastKnownPos()
		end
		self:MarkEnemyAsEluded(ene)
		//self:ClearEnemyMemory(ene) // Completely resets the enemy memory
		self:AddEntityRelationship(ene, D_NU, 10)
	end
	
	selfData.LastHiddenZone_CanWander = curTime > selfData.LastHiddenZoneT and true or false
	selfData.LastHiddenZoneT = 0
	
	-- Clear memory of the enemy if it's not a player AND it's dead
	if eneValid && !ene:IsPlayer() && !ene:Alive() then
		//print("Clear memory", ene)
		self:ClearEnemyMemory(ene)
	end
	-- This is needed for the human base because when taking cover from enemy, the AI can get stuck in a loop (EX: When selfData.Weapon_UnarmedBehavior_Active is true!)
	if selfData.CurrentScheduleName == "SCHEDULE_COVER_ENEMY" or selfData.CurrentScheduleName == "SCHEDULE_COVER_ENEMY_FAIL" then
		self:StopMoving()
	end
	selfData.NextWanderTime = curTime + math.Rand(3, 5)
	self:SetEnemy(NULL)
	if moveToEnemy then
		self:SetLastPosition(moveToEnemy)
		self:SCHEDULE_GOTO_POSITION("TASK_WALK_PATH", function(schedule)
			//if eneValid then schedule:EngTask("TASK_FORGET", ene) end
			//schedule:EngTask("TASK_IGNORE_OLD_ENEMIES", 0)
			schedule.ResetOnFail = true
			schedule.CanShootWhenMoving = true
			schedule.CanBeInterrupted = true
			schedule.TurnData = {Type = VJ.FACE_ENEMY}
		end)
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnTakeDamage(dmginfo)
	local dmgAttacker = dmginfo:GetAttacker()
	if !IsValid(dmgAttacker) then dmgAttacker = false end
	
	-- Don't take bullet damage from friendly NPCs
	if dmgAttacker && dmginfo:IsBulletDamage() && dmgAttacker:IsNPC() && dmgAttacker:Disposition(self) != D_HT && (dmgAttacker:GetClass() == self:GetClass() or self:Disposition(dmgAttacker) == D_LI) then return 0 end
	
	local dmgInflictor = dmginfo:GetInflictor()
	if !IsValid(dmgInflictor) then dmgInflictor = false end
	
	-- Attempt to avoid taking damage when walking on ragdolls
	if dmgInflictor && dmgInflictor:GetClass() == "prop_ragdoll" && dmgInflictor:GetVelocity():Length() <= 100 then return 0 end
	
	local selfData = self:GetTable()
	local hitgroup = self:GetLastDamageHitGroup()
	self:OnDamaged(dmginfo, hitgroup, "Init")
	if selfData.GodMode or dmginfo:GetDamage() <= 0 then return 0 end
	
	local dmgType = dmginfo:GetDamageType()
	local curTime = CurTime()
	local isFireEnt = false
	if self:IsOnFire() then
		isFireEnt = dmgInflictor && dmgAttacker && dmgInflictor:GetClass() == "entityflame" && dmgAttacker:GetClass() == "entityflame"
		if self:WaterLevel() > 1 then self:Extinguish() end -- If we are in water, then extinguish the fire
	end
	
	-- If it should always take damage from huge monsters, then skip immunity checks!
	if dmgAttacker && selfData.ForceDamageFromBosses && dmgAttacker.VJ_ID_Boss then
		goto skip_immunity
	end
	
	-- Immunity checks
	if isFireEnt && !selfData.AllowIgnition then self:Extinguish() return 0 end
	if (selfData.Immune_Fire && (dmgType == DMG_BURN or dmgType == DMG_SLOWBURN or isFireEnt)) or (selfData.Immune_Toxic && (dmgType == DMG_ACID or dmgType == DMG_RADIATION or dmgType == DMG_POISON or dmgType == DMG_NERVEGAS or dmgType == DMG_PARALYZE)) or (selfData.Immune_Bullet && (dmginfo:IsBulletDamage() or dmgType == DMG_BULLET or dmgType == DMG_AIRBOAT or dmgType == DMG_BUCKSHOT or dmgType == DMG_SNIPER)) or (selfData.Immune_Explosive && (dmgType == DMG_BLAST or dmgType == DMG_BLAST_SURFACE or dmgType == DMG_MISSILEDEFENSE)) or (selfData.Immune_Dissolve && dmginfo:IsDamageType(DMG_DISSOLVE)) or (selfData.Immune_Electricity && (dmgType == DMG_SHOCK or dmgType == DMG_ENERGYBEAM or dmgType == DMG_PHYSGUN)) or (selfData.Immune_Melee && (dmgType == DMG_CLUB or dmgType == DMG_SLASH)) or (selfData.Immune_Sonic && dmgType == DMG_SONIC) then return 0 end
	
	-- Make sure combine ball does reasonable damage and doesn't spam!
	if (dmgInflictor && dmgInflictor:GetClass() == "prop_combine_ball") or (dmgAttacker && dmgAttacker:GetClass() == "prop_combine_ball") then
		if selfData.Immune_Dissolve then return 0 end
		if curTime > selfData.NextCombineBallDmgT then
			dmginfo:SetDamage(math.random(400, 500))
			dmginfo:SetDamageType(DMG_DISSOLVE)
			selfData.NextCombineBallDmgT = curTime + 0.2
		else
			return 0
		end
	end
	::skip_immunity::
	
	local function DoBleed()
		if selfData.Bleeds then
			self:OnBleed(dmginfo, hitgroup)
			-- Spawn the blood particle only if it's not caused by the default fire entity [Causes the damage position to be at Vector(0, 0, 0)]
			if selfData.HasBloodParticle && !isFireEnt then self:SpawnBloodParticles(dmginfo, hitgroup) end
			if selfData.HasBloodDecal then self:SpawnBloodDecals(dmginfo, hitgroup) end
			self:PlaySoundSystem("Impact")
		end
	end
	if selfData.Dead then DoBleed() return 0 end -- If dead then just bleed but take no damage
	
	self:OnDamaged(dmginfo, hitgroup, "PreDamage")
	if dmginfo:GetDamage() <= 0 then return 0 end -- Only take damage if it's above 0!
	-- Why? Because GMod resets/randomizes dmginfo after a tick...
	selfData.SavedDmgInfo = {
		dmginfo = dmginfo, -- The actual CTakeDamageInfo object | WARNING: Can be corrupted after a tick, recommended not to use this!
		attacker = dmginfo:GetAttacker(),
		inflictor = dmginfo:GetInflictor(),
		amount = dmginfo:GetDamage(),
		pos = dmginfo:GetDamagePosition(),
		type = dmginfo:GetDamageType(),
		force = dmginfo:GetDamageForce(),
		ammoType = dmginfo:GetAmmoType(),
		hitgroup = hitgroup,
	}
	self:SetHealth(self:Health() - dmginfo:GetDamage())
	if selfData.VJ_DEBUG && GetConVar("vj_npc_debug_damage"):GetInt() == 1 then VJ.DEBUG_Print(self, "OnTakeDamage", "Amount = ", dmginfo:GetDamage(), " | Attacker = ", dmgAttacker, " | Inflictor = ", dmgInflictor) end
	local healthRegen = selfData.HealthRegenParams
	if healthRegen.Enabled && healthRegen.ResetOnDmg then
		selfData.HealthRegenDelayT = curTime + (math.Rand(healthRegen.Delay.a, healthRegen.Delay.b) * 1.5)
	end
	self:SetSaveValue("m_iDamageCount", self:GetTotalDamageCount() + 1)
	self:SetSaveValue("m_flLastDamageTime", curTime)
	self:OnDamaged(dmginfo, hitgroup, "PostDamage")
	DoBleed()
	
	-- I/O events, from: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/game/server/ai_basenpc.cpp#L764
	if dmgAttacker then
		self:TriggerOutput("OnDamaged", dmgAttacker)
		self:MarkTookDamageFromEnemy(dmgAttacker)
	else
		self:TriggerOutput("OnDamaged", self)
	end
	
	local stillAlive = self:Health() > 0
	if stillAlive then self:PlaySoundSystem("Pain") end

	if VJ_CVAR_AI_ENABLED && self:GetState() != VJ_STATE_FREEZE then
		local isPassive = selfData.Behavior == VJ_BEHAVIOR_PASSIVE or selfData.Behavior == VJ_BEHAVIOR_PASSIVE_NATURE
		if stillAlive then
			if !isFireEnt then
				self:Flinch(dmginfo, hitgroup)
			end
			
			-- Player attackers
			if dmgAttacker && dmgAttacker:IsPlayer() then
				-- Become enemy to a friendly player | RESULT: May become hostile to an allied player
				if selfData.BecomeEnemyToPlayer && self:CheckRelationship(dmgAttacker) == D_LI then
					local relationMemory = selfData.RelationshipMemory[dmgAttacker]
					self:SetRelationshipMemory(dmgAttacker, VJ.MEM_HOSTILITY_LEVEL, relationMemory[VJ.MEM_HOSTILITY_LEVEL] and relationMemory[VJ.MEM_HOSTILITY_LEVEL] + 1 or 1)
					if relationMemory[VJ.MEM_HOSTILITY_LEVEL] > selfData.BecomeEnemyToPlayer && self:Disposition(dmgAttacker) != D_HT then
						self:OnBecomeEnemyToPlayer(dmginfo, hitgroup)
						if selfData.IsFollowing && selfData.FollowData.Target == dmgAttacker then self:ResetFollowBehavior() end
						self:SetRelationshipMemory(dmgAttacker, VJ.MEM_OVERRIDE_DISPOSITION, D_HT)
						self:AddEntityRelationship(dmgAttacker, D_HT, 2)
						selfData.TakingCoverT = curTime + 2
						self:PlaySoundSystem("BecomeEnemyToPlayer")
						if !IsValid(self:GetEnemy()) then
							self:StopMoving()
							self:SetTarget(dmgAttacker)
							self:SCHEDULE_FACE("TASK_FACE_TARGET")
						end
						if selfData.CanChatMessage then
							dmgAttacker:PrintMessage(HUD_PRINTTALK, self:GetName() .. " no longer likes you.")
						end
					end
				end
			
				-- React to damage by a player
					-- 0 = Run it every time | 1 = Run it only when friendly to player | 2 = Run it only when enemy to player
				if selfData.HasDamageByPlayerSounds && curTime > selfData.NextDamageByPlayerSoundT && self:Visible(dmgAttacker) then
					local dispLvl = selfData.DamageByPlayerDispositionLevel
					if (dispLvl == 0 or (dispLvl == 1 && self:Disposition(dmgAttacker) == D_LI) or (dispLvl == 2 && self:Disposition(dmgAttacker) != D_HT)) then
						self:PlaySoundSystem("DamageByPlayer")
					end
				end
			end
			
			self:PlaySoundSystem("Pain")
			
			-- Move away or hide behind object when damaged while enemy is valid | RESULT: May play a hiding animation OR move to take cover from enemy
			local eneData = selfData.EnemyData
			if !isPassive && selfData.CombatDamageResponse && IsValid(eneData.Target) && curTime > selfData.NextCombatDamageResponseT && !selfData.IsFollowing && !selfData.AttackType && !self:IsBusy() && curTime > selfData.TakingCoverT && eneData.Visible && self:GetWeaponState() != VJ.WEP_STATE_RELOADING && eneData.Distance < selfData.Weapon_MaxDistance then
				local wep = self:GetActiveWeapon()
				local canMove = true
				if self:DoCoverTrace(self:GetPos() + self:OBBCenter(), eneData.Target:EyePos()) then
					local hideTime = math.Rand(selfData.CombatDamageResponse_CoverTime.a, selfData.CombatDamageResponse_CoverTime.b)
					local anim = self:PlayAnim(selfData.AnimTbl_TakingCover, false, hideTime, false) -- Don't set lockAnim because we want it to shoot if an enemy is suddenly visible!
					if anim != ACT_INVALID then
						selfData.NextChaseTime = curTime + hideTime
						selfData.TakingCoverT = curTime + hideTime
						selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
						selfData.NextCombatDamageResponseT = curTime + math.random(selfData.CombatDamageResponse_Cooldown.a, selfData.CombatDamageResponse_Cooldown.b)
						canMove = false
					end
				end
				if canMove && !self:IsMoving() && (!IsValid(wep) or (IsValid(wep) && !wep.IsMeleeWeapon)) then -- Run away if not moving AND has a non-melee weapon
					self:SCHEDULE_COVER_ENEMY("TASK_RUN_PATH", function(x) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
					selfData.NextCombatDamageResponseT = curTime + math.random(selfData.CombatDamageResponse_Cooldown.a, selfData.CombatDamageResponse_Cooldown.b)
				end
			end
			
			if !isPassive && !IsValid(self:GetEnemy()) then
				local canMove = true
				
				-- How allies respond when it's damaged
				if selfData.DamageAllyResponse && curTime > selfData.NextDamageAllyResponseT && !selfData.IsFollowing then
					local responseDist = math_max(800, self:OBBMaxs():Distance(self:OBBMins()) * 12)
					local allies = self:Allies_Check(responseDist)
					if allies != false then
						if !isFireEnt then
							self:Allies_Bring("Diamond", responseDist, allies, 4)
						end
						for _, ally in ipairs(allies) do
							ally:DoReadyAlert()
						end
						if !isFireEnt && !self:IsBusy("Activities") then
							self:DoReadyAlert()
							local anim = self:PlayAnim(selfData.AnimTbl_DamageAllyResponse, true, false, true)
							if anim != ACT_INVALID then
								canMove = false
								selfData.NextFlinchT = curTime + 1
							end
						end
						selfData.NextDamageAllyResponseT = curTime + math.Rand(selfData.DamageAllyResponse_Cooldown.a, selfData.DamageAllyResponse_Cooldown.b)
					end
				end
				
				local dmgResponse = selfData.DamageResponse
				if dmgResponse && curTime > selfData.TakingCoverT && !self:IsBusy("Activities") then
					-- Attempt to find who damaged me | RESULT: May become alerted if attacker is visible OR it may hide if it didn't find the attacker
					if dmgAttacker && (dmgResponse == true or dmgResponse == "OnlySearch") then
						local sightDist = self:GetMaxLookDistance()
						sightDist = math_min(math_max(sightDist / 2, sightDist <= 1000 and sightDist or 1000), sightDist)
						-- IF normal sight dist is less than 1000 then change nothing, OR ELSE use half the distance with 1000 as minimum
						if self:GetPos():Distance(dmgAttacker:GetPos()) <= sightDist && self:Visible(dmgAttacker) then
							local dispLvl = self:CheckRelationship(dmgAttacker)
							if dispLvl == D_HT or dispLvl == D_NU then
								//self:AddEntityRelationship(dmgAttacker, D_HT, 10)
								self:OnSetEnemyFromDamage(dmginfo, hitgroup)
								selfData.NextCallForHelpT = curTime + 1
								self:ForceSetEnemy(dmgAttacker, true)
								self:MaintainAlertBehavior()
								canMove = false
							end
						end
					end
					
					-- If all else failed then take cover!
					if canMove && (dmgResponse == true or dmgResponse == "OnlyMove") && !selfData.IsFollowing && selfData.MovementType != VJ_MOVETYPE_STATIONARY && dmginfo:GetDamageCustom() != VJ.DMG_BLEED then
						self:SCHEDULE_COVER_ORIGIN("TASK_RUN_PATH", function(x) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
						selfData.TakingCoverT = curTime + 5
					end
				end
			-- Passive NPCs
			elseif isPassive && curTime > selfData.TakingCoverT then
				if selfData.DamageResponse && !self:IsBusy() then
					self:SCHEDULE_COVER_ORIGIN("TASK_RUN_PATH")
				end
			end
		end
		
		-- Make passive NPCs move away | RESULT: May move away AND may cause other passive NPCs to move as well
		if isPassive && curTime > selfData.TakingCoverT then
			if selfData.Passive_AlliesRunOnDamage then -- Make passive allies run too!
				local allies = self:Allies_Check(math_max(800, self:OBBMaxs():Distance(self:OBBMins()) * 20))
				if allies != false then
					for _, ally in ipairs(allies) do
						ally.TakingCoverT = curTime + math.Rand(6, 7)
						ally:SCHEDULE_COVER_ORIGIN("TASK_RUN_PATH")
						ally:PlaySoundSystem("Alert")
					end
				end
			end
			selfData.TakingCoverT = curTime + math.Rand(6, 7)
		end
	end
	
	-- If eating, stop!
	if selfData.CanEat && selfData.VJ_ST_Eating then
		selfData.EatingData.NextCheck = curTime + 15
		self:ResetEatingBehavior("Injured")
	end
	
	if self:Health() <= 0 && !selfData.Dead then
		self:RemoveEFlags(EFL_NO_DISSOLVE)
		if (dmginfo:IsDamageType(DMG_DISSOLVE)) or (dmgInflictor && dmgInflictor:GetClass() == "prop_combine_ball") then
			local dissolve = DamageInfo()
			dissolve:SetDamage(self:Health())
			dissolve:SetAttacker(dmginfo:GetAttacker())
			dissolve:SetDamageType(DMG_DISSOLVE)
			self:TakeDamageInfo(dissolve)
		end
		self:BeginDeath(dmginfo, hitgroup)
	end
	return 1
end
---------------------------------------------------------------------------------------------------------------------------------------------
local vecZ500 = Vector(0, 0, 500)
local vecZ4 = Vector(0, 0, 4)
--
function ENT:BeginDeath(dmginfo, hitgroup)
	self.Dead = true
	self:SetSaveValue("m_lifeState", 1) -- LIFE_DYING
	self:OnDeath(dmginfo, hitgroup, "Init")
	if self.MedicData.Status then self:ResetMedicBehavior() end
	if self.IsFollowing then self:ResetFollowBehavior() end
	local dmgInflictor = dmginfo:GetInflictor()
	local dmgAttacker = dmginfo:GetAttacker()
	local myPos = self:GetPos()
	
	if VJ_CVAR_AI_ENABLED then
		local responseDist = math_max(800, self:OBBMaxs():Distance(self:OBBMins()) * 12)
		local allies = self:Allies_Check(responseDist)
		if allies then
			local doBecomeEnemyToPlayer = (self.BecomeEnemyToPlayer && dmgAttacker:IsPlayer() && !VJ_CVAR_IGNOREPLAYERS) or false
			local responseType = self.DeathAllyResponse
			local movedAllyNum = 0 -- Number of allies that have moved
			for _, ally in ipairs(allies) do
				ally:OnAllyKilled(self)
				ally:PlaySoundSystem("AllyDeath")
				
				if responseType && myPos:Distance(ally:GetPos()) < responseDist then
					local moved = false
					-- Bring ally
					if responseType == true && movedAllyNum < self.DeathAllyResponse_MoveLimit then
						moved = self:Allies_Bring("Random", responseDist, {ally}, 0, true)
						if moved then
							movedAllyNum = movedAllyNum + 1
						end
					end
					-- Alert ally
					if (responseType == true or responseType == "OnlyAlert") && !IsValid(ally:GetEnemy()) then
						ally:DoReadyAlert()
						if !moved then
							local faceTime = math.Rand(5, 8)
							ally:SetTurnTarget(myPos, faceTime, true)
							ally.NextIdleTime = CurTime() + faceTime
						end
					end
				end
				
				-- BecomeEnemyToPlayer
				if doBecomeEnemyToPlayer && ally.BecomeEnemyToPlayer && ally:Disposition(dmgAttacker) == D_LI then
					local relationMemory = ally.RelationshipMemory[dmgAttacker]
					ally:SetRelationshipMemory(dmgAttacker, VJ.MEM_HOSTILITY_LEVEL, relationMemory[VJ.MEM_HOSTILITY_LEVEL] and relationMemory[VJ.MEM_HOSTILITY_LEVEL] + 1 or 1)
					if relationMemory[VJ.MEM_HOSTILITY_LEVEL] > ally.BecomeEnemyToPlayer then
						if ally:Disposition(dmgAttacker) != D_HT then
							ally:OnBecomeEnemyToPlayer(dmginfo, hitgroup)
							if ally.IsFollowing && ally.FollowData.Target == dmgAttacker then ally:ResetFollowBehavior() end
							ally:SetRelationshipMemory(dmgAttacker, VJ.MEM_OVERRIDE_DISPOSITION, D_HT)
							ally:AddEntityRelationship(dmgAttacker, D_HT, 2)
							if ally.CanChatMessage then
								dmgAttacker:PrintMessage(HUD_PRINTTALK, ally:GetName() .. " no longer likes you.")
							end
							ally:PlaySoundSystem("BecomeEnemyToPlayer")
						end
						ally.Alerted = true
					end
				end
			end
		end
	end
	
	-- Blood decal on the ground
	if self.Bleeds && self.HasBloodDecal then
		local bloodDecal = PICK(self.BloodDecal)
		if bloodDecal then
			local decalPos = myPos + vecZ4
			self:SetLocalPos(decalPos) -- NPC is too close to the ground, we need to move it up a bit
			local tr = util.TraceLine({start = decalPos, endpos = decalPos - vecZ500, filter = self})
			util.Decal(bloodDecal, tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal)
		end
	end
	
	self:RemoveTimers()
	self:StopAllSounds()
	self.AttackType = VJ.ATTACK_TYPE_NONE
	self.HasMeleeAttack = false
	if IsValid(dmgAttacker) then
		if dmgAttacker:GetClass() == "npc_barnacle" then self.HasDeathCorpse = false end -- Don't make a corpse if it's killed by a barnacle!
		if vj_npc_ply_frag:GetInt() == 1 && dmgAttacker:IsPlayer() then dmgAttacker:AddFrags(1) end
		if IsValid(dmgInflictor) then
			gamemode.Call("OnNPCKilled", self, dmgAttacker, dmgInflictor, dmginfo)
		end
	end
	self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
	self:GibOnDeath(dmginfo, hitgroup)
	self:PlaySoundSystem("Death")
	//if (self.MovementType == VJ_MOVETYPE_AERIAL or self.MovementType == VJ_MOVETYPE_AQUATIC) then self:AA_StopMoving() end
	
	-- I/O events, from: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/server/basecombatcharacter.cpp#L1582
	if IsValid(dmgAttacker) then -- Someone else killed me
		self:TriggerOutput("OnDeath", dmgAttacker)
		dmgAttacker:Fire("KilledNPC", "", 0, self, self) -- Allows player companions (npc_citizen) to respond to kill
	else
		self:TriggerOutput("OnDeath", self)
	end
	
	-- Handle death animation, death delay, and the final death phase
	local deathTime = self.DeathDelayTime
	if IsValid(dmgInflictor) && dmgInflictor:GetClass() == "prop_combine_ball" then self.HasDeathAnimation = false end
	if self.HasDeathAnimation && VJ_CVAR_AI_ENABLED && !dmginfo:IsDamageType(DMG_REMOVENORAGDOLL) && !dmginfo:IsDamageType(DMG_DISSOLVE) && self:GetNavType() != NAV_CLIMB && math.random(1, self.DeathAnimationChance) == 1 then
		self:RemoveAllGestures()
		self:OnDeath(dmginfo, hitgroup, "DeathAnim")
		local chosenAnim = PICK(self.AnimTbl_Death)
		local animTime = VJ.AnimDurationEx(self, chosenAnim, self.DeathAnimationTime) - self.DeathAnimationDecreaseLengthAmount
		self:PlayAnim(chosenAnim, true, animTime, false, 0, {PlayBackRateCalculated = true})
		deathTime = deathTime + animTime
		self.DeathAnimationCodeRan = true
	else
		-- If no death anim then just set the NPC to dead even if it has a delayed remove
		self:SetSaveValue("m_lifeState", 2) -- LIFE_DEAD
	end
	if deathTime > 0 then
		timer.Simple(deathTime, function()
			if IsValid(self) then
				self:FinishDeath(dmginfo, hitgroup)
			end
		end)
	else
		self:FinishDeath(dmginfo, hitgroup)
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:FinishDeath(dmginfo, hitgroup)
	if self.VJ_DEBUG && GetConVar("vj_npc_debug_damage"):GetInt() == 1 then VJ.DEBUG_Print(self, "FinishDeath", "Attacker = ", self.SavedDmgInfo.attacker, " | Inflictor = ", self.SavedDmgInfo.inflictor) end
	self:SetSaveValue("m_lifeState", 2) -- LIFE_DEAD
	//self:SetNPCState(NPC_STATE_DEAD)
	self:OnDeath(dmginfo, hitgroup, "Finish")
	if self.DropDeathLoot then
		self:CreateDeathLoot(dmginfo, hitgroup)
	end
	if bit.band(self.SavedDmgInfo.type, DMG_REMOVENORAGDOLL) == 0 then self:DeathWeaponDrop(dmginfo, hitgroup) self:CreateDeathCorpse(dmginfo, hitgroup) end
	self:Remove()
end
---------------------------------------------------------------------------------------------------------------------------------------------
local colorGrey = Color(90, 90, 90)
--
function ENT:CreateDeathCorpse(dmginfo, hitgroup)
	-- In case it was not set
		-- NOTE: dmginfo at this point can be incorrect/corrupted, but its better than leaving the self.SavedDmgInfo empty!
	if !self.SavedDmgInfo then
		self.SavedDmgInfo = {
			dmginfo = dmginfo, -- The actual CTakeDamageInfo object | WARNING: Can be corrupted after a tick, recommended not to use this!
			attacker = dmginfo:GetAttacker(),
			inflictor = dmginfo:GetInflictor(),
			amount = dmginfo:GetDamage(),
			pos = dmginfo:GetDamagePosition(),
			type = dmginfo:GetDamageType(),
			force = dmginfo:GetDamageForce(),
			ammoType = dmginfo:GetAmmoType(),
			hitgroup = hitgroup,
		}
	end
	
	if self.HasDeathCorpse && self.HasDeathRagdoll != false then
		local corpseMdl = self:GetModel()
		local corpseMdlCustom = PICK(self.DeathCorpseModel)
		if corpseMdlCustom then corpseMdl = corpseMdlCustom end
		local corpseClass = "prop_physics"
		if self.DeathCorpseEntityClass then
			corpseClass = self.DeathCorpseEntityClass
		else
			if util.IsValidRagdoll(corpseMdl) then
				corpseClass = "prop_ragdoll"
			elseif !util.IsValidProp(corpseMdl) or !util.IsValidModel(corpseMdl) then
				if IsValid(self.WeaponEntity) then self.WeaponEntity:Remove() end
				return false
			end
		end
		self.Corpse = ents.Create(corpseClass)
		local corpse = self.Corpse
		corpse:SetModel(corpseMdl)
		corpse:SetPos(self:GetPos())
		corpse:SetAngles(self:GetAngles())
		corpse:Spawn()
		corpse:Activate()
		corpse:SetSkin(self:GetSkin())
		for i = 0, self:GetNumBodyGroups() do
			corpse:SetBodygroup(i, self:GetBodygroup(i))
		end
		corpse:SetColor(self:GetColor())
		corpse:SetMaterial(self:GetMaterial())
		if corpseMdlCustom == false && self.DeathCorpseSubMaterials != nil then -- Take care of sub materials
			for _, x in ipairs(self.DeathCorpseSubMaterials) do
				if self:GetSubMaterial(x) != "" then
					corpse:SetSubMaterial(x, self:GetSubMaterial(x))
				end
			end
			 -- This causes lag, not a very good way to do it.
			/*for x = 0, #self:GetMaterials() do
				if self:GetSubMaterial(x) != "" then
					corpse:SetSubMaterial(x, self:GetSubMaterial(x))
				end
			end*/
		end
		//corpse:SetName("corpse" .. self:EntIndex())
		//corpse:SetModelScale(self:GetModelScale())
		corpse.FadeCorpseType = (corpse:GetClass() == "prop_ragdoll" and "FadeAndRemove") or "kill"
		corpse.IsVJBaseCorpse = true
		corpse.DamageInfo = dmginfo
		corpse.ChildEnts = self.DeathCorpse_ChildEnts or {}
		corpse.BloodData = {Color = self.BloodColor, Particle = self.BloodParticle, Decal = self.BloodDecal}

		if self.Bleeds && self.HasBloodPool && vj_npc_blood_pool:GetInt() == 1 then
			self:SpawnBloodPool(dmginfo, hitgroup, corpse)
		end
		
		-- Collision
		corpse:SetCollisionGroup(self.DeathCorpseCollisionType)
		if ai_serverragdolls:GetInt() == 1 then
			undo.ReplaceEntity(self, corpse)
		else -- Keep corpses is not enabled...
			VJ.Corpse_Add(corpse)
			if vj_npc_corpse_undo:GetInt() == 1 then undo.ReplaceEntity(self, corpse) end -- Undoable
		end
		cleanup.ReplaceEntity(self, corpse) -- Delete on cleanup
		
		-- On fire
		if self:IsOnFire() then
			corpse:Ignite(math.Rand(8, 10), 0)
			if !self.Immune_Fire then -- Don't darken the corpse if we are immune to fire!
				corpse:SetColor(colorGrey)
				//corpse:SetMaterial("models/props_foliage/tree_deciduous_01a_trunk")
			end
		end
		
		-- Dissolve
		if (bit.band(self.SavedDmgInfo.type, DMG_DISSOLVE) != 0) or (IsValid(self.SavedDmgInfo.inflictor) && self.SavedDmgInfo.inflictor:GetClass() == "prop_combine_ball") then
			corpse:Dissolve(0, 1)
		end
		
		-- Bone and Angle
		-- If it's a bullet, it will use localized velocity on each bone depending on how far away the bone is from the dmg position
		local useLocalVel = (bit.band(self.SavedDmgInfo.type, DMG_BULLET) != 0 and self.SavedDmgInfo.pos != defPos) or false
		local dmgForce = (self.SavedDmgInfo.force / 40) + self:GetMoveVelocity() + self:GetVelocity()
		if self.DeathAnimationCodeRan then
			useLocalVel = false
			dmgForce = self:GetGroundSpeedVelocity()
		end
		local totalSurface = 0
		local physCount = corpse:GetPhysicsObjectCount()
		for childNum = 0, physCount - 1 do -- 128 = Bone Limit
			local childPhysObj = corpse:GetPhysicsObjectNum(childNum)
			if IsValid(childPhysObj) then
				totalSurface = totalSurface + childPhysObj:GetSurfaceArea()
				local childPhysObj_BonePos, childPhysObj_BoneAng = self:GetBonePosition(corpse:TranslatePhysBoneToBone(childNum))
				if childPhysObj_BonePos then
					if self.DeathCorpseSetBoneAngles then childPhysObj:SetAngles(childPhysObj_BoneAng) end
					childPhysObj:SetPos(childPhysObj_BonePos)
					if self.DeathCorpseApplyForce then
						childPhysObj:SetVelocity(dmgForce / math_max(1, (useLocalVel and childPhysObj_BonePos:Distance(self.SavedDmgInfo.pos) / 12) or 1))
					end
				-- If it's 1, then it's likely a regular physics model with no bones
				elseif physCount == 1 then
					if self.DeathCorpseApplyForce then
						childPhysObj:SetVelocity(dmgForce / math_max(1, (useLocalVel and corpse:GetPos():Distance(self.SavedDmgInfo.pos) / 12) or 1))
					end
				end
			end
		end
		
		-- Health & stink system
		if corpse:Health() <= 0 then
			local hpCalc = totalSurface / 60
			corpse:SetMaxHealth(hpCalc)
			corpse:SetHealth(hpCalc)
		end
		VJ.Corpse_AddStinky(corpse, true)
		
		if IsValid(self.WeaponEntity) then corpse.ChildEnts[#corpse.ChildEnts + 1] = self.WeaponEntity end
		if self.DeathCorpseFade then corpse:Fire(corpse.FadeCorpseType, "", self.DeathCorpseFade) end
		if vj_npc_corpse_fade:GetInt() == 1 then corpse:Fire(corpse.FadeCorpseType, "", vj_npc_corpse_fadetime:GetInt()) end
		self:OnCreateDeathCorpse(dmginfo, hitgroup, corpse)
		if corpse:IsFlagSet(FL_DISSOLVING) then
			if IsValid(self.WeaponEntity) then
				self.WeaponEntity:Dissolve(0, 1)
			end
			if corpse.ChildEnts then
				for _, child in ipairs(corpse.ChildEnts) do
					child:Dissolve(0, 1)
				end
			end
		end
		corpse:CallOnRemove("vj_" .. corpse:EntIndex(), function(ent, childPieces)
			for _, child in ipairs(childPieces) do
				if IsValid(child) then
					if child:GetClass() == "prop_ragdoll" then -- Make ragdolls fade
						child:Fire("FadeAndRemove", "", 0)
					else
						child:Fire("kill", "", 0)
					end
				end
			end
		end, corpse.ChildEnts)
		hook.Call("CreateEntityRagdoll", nil, self, corpse)
		return corpse
	else
		if IsValid(self.WeaponEntity) then self.WeaponEntity:Remove() end -- Remove dropped weapon
		-- Remove child entities | No fade effects as it will look weird, remove it instantly!
		if self.DeathCorpse_ChildEnts then
			for _, child in ipairs(self.DeathCorpse_ChildEnts) do
				child:Remove()
			end
		end
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:DeathWeaponDrop(dmginfo, hitgroup)
	local activeWep = self:GetActiveWeapon()
	if !self.DropWeaponOnDeath or !IsValid(activeWep) then return end
	
	-- Save its original pos & ang in case the weapon uses custom world model pos & ang
	-- because doing DropWeapon will mess up its spawn pos and ang, example: K-3 will spawn floating above the NPC
	local orgPos, orgAng = activeWep:GetPos(), activeWep:GetAngles()
	self:DropWeapon(activeWep, nil, self:GetForward()) -- Override the velocity so it doesn't throw the weapon (default source behavior)
	if activeWep.WorldModel_UseCustomPosition then
		activeWep:SetPos(orgPos)
		activeWep:SetAngles(orgAng)
	end
	local phys = activeWep:GetPhysicsObject()
	if IsValid(phys) then
		if (bit.band(self.SavedDmgInfo.type, DMG_DISSOLVE) != 0) or (IsValid(self.SavedDmgInfo.inflictor) && self.SavedDmgInfo.inflictor:GetClass() == "prop_combine_ball") then
			phys:EnableGravity(false)
			phys:SetVelocity(self:GetForward()*-150 + self:GetRight()*math.Rand(100, -100) + self:GetUp()*50)
		else
			local dmgForce = (self.SavedDmgInfo.force / 40) + self:GetMoveVelocity() + self:GetVelocity()
			if self.DeathAnimationCodeRan then
				dmgForce = self:GetGroundSpeedVelocity()
			end
			phys:SetMass(1)
			phys:ApplyForceCenter(dmgForce)
		end
	end
	self.WeaponEntity = activeWep
	
	self:OnDeathWeaponDrop(dmginfo, hitgroup, activeWep)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:GetAttackSpread(wep, target) return end