<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Glua glua Garrys Mod Lua API - Инструкция к использованию, и списки.</title><generator>teletype.in</generator><description><![CDATA[Данный блог имеет цель помочь людям в Программировании на &quot;Garrys Mod Lua API&quot;. 
В этом блоге не будет инструкций по библиотекам на подобии VJ BASЕ !]]></description><image><url>https://img1.teletype.in/files/0f/c3/0fc3344a-f716-40aa-a8e1-bcf4bb5663e8.png</url><title>Glua glua Garrys Mod Lua API - Инструкция к использованию, и списки.</title><link>https://teletype.in/@garrys_mod_lua_api</link></image><link>https://teletype.in/@garrys_mod_lua_api?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/garrys_mod_lua_api?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/garrys_mod_lua_api?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Fri, 10 Apr 2026 08:16:57 GMT</pubDate><lastBuildDate>Fri, 10 Apr 2026 08:16:57 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@garrys_mod_lua_api/G3ZeWIewtqz</guid><link>https://teletype.in/@garrys_mod_lua_api/G3ZeWIewtqz?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><comments>https://teletype.in/@garrys_mod_lua_api/G3ZeWIewtqz?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api#comments</comments><dc:creator>garrys_mod_lua_api</dc:creator><title>VJ-Base - npc_vj_human_base - init</title><pubDate>Fri, 11 Jul 2025 20:18:48 GMT</pubDate><category>Библиотека VJ Base</category><description><![CDATA[Путь к файлу «VJ-Base/lua/entities/npc_vj_human_base/init.lua»]]></description><content:encoded><![CDATA[
  <p id="igfd">Путь к файлу «VJ-Base/lua/entities/npc_vj_human_base/init.lua»</p>
  <p id="GQ0b">Код файла init.lua</p>
  <pre id="Yg9f" data-lang="lua">AddCSLuaFile(&quot;shared.lua&quot;)
include(&quot;vj_base/ai/core.lua&quot;)
include(&quot;vj_base/ai/schedules.lua&quot;)
include(&quot;vj_base/ai/base_aa.lua&quot;)
include(&quot;shared.lua&quot;)
/*--------------------------------------------------
	*** 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 &amp; Misc ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.Model = false -- Model(s) to spawn with | Picks a random one if it&#x27;s a table
ENT.CanChatMessage = true -- Is it allowed to post in a player&#x27;s chat? | Example: &quot;Blank no longer likes you.&quot;
	-- ====== 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 = &quot;ValveBiped.Bip01_Head1&quot;, -- 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&#x27;s view
	FirstP_CameraBoneAng = 0, -- Should the camera&#x27;s angle be affected by the bone&#x27;s angle? | 0 = No, 1 = Pitch, 2 = Yaw, 3 = Roll
	FirstP_CameraBoneAng_Offset = 0, -- How much should the camera&#x27;s angle be rotated by? | Useful for weird bone angles
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Movement ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.SightDistance = 6500 -- Initial sight distance | To retrieve: &quot;self:GetMaxLookDistance()&quot; | To change: &quot;self:SetMaxLookDistance(distance)&quot;
ENT.SightAngle = 177 -- Initial field of view | To retrieve: &quot;self:GetFOV()&quot; | To change: &quot;self:SetFOV(degree)&quot; | 360 = See all around
ENT.TurningSpeed = 20 -- Initial turning speed | To retrieve: &quot;self:GetMaxYawSpeed()&quot; | To change: &quot;self:SetMaxYawSpeed(speed)&quot;
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&#x27;s &quot;move_x&quot; and &quot;move_y&quot; pose parameters while moving | Required for player models to move properly!
	-- ====== JUMPING ====== --
	-- Requires &quot;CAP_MOVE_JUMP&quot; capability
	-- Applied automatically by the base if &quot;ACT_JUMP&quot; is valid on the NPC&#x27;s model
	-- Example scenario:
	--      [A]       &lt;- Apex
	--     /   \
	--    /     [S]   &lt;- Start
	--  [E]           &lt;- End
ENT.JumpParams = {
	Enabled = true, -- Can it do movement jumps?
	MaxRise = 80, -- How high it can jump up ((S -&gt; A) AND (S -&gt; E))
	MaxDrop = 230, -- How low it can jump down (E -&gt; S)
	MaxDistance = 275, -- Maximum distance between Start and End
}
	-- ====== STATIONARY ====== --
ENT.CanTurnWhileStationary = true -- Can it turn while using stationary move type?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ AI &amp; 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 &amp; objects?
ENT.EnemyTimeout = 15 -- Time until the enemy target is reset if it&#x27;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 = &quot;CLASS_PLAYER_ALLY&quot; || HECU = &quot;CLASS_UNITED_STATES&quot; || Portal = &quot;CLASS_APERTURE&quot;
		-- Combine = &quot;CLASS_COMBINE&quot; || Zombie = &quot;CLASS_ZOMBIE&quot; || Antlions = &quot;CLASS_ANTLION&quot; || Xen = &quot;CLASS_XEN&quot; || Black-Ops = &quot;CLASS_BLACKOPS&quot;
ENT.AlliedWithPlayerAllies = false -- Should it be allied with other player allies? | Both entities must have &quot;CLASS_PLAYER_ALLY&quot;
ENT.YieldToAlliedPlayers = true -- Should it give space to allied players?
ENT.BecomeEnemyToPlayer = false -- Should it become enemy towards an allied player if it&#x27;s damaged by them or it witnesses another ally killed by them?
	-- false = Don&#x27;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: &quot;CallForHelp&quot;, &quot;DamageAllyResponse&quot;, &quot;DeathAllyResponse&quot;, &quot;Passive_AlliesRunOnDamage&quot;
	-- ====== 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&#x27;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 &quot;self.HasOnPlayerSight&quot; 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&#x27;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 &quot;self.VJ_ID_Healable&quot;, 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&#x27;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 = &quot;models/healthvial.mdl&quot; -- The model that it spawns
ENT.Medic_SpawnPropOnHealAttachment = &quot;anim_attachment_LH&quot; -- The attachment it spawns on
	-- ====== Follow System ====== --
	-- Associated variables: self.FollowData, self.IsFollowing
	-- NOTE: Stationary NPCs can&#x27;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&#x27;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&#x27;s visible?
ENT.ConstantlyFaceEnemy_IfAttacking = false -- Should it face the enemy when attacking?
ENT.ConstantlyFaceEnemy_Postures = &quot;Both&quot; -- &quot;Both&quot; = Moving or standing | &quot;Moving&quot; = Only when moving | &quot;Standing&quot; = 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 &amp; 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&#x27;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&#x27;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&#x27;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&#x27;s damaged
ENT.BloodDecalUseGMod = false -- Should it use the current default decals defined by Garry&#x27;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&#x27;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 &quot;VJ_ID_Boss&quot;
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&#x27;t flinch | true = Always flinch | &quot;DamageTypes&quot; = Flinch only from certain damages types
ENT.FlinchDamageTypes = {DMG_BLAST} -- Which types of damage types should it flinch from when &quot;DamageTypes&quot; 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 &quot;self.AnimTbl_Flinch&quot; 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 | &quot;OnlyMove&quot; = Will only run to a covered position | &quot;OnlySearch&quot; = Will only search for enemies
ENT.DamageAllyResponse = true -- Should allies respond when it&#x27;s damaged while it has no enemy?
ENT.AnimTbl_DamageAllyResponse = ACT_SIGNAL_GROUP -- Animations to play when it calls allies to respond | false = Don&#x27;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 &quot;self.AnimTbl_TakingCover&quot;
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 &amp; Corpse ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.DeathDelayTime = 0 -- Time until it spawns the corpse, removes itself, etc.
	-- ====== Ally Responses ====== --
	-- An ally must have &quot;self.CanReceiveOrders&quot; enabled to respond!
ENT.DeathAllyResponse = &quot;OnlyAlert&quot; -- How should allies response when it dies?
	-- false = No reactions | true = Allies respond by becoming alert and moving to its location | &quot;OnlyAlert&quot; = 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 &quot;self.DeathDelayTime&quot;
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&#x27;s killed?
ENT.DeathCorpseEntityClass = false -- Corpse&#x27;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&#x27;s set to COLLISION_GROUP_DEBRIS!
ENT.DeathCorpseFade = false -- Should the corpse fade after the given amount of seconds? | false = Don&#x27;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&#x27;s sub material to the corpse.
	-- ====== Dismemberment / Gib ====== --
ENT.CanGib = true -- Can it dismember? | Makes &quot;CreateGibEntity&quot; fail and overrides &quot;CanGibOnDeath&quot; to false
ENT.CanGibOnDeath = true -- Can it dismember on death?
ENT.GibOnDeathFilter = true -- Should it only gib and call &quot;self:HandleGibOnDeath&quot; when it&#x27;s killed by a specific damage types? | false = Call &quot;self:HandleGibOnDeath&quot; 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 = {&quot;weapon_frag&quot;, &quot;item_healthvial&quot;} -- 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 &quot;MeleeAttackKnockbackVelocity&quot; 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&#x27;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 = &quot;obj_vj_grenade&quot; -- Entities that it can spawn when throwing a grenade | If set as a table, it picks a random entity | VJ: &quot;obj_vj_grenade&quot; | HL2: &quot;npc_grenade_frag&quot;
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 = &quot;anim_attachment_LH&quot; -- The attachment that the grenade will be set to | -1 = Skip to use &quot;self.GrenadeAttackBone&quot; instead
ENT.GrenadeAttackBone = &quot;ValveBiped.Bip01_L_Finger1&quot; -- The bone that the grenade will be set to | -1 = Skip to use fail safe instead
	-- ====== Animation ====== --
ENT.AnimTbl_GrenadeAttack = &quot;grenThrow&quot; -- Animations to play when it throws a grenade | false = Don&#x27;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&#x27;s fuse time after it&#x27;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&#x27;s unarmed?
ENT.Weapon_Accuracy = 1 -- Its accuracy with weapons, affects bullet spread! | x &lt; 1 = Better accuracy | x &gt; 1 = Worse accuracy
ENT.Weapon_CanMoveFire = true -- Can it fire its weapon while it&#x27;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 | &quot;self.HasPoseParameterLooking&quot; 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&#x27;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&#x27;s secondary fire if it&#x27;s available?
ENT.Weapon_SecondaryFireTime = false -- How much time until the secondary fire&#x27;s projectile is released | false = Base auto calculates the duration
ENT.AnimTbl_WeaponAttackSecondary = ACT_RANGE_ATTACK2 -- Animations to play while firing the weapon&#x27;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 &quot;self.WeaponInventory&quot; 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 &quot;DamageByPlayer&quot; 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 &quot;self.SoundTbl_Idle&quot;, &quot;self.SoundTbl_IdleDialogue&quot;, &quot;self.SoundTbl_CombatIdle&quot;
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 &quot;self.SoundTbl_KilledEnemy&quot; 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 &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
ENT.HasYieldToPlayerSounds = true -- Can it play sounds when it yields to an allied player?
ENT.HasMedicSounds = true -- Can it play medic sounds? | Controls &quot;self.SoundTbl_MedicBeforeHeal&quot;, &quot;self.SoundTbl_MedicOnHeal&quot;, &quot;self.SoundTbl_MedicReceiveHeal&quot;
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 &quot;self.SoundTbl_BeforeMeleeAttack&quot;, &quot;self.SoundTbl_MeleeAttack&quot;, &quot;self.SoundTbl_MeleeAttackExtra&quot;
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 &quot;self.SoundTbl_DangerSight&quot;, &quot;self.SoundTbl_GrenadeSight&quot;
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&#x27;s damaged by a player?
ENT.HasDeathSounds = true -- Can it play death sounds?
	-- ====== Sound Paths ====== --
	-- There are 2 types of sounds: &quot;Speech&quot; and &quot;EFFECT&quot; | Most sound tables are &quot;SPEECH&quot; 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 = &quot;VJ.Footstep.Human&quot; -- 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 = &quot;items/smallmedkit1.wav&quot; -- 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 = &quot;Flesh.ImpactHard&quot; -- EFFECT
ENT.SoundTbl_MeleeAttackMiss = &quot;Zombie.AttackMiss&quot; -- EFFECT
ENT.SoundTbl_GrenadeAttack = false
ENT.SoundTbl_DangerSight = false
ENT.SoundTbl_GrenadeSight = false -- If empty it will play &quot;self.SoundTbl_DangerSight&quot;
ENT.SoundTbl_KilledEnemy = false
ENT.SoundTbl_AllyDeath = false
ENT.SoundTbl_Pain = false
ENT.SoundTbl_Impact = &quot;Flesh.BulletImpact&quot; -- 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 &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
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 &quot;self.SoundTbl_DangerSight&quot;, &quot;self.SoundTbl_GrenadeSight&quot;
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 &quot;self.SoundTbl_IdleDialogue&quot;, &quot;self.SoundTbl_IdleDialogueAnswer&quot;
ENT.CombatIdleSoundLevel = 80
ENT.ReceiveOrderSoundLevel = 80
ENT.FollowPlayerSoundLevel = 75 -- Controls &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
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 &quot;self.SoundTbl_DangerSight&quot;, &quot;self.SoundTbl_GrenadeSight&quot;
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 &lt; x &gt; 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 &quot;self.SoundTbl_IdleDialogue&quot;, &quot;self.SoundTbl_IdleDialogueAnswer&quot;
ENT.CombatIdleSoundPitch = false
ENT.ReceiveOrderSoundPitch = false
ENT.FollowPlayerPitch = false -- Controls &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
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 &quot;self.SoundTbl_DangerSight&quot;, &quot;self.SoundTbl_GrenadeSight&quot;
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&#x27;t have a hook because you can simply override them | Call &quot;self.BaseClass.FuncName(self)&quot; or &quot;baseclass.Get(baseName)&quot; 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: &quot;cl_ent_bbox&quot;
	-- 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: &quot;cl_ent_absbox&quot;
	-- 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: &quot;calculatedDisp&quot; 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 &quot;VJ.CreateSound&quot; or &quot;VJ.EmitSound&quot; is called | return a new file path to replace the one that is about to play
-- function ENT:OnPlaySound(sdFile) return &quot;example/sound.wav&quot; end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called whenever a sound starts playing through &quot;VJ.CreateSound&quot;
-- function ENT:OnCreateSound(sdData, sdFile) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called whenever a sound starts playing through &quot;VJ.EmitSound&quot;
-- function ENT:OnEmitSound(sdFile) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE | Called every time &quot;self:FireBullets&quot; 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, &quot;OnCondition&quot;, cond, &quot; = &quot;, self:ConditionName(cond)) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE
-- function ENT:OnInput(key, activator, caller, data) VJ.DEBUG_Print(self, &quot;OnInput&quot;, 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, &quot;OnAnimEvent&quot;, eventName, ev, evTime, evCycle, evType, evOptions)
-- end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Called whenever the NPC begins following or stops following an entity
		- status = Type of call:
			- &quot;Start&quot;	= NPC is now following the given entity
			- &quot;Stop&quot;	= 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:
			- &quot;CheckEnt&quot;	= Possible friendly entity found, should we speak to it? | return anything other than true to skip and not speak to this entity!
			- &quot;Speak&quot;		= Everything passed, start speaking
			- &quot;Answer&quot;		= 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 &quot;CheckEnt&quot;	= Boolean value, whether or not the entity can answer back
			- For &quot;Speak&quot;		= Duration of our sentence
	Returns
		- ONLY used for &quot;CheckEnt&quot; &amp; &quot;Answer&quot; | 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:
		-&gt; &quot;BeforeHeal&quot; : Right before it&#x27;s about to heal an entity
				USAGE EXAMPLES -&gt; Play chain of animations | Additional sound effect
				PARAMETERS
					2. statusData [nil]
				RETURNS
					-&gt; [nil]
		-&gt; &quot;OnHeal&quot; : When the timer expires and is about to give health
				USAGE EXAMPLES -&gt; Override healing code | Play an after heal animation
				PARAMETERS
					2. statusData [entity] : The entity that it&#x27;s about to heal
				RETURNS
					-&gt; [bool] : Returning false will NOT update entity&#x27;s health and will NOT clear its decals (Useful for custom code)
		-&gt; &quot;OnReset&quot; : When the behavior ends OR has to move because entity moved
				USAGE EXAMPLES -&gt; Cleanup bodygroups | Play a sound
				PARAMETERS
					2. statusData [string] : Holds one of the following states:
						--&gt; &quot;Retry&quot; : When it attempts to retry healing the entity, such as when the entity moved away so it has to chase again
						--&gt; &quot;End&quot; : When the medic behavior exits completely
				RETURNS
					-&gt; [nil]
	2. statusData [nil | entity | string] : Depends on &#x60;status&#x60; value, refer to it for more details

=-=-=| RETURNS |=-=-=
	-&gt; [nil | bool] : Depends on &#x60;status&#x60; 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: &quot;Walk&quot;, &quot;Run&quot;, &quot;Event&quot;
		- 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 &quot;DANGER_TYPE_ENTITY&quot; and &quot;DANGER_TYPE_GRENADE&quot;
			-- Currently empty for danger type &quot;DANGER_TYPE_HINT&quot;
-----------------------------------------------------------]]
-- function ENT:OnDangerDetected(dangerType, data) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnInvestigate(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnResetEnemy() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnAlert(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- &quot;ally&quot; = Ally that we called for help
-- &quot;isFirst&quot; = 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:
		-&gt; &quot;PreInit&quot; : Before the attack is initialized | Before anything is set, useful to prevent the attack completely
			RETURNS
				-&gt; [nil | boolean] : Return true to prevent the attack from being triggered
		-&gt; &quot;Init&quot; : When the attack initially starts | Before sound, timers, and animations are set!
			RETURNS
				-&gt; [nil]
		-&gt; &quot;PostInit&quot; : After the sound, timers, and animations are set!
			RETURNS
				-&gt; [nil]
	2. enemy [entity] : Enemy that caused the attack to trigger

=-=-=| RETURNS |=-=-=
	-&gt; [nil | boolean] : Depends on &#x60;status&#x60; 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
---------------------------------------------------------------------------------------------------------------------------------------------
-- &quot;self.MeleeAttackDamageAngleRadius&quot; 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:
		-&gt; &quot;Init&quot; : When the attack initially executed | Before entities are checked and damaged
			RETURNS
				-&gt; [nil | boolean] : Return true to skip running the default execution (Useful for custom code)
		-&gt; &quot;PreDamage&quot; : 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
				-&gt; [nil | boolean] : Return true to skip hitting this entity
		-&gt; &quot;Miss&quot; : When the attack misses and doesn&#x27;t hit anything
			RETURNS
				-&gt; [nil]
	2. ent [nil | entity] : Depends on &#x60;status&#x60; value, refer to it for more details
	3. isProp [nil | entity] : Depends on &#x60;status&#x60; value, refer to it for more details

=-=-=| RETURNS |=-=-=
	-&gt; [nil | boolean] : Depends on &#x60;status&#x60; 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:
		-&gt; &quot;Init&quot; : When the attack initially starts | Before sound, timers, and animations are set!
			USAGE EXAMPLES -&gt; Change grenade attack sounds or make changes to &quot;self.GrenadeAttackThrowTime&quot;
			RETURNS
				-&gt; [nil | boolean] : Return true to disallow throwing a grenade
		-&gt; &quot;PostInit&quot; : After the sound, timers, and animations are set!
			RETURNS
				-&gt; [nil]
		-&gt; &quot;SpawnPos&quot; : When the spawn position is requested
			USAGE EXAMPLES -&gt; Override the spawn position if needed by returning a vector
			RETURNS
				-&gt; [nil] : Do NOT override the spawn position
				-&gt; [vector] : Override the spawn position
	2. overrideEnt [nil | string | entity] : string or entity if the grenade attack was triggered through an override
		-&gt; [nil] : Using the default grenade class set by &quot;self.GrenadeAttackEntity&quot; | DEFAULT
		-&gt; [string] : Using the given class name as an override
		-&gt; [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
		-&gt; &quot;Enemy&quot; : Use enemy&#x27;s position
		-&gt; &quot;EnemyLastVis&quot; : Use enemy&#x27;s last visible position
		-&gt; &quot;FindBest&quot; : Find the best random position
		-&gt; [vector] : Use given vector

=-=-=| RETURNS |=-=-=
	-&gt; [nil | vector | boolean] : Depends on &#x60;status&#x60; 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:
		-&gt; &quot;PreSpawn&quot; : Right before &quot;Spawn()&quot; is called on the grenade | Not called for grenade entity overrides, such as throwing back an enemy grenade
			RETURNS
				-&gt; [nil]
		-&gt; &quot;PostSpawn&quot; : After &quot;Spawn()&quot; is called on the grenade | Can be used to override the throw velocity or not apply it at all
			RETURNS
				-&gt; [nil] : Apply the default velocity
				-&gt; [vector] : Override the velocity to the given vector
				-&gt; [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
		-&gt; [nil] : Using the default grenade class set by &quot;self.GrenadeAttackEntity&quot; | DEFAULT
		-&gt; [string] : Using the given class name as an override
		-&gt; [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
		-&gt; &quot;Enemy&quot; : Use enemy&#x27;s position
		-&gt; &quot;EnemyLastVis&quot; : Use enemy&#x27;s last visible position
		-&gt; &quot;FindBest&quot; : Find the best random position
		-&gt; [vector] : Use given vector
	5. landingPos [nil | vector] : The position the grenade is aimed to land

=-=-=| RETURNS |=-=-=
	-&gt; [nil | vector | boolean] : Depends on &#x60;status&#x60; 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:
		-&gt; &quot;Init&quot; : First call on take damage, even before immune checks
		-&gt; &quot;PreDamage&quot; : Right before the damage is applied to the NPC
		-&gt; &quot;PostDamage&quot; : 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:
		-&gt; &quot;Init&quot; : Before the animation is played or any values are set
				USAGE EXAMPLES -&gt; Disallow flinch | Override the animation | Add a extra check
				RETURNS
					-&gt; [nil | bool] : Return true to disallow the flinch from playing
		-&gt; &quot;Execute&quot; : Right after the flinch animation starts playing and all the values are set
				RETURNS
					-&gt; [nil]

=-=-=| RETURNS |=-=-=
	-&gt; [nil | bool] : Depends on &#x60;status&#x60; 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 |=-=-=
	-&gt; [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
	-&gt; [nil | table] : Overrides default actions, first return must be &quot;true&quot; 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:
		-&gt; &quot;Init&quot; : First call when it dies before anything is changed or reset
		-&gt; &quot;DeathAnim&quot; : Right before the death animation plays
		-&gt; &quot;Finish&quot; : 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(&quot;CTRL + MOUSE2: Rocket Attack&quot;) -- 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, &quot;shootAR2alt&quot;)
		
		self.AnimationTranslations[ACT_COVER_LOW] 					= {ACT_COVER, &quot;vjseq_Leanwall_CrouchLeft_A_idle&quot;, &quot;vjseq_Leanwall_CrouchLeft_B_idle&quot;, &quot;vjseq_Leanwall_CrouchLeft_C_idle&quot;, &quot;vjseq_Leanwall_CrouchLeft_D_idle&quot;}
		//self.AnimationTranslations[ACT_RELOAD] 					= ACT_RELOAD_SMG1 -- No need to translate, it&#x27;s already the correct animation
		//self.AnimationTranslations[ACT_RELOAD_LOW] 				= ACT_RELOAD_SMG1_LOW -- No need to translate, it&#x27;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 == &quot;ar2&quot; or wepHoldType == &quot;smg&quot; or wepHoldType == &quot;rpg&quot; then
			if wepHoldType == &quot;ar2&quot; 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&#x27;s already the correct animation
			elseif wepHoldType == &quot;smg&quot; or wepHoldType == &quot;rpg&quot; 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, &quot;walkeasy_all&quot;)
			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 == &quot;pistol&quot; or wepHoldType == &quot;revolver&quot; 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, &quot;idle_unarmed&quot;)
			//self.AnimationTranslations[ACT_IDLE_ANGRY] 				= ACT_IDLE_ANGRY -- No need to translate, it&#x27;s already the correct animation
			
			self.AnimationTranslations[ACT_WALK] 						= VJ.SequenceToActivity(self, &quot;walkunarmed_all&quot;)
			//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 == &quot;crossbow&quot; or wepHoldType == &quot;shotgun&quot; then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_RANGE_ATTACK_SHOTGUN
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= wepHoldType == &quot;crossbow&quot; 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 == &quot;melee&quot; or wepHoldType == &quot;melee2&quot; or wepHoldType == &quot;knife&quot; then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_MELEE_ATTACK1
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= false -- Don&#x27;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, &quot;idle_unarmed&quot;)
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= VJ.SequenceToActivity(self, &quot;idle_unarmed&quot;)
			
			self.AnimationTranslations[ACT_WALK] 						= VJ.SequenceToActivity(self, &quot;walkunarmed_all&quot;)
			//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, &quot;idle_unarmed&quot;)
			self.AnimationTranslations[ACT_WALK] 						= VJ.SequenceToActivity(self, &quot;walkunarmed_all&quot;)
			//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, &quot;shootAR2alt&quot;) -- They don&#x27;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 == &quot;smg&quot; or wepHoldType == &quot;rpg&quot; or wepHoldType == &quot;ar2&quot; or wepHoldType == &quot;crossbow&quot; or wepHoldType == &quot;shotgun&quot; then
			-- Note: Metrocops must use smg animation, they don&#x27;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 == &quot;pistol&quot; or wepHoldType == &quot;revolver&quot; 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 == &quot;melee&quot; or wepHoldType == &quot;melee2&quot; or wepHoldType == &quot;knife&quot; then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_MELEE_ATTACK_SWING
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= false //ACT_MELEE_ATTACK_SWING_GESTURE -- Don&#x27;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, &quot;plazathreat1&quot;)}
			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, &quot;shoot_ar2_alt&quot;)
		
		-- Handguns use a different set!
		self.AnimationTranslations[ACT_COVER_LOW] 						= {ACT_COVER_LOW_RPG, ACT_COVER_LOW, &quot;vjseq_coverlow_l&quot;, &quot;vjseq_coverlow_r&quot;}
		
		if wepHoldType == &quot;ar2&quot; 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, &quot;reload_ar2&quot;)
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= ACT_RELOAD_SMG1_LOW
			
			self.AnimationTranslations[ACT_IDLE] 						= PICK({VJ.SequenceToActivity(self, &quot;idle_relaxed_ar2_1&quot;), VJ.SequenceToActivity(self, &quot;idle_alert_ar2_1&quot;), VJ.SequenceToActivity(self, &quot;idle_angry_ar2&quot;)})
			self.AnimationTranslations[ACT_IDLE_ANGRY] 					= VJ.SequenceToActivity(self, &quot;idle_ar2_aim&quot;)
			
			self.AnimationTranslations[ACT_WALK] 						= PICK({VJ.SequenceToActivity(self, &quot;walk_ar2_relaxed_all&quot;), VJ.SequenceToActivity(self, &quot;walkalerthold_ar2_all1&quot;), VJ.SequenceToActivity(self, &quot;walkholdall1_ar2&quot;)})
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= VJ.SequenceToActivity(self, &quot;walkalerthold_ar2_all1&quot;)
			self.AnimationTranslations[ACT_WALK_AIM] 					= PICK({VJ.SequenceToActivity(self, &quot;walkaimall1_ar2&quot;), VJ.SequenceToActivity(self, &quot;walkalertaim_ar2_all1&quot;)})
			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, &quot;run_alert_holding_ar2_all&quot;), VJ.SequenceToActivity(self, &quot;run_ar2_relaxed_all&quot;), VJ.SequenceToActivity(self, &quot;run_holding_ar2_all&quot;)})
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= PICK({VJ.SequenceToActivity(self, &quot;run_alert_holding_ar2_all&quot;), VJ.SequenceToActivity(self, &quot;run_holding_ar2_all&quot;)})
			self.AnimationTranslations[ACT_RUN_AIM] 					= PICK({ACT_RUN_AIM_RIFLE, VJ.SequenceToActivity(self, &quot;run_alert_aiming_ar2_all&quot;)})
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RPG
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == &quot;smg&quot; 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, &quot;idle_smg1_relaxed&quot;)})
			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 == &quot;crossbow&quot; or wepHoldType == &quot;shotgun&quot; 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, &quot;idle_ar2_aim&quot;)
			
			self.AnimationTranslations[ACT_WALK] 						= PICK({VJ.SequenceToActivity(self, &quot;walk_ar2_relaxed_all&quot;), VJ.SequenceToActivity(self, &quot;walkalerthold_ar2_all1&quot;), VJ.SequenceToActivity(self, &quot;walkholdall1_ar2&quot;)})
			self.AnimationTranslations[ACT_WALK_AGITATED] 				= VJ.SequenceToActivity(self, &quot;walkalerthold_ar2_all1&quot;)
			self.AnimationTranslations[ACT_WALK_AIM] 					= PICK({VJ.SequenceToActivity(self, &quot;walkaimall1_ar2&quot;), VJ.SequenceToActivity(self, &quot;walkalertaim_ar2_all1&quot;)})
			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, &quot;run_alert_holding_ar2_all&quot;), VJ.SequenceToActivity(self, &quot;run_ar2_relaxed_all&quot;), VJ.SequenceToActivity(self, &quot;run_holding_ar2_all&quot;)})
			self.AnimationTranslations[ACT_RUN_AGITATED] 				= PICK({VJ.SequenceToActivity(self, &quot;run_alert_holding_ar2_all&quot;), VJ.SequenceToActivity(self, &quot;run_holding_ar2_all&quot;)})
			self.AnimationTranslations[ACT_RUN_AIM] 					= PICK({ACT_RUN_AIM_RIFLE, VJ.SequenceToActivity(self, &quot;run_alert_aiming_ar2_all&quot;)})
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RPG
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == &quot;rpg&quot; 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, &quot;walkaimall1_ar2&quot;), VJ.SequenceToActivity(self, &quot;walkalertaim_ar2_all1&quot;)})
			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, &quot;run_alert_aiming_ar2_all&quot;)})
			self.AnimationTranslations[ACT_RUN_CROUCH] 					= ACT_RUN_CROUCH_RPG
			self.AnimationTranslations[ACT_RUN_CROUCH_AIM] 				= ACT_RUN_CROUCH_AIM_RIFLE
		elseif wepHoldType == &quot;pistol&quot; or wepHoldType == &quot;revolver&quot; 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] 					= {&quot;crouchidle_panicked4&quot;, &quot;vjseq_crouchidlehide&quot;}
			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, &quot;idle_ar2_aim&quot;) -- 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, &quot;walkaimall1_ar2&quot;), VJ.SequenceToActivity(self, &quot;walkalertaim_ar2_all1&quot;)})
			//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, &quot;run_alert_aiming_ar2_all&quot;)
			//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 == &quot;melee&quot; or wepHoldType == &quot;melee2&quot; or wepHoldType == &quot;knife&quot; then
			self.AnimationTranslations[ACT_RANGE_ATTACK1] 				= ACT_MELEE_ATTACK_SWING
			self.AnimationTranslations[ACT_GESTURE_RANGE_ATTACK1] 		= false -- Don&#x27;t play anything!
			//self.AnimationTranslations[ACT_RANGE_ATTACK1_LOW] 		= ACT_RANGE_ATTACK_SMG1_LOW -- Not used for melee
			self.AnimationTranslations[ACT_COVER_LOW] 					= {&quot;crouchidle_panicked4&quot;, &quot;vjseq_crouchidlehide&quot;}
			//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&#x27;t have this sequence
				self.AnimationTranslations[ACT_RUN_AGITATED] 			= VJ.SequenceToActivity(self, &quot;run_all_panicked&quot;)
			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 == &quot;ar2&quot; 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] 						= &quot;vjges_reload_ar2&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_ar2&quot;
			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 == &quot;pistol&quot; 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] 						= &quot;vjges_reload_pistol&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_pistol&quot;
			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 == &quot;smg&quot; 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] 						= &quot;vjges_reload_smg1&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_smg1&quot;
			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 == &quot;shotgun&quot; 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] 						= &quot;vjges_reload_shotgun&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_shotgun&quot;
			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 == &quot;rpg&quot; 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] 						= &quot;vjges_reload_ar2&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_ar2&quot;
			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 == &quot;physgun&quot; 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] 						= &quot;vjges_reload_ar2&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_ar2&quot;
			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 == &quot;crossbow&quot; 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] 						= &quot;vjges_reload_ar2&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_ar2&quot;
			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 == &quot;slam&quot; 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] 					= &quot;vjges_reload_pistol&quot;
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= &quot;vjges_reload_pistol&quot;
			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 == &quot;duel&quot; 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] 						= &quot;vjges_reload_duel&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_duel&quot;
			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 == &quot;revolver&quot; 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] 						= &quot;vjges_reload_revolver&quot;
			self.AnimationTranslations[ACT_RELOAD_LOW] 					= &quot;vjges_reload_revolver&quot;
			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 == &quot;melee&quot; 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] 					= &quot;vjges_reload_pistol&quot;
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= &quot;vjges_reload_pistol&quot;
			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 == &quot;melee2&quot; 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] 					= &quot;vjges_reload_pistol&quot;
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= &quot;vjges_reload_pistol&quot;
			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 == &quot;knife&quot; 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] 					= &quot;vjges_reload_pistol&quot;
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= &quot;vjges_reload_pistol&quot;
			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 == &quot;grenade&quot; 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] 					= &quot;vjges_reload_pistol&quot;
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= &quot;vjges_reload_pistol&quot;
			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 == &quot;camera&quot; 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] 					= &quot;vjges_reload_pistol&quot;
			//self.AnimationTranslations[ACT_RELOAD_LOW] 				= &quot;vjges_reload_pistol&quot;
			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&#x27;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(&quot;Entity&quot;)
local funcGetPoseParameter = metaEntity.GetPoseParameter
local funcSetPoseParameter = metaEntity.SetPoseParameter
--
local metaNPC = FindMetaTable(&quot;NPC&quot;)
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 &quot;self.Weapon_AimTurnDiff&quot; 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(&quot;vj_npc_debug&quot;)
local vj_npc_processtime = GetConVar(&quot;vj_npc_processtime&quot;)
local vj_npc_poseparams = GetConVar(&quot;vj_npc_poseparams&quot;)
local vj_npc_shadows = GetConVar(&quot;vj_npc_shadows&quot;)
local vj_npc_snd = GetConVar(&quot;vj_npc_snd&quot;)
local vj_npc_fri_base = GetConVar(&quot;vj_npc_fri_base&quot;)
local vj_npc_fri_player = GetConVar(&quot;vj_npc_fri_player&quot;)
local vj_npc_fri_antlion = GetConVar(&quot;vj_npc_fri_antlion&quot;)
local vj_npc_fri_combine = GetConVar(&quot;vj_npc_fri_combine&quot;)
local vj_npc_fri_zombie = GetConVar(&quot;vj_npc_fri_zombie&quot;)
local vj_npc_allies = GetConVar(&quot;vj_npc_allies&quot;)
local vj_npc_anim_death = GetConVar(&quot;vj_npc_anim_death&quot;)
local vj_npc_corpse = GetConVar(&quot;vj_npc_corpse&quot;)
local vj_npc_loot = GetConVar(&quot;vj_npc_loot&quot;)
local vj_npc_wander = GetConVar(&quot;vj_npc_wander&quot;)
local vj_npc_chase = GetConVar(&quot;vj_npc_chase&quot;)
local vj_npc_flinch = GetConVar(&quot;vj_npc_flinch&quot;)
local vj_npc_melee = GetConVar(&quot;vj_npc_melee&quot;)
local vj_npc_blood = GetConVar(&quot;vj_npc_blood&quot;)
local vj_npc_god = GetConVar(&quot;vj_npc_god&quot;)
local vj_npc_wep_reload = GetConVar(&quot;vj_npc_wep_reload&quot;)
local vj_npc_ply_betray = GetConVar(&quot;vj_npc_ply_betray&quot;)
local vj_npc_callhelp = GetConVar(&quot;vj_npc_callhelp&quot;)
local vj_npc_investigate = GetConVar(&quot;vj_npc_investigate&quot;)
local vj_npc_eat = GetConVar(&quot;vj_npc_eat&quot;)
local vj_npc_ply_follow = GetConVar(&quot;vj_npc_ply_follow&quot;)
local vj_npc_ply_chat = GetConVar(&quot;vj_npc_ply_chat&quot;)
local vj_npc_medic = GetConVar(&quot;vj_npc_medic&quot;)
local vj_npc_wep = GetConVar(&quot;vj_npc_wep&quot;)
local vj_npc_grenade = GetConVar(&quot;vj_npc_grenade&quot;)
local vj_npc_dangerdetection = GetConVar(&quot;vj_npc_dangerdetection&quot;)
local vj_npc_wep_drop = GetConVar(&quot;vj_npc_wep_drop&quot;)
local vj_npc_gib_vfx = GetConVar(&quot;vj_npc_gib_vfx&quot;)
local vj_npc_gib = GetConVar(&quot;vj_npc_gib&quot;)
local vj_npc_blood_gmod = GetConVar(&quot;vj_npc_blood_gmod&quot;)
local vj_npc_sight_xray = GetConVar(&quot;vj_npc_sight_xray&quot;)
local vj_npc_snd_gib = GetConVar(&quot;vj_npc_snd_gib&quot;)
local vj_npc_snd_track = GetConVar(&quot;vj_npc_snd_track&quot;)
local vj_npc_snd_footstep = GetConVar(&quot;vj_npc_snd_footstep&quot;)
local vj_npc_snd_idle = GetConVar(&quot;vj_npc_snd_idle&quot;)
local vj_npc_snd_breath = GetConVar(&quot;vj_npc_snd_breath&quot;)
local vj_npc_snd_alert = GetConVar(&quot;vj_npc_snd_alert&quot;)
local vj_npc_snd_danger = GetConVar(&quot;vj_npc_snd_danger&quot;)
local vj_npc_snd_melee = GetConVar(&quot;vj_npc_snd_melee&quot;)
local vj_npc_snd_pain = GetConVar(&quot;vj_npc_snd_pain&quot;)
local vj_npc_snd_death = GetConVar(&quot;vj_npc_snd_death&quot;)
local vj_npc_snd_plyfollow = GetConVar(&quot;vj_npc_snd_plyfollow&quot;)
local vj_npc_snd_plybetrayal = GetConVar(&quot;vj_npc_snd_plybetrayal&quot;)
local vj_npc_snd_plydamage = GetConVar(&quot;vj_npc_snd_plydamage&quot;)
local vj_npc_snd_plysight = GetConVar(&quot;vj_npc_snd_plysight&quot;)
local vj_npc_snd_medic = GetConVar(&quot;vj_npc_snd_medic&quot;)
local vj_npc_snd_wep_reload = GetConVar(&quot;vj_npc_snd_wep_reload&quot;)
local vj_npc_snd_grenade = GetConVar(&quot;vj_npc_snd_grenade&quot;)
local vj_npc_snd_wep_suppressing = GetConVar(&quot;vj_npc_snd_wep_suppressing&quot;)
local vj_npc_snd_callhelp = GetConVar(&quot;vj_npc_snd_callhelp&quot;)
local vj_npc_snd_receiveorder = GetConVar(&quot;vj_npc_snd_receiveorder&quot;)
local vj_npc_corpse_collision = GetConVar(&quot;vj_npc_corpse_collision&quot;)
local vj_npc_debug_engine = GetConVar(&quot;vj_npc_debug_engine&quot;)
local vj_npc_difficulty = GetConVar(&quot;vj_npc_difficulty&quot;)
local vj_npc_sight_distance = GetConVar(&quot;vj_npc_sight_distance&quot;)
local vj_npc_health = GetConVar(&quot;vj_npc_health&quot;)
local vj_npc_human_jump = GetConVar(&quot;vj_npc_human_jump&quot;)
local vj_npc_ply_frag = GetConVar(&quot;vj_npc_ply_frag&quot;)
local vj_npc_blood_pool = GetConVar(&quot;vj_npc_blood_pool&quot;)
local vj_npc_corpse_undo = GetConVar(&quot;vj_npc_corpse_undo&quot;)
local vj_npc_corpse_fade = GetConVar(&quot;vj_npc_corpse_fade&quot;)
local vj_npc_corpse_fadetime = GetConVar(&quot;vj_npc_corpse_fadetime&quot;)
local ai_serverragdolls = GetConVar(&quot;ai_serverragdolls&quot;)

---------------------------------------------------------------------------------------------------------------------------------------------
local function InitConvars(self)
	if vj_npc_debug:GetInt() == 1 then self.VJ_DEBUG = true end
	if vj_npc_poseparams:GetInt() == 0 &amp;&amp; !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] = &quot;CLASS_VJ_BASE&quot; end
	if vj_npc_fri_player:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_PLAYER_ALLY&quot; end
	if vj_npc_fri_antlion:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_ANTLION&quot; end
	if vj_npc_fri_combine:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_COMBINE&quot; end
	if vj_npc_fri_zombie:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_ZOMBIE&quot; 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 &amp;&amp; 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 &#x27;npc_conditions&#x27; need it)
	if self.VJ_DEBUG &amp;&amp; vj_npc_debug_engine:GetInt() == 1 then
		self:SetSaveValue(&quot;m_debugOverlays&quot;, 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 &amp; 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] = &quot;CLASS_PLAYER_ALLY&quot; 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 = &quot;OnlySearch&quot; end
	if self.DisableTakeDamageFindEnemy == true then if self.HideOnUnknownDamage == false then self.DamageResponse = false else self.DamageResponse = &quot;OnlyMove&quot; 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 = &quot;DamageTypes&quot; end
	if self.BringFriendsOnDeath != nil or self.AlertFriendsOnDeath != nil then
		if self.AlertFriendsOnDeath == true &amp;&amp; (self.BringFriendsOnDeath == false or self.BringFriendsOnDeath == nil) then
			self.DeathAllyResponse = &quot;OnlyAlert&quot;
		elseif self.BringFriendsOnDeath == false &amp;&amp; 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 == &quot;All&quot; 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 &amp;&amp; !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 &amp;&amp; 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 == &quot;BeforeHeal&quot; &amp;&amp; self.CustomOnMedic_BeforeHeal then
				self:CustomOnMedic_BeforeHeal()
			elseif status == &quot;OnHeal&quot; &amp;&amp; self.CustomOnMedic_OnHeal then
				return self:CustomOnMedic_OnHeal(statusData)
			elseif status == &quot;OnReset&quot; &amp;&amp; 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 == &quot;Init&quot; &amp;&amp; self.CustomOnTakeDamage_BeforeImmuneChecks then
				self:CustomOnTakeDamage_BeforeImmuneChecks(dmginfo, hitgroup)
			elseif status == &quot;PreDamage&quot; &amp;&amp; self.CustomOnTakeDamage_BeforeDamage then
				self:CustomOnTakeDamage_BeforeDamage(dmginfo, hitgroup)
			elseif status == &quot;PostDamage&quot; &amp;&amp; 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 == &quot;Init&quot; then
				if self.CustomOnFlinch_BeforeFlinch then
					return !self:CustomOnFlinch_BeforeFlinch(dmginfo, hitgroup)
				end
			elseif status == &quot;Execute&quot; 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 == &quot;Init&quot; then
				if self.CustomOnInitialKilled then
					self:CustomOnInitialKilled(dmginfo, hitgroup)
				end
				if self.CustomOnPriorToKilled then
					self:CustomOnPriorToKilled(dmginfo, hitgroup)
				end
			elseif status == &quot;DeathAnim&quot; &amp;&amp; self.CustomDeathAnimationCode then
				self:CustomDeathAnimationCode(dmginfo, hitgroup)
			elseif status == &quot;Finish&quot; 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 &amp;&amp; !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 &amp;&amp; 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 == &quot;PreInit&quot; &amp;&amp; self.CustomAttackCheck_MeleeAttack then
				return !self:CustomAttackCheck_MeleeAttack(enemy)
			elseif status == &quot;Init&quot; &amp;&amp; self.CustomOnMeleeAttack_BeforeStartTimer then
				self:CustomOnMeleeAttack_BeforeStartTimer(self.AttackSeed)
			elseif status == &quot;PostInit&quot; &amp;&amp; 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 == &quot;Init&quot; &amp;&amp; (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 == &quot;PreDamage&quot; &amp;&amp; self.CustomOnMeleeAttack_AfterChecks then
				return self:CustomOnMeleeAttack_AfterChecks(ent, isProp)
			elseif status == &quot;Miss&quot; &amp;&amp; (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(&quot;m_HackedGunPos&quot;, defShootVec) -- Overrides the location of self:GetShootPos()
	
	-- Set a name if it doesn&#x27;t have one
	if self:GetName() == &quot;&quot; then
		local findListing = list.Get(&quot;NPC&quot;)[self:GetClass()]
		if findListing then
			self:SetName((self.PrintName == &quot;&quot; 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 &gt; 0 then self.SightDistance = sightConvar end
	
	-- Capabilities &amp; 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 &quot;ai_baseactor&quot; to work properly!
	if self:LookupAttachment(&quot;eyes&quot;) &gt; 0 &amp;&amp; self:LookupAttachment(&quot;forward&quot;) &gt; 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 &amp;&amp; !self.Weapon_IgnoreSpawnMenu then
		self:CapabilitiesAdd(capBitsWeapons)
	end
	
	-- Health
	local hpConvar = vj_npc_health:GetInt()
	local hp = hpConvar &gt; 0 &amp;&amp; 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 &quot;Init&quot;
	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&#x27;t given a value THEN if self.IdleAlwaysWander isn&#x27;t true, wait at least 1 sec before wandering
	duplicator.RegisterEntityClass(self:GetClass(), VJ.CreateDupe_NPC, &quot;Model&quot;, &quot;Class&quot;, &quot;Equipment&quot;, &quot;SpawnFlags&quot;, &quot;Data&quot;)
	
	-- Delayed init
	timer.Simple(0.1, function()
		if IsValid(self) then
			self:SetMaxLookDistance(self.SightDistance)
			self:SetFOV(self.SightAngle)
			if self:GetNPCState() &lt;= NPC_STATE_NONE then self:SetNPCState(NPC_STATE_IDLE) end
			if IsValid(self:GetCreator()) &amp;&amp; self:GetCreator():GetInfoNum(&quot;vj_npc_spawn_guard&quot;, 0) == 1 then self.IsGuard = true end
			self:StartSoundTrack()
			
			-- Setup common default pose parameters
			if self:LookupPoseParameter(&quot;aim_pitch&quot;) != -1 then
				self.PoseParameterLooking_Names.pitch[#self.PoseParameterLooking_Names.pitch + 1] = &quot;aim_pitch&quot;
			end
			if self:LookupPoseParameter(&quot;head_pitch&quot;) != -1 then
				self.PoseParameterLooking_Names.pitch[#self.PoseParameterLooking_Names.pitch + 1] = &quot;head_pitch&quot;
			end
			if self:LookupPoseParameter(&quot;aim_yaw&quot;) != -1 then
				self.PoseParameterLooking_Names.yaw[#self.PoseParameterLooking_Names.yaw + 1] = &quot;aim_yaw&quot;
			end
			if self:LookupPoseParameter(&quot;head_yaw&quot;) != -1 then
				self.PoseParameterLooking_Names.yaw[#self.PoseParameterLooking_Names.yaw + 1] = &quot;head_yaw&quot;
			end
			if self:LookupPoseParameter(&quot;aim_roll&quot;) != -1 then
				self.PoseParameterLooking_Names.roll[#self.PoseParameterLooking_Names.roll + 1] = &quot;aim_roll&quot;
			end
			if self:LookupPoseParameter(&quot;head_roll&quot;) != -1 then
				self.PoseParameterLooking_Names.roll[#self.PoseParameterLooking_Names.roll + 1] = &quot;head_roll&quot;
			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 &amp;&amp; self.CanChatMessage &amp;&amp; IsValid(self:GetCreator()) then
						self:GetCreator():PrintMessage(HUD_PRINTTALK, &quot;WARNING: &quot; .. self:GetName() .. &quot; requires a VJ Base weapon to work properly!&quot;)
					end
					local antiArmor = PICK(self.WeaponInventory_AntiArmorList)
					if antiArmor &amp;&amp; wep:GetClass() != antiArmor then -- If the list isn&#x27;t empty and it&#x27;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 &amp;&amp; wep:GetClass() != melee then -- If the list isn&#x27;t empty and it&#x27;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()) &amp;&amp; self.CanChatMessage &amp;&amp; !self.Weapon_IgnoreSpawnMenu then
						self:GetCreator():PrintMessage(HUD_PRINTTALK, &quot;WARNING: &quot; .. self:GetName() .. &quot; requires a weapon!&quot;)
					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 &quot;NextThink&quot; to CurTime will cause performance drops, so we set the idle maintain in a separate hook that runs every tick
			local thinkHook = hook.GetTable()[&quot;Think&quot;]
			if (thinkHook &amp;&amp; !thinkHook[self]) or (!thinkHook) then
				local idleFunc = self.MaintainIdleAnimation
				if #self:GetBoneFollowers() &gt; 0 then
					hook.Add(&quot;Think&quot;, self, function()
						if VJ_CVAR_AI_ENABLED then
							idleFunc(self)
						end
						self:UpdateBoneFollowers()
					end)
				else
					hook.Add(&quot;Think&quot;, self, function()
						if VJ_CVAR_AI_ENABLED then
							idleFunc(self)
						end
					end)
				end
			else
				VJ.DEBUG_Print(self, false, &quot;warn&quot;, &quot;has an existing embedded \&quot;Think\&quot; hook already, which is disallowing the default base hook from assigning. Make sure to handle \&quot;MaintainIdleAnimation\&quot; in the overridden hook!&quot;)
			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) &amp;&amp; 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 &amp;&amp; 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(&quot;SCHEDULE_ALERT_CHASE_LOS&quot;)
	schedule_alert_chaseLOS:EngTask(&quot;TASK_GET_PATH_TO_ENEMY_LOS&quot;, 0)
	//schedule_alert_chaseLOS:EngTask(&quot;TASK_RUN_PATH&quot;, 0)
	schedule_alert_chaseLOS:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
	//schedule_alert_chaseLOS:EngTask(&quot;TASK_FACE_ENEMY&quot;, 0)
	//schedule_alert_chaseLOS.ResetOnFail = true
	schedule_alert_chaseLOS.CanShootWhenMoving = true
	schedule_alert_chaseLOS.CanBeInterrupted = true
--
local schedule_alert_chase = vj_ai_schedule.New(&quot;SCHEDULE_ALERT_CHASE&quot;)
	schedule_alert_chase:EngTask(&quot;TASK_GET_PATH_TO_ENEMY&quot;, 0)
	schedule_alert_chase:EngTask(&quot;TASK_RUN_PATH&quot;, 0)
	schedule_alert_chase:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
	//schedule_alert_chase:EngTask(&quot;TASK_FACE_ENEMY&quot;, 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 == &quot;SCHEDULE_ALERT_CHASE&quot; then return end // &amp;&amp; (self:GetEnemyLastKnownPos():Distance(self:GetEnemy():GetPos()) &lt;= 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 &gt; 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 &gt; curTime or (selfData.AttackAnimTime &gt; curTime &amp;&amp; moveType != VJ_MOVETYPE_AERIAL &amp;&amp; moveType != VJ_MOVETYPE_AQUATIC) then return end
	
	-- Not melee attacking yet but it is in range, so don&#x27;t chase the enemy!
	if selfData.HasMeleeAttack &amp;&amp; eneData.DistanceNearest &lt; selfData.MeleeAttackDistance &amp;&amp; eneData.Visible &amp;&amp; (self:GetHeadDirection():Dot((ene:GetPos() - self:GetPos()):GetNormalized()) &gt; 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&#x27;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(&quot;TASK_RUN_PATH&quot;)
		selfData.NextChaseTime = curTime + 3
		return
	end
	
	if !alwaysChase &amp;&amp; (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)) &amp;&amp; (IsValid(self:GetActiveWeapon()) &amp;&amp; (!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 &gt; curTime then return end -- Don&#x27;t set it if it&#x27;s already set!
	selfData.NextChaseTime = curTime + (((eneData.Distance &gt; 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 &#x60;return self.BaseClass.TranslateActivity(self, act)&#x60; at the end of the function
		2. If you are replacing ACT_IDLE from a randomized table, then you must call &#x60;self:ResolveAnimation&#x60;
			- 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, &quot;TranslateActivity&quot;, 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 &amp;&amp; self:GetWeaponState() != VJ.WEP_STATE_HOLSTERED &amp;&amp; IsValid(self:GetActiveWeapon()) then
			//return PICK(selfData.AnimTbl_WeaponAim)
			return ACT_IDLE_ANGRY
		end
	-- Handle running while scared animation
	elseif act == ACT_RUN &amp;&amp; selfData.Weapon_UnarmedBehavior_Active &amp;&amp; !selfData.VJ_IsBeingControlled then
		// PICK(selfData.AnimTbl_ScaredBehaviorMovement)
		return ACT_RUN_PROTECTED
	elseif (act == ACT_RUN or act == ACT_WALK) &amp;&amp; selfData.Alerted then
		-- Handle aiming while moving animations
		local eneData = selfData.EnemyData
		if selfData.Weapon_CanMoveFire &amp;&amp; IsValid(eneData.Target) &amp;&amp; (eneData.Visible or (eneData.VisibleTime + 5) &gt; CurTime()) &amp;&amp; selfData.CurrentSchedule &amp;&amp; selfData.CurrentSchedule.CanShootWhenMoving &amp;&amp; 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 -- &quot;or act&quot; = To make sure it doesn&#x27;t return nil when the table is empty!
		end
		return translation
	end
	return act
end
---------------------------------------------------------------------------------------------------------------------------------------------
local sdWepSwitch = {&quot;physics/metal/weapon_impact_soft1.wav&quot;, &quot;physics/metal/weapon_impact_soft2.wav&quot;, &quot;physics/metal/weapon_impact_soft3.wav&quot;}
--
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 &amp;&amp; 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) &amp;&amp; self.WeaponInventoryStatus &lt;= 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&#x27;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&#x27;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 &gt;= 0 then
		timer.Create(&quot;wep_state_reset&quot; .. self:EntIndex(), time, 1, function()
			self:SetWeaponState()
		end)
	else
		timer.Remove(&quot;wep_state_reset&quot; .. 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(&quot;attack_melee_reset&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextAnyAttackTime_Melee, self.TimeUntilMeleeAttackDamage, self.AttackAnimDuration), 1, function()
				self:StopAttacks()
				self:MaintainAlertBehavior()
			end)
		end
		timer.Create(&quot;attack_melee_reset_able&quot; .. 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(&quot;attack_grenade_reset&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextAnyAttackTime_Grenade, self.GrenadeAttackThrowTime, self.AttackAnimDuration), 1, function()
				self:StopAttacks()
				self:MaintainAlertBehavior()
			end)
		end
		//timer.Create(&quot;attack_grenade_reset_able&quot; .. 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, &quot;Visible&quot;)
	if anim != ACT_INVALID then
		local wep = self.WeaponEntity
		if wep.IsVJBaseWeapon then wep:NPC_Reload() end
		timer.Create(&quot;wep_reload_reset&quot; .. self:EntIndex(), animDur, 1, function()
			if IsValid(self) &amp;&amp; IsValid(wep) &amp;&amp; self:GetWeaponState() == VJ.WEP_STATE_RELOADING then
				wep:SetClip1(wep:GetMaxClip1())
				if wep.IsVJBaseWeapon then wep:OnReload(&quot;Finish&quot;) 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&#x27;t run after the enemy right away
		if !self.VJ_IsBeingControlled &amp;&amp; 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 &lt;= 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 &quot;sv_pvsskipanimation&quot; handles it | Fix attachments, bones, positions, angles etc. being broken in NPCs! This condition is used as a backup in case &quot;sv_pvsskipanimation&quot; isn&#x27;t disabled!
	//if self.MovementType == VJ_MOVETYPE_GROUND &amp;&amp; self:GetVelocity():Length() &lt;= 0 &amp;&amp; !self:IsEFlagSet(EFL_IS_BEING_LIFTED_BY_BARNACLE) /*&amp;&amp; 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 &gt; 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 &amp;&amp; selfData.HasSounds &amp;&amp; curTime &gt; selfData.NextBreathSoundT then
			local pickedSD = PICK(selfData.SoundTbl_Breath)
			local dur = 10 -- Make the default value large so we don&#x27;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 &amp;&amp; self:GetState() != VJ_STATE_FREEZE &amp;&amp; !self:IsEFlagSet(EFL_IS_BEING_LIFTED_BY_BARNACLE) then
		if selfData.VJ_DEBUG then
			if GetConVar(&quot;vj_npc_debug_enemy&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, false, &quot;Enemy -&gt; &quot; .. tostring(self:GetEnemy() or &quot;NULL&quot;) .. &quot; | Alerted? &quot; .. tostring(selfData.Alerted))  end
			if GetConVar(&quot;vj_npc_debug_takingcover&quot;):GetInt() == 1 then if curTime &gt; selfData.TakingCoverT then VJ.DEBUG_Print(self, false, &quot;NOT taking cover&quot;) else VJ.DEBUG_Print(self, false, &quot;Taking cover (&quot; .. selfData.TakingCoverT - curTime .. &quot;)&quot;) end end
			if GetConVar(&quot;vj_npc_debug_lastseenenemytime&quot;):GetInt() == 1 then PrintMessage(HUD_PRINTTALK, (curTime - selfData.EnemyData.VisibleTime) .. &quot; (&quot; .. self:GetName() .. &quot;)&quot;) end
			if IsValid(selfData.WeaponEntity) &amp;&amp; GetConVar(&quot;vj_npc_debug_weapon&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, false, &quot; : Weapon -&gt; &quot; .. tostring(selfData.WeaponEntity) .. &quot; | Ammo: &quot; .. selfData.WeaponEntity:Clip1() .. &quot; / &quot; .. selfData.WeaponEntity:GetMaxClip1() .. &quot; | Accuracy: &quot; .. selfData.Weapon_Accuracy) end
		end
		
		//self:SetPlaybackRate(self.AnimationPlaybackRate)
		self:OnThinkActive()
		
		-- Update follow system&#x27;s data
		//print(&quot;------------------&quot;)
		//PrintTable(selfData.FollowData)
		if selfData.IsFollowing &amp;&amp; self:GetNavType() != NAV_JUMP &amp;&amp; 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) &amp;&amp; (!followIsLiving or (followIsLiving &amp;&amp; (self:Disposition(followEnt) == D_LI or self:GetClass() == followEnt:GetClass()) &amp;&amp; followEnt:Alive())) then
				if curTime &gt; followData.NextUpdateT &amp;&amp; !selfData.VJ_ST_Healing then
					local distToPly = self:GetPos():Distance(followEnt:GetPos())
					local busy = self:IsBusy(&quot;Activities&quot;)
					self:SetTarget(followEnt)
					followData.StopAct = false
					if distToPly &gt; followData.MinDist then -- Entity is far away, move towards it!
						local isFar = distToPly &gt; (followData.MinDist * 4)
						-- IF (we are busy but far) OR (not busy) THEN move
						if (busy &amp;&amp; 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 &lt; (followData.MinDist * 1.5) and &quot;Calm&quot;) or &quot;Alert&quot;, {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 &quot;OnTaskFailed&quot; so an NPC can capture it! (Ex: HL1 scientist complaining to the player)
								//if goalTarget then
								local schedule = vj_ai_schedule.New(&quot;SCHEDULE_FOLLOW&quot;)
								schedule:EngTask(&quot;TASK_GET_PATH_TO_TARGET&quot;, 0) -- Required to generate the path!
								schedule:EngTask(&quot;TASK_MOVE_TO_TARGET_RANGE&quot;, followData.MinDist * 0.8)
								schedule:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
								schedule:EngTask(&quot;TASK_FACE_TARGET&quot;, 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 &lt; (followData.MinDist * 1.5) and &quot;TASK_WALK_PATH&quot;) or &quot;TASK_RUN_PATH&quot;, 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(&quot;MAX CLIP: &quot;, selfData.WeaponEntity:GetMaxClip1())
		//print(&quot;CLIP: &quot;, selfData.WeaponEntity:Clip1())
			
		if !selfData.Dead then
			-- Health Regeneration System
			local healthRegen = selfData.HealthRegenParams
			if healthRegen.Enabled &amp;&amp; curTime &gt; 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&#x27;t exist or it&#x27;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) &gt; ((eneData.Distance &lt; 4000 and selfData.EnemyTimeout) or (selfData.EnemyTimeout / 2)) &amp;&amp; !selfData.IsVJBaseSNPC_Tank then
					self:PlaySoundSystem(&quot;LostEnemy&quot;)
					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) &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
				-- Weapon Inventory System
				if !plyControlled then
					if eneValid then
						-- Switch to melee
						if !selfData.IsGuard &amp;&amp; IsValid(selfData.WeaponInventory.Melee) &amp;&amp; ((eneData.Distance &lt; selfData.MeleeAttackDistance) or (eneData.Distance &lt; 300 &amp;&amp; curWep:Clip1() &lt;= 0)) &amp;&amp; (self:Health() &gt; self:GetMaxHealth() * 0.25) &amp;&amp; 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(&quot;wep_reload_reset&quot; .. 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 &amp;&amp; IsValid(selfData.WeaponInventory.AntiArmor) &amp;&amp; (ene.IsVJBaseSNPC_Tank or ene.VJ_ID_Boss) &amp;&amp; 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 &amp;&amp; (!eneValid or (eneValid &amp;&amp; eneData.Distance &gt;= 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 &amp;&amp; (!eneValid or (eneValid &amp;&amp; !ene.IsVJBaseSNPC_Tank &amp;&amp; !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 &amp;&amp; !selfData.AttackType &amp;&amp; !curWep.IsMeleeWeapon &amp;&amp; self:GetWeaponState() == VJ.WEP_STATE_READY &amp;&amp; ((!plyControlled &amp;&amp; ((!eneValid &amp;&amp; curWep:GetMaxClip1() &gt; curWep:Clip1() &amp;&amp; (curTime - eneData.TimeSet) &gt; math.random(3, 8) &amp;&amp; !self:IsMoving()) or (eneValid &amp;&amp; curWep:Clip1() &lt;= 0))) or (plyControlled &amp;&amp; selfData.VJ_TheController:KeyDown(IN_RELOAD) &amp;&amp; curWep:GetMaxClip1() &gt; 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(&quot;WeaponReload&quot;) 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 &amp;&amp; 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 &lt; 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(&quot;SCHEDULE_COVER_RELOAD&quot;)
									schedule:EngTask(&quot;TASK_FIND_COVER_FROM_ENEMY&quot;, 0)
									schedule:EngTask(&quot;TASK_RUN_PATH&quot;, 0)
									schedule:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
									schedule.RunCode_OnFinish = function()
										if self:GetWeaponState() == VJ.WEP_STATE_RELOADING then
											-- If the current situation isn&#x27;t favorable, then abandon the current reload, and try again!
											if self.AttackType or (IsValid(self:GetEnemy()) &amp;&amp; eneData.Distance &lt;= self.Weapon_RetreatDistance) then
												self:SetWeaponState()
												//timer.Remove(&quot;wep_reload_reset&quot; .. self:EntIndex()) -- Remove the timer to make sure it doesn&#x27;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 &amp;&amp; selfData.WeaponAttackState &gt;= VJ.WEP_ATTACK_STATE_FIRE
				if eneIsVisible then
					if self:IsInViewCone(enePos) &amp;&amp; (eneDist &lt; self:GetMaxLookDistance()) then
						eneData.VisibleTime = curTime
						-- Why 2 vars? Because the last &quot;Visible&quot; 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 &quot;Visible&quot; uses it to run the trace in the engine! | For origin, use &quot;self:GetEnemyLastSeenPos()&quot;
					end
					if firingWep then self:PlaySoundSystem(&quot;Suppressing&quot;) end
				elseif firingWep then
					selfData.WeaponAttackState = VJ.WEP_ATTACK_STATE_NONE
				end

				-- Call for help
				if selfData.CallForHelp &amp;&amp; curTime &gt; selfData.NextCallForHelpT &amp;&amp; !selfData.AttackType then
					self:Allies_CallHelp(selfData.CallForHelpDistance)
					selfData.NextCallForHelpT = curTime + selfData.CallForHelpCooldown
				end
				
				self:UpdatePoseParamTracking()
				
				-- Attacks
				if !selfData.PauseAttacks &amp;&amp; !selfData.Flinching &amp;&amp; !selfData.FollowData.StopAct &amp;&amp; curTime &gt; selfData.NextDoAnyAttackT &amp;&amp; self:GetState() != VJ_STATE_ONLY_ANIMATION_NOATTACK &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE_NATURE then
					-- Attack priority in order: Custom --&gt; Melee --&gt; Grenade
					local funcThinkAtk = self.OnThinkAttack; if funcThinkAtk then funcThinkAtk(self, !!selfData.AttackType, ene) end
					
					-- Melee Attack
					if selfData.HasMeleeAttack &amp;&amp; selfData.IsAbleToMeleeAttack &amp;&amp; !selfData.AttackType &amp;&amp; (!IsValid(curWep) or (IsValid(curWep) &amp;&amp; (!curWep.IsMeleeWeapon))) &amp;&amp; ((plyControlled &amp;&amp; selfData.VJ_TheController:KeyDown(IN_ATTACK)) or (!plyControlled &amp;&amp; (eneDistNear &lt; selfData.MeleeAttackDistance &amp;&amp; eneIsVisible) &amp;&amp; (self:GetHeadDirection():Dot((enePos - myPos):GetNormalized()) &gt; math_cos(math_rad(selfData.MeleeAttackAngleRadius))))) &amp;&amp; self:OnMeleeAttack(&quot;PreInit&quot;, 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(&quot;Enemy&quot;) -- Always turn towards the enemy at the start
						self:OnMeleeAttack(&quot;Init&quot;, ene)
						self:PlaySoundSystem(&quot;BeforeMeleeAttack&quot;)
						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(&quot;attack_melee_start&quot; .. 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(&quot;attack_melee_start&quot; .. curTime + k, t, function() if selfData.AttackSeed == seed then self:ExecuteMeleeAttack() end end)
								end
							end
						end
						self:OnMeleeAttack(&quot;PostInit&quot;, ene)
					end
					
					-- Grenade attack
					if selfData.HasGrenadeAttack &amp;&amp; curTime &gt; selfData.NextThrowGrenadeT &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; self:GetWeaponState() != VJ.WEP_STATE_RELOADING &amp;&amp; !self:IsBusy(&quot;Activities&quot;) 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 &gt; 3 &amp;&amp; (ene.IsVJBaseSNPC_Tank or !eneIsVisible) and math.floor(chance / 2)) or chance) == 1 &amp;&amp; eneDist &lt; selfData.GrenadeAttackMaxDistance &amp;&amp; eneDist &gt; 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 &amp;&amp; selfData.UpdatedPoseParam &amp;&amp; !plyControlled then
					self:ClearPoseParameters()
					selfData.UpdatedPoseParam = false
				end
				eneData.TimeAcquired = 0
			end
			
			-- Guarding Behavior
			if selfData.IsGuard &amp;&amp; !selfData.IsFollowing &amp;&amp; !selfData.IsVJBaseSNPC_Tank then
				local guardData = selfData.GuardData
				if !guardData.Position then -- If we don&#x27;t have a position, then set it!
					guardData.Position = myPos
					guardData.Direction = myPos + self:GetForward() * 51
				end
				-- If it&#x27;s far from the guarding position, then go there!
				if !self:IsMoving() &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
					local dist = myPos:Distance(guardData.Position) -- Distance to the guard position
					if dist &gt; 50 then
						self:SetLastPosition(guardData.Position)
						self:SCHEDULE_GOTO_POSITION(dist &lt;= 800 and &quot;TASK_WALK_PATH&quot; or &quot;TASK_RUN_PATH&quot;, function(x)
							x.CanShootWhenMoving = true
							x.TurnData = {Type = VJ.FACE_ENEMY}
							x.RunCode_OnFinish = function()
								timer.Simple(0.01, function()
									if IsValid(self) &amp;&amp; !self:IsMoving() &amp;&amp; !self:IsBusy(&quot;Activities&quot;) &amp;&amp; selfData.IsGuard &amp;&amp; guardData.Position then
										self:SetLastPosition(guardData.Direction)
										self:SCHEDULE_FACE(&quot;TASK_FACE_LASTPOSITION&quot;)
									end
								end)
							end
						end)
					end
				end
			end
		end
		-- Handle the unique movement system for player models
		if selfData.UsePoseParameterMovement &amp;&amp; selfData.MovementType == VJ_MOVETYPE_GROUND then
			local moveDir = VJ.GetMoveDirection(self, true)
			if moveDir then
				funcSetPoseParameter(self, &quot;move_x&quot;, moveDir.x)
				funcSetPoseParameter(self, &quot;move_y&quot;, moveDir.y)
			else -- I am not moving, reset the pose parameters, otherwise I will run in place!
				funcSetPoseParameter(self, &quot;move_x&quot;, 0)
				funcSetPoseParameter(self, &quot;move_y&quot;, 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 &quot;OverrideMoveFacing&quot; now handles it!
	/*if !didTurn then
		local curTurnData = self.TurnData
		if curTurnData.Type &amp;&amp; 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 &amp;&amp; selfData.AttackState == VJ.ATTACK_STATE_EXECUTED_HIT) then return end
	local skip = self:OnMeleeAttackExecute(&quot;Init&quot;)
	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 &amp;&amp; ent.VJ_IsBeingControlled) then continue end
			if ent:IsPlayer() &amp;&amp; (ent.VJ_IsControllingNPC or !ent:Alive() or VJ_CVAR_IGNOREPLAYERS) then continue end
			if ((ent.VJ_ID_Living &amp;&amp; self:Disposition(ent) != D_LI) or ent.VJ_ID_Attackable or ent.VJ_ID_Destructible) &amp;&amp; self:MeleeAttackTraceDirection():Dot((Vector(ent:GetPos().x, ent:GetPos().y, 0) - Vector(myPos.x, myPos.y, 0)):GetNormalized()) &gt; math_cos(math_rad(selfData.MeleeAttackDamageAngleRadius)) then
				local isProp = ent.VJ_ID_Attackable
				if self:OnMeleeAttackExecute(&quot;PreDamage&quot;, ent, isProp) == true then continue end
				local dmgAmount = self:ScaleByDifficulty(selfData.MeleeAttackDamage)
				-- Knockback (Don&#x27;t push things like doors, trains, elevators as it will make them fly when activated)
				if selfData.HasMeleeAttackKnockBack &amp;&amp; ent:GetMoveType() != MOVETYPE_PUSH &amp;&amp; ent.MovementType != VJ_MOVETYPE_STATIONARY &amp;&amp; (!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 &lt; 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(&quot;MeleeAttack&quot;)
			selfData.AttackState = VJ.ATTACK_STATE_EXECUTED_HIT
		else
			self:OnMeleeAttackExecute(&quot;Miss&quot;)
			self:PlaySoundSystem(&quot;MeleeAttackMiss&quot;)
		end
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Triggers a grenade attack
		- customEnt = What entity it should throw | DEFAULT: nil
			- nil = Spawn the NPC&#x27;s default grenade class usually set by &quot;self.GrenadeAttackEntity&quot;
			- 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 = &quot;FindBest&quot;

	-- Handle possible destinations:
		-- Enemy not valid --&gt; Best position away from the NPC and allies
		-- Enemy valid AND Enemy visible --&gt; Enemy&#x27;s position
		-- Enemy valid AND Enemy not visible AND last seen position is visible --&gt; Enemy&#x27;s last visible position
		-- Enemy valid AND Enemy not visible AND last seen position is not visible --&gt; Cancel attack
		-- Enemy valid AND Enemy not visible AND last seen position is not visible AND grenade is live throw back --&gt; Best position away from the NPC and allies
	if IsValid(ene) then
		-- If enemy is visible then face them!
		if eneData.Visible then
			landDir = &quot;Enemy&quot; -- Do NOT face random pos, even if &quot;self.GrenadeAttackAnimationFaceEnemy&quot; is disabled!
		else -- We have a hidden enemy...
			-- Attempt to flush the enemy out of hiding
			if self:VisibleVec(eneData.VisiblePos) &amp;&amp; ene:GetPos():Distance(eneData.VisiblePos) &lt;= self.GrenadeAttackMaxDistance then // self.GrenadeAttackMaxDistance
				landDir = &quot;EnemyLastVis&quot; -- We are going to face flush position, do NOT face random pos!
			-- If can&#x27;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&#x27;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(&quot;Init&quot;, 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 == &quot;Enemy&quot; then -- Face enemy
		if self.GrenadeAttackAnimationFaceEnemy then
			self:SetTurnTarget(&quot;Enemy&quot;)
		end
	elseif landDir == &quot;EnemyLastVis&quot; then -- Face enemy&#x27;s last visible pos
		self:SetTurnTarget(eneData.VisiblePos, self.AttackAnimDuration or 1.5)
	else -- Face best pos
		local bestPos = PICK(VJ.TraceDirections(self, &quot;Quick&quot;, 200, true, false, 8))
		if bestPos then
			landDir = bestPos -- Save the position so it can be used when it&#x27;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&#x27;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&#x27;s shoot position (fail safe)
		local customPos = self:OnGrenadeAttack(&quot;SpawnPos&quot;, 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(&quot;GrenadeAttack&quot;)
	
	local releaseTime = self.GrenadeAttackThrowTime
	if !releaseTime then -- Call this right away for event-based attacks!
		attackTimers[VJ.ATTACK_TYPE_GRENADE](self)
	end
	-- &quot;attack_grenade_start&quot; 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 &quot;attack_grenade_reset&quot; to be used as a fail safe in case the animation is cut off!
	-- Call &quot;timer.Adjust(&quot;attack_grenade_start&quot; .. self:EntIndex(), 0)&quot; in the event code to make it throw the grenade
	timer.Create(&quot;attack_grenade_start&quot; .. self:EntIndex(), (!releaseTime and timer.TimeLeft(&quot;attack_grenade_reset&quot; .. self:EntIndex())) or releaseTime / self.AnimPlaybackRate, 1, function()
		if self.AttackSeed == seed then
			if isLiveEnt &amp;&amp; !IsValid(customEnt) then return end
			self:ExecuteGrenadeAttack(customEnt, disableOwner, landDir)
		end
	end)
	self:OnGrenadeAttack(&quot;PostInit&quot;, customEnt, landDir)
	return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Performs a grenade attack
		- customEnt = What entity it should throw | DEFAULT: nil
			- nil = Spawn the NPC&#x27;s default grenade class usually set by &quot;self.GrenadeAttackEntity&quot;
			- 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
			- &quot;Enemy&quot; = Use enemy&#x27;s position
			- &quot;EnemyLastVis&quot; = Use enemy&#x27;s last visible position
			- vector = Use given vector&#x27;s position
			- &quot;FindBest&quot; 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&#x27;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&#x27;s shoot position (fail safe)
	local spawnPos = self:OnGrenadeAttack(&quot;SpawnPos&quot;, 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 &amp; face because it&#x27;s pointless at this point since the grenade is already being released!
	local landingPos = self:GetPos() + self:GetForward()*200
	if landDir == &quot;Enemy&quot; then -- Use enemy&#x27;s position
		landingPos = self:GetEnemyLastKnownPos()
		//if self.GrenadeAttackAnimationFaceEnemy then self:SetTurnTarget(&quot;Enemy&quot;) end
	elseif landDir == &quot;EnemyLastVis&quot; then -- Use enemy&#x27;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&#x27;s position
		landingPos = landDir
	else -- Find a best random position | Includes &quot;FindBest&quot;
		local bestPos = PICK(VJ.TraceDirections(self, &quot;Quick&quot;, 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&#x27;s default grenades
	if isLiveEnt then -- It&#x27;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 &amp;&amp; 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 == &quot;obj_vj_grenade&quot; then
			grenade.FuseTime = fuseTime
		elseif gerClass == &quot;npc_grenade_frag&quot; then
			grenade:Input(&quot;SetTimer&quot;, grenade:GetOwner(), grenade:GetOwner(), fuseTime)
		elseif gerClass == &quot;obj_cpt_grenade&quot; then
			grenade:SetTimer(fuseTime)
		elseif gerClass == &quot;obj_spore&quot; then
			grenade:SetGrenade(true)
		elseif gerClass == &quot;ent_hl1_grenade&quot; then
			grenade:ShootTimed(grenade:GetOwner(), defPos, fuseTime)
		elseif gerClass == &quot;doom3_grenade&quot; or gerClass == &quot;obj_handgrenade&quot; then
			grenade:SetExplodeDelay(fuseTime)
		elseif gerClass == &quot;cw_grenade_thrown&quot; or gerClass == &quot;cw_flash_thrown&quot; or gerClass == &quot;cw_smoke_thrown&quot; then
			grenade:SetOwner(self)
			grenade:Fuse(fuseTime)
		end
		
		self:OnGrenadeAttackExecute(&quot;PreSpawn&quot;, grenade, customEnt, landDir, landingPos)
		grenade:Spawn()
		grenade:Activate()
	end
	
	-- Handle throw velocity
	local postSpawnResult = self:OnGrenadeAttackExecute(&quot;PostSpawn&quot;, 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&#x27;t have a physics object, then attempt to set the entity&#x27;s velocity directly
			grenade:SetVelocity(vel)
		end
	end
	
	if self.AttackState &lt; 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) ---&gt; Combine dropship impact position, Combine gunship turret impact position, Strider minigun impact position
local sdBitCombine = bit.bor(SOUND_DANGER, SOUND_CONTEXT_EXCLUDE_COMBINE) ---&gt; Flechette impact position, Strider foot impact position
local sdBitPlyVehicle = bit.bor(SOUND_DANGER, SOUND_CONTEXT_PLAYER_VEHICLE) ---&gt; Player driving a vehicle
local sdBitMortar = bit.bor(SOUND_DANGER, SOUND_CONTEXT_MORTAR) ---&gt; 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&#x27;s allies, commonly used for projectiles
- NPC Conditions
	- Detected as a danger
	- Distance based on the sound hint&#x27;s volume/distance
	- Does NOT ignore, is detected by everyone that catches the hint, including allies
	- BEST USE: Sounds that should scare the owner&#x27;s allies
-----------------------------------------------------------]]
function ENT:CheckForDangers()
	local selfData = self:GetTable()
	if !selfData.CanDetectDangers or selfData.AttackType == VJ.ATTACK_TYPE_GRENADE or selfData.NextDangerDetectionT &gt; 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) &amp;&amp; self:Visible(ent) then
			local owner = ent:GetOwner()
			if !(IsValid(owner) &amp;&amp; owner.IsVJBaseSNPC &amp;&amp; ((self:GetClass() == owner:GetClass()) or (self:Disposition(owner) == D_LI))) then
				if ent.VJ_ID_Danger then regDangerDetected = ent continue end -- If it&#x27;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(&quot;GrenadeSight&quot;) then self:PlaySoundSystem(&quot;DangerSight&quot;) 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 &amp;&amp; selfData.HasGrenadeAttack &amp;&amp; ent.VJ_ID_Grabbable &amp;&amp; !ent.VJ_ST_Grabbed &amp;&amp; ent:GetVelocity():Length() &lt; 400 &amp;&amp; VJ.GetNearestDistance(self, ent) &lt; 100 &amp;&amp; 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(&quot;TASK_RUN_PATH&quot;, 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(&quot;DangerSight&quot;)
		local curTime = CurTime()
		selfData.NextDangerDetectionT = curTime + 4
		selfData.TakingCoverT = curTime + 4
		self:SCHEDULE_COVER_ORIGIN(&quot;TASK_RUN_PATH&quot;, 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 &amp;&amp; GetConVar(&quot;vj_npc_debug_attack&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;StopAttacks&quot;, &quot;Attack type = &quot; .. selfData.AttackType) end
	
	if checkTimers &amp;&amp; selfData.AttackType == VJ.ATTACK_TYPE_MELEE &amp;&amp; selfData.AttackState &lt; 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 &gt; 180 and (diff - 360) or diff
end
--
function ENT:UpdatePoseParamTracking(resetPoses)
	local selfData = self:GetTable()
	if !selfData.HasPoseParameterLooking or (!selfData.VJ_IsBeingControlled &amp;&amp; (!selfData.WeaponAttackState or (!selfData.EnemyData.Visible &amp;&amp; selfData.WeaponAttackState &lt; 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 &amp;&amp; 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&#x27;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 &amp;&amp; CurTime() &gt; selfData.NextWeaponAttackT &amp;&amp; enemyDist &lt; selfData.Weapon_MaxDistance &amp;&amp; ((enemyDist &gt; selfData.Weapon_MinDistance) or curWep.IsMeleeWeapon) then
			hasDist = true
		end
		if checkDistanceOnly then
			return hasDist
		end
	end
	if !selfData.AttackType &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
		hasChecks = true
		if !checkDistance then return true end
	end
	return hasDist &amp;&amp; hasChecks
end
---------------------------------------------------------------------------------------------------------------------------------------------
local schedule_yield_player = vj_ai_schedule.New(&quot;SCHEDULE_YIELD_PLAYER&quot;)
	schedule_yield_player:EngTask(&quot;TASK_MOVE_AWAY_PATH&quot;, 120)
	schedule_yield_player:EngTask(&quot;TASK_RUN_PATH&quot;, 0)
	schedule_yield_player:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 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 &amp;&amp; (funcHasCondition(self, COND_HEAR_BULLET_IMPACT) or funcHasCondition(self, COND_HEAR_COMBAT) or funcHasCondition(self, COND_HEAR_WORLD) or funcHasCondition(self, COND_HEAR_DANGER)) &amp;&amp; selfData.NextInvestigationMove &lt; curTime &amp;&amp; selfData.TakingCoverT &lt; curTime &amp;&amp; !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 &amp;&amp; sdOwner:IsVehicle() &amp;&amp; IsValid(sdOwner:GetDriver()) &amp;&amp; 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 &amp;&amp; sdOwner:IsNPC() &amp;&amp; !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(&quot;TASK_FACE_LASTPOSITION&quot;)
					-- Works but just faces the enemy that fired at
					//local sched = vj_ai_schedule.New(&quot;SCHEDULE_HEAR_SOUND&quot;)
					//sched:EngTask(&quot;TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION&quot;, 0)
					//sched:EngTask(&quot;TASK_STOP_MOVING&quot;, 0)
					//sched:EngTask(&quot;TASK_FACE_SAVEPOSITION&quot;, 0)
					//self:StartSchedule(sched)
					self:OnInvestigate(sdOwner)
					self:PlaySoundSystem(&quot;Investigate&quot;)
					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() &amp;&amp; curTime &gt; selfData.NextChaseTime then
					selfData.Weapon_UnarmedBehavior_Active = true -- Tells the idle system to use the scared behavior animation
					if !selfData.IsFollowing &amp;&amp; eneData.Visible then
						self:SCHEDULE_COVER_ENEMY(&quot;TASK_RUN_PATH&quot;)
						return
					end
				end
			-- If it doesn&#x27;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 &quot;COND_PLAYER_PUSHING&quot;, 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&#x27;s to close
			if eneData.Distance &lt;= selfData.Weapon_RetreatDistance &amp;&amp; !wep.IsMeleeWeapon &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; curTime &gt; selfData.NextChaseTime &amp;&amp; !selfData.AttackType &amp;&amp; !selfData.IsFollowing &amp;&amp; ene.Behavior != VJ_BEHAVIOR_PASSIVE &amp;&amp; !self:DoCoverTrace(myPosCentered, enePos_Eye) then
				local moveCheck = PICK(VJ.TraceDirections(self, &quot;Quick&quot;, 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(&quot;TASK_RUN_PATH&quot;, function(x) x:EngTask(&quot;TASK_FACE_ENEMY&quot;, 0) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
					goto goto_conditions
				end
			end
			
			if self:CanFireWeapon(false, false) &amp;&amp; self:GetState() != VJ_STATE_ONLY_ANIMATION_NOATTACK then
				-- Enemy to far away or not allowed to fire a weapon
				if eneData.Distance &gt; selfData.Weapon_MaxDistance or curTime &lt; selfData.NextWeaponAttackT then
					self:MaintainAlertBehavior()
					selfData.AllowWeaponOcclusionDelay = false
				-- Check if enemy is in sight, then continue...
				elseif self:CanFireWeapon(true, true) then
					-- I can&#x27;t see the enemy from my eyes
					if self:DoCoverTrace(self:EyePos(), enePos_Eye, true) then // or (!eneData.Visible)
						if selfData.TakingCoverT &gt; curTime then return end -- Do NOT interrupt when taking cover (such as &quot;CombatDamageResponse&quot;)
						if self:GetWeaponState() != VJ.WEP_STATE_RELOADING then
							-- Wait when enemy is occluded
							if selfData.Weapon_OcclusionDelay &amp;&amp; selfData.WeaponAttackState != VJ.WEP_ATTACK_STATE_AIM_OCCLUSION &amp;&amp; !wep.IsMeleeWeapon &amp;&amp; selfData.AllowWeaponOcclusionDelay &amp;&amp; (curTime - selfData.WeaponLastShotTime) &lt;= 4.5 &amp;&amp; eneData.Distance &gt; 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 &lt; selfData.LastHiddenZoneT &amp;&amp; !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 &amp;&amp; selfData.WeaponAttackState &gt;= VJ.WEP_ATTACK_STATE_FIRE &amp;&amp; selfData.CurrentScheduleName != &quot;SCHEDULE_ALERT_CHASE&quot; &amp;&amp; selfData.CurrentScheduleName != &quot;SCHEDULE_ALERT_CHASE_LOS&quot; 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 &quot;FInAimCone&quot; - 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(&quot;Enemy&quot;)
						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 &lt; wepDif then
								self:SetTurnTarget(&quot;Enemy&quot;)
								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(&quot;Is covered? &quot;, inCover)
						//print(&quot;Is gun covered? &quot;, wepInCover)
						local inCoverEntLiving = false -- The covered entity is NOT a living entity
						if IsValid(inCoverEnt) &amp;&amp; inCoverEnt.VJ_ID_Living then
							inCoverEntLiving = true
						end
						if !wep.IsMeleeWeapon then
							-- If friendly in line of fire, then move!
							if inCoverEntLiving &amp;&amp; selfData.WeaponAttackState == VJ.WEP_ATTACK_STATE_FIRE_STAND &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; IsValid(wepInCoverEnt) &amp;&amp; wepInCoverEnt:IsNPC() &amp;&amp; wepInCoverEnt != self &amp;&amp; (self:Disposition(wepInCoverEnt) == D_LI or self:Disposition(wepInCoverEnt) == D_NU) &amp;&amp; wepInCoverTrace.HitPos:Distance(wepInCoverTrace.StartPos) &lt;= 3000 then
								local moveCheck = PICK(VJ.TraceDirections(self, &quot;Quick&quot;, 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(&quot;TASK_WALK_PATH&quot;, function(x) x:EngTask(&quot;TASK_FACE_ENEMY&quot;, 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&#x27;t fire!
								if curTime &lt; selfData.TakingCoverT then
									goto goto_conditions
								elseif curTime &gt; selfData.NextMoveOnGunCoveredT &amp;&amp; ((inCoverTrace.HitPos:Distance(myPos) &gt; 150 &amp;&amp; !inCoverEntLiving) or (wepInCover &amp;&amp; !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) &lt;= (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(&quot;SCHEDULE_GOTO_POSITION&quot;)
										schedule:EngTask(&quot;TASK_GET_PATH_TO_LASTPOSITION&quot;, 0)
										local coverRunAnim = self:TranslateActivity(PICK(selfData.AnimTbl_MoveToCover))
										if VJ.AnimExists(self, coverRunAnim) then
											self:SetMovementActivity(coverRunAnim)
										else -- Only shoot if we aren&#x27;t crouching running!
											schedule.CanShootWhenMoving = true
										end
										schedule:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
										schedule.TurnData = {Type = VJ.FACE_ENEMY}
										//schedule.StopScheduleIfNotMoving_Any = true
										self:StartSchedule(schedule)
										//self:SCHEDULE_GOTO_POSITION(&quot;TASK_WALK_PATH&quot;, function(x) x:EngTask(&quot;TASK_FACE_ENEMY&quot;, 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 &gt; selfData.NextWeaponAttackT &amp;&amp; curTime &gt; selfData.NextWeaponAttackT_Base then
							-- Melee weapons
							if wep.IsMeleeWeapon then
								self:OnWeaponAttack()
								local finalAnim = self:TranslateActivity(PICK(selfData.AnimTbl_WeaponAttack))
								if curTime &gt; selfData.NextMeleeWeaponAttackT &amp;&amp; VJ.AnimExists(self, finalAnim) then // &amp;&amp; !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() &gt; 0 -- Does it have ammo?
								if !hasAmmo &amp;&amp; selfData.WeaponAttackState != VJ.WEP_ATTACK_STATE_AIM then
									selfData.WeaponAttackAnim = ACT_INVALID
								end
								-- If it&#x27;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&#x27;t the last weapon animation and it&#x27;s not a transition, then continue
								elseif self:GetActivity() != selfData.WeaponAttackAnim &amp;&amp; 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 &amp;&amp; !inCover &amp;&amp; !wepInCover &amp;&amp; eneData.Distance &gt; 500 &amp;&amp; VJ.AnimExists(self, anim_crouch) &amp;&amp; math.random(1, selfData.Weapon_CrouchAttackChance) == 1 &amp;&amp; !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 &amp;&amp; VJ.AnimExists(self, finalAnim) &amp;&amp; (!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 &amp;&amp; !inCover &amp;&amp; !selfData.IsGuard &amp;&amp; !selfData.IsFollowing &amp;&amp; !wep.IsMeleeWeapon &amp;&amp; (!wep.NPC_StandingOnly) &amp;&amp; selfData.WeaponAttackState == VJ.WEP_ATTACK_STATE_FIRE_STAND &amp;&amp; curTime &gt; selfData.NextWeaponStrafeT &amp;&amp; (curTime - eneData.TimeAcquired) &gt; 2 &amp;&amp; (eneData.Distance &lt; (selfData.Weapon_MaxDistance / 1.25)) then
							if self:OnWeaponStrafe() != false then
								local moveCheck = PICK(VJ.TraceDirections(self, &quot;Radial&quot;, 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 &quot;TASK_RUN_PATH&quot; or &quot;TASK_WALK_PATH&quot;, function(x) x:EngTask(&quot;TASK_FACE_ENEMY&quot;, 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(&quot;Enemy&quot;)
						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) &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
		self:PlaySoundSystem(&quot;YieldToPlayer&quot;)
		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 &amp;&amp; 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) &amp;&amp; (curTime - ally.EnemyData.VisibleTime) &lt; selfData.EnemyTimeout &amp;&amp; allyEne:Alive() &amp;&amp; self:GetPos():Distance(allyEne:GetPos()) &lt;= self:GetMaxLookDistance() &amp;&amp; self:CheckRelationship(allyEne) == D_HT then
					selfData.AllowWeaponOcclusionDelay = false
					self:ForceSetEnemy(allyEne, false)
					eneData.VisibleTime = curTime -- Reset the time otherwise it will run &quot;ResetEnemy&quot; 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&#x27;t reset
		local curEnemies = eneData.VisibleCount //selfData.CurrentReachableEnemies
		if (eneValid &amp;&amp; (curEnemies - 1) &gt;= 1) or (!eneValid &amp;&amp; curEnemies &gt;= 1) then
			self:MaintainRelationships() -- Select a new enemy
			-- Check that the reset enemy wasn&#x27;t the only visible enemy
			-- If we don&#x27;t this, it will call &quot;ResetEnemy&quot; again!
			if eneData.VisibleCount &gt; 0 then
				eneData.Reset = false
				return false
			end
		end
	end
	
	if selfData.VJ_DEBUG &amp;&amp; GetConVar(&quot;vj_npc_debug_resetenemy&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;ResetEnemy&quot;, tostring(ene)) end
	eneData.Reset = true
	self:SetNPCState(NPC_STATE_ALERT)
	timer.Create(&quot;alert_reset&quot; .. 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 &amp;&amp; !selfData.IsGuard &amp;&amp; !selfData.IsVJBaseSNPC_Tank &amp;&amp; !selfData.VJ_IsBeingControlled &amp;&amp; selfData.LastHiddenZone_CanWander == true &amp;&amp; !selfData.Weapon_UnarmedBehavior_Active &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE_NATURE &amp;&amp; !self:IsBusy() &amp;&amp; !self:Visible(ene) &amp;&amp; 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 &gt; selfData.LastHiddenZoneT and true or false
	selfData.LastHiddenZoneT = 0
	
	-- Clear memory of the enemy if it&#x27;s not a player AND it&#x27;s dead
	if eneValid &amp;&amp; !ene:IsPlayer() &amp;&amp; !ene:Alive() then
		//print(&quot;Clear memory&quot;, 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 == &quot;SCHEDULE_COVER_ENEMY&quot; or selfData.CurrentScheduleName == &quot;SCHEDULE_COVER_ENEMY_FAIL&quot; then
		self:StopMoving()
	end
	selfData.NextWanderTime = curTime + math.Rand(3, 5)
	self:SetEnemy(NULL)
	if moveToEnemy then
		self:SetLastPosition(moveToEnemy)
		self:SCHEDULE_GOTO_POSITION(&quot;TASK_WALK_PATH&quot;, function(schedule)
			//if eneValid then schedule:EngTask(&quot;TASK_FORGET&quot;, ene) end
			//schedule:EngTask(&quot;TASK_IGNORE_OLD_ENEMIES&quot;, 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&#x27;t take bullet damage from friendly NPCs
	if dmgAttacker &amp;&amp; dmginfo:IsBulletDamage() &amp;&amp; dmgAttacker:IsNPC() &amp;&amp; dmgAttacker:Disposition(self) != D_HT &amp;&amp; (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 &amp;&amp; dmgInflictor:GetClass() == &quot;prop_ragdoll&quot; &amp;&amp; dmgInflictor:GetVelocity():Length() &lt;= 100 then return 0 end
	
	local selfData = self:GetTable()
	local hitgroup = self:GetLastDamageHitGroup()
	self:OnDamaged(dmginfo, hitgroup, &quot;Init&quot;)
	if selfData.GodMode or dmginfo:GetDamage() &lt;= 0 then return 0 end
	
	local dmgType = dmginfo:GetDamageType()
	local curTime = CurTime()
	local isFireEnt = false
	if self:IsOnFire() then
		isFireEnt = dmgInflictor &amp;&amp; dmgAttacker &amp;&amp; dmgInflictor:GetClass() == &quot;entityflame&quot; &amp;&amp; dmgAttacker:GetClass() == &quot;entityflame&quot;
		if self:WaterLevel() &gt; 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 &amp;&amp; selfData.ForceDamageFromBosses &amp;&amp; dmgAttacker.VJ_ID_Boss then
		goto skip_immunity
	end
	
	-- Immunity checks
	if isFireEnt &amp;&amp; !selfData.AllowIgnition then self:Extinguish() return 0 end
	if (selfData.Immune_Fire &amp;&amp; (dmgType == DMG_BURN or dmgType == DMG_SLOWBURN or isFireEnt)) or (selfData.Immune_Toxic &amp;&amp; (dmgType == DMG_ACID or dmgType == DMG_RADIATION or dmgType == DMG_POISON or dmgType == DMG_NERVEGAS or dmgType == DMG_PARALYZE)) or (selfData.Immune_Bullet &amp;&amp; (dmginfo:IsBulletDamage() or dmgType == DMG_BULLET or dmgType == DMG_AIRBOAT or dmgType == DMG_BUCKSHOT or dmgType == DMG_SNIPER)) or (selfData.Immune_Explosive &amp;&amp; (dmgType == DMG_BLAST or dmgType == DMG_BLAST_SURFACE or dmgType == DMG_MISSILEDEFENSE)) or (selfData.Immune_Dissolve &amp;&amp; dmginfo:IsDamageType(DMG_DISSOLVE)) or (selfData.Immune_Electricity &amp;&amp; (dmgType == DMG_SHOCK or dmgType == DMG_ENERGYBEAM or dmgType == DMG_PHYSGUN)) or (selfData.Immune_Melee &amp;&amp; (dmgType == DMG_CLUB or dmgType == DMG_SLASH)) or (selfData.Immune_Sonic &amp;&amp; dmgType == DMG_SONIC) then return 0 end
	
	-- Make sure combine ball does reasonable damage and doesn&#x27;t spam!
	if (dmgInflictor &amp;&amp; dmgInflictor:GetClass() == &quot;prop_combine_ball&quot;) or (dmgAttacker &amp;&amp; dmgAttacker:GetClass() == &quot;prop_combine_ball&quot;) then
		if selfData.Immune_Dissolve then return 0 end
		if curTime &gt; 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&#x27;s not caused by the default fire entity [Causes the damage position to be at Vector(0, 0, 0)]
			if selfData.HasBloodParticle &amp;&amp; !isFireEnt then self:SpawnBloodParticles(dmginfo, hitgroup) end
			if selfData.HasBloodDecal then self:SpawnBloodDecals(dmginfo, hitgroup) end
			self:PlaySoundSystem(&quot;Impact&quot;)
		end
	end
	if selfData.Dead then DoBleed() return 0 end -- If dead then just bleed but take no damage
	
	self:OnDamaged(dmginfo, hitgroup, &quot;PreDamage&quot;)
	if dmginfo:GetDamage() &lt;= 0 then return 0 end -- Only take damage if it&#x27;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 &amp;&amp; GetConVar(&quot;vj_npc_debug_damage&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;OnTakeDamage&quot;, &quot;Amount = &quot;, dmginfo:GetDamage(), &quot; | Attacker = &quot;, dmgAttacker, &quot; | Inflictor = &quot;, dmgInflictor) end
	local healthRegen = selfData.HealthRegenParams
	if healthRegen.Enabled &amp;&amp; healthRegen.ResetOnDmg then
		selfData.HealthRegenDelayT = curTime + (math.Rand(healthRegen.Delay.a, healthRegen.Delay.b) * 1.5)
	end
	self:SetSaveValue(&quot;m_iDamageCount&quot;, self:GetTotalDamageCount() + 1)
	self:SetSaveValue(&quot;m_flLastDamageTime&quot;, curTime)
	self:OnDamaged(dmginfo, hitgroup, &quot;PostDamage&quot;)
	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(&quot;OnDamaged&quot;, dmgAttacker)
		self:MarkTookDamageFromEnemy(dmgAttacker)
	else
		self:TriggerOutput(&quot;OnDamaged&quot;, self)
	end
	
	local stillAlive = self:Health() &gt; 0
	if stillAlive then self:PlaySoundSystem(&quot;Pain&quot;) end

	if VJ_CVAR_AI_ENABLED &amp;&amp; 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 &amp;&amp; dmgAttacker:IsPlayer() then
				-- Become enemy to a friendly player | RESULT: May become hostile to an allied player
				if selfData.BecomeEnemyToPlayer &amp;&amp; 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] &gt; selfData.BecomeEnemyToPlayer &amp;&amp; self:Disposition(dmgAttacker) != D_HT then
						self:OnBecomeEnemyToPlayer(dmginfo, hitgroup)
						if selfData.IsFollowing &amp;&amp; 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(&quot;BecomeEnemyToPlayer&quot;)
						if !IsValid(self:GetEnemy()) then
							self:StopMoving()
							self:SetTarget(dmgAttacker)
							self:SCHEDULE_FACE(&quot;TASK_FACE_TARGET&quot;)
						end
						if selfData.CanChatMessage then
							dmgAttacker:PrintMessage(HUD_PRINTTALK, self:GetName() .. &quot; no longer likes you.&quot;)
						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 &amp;&amp; curTime &gt; selfData.NextDamageByPlayerSoundT &amp;&amp; self:Visible(dmgAttacker) then
					local dispLvl = selfData.DamageByPlayerDispositionLevel
					if (dispLvl == 0 or (dispLvl == 1 &amp;&amp; self:Disposition(dmgAttacker) == D_LI) or (dispLvl == 2 &amp;&amp; self:Disposition(dmgAttacker) != D_HT)) then
						self:PlaySoundSystem(&quot;DamageByPlayer&quot;)
					end
				end
			end
			
			self:PlaySoundSystem(&quot;Pain&quot;)
			
			-- 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 &amp;&amp; selfData.CombatDamageResponse &amp;&amp; IsValid(eneData.Target) &amp;&amp; curTime &gt; selfData.NextCombatDamageResponseT &amp;&amp; !selfData.IsFollowing &amp;&amp; !selfData.AttackType &amp;&amp; !self:IsBusy() &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; eneData.Visible &amp;&amp; self:GetWeaponState() != VJ.WEP_STATE_RELOADING &amp;&amp; eneData.Distance &lt; 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&#x27;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 &amp;&amp; !self:IsMoving() &amp;&amp; (!IsValid(wep) or (IsValid(wep) &amp;&amp; !wep.IsMeleeWeapon)) then -- Run away if not moving AND has a non-melee weapon
					self:SCHEDULE_COVER_ENEMY(&quot;TASK_RUN_PATH&quot;, 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 &amp;&amp; !IsValid(self:GetEnemy()) then
				local canMove = true
				
				-- How allies respond when it&#x27;s damaged
				if selfData.DamageAllyResponse &amp;&amp; curTime &gt; selfData.NextDamageAllyResponseT &amp;&amp; !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(&quot;Diamond&quot;, responseDist, allies, 4)
						end
						for _, ally in ipairs(allies) do
							ally:DoReadyAlert()
						end
						if !isFireEnt &amp;&amp; !self:IsBusy(&quot;Activities&quot;) 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 &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
					-- Attempt to find who damaged me | RESULT: May become alerted if attacker is visible OR it may hide if it didn&#x27;t find the attacker
					if dmgAttacker &amp;&amp; (dmgResponse == true or dmgResponse == &quot;OnlySearch&quot;) then
						local sightDist = self:GetMaxLookDistance()
						sightDist = math_min(math_max(sightDist / 2, sightDist &lt;= 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()) &lt;= sightDist &amp;&amp; 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 &amp;&amp; (dmgResponse == true or dmgResponse == &quot;OnlyMove&quot;) &amp;&amp; !selfData.IsFollowing &amp;&amp; selfData.MovementType != VJ_MOVETYPE_STATIONARY &amp;&amp; dmginfo:GetDamageCustom() != VJ.DMG_BLEED then
						self:SCHEDULE_COVER_ORIGIN(&quot;TASK_RUN_PATH&quot;, function(x) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
						selfData.TakingCoverT = curTime + 5
					end
				end
			-- Passive NPCs
			elseif isPassive &amp;&amp; curTime &gt; selfData.TakingCoverT then
				if selfData.DamageResponse &amp;&amp; !self:IsBusy() then
					self:SCHEDULE_COVER_ORIGIN(&quot;TASK_RUN_PATH&quot;)
				end
			end
		end
		
		-- Make passive NPCs move away | RESULT: May move away AND may cause other passive NPCs to move as well
		if isPassive &amp;&amp; curTime &gt; 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(&quot;TASK_RUN_PATH&quot;)
						ally:PlaySoundSystem(&quot;Alert&quot;)
					end
				end
			end
			selfData.TakingCoverT = curTime + math.Rand(6, 7)
		end
	end
	
	-- If eating, stop!
	if selfData.CanEat &amp;&amp; selfData.VJ_ST_Eating then
		selfData.EatingData.NextCheck = curTime + 15
		self:ResetEatingBehavior(&quot;Injured&quot;)
	end
	
	if self:Health() &lt;= 0 &amp;&amp; !selfData.Dead then
		self:RemoveEFlags(EFL_NO_DISSOLVE)
		if (dmginfo:IsDamageType(DMG_DISSOLVE)) or (dmgInflictor &amp;&amp; dmgInflictor:GetClass() == &quot;prop_combine_ball&quot;) 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(&quot;m_lifeState&quot;, 1) -- LIFE_DYING
	self:OnDeath(dmginfo, hitgroup, &quot;Init&quot;)
	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 &amp;&amp; dmgAttacker:IsPlayer() &amp;&amp; !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(&quot;AllyDeath&quot;)
				
				if responseType &amp;&amp; myPos:Distance(ally:GetPos()) &lt; responseDist then
					local moved = false
					-- Bring ally
					if responseType == true &amp;&amp; movedAllyNum &lt; self.DeathAllyResponse_MoveLimit then
						moved = self:Allies_Bring(&quot;Random&quot;, responseDist, {ally}, 0, true)
						if moved then
							movedAllyNum = movedAllyNum + 1
						end
					end
					-- Alert ally
					if (responseType == true or responseType == &quot;OnlyAlert&quot;) &amp;&amp; !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 &amp;&amp; ally.BecomeEnemyToPlayer &amp;&amp; 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] &gt; ally.BecomeEnemyToPlayer then
						if ally:Disposition(dmgAttacker) != D_HT then
							ally:OnBecomeEnemyToPlayer(dmginfo, hitgroup)
							if ally.IsFollowing &amp;&amp; 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() .. &quot; no longer likes you.&quot;)
							end
							ally:PlaySoundSystem(&quot;BecomeEnemyToPlayer&quot;)
						end
						ally.Alerted = true
					end
				end
			end
		end
	end
	
	-- Blood decal on the ground
	if self.Bleeds &amp;&amp; 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() == &quot;npc_barnacle&quot; then self.HasDeathCorpse = false end -- Don&#x27;t make a corpse if it&#x27;s killed by a barnacle!
		if vj_npc_ply_frag:GetInt() == 1 &amp;&amp; dmgAttacker:IsPlayer() then dmgAttacker:AddFrags(1) end
		if IsValid(dmgInflictor) then
			gamemode.Call(&quot;OnNPCKilled&quot;, self, dmgAttacker, dmgInflictor, dmginfo)
		end
	end
	self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
	self:GibOnDeath(dmginfo, hitgroup)
	self:PlaySoundSystem(&quot;Death&quot;)
	//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(&quot;OnDeath&quot;, dmgAttacker)
		dmgAttacker:Fire(&quot;KilledNPC&quot;, &quot;&quot;, 0, self, self) -- Allows player companions (npc_citizen) to respond to kill
	else
		self:TriggerOutput(&quot;OnDeath&quot;, self)
	end
	
	-- Handle death animation, death delay, and the final death phase
	local deathTime = self.DeathDelayTime
	if IsValid(dmgInflictor) &amp;&amp; dmgInflictor:GetClass() == &quot;prop_combine_ball&quot; then self.HasDeathAnimation = false end
	if self.HasDeathAnimation &amp;&amp; VJ_CVAR_AI_ENABLED &amp;&amp; !dmginfo:IsDamageType(DMG_REMOVENORAGDOLL) &amp;&amp; !dmginfo:IsDamageType(DMG_DISSOLVE) &amp;&amp; self:GetNavType() != NAV_CLIMB &amp;&amp; math.random(1, self.DeathAnimationChance) == 1 then
		self:RemoveAllGestures()
		self:OnDeath(dmginfo, hitgroup, &quot;DeathAnim&quot;)
		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(&quot;m_lifeState&quot;, 2) -- LIFE_DEAD
	end
	if deathTime &gt; 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 &amp;&amp; GetConVar(&quot;vj_npc_debug_damage&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;FinishDeath&quot;, &quot;Attacker = &quot;, self.SavedDmgInfo.attacker, &quot; | Inflictor = &quot;, self.SavedDmgInfo.inflictor) end
	self:SetSaveValue(&quot;m_lifeState&quot;, 2) -- LIFE_DEAD
	//self:SetNPCState(NPC_STATE_DEAD)
	self:OnDeath(dmginfo, hitgroup, &quot;Finish&quot;)
	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 &amp;&amp; self.HasDeathRagdoll != false then
		local corpseMdl = self:GetModel()
		local corpseMdlCustom = PICK(self.DeathCorpseModel)
		if corpseMdlCustom then corpseMdl = corpseMdlCustom end
		local corpseClass = &quot;prop_physics&quot;
		if self.DeathCorpseEntityClass then
			corpseClass = self.DeathCorpseEntityClass
		else
			if util.IsValidRagdoll(corpseMdl) then
				corpseClass = &quot;prop_ragdoll&quot;
			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 &amp;&amp; self.DeathCorpseSubMaterials != nil then -- Take care of sub materials
			for _, x in ipairs(self.DeathCorpseSubMaterials) do
				if self:GetSubMaterial(x) != &quot;&quot; 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) != &quot;&quot; then
					corpse:SetSubMaterial(x, self:GetSubMaterial(x))
				end
			end*/
		end
		//corpse:SetName(&quot;corpse&quot; .. self:EntIndex())
		//corpse:SetModelScale(self:GetModelScale())
		corpse.FadeCorpseType = (corpse:GetClass() == &quot;prop_ragdoll&quot; and &quot;FadeAndRemove&quot;) or &quot;kill&quot;
		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 &amp;&amp; self.HasBloodPool &amp;&amp; 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&#x27;t darken the corpse if we are immune to fire!
				corpse:SetColor(colorGrey)
				//corpse:SetMaterial(&quot;models/props_foliage/tree_deciduous_01a_trunk&quot;)
			end
		end
		
		-- Dissolve
		if (bit.band(self.SavedDmgInfo.type, DMG_DISSOLVE) != 0) or (IsValid(self.SavedDmgInfo.inflictor) &amp;&amp; self.SavedDmgInfo.inflictor:GetClass() == &quot;prop_combine_ball&quot;) then
			corpse:Dissolve(0, 1)
		end
		
		-- Bone and Angle
		-- If it&#x27;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&#x27;s 1, then it&#x27;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 &amp; stink system
		if corpse:Health() &lt;= 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, &quot;&quot;, self.DeathCorpseFade) end
		if vj_npc_corpse_fade:GetInt() == 1 then corpse:Fire(corpse.FadeCorpseType, &quot;&quot;, 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(&quot;vj_&quot; .. corpse:EntIndex(), function(ent, childPieces)
			for _, child in ipairs(childPieces) do
				if IsValid(child) then
					if child:GetClass() == &quot;prop_ragdoll&quot; then -- Make ragdolls fade
						child:Fire(&quot;FadeAndRemove&quot;, &quot;&quot;, 0)
					else
						child:Fire(&quot;kill&quot;, &quot;&quot;, 0)
					end
				end
			end
		end, corpse.ChildEnts)
		hook.Call(&quot;CreateEntityRagdoll&quot;, 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 &amp; ang in case the weapon uses custom world model pos &amp; 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&#x27;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) &amp;&amp; self.SavedDmgInfo.inflictor:GetClass() == &quot;prop_combine_ball&quot;) 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</pre>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@garrys_mod_lua_api/1-7fl4of7tH</guid><link>https://teletype.in/@garrys_mod_lua_api/1-7fl4of7tH?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><comments>https://teletype.in/@garrys_mod_lua_api/1-7fl4of7tH?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api#comments</comments><dc:creator>garrys_mod_lua_api</dc:creator><title>VJ-Base - npc_vj_creature_base - init файл</title><pubDate>Fri, 11 Jul 2025 20:06:06 GMT</pubDate><category>Библиотека VJ Base</category><description><![CDATA[Путь к файлу init.lua. «VJ-Base/lua/entities/npc_vj_creature_base/init.lua»]]></description><content:encoded><![CDATA[
  <p id="Um1W">Путь к файлу init.lua. «VJ-Base/lua/entities/npc_vj_creature_base/init.lua»</p>
  <p id="nmTI">«VJ-Base/lua/entities/npc_vj_creature_base/init.lua»</p>
  <p id="NhFt">Код файла init.lua</p>
  <pre id="j3r0" data-lang="lua">AddCSLuaFile(&quot;shared.lua&quot;)
include(&quot;vj_base/ai/core.lua&quot;)
include(&quot;vj_base/ai/schedules.lua&quot;)
include(&quot;vj_base/ai/base_aa.lua&quot;)
include(&quot;shared.lua&quot;)
/*--------------------------------------------------
	*** 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 &amp; Misc ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.Model = false -- Model(s) to spawn with | Picks a random one if it&#x27;s a table
ENT.CanChatMessage = true -- Is it allowed to post in a player&#x27;s chat? | Example: &quot;Blank no longer likes you.&quot;
	-- ====== 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 = &quot;ValveBiped.Bip01_Head1&quot;, -- 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&#x27;s view
	FirstP_CameraBoneAng = 0, -- Should the camera&#x27;s angle be affected by the bone&#x27;s angle? | 0 = No, 1 = Pitch, 2 = Yaw, 3 = Roll
	FirstP_CameraBoneAng_Offset = 0, -- How much should the camera&#x27;s angle be rotated by? | Useful for weird bone angles
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Movement &amp; Sight ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.SightDistance = 6500 -- Initial sight distance | To retrieve: &quot;self:GetMaxLookDistance()&quot; | To change: &quot;self:SetMaxLookDistance(distance)&quot;
ENT.SightAngle = 156 -- Initial field of view | To retrieve: &quot;self:GetFOV()&quot; | To change: &quot;self:SetFOV(degree)&quot; | 360 = See all around
ENT.TurningSpeed = 20 -- Initial turning speed | To retrieve: &quot;self:GetMaxYawSpeed()&quot; | To change: &quot;self:SetMaxYawSpeed(speed)&quot;
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&#x27;s &quot;move_x&quot; and &quot;move_y&quot; pose parameters while moving | Required for player models to move properly!
	-- ====== JUMPING ====== --
	-- Requires &quot;CAP_MOVE_JUMP&quot; capability
	-- Applied automatically by the base if &quot;ACT_JUMP&quot; is valid on the NPC&#x27;s model
	-- Example scenario:
	--      [A]       &lt;- Apex
	--     /   \
	--    /     [S]   &lt;- Start
	--  [E]           &lt;- End
ENT.JumpParams = {
	Enabled = true, -- Can it do movement jumps?
	MaxRise = 220, -- How high it can jump up ((S -&gt; A) AND (S -&gt; E))
	MaxDrop = 384, -- How low it can jump down (E -&gt; S)
	MaxDistance = 512, -- Maximum distance between Start and End
}
	-- ====== STATIONARY ====== --
ENT.CanTurnWhileStationary = true -- Can it turn while using stationary move type?
	-- ====== AERIAL &amp; AQUATIC ====== --
ENT.AA_GroundLimit = 100 -- If the NPC&#x27;s distance from itself to the ground is less than this, it will attempt to move up
ENT.AA_MinWanderDist = 150 -- Minimum distance that it should move when wandering
ENT.AA_MoveAccelerate = 5 -- It will gradually speed up to the max movement speed as it moves towards its destination | Calculation = FrameTime * x
	-- 0 = Constant max speed | 1 = Slight acceleration | 50 = Rapid acceleration
ENT.AA_MoveDecelerate = 5 -- It will slow down as it approaches its destination | Calculation = MaxSpeed / x
	-- 1 = Constant max speed | 2 = Slight deceleration | 50 = Rapid deceleration
	-- AERIAL --
ENT.Aerial_FlyingSpeed_Calm = 80 -- Speed it should fly with, when it&#x27;s wandering, moving slowly, etc. | Basically walking compared to ground NPCs
ENT.Aerial_FlyingSpeed_Alerted = 200 -- Speed it should fly with, when it&#x27;s chasing an enemy, moving away quickly, etc. | Basically running compared to ground NPCs
ENT.Aerial_AnimTbl_Calm = ACT_FLY -- Flying animations to play while idle | Equivalent to &quot;walking&quot; | Unlike other movements, sequences are allowed!
ENT.Aerial_AnimTbl_Alerted = ACT_FLY -- Flying animations to play while alert | Equivalent to &quot;Running&quot; | Unlike other movements, sequences are allowed!
	-- AQUATIC --
ENT.Aquatic_SwimmingSpeed_Calm = 80 -- The speed it should swim with, when it&#x27;s wandering, moving slowly, etc. | Basically walking compared to ground NPCs
ENT.Aquatic_SwimmingSpeed_Alerted = 200 -- The speed it should swim with, when it&#x27;s chasing an enemy, moving away quickly, etc. | Basically running compared to ground NPCs
ENT.Aquatic_AnimTbl_Calm = ACT_SWIM -- Swimming animations to play while idle | Equivalent to &quot;walking&quot; | Unlike other movements, sequences are allowed!
ENT.Aquatic_AnimTbl_Alerted = ACT_SWIM -- Swimming animations to play while alert | Equivalent to &quot;Running&quot; | Unlike other movements, sequences are allowed!
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ AI &amp; 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 &amp; objects?
ENT.EnemyTimeout = 15 -- Time until the enemy target is reset if it&#x27;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?
ENT.CanEat = false -- Can it search and eat organic stuff?
ENT.EatCooldown = 30 -- How much time until it can eat again after devouring something?
	-- ====== 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 = &quot;CLASS_PLAYER_ALLY&quot; || HECU = &quot;CLASS_UNITED_STATES&quot; || Portal = &quot;CLASS_APERTURE&quot;
		-- Combine = &quot;CLASS_COMBINE&quot; || Zombie = &quot;CLASS_ZOMBIE&quot; || Antlions = &quot;CLASS_ANTLION&quot; || Xen = &quot;CLASS_XEN&quot; || Black-Ops = &quot;CLASS_BLACKOPS&quot;
ENT.AlliedWithPlayerAllies = false -- Should it be allied with other player allies? | Both entities must have &quot;CLASS_PLAYER_ALLY&quot;
ENT.YieldToAlliedPlayers = true -- Should it give space to allied players?
ENT.BecomeEnemyToPlayer = false -- Should it become enemy towards an allied player if it&#x27;s damaged by them or it witnesses another ally killed by them?
	-- false = Don&#x27;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: &quot;CallForHelp&quot;, &quot;DamageAllyResponse&quot;, &quot;DeathAllyResponse&quot;, &quot;Passive_AlliesRunOnDamage&quot;
	-- ====== 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&#x27;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 &quot;self.HasOnPlayerSight&quot; 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 = false -- Call for help animations | false = Don&#x27;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 &quot;self.VJ_ID_Healable&quot;, 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&#x27;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 = &quot;models/healthvial.mdl&quot; -- The model that it spawns
ENT.Medic_SpawnPropOnHealAttachment = &quot;anim_attachment_LH&quot; -- The attachment it spawns on
	-- ====== Follow System ====== --
	-- Associated variables: self.FollowData, self.IsFollowing
	-- NOTE: Stationary NPCs can&#x27;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&#x27;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&#x27;s visible?
ENT.ConstantlyFaceEnemy_IfAttacking = false -- Should it face the enemy when attacking?
ENT.ConstantlyFaceEnemy_Postures = &quot;Both&quot; -- &quot;Both&quot; = Moving or standing | &quot;Moving&quot; = Only when moving | &quot;Standing&quot; = 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
	-- ====== Limit Chase Distance Behavior ====== --
ENT.LimitChaseDistance = false -- Should it limit chasing when between certain distances? | true = Always limit | &quot;OnlyRange&quot; = Only limit if it&#x27;s able to range attack
ENT.LimitChaseDistance_Min = 300 -- Min distance from the enemy to limit its chasing | &quot;UseRangeDistance&quot; = Use range attack&#x27;s min distance
ENT.LimitChaseDistance_Max = 2000 -- Max distance from the enemy to limit its chasing | &quot;UseRangeDistance&quot; = Use range attack&#x27;s max distance
	-- ====== Prop Damaging &amp; Pushing Behavior ====== --
	-- By default this requires the NPC to have a melee attack, unless coded otherwise
ENT.PropInteraction = true -- Controls how it should interact with props
	-- false = Disable both damaging and pushing | true = Damage and push | &quot;OnlyDamage&quot; = Damage but don&#x27;t push | &quot;OnlyPush&quot; = Push but don&#x27;t damage
ENT.PropInteraction_MaxScale = 1 -- Max prop size multiplier | x &lt; 1  = Smaller props | x &gt; 1  = Larger props
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ 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&#x27;s damaged
ENT.BloodDecalUseGMod = false -- Should it use the current default decals defined by Garry&#x27;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&#x27;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 &quot;VJ_ID_Boss&quot;
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&#x27;t flinch | true = Always flinch | &quot;DamageTypes&quot; = Flinch only from certain damages types
ENT.FlinchDamageTypes = {DMG_BLAST} -- Which types of damage types should it flinch from when &quot;DamageTypes&quot; is used?
ENT.FlinchChance = 14 -- 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 &quot;self.AnimTbl_Flinch&quot; 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 | &quot;OnlyMove&quot; = Will only run to a covered position | &quot;OnlySearch&quot; = Will only search for enemies
ENT.DamageAllyResponse = true -- Should allies respond when it&#x27;s damaged while it has no enemy?
ENT.AnimTbl_DamageAllyResponse = false -- Animations to play when it calls allies to respond | false = Don&#x27;t play an animation
ENT.DamageAllyResponse_Cooldown = VJ.SET(9, 12) -- How long until it can call allies again?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Death &amp; Corpse ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.DeathDelayTime = 0 -- Time until it spawns the corpse, removes itself, etc.
	-- ====== Ally Responses ====== --
	-- An ally must have &quot;self.CanReceiveOrders&quot; enabled to respond!
ENT.DeathAllyResponse = true -- How should allies response when it dies?
	-- false = No reactions | true = Allies respond by becoming alert and moving to its location | &quot;OnlyAlert&quot; = 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 &quot;self.DeathDelayTime&quot;
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&#x27;s killed?
ENT.DeathCorpseEntityClass = false -- Corpse&#x27;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&#x27;s set to COLLISION_GROUP_DEBRIS!
ENT.DeathCorpseFade = false -- Should the corpse fade after the given amount of seconds? | false = Don&#x27;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&#x27;s sub material to the corpse.
	-- ====== Dismemberment / Gib ====== --
ENT.CanGib = true -- Can it dismember? | Makes &quot;CreateGibEntity&quot; fail and overrides &quot;CanGibOnDeath&quot; to false
ENT.CanGibOnDeath = true -- Can it dismember on death?
ENT.GibOnDeathFilter = true -- Should it only gib and call &quot;self:HandleGibOnDeath&quot; when it&#x27;s killed by a specific damage types? | false = Call &quot;self:HandleGibOnDeath&quot; 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.DropDeathLoot = true -- Should it drop loot on death?
ENT.DeathLoot = {} -- 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_SLASH
ENT.HasMeleeAttackKnockBack = false -- Should knockback be applied on melee hit? | Use &quot;MeleeAttackKnockbackVelocity&quot; 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&#x27;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.6 -- 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?
	-- ====== Bleeding System ====== --
	-- Causes the enemy to continue taking damage after it&#x27;s hit based on the given parameters:
ENT.MeleeAttackBleedEnemy = false -- Should it bleed enemies it hits?
ENT.MeleeAttackBleedEnemyChance = 3 -- Chance that the enemy bleeds | 1 = always
ENT.MeleeAttackBleedEnemyDamage = 1 -- How much damage per repetition
ENT.MeleeAttackBleedEnemyTime = 1 -- How much time until the next repetition?
ENT.MeleeAttackBleedEnemyReps = 4 -- How many repetitions?
	-- ====== Player Speed Modifier ====== --
ENT.MeleeAttackPlayerSpeed = false -- Should it modify the movement speed of players that got damaged?
ENT.MeleeAttackPlayerSpeedWalk = 100
ENT.MeleeAttackPlayerSpeedRun = 100
ENT.MeleeAttackPlayerSpeedTime = 5 -- How much time until player&#x27;s speed resets back to normal
	-- ====== Digital Signal Processor (DSP) Effect ====== --
	-- DSP ID Presents: https://wiki.facepunch.com/gmod/DSP_Presets AND https://developer.valvesoftware.com/wiki/Dsp_presets
ENT.MeleeAttackDSP = 32 -- Should it apply a DSP effect to players? | false = Disable applying DSP effect | number = DSP effect ID
ENT.MeleeAttackDSPLimit = 60 -- Should it only apply if the damage surpasses the given number? | false = Always apply | number = Only apply when damage is greater than or equal to this number
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Range Attack ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.HasRangeAttack = false
ENT.RangeAttackProjectiles = &quot;obj_vj_rocket&quot; -- Entities that it can spawn when range attacking | table = Picks randomly
	-- ====== Animation ====== --
ENT.AnimTbl_RangeAttack = ACT_RANGE_ATTACK1 -- Animations to play when it range attacks | false = Don&#x27;t play an animation
ENT.RangeAttackAnimationDelay = 0 -- It will wait certain amount of time before playing the animation
ENT.RangeAttackAnimationFaceEnemy = true -- Should it face the enemy while playing the range attack animation?
ENT.RangeAttackAnimationDecreaseLengthAmount = 0 -- Decreases animation time | Use it to fix animations that have extra frames at the end
	-- ====== Distance ====== --
ENT.RangeAttackMinDistance = 800 -- Min range attack distance
ENT.RangeAttackMaxDistance = 2000 -- Max range attack distance
ENT.RangeAttackAngleRadius = 100 -- What is the attack angle radius? | 100 = In front of it | 180 = All around it
	-- ====== Timer ====== --
ENT.TimeUntilRangeAttackProjectileRelease = 1.5 -- How much time until the projectile is thrown? | false = Make the attack event-based
ENT.NextRangeAttackTime = 3 -- How much time until it can use a range attack? | number = Specific time | VJ.SET = Randomized between the 2 numbers
ENT.NextAnyAttackTime_Range = 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.RangeAttackReps = 1 -- How many times does it throw a projectile?
ENT.RangeAttackExtraTimers = false -- Extra range attack timers | EX: {1, 1.4}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Leap Attack ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.HasLeapAttack = false
ENT.LeapAttackDamage = 15
ENT.LeapAttackDamageType = DMG_SLASH
ENT.DisableDefaultLeapAttackDamageCode = false -- Disables the default leap attack damage code
	-- ====== Animation ====== --
ENT.AnimTbl_LeapAttack = ACT_SPECIAL_ATTACK1 -- Animations to play when it leap attacks | false = Don&#x27;t play an animation
ENT.LeapAttackAnimationFaceEnemy = 2 -- 2 = Face the enemy UNTIL it jumps! | true = Face the enemy the entire time! | false = Don&#x27;t face the enemy AT ALL!
ENT.LeapAttackAnimationDecreaseLengthAmount = 0 -- Decreases animation time | Use it to fix animations that have extra frames at the end
	-- ====== Distance ====== --
ENT.LeapAttackMinDistance = 200 -- Min distance that it can leap from
ENT.LeapAttackMaxDistance = 500 -- Max distance that it can leap from
ENT.LeapAttackDamageDistance = 100 -- How far does the damage go?
ENT.LeapAttackAngleRadius = 60 -- What is the attack angle radius? | 100 = In front of it | 180 = All around it
	-- ====== Timer ====== --
ENT.TimeUntilLeapAttackDamage = 0.2 -- How much time until it executes the damage? | false = Make the attack event-based
ENT.TimeUntilLeapAttackVelocity = 0.1 -- How much time until it jumps and applies the velocity?
ENT.NextLeapAttackTime = 3 -- How much time until it can use a leap attack? | number = Specific time | VJ.SET = Randomized between the 2 numbers
ENT.NextAnyAttackTime_Leap = 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.LeapAttackReps = 1 -- How many times does it run the leap attack code?
ENT.LeapAttackExtraTimers = false -- Extra leap attack timers | EX: {1, 1.4}
ENT.LeapAttackStopOnHit = true -- Should it stop executing the leap attack after it hits an enemy?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ Sound ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ENT.HasSounds = true -- Can it play sounds? | false = Disable ALL sounds
ENT.DamageByPlayerDispositionLevel = 1 -- When should it play &quot;DamageByPlayer&quot; 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 = 1 -- Delay between footstep sounds while it is walking | false = Disable while walking
ENT.FootstepSoundTimerRun = 0.5 -- Delay between footstep sounds while it is running | false = Disable while running
	-- ====== Idle Sound ====== --
ENT.HasIdleSounds = true -- Can it play idle sounds? | Controls &quot;self.SoundTbl_Idle&quot;, &quot;self.SoundTbl_IdleDialogue&quot;, &quot;self.SoundTbl_CombatIdle&quot;
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 &quot;self.SoundTbl_KilledEnemy&quot; 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 &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
ENT.HasYieldToPlayerSounds = true -- Can it play sounds when it yields to an allied player?
ENT.HasMedicSounds = true -- Can it play medic sounds? | Controls &quot;self.SoundTbl_MedicBeforeHeal&quot;, &quot;self.SoundTbl_MedicOnHeal&quot;, &quot;self.SoundTbl_MedicReceiveHeal&quot;
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.HasMeleeAttackSounds = true -- Can it play melee attack sounds? | Controls &quot;self.SoundTbl_BeforeMeleeAttack&quot;, &quot;self.SoundTbl_MeleeAttack&quot;, &quot;self.SoundTbl_MeleeAttackExtra&quot;
ENT.HasExtraMeleeAttackSounds = false -- Can it play extra melee attack sound effects?
ENT.HasMeleeAttackMissSounds = true -- Can it play melee attack miss sounds?
ENT.HasMeleeAttackPlayerSpeedSounds = true -- Does it have a sound when it slows down the player?
ENT.HasRangeAttackSounds = true -- Can it play range attack sounds? | Controls &quot;self.SoundTbl_BeforeRangeAttack&quot;, &quot;self.SoundTbl_RangeAttack&quot;
ENT.HasBeforeLeapAttackSounds = true -- Can it play leap attack before jump sounds?
ENT.HasLeapAttackJumpSounds = true -- Can it play leap attack jump sounds?
ENT.HasLeapAttackDamageSounds = true -- Can it play leap attack damage sounds?
ENT.HasLeapAttackDamageMissSounds = true -- Can it play leap attack miss sounds?
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&#x27;s damaged by a player?
ENT.HasDeathSounds = true -- Can it play death sounds?
	-- ====== Sound Paths ====== --
	-- There are 2 types of sounds: &quot;SPEECH&quot; and &quot;EFFECT&quot; | Most sound tables are &quot;SPEECH&quot; 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 = false -- 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 = &quot;items/smallmedkit1.wav&quot; -- 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_BeforeMeleeAttack = false
ENT.SoundTbl_MeleeAttack = false
ENT.SoundTbl_MeleeAttackExtra = &quot;Zombie.AttackHit&quot; -- EFFECT
ENT.SoundTbl_MeleeAttackMiss = false -- EFFECT
ENT.SoundTbl_MeleeAttackPlayerSpeed = &quot;vj_base/player/heartbeat_loop.wav&quot;
ENT.SoundTbl_BeforeRangeAttack = false
ENT.SoundTbl_RangeAttack = false
ENT.SoundTbl_BeforeLeapAttack = false
ENT.SoundTbl_LeapAttackJump = false
ENT.SoundTbl_LeapAttackDamage = false -- EFFECT
ENT.SoundTbl_LeapAttackDamageMiss = false -- EFFECT
ENT.SoundTbl_KilledEnemy = false
ENT.SoundTbl_AllyDeath = false
ENT.SoundTbl_Pain = false
ENT.SoundTbl_Impact = &quot;VJ.Impact.Flesh_Alien&quot; -- EFFECT
ENT.SoundTbl_DamageByPlayer = false
ENT.SoundTbl_Death = false
	-- ====== Sound Chance ====== --
	-- Higher number = less chance of playing | 1 = Always play
ENT.IdleSoundChance = 2
ENT.IdleDialogueAnswerSoundChance = 1
ENT.CombatIdleSoundChance = 1
ENT.ReceiveOrderSoundChance = 1
ENT.FollowPlayerSoundChance = 1 -- Controls &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
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.BeforeRangeAttackSoundChance = 1
ENT.RangeAttackSoundChance = 1
ENT.BeforeLeapAttackSoundChance = 1
ENT.LeapAttackJumpSoundChance = 1
ENT.LeapAttackDamageSoundChance = 1
ENT.LeapAttackDamageMissSoundChance = 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(4, 11)
ENT.NextSoundTime_Investigate = VJ.SET(5, 5)
ENT.NextSoundTime_LostEnemy = VJ.SET(5, 6)
ENT.NextSoundTime_Alert = VJ.SET(2, 3)
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 &quot;self.SoundTbl_IdleDialogue&quot;, &quot;self.SoundTbl_IdleDialogueAnswer&quot;
ENT.CombatIdleSoundLevel = 80
ENT.ReceiveOrderSoundLevel = 80
ENT.FollowPlayerSoundLevel = 75 -- Controls &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
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.MeleeAttackPlayerSpeedSoundLevel = 100
ENT.BeforeRangeAttackSoundLevel = 75
ENT.RangeAttackSoundLevel = 75
ENT.BeforeLeapAttackSoundLevel = 75
ENT.LeapAttackJumpSoundLevel = 75
ENT.LeapAttackDamageSoundLevel = 75
ENT.LeapAttackDamageMissSoundLevel = 75
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 &lt; x &gt; 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 &quot;self.SoundTbl_IdleDialogue&quot;, &quot;self.SoundTbl_IdleDialogueAnswer&quot;
ENT.CombatIdleSoundPitch = false
ENT.ReceiveOrderSoundPitch = false
ENT.FollowPlayerPitch = false -- Controls &quot;self.SoundTbl_FollowPlayer&quot;, &quot;self.SoundTbl_UnFollowPlayer&quot;
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 = false
ENT.ExtraMeleeSoundPitch = VJ.SET(80, 100)
ENT.MeleeAttackMissSoundPitch = VJ.SET(90, 100)
ENT.BeforeRangeAttackPitch = false
ENT.RangeAttackPitch = false
ENT.BeforeLeapAttackSoundPitch = false
ENT.LeapAttackJumpSoundPitch = false
ENT.LeapAttackDamageSoundPitch = false
ENT.LeapAttackDamageMissSoundPitch = false
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&#x27;t have a hook because you can simply override them | Call &quot;self.BaseClass.FuncName(self)&quot; or &quot;baseclass.Get(baseName)&quot; to run the base code as well
--
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:PreInit() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:Init()
	-- Collision bounds of the NPC | NOTE: Both Xs and Ys should be the same! | To view: &quot;cl_ent_bbox&quot;
	-- 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: &quot;cl_ent_absbox&quot;
	-- 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: &quot;calculatedDisp&quot; 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 &quot;example/sound.wav&quot; 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 &quot;self:FireBullets&quot; 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, &quot;OnCondition&quot;, cond, &quot; = &quot;, self:ConditionName(cond)) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- UNCOMMENT TO USE
-- function ENT:OnInput(key, activator, caller, data) VJ.DEBUG_Print(self, &quot;OnInput&quot;, 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, &quot;OnAnimEvent&quot;, eventName, ev, evTime, evCycle, evType, evOptions)
-- end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[---------------------------------------------------------
	Called whenever the NPC begins following or stops following an entity
		- status = Type of call:
			- &quot;Start&quot;	= NPC is now following the given entity
			- &quot;Stop&quot;	= 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:
			- &quot;CheckEnt&quot;	= Possible friendly entity found, should we speak to it? | return anything other than true to skip and not speak to this entity!
			- &quot;Speak&quot;		= Everything passed, start speaking
			- &quot;Answer&quot;		= 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 &quot;CheckEnt&quot;	= Boolean value, whether or not the entity can answer back
			- For &quot;Speak&quot;		= Duration of our sentence
	Returns
		- ONLY used for &quot;CheckEnt&quot; &amp; &quot;Answer&quot; | 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:
		-&gt; &quot;BeforeHeal&quot; : Right before it&#x27;s about to heal an entity
				USAGE EXAMPLES -&gt; Play chain of animations | Additional sound effect
				PARAMETERS
					2. statusData [nil]
				RETURNS
					-&gt; [nil]
		-&gt; &quot;OnHeal&quot; : When the timer expires and is about to give health
				USAGE EXAMPLES -&gt; Override healing code | Play an after heal animation
				PARAMETERS
					2. statusData [entity] : The entity that it&#x27;s about to heal
				RETURNS
					-&gt; [bool] : Returning false will NOT update entity&#x27;s health and will NOT clear its decals (Useful for custom code)
		-&gt; &quot;OnReset&quot; : When the behavior ends OR has to move because entity moved
				USAGE EXAMPLES -&gt; Cleanup bodygroups | Play a sound
				PARAMETERS
					2. statusData [string] : Holds one of the following states:
						--&gt; &quot;Retry&quot; : When it attempts to retry healing the entity, such as when the entity moved away so it has to chase again
						--&gt; &quot;End&quot; : When the medic behavior exits completely
				RETURNS
					-&gt; [nil]
	2. statusData [nil | entity | string] : Depends on &#x60;status&#x60; value, refer to it for more details

=-=-=| RETURNS |=-=-=
	-&gt; [nil | bool] : Depends on &#x60;status&#x60; 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: &quot;Walk&quot;, &quot;Run&quot;, &quot;Event&quot;
		- sdFile = Sound that it just played
-----------------------------------------------------------]]
-- function ENT:OnFootstepSound(moveType, sdFile) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnInvestigate(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnResetEnemy() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:OnAlert(ent) end
---------------------------------------------------------------------------------------------------------------------------------------------
-- &quot;ally&quot; = Ally that we called for help
-- &quot;isFirst&quot; = 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:
		-&gt; &quot;PreInit&quot; : Before the attack is initialized | Before anything is set, useful to prevent the attack completely
			RETURNS
				-&gt; [nil | boolean] : Return true to prevent the attack from being triggered
		-&gt; &quot;Init&quot; : When the attack initially starts | Before sound, timers, and animations are set!
			RETURNS
				-&gt; [nil]
		-&gt; &quot;PostInit&quot; : After the sound, timers, and animations are set!
			RETURNS
				-&gt; [nil]
	2. enemy [entity] : Enemy that caused the attack to trigger

=-=-=| RETURNS |=-=-=
	-&gt; [nil | boolean] : Depends on &#x60;status&#x60; 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
---------------------------------------------------------------------------------------------------------------------------------------------
-- &quot;self.MeleeAttackDamageAngleRadius&quot; 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:
		-&gt; &quot;Init&quot; : When the attack initially executed | Before entities are checked and damaged
			RETURNS
				-&gt; [nil | boolean] : Return true to skip running the default execution (Useful for custom code)
		-&gt; &quot;PreDamage&quot; : 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
				-&gt; [nil | boolean] : Return true to skip hitting this entity
		-&gt; &quot;Miss&quot; : When the attack misses and doesn&#x27;t hit anything
			RETURNS
				-&gt; [nil]
	2. ent [nil | entity] : Depends on &#x60;status&#x60; value, refer to it for more details
	3. isProp [nil | entity] : Depends on &#x60;status&#x60; value, refer to it for more details

=-=-=| RETURNS |=-=-=
	-&gt; [nil | boolean] : Depends on &#x60;status&#x60; value, refer to it for more details
--]]
function ENT:OnMeleeAttackExecute(status, ent, isProp) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when range attack is triggered

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

=-=-=| RETURNS |=-=-=
	-&gt; [nil | boolean] : Depends on &#x60;status&#x60; value, refer to it for more details
--]]
function ENT:OnRangeAttack(status, enemy) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when range attack is executed

=-=-=| PARAMETERS |=-=-=
	1. status [string] : Type of update that is occurring, holds one of the following states:
		-&gt; &quot;Init&quot; : When the attack initially executed | Before entities are checked and damaged
			RETURNS
				-&gt; [nil | boolean] : Return true to skip spawning the projectile
		-&gt; &quot;PreSpawn&quot; : Right before &quot;Spawn()&quot; is called on the projectile
			PARAMETERS
				3. projectile [entity] : The projectile entity that is about to spawn
			RETURNS
				-&gt; [nil]
		-&gt; &quot;PostSpawn&quot; : After &quot;Spawn()&quot; is called and velocity is set on the projectile
			PARAMETERS
				3. projectile [entity] : The projectile entity that just spawned
			RETURNS
				-&gt; [nil]
	2. enemy [entity] : Enemy that it&#x27;s about to fire at
	3. projectile [nil | entity] : Depends on &#x60;status&#x60; value, refer to it for more details

=-=-=| RETURNS |=-=-=
	-&gt; [nil | boolean] : Depends on &#x60;status&#x60; value, refer to it for more details
--]]
function ENT:OnRangeAttackExecute(status, enemy, projectile) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:RangeAttackProjPos(projectile)
	// return self:GetAttachment(self:LookupAttachment(&quot;muzzle&quot;)).Pos -- Attachment example
	return self:GetPos() + self:GetUp() * 20
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:RangeAttackProjVel(projectile)
	-- Use curve if the projectile has physics, otherwise use a simple line
	local phys = projectile:GetPhysicsObject()
	if IsValid(phys) &amp;&amp; phys:IsGravityEnabled() then
		return VJ.CalculateTrajectory(self, self:GetEnemy(), &quot;Curve&quot;, projectile:GetPos(), 1, 10)
	end
	return VJ.CalculateTrajectory(self, self:GetEnemy(), &quot;Line&quot;, projectile:GetPos(), 1, 1500)
end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when leap attack is triggered

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

=-=-=| RETURNS |=-=-=
	-&gt; [nil | vector | boolean] : Depends on &#x60;status&#x60; value, refer to it for more details
--]]
function ENT:OnLeapAttack(status, enemy) end
---------------------------------------------------------------------------------------------------------------------------------------------
--[[
Called when leap attack is executed

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

=-=-=| RETURNS |=-=-=
	-&gt; [nil | boolean] : Depends on &#x60;status&#x60; value, refer to it for more details
--]]
function ENT:OnLeapAttackExecute(status, ent) 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:
		-&gt; &quot;Init&quot; : First call on take damage, even before immune checks
		-&gt; &quot;PreDamage&quot; : Right before the damage is applied to the NPC
		-&gt; &quot;PostDamage&quot; : 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:
		-&gt; &quot;Init&quot; : Before the animation is played or any values are set
				USAGE EXAMPLES -&gt; Disallow flinch | Override the animation | Add a extra check
				RETURNS
					-&gt; [nil | bool] : Return true to disallow the flinch from playing
		-&gt; &quot;Execute&quot; : Right after the flinch animation starts playing and all the values are set
				RETURNS
					-&gt; [nil]

=-=-=| RETURNS |=-=-=
	-&gt; [nil | bool] : Depends on &#x60;status&#x60; 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 |=-=-=
	-&gt; [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
	-&gt; [nil | table] : Overrides default actions, first return must be &quot;true&quot; 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:
		-&gt; &quot;Init&quot; : First call when it dies before anything is changed or reset
		-&gt; &quot;DeathAnim&quot; : Right before the death animation plays
		-&gt; &quot;Finish&quot; : 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:OnCreateDeathCorpse(dmginfo, hitgroup, corpse) end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:CustomOnRemove() end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:Controller_Initialize(ply, controlEnt)
	//ply:ChatPrint(&quot;CTRL + MOUSE2: Rocket Attack&quot;) -- Example key binding message
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:SetAnimationTranslations(wepHoldType) end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------ ///// WARNING: Don&#x27;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 PICK = VJ.PICK
local VJ_STATE_NONE = VJ_STATE_NONE
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(&quot;Entity&quot;)
local funcGetPoseParameter = metaEntity.GetPoseParameter
local funcSetPoseParameter = metaEntity.SetPoseParameter
--
local metaNPC = FindMetaTable(&quot;NPC&quot;)
local funcHasCondition = metaNPC.HasCondition

ENT.PropInteraction_Found = false
ENT.PropInteraction_NextCheckT = 0
ENT.IsAbleToRangeAttack = true
ENT.IsAbleToLeapAttack = true
ENT.LeapAttackHasJumped = false
//ENT.EatingData = {} -- Set later

local vj_npc_debug = GetConVar(&quot;vj_npc_debug&quot;)
local vj_npc_processtime = GetConVar(&quot;vj_npc_processtime&quot;)
local vj_npc_poseparams = GetConVar(&quot;vj_npc_poseparams&quot;)
local vj_npc_shadows = GetConVar(&quot;vj_npc_shadows&quot;)
local vj_npc_snd = GetConVar(&quot;vj_npc_snd&quot;)
local vj_npc_fri_base = GetConVar(&quot;vj_npc_fri_base&quot;)
local vj_npc_fri_player = GetConVar(&quot;vj_npc_fri_player&quot;)
local vj_npc_fri_antlion = GetConVar(&quot;vj_npc_fri_antlion&quot;)
local vj_npc_fri_combine = GetConVar(&quot;vj_npc_fri_combine&quot;)
local vj_npc_fri_zombie = GetConVar(&quot;vj_npc_fri_zombie&quot;)
local vj_npc_allies = GetConVar(&quot;vj_npc_allies&quot;)
local vj_npc_anim_death = GetConVar(&quot;vj_npc_anim_death&quot;)
local vj_npc_corpse = GetConVar(&quot;vj_npc_corpse&quot;)
local vj_npc_loot = GetConVar(&quot;vj_npc_loot&quot;)
local vj_npc_melee_bleed = GetConVar(&quot;vj_npc_melee_bleed&quot;)
local vj_npc_melee_ply_speed = GetConVar(&quot;vj_npc_melee_ply_speed&quot;)
local vj_npc_wander = GetConVar(&quot;vj_npc_wander&quot;)
local vj_npc_chase = GetConVar(&quot;vj_npc_chase&quot;)
local vj_npc_flinch = GetConVar(&quot;vj_npc_flinch&quot;)
local vj_npc_melee = GetConVar(&quot;vj_npc_melee&quot;)
local vj_npc_range = GetConVar(&quot;vj_npc_range&quot;)
local vj_npc_leap = GetConVar(&quot;vj_npc_leap&quot;)
local vj_npc_blood = GetConVar(&quot;vj_npc_blood&quot;)
local vj_npc_god = GetConVar(&quot;vj_npc_god&quot;)
local vj_npc_ply_betray = GetConVar(&quot;vj_npc_ply_betray&quot;)
local vj_npc_callhelp = GetConVar(&quot;vj_npc_callhelp&quot;)
local vj_npc_investigate = GetConVar(&quot;vj_npc_investigate&quot;)
local vj_npc_eat = GetConVar(&quot;vj_npc_eat&quot;)
local vj_npc_ply_follow = GetConVar(&quot;vj_npc_ply_follow&quot;)
local vj_npc_ply_chat = GetConVar(&quot;vj_npc_ply_chat&quot;)
local vj_npc_medic = GetConVar(&quot;vj_npc_medic&quot;)
local vj_npc_gib_vfx = GetConVar(&quot;vj_npc_gib_vfx&quot;)
local vj_npc_gib = GetConVar(&quot;vj_npc_gib&quot;)
local vj_npc_blood_gmod = GetConVar(&quot;vj_npc_blood_gmod&quot;)
local vj_npc_sight_xray = GetConVar(&quot;vj_npc_sight_xray&quot;)
local vj_npc_snd_gib = GetConVar(&quot;vj_npc_snd_gib&quot;)
local vj_npc_snd_track = GetConVar(&quot;vj_npc_snd_track&quot;)
local vj_npc_snd_footstep = GetConVar(&quot;vj_npc_snd_footstep&quot;)
local vj_npc_snd_idle = GetConVar(&quot;vj_npc_snd_idle&quot;)
local vj_npc_snd_breath = GetConVar(&quot;vj_npc_snd_breath&quot;)
local vj_npc_snd_alert = GetConVar(&quot;vj_npc_snd_alert&quot;)
local vj_npc_snd_melee = GetConVar(&quot;vj_npc_snd_melee&quot;)
local vj_npc_snd_plyspeed = GetConVar(&quot;vj_npc_snd_plyspeed&quot;)
local vj_npc_snd_range = GetConVar(&quot;vj_npc_snd_range&quot;)
local vj_npc_snd_leap = GetConVar(&quot;vj_npc_snd_leap&quot;)
local vj_npc_snd_pain = GetConVar(&quot;vj_npc_snd_pain&quot;)
local vj_npc_snd_death = GetConVar(&quot;vj_npc_snd_death&quot;)
local vj_npc_snd_plyfollow = GetConVar(&quot;vj_npc_snd_plyfollow&quot;)
local vj_npc_snd_plybetrayal = GetConVar(&quot;vj_npc_snd_plybetrayal&quot;)
local vj_npc_snd_plydamage = GetConVar(&quot;vj_npc_snd_plydamage&quot;)
local vj_npc_snd_plysight = GetConVar(&quot;vj_npc_snd_plysight&quot;)
local vj_npc_snd_medic = GetConVar(&quot;vj_npc_snd_medic&quot;)
local vj_npc_snd_callhelp = GetConVar(&quot;vj_npc_snd_callhelp&quot;)
local vj_npc_snd_receiveorder = GetConVar(&quot;vj_npc_snd_receiveorder&quot;)
local vj_npc_creature_opendoor = GetConVar(&quot;vj_npc_creature_opendoor&quot;)
local vj_npc_melee_propint = GetConVar(&quot;vj_npc_melee_propint&quot;)
local vj_npc_corpse_collision = GetConVar(&quot;vj_npc_corpse_collision&quot;)
local vj_npc_debug_engine = GetConVar(&quot;vj_npc_debug_engine&quot;)
local vj_npc_difficulty = GetConVar(&quot;vj_npc_difficulty&quot;)
local vj_npc_sight_distance = GetConVar(&quot;vj_npc_sight_distance&quot;)
local vj_npc_health = GetConVar(&quot;vj_npc_health&quot;)
local vj_npc_melee_ply_dsp = GetConVar(&quot;vj_npc_melee_ply_dsp&quot;)
local vj_npc_ply_frag = GetConVar(&quot;vj_npc_ply_frag&quot;)
local vj_npc_blood_pool = GetConVar(&quot;vj_npc_blood_pool&quot;)
local vj_npc_corpse_undo = GetConVar(&quot;vj_npc_corpse_undo&quot;)
local vj_npc_corpse_fade = GetConVar(&quot;vj_npc_corpse_fade&quot;)
local vj_npc_corpse_fadetime = GetConVar(&quot;vj_npc_corpse_fadetime&quot;)
local ai_serverragdolls = GetConVar(&quot;ai_serverragdolls&quot;)

---------------------------------------------------------------------------------------------------------------------------------------------
local function InitConvars(self)
	if vj_npc_debug:GetInt() == 1 then self.VJ_DEBUG = true end
	if vj_npc_poseparams:GetInt() == 0 &amp;&amp; !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] = &quot;CLASS_VJ_BASE&quot; end
	if vj_npc_fri_player:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_PLAYER_ALLY&quot; end
	if vj_npc_fri_antlion:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_ANTLION&quot; end
	if vj_npc_fri_combine:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_COMBINE&quot; end
	if vj_npc_fri_zombie:GetInt() == 1 then self.VJ_NPC_Class[#self.VJ_NPC_Class + 1] = &quot;CLASS_ZOMBIE&quot; 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_melee_bleed:GetInt() == 0 then self.MeleeAttackBleedEnemy = false end
	if vj_npc_melee_ply_dsp:GetInt() == 0 then self.MeleeAttackDSP = false end
	if vj_npc_melee_ply_speed:GetInt() == 0 then self.MeleeAttackPlayerSpeed = 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_range:GetInt() == 0 then self.HasRangeAttack = false end
	if vj_npc_leap:GetInt() == 0 then self.HasLeapAttack = 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_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_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_melee:GetInt() == 0 then self.HasMeleeAttackSounds = false self.HasExtraMeleeAttackSounds = false self.HasMeleeAttackMissSounds = false end
	if vj_npc_snd_plyspeed:GetInt() == 0 then self.HasMeleeAttackPlayerSpeedSounds = false end
	if vj_npc_snd_range:GetInt() == 0 then self.HasRangeAttackSounds = false end
	if vj_npc_snd_leap:GetInt() == 0 then self.HasBeforeLeapAttackSounds = false self.HasLeapAttackJumpSounds = false self.HasLeapAttackDamageSounds = false self.HasLeapAttackDamageMissSounds = 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_callhelp:GetInt() == 0 then self.HasCallForHelpSounds = false end
	if vj_npc_snd_receiveorder:GetInt() == 0 then self.HasReceiveOrderSounds = false end
	if vj_npc_creature_opendoor:GetInt() == 0 then self.CanOpenDoors = false end
	local propAPType = vj_npc_melee_propint:GetInt()
	if propAPType != 1 then
		if propAPType == 0 then -- Disable
			self.PropInteraction = false
		elseif propAPType == 2 &amp;&amp; self.PropInteraction != &quot;OnlyPush&quot; then -- Only damage
			if self.PropInteraction == &quot;OnlyDamage&quot; then
				self.PropInteraction = false
			else
				self.PropInteraction = &quot;OnlyDamage&quot;
			end
		elseif propAPType == 3 &amp;&amp; self.PropInteraction != &quot;OnlyDamage&quot; then -- Only push
			if self.PropInteraction == &quot;OnlyPush&quot; then
				self.PropInteraction = false
			else
				self.PropInteraction = &quot;OnlyPush&quot;
			end
		end
	end
	local corpseCollision = vj_npc_corpse_collision:GetInt()
	if corpseCollision != 0 &amp;&amp; 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 &#x27;npc_conditions&#x27; need it)
	if self.VJ_DEBUG &amp;&amp; vj_npc_debug_engine:GetInt() == 1 then
		self:SetSaveValue(&quot;m_debugOverlays&quot;, 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 &amp; 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.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.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] = &quot;CLASS_PLAYER_ALLY&quot; 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.Medic_CanBeHealed == false then self.VJ_ID_Healable = 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.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.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.SlowPlayerOnMeleeAttack then self.MeleeAttackPlayerSpeed = true end
	if self.SlowPlayerOnMeleeAttack_WalkSpeed then self.MeleeAttackPlayerSpeedWalk = self.SlowPlayerOnMeleeAttack_WalkSpeed end
	if self.SlowPlayerOnMeleeAttack_RunSpeed then self.MeleeAttackPlayerSpeedRun = self.SlowPlayerOnMeleeAttack_RunSpeed end
	if self.SlowPlayerOnMeleeAttackTime then self.MeleeAttackPlayerSpeedTime = self.SlowPlayerOnMeleeAttackTime end
	if self.HasMeleeAttackSlowPlayerSound != nil then self.HasMeleeAttackPlayerSpeedSounds = self.HasMeleeAttackSlowPlayerSound end
	if self.SoundTbl_MeleeAttackSlowPlayer != nil then self.SoundTbl_MeleeAttackPlayerSpeed = self.SoundTbl_MeleeAttackSlowPlayer end
	if self.MeleeAttackSlowPlayerSoundLevel != nil then self.MeleeAttackPlayerSpeedSoundLevel = self.MeleeAttackSlowPlayerSoundLevel end
	if self.StopMeleeAttackAfterFirstHit != nil then self.MeleeAttackStopOnHit = self.StopMeleeAttackAfterFirstHit end
	if self.StopLeapAttackAfterFirstHit != nil then self.LeapAttackStopOnHit = self.StopLeapAttackAfterFirstHit end
	if self.NextLeapAttackTime_DoRand then self.NextLeapAttackTime = VJ.SET(self.NextLeapAttackTime, self.NextLeapAttackTime_DoRand) end
	if self.NextAnyAttackTime_Leap_DoRand then self.NextAnyAttackTime_Leap = VJ.SET(self.NextAnyAttackTime_Leap, self.NextAnyAttackTime_Leap_DoRand) end
	if self.NextRangeAttackTime_DoRand then self.NextRangeAttackTime = VJ.SET(self.NextRangeAttackTime, self.NextRangeAttackTime_DoRand) end
	if self.NextAnyAttackTime_Range_DoRand then self.NextAnyAttackTime_Range = VJ.SET(self.NextAnyAttackTime_Range, self.NextAnyAttackTime_Range_DoRand) end
	if self.MeleeAttackDSPSoundType != nil then self.MeleeAttackDSP = self.MeleeAttackDSPSoundType end
	if self.MeleeAttackDSPSoundUseDamage == false then self.MeleeAttackDSPLimit = false end
	if self.MeleeAttackDSPSoundUseDamageAmount then self.MeleeAttackDSPLimit = self.MeleeAttackDSPSoundUseDamageAmount end
	if self.DisableMeleeAttackAnimation == true then self.AnimTbl_MeleeAttack = false end
	if self.DisableRangeAttackAnimation == true then self.AnimTbl_RangeAttack = false end
	if self.DisableLeapAttackAnimation == true then self.AnimTbl_LeapAttack = false end
	if self.RangeAttackEntityToSpawn then self.RangeAttackProjectiles = self.RangeAttackEntityToSpawn end
	if self.RangeDistance then self.RangeAttackMaxDistance = self.RangeDistance end
	if self.RangeToMeleeDistance then self.RangeAttackMinDistance = self.RangeToMeleeDistance end
	if self.LeapDistance then self.LeapAttackMaxDistance = self.LeapDistance end
	if self.LeapToMeleeDistance then self.LeapAttackMinDistance = self.LeapToMeleeDistance end
	if self.Passive_RunOnDamage == false then self.DamageResponse = false end
	if self.HideOnUnknownDamage == false then self.DamageResponse = &quot;OnlySearch&quot; end
	if self.DisableTakeDamageFindEnemy == true then if self.HideOnUnknownDamage == false then self.DamageResponse = false else self.DamageResponse = &quot;OnlyMove&quot; 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 = &quot;DamageTypes&quot; end
	if self.BringFriendsOnDeath != nil or self.AlertFriendsOnDeath != nil then
		if self.AlertFriendsOnDeath == true &amp;&amp; (self.BringFriendsOnDeath == false or self.BringFriendsOnDeath == nil) then
			self.DeathAllyResponse = &quot;OnlyAlert&quot;
		elseif self.BringFriendsOnDeath == false &amp;&amp; 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.PropAP_MaxSize then self.PropInteraction_MaxScale = self.PropAP_MaxSize end
	if self.AttackProps == false or self.PushProps == false then
		if self.AttackProps == false &amp;&amp; self.PushProps == false then
			self.PropInteraction = false
		elseif self.AttackProps == false then
			self.PropInteraction = &quot;OnlyPush&quot;
		elseif self.PushProps == false then
			self.PropInteraction = &quot;OnlyDamage&quot;
		end
	end
	if self.NoChaseAfterCertainRange then self.LimitChaseDistance = self.NoChaseAfterCertainRange end
	if self.NoChaseAfterCertainRange_CloseDistance then self.LimitChaseDistance_Min = self.NoChaseAfterCertainRange_CloseDistance end
	if self.NoChaseAfterCertainRange_FarDistance then self.LimitChaseDistance_Max = self.NoChaseAfterCertainRange_FarDistance end
	if self.NoChaseAfterCertainRange_Type then
		if self.NoChaseAfterCertainRange_Type == &quot;Regular&quot; then
			self.LimitChaseDistance = true
		elseif self.NoChaseAfterCertainRange_Type == &quot;OnlyRange&quot; then
			self.LimitChaseDistance = &quot;OnlyRange&quot;
		end
	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.OnlyDoKillEnemyWhenClear != nil then self.KilledEnemySoundLast = self.OnlyDoKillEnemyWhenClear 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 == &quot;All&quot; 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 &amp;&amp; !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 &amp;&amp; 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 == &quot;BeforeHeal&quot; &amp;&amp; self.CustomOnMedic_BeforeHeal then
				self:CustomOnMedic_BeforeHeal()
			elseif status == &quot;OnHeal&quot; &amp;&amp; self.CustomOnMedic_OnHeal then
				return self:CustomOnMedic_OnHeal(statusData)
			elseif status == &quot;OnReset&quot; &amp;&amp; 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 == &quot;Init&quot; &amp;&amp; self.CustomOnTakeDamage_BeforeImmuneChecks then
				self:CustomOnTakeDamage_BeforeImmuneChecks(dmginfo, hitgroup)
			elseif status == &quot;PreDamage&quot; &amp;&amp; self.CustomOnTakeDamage_BeforeDamage then
				self:CustomOnTakeDamage_BeforeDamage(dmginfo, hitgroup)
			elseif status == &quot;PostDamage&quot; &amp;&amp; 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 == &quot;Init&quot; then
				if self.CustomOnFlinch_BeforeFlinch then
					return !self:CustomOnFlinch_BeforeFlinch(dmginfo, hitgroup)
				end
			elseif status == &quot;Execute&quot; 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 == &quot;Init&quot; then
				if self.CustomOnInitialKilled then
					self:CustomOnInitialKilled(dmginfo, hitgroup)
				end
				if self.CustomOnPriorToKilled then
					self:CustomOnPriorToKilled(dmginfo, hitgroup)
				end
			elseif status == &quot;DeathAnim&quot; &amp;&amp; self.CustomDeathAnimationCode then
				self:CustomDeathAnimationCode(dmginfo, hitgroup)
			elseif status == &quot;Finish&quot; 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 &amp;&amp; !self.OnFootstepSound then
		-- Only do this if &quot;self.OnFootstepSound&quot; isn&#x27;t already being used
		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.MeleeAttackKnockBack_Forward1 or self.MeleeAttackKnockBack_Forward2 or self.MeleeAttackKnockBack_Up1 or self.MeleeAttackKnockBack_Up2 then
		self.MeleeAttackKnockbackVelocity = function()
			return self:GetForward()*math.random(self.MeleeAttackKnockBack_Forward1 or 100, self.MeleeAttackKnockBack_Forward2 or 100) + self:GetUp()*math.random(self.MeleeAttackKnockBack_Up1 or 10, self.MeleeAttackKnockBack_Up2 or 10) + self:GetRight()*math.random(self.MeleeAttackKnockBack_Right1 or 0, self.MeleeAttackKnockBack_Right2 or 0)
		end
	end
	if self.DeathCorpseSkin &amp;&amp; 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.RangeUseAttachmentForPos then
		self.RangeAttackProjPos = function(_, projectile)
			return self:GetAttachment(self:LookupAttachment(self.RangeUseAttachmentForPosID)).Pos
		end
	elseif self.RangeAttackPos_Up or self.RangeAttackPos_Forward or self.RangeAttackPos_Right then
		self.RangeAttackProjPos = function(_, projectile)
			return self:GetPos() + self:GetUp()*(self.RangeAttackPos_Up or 20) + self:GetForward()*(self.RangeAttackPos_Forward or 0) + self:GetRight()*(self.RangeAttackPos_Right or 0)
		end
	end
	if self.RangeAttackCode_GetShootPos then
		self.RangeAttackProjVel = function(_, projectile)
			return self.RangeAttackCode_GetShootPos(self, projectile)
		end
	end
	if self.LeapAttackVelocityForward or self.LeapAttackVelocityUp or self.CustomAttackCheck_LeapAttack or self.CustomOnLeapAttack_BeforeStartTimer or self.CustomOnLeapAttack_AfterStartTimer then
		self.OnLeapAttack = function(_, status, enemy)
			if status == &quot;PreInit&quot; &amp;&amp; self.CustomAttackCheck_LeapAttack then
				return !self:CustomAttackCheck_LeapAttack(enemy)
			elseif status == &quot;Init&quot; &amp;&amp; self.CustomOnLeapAttack_BeforeStartTimer then
				self:CustomOnLeapAttack_BeforeStartTimer(self.AttackSeed)
			elseif status == &quot;PostInit&quot; &amp;&amp; self.CustomOnLeapAttack_AfterStartTimer then
				self:CustomOnLeapAttack_AfterStartTimer(self.AttackSeed)
			elseif status == &quot;Jump&quot; &amp;&amp; (self.LeapAttackVelocityForward or self.LeapAttackVelocityUp) then
				local ene = self:GetEnemy()
				return ((ene:GetPos() + ene:OBBCenter()) - (self:GetPos() + self:OBBCenter())):GetNormal()*400 + self:GetForward()*(self.LeapAttackVelocityForward or 2000) + self:GetUp()*(self.LeapAttackVelocityUp or 200)
			end
		end
	end
	if self.CustomOnLeapAttack_BeforeChecks or self.CustomOnLeapAttack_AfterChecks or self.CustomOnLeapAttack_Miss then
		self.OnLeapAttackExecute = function(_, status, ent)
			if status == &quot;Init&quot; &amp;&amp; self.CustomOnLeapAttack_BeforeChecks then
				self:CustomOnLeapAttack_BeforeChecks()
			elseif status == &quot;PreDamage&quot; &amp;&amp; self.CustomOnLeapAttack_AfterChecks then
				self:CustomOnLeapAttack_AfterChecks(ent)
			elseif status == &quot;Miss&quot; &amp;&amp; self.CustomOnLeapAttack_Miss then
				self:CustomOnLeapAttack_Miss()
			end
		end
	end
	if self.CustomAttack or self.MultipleMeleeAttacks or self.MultipleRangeAttacks or self.MultipleLeapAttacks then
		self.OnThinkAttack = function(_, isAttacking, enemy)
			if self.CustomAttack then self:CustomAttack(enemy, self.EnemyData.Visible) end
			if isAttacking then return end
			if self.MultipleMeleeAttacks then self:MultipleMeleeAttacks() end
			if self.MultipleRangeAttacks then self:MultipleRangeAttacks() end
			if self.MultipleLeapAttacks then self:MultipleLeapAttacks() end
		end
	end
	if self.CustomAttackCheck_RangeAttack or self.CustomOnRangeAttack_BeforeStartTimer or self.CustomOnRangeAttack_AfterStartTimer then
		self.OnRangeAttack = function(_, status, enemy)
			if status == &quot;PreInit&quot; &amp;&amp; self.CustomAttackCheck_RangeAttack then
				return !self:CustomAttackCheck_RangeAttack(enemy)
			elseif status == &quot;Init&quot; &amp;&amp; self.CustomOnRangeAttack_BeforeStartTimer then
				self:CustomOnRangeAttack_BeforeStartTimer(self.AttackSeed)
			elseif status == &quot;PostInit&quot; &amp;&amp; self.CustomOnRangeAttack_AfterStartTimer then
				self:CustomOnRangeAttack_AfterStartTimer(self.AttackSeed)
			end
		end
	end
	if self.DisableDefaultRangeAttackCode or self.CustomRangeAttackCode or self.CustomRangeAttackCode_BeforeProjectileSpawn or self.CustomRangeAttackCode_AfterProjectileSpawn then
		self.OnRangeAttackExecute = function(_, status, enemy, projectile)
			if status == &quot;Init&quot; &amp;&amp; (self.CustomRangeAttackCode or self.DisableDefaultRangeAttackCode) then
				if self.CustomRangeAttackCode then
					self:CustomRangeAttackCode()
				end
				if self.DisableDefaultRangeAttackCode then
					return true
				end
			elseif status == &quot;PreSpawn&quot; &amp;&amp; self.CustomRangeAttackCode_BeforeProjectileSpawn then
				self:CustomRangeAttackCode_BeforeProjectileSpawn(projectile)
			elseif status == &quot;PostSpawn&quot; &amp;&amp; self.CustomRangeAttackCode_AfterProjectileSpawn then
				self:CustomRangeAttackCode_AfterProjectileSpawn(projectile)
			end
		end
	end
	if self.CustomAttackCheck_MeleeAttack or self.CustomOnMeleeAttack_BeforeStartTimer or self.CustomOnMeleeAttack_AfterStartTimer then
		self.OnMeleeAttack = function(_, status, enemy)
			if status == &quot;PreInit&quot; &amp;&amp; self.CustomAttackCheck_MeleeAttack then
				return !self:CustomAttackCheck_MeleeAttack(enemy)
			elseif status == &quot;Init&quot; &amp;&amp; self.CustomOnMeleeAttack_BeforeStartTimer then
				self:CustomOnMeleeAttack_BeforeStartTimer(self.AttackSeed)
			elseif status == &quot;PostInit&quot; &amp;&amp; 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 == &quot;Init&quot; &amp;&amp; (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 == &quot;PreDamage&quot; &amp;&amp; self.CustomOnMeleeAttack_AfterChecks then
				return self:CustomOnMeleeAttack_AfterChecks(ent, isProp)
			elseif status == &quot;Miss&quot; &amp;&amp; (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)
local capBitsDoors = bit.bor(CAP_OPEN_DOORS, CAP_AUTO_DOORS, CAP_USE)
--
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(&quot;m_HackedGunPos&quot;, defShootVec) -- Overrides the location of self:GetShootPos()
	
	-- Set a name if it doesn&#x27;t have one
	if self:GetName() == &quot;&quot; then
		local findListing = list.Get(&quot;NPC&quot;)[self:GetClass()]
		if findListing then
			self:SetName((self.PrintName == &quot;&quot; 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.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 &gt; 0 then self.SightDistance = sightConvar end
	
	-- Capabilities &amp; 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 &quot;ai_baseactor&quot; to work properly!
	if self:LookupAttachment(&quot;eyes&quot;) &gt; 0 &amp;&amp; self:LookupAttachment(&quot;forward&quot;) &gt; 0 then
		self:CapabilitiesAdd(CAP_ANIMATEDFACE)
	end
	
	-- Health
	local hpConvar = vj_npc_health:GetInt()
	local hp = hpConvar &gt; 0 &amp;&amp; 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 &quot;Init&quot;
	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&#x27;t given a value THEN if self.IdleAlwaysWander isn&#x27;t true, wait at least 1 sec before wandering
	duplicator.RegisterEntityClass(self:GetClass(), VJ.CreateDupe_NPC, &quot;Model&quot;, &quot;Class&quot;, &quot;Equipment&quot;, &quot;SpawnFlags&quot;, &quot;Data&quot;)
	
	-- Delayed init
	timer.Simple(0.1, function()
		if IsValid(self) then
			self:SetMaxLookDistance(self.SightDistance)
			self:SetFOV(self.SightAngle)
			if self:GetNPCState() &lt;= NPC_STATE_NONE then self:SetNPCState(NPC_STATE_IDLE) end
			if IsValid(self:GetCreator()) &amp;&amp; self:GetCreator():GetInfoNum(&quot;vj_npc_spawn_guard&quot;, 0) == 1 then self.IsGuard = true end
			self:StartSoundTrack()
			
			-- Setup common default pose parameters
			if self:LookupPoseParameter(&quot;aim_pitch&quot;) != -1 then
				self.PoseParameterLooking_Names.pitch[#self.PoseParameterLooking_Names.pitch + 1] = &quot;aim_pitch&quot;
			end
			if self:LookupPoseParameter(&quot;head_pitch&quot;) != -1 then
				self.PoseParameterLooking_Names.pitch[#self.PoseParameterLooking_Names.pitch + 1] = &quot;head_pitch&quot;
			end
			if self:LookupPoseParameter(&quot;aim_yaw&quot;) != -1 then
				self.PoseParameterLooking_Names.yaw[#self.PoseParameterLooking_Names.yaw + 1] = &quot;aim_yaw&quot;
			end
			if self:LookupPoseParameter(&quot;head_yaw&quot;) != -1 then
				self.PoseParameterLooking_Names.yaw[#self.PoseParameterLooking_Names.yaw + 1] = &quot;head_yaw&quot;
			end
			if self:LookupPoseParameter(&quot;aim_roll&quot;) != -1 then
				self.PoseParameterLooking_Names.roll[#self.PoseParameterLooking_Names.roll + 1] = &quot;aim_roll&quot;
			end
			if self:LookupPoseParameter(&quot;head_roll&quot;) != -1 then
				self.PoseParameterLooking_Names.roll[#self.PoseParameterLooking_Names.roll + 1] = &quot;head_roll&quot;
			end
			
			self:UpdateAnimationTranslations()
			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 &quot;NextThink&quot; to CurTime will cause performance drops, so we set the idle maintain in a separate hook that runs every tick
			local thinkHook = hook.GetTable()[&quot;Think&quot;]
			if (thinkHook &amp;&amp; !thinkHook[self]) or (!thinkHook) then
				local idleFunc = self.MaintainIdleAnimation
				if #self:GetBoneFollowers() &gt; 0 then
					hook.Add(&quot;Think&quot;, self, function()
						if VJ_CVAR_AI_ENABLED then
							idleFunc(self)
						end
						self:UpdateBoneFollowers()
					end)
				else
					hook.Add(&quot;Think&quot;, self, function()
						if VJ_CVAR_AI_ENABLED then
							idleFunc(self)
						end
					end)
				end
			else
				VJ.DEBUG_Print(self, false, &quot;warn&quot;, &quot;has an existing embedded \&quot;Think\&quot; hook already, which is disallowing the default base hook from assigning. Make sure to handle \&quot;MaintainIdleAnimation\&quot; in the overridden hook!&quot;)
			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) or self.UsePoseParameterMovement then self:CapabilitiesAdd(CAP_MOVE_JUMP) end
			if VJ.AnimExists(self, ACT_CLIMB_UP) then self:CapabilitiesAdd(CAP_MOVE_CLIMB) 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(&quot;SCHEDULE_ALERT_CHASE_LOS&quot;)
	schedule_alert_chaseLOS:EngTask(&quot;TASK_GET_PATH_TO_ENEMY_LOS&quot;, 0)
	//schedule_alert_chaseLOS:EngTask(&quot;TASK_RUN_PATH&quot;, 0)
	schedule_alert_chaseLOS:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
	//schedule_alert_chaseLOS:EngTask(&quot;TASK_FACE_ENEMY&quot;, 0)
	//schedule_alert_chaseLOS.ResetOnFail = true
	schedule_alert_chaseLOS.CanShootWhenMoving = true
	schedule_alert_chaseLOS.CanBeInterrupted = true
--
local schedule_alert_chase = vj_ai_schedule.New(&quot;SCHEDULE_ALERT_CHASE&quot;)
	schedule_alert_chase:EngTask(&quot;TASK_GET_PATH_TO_ENEMY&quot;, 0)
	schedule_alert_chase:EngTask(&quot;TASK_RUN_PATH&quot;, 0)
	schedule_alert_chase:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
	//schedule_alert_chase:EngTask(&quot;TASK_FACE_ENEMY&quot;, 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 == &quot;SCHEDULE_ALERT_CHASE&quot; then return end // &amp;&amp; (self:GetEnemyLastKnownPos():Distance(self:GetEnemy():GetPos()) &lt;= 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
		schedule_alert_chase.RunCode_OnFail = function() if self.SCHEDULE_IDLE_STAND then self:SCHEDULE_IDLE_STAND() end end
		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 &gt; 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 &gt; curTime or (selfData.AttackAnimTime &gt; curTime &amp;&amp; moveType != VJ_MOVETYPE_AERIAL &amp;&amp; moveType != VJ_MOVETYPE_AQUATIC) then return end
	
	-- Not melee attacking yet but it is in range, so don&#x27;t chase the enemy!
	if selfData.HasMeleeAttack &amp;&amp; eneData.DistanceNearest &lt; selfData.MeleeAttackDistance &amp;&amp; eneData.Visible &amp;&amp; (self:GetHeadDirection():Dot((ene:GetPos() - self:GetPos()):GetNormalized()) &gt; 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&#x27;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(&quot;TASK_RUN_PATH&quot;)
		selfData.NextChaseTime = curTime + 3
		return
	end
	
	if !alwaysChase &amp;&amp; (selfData.DisableChasingEnemy or selfData.IsGuard) then self:SCHEDULE_IDLE_STAND() return end
	
	-- If the enemy is not reachable then wander around
	if self:IsUnreachable(ene) then
		if selfData.HasRangeAttack then -- Ranged NPCs
			self:SCHEDULE_ALERT_CHASE(true)
		elseif math.random(1, 30) == 1 &amp;&amp; !self:IsMoving() then
			selfData.NextWanderTime = 0
			self:MaintainIdleBehavior(1)
			self:RememberUnreachable(ene, 4)
		else
			self:SCHEDULE_IDLE_STAND()
		end
	else -- Is reachable, so chase the enemy!
		self:SCHEDULE_ALERT_CHASE()
	end
	
	-- Set the next chase time
	if selfData.NextChaseTime &gt; curTime then return end -- Don&#x27;t set it if it&#x27;s already set!
	selfData.NextChaseTime = curTime + (((eneData.Distance &gt; 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 &#x60;return self.BaseClass.TranslateActivity(self, act)&#x60; at the end of the function
		2. If you are replacing ACT_IDLE from a randomized table, then you must call &#x60;self:ResolveAnimation&#x60;
			- 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, &quot;TranslateActivity&quot;, act)
	-- Handle translations table
	local translation = self.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 -- &quot;or act&quot; = To make sure it doesn&#x27;t return nil when the table is empty!
		end
		return translation
	end
	return act
end
---------------------------------------------------------------------------------------------------------------------------------------------
local attackTimers = {
	[VJ.ATTACK_TYPE_MELEE] = function(self, skipStopAttacks)
		if !skipStopAttacks then
			timer.Create(&quot;attack_melee_reset&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextAnyAttackTime_Melee, self.TimeUntilMeleeAttackDamage, self.AttackAnimDuration), 1, function()
				self:StopAttacks()
				self:MaintainAlertBehavior()
			end)
		end
		timer.Create(&quot;attack_melee_reset_able&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextMeleeAttackTime), 1, function()
			self.IsAbleToMeleeAttack = true
		end)
	end,
	[VJ.ATTACK_TYPE_RANGE] = function(self, skipStopAttacks)
		if !skipStopAttacks then
			timer.Create(&quot;attack_range_reset&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextAnyAttackTime_Range, self.TimeUntilRangeAttackProjectileRelease, self.AttackAnimDuration), 1, function()
				self:StopAttacks()
				self:MaintainAlertBehavior()
			end)
		end
		timer.Create(&quot;attack_range_reset_able&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextRangeAttackTime), 1, function()
			self.IsAbleToRangeAttack = true
		end)
	end,
	[VJ.ATTACK_TYPE_LEAP] = function(self, skipStopAttacks)
		if !skipStopAttacks then
			timer.Create(&quot;attack_leap_reset&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextAnyAttackTime_Leap, self.TimeUntilLeapAttackDamage, self.AttackAnimDuration), 1, function()
				self:StopAttacks()
				self:MaintainAlertBehavior()
			end)
		end
		timer.Create(&quot;attack_leap_reset_able&quot; .. self:EntIndex(), self:GetAttackTimer(self.NextLeapAttackTime), 1, function()
			self.IsAbleToLeapAttack = true
		end)
	end
}
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:Think()
	/*
	local newEyeOffset = self:WorldToLocal(self:GetAttachment(self:LookupAttachment(&quot;mouth&quot;)).Pos)
	self:SetViewOffset(newEyeOffset)
	self:SetSaveValue(&quot;m_vDefaultEyeOffset&quot;, newEyeOffset)
	*/
	
	//if self.NextActualThink &lt;= 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 &quot;sv_pvsskipanimation&quot; handles it | Fix attachments, bones, positions, angles etc. being broken in NPCs! This condition is used as a backup in case &quot;sv_pvsskipanimation&quot; isn&#x27;t disabled!
	//if self.MovementType == VJ_MOVETYPE_GROUND &amp;&amp; self:GetVelocity():Length() &lt;= 0 &amp;&amp; !self:IsEFlagSet(EFL_IS_BEING_LIFTED_BY_BARNACLE) /*&amp;&amp; curSchedule.HasMovement*/ 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 &gt; selfData.NextProcessT
	if doHeavyProcesses then
		selfData.NextProcessT = curTime + selfData.NextProcessTime
	end
	
	-- Breath sound system
	if !selfData.Dead &amp;&amp; selfData.HasBreathSound &amp;&amp; selfData.HasSounds &amp;&amp; curTime &gt; selfData.NextBreathSoundT then
		local pickedSD = PICK(selfData.SoundTbl_Breath)
		local dur = 10 -- Make the default value large so we don&#x27;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
	
	self:OnThink()
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	local moveType = selfData.MovementType
	local moveTypeAA = moveType == VJ_MOVETYPE_AERIAL or moveType == VJ_MOVETYPE_AQUATIC
	if VJ_CVAR_AI_ENABLED &amp;&amp; self:GetState() != VJ_STATE_FREEZE &amp;&amp; !self:IsEFlagSet(EFL_IS_BEING_LIFTED_BY_BARNACLE) then
		if selfData.VJ_DEBUG then
			if GetConVar(&quot;vj_npc_debug_enemy&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, false, &quot;Enemy -&gt; &quot; .. tostring(self:GetEnemy() or &quot;NULL&quot;) .. &quot; | Alerted? &quot; .. tostring(selfData.Alerted))  end
			if GetConVar(&quot;vj_npc_debug_takingcover&quot;):GetInt() == 1 then if curTime &gt; selfData.TakingCoverT then VJ.DEBUG_Print(self, false, &quot;NOT taking cover&quot;) else VJ.DEBUG_Print(self, false, &quot;Taking cover (&quot; .. selfData.TakingCoverT - curTime .. &quot;)&quot;) end end
			if GetConVar(&quot;vj_npc_debug_lastseenenemytime&quot;):GetInt() == 1 then PrintMessage(HUD_PRINTTALK, (curTime - selfData.EnemyData.VisibleTime) .. &quot; (&quot; .. self:GetName() .. &quot;)&quot;) end
		end
		
		//self:SetPlaybackRate(self.AnimationPlaybackRate)
		self:OnThinkActive()
		
		-- For AA move types
		if moveTypeAA then
			local myVelLen = self:GetVelocity():Length()
			if myVelLen &gt; 0 then
				if selfData.AA_CurrentMovePos then
					local dist = selfData.AA_CurrentMovePos:Distance(self:GetPos())
					-- Make sure we are making progress so we don&#x27;t get stuck in a infinite movement!
					if selfData.AA_CurrentMoveDist == -1 or selfData.AA_CurrentMoveDist &gt;= dist then
						selfData.AA_CurrentMoveDist = dist
						local moveSpeed = selfData.AA_CurrentMoveMaxSpeed
						-- Only decelerate if the distance is smaller than the max speed!
						if selfData.AA_MoveDecelerate &gt; 1 &amp;&amp; dist &lt; moveSpeed then
							moveSpeed = math_min(math_max(dist, moveSpeed / selfData.AA_MoveDecelerate), moveSpeed)
						elseif selfData.AA_MoveAccelerate &gt; 0 then
							moveSpeed = Lerp(FrameTime() * selfData.AA_MoveAccelerate, myVelLen, moveSpeed)
						end
						local velPos = selfData.AA_CurrentMovePosDir:GetNormal() * moveSpeed
						local velTimeCur = curTime + (dist / velPos:Length())
						if velTimeCur == velTimeCur then -- Check for NaN
							selfData.AA_CurrentMoveTime = velTimeCur
						end
						self:SetLocalVelocity(velPos)
					-- We are NOT making any progress, stop the movement
					else
						self:AA_StopMoving()
					end
				end
				-- Is aquatic and is NOT completely in water then attempt to go down!
				if moveType == VJ_MOVETYPE_AQUATIC &amp;&amp; self:WaterLevel() &lt;= 2 then
					self:AA_IdleWander()
				end
				if selfData.AA_CurrentMoveAnim != -1 then
					self:AA_MoveAnimation()
				end
			-- Not moving, reset its move time!
			else
				selfData.AA_CurrentMoveTime = 0
			end
		end
		
		-- Update follow system&#x27;s data
		//print(&quot;------------------&quot;)
		//PrintTable(selfData.FollowData)
		if selfData.IsFollowing &amp;&amp; self:GetNavType() != NAV_JUMP &amp;&amp; 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) &amp;&amp; (!followIsLiving or (followIsLiving &amp;&amp; (self:Disposition(followEnt) == D_LI or self:GetClass() == followEnt:GetClass()) &amp;&amp; followEnt:Alive())) then
				if curTime &gt; followData.NextUpdateT &amp;&amp; !selfData.VJ_ST_Healing then
					local distToPly = self:GetPos():Distance(followEnt:GetPos())
					local busy = self:IsBusy(&quot;Activities&quot;)
					self:SetTarget(followEnt)
					followData.StopAct = false
					if distToPly &gt; followData.MinDist then -- Entity is far away, move towards it!
						local isFar = distToPly &gt; (followData.MinDist * 4)
						-- IF (we are busy but far) OR (not busy) THEN move
						if (busy &amp;&amp; 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 moveTypeAA then
								self:AA_MoveTo(self:GetTarget(), true, (distToPly &lt; (followData.MinDist * 1.5) and &quot;Calm&quot;) or &quot;Alert&quot;, {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 &quot;OnTaskFailed&quot; so an NPC can capture it! (Ex: HL1 scientist complaining to the player)
								//if goalTarget then
								local schedule = vj_ai_schedule.New(&quot;SCHEDULE_FOLLOW&quot;)
								schedule:EngTask(&quot;TASK_GET_PATH_TO_TARGET&quot;, 0) -- Required to generate the path!
								schedule:EngTask(&quot;TASK_MOVE_TO_TARGET_RANGE&quot;, followData.MinDist * 0.8)
								schedule:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 0)
								schedule:EngTask(&quot;TASK_FACE_TARGET&quot;, 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 &lt; (followData.MinDist * 1.5) and &quot;TASK_WALK_PATH&quot;) or &quot;TASK_RUN_PATH&quot;, 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

		
		if !selfData.Dead then
			-- Health Regeneration System
			local healthRegen = selfData.HealthRegenParams
			if healthRegen.Enabled &amp;&amp; curTime &gt; 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()
				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&#x27;t exist or it&#x27;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) &gt; selfData.EnemyTimeout &amp;&amp; !selfData.IsVJBaseSNPC_Tank then
					self:PlaySoundSystem(&quot;LostEnemy&quot;)
					self:ResetEnemy(true, true)
					ene = self:GetEnemy()
					eneValid = IsValid(ene)
				end
			end
			
			-- Eating system
			if selfData.CanEat then
				local eatingData = selfData.EatingData
				if !eatingData then -- Eating data has NOT been initialized, so initialize it!
					self.EatingData = {Target = NULL, NextCheck = 0, AnimStatus = &quot;None&quot;, OrgIdle = nil}
						-- AnimStatus: &quot;None&quot; = Not prepared (Probably moving to food location) | &quot;Prepared&quot; = Prepared (Ex: Played crouch down anim) | &quot;Eating&quot; = Prepared and is actively eating
					eatingData = self.EatingData
				end
				if eneValid or selfData.Alerted then
					if selfData.VJ_ST_Eating then
						eatingData.NextCheck = curTime + 15
						self:ResetEatingBehavior(&quot;Enemy&quot;)
					end
				elseif curTime &gt; eatingData.NextCheck then
					if selfData.VJ_ST_Eating then
						local food = eatingData.Target
						if !IsValid(food) then -- Food no longer exists, reset!
							eatingData.NextCheck = curTime + 10
							self:ResetEatingBehavior(&quot;Unspecified&quot;)
						elseif !self:IsMoving() then
							local foodDist = VJ.GetNearestDistance(self, food) // myPos:Distance(food:GetPos())
							if foodDist &gt; 400 then -- Food too far away, reset!
								eatingData.NextCheck = curTime + 10
								self:ResetEatingBehavior(&quot;Unspecified&quot;)
							elseif foodDist &gt; 30 then -- Food moved a bit, go to new location
								if self:IsBusy() then -- Something else has come up, stop eating completely!
									eatingData.NextCheck = curTime + 15
									self:ResetEatingBehavior(&quot;Unspecified&quot;)
								else
									if eatingData.AnimStatus != &quot;None&quot; then -- We need to play get up anim first!
										eatingData.AnimStatus = &quot;None&quot;
										selfData.AnimationTranslations[ACT_IDLE] = eatingData.OrgIdle -- Reset the idle animation table in case it changed!
										eatingData.NextCheck = curTime + (self:OnEat(&quot;StopEating&quot;, &quot;HaltOnly&quot;) or 1)
									else
										selfData.NextWanderTime = CurTime() + math.Rand(3, 5)
										self:SetState(VJ_STATE_NONE)
										self:SetLastPosition(select(2, VJ.GetNearestPositions(self, food)))
										self:SCHEDULE_GOTO_POSITION(&quot;TASK_WALK_PATH&quot;)
										//self:SetTarget(food)
										//self:SCHEDULE_GOTO_TARGET(&quot;TASK_WALK_PATH&quot;)
										eatingData.NextCheck = curTime + 1
									end
								end
							else -- No changes, continue eating
								self:SetTurnTarget(food, 1)
								self:SetState(VJ_STATE_ONLY_ANIMATION_NOATTACK)
								if eatingData.AnimStatus != &quot;None&quot; then -- We are already prepared, so eat!
									eatingData.AnimStatus = &quot;Eating&quot;
									eatingData.NextCheck = curTime + self:OnEat(&quot;Eat&quot;)
									if food:Health() &lt;= 0 then -- Finished eating!
										eatingData.NextCheck = curTime + selfData.EatCooldown
										self:ResetEatingBehavior(&quot;Devoured&quot;)
										food:TakeDamage(100, self, self) -- For entities that react to dmg, Ex: HLR corpses
										food:Remove()
									end
								else -- We need to first prepare before eating! (Ex: Crouch-down animation)
									eatingData.AnimStatus = &quot;Prepared&quot;
									eatingData.NextCheck = curTime + (self:OnEat(&quot;BeginEating&quot;) or 1)
								end
							end
						end
					elseif funcHasCondition(self, COND_SMELL) &amp;&amp; !self:IsMoving() &amp;&amp; !self:IsBusy() then
						local hint = sound.GetLoudestSoundHint(SOUND_CARCASS, myPos)
						if hint then
							local food = hint.owner
							if IsValid(food) /*&amp;&amp; !food.VJ_ST_BeingEaten*/ then
								if !food.FoodData then
									local size = food:OBBMaxs():Distance(food:OBBMins()) * 2
									food.FoodData = {
										NumConsumers = 0,
										Size = size,
										SizeRemaining = size,
									}
								end
								//print(&quot;food&quot;, food, self)
								if food.FoodData.SizeRemaining &gt; 0 &amp;&amp; self:OnEat(&quot;CheckFood&quot;, hint) then
									local foodData = food.FoodData
									foodData.NumConsumers = foodData.NumConsumers + 1
									foodData.SizeRemaining = foodData.SizeRemaining - self:OBBMaxs():Distance(self:OBBMins())
									//PrintTable(hint)
									selfData.VJ_ST_Eating = true
									food.VJ_ST_BeingEaten = true
									selfData.EatingData.OrgIdle = selfData.AnimationTranslations[ACT_IDLE] -- Save the current idle anim table in case we gonna change it while eating!
									eatingData.Target = food
									self:OnEat(&quot;StartBehavior&quot;)
									self:SetState(VJ_STATE_ONLY_ANIMATION_NOATTACK)
									selfData.NextWanderTime = curTime + math.Rand(3, 5)
								end
							end
						end
					//else -- No food was found OR it&#x27;s not eating
						//eatingData.NextCheck = curTime + 3
					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
				if eneIsVisible &amp;&amp; self:IsInViewCone(enePos) &amp;&amp; (eneDist &lt; self:GetMaxLookDistance()) then
					eneData.VisibleTime = curTime
					-- Why 2 vars? Because the last &quot;Visible&quot; 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 &quot;Visible&quot; uses it to run the trace in the engine! | For origin, use &quot;self:GetEnemyLastSeenPos()&quot;
				end
				
				-- Call for help
				if selfData.CallForHelp &amp;&amp; curTime &gt; selfData.NextCallForHelpT &amp;&amp; !selfData.AttackType then
					self:Allies_CallHelp(selfData.CallForHelpDistance)
					selfData.NextCallForHelpT = curTime + selfData.CallForHelpCooldown
				end
				
				-- Stop chasing at certain distance
				local limitChase = selfData.LimitChaseDistance
				if limitChase &amp;&amp; eneIsVisible &amp;&amp; ((limitChase == true) or (limitChase == &quot;OnlyRange&quot; &amp;&amp; selfData.HasRangeAttack)) then
					local minDist = selfData.LimitChaseDistance_Min
					local maxDist = selfData.LimitChaseDistance_Max
					if minDist == &quot;UseRangeDistance&quot; then minDist = selfData.RangeAttackMinDistance end
					if maxDist == &quot;UseRangeDistance&quot; then maxDist = selfData.RangeAttackMaxDistance end
					if (eneDist &lt; maxDist) &amp;&amp; (eneDist &gt; minDist) then
						-- If the selfData.NextChaseTime is about to expire, then give it 0.5 delay so it does NOT chase!
						if (selfData.NextChaseTime - curTime) &lt; 0.1 then
							selfData.NextChaseTime = curTime + 0.5
						end
						self:MaintainIdleBehavior(2) -- Otherwise it won&#x27;t play the idle animation and will loop the last PlayAct animation if range attack doesn&#x27;t use animations!
						if selfData.CurrentScheduleName == &quot;SCHEDULE_ALERT_CHASE&quot; then self:StopMoving() end -- Interrupt enemy chasing because we are in range!
						if moveType == VJ_MOVETYPE_GROUND then
							if !self:IsMoving() &amp;&amp; self:OnGround() then
								self:SetTurnTarget(&quot;Enemy&quot;, 0.5)
							end
						elseif moveTypeAA then
							if selfData.AA_CurrentMoveType == 3 then self:AA_StopMoving() end -- Interrupt enemy chasing because we are in range!
							if curTime &gt; selfData.AA_CurrentMoveTime then self:AA_IdleWander(true, &quot;Calm&quot;, {FaceDest = !selfData.ConstantlyFaceEnemy}) /*self:AA_StopMoving()*/ end -- Only face the position if ConstantlyFaceEnemy is false!
						end
					else
						if selfData.CurrentScheduleName != &quot;SCHEDULE_ALERT_CHASE&quot; then self:MaintainAlertBehavior() end
					end
				end
				
				self:UpdatePoseParamTracking()
				
				-- Attacks
				if !selfData.PauseAttacks &amp;&amp; !selfData.Flinching &amp;&amp; !selfData.FollowData.StopAct &amp;&amp; curTime &gt; selfData.NextDoAnyAttackT &amp;&amp; self:GetState() != VJ_STATE_ONLY_ANIMATION_NOATTACK &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE_NATURE then
					-- Attack priority in order: Custom --&gt; Melee --&gt; Range --&gt; Leap
					local funcThinkAtk = self.OnThinkAttack; if funcThinkAtk then funcThinkAtk(self, !!selfData.AttackType, ene) end
					
					-- Melee Attack
					if selfData.HasMeleeAttack &amp;&amp; selfData.IsAbleToMeleeAttack &amp;&amp; !selfData.AttackType then
						local atkType = false -- false = No attack | 1 = Normal attack | 2 = Prop attack
						if plyControlled then
							if selfData.VJ_TheController:KeyDown(IN_ATTACK) then
								atkType = 1
							end
						else
							-- Regular non-prop attack
							if eneIsVisible &amp;&amp; eneDistNear &lt; selfData.MeleeAttackDistance &amp;&amp; self:GetHeadDirection():Dot((enePos - myPos):GetNormalized()) &gt; math_cos(math_rad(selfData.MeleeAttackAngleRadius)) then
								atkType = 1
							-- Check for possible props that we can attack/push
							elseif curTime &gt; selfData.PropInteraction_NextCheckT then
								local propCheck = self:MaintainPropInteraction()
								if propCheck then
									atkType = 2
								end
								selfData.PropInteraction_Found = propCheck
								selfData.PropInteraction_NextCheckT = curTime + 0.5
							end
						end
						if atkType &amp;&amp; self:OnMeleeAttack(&quot;PreInit&quot;, 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
							selfData.NextAlertSoundT = curTime + 0.4
							if atkType == 2 then
								selfData.MeleeAttack_IsPropAttack = true
							else
								self:SetTurnTarget(&quot;Enemy&quot;) -- Always turn towards the enemy at the start
								selfData.MeleeAttack_IsPropAttack = false
							end
							self:OnMeleeAttack(&quot;Init&quot;, ene)
							self:PlaySoundSystem(&quot;BeforeMeleeAttack&quot;)
							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(&quot;attack_melee_start&quot; .. self:EntIndex(), selfData.TimeUntilMeleeAttackDamage / selfData.AnimPlaybackRate, selfData.MeleeAttackReps, function() if selfData.AttackSeed == seed then self:ExecuteMeleeAttack(atkType == 2) end end)
								if selfData.MeleeAttackExtraTimers then
									for k, t in ipairs(selfData.MeleeAttackExtraTimers) do
										self:AddExtraAttackTimer(&quot;timer_melee_start_&quot; .. curTime + k, t, function() if selfData.AttackSeed == seed then self:ExecuteMeleeAttack(atkType == 2) end end)
									end
								end
							end
							self:OnMeleeAttack(&quot;PostInit&quot;, ene)
						end
					end
					
					-- Range Attack
					if eneIsVisible &amp;&amp; selfData.HasRangeAttack &amp;&amp; selfData.IsAbleToRangeAttack &amp;&amp; !selfData.AttackType &amp;&amp; ((plyControlled &amp;&amp; selfData.VJ_TheController:KeyDown(IN_ATTACK2)) or (!plyControlled &amp;&amp; (eneDist &lt; selfData.RangeAttackMaxDistance) &amp;&amp; (eneDist &gt; selfData.RangeAttackMinDistance) &amp;&amp; (self:GetHeadDirection():Dot((enePos - myPos):GetNormalized()) &gt; math_cos(math_rad(selfData.RangeAttackAngleRadius))))) &amp;&amp; self:OnRangeAttack(&quot;PreInit&quot;, ene) != true then
						local seed = curTime; selfData.AttackSeed = seed
						selfData.IsAbleToRangeAttack = false
						selfData.AttackType = VJ.ATTACK_TYPE_RANGE
						selfData.AttackState = VJ.ATTACK_STATE_STARTED
						selfData.AttackAnim = ACT_INVALID
						selfData.AttackAnimDuration = 0
						selfData.AttackAnimTime = 0
						self:OnRangeAttack(&quot;Init&quot;, ene)
						self:PlaySoundSystem(&quot;BeforeRangeAttack&quot;)
						if selfData.AnimTbl_RangeAttack then
							local anim, animDur, animType = self:PlayAnim(selfData.AnimTbl_RangeAttack, false, 0, false, selfData.RangeAttackAnimationDelay)
							if anim != ACT_INVALID then
								selfData.AttackAnim = anim
								selfData.AttackAnimDuration = animDur - (selfData.RangeAttackAnimationDecreaseLengthAmount / 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.TimeUntilRangeAttackProjectileRelease then
							attackTimers[VJ.ATTACK_TYPE_RANGE](self)
						else -- NOT event based...
							timer.Create(&quot;attack_range_start&quot; .. self:EntIndex(), selfData.TimeUntilRangeAttackProjectileRelease / selfData.AnimPlaybackRate, selfData.RangeAttackReps, function() if selfData.AttackSeed == seed then self:ExecuteRangeAttack() end end)
							if selfData.RangeAttackExtraTimers then
								for k, t in ipairs(selfData.RangeAttackExtraTimers) do
									self:AddExtraAttackTimer(&quot;timer_range_start_&quot; .. curTime + k, t, function() if selfData.AttackSeed == seed then self:ExecuteRangeAttack() end end)
								end
							end
						end
						self:OnRangeAttack(&quot;PostInit&quot;, ene)
					end
					
					-- Leap Attack
					if eneIsVisible &amp;&amp; selfData.HasLeapAttack &amp;&amp; selfData.IsAbleToLeapAttack &amp;&amp; !selfData.AttackType &amp;&amp; ((plyControlled &amp;&amp; selfData.VJ_TheController:KeyDown(IN_JUMP)) or (!plyControlled &amp;&amp; (self:IsOnGround() &amp;&amp; eneDist &lt; selfData.LeapAttackMaxDistance) &amp;&amp; (eneDist &gt; selfData.LeapAttackMinDistance) &amp;&amp; (self:GetHeadDirection():Dot((enePos - myPos):GetNormalized()) &gt; math_cos(math_rad(selfData.LeapAttackAngleRadius))))) &amp;&amp; self:OnLeapAttack(&quot;PreInit&quot;, ene) != true then
						local seed = curTime; selfData.AttackSeed = seed
						selfData.IsAbleToLeapAttack = false
						selfData.LeapAttackHasJumped = false
						selfData.AttackType = VJ.ATTACK_TYPE_LEAP
						selfData.AttackState = VJ.ATTACK_STATE_STARTED
						selfData.AttackAnim = ACT_INVALID
						selfData.AttackAnimDuration = 0
						selfData.AttackAnimTime = 0
						self:OnLeapAttack(&quot;Init&quot;, ene)
						self:PlaySoundSystem(&quot;BeforeLeapAttack&quot;)
						timer.Create(&quot;attack_leap_jump&quot; .. self:EntIndex(), selfData.TimeUntilLeapAttackVelocity / selfData.AnimPlaybackRate, 1, function() self:LeapAttackJump() end)
						if selfData.AnimTbl_LeapAttack then
							local anim, animDur, animType = self:PlayAnim(selfData.AnimTbl_LeapAttack, false, 0, false)
							if anim != ACT_INVALID then
								selfData.AttackAnim = anim
								selfData.AttackAnimDuration = animDur - (selfData.LeapAttackAnimationDecreaseLengthAmount / 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.TimeUntilLeapAttackDamage then
							attackTimers[VJ.ATTACK_TYPE_LEAP](self)
						else -- NOT event based...
							timer.Create(&quot;attack_leap_start&quot; .. self:EntIndex(), selfData.TimeUntilLeapAttackDamage / selfData.AnimPlaybackRate, selfData.LeapAttackReps, function() if selfData.AttackSeed == seed then self:ExecuteLeapAttack() end end)
							if selfData.LeapAttackExtraTimers then
								for k, t in ipairs(selfData.LeapAttackExtraTimers) do
									self:AddExtraAttackTimer(&quot;timer_leap_start_&quot; .. curTime + k, t, function() if selfData.AttackSeed == seed then self:ExecuteLeapAttack() end end)
								end
							end
						end
						self:OnLeapAttack(&quot;PostInit&quot;, ene)
					end
				end
			else -- No enemy
				if !plyControlled then
					self:UpdatePoseParamTracking(true)
					//self:ClearPoseParameters()
				end
				eneData.TimeAcquired = 0
			end
			
			if moveTypeAA then
				if eneValid &amp;&amp; selfData.AttackAnimTime &gt; curTime &amp;&amp; eneData.DistanceNearest &lt; selfData.MeleeAttackDistance then
					self:AA_StopMoving()
				else
					self:SelectSchedule()
				end
			end
			
			-- Guarding Behavior
			if selfData.IsGuard &amp;&amp; !selfData.IsFollowing &amp;&amp; !selfData.IsVJBaseSNPC_Tank then
				local guardData = selfData.GuardData
				if !guardData.Position then -- If we don&#x27;t have a position, then set it!
					guardData.Position = myPos
					guardData.Direction = myPos + self:GetForward() * 51
				end
				-- If it&#x27;s far from the guarding position, then go there!
				if !self:IsMoving() &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
					local dist = myPos:Distance(guardData.Position) -- Distance to the guard position
					if dist &gt; 50 then
						self:SetLastPosition(guardData.Position)
						self:SCHEDULE_GOTO_POSITION(dist &lt;= 800 and &quot;TASK_WALK_PATH&quot; or &quot;TASK_RUN_PATH&quot;, function(x)
							x.CanShootWhenMoving = true
							x.TurnData = {Type = VJ.FACE_ENEMY}
							x.RunCode_OnFinish = function()
								timer.Simple(0.01, function()
									if IsValid(self) &amp;&amp; !self:IsMoving() &amp;&amp; !self:IsBusy(&quot;Activities&quot;) &amp;&amp; selfData.IsGuard &amp;&amp; guardData.Position then
										self:SetLastPosition(guardData.Direction)
										self:SCHEDULE_FACE(&quot;TASK_FACE_LASTPOSITION&quot;)
									end
								end)
							end
						end)
					end
				end
			end
		end
		-- Handle the unique movement system for player models
		if selfData.UsePoseParameterMovement &amp;&amp; moveType == VJ_MOVETYPE_GROUND then
			local moveDir = VJ.GetMoveDirection(self, true)
			if moveDir then
				funcSetPoseParameter(self, &quot;move_x&quot;, moveDir.x)
				funcSetPoseParameter(self, &quot;move_y&quot;, moveDir.y)
			else -- I am not moving, reset the pose parameters, otherwise I will run in place!
				funcSetPoseParameter(self, &quot;move_x&quot;, 0)
				funcSetPoseParameter(self, &quot;move_y&quot;, 0)
			end
		end
	else -- AI Not enabled
		if moveTypeAA then self:AA_StopMoving() end
	end
	
	//if aiEnabled then
		//self:MaintainIdleAnimation()
	//end

	-- Maintain turning when needed otherwise Engine will take over during movements!
	-- No longer needed as &quot;OverrideMoveFacing&quot; now handles it!
	/*if !didTurn then
		local curTurnData = self.TurnData
		if curTurnData.Type &amp;&amp; curTurnData.LastYaw != 0 then
			self:SetIdealYawAndUpdate(curTurnData.LastYaw)
			didTurn = true
		end
	end*/

	self:NextThink(curTime + 0.065)
	return true
end
--------------------------------------------------------------------------------------------------------------------------------------------
local propColBlacklist = {[COLLISION_GROUP_DEBRIS] = true, [COLLISION_GROUP_DEBRIS_TRIGGER] = true, [COLLISION_GROUP_DISSOLVING] = true, [COLLISION_GROUP_IN_VEHICLE] = true, [COLLISION_GROUP_WORLD] = true}
--
function ENT:MaintainPropInteraction(customEnts)
	local behavior = self.PropInteraction
	if !behavior then return false end
	local myPos = self:GetPos()
	local myCenter = myPos + self:OBBCenter()
	for _, ent in ipairs(customEnts or ents.FindInSphere(myCenter, self.MeleeAttackDistance * 1.2)) do
		if ent.VJ_ID_Attackable then
			local vPhys = ent:GetPhysicsObject()
			if IsValid(vPhys) &amp;&amp; !propColBlacklist[ent:GetCollisionGroup()] &amp;&amp; (customEnts or (self:GetHeadDirection():Dot((ent:GetPos() - myPos):GetNormalized()) &gt; math_cos(math_rad(self.MeleeAttackAngleRadius / 1.3)))) then
				local tr = util.TraceLine({
					start = myCenter,
					endpos = ent:NearestPoint(myCenter),
					filter = self
				})
				if !tr.HitWorld &amp;&amp; !tr.HitSky then
					-- Attacking: Make sure it has health
					if (behavior == true or behavior == &quot;OnlyDamage&quot;) &amp;&amp; ent:Health() &gt; 0 then
						return true
					end
					-- Pushing: Make sure it&#x27;s not a small object and the NPC is appropriately sized to push the object
					local surfaceArea = vPhys:GetSurfaceArea() or 900
					if (behavior == true or behavior == &quot;OnlyPush&quot;) &amp;&amp; ent:GetMoveType() != MOVETYPE_PUSH &amp;&amp; surfaceArea &gt; 800 then // &amp;&amp; vPhys:GetMass() &gt; 4
						local myPhys = self:GetPhysicsObject()
						if IsValid(myPhys) &amp;&amp; (myPhys:GetSurfaceArea() * self.PropInteraction_MaxScale) &gt;= surfaceArea then
							return true
						end
					end
				end
			end
		end
	end
	return false
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:ExecuteMeleeAttack(isPropAttack)
	local selfData = self:GetTable()
	if selfData.Dead or selfData.PauseAttacks or selfData.Flinching or (selfData.MeleeAttackStopOnHit &amp;&amp; selfData.AttackState == VJ.ATTACK_STATE_EXECUTED_HIT) then return end
	isPropAttack = isPropAttack or selfData.MeleeAttack_IsPropAttack -- Is this a prop attack?
	local skip = self:OnMeleeAttackExecute(&quot;Init&quot;)
	local hitRegistered = false
	if !skip then
		local myPos = self:GetPos()
		local myClass = self:GetClass()
		//debugoverlay.Cross(self:MeleeAttackTraceOrigin(), 5, 3, Color(255, 255, 0))
		//debugoverlay.EntityTextAtPosition(self:MeleeAttackTraceOrigin(), 0, &quot;Melee damage origin&quot;, 3, Color(255, 255, 0))
		//debugoverlay.Cross(self:MeleeAttackTraceOrigin() + self:GetForward()*selfData.MeleeAttackDamageDistance, 5, 3, Color(238, 119, 222))
		//debugoverlay.EntityTextAtPosition(self:MeleeAttackTraceOrigin() + self:GetForward()*selfData.MeleeAttackDamageDistance, 0, &quot;Melee damage distance&quot;, 3, Color(238, 119, 222))
		for _, ent in ipairs(ents.FindInSphere(self:MeleeAttackTraceOrigin(), selfData.MeleeAttackDamageDistance)) do
			if ent == self or ent:GetClass() == myClass or (ent.IsVJBaseBullseye &amp;&amp; ent.VJ_IsBeingControlled) then continue end
			if ent:IsPlayer() &amp;&amp; (ent.VJ_IsControllingNPC or !ent:Alive() or VJ_CVAR_IGNOREPLAYERS) then continue end
			if ((ent.VJ_ID_Living &amp;&amp; self:Disposition(ent) != D_LI) or ent.VJ_ID_Attackable or ent.VJ_ID_Destructible) &amp;&amp; self:MeleeAttackTraceDirection():Dot((Vector(ent:GetPos().x, ent:GetPos().y, 0) - Vector(myPos.x, myPos.y, 0)):GetNormalized()) &gt; math_cos(math_rad(selfData.MeleeAttackDamageAngleRadius)) then
				if isPropAttack &amp;&amp; ent.VJ_ID_Living &amp;&amp; VJ.GetNearestDistance(self, ent, true) &gt; selfData.MeleeAttackDistance then continue end -- Since this attack initiated as prop attack, its melee distance may be off!
				local applyDmg = true
				local isProp = ent.VJ_ID_Attackable
				if self:OnMeleeAttackExecute(&quot;PreDamage&quot;, ent, isProp) == true then continue end
				local dmgAmount = self:ScaleByDifficulty(selfData.MeleeAttackDamage)
				-- Handle prop interaction
				local propBehavior = selfData.PropInteraction
				if isProp then
					if propBehavior then
						if (propBehavior == true or propBehavior == &quot;OnlyDamage&quot;) &amp;&amp; (ent:Health() &gt; 0 or ent:GetInternalVariable(&quot;m_takedamage&quot;) == 2) then
							hitRegistered = true
							applyDmg = true
						elseif propBehavior == &quot;OnlyPush&quot; then
							applyDmg = false
						end
						local phys = ent:GetPhysicsObject()
						if IsValid(phys) &amp;&amp; self:MaintainPropInteraction({ent}) then
							phys:EnableMotion(true)
							phys:Wake()
							constraint.RemoveConstraints(ent, &quot;Weld&quot;) //constraint.RemoveAll(ent)
							if propBehavior == true or propBehavior == &quot;OnlyPush&quot; then
								hitRegistered = true
								local curEnemy = self:GetEnemy()
								local physMass = phys:GetMass()
								phys:ApplyForceCenter((IsValid(curEnemy) and curEnemy:GetPos() or myPos) + self:GetForward() * (physMass * 700) + self:GetUp() * (physMass * 200))
							end
						end
					else -- We can&#x27;t damage or push props
						applyDmg = false
					end
				end
				if applyDmg then
					-- Knockback | Ignore doors, trains, elevators as it will make them fly when activated
					if selfData.HasMeleeAttackKnockBack &amp;&amp; ent:GetMoveType() != MOVETYPE_PUSH &amp;&amp; ent.MovementType != VJ_MOVETYPE_STATIONARY &amp;&amp; (!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 damage
					if !selfData.DisableDefaultMeleeAttackDamageCode then
						local dmgInfo = DamageInfo()
						dmgInfo:SetDamage(self:ScaleByDifficulty(dmgAmount))
						dmgInfo:SetDamageType(selfData.MeleeAttackDamageType)
						if ent.VJ_ID_Living then dmgInfo:SetDamageForce(self:GetForward() * ((dmgInfo:GetDamage() + 100) * 70)) end
						dmgInfo:SetInflictor(self)
						dmgInfo:SetAttacker(self)
						VJ.DamageSpecialEnts(self, ent, dmgInfo)
						ent:TakeDamageInfo(dmgInfo, self)
					end
					-- Apply bleeding damage
					if selfData.MeleeAttackBleedEnemy &amp;&amp; ent.VJ_ID_Living &amp;&amp; (!ent.VJ_ID_Boss or selfData.VJ_ID_Boss) &amp;&amp; math.random(1, selfData.MeleeAttackBleedEnemyChance) == 1 then
						local bleedName = &quot;timer_melee_bleed&quot; .. ent:EntIndex() -- Timer&#x27;s name
						local bleedDmg = self:ScaleByDifficulty(selfData.MeleeAttackBleedEnemyDamage) -- How much damage each rep does
						timer.Create(bleedName, selfData.MeleeAttackBleedEnemyTime, selfData.MeleeAttackBleedEnemyReps, function()
							if IsValid(ent) &amp;&amp; ent:Health() &gt; 0 then
								local dmgInfo = DamageInfo()
								dmgInfo:SetDamage(bleedDmg)
								dmgInfo:SetDamageType(DMG_GENERIC)
								dmgInfo:SetDamageCustom(VJ.DMG_BLEED)
								if self:IsValid() then
									dmgInfo:SetInflictor(self)
									dmgInfo:SetAttacker(self)
								end
								ent:TakeDamageInfo(dmgInfo)
							else -- Remove the timer if the entity is dead in attempt to remove it before the entity respawns (Essential for players)
								timer.Remove(bleedName)
							end
						end)
					end
				end
				if ent:IsPlayer() then
					ent:ViewPunch(Angle(math.random(-1, 1) * dmgAmount, math.random(-1, 1) * dmgAmount, math.random(-1, 1) * dmgAmount))
					-- Apply DSP
					if selfData.MeleeAttackDSP &amp;&amp; ((!selfData.MeleeAttackDSPLimit) or (dmgAmount &gt;= selfData.MeleeAttackDSPLimit)) then
						ent:SetDSP(selfData.MeleeAttackDSP, false)
					end
					-- Speed modifier
					if selfData.MeleeAttackPlayerSpeed then
						self:DoMeleeAttackPlayerSpeed(ent, selfData.MeleeAttackPlayerSpeedWalk, selfData.MeleeAttackPlayerSpeedRun, selfData.MeleeAttackPlayerSpeedTime, {PlaySound = selfData.HasMeleeAttackPlayerSpeedSounds, SoundTable = selfData.SoundTbl_MeleeAttackPlayerSpeed, SoundLevel = selfData.MeleeAttackPlayerSpeedSoundLevel, FadeOutTime = 1})
					end
				end
				if !isProp then -- Only for non-props...
					hitRegistered = true
					if selfData.MeleeAttackStopOnHit then break end
				end
			end
		end
	end
	if selfData.AttackState &lt; 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(&quot;MeleeAttack&quot;)
			selfData.AttackState = VJ.ATTACK_STATE_EXECUTED_HIT
		else
			self:OnMeleeAttackExecute(&quot;Miss&quot;)
			self:PlaySoundSystem(&quot;MeleeAttackMiss&quot;)
		end
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:DoMeleeAttackPlayerSpeed(ent, walkSpeed, runSpeed, speedTime, sdData, extraOptions, customFunc)
	speedTime = speedTime or 5
	sdData = sdData or {}
		local vSD_PlaySound = sdData.PlaySound or false -- Should it play a sound?
		local vSD_SoundTable = sdData.SoundTable or {} -- Sounds it should play (Picks randomly)
		local vSD_SoundLevel = sdData.SoundLevel or 100 -- How loud should the sound play?
		local vSD_FadeOutTime = sdData.FadeOutTime or 1 -- How long until it the sound fully fades out?
	extraOptions = extraOptions or {}
		local vEF_NoInterrupt = extraOptions.NoInterrupt or false -- If set to true, the player&#x27;s speed won&#x27;t change by another instance of this code
	local walkspeed_before = ent:GetWalkSpeed()
	local runspeed_before = ent:GetRunSpeed()
	if ent.VJ_SpeedModified &amp;&amp; ent.VJ_SpeedModified_NoInterrupt then return end
	if (!ent.VJ_SpeedModified) then
		ent.VJ_SpeedModified = true
		if vEF_NoInterrupt then ent.VJ_SpeedModified_NoInterrupt = true end
		ent.VJ_SlowDownPlayerWalkSpeed = walkspeed_before
		ent.VJ_SlowDownPlayerRunSpeed = runspeed_before
	end
	ent:SetWalkSpeed(walkSpeed or 50)
	ent:SetRunSpeed(runSpeed or 50)
	if (customFunc) then customFunc() end
	if self.HasSounds &amp;&amp; vSD_PlaySound then
		self.CurrentMeleeAttackPlayerSpeedSound = CreateSound(ent, PICK(vSD_SoundTable))
		self.CurrentMeleeAttackPlayerSpeedSound:Play()
		self.CurrentMeleeAttackPlayerSpeedSound:SetSoundLevel(vSD_SoundLevel)
		if !ent:Alive() &amp;&amp; self.CurrentMeleeAttackPlayerSpeedSound then self.CurrentMeleeAttackPlayerSpeedSound:FadeOut(vSD_FadeOutTime) end
	end
	local pickedSD = self.CurrentMeleeAttackPlayerSpeedSound
	local sdFadeTime = vSD_FadeOutTime
	local timerName = &quot;timer_melee_slowply&quot; .. ent:EntIndex()
	
	if timer.Exists(timerName) &amp;&amp; timer.TimeLeft(timerName) &gt; speedTime then
		return
	end
	timer.Create(timerName, speedTime, 1, function()
		ent:SetWalkSpeed(ent.VJ_SlowDownPlayerWalkSpeed)
		ent:SetRunSpeed(ent.VJ_SlowDownPlayerRunSpeed)
		ent.VJ_SpeedModified = false
		ent.VJ_SpeedModified_NoInterrupt = false
		if pickedSD then pickedSD:FadeOut(sdFadeTime) end
		if !IsValid(ent) then timer.Remove(timerName) end
	end)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:ExecuteRangeAttack()
	local selfData = self:GetTable()
	if selfData.Dead or selfData.PauseAttacks or selfData.Flinching or selfData.AttackType == VJ.ATTACK_TYPE_MELEE then return end
	local ene = self:GetEnemy()
	local eneValid = IsValid(ene)
	if eneValid then
		selfData.AttackType = VJ.ATTACK_TYPE_RANGE
		//self:PointAtEntity(ene)
		-- Create projectile
		if !self:OnRangeAttackExecute(&quot;Init&quot;, ene) then
			local projectileClass = PICK(selfData.RangeAttackProjectiles) or PICK(selfData.RangeAttackEntityToSpawn)
			if projectileClass then
				local projectile = ents.Create(projectileClass)
				local spawnPos = self:RangeAttackProjPos(projectile)
				projectile:SetPos(spawnPos)
				projectile:SetAngles((ene:GetPos() - spawnPos):Angle())
				self:OnRangeAttackExecute(&quot;PreSpawn&quot;, ene, projectile)
				projectile:SetOwner(self)
				projectile:SetPhysicsAttacker(self)
				projectile:Spawn()
				projectile:Activate()
				//constraint.NoCollide(self, projectile, 0, 0)
				local phys = projectile:GetPhysicsObject()
				if IsValid(phys) then
					phys:Wake()
					local vel = self:RangeAttackProjVel(projectile)
					phys:SetVelocity(vel)
					projectile:SetAngles(vel:GetNormal():Angle())
				else
					local vel = self:RangeAttackProjVel(projectile)
					projectile:SetVelocity(vel)
					projectile:SetAngles(vel:GetNormal():Angle())
				end
				self:OnRangeAttackExecute(&quot;PostSpawn&quot;, ene, projectile)
			end
		end
	end
	if selfData.AttackState &lt; VJ.ATTACK_STATE_EXECUTED then
		if eneValid then -- Play range attack only once, otherwise it will spam it for every projectile!
			self:PlaySoundSystem(&quot;RangeAttack&quot;)
		end
		selfData.AttackState = VJ.ATTACK_STATE_EXECUTED
		if selfData.TimeUntilRangeAttackProjectileRelease then
			attackTimers[VJ.ATTACK_TYPE_RANGE](self)
		end
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:ExecuteLeapAttack()
	local selfData = self:GetTable()
	if selfData.Dead or selfData.PauseAttacks or selfData.Flinching or (selfData.LeapAttackStopOnHit &amp;&amp; selfData.AttackState == VJ.ATTACK_STATE_EXECUTED_HIT) then return end
	local skip = self:OnLeapAttackExecute(&quot;Init&quot;)
	local hitRegistered = false
	if !skip then
		local myClass = self:GetClass()
		for _, ent in ipairs(ents.FindInSphere(self:GetPos(), selfData.LeapAttackDamageDistance)) do
			if ent == self or ent:GetClass() == myClass or (ent.IsVJBaseBullseye &amp;&amp; ent.VJ_IsBeingControlled) then continue end
			if ent:IsPlayer() &amp;&amp; (ent.VJ_IsControllingNPC or !ent:Alive() or VJ_CVAR_IGNOREPLAYERS) then continue end
			if (ent.VJ_ID_Living &amp;&amp; self:Disposition(ent) != D_LI) or ent.VJ_ID_Attackable or ent.VJ_ID_Destructible then
				if self:OnLeapAttackExecute(&quot;PreDamage&quot;, ent) == true then continue end
				local dmgAmount = self:ScaleByDifficulty(selfData.LeapAttackDamage)
				-- Damage
				if !selfData.DisableDefaultLeapAttackDamageCode then
					local dmgInfo = DamageInfo()
					dmgInfo:SetDamage(dmgAmount)
					dmgInfo:SetInflictor(self)
					dmgInfo:SetDamageType(selfData.LeapAttackDamageType)
					dmgInfo:SetAttacker(self)
					if ent.VJ_ID_Living then dmgInfo:SetDamageForce(self:GetForward() * ((dmgInfo:GetDamage() + 100) * 70)) end
					ent:TakeDamageInfo(dmgInfo, 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
				hitRegistered = true
				if selfData.LeapAttackStopOnHit then break end
			end
		end
	end
	if selfData.AttackState &lt; VJ.ATTACK_STATE_EXECUTED then
		selfData.AttackState = VJ.ATTACK_STATE_EXECUTED
		if selfData.TimeUntilLeapAttackDamage then
			attackTimers[VJ.ATTACK_TYPE_LEAP](self)
		end
	end
	if !skip then
		if hitRegistered then
			self:PlaySoundSystem(&quot;LeapAttackDamage&quot;)
			selfData.AttackState = VJ.ATTACK_STATE_EXECUTED_HIT
		else
			self:OnLeapAttackExecute(&quot;Miss&quot;)
			self:PlaySoundSystem(&quot;LeapAttackDamageMiss&quot;)
		end
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:LeapAttackJump()
	local ene = self:GetEnemy()
	if !IsValid(ene) then return end
	self:SetGroundEntity(NULL)
	self.LeapAttackHasJumped = true
	-- Classic velocity, useful for more straight line jumps
	//return ((ene:GetPos() + ene:OBBCenter()) - (self:GetPos() + self:OBBCenter())):GetNormal() * 400 + self:GetForward() * 200 + self:GetUp() * 100
	self:SetLocalVelocity(self:OnLeapAttack(&quot;Jump&quot;, ene) or VJ.CalculateTrajectory(self, ene, &quot;Curve&quot;, self:GetPos() + self:OBBCenter(), ene:GetPos() + ene:OBBCenter(), 1))
	self:PlaySoundSystem(&quot;LeapAttackJump&quot;)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:StopAttacks(checkTimers)
	if !self:Alive() then return end
	local selfData = self:GetTable()
	if selfData.VJ_DEBUG &amp;&amp; GetConVar(&quot;vj_npc_debug_attack&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;StopAttacks&quot;, &quot;Attack type = &quot; .. selfData.AttackType) end
	
	if checkTimers &amp;&amp; attackTimers[selfData.AttackType] &amp;&amp; selfData.AttackState &lt; VJ.ATTACK_STATE_EXECUTED then
		attackTimers[selfData.AttackType](self, true)
	end
	
	selfData.AttackType = VJ.ATTACK_TYPE_NONE
	selfData.AttackState = VJ.ATTACK_STATE_DONE
	selfData.AttackSeed = 0
	selfData.LeapAttackHasJumped = false

	self:MaintainAlertBehavior()
end
---------------------------------------------------------------------------------------------------------------------------------------------
local function math_angDif(diff)
    diff = diff % 360
    return diff &gt; 180 and (diff - 360) or diff
end
--
function ENT:UpdatePoseParamTracking(resetPoses)
	local selfData = self:GetTable()
	if !selfData.HasPoseParameterLooking then return end
	//VJ.GetPoseParameters(self)
	local ene = self:GetEnemy()
	local newPitch = 0
	local newYaw = 0
	local newRoll = 0
	if !resetPoses &amp;&amp; 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 speed = selfData.PoseParameterLooking_TurningSpeed
	local names = selfData.PoseParameterLooking_Names
	local namesPitch = names.pitch
	local namesYaw = names.yaw
	local namesRoll = names.roll
	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
end
---------------------------------------------------------------------------------------------------------------------------------------------
local schedule_yield_player = vj_ai_schedule.New(&quot;SCHEDULE_YIELD_PLAYER&quot;)
	schedule_yield_player:EngTask(&quot;TASK_MOVE_AWAY_PATH&quot;, 120)
	schedule_yield_player:EngTask(&quot;TASK_RUN_PATH&quot;, 0)
	schedule_yield_player:EngTask(&quot;TASK_WAIT_FOR_MOVEMENT&quot;, 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 eneValid = IsValid(self:GetEnemy())
	self:PlayIdleSound(nil, nil, eneValid)
	
	-- Handle move away behavior
	if funcHasCondition(self, COND_PLAYER_PUSHING) &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
		self:PlaySoundSystem(&quot;YieldToPlayer&quot;)
		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
	
	if eneValid then -- Chase the enemy
		self:MaintainAlertBehavior()
	/*elseif selfData.Alerted then -- No enemy, but alerted
		selfData.TakingCoverT = 0
		self:MaintainIdleBehavior()*/
	else -- Idle
		if !selfData.Alerted then
			selfData.TakingCoverT = 0
		end
		
		-- Investigation: Conditions // funcHasCondition(self, COND_HEAR_PLAYER)
		if selfData.CanInvestigate &amp;&amp; (funcHasCondition(self, COND_HEAR_BULLET_IMPACT) or funcHasCondition(self, COND_HEAR_COMBAT) or funcHasCondition(self, COND_HEAR_WORLD) or funcHasCondition(self, COND_HEAR_DANGER)) &amp;&amp; selfData.NextInvestigationMove &lt; curTime &amp;&amp; selfData.TakingCoverT &lt; curTime &amp;&amp; !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 &amp;&amp; sdOwner:IsVehicle() &amp;&amp; IsValid(sdOwner:GetDriver()) &amp;&amp; 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 &amp;&amp; sdOwner:IsNPC() &amp;&amp; !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(&quot;TASK_FACE_LASTPOSITION&quot;)
					-- Works but just faces the enemy that fired at
					//local sched = vj_ai_schedule.New(&quot;SCHEDULE_HEAR_SOUND&quot;)
					//sched:EngTask(&quot;TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION&quot;, 0)
					//sched:EngTask(&quot;TASK_STOP_MOVING&quot;, 0)
					//sched:EngTask(&quot;TASK_FACE_SAVEPOSITION&quot;, 0)
					//self:StartSchedule(sched)
					self:OnInvestigate(sdOwner)
					self:PlaySoundSystem(&quot;Investigate&quot;)
					selfData.TakingCoverT = curTime + 1
				end
			end
		end
		
		self:MaintainIdleBehavior()
	end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:ResetEnemy(checkAllies, checkVis)
	local selfData = self:GetTable()
	if selfData.Dead or (selfData.VJ_IsBeingControlled &amp;&amp; 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) &amp;&amp; (curTime - ally.EnemyData.VisibleTime) &lt; selfData.EnemyTimeout &amp;&amp; allyEne:Alive() &amp;&amp; self:GetPos():Distance(allyEne:GetPos()) &lt;= self:GetMaxLookDistance() &amp;&amp; self:CheckRelationship(allyEne) == D_HT then
					self:ForceSetEnemy(allyEne, false)
					eneData.VisibleTime = curTime -- Reset the time otherwise it will run &quot;ResetEnemy&quot; 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&#x27;t reset
		local curEnemies = eneData.VisibleCount //selfData.CurrentReachableEnemies
		if (eneValid &amp;&amp; (curEnemies - 1) &gt;= 1) or (!eneValid &amp;&amp; curEnemies &gt;= 1) then
			self:MaintainRelationships() -- Select a new enemy
			-- Check that the reset enemy wasn&#x27;t the only visible enemy
			-- If we don&#x27;t this, it will call &quot;ResetEnemy&quot; again!
			if eneData.VisibleCount &gt; 0 then
				eneData.Reset = false
				return false
			end
		end
	end
	
	if selfData.VJ_DEBUG &amp;&amp; GetConVar(&quot;vj_npc_debug_resetenemy&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;ResetEnemy&quot;, tostring(ene)) end
	eneData.Reset = true
	self:SetNPCState(NPC_STATE_ALERT)
	timer.Create(&quot;alert_reset&quot; .. 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 &amp;&amp; !selfData.IsGuard &amp;&amp; !selfData.IsVJBaseSNPC_Tank &amp;&amp; !selfData.VJ_IsBeingControlled &amp;&amp; selfData.LastHiddenZone_CanWander == true &amp;&amp; !selfData.Weapon_UnarmedBehavior_Active &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE &amp;&amp; selfData.Behavior != VJ_BEHAVIOR_PASSIVE_NATURE &amp;&amp; !self:IsBusy() &amp;&amp; !self:Visible(ene) &amp;&amp; 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
	
	-- Clear memory of the enemy if it&#x27;s not a player AND it&#x27;s dead
	if eneValid &amp;&amp; !ene:IsPlayer() &amp;&amp; !ene:Alive() then
		//print(&quot;Clear memory&quot;, ene)
		self:ClearEnemyMemory(ene)
	end
	selfData.NextWanderTime = curTime + math.Rand(3, 5)
	self:SetEnemy(NULL)
	if moveToEnemy then
		self:SetLastPosition(moveToEnemy)
		self:SCHEDULE_GOTO_POSITION(&quot;TASK_WALK_PATH&quot;, function(schedule)
			//if eneValid then schedule:EngTask(&quot;TASK_FORGET&quot;, ene) end
			//schedule:EngTask(&quot;TASK_IGNORE_OLD_ENEMIES&quot;, 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&#x27;t take bullet damage from friendly NPCs
	if dmgAttacker &amp;&amp; dmginfo:IsBulletDamage() &amp;&amp; dmgAttacker:IsNPC() &amp;&amp; dmgAttacker:Disposition(self) != D_HT &amp;&amp; (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 &amp;&amp; dmgInflictor:GetClass() == &quot;prop_ragdoll&quot; &amp;&amp; dmgInflictor:GetVelocity():Length() &lt;= 100 then return 0 end
	
	local selfData = self:GetTable()
	local hitgroup = self:GetLastDamageHitGroup()
	self:OnDamaged(dmginfo, hitgroup, &quot;Init&quot;)
	if selfData.GodMode or dmginfo:GetDamage() &lt;= 0 then return 0 end
	
	local dmgType = dmginfo:GetDamageType()
	local curTime = CurTime()
	local isFireEnt = false
	if self:IsOnFire() then
		isFireEnt = dmgInflictor &amp;&amp; dmgAttacker &amp;&amp; dmgInflictor:GetClass() == &quot;entityflame&quot; &amp;&amp; dmgAttacker:GetClass() == &quot;entityflame&quot;
		if self:WaterLevel() &gt; 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 &amp;&amp; selfData.ForceDamageFromBosses &amp;&amp; dmgAttacker.VJ_ID_Boss then
		goto skip_immunity
	end
	
	-- Immunity checks
	if isFireEnt &amp;&amp; !selfData.AllowIgnition then self:Extinguish() return 0 end
	if (selfData.Immune_Fire &amp;&amp; (dmgType == DMG_BURN or dmgType == DMG_SLOWBURN or isFireEnt)) or (selfData.Immune_Toxic &amp;&amp; (dmgType == DMG_ACID or dmgType == DMG_RADIATION or dmgType == DMG_POISON or dmgType == DMG_NERVEGAS or dmgType == DMG_PARALYZE)) or (selfData.Immune_Bullet &amp;&amp; (dmginfo:IsBulletDamage() or dmgType == DMG_BULLET or dmgType == DMG_AIRBOAT or dmgType == DMG_BUCKSHOT or dmgType == DMG_SNIPER)) or (selfData.Immune_Explosive &amp;&amp; (dmgType == DMG_BLAST or dmgType == DMG_BLAST_SURFACE or dmgType == DMG_MISSILEDEFENSE)) or (selfData.Immune_Dissolve &amp;&amp; dmginfo:IsDamageType(DMG_DISSOLVE)) or (selfData.Immune_Electricity &amp;&amp; (dmgType == DMG_SHOCK or dmgType == DMG_ENERGYBEAM or dmgType == DMG_PHYSGUN)) or (selfData.Immune_Melee &amp;&amp; (dmgType == DMG_CLUB or dmgType == DMG_SLASH)) or (selfData.Immune_Sonic &amp;&amp; dmgType == DMG_SONIC) then return 0 end
	
	-- Make sure combine ball does reasonable damage and doesn&#x27;t spam!
	if (dmgInflictor &amp;&amp; dmgInflictor:GetClass() == &quot;prop_combine_ball&quot;) or (dmgAttacker &amp;&amp; dmgAttacker:GetClass() == &quot;prop_combine_ball&quot;) then
		if selfData.Immune_Dissolve then return 0 end
		if curTime &gt; 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&#x27;s not caused by the default fire entity [Causes the damage position to be at Vector(0, 0, 0)]
			if selfData.HasBloodParticle &amp;&amp; !isFireEnt then self:SpawnBloodParticles(dmginfo, hitgroup) end
			if selfData.HasBloodDecal then self:SpawnBloodDecals(dmginfo, hitgroup) end
			self:PlaySoundSystem(&quot;Impact&quot;)
		end
	end
	if selfData.Dead then DoBleed() return 0 end -- If dead then just bleed but take no damage
	
	self:OnDamaged(dmginfo, hitgroup, &quot;PreDamage&quot;)
	if dmginfo:GetDamage() &lt;= 0 then return 0 end -- Only take damage if it&#x27;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 &amp;&amp; GetConVar(&quot;vj_npc_debug_damage&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;OnTakeDamage&quot;, &quot;Amount = &quot;, dmginfo:GetDamage(), &quot; | Attacker = &quot;, dmgAttacker, &quot; | Inflictor = &quot;, dmgInflictor) end
	local healthRegen = selfData.HealthRegenParams
	if healthRegen.Enabled &amp;&amp; healthRegen.ResetOnDmg then
		selfData.HealthRegenDelayT = curTime + (math.Rand(healthRegen.Delay.a, healthRegen.Delay.b) * 1.5)
	end
	self:SetSaveValue(&quot;m_iDamageCount&quot;, self:GetTotalDamageCount() + 1)
	self:SetSaveValue(&quot;m_flLastDamageTime&quot;, curTime)
	self:OnDamaged(dmginfo, hitgroup, &quot;PostDamage&quot;)
	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(&quot;OnDamaged&quot;, dmgAttacker)
		self:MarkTookDamageFromEnemy(dmgAttacker)
	else
		self:TriggerOutput(&quot;OnDamaged&quot;, self)
	end
	
	local stillAlive = self:Health() &gt; 0
	if stillAlive then self:PlaySoundSystem(&quot;Pain&quot;) end

	if VJ_CVAR_AI_ENABLED &amp;&amp; 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 &amp;&amp; dmgAttacker:IsPlayer() then
				-- Become enemy to a friendly player | RESULT: May become hostile to an allied player
				if selfData.BecomeEnemyToPlayer &amp;&amp; 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] &gt; selfData.BecomeEnemyToPlayer &amp;&amp; self:Disposition(dmgAttacker) != D_HT then
						self:OnBecomeEnemyToPlayer(dmginfo, hitgroup)
						if selfData.IsFollowing &amp;&amp; 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(&quot;BecomeEnemyToPlayer&quot;)
						if !IsValid(self:GetEnemy()) then
							self:StopMoving()
							self:SetTarget(dmgAttacker)
							self:SCHEDULE_FACE(&quot;TASK_FACE_TARGET&quot;)
						end
						if selfData.CanChatMessage then
							dmgAttacker:PrintMessage(HUD_PRINTTALK, self:GetName() .. &quot; no longer likes you.&quot;)
						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 &amp;&amp; curTime &gt; selfData.NextDamageByPlayerSoundT &amp;&amp; self:Visible(dmgAttacker) then
					local dispLvl = selfData.DamageByPlayerDispositionLevel
					if (dispLvl == 0 or (dispLvl == 1 &amp;&amp; self:Disposition(dmgAttacker) == D_LI) or (dispLvl == 2 &amp;&amp; self:Disposition(dmgAttacker) != D_HT)) then
						self:PlaySoundSystem(&quot;DamageByPlayer&quot;)
					end
				end
			end
			
			self:PlaySoundSystem(&quot;Pain&quot;)

			if !isPassive &amp;&amp; !IsValid(self:GetEnemy()) then
				local canMove = true
				
				-- How allies respond when it&#x27;s damaged
				if selfData.DamageAllyResponse &amp;&amp; curTime &gt; selfData.NextDamageAllyResponseT &amp;&amp; !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(&quot;Diamond&quot;, responseDist, allies, 4)
						end
						for _, ally in ipairs(allies) do
							ally:DoReadyAlert()
						end
						if !isFireEnt &amp;&amp; !self:IsBusy(&quot;Activities&quot;) 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 &amp;&amp; curTime &gt; selfData.TakingCoverT &amp;&amp; !self:IsBusy(&quot;Activities&quot;) then
					-- Attempt to find who damaged me | RESULT: May become alerted if attacker is visible OR it may hide if it didn&#x27;t find the attacker
					if dmgAttacker &amp;&amp; (dmgResponse == true or dmgResponse == &quot;OnlySearch&quot;) then
						local sightDist = self:GetMaxLookDistance()
						sightDist = math_min(math_max(sightDist / 2, sightDist &lt;= 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()) &lt;= sightDist &amp;&amp; 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 &amp;&amp; (dmgResponse == true or dmgResponse == &quot;OnlyMove&quot;) &amp;&amp; !selfData.IsFollowing &amp;&amp; selfData.MovementType != VJ_MOVETYPE_STATIONARY &amp;&amp; dmginfo:GetDamageCustom() != VJ.DMG_BLEED then
						self:SCHEDULE_COVER_ORIGIN(&quot;TASK_RUN_PATH&quot;, function(x) x.CanShootWhenMoving = true x.TurnData = {Type = VJ.FACE_ENEMY} end)
						selfData.TakingCoverT = curTime + 5
					end
				end
			-- Passive NPCs
			elseif isPassive &amp;&amp; curTime &gt; selfData.TakingCoverT then
				if selfData.DamageResponse &amp;&amp; !self:IsBusy() then
					self:SCHEDULE_COVER_ORIGIN(&quot;TASK_RUN_PATH&quot;)
				end
			end
		end
		
		-- Make passive NPCs move away | RESULT: May move away AND may cause other passive NPCs to move as well
		if isPassive &amp;&amp; curTime &gt; 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(&quot;TASK_RUN_PATH&quot;)
						ally:PlaySoundSystem(&quot;Alert&quot;)
					end
				end
			end
			selfData.TakingCoverT = curTime + math.Rand(6, 7)
		end
	end
	
	-- If eating, stop!
	if selfData.CanEat &amp;&amp; selfData.VJ_ST_Eating then
		selfData.EatingData.NextCheck = curTime + 15
		self:ResetEatingBehavior(&quot;Injured&quot;)
	end
	
	if self:Health() &lt;= 0 &amp;&amp; !selfData.Dead then
		self:RemoveEFlags(EFL_NO_DISSOLVE)
		if (dmginfo:IsDamageType(DMG_DISSOLVE)) or (dmgInflictor &amp;&amp; dmgInflictor:GetClass() == &quot;prop_combine_ball&quot;) 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(&quot;m_lifeState&quot;, 1) -- LIFE_DYING
	self:OnDeath(dmginfo, hitgroup, &quot;Init&quot;)
	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 &amp;&amp; dmgAttacker:IsPlayer() &amp;&amp; !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(&quot;AllyDeath&quot;)
				
				if responseType &amp;&amp; myPos:Distance(ally:GetPos()) &lt; responseDist then
					local moved = false
					-- Bring ally
					if responseType == true &amp;&amp; movedAllyNum &lt; self.DeathAllyResponse_MoveLimit then
						moved = self:Allies_Bring(&quot;Random&quot;, responseDist, {ally}, 0, true)
						if moved then
							movedAllyNum = movedAllyNum + 1
						end
					end
					-- Alert ally
					if (responseType == true or responseType == &quot;OnlyAlert&quot;) &amp;&amp; !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 &amp;&amp; ally.BecomeEnemyToPlayer &amp;&amp; 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] &gt; ally.BecomeEnemyToPlayer then
						if ally:Disposition(dmgAttacker) != D_HT then
							ally:OnBecomeEnemyToPlayer(dmginfo, hitgroup)
							if ally.IsFollowing &amp;&amp; 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() .. &quot; no longer likes you.&quot;)
							end
							ally:PlaySoundSystem(&quot;BecomeEnemyToPlayer&quot;)
						end
						ally.Alerted = true
					end
				end
			end
		end
	end
	
	-- Blood decal on the ground
	if self.Bleeds &amp;&amp; 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
	self.HasRangeAttack = false
	self.HasLeapAttack = false
	if IsValid(dmgAttacker) then
		if dmgAttacker:GetClass() == &quot;npc_barnacle&quot; then self.HasDeathCorpse = false end -- Don&#x27;t make a corpse if it&#x27;s killed by a barnacle!
		if vj_npc_ply_frag:GetInt() == 1 &amp;&amp; dmgAttacker:IsPlayer() then dmgAttacker:AddFrags(1) end
		if IsValid(dmgInflictor) then
			gamemode.Call(&quot;OnNPCKilled&quot;, self, dmgAttacker, dmgInflictor, dmginfo)
		end
	end
	self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
	self:GibOnDeath(dmginfo, hitgroup)
	self:PlaySoundSystem(&quot;Death&quot;)
	//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(&quot;OnDeath&quot;, dmgAttacker)
		dmgAttacker:Fire(&quot;KilledNPC&quot;, &quot;&quot;, 0, self, self) -- Allows player companions (npc_citizen) to respond to kill
	else
		self:TriggerOutput(&quot;OnDeath&quot;, self)
	end
	
	-- Handle death animation, death delay, and the final death phase
	local deathTime = self.DeathDelayTime
	if IsValid(dmgInflictor) &amp;&amp; dmgInflictor:GetClass() == &quot;prop_combine_ball&quot; then self.HasDeathAnimation = false end
	if self.HasDeathAnimation &amp;&amp; VJ_CVAR_AI_ENABLED &amp;&amp; !dmginfo:IsDamageType(DMG_REMOVENORAGDOLL) &amp;&amp; !dmginfo:IsDamageType(DMG_DISSOLVE) &amp;&amp; self:GetNavType() != NAV_CLIMB &amp;&amp; math.random(1, self.DeathAnimationChance) == 1 then
		self:RemoveAllGestures()
		self:OnDeath(dmginfo, hitgroup, &quot;DeathAnim&quot;)
		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(&quot;m_lifeState&quot;, 2) -- LIFE_DEAD
	end
	if deathTime &gt; 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 &amp;&amp; GetConVar(&quot;vj_npc_debug_damage&quot;):GetInt() == 1 then VJ.DEBUG_Print(self, &quot;FinishDeath&quot;, &quot;Attacker = &quot;, self.SavedDmgInfo.attacker, &quot; | Inflictor = &quot;, self.SavedDmgInfo.inflictor) end
	self:SetSaveValue(&quot;m_lifeState&quot;, 2) -- LIFE_DEAD
	//self:SetNPCState(NPC_STATE_DEAD)
	self:OnDeath(dmginfo, hitgroup, &quot;Finish&quot;)
	if self.DropDeathLoot then
		self:CreateDeathLoot(dmginfo, hitgroup)
	end
	if bit.band(self.SavedDmgInfo.type, DMG_REMOVENORAGDOLL) == 0 then 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 &amp;&amp; self.HasDeathRagdoll != false then
		local corpseMdl = self:GetModel()
		local corpseMdlCustom = PICK(self.DeathCorpseModel)
		if corpseMdlCustom then corpseMdl = corpseMdlCustom end
		local corpseClass = &quot;prop_physics&quot;
		if self.DeathCorpseEntityClass then
			corpseClass = self.DeathCorpseEntityClass
		else
			if util.IsValidRagdoll(corpseMdl) then
				corpseClass = &quot;prop_ragdoll&quot;
			elseif !util.IsValidProp(corpseMdl) or !util.IsValidModel(corpseMdl) then
				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 &amp;&amp; self.DeathCorpseSubMaterials != nil then -- Take care of sub materials
			for _, x in ipairs(self.DeathCorpseSubMaterials) do
				if self:GetSubMaterial(x) != &quot;&quot; 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) != &quot;&quot; then
					corpse:SetSubMaterial(x, self:GetSubMaterial(x))
				end
			end*/
		end
		//corpse:SetName(&quot;corpse&quot; .. self:EntIndex())
		//corpse:SetModelScale(self:GetModelScale())
		corpse.FadeCorpseType = (corpse:GetClass() == &quot;prop_ragdoll&quot; and &quot;FadeAndRemove&quot;) or &quot;kill&quot;
		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 &amp;&amp; self.HasBloodPool &amp;&amp; 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&#x27;t darken the corpse if we are immune to fire!
				corpse:SetColor(colorGrey)
				//corpse:SetMaterial(&quot;models/props_foliage/tree_deciduous_01a_trunk&quot;)
			end
		end
		
		-- Dissolve
		if (bit.band(self.SavedDmgInfo.type, DMG_DISSOLVE) != 0) or (IsValid(self.SavedDmgInfo.inflictor) &amp;&amp; self.SavedDmgInfo.inflictor:GetClass() == &quot;prop_combine_ball&quot;) then
			corpse:Dissolve(0, 1)
		end
		
		-- Bone and Angle
		-- If it&#x27;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&#x27;s 1, then it&#x27;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 &amp; stink system
		if corpse:Health() &lt;= 0 then
			local hpCalc = totalSurface / 60
			corpse:SetMaxHealth(hpCalc)
			corpse:SetHealth(hpCalc)
		end
		VJ.Corpse_AddStinky(corpse, true)
		
		if self.DeathCorpseFade then corpse:Fire(corpse.FadeCorpseType, &quot;&quot;, self.DeathCorpseFade) end
		if vj_npc_corpse_fade:GetInt() == 1 then corpse:Fire(corpse.FadeCorpseType, &quot;&quot;, vj_npc_corpse_fadetime:GetInt()) end
		self:OnCreateDeathCorpse(dmginfo, hitgroup, corpse)
		if corpse:IsFlagSet(FL_DISSOLVING) &amp;&amp; corpse.ChildEnts then
			for _, child in ipairs(corpse.ChildEnts) do
				child:Dissolve(0, 1)
			end
		end
		corpse:CallOnRemove(&quot;vj_&quot; .. corpse:EntIndex(), function(ent, childPieces)
			for _, child in ipairs(childPieces) do
				if IsValid(child) then
					if child:GetClass() == &quot;prop_ragdoll&quot; then -- Make ragdolls fade
						child:Fire(&quot;FadeAndRemove&quot;, &quot;&quot;, 0)
					else
						child:Fire(&quot;kill&quot;, &quot;&quot;, 0)
					end
				end
			end
		end, corpse.ChildEnts)
		hook.Call(&quot;CreateEntityRagdoll&quot;, nil, self, corpse)
		return corpse
	else
		-- 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</pre>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@garrys_mod_lua_api/rpMtWyrlYyQ</guid><link>https://teletype.in/@garrys_mod_lua_api/rpMtWyrlYyQ?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><comments>https://teletype.in/@garrys_mod_lua_api/rpMtWyrlYyQ?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api#comments</comments><dc:creator>garrys_mod_lua_api</dc:creator><title>VJ-Base - npc_vj_creature_base, shared файл</title><pubDate>Fri, 11 Jul 2025 19:55:42 GMT</pubDate><category>Библиотека VJ Base</category><description><![CDATA[Путь файла «VJ-Base/lua/entities/npc_vj_creature_base/shared.lua»]]></description><content:encoded><![CDATA[
  <p id="ERCv">Путь файла «VJ-Base/lua/entities/npc_vj_creature_base/shared.lua»</p>
  <p id="Yg9f">Код файла shared.lua</p>
  <pre id="eJno" data-lang="lua">ENT.Base 			= &quot;base_entity&quot;
ENT.Type 			= &quot;ai&quot;
ENT.PrintName 		= &quot;VJ Base Creature&quot;
ENT.Author 			= &quot;DrVrej&quot;
ENT.Contact 		= &quot;http://steamcommunity.com/groups/vrejgaming&quot;
ENT.Category		= &quot;VJ Base&quot;
ENT.AutomaticFrameAdvance = false

ENT.IsVJBaseSNPC = true
ENT.IsVJBaseSNPC_Creature = true
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:SetAutomaticFrameAdvance(val)
	self.AutomaticFrameAdvance = val
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:MatFootStepQCEvent(data)
	-- Return true to apply all changes done to the data table.
	-- Return false to prevent the sound from playing.
	-- Return nil or nothing to play the sound without altering it.
	return false
end
---------------------------------------------------------------------------------------------------------------------------------------------
//function ENT:FireAnimationEvent(pos, ang, event, name)
	//VJ.DEBUG_Print(self, &quot;FireAnimationEvent&quot;, pos, ang, event, name)
//end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
	function ENT:Init() end
	--[[---------------------------------------------------------
		UNCOMMENT TO USE | Overrides the camera calculations for the NPC Controller
			- ply = Player that is controlling the NPC
			- origin = Current view position
			- angles = Current view angles
			- fov = Current field of view
			- camera = Camera entity
			- cameraMode = Camera mode | 1 = Third, 2 = First
		Returns
			- false or nothing = Run base code
			- Table: Override base code, possible values --&gt; {origin, ang, fov, speed}, &quot;speed&quot; = Camera lerp speed
		Example Code:
			Use a new cool view origin!
			--
			if cameraMode == 1 then -- Only if we are in third person
				return {origin = origin - (angles:Forward() * 300)}
			end
			return false
			--
	-----------------------------------------------------------]]
	-- function ENT:Controller_CalcView(ply, origin, angles, fov, camera, cameraMode) end
	---------------------------------------------------------------------------------------------------------------------------------------------
	//ENT.RenderGroup = RENDERGROUP_BOTH
	local metaEntity = FindMetaTable(&quot;Entity&quot;)
	local funcDrawModel = metaEntity.DrawModel
	
	function ENT:Initialize()
		if GetConVar(&quot;vj_npc_ikchains&quot;):GetInt() == 0 then self:SetIK(false) end
		if GetConVar(&quot;vj_npc_forcelowlod&quot;):GetInt() == 1 then self:SetLOD(8) end
		if self.CustomOnDraw then -- !!!!!!!!!!!!!! DO NOT USE THIS FUNCTION !!!!!!!!!!!!!! [Backwards Compatibility!]
			function self:Draw()
				funcDrawModel(self)
				self:CustomOnDraw()
			end
		end
		self:Init()
	end
	function ENT:Draw() funcDrawModel(self) end
	function ENT:DrawTranslucent() self:Draw() end
	//function ENT:CalcAbsolutePosition(pos, ang) end
end</pre>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@garrys_mod_lua_api/9BDY6_r79mR</guid><link>https://teletype.in/@garrys_mod_lua_api/9BDY6_r79mR?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><comments>https://teletype.in/@garrys_mod_lua_api/9BDY6_r79mR?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api#comments</comments><dc:creator>garrys_mod_lua_api</dc:creator><title>Примеры кода на glua для garrys mod</title><pubDate>Mon, 05 Feb 2024 22:36:04 GMT</pubDate><description><![CDATA[Пример 1:]]></description><content:encoded><![CDATA[
  <p id="Wj7o"><strong>Пример 1:</strong></p>
  <pre id="Wj7o" data-lang="lua">local TEMP_NPC_Victims = {
    [&quot;npc_vj_zend_guard&quot;] = &quot;npc_vj_Security&quot;,
    [&quot;npc_alyx&quot;] = &quot;npc_zombie_alyx&quot;,
    [&quot;&quot;] = &quot;&quot;,
    [&quot;npc_kleiner&quot;] = &quot;npc_14d_hunter&quot;
}

hook.Add(&quot;OnNPCKilled&quot;, &quot;InfectionNPCKilled&quot;, function(NPC, ATT, INF)
    if isstring(TEMP_NPC_Victims[NPC:GetClass()]) then
        local TEMP_MDL = NPC:GetModel()
        local TEMP_POS = NPC:GetPos()
        local TEMP_ANG = NPC:GetAngles()
        local TEMP_CLS = TEMP_NPC_Victims[NPC:GetClass()]

        print(&quot;МЕСТО ДЛЯ ПАРТИКЛА&quot;)

        timer.Create(&quot;INFECTION_CREATE_ZOMBIE_NPC_&quot; .. tostring(NPC),  10,  1, function()
            local TEMP_Victim = ents.Create(TEMP_CLS)
            TEMP_Victim:SetModel(TEMP_MDL)
            TEMP_Victim:SetPos(TEMP_POS)
            TEMP_Victim:SetAngles(TEMP_ANG)
            TEMP_Victim:Spawn()
        end)
    end
end)</pre>
  <p id="n6js"></p>
  <p id="vADR"><strong>Пример 2:</strong></p>
  <pre id="T2qK" data-lang="lua">hook.Add(&quot;OnNPCKilled&quot;, &quot;Dying_Light_Mutant_Level_Up_numberi&quot;, function(DEAD_NPC, Entity_Attacker, Entity_Inflictor)
    if IsValid(Entity_Attacker) and DEAD_NPC:IsNPC() and Entity_Attacker ~= NULL then
        if Entity_Attacker:GetClass() == &quot;npc_vj_dyinglight_toxicbiter&quot; then
            Entity_Attacker.VAR_Points = Entity_Attacker.VAR_Points + 1
            if Entity_Attacker.VAR_Points &gt; 3 then
                Entity_Attacker.VAR_Points = -999999

                timer.Create(&quot;DL_Biter_Upgrade_1_&quot; .. tostring(Entity_Attacker), 30, 1, function()
                    if IsValid(Entity_Attacker) and Entity_Attacker ~= NULL then
                        Entity_Attacker:SetHealth(Entity_Attacker:Health() + 60)
                        Entity_Attacker:VJ_ACT_PLAYACTIVITY(&quot;Cower&quot;, true, 2, false)

                        timer.Create(&quot;DL_Biter_Upgrade_2_&quot; .. tostring(Entity_Attacker), 3, 1, function()
                            if IsValid(Entity_Attacker) and Entity_Attacker ~= NULL then
                                local ReincarnationMonster = ents.Create(&quot;npc_vj_14d_com_m_soldier&quot;)
                                ReincarnationMonster:SetModel(Entity_Attacker:GetModel())
                                ReincarnationMonster:SetPos(Entity_Attacker:GetPos())
                                ReincarnationMonster:SetAngles(Entity_Attacker:GetAngles())
                                -- ReincarnationMonster:SetColor(Color(242,162,162))
                                ReincarnationMonster:Spawn()
                                ReincarnationMonster:VJ_ACT_PLAYACTIVITY(&quot;attackdoor_01&quot;, true, 3, false)
                                Entity_Attacker:Remove()
                            end
                        end)
                    end
                end)
            end
        end
    end
end)</pre>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@garrys_mod_lua_api/PRH2M7ecvmY</guid><link>https://teletype.in/@garrys_mod_lua_api/PRH2M7ecvmY?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><comments>https://teletype.in/@garrys_mod_lua_api/PRH2M7ecvmY?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api#comments</comments><dc:creator>garrys_mod_lua_api</dc:creator><title>Как использовать Phind</title><pubDate>Sat, 12 Aug 2023 03:09:12 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/b8/d9/b8d9b2e2-b644-4115-860b-75f2ad234257.png"></media:content><description><![CDATA[<img src="https://img4.teletype.in/files/3b/4e/3b4e1cbd-ed6b-44db-a0b6-91f683c99373.png"></img>Как использовать Phind]]></description><content:encoded><![CDATA[
  <nav>
    <ul>
      <li class="m_level_1"><a href="#bKBJ">Описание:</a></li>
      <li class="m_level_2"><a href="#YH89">Изменение кода:</a></li>
      <li class="m_level_2"><a href="#VIYr">Где используется ключ и с каким другим кодом связан текущий код:</a></li>
      <li class="m_level_2"><a href="#cqzD">Контекст слов/действий:</a></li>
    </ul>
  </nav>
  <h2 id="bKBJ">Описание:</h2>
  <figure id="RCZy" class="m_original">
    <img src="https://img4.teletype.in/files/3b/4e/3b4e1cbd-ed6b-44db-a0b6-91f683c99373.png" width="850" />
  </figure>
  <figure id="niH7" class="m_original">
    <img src="https://img3.teletype.in/files/eb/b1/ebb1b88c-e92d-4cc3-85c2-cd847487c63c.png" width="836" />
  </figure>
  <figure id="WxnM" class="m_original">
    <img src="https://img4.teletype.in/files/fa/9c/fa9ce848-db9a-48bc-a3a1-e414aa34638f.png" width="837" />
  </figure>
  <figure id="wQ24" class="m_original">
    <img src="https://img3.teletype.in/files/ec/68/ec686716-bc89-48b0-b885-69636e7658fc.png" width="859" />
  </figure>
  <figure id="VEJf" class="m_original">
    <img src="https://img2.teletype.in/files/12/93/1293e965-30b2-4333-a18d-e9bc902cd5a4.png" width="855" />
  </figure>
  <figure id="ei75" class="m_original">
    <img src="https://img3.teletype.in/files/ed/cd/edcd32b0-0f44-45a7-ae3d-8d932e0730ca.png" width="835" />
  </figure>
  <p id="zn02"></p>
  <hr />
  <p id="eQ1R"></p>
  <h3 id="YH89">Изменение кода:</h3>
  <figure id="rPp2" class="m_original">
    <img src="https://img2.teletype.in/files/16/32/1632abd3-f0bc-4c01-b9be-e001f757a1e3.png" width="872" />
  </figure>
  <figure id="Rqgn" class="m_original">
    <img src="https://img3.teletype.in/files/a2/17/a217a1c6-0a56-4a17-9aaf-63cc410b191a.png" width="884" />
  </figure>
  <figure id="V5RI" class="m_original">
    <img src="https://img1.teletype.in/files/84/e8/84e8b956-9834-45e4-8608-088e74084c24.png" width="896" />
  </figure>
  <figure id="2vZ7" class="m_original">
    <img src="https://img4.teletype.in/files/3a/c8/3ac8d809-f6cc-4f25-bacd-427a2758a973.png" width="899" />
  </figure>
  <figure id="ffSo" class="m_original">
    <img src="https://img2.teletype.in/files/58/4c/584cc411-51a2-4512-b4b3-9e630c4f2028.png" width="843" />
  </figure>
  <figure id="Hqlo" class="m_original">
    <img src="https://img2.teletype.in/files/5b/66/5b6674b2-583e-4479-9d2a-109c62450309.png" width="835" />
  </figure>
  <figure id="TK2k" class="m_original">
    <img src="https://img2.teletype.in/files/13/f6/13f612b7-f982-4d50-807a-dd5d13fe8d7b.png" width="892" />
  </figure>
  <figure id="UJ8M" class="m_original">
    <img src="https://img2.teletype.in/files/5e/45/5e453d22-78b8-4f80-8d5c-2feb277e08ca.png" width="876" />
  </figure>
  <figure id="aXT9" class="m_original">
    <img src="https://img4.teletype.in/files/f9/2a/f92aca65-3cd7-4bd9-9597-b90ebe366276.png" width="832" />
  </figure>
  <figure id="lmol" class="m_original">
    <img src="https://img1.teletype.in/files/cd/c3/cdc39cf1-3fed-4390-8470-6c0c48a4b764.png" width="820" />
  </figure>
  <p id="mKYa"></p>
  <hr />
  <p id="LS56"></p>
  <h3 id="VIYr">Где используется ключ и с каким другим кодом связан текущий код:</h3>
  <figure id="QDLU" class="m_original">
    <img src="https://img2.teletype.in/files/97/8b/978b9984-e23b-4901-8dc0-456fe5f6435e.png" width="876" />
  </figure>
  <figure id="vPPH" class="m_original">
    <img src="https://img2.teletype.in/files/53/9e/539e9b83-1451-4bd2-a46a-63181b96f895.png" width="816" />
  </figure>
  <figure id="nolt" class="m_original">
    <img src="https://img4.teletype.in/files/bd/14/bd140ab7-d8bb-4127-84ff-b3f5ab16382b.png" width="798" />
  </figure>
  <figure id="b6pi" class="m_original">
    <img src="https://img1.teletype.in/files/00/7b/007b3991-8083-46ee-a629-d4a8abc9a093.png" width="788" />
  </figure>
  <figure id="bBk2" class="m_original">
    <img src="https://img4.teletype.in/files/b3/d5/b3d51a5f-ebd5-49ef-90f8-6ecfee5a4cb3.png" width="850" />
  </figure>
  <figure id="Ora7" class="m_original">
    <img src="https://img1.teletype.in/files/0b/cc/0bcc9e9a-70f3-4e55-84e9-8700431988e0.png" width="862" />
  </figure>
  <figure id="qpzS" class="m_original">
    <img src="https://img3.teletype.in/files/ee/76/ee766889-4ba2-47f9-aa5b-7c253785b105.png" width="828" />
  </figure>
  <figure id="noAl" class="m_original">
    <img src="https://img2.teletype.in/files/50/cb/50cbc208-8ab8-4d0b-9694-3737d0c1508d.png" width="822" />
  </figure>
  <p id="KaDm"></p>
  <hr />
  <p id="75KX"></p>
  <h3 id="cqzD">Контекст слов/действий:</h3>
  <figure id="pQhI" class="m_original">
    <img src="https://img4.teletype.in/files/f0/58/f0588549-305e-464a-a7c4-d6ea9930315b.png" width="814" />
  </figure>
  <figure id="x02J" class="m_original">
    <img src="https://img4.teletype.in/files/b3/e5/b3e500e0-188b-4a8e-909d-1255f9b2eaaa.png" width="832" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@garrys_mod_lua_api/NVFVWmYJj5U</guid><link>https://teletype.in/@garrys_mod_lua_api/NVFVWmYJj5U?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><comments>https://teletype.in/@garrys_mod_lua_api/NVFVWmYJj5U?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api#comments</comments><dc:creator>garrys_mod_lua_api</dc:creator><title>Методы Функции и аргументы в Glua Garrys Mod Lua API</title><pubDate>Sun, 06 Aug 2023 19:47:19 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/4b/6b/4b6b6e2c-55cd-4d0a-b2e5-d770f70065eb.png"></media:content><description><![CDATA[<img src="https://img1.teletype.in/files/8b/77/8b771c2d-55f5-4660-a82f-53175fe4fba7.png"></img>В контексте Garry's Mod Lua API, термины &quot;методы&quot; и &quot;функции&quot; имеют те же основные определения, что и в общем программировании. Однако, в Garry's Mod Lua API они имеют некоторые специфические особенности:]]></description><content:encoded><![CDATA[
  <figure id="5GeW" class="m_custom" data-caption-align="center">
    <img src="https://img1.teletype.in/files/8b/77/8b771c2d-55f5-4660-a82f-53175fe4fba7.png" width="414" />
  </figure>
  <nav>
    <ul>
      <li class="m_level_1"><a href="#5vJy">Вступление:</a></li>
      <li class="m_level_2"><a href="#C6Bs">Методы:</a></li>
      <li class="m_level_2"><a href="#YORQ">Функции:</a></li>
      <li class="m_level_2"><a href="#vesL">используется self в классик функциях ?</a></li>
      <li class="m_level_2"><a href="#M9yy">Методы с "ENT:"</a></li>
      <li class="m_level_2"><a href="#95gu">Что такое Аргументы:</a></li>
      <li class="m_level_1"><a href="#myLD">Варианты self</a></li>
      <li class="m_level_2"><a href="#ZG2k">self.</a></li>
      <li class="m_level_2"><a href="#vw3l">self:</a></li>
      <li class="m_level_1"><a href="#0Ueb">Циклы:</a></li>
      <li class="m_level_2"><a href="#BWHf">Цикл For:</a></li>
      <li class="m_level_1"><a href="#iKmW">Скобки для группировки условий:</a></li>
      <li class="m_level_1"><a href="#O8KZ">Будем использовать нейросеть Phind для создания метода.</a></li>
      <li class="m_level_2"><a href="#HRsx">Итог в фото:</a></li>
    </ul>
  </nav>
  <h2 id="5vJy">Вступление:</h2>
  <p id="KpBQ">В контексте Garry&#x27;s Mod Lua API, термины &quot;методы&quot; и &quot;функции&quot; имеют те же основные определения, что и в общем программировании. Однако, в Garry&#x27;s Mod Lua API они имеют некоторые специфические особенности:</p>
  <h3 id="C6Bs">Методы:</h3>
  <ul id="sy2q">
    <li id="nuef">Методы в Garry&#x27;s Mod Lua API являются функциями, которые связаны с определенными объектами или классами, предоставляемыми API.</li>
    <li id="yJOq">Методы могут быть вызваны на конкретных объектах или экземплярах классов, чтобы выполнить определенные действия или получить доступ к свойствам объекта.</li>
    <li id="YVO1">Методы могут иметь специальные параметры, такие как <code>self</code>, который ссылается на текущий объект, на котором вызывается метод.</li>
  </ul>
  <p id="4MBF">Пример метода из Garry&#x27;s Mod Lua API:</p>
  <pre id="Wbnv" data-lang="lua">&#x60;&#x60;&#x60;lua
-- Создание нового игрока
local player = Player(1)</pre>
  <pre id="QsTK" data-lang="lua">-- Вызов метода GetPos() на объекте player
local position = player:GetPos()
&#x60;&#x60;&#x60;</pre>
  <h3 id="YORQ">Функции:</h3>
  <ul id="pBzA">
    <li id="g28W">Функции в Garry&#x27;s Mod Lua API являются самостоятельными блоками кода, которые выполняют определенные действия или возвращают результаты.</li>
    <li id="XGzb">Функции могут быть определены в любом месте кода и вызываться из других частей программы.</li>
    <li id="73cM">Функции могут принимать аргументы и возвращать значения.</li>
  </ul>
  <p id="beTA"></p>
  <p id="ln4N">Пример функции из Garry&#x27;s Mod Lua API:</p>
  <pre id="5mtb" data-lang="lua">&#x60;&#x60;&#x60;lua
-- Функция для создания нового пропа
local function SpawnProp(model, position, angle)
    local prop = ents.Create(&quot;prop_physics&quot;)
    prop:SetModel(model)
    prop:SetPos(position)
    prop:SetAngles(angle)
    prop:Spawn()
    return prop
end</pre>
  <pre id="Klbh" data-lang="lua">-- Вызов функции для создания пропа
local prop = SpawnProp(&quot;models/props_c17/oildrum001.mdl&quot;, Vector(0, 0, 0), Angle(0, 0, 0))
&#x60;&#x60;&#x60;</pre>
  <p id="lXZp">В общем, методы в Garry&#x27;s Mod Lua API связаны с объектами или классами, предоставляемыми API, и могут быть вызваны на конкретных объектах. Функции в Garry&#x27;s Mod Lua API являются самостоятельными блоками кода, которые могут быть вызваны из любой части программы.</p>
  <hr />
  <h3 id="vesL">используется self в классик функциях ?</h3>
  <blockquote id="DiDm">В Garrys Mod Lua API, в классической функции, обычно не используется &quot;self&quot;. Вместо этого, функции могут принимать параметры, которые передаются при вызове функции.</blockquote>
  <p id="ALeV">Например, в следующем коде функция <code>myFunction</code> принимает два параметра <code>param1</code> и <code>param2</code>, которые могут быть использованы внутри функции:</p>
  <pre id="Aq3D" data-lang="lua">function myFunction(param1, param2)
    print(param1 + param2)
end</pre>
  <pre id="fEjr" data-lang="lua">myFunction(10, 20) -- Выводит 30
</pre>
  <p id="F2ak"></p>
  <hr />
  <p id="7Jcb"></p>
  <h3 id="M9yy">Методы с &quot;ENT:&quot;</h3>
  <p id="rcsf">В Garry&#x27;s Mod Lua API, &quot;function ENT:ddd()&quot; описывает метод &quot;ddd()&quot; для объекта ENT (Entity). В этом контексте &quot;ENT&quot; представляет сущность или объект в игре, такой как игрок, предмет, NPC и т. д. Метод &quot;ddd()&quot; является пользовательским методом, который можно определить для расширения функциональности объекта ENT.</p>
  <p id="UTXA">Приведенный ниже пример кода демонстрирует определение метода &#x60;ddd()&#x60; для объекта ENT:</p>
  <pre id="kUI0" data-lang="lua">&#x60;&#x60;&#x60;lua
function ENT:ddd()
    -- Код метода ddd()
end
&#x60;&#x60;&#x60;</pre>
  <p id="Dlbs">Это позволяет вызывать метод &#x60;ddd()&#x60; на объектах ENT. Например:</p>
  <pre id="8Vov" data-lang="lua">&#x60;&#x60;&#x60;lua
local myEnt = ents.Create(&quot;my_entity&quot;)
myEnt:ddd()
&#x60;&#x60;&#x60;</pre>
  <p id="QAFT">Метод &quot;ddd()&quot; может содержать любую логику и действия, необходимые для объекта ENT. Важно помнить, что методы, определенные в ENT, должны быть определены с использованием двоеточия (&#x60;:&#x60;) вместо точки (&#x60;.&#x60;), чтобы передать объект ENT в качестве первого аргумента метода.</p>
  <p id="Mv1R">То есть - &quot;ENT:&quot; ставится в создаваемый метод где используется в аргументах Entity или класс - пример кода вам на глаз !</p>
  <p id="L66s">Пример кода.</p>
  <p id="PTxH">аргумент &quot;npcEntities&quot; - является &quot;Entity&quot;.</p>
  <pre id="SB1i" data-lang="lua">-- Внутри файла dv.lua

-- Определяем метод AttackIfVisible для класса dv
function ENT:AttackIfVisible(npcEntities, weaponClass)
    -- Проходимся по каждому объекту dm
    for _, npcEntity in pairs(npcEntities) do
        -- Проверяем видимость между текущим объектом dv и объектом dm
        if self:Visible(npcEntity) then
            -- Проверяем, если dm является NPC
            if npcEntity:IsNPC() then
                self:Give(weaponClass)
                self:SelectWeapon(weaponClass)

                -- Проверяем расстояние между dv и dm
                if self:GetPos():Distance(npcEntity:GetPos()) &gt; 100 then
                    self:SetLastPosition(npcEntity:GetPos())
                    self:SetSchedule(SCHED_FORCED_GO_RUN)
                else
                    self:AttackTarget(npcEntity)
                end
            else
                -- Обработка, если dm не является NPC
                -- ...
            end
        end
    end
end</pre>
  <p id="SB1i"></p>
  <hr />
  <p id="6Fpd"></p>
  <h3 id="95gu">Что такое Аргументы:</h3>
  <ol id="sXos">
    <li id="Q2tH">В программировании, аргументы относятся к значениям или переменным, которые передаются в функцию при ее вызове. Аргументы предоставляют данные, с которыми функция будет работать или на основе которых будет выполнять определенные операции.</li>
    <li id="cUvf">В Garry&#x27;s Mod Lua API, аргументы относятся к значениям, которые передаются в функцию при ее вызове. Аргументы предоставляют данные, с которыми функция будет работать или на основе которых будет выполнять определенные операции.</li>
  </ol>
  <p id="aWLR"></p>
  <p id="1Gpp">Например, в следующем коде функции <code>MyFunction(arg1, arg2)</code> имеются два аргумента <code>arg1</code> и <code>arg2</code>:</p>
  <pre id="Pd2X" data-lang="lua">function MyFunction(arg1, arg2)
    -- Код функции
end
</pre>
  <p id="asHE">При вызове этой функции необходимо передать значения для аргументов <code>arg1</code> и <code>arg2</code>. Например:</p>
  <pre id="ufWe" data-lang="lua">MyFunction(value1, value2)</pre>
  <p id="B82s">Внутри функции <code>MyFunction</code> можно использовать переданные аргументы для выполнения нужных операций.</p>
  <p id="9V7a">Источник: <a href="https://wiki.facepunch.com/gmod/" target="_blank">wiki.facepunch</a></p>
  <p id="fYHm"></p>
  <p id="NShD">Аргументы в Garry&#x27;s Mod Lua API могут быть различных типов данных, таких как числа, строки, булевы значения или даже другие объекты из API. В зависимости от функции и ее назначения, аргументы могут иметь различные значения и использоваться для разных целей.</p>
  <p id="Dw26">Например, в функции <code>ents.Create(classname, position, angles, frozen)</code> из Garry&#x27;s Mod Lua API есть четыре аргумента:</p>
  <ul id="ehU7">
    <li id="umVz"><code>classname</code> (строка) - имя класса объекта, который будет создан.</li>
    <li id="E8XV"><code>position</code> (вектор) - позиция, в которой будет создан объект.</li>
    <li id="RY06"><code>angles</code> (угол) - углы поворота объекта.</li>
    <li id="r4sN"><code>frozen</code> (булево значение) - указывает, будет ли объект заморожен в начальном состоянии.</li>
  </ul>
  <pre id="9aMm" data-lang="lua">local myEnt = ents.Create(&quot;my_entity&quot;, Vector(0, 0, 0), Angle(0, 0, 0), true)</pre>
  <p id="QvtL">В приведенном примере мы создаем объект с классом &quot;my_entity&quot; на позиции (0, 0, 0) с нулевыми углами поворота и замороженным состоянием.</p>
  <p id="KXG6">Источник: <a href="https://wiki.facepunch.com/gmod/" target="_blank">wiki.facepunch</a></p>
  <hr />
  <hr />
  <p id="dDpB"></p>
  <h2 id="myLD">Варианты self</h2>
  <p id="AdwI">в термине self есть 2 вида обращения или отсылки. &quot;<code>self.</code>&quot; - это обращение к переменной, в простой функции или таблице, где может быть функция.</p>
  <p id="lCJH">А &quot;<code>self:</code>&quot; - это обращение исключительно к методу, который может быть в функции или в таблице.</p>
  <p id="dz3g"></p>
  <hr />
  <p id="mMCi"></p>
  <h3 id="ZG2k">self.</h3>
  <p id="5Dmw">Строка кода &quot;self.health = self.health - amount&quot; в Garry&#x27;s Mod Lua API используется для вычитания значения &quot;amount&quot; из поля &quot;health&quot; текущего объекта или таблицы.</p>
  <p id="S0Lj">Вот пошаговое объяснение этой строки:</p>
  <ol id="bHtT">
    <li id="TZ9S"><u>&quot;self.health&quot;</u> обращается к полю <u>&quot;health&quot;</u> текущего <u>объекта</u> или <u>таблицы</u>. <u>&quot;self&quot;</u> является ссылкой на текущий <u>объект</u> или таблицу, а оператор точки <u>&quot;.&quot;</u> используется для доступа к их полям.</li>
    <li id="uRpz">Оператор минус <u>&quot;-&quot;</u> вычитает значение <u>&quot;amount&quot;</u> из текущего значения <u>&quot;self.health&quot;</u>.</li>
    <li id="Kog5">Не забывайте &quot;<code>self.health</code>&quot; это отсылка  к переменной &quot;<code>health = 100</code>&quot; в следующем коде.</li>
    <li id="0IV4">Результат вычитания затем присваивается обратно в поле &quot;health&quot; текущего объекта или таблицы с помощью оператора присваивания &quot;=&quot;.</li>
  </ol>
  <p id="Zhs1">Проще говоря, эта строка кода обновляет поле &quot;health&quot; текущего объекта или таблицы, вычитая из него значение &quot;amount&quot;.</p>
  <p id="sduj">Вот пример, иллюстрирующий использование этой строки кода:</p>
  <pre id="DKOo" data-lang="lua">&#x60;&#x60;&#x60;lua
local myObject = {
    health = 100,
    
    TakeDamage = function(self, amount)
        self.health = self.health - amount
        print(&quot;Здоровье: &quot; .. self.health)
    end
}</pre>
  <pre id="mQqJ" data-lang="lua">myObject:TakeDamage(20) -- Вывод: Здоровье: 80
&#x60;&#x60;&#x60;
</pre>
  <p id="68y1">В этом примере вызывается метод &quot;TakeDamage&quot; таблицы &quot;myObject&quot; с аргументом 20. Строка &quot;self.health = self.health - amount&quot; вычитает 20 из начального значения &quot;health&quot; (100), что приводит к новому значению 80. Обновленное значение &quot;health&quot; затем выводится на экран.</p>
  <p id="iP17"></p>
  <hr />
  <p id="Bmww"></p>
  <h3 id="vw3l">self:</h3>
  <p id="IVZ5">Когда вы видите &quot;<code>self:</code>&quot; перед методом, это означает, что вы вызываете метод на текущем объекте, но передаете его в качестве первого аргумента. Это позволяет вам явно указать, что метод вызывается на объекте &quot;<code>self</code>&quot;. Например, если у вас есть метод &quot;<code>SetName</code>&quot; и вы хотите вызвать его на объекте &quot;<code>player</code>&quot; с аргументом &quot;<code>John</code>&quot;, вы можете использовать &quot;<code>self:SetName(&quot;John&quot;)</code>&quot;.</p>
  <p id="yVEx"></p>
  <hr />
  <p id="WSgK"></p>
  <h2 id="0Ueb">Циклы:</h2>
  <pre id="xX5Y" data-lang="lua">#--Цикл while
local i = 1  -- Инициализируем переменную i со значением 1
while i &lt;= 5 do  -- Пока i меньше или равно 5, выполняем следующий блок кода
    print(&quot;Цикл while: &quot;, i)  -- Выводим значение переменной i
    i = i + 1  -- Увеличиваем значение переменной i на 1    
end

===================================================================================================================

#--Цикл for
for j = 1, 5 do  -- Итерируемся от 1 до 5 с шагом 1
    print(&quot;Цикл for: &quot;, j)  -- Выводим значение переменной j
end

===================================================================================================================

#--Цикл repeat...until
local k = 1  -- Инициализируем переменную k со значением 1
repeat  -- слово repeat обозначает &quot;повторять&quot;.
    print(&quot;Цикл repeat...until: &quot;, k)  -- Выводим значение переменной k
    k = k + 1  -- Увеличиваем значение переменной k на 1
until k &gt; 5  -- Повторяем цикл, пока k не станет больше 5
</pre>
  <p id="xX5Y"></p>
  <hr />
  <p id="6deY"></p>
  <h3 id="BWHf">Цикл For:</h3>
  <p id="CQYU">Цикл for: Этот цикл используется для итерации через коллекции или задания диапазона значений.</p>
  <pre id="Kcb0" data-lang="lua">#--Итерация по таблице
local players = {&quot;Player1&quot;, &quot;Player2&quot;, &quot;Player3&quot;}  -- Создаем таблицу players с элементами &quot;Player1&quot;, &quot;Player2&quot; и &quot;Player3&quot;
for i, player in ipairs(players) do  -- Итерируемся по таблице players, присваивая индекс элемента переменной i и значение элемента переменной player
    print(i, player)  -- Выводим индекс и значение элемента таблицы
end

#--Итерация по диапазону значений
for i = 1, 10, 2 do  -- Итерируемся от 1 до 10 с шагом 2
    print(i)  -- Выводим значение переменной i
end
</pre>
  <p id="3r1D">В первом примере цикл for будет выполняться для каждого элемента таблицы <code>players</code>, выводя индекс и значение элемента. Во втором примере цикл for будет выводить нечетные числа от 1 до 10.</p>
  <p id="Uudr"></p>
  <p id="O7MF"></p>
  <h2 id="iKmW">Скобки для группировки условий:</h2>
  <p id="HguH">Если вы используете методы объектов с помощью двоеточия (<code>:</code>), такие как <code>riot:GetClass()</code>, то скобки вокруг всего условного выражения не требуются. Однако, если вы хотите добавить несколько условий с использованием логических операторов, таких как <code>and</code>, <code>or</code>, то для улучшения читаемости кода рекомендуется использовать скобки для группировки условий. Это особенно полезно, когда условия становятся сложнее и включают в себя несколько логических операторов.</p>
  <p id="nqJD">Вот пример кода с использованием скобок для <strong>группировки условий:</strong></p>
  <pre id="NK7b" data-lang="lua">if (riot:GetClass() == &quot;vj_riot&quot; and spak:IsValid()) then -- Ваш код здесь 
end</pre>
  <p id="NKgr">Скобки здесь используются для того, чтобы было ясно, что условие <code>spak:IsValid()</code> должно быть выполнено вместе с условием <code>riot:GetClass() == &quot;vj_riot&quot;</code>. Если бы вы опустили скобки, то порядок выполнения условий мог бы измениться, что может привести к непредсказуемым результатам.</p>
  <p id="x9zP"></p>
  <hr />
  <p id="Yfnl"></p>
  <h2 id="O8KZ">Будем использовать нейросеть Phind для создания метода.</h2>
  <p id="sVhn"></p>
  <ul id="GCZ0">
    <li id="4uwS">Пиши слово &quot;пиши по русский&quot; - вы зададите диалог на русском языке. </li>
  </ul>
  <blockquote id="HNHA">Phind</blockquote>
  <blockquote id="fVv2">Конечно, я могу писать по-русски. Чем могу помочь?</blockquote>
  <ul id="T4mz">
    <li id="x0EY">Пиши - &quot;будем создавать метод на Garrys Mod Lua API. С использованием &quot;ENT:&quot;, self и аргументов.&quot;</li>
  </ul>
  <blockquote id="XBcZ">Phind</blockquote>
  <blockquote id="hg47">Хорошо, мы будем создавать метод на Garrys Mod Lua API с использованием &quot;ENT:&quot;, self и аргументов. Что именно должен делать этот метод? Нужно ли вам объяснить, как работает Garrys Mod Lua API или вы уже знакомы с ним?</blockquote>
  <p id="No2z">Пиши - &quot;entity - &quot;weapon_pist&quot; является огнестрельным оружием которое должно применяться против entity - &quot;NPCgude&quot;.&quot;<br /></p>
  <blockquote id="wqiM">Phind SOLVE</blockquote>
  <blockquote id="tWNV"><strong>final task:</strong> Создайте метод, который будет использовать оружие &#x27;weapon_pist&#x27; для атаки сущности &#x27;NPCgude&#x27;.</blockquote>
  <p id="W0QM"></p>
  <p id="e6F0"></p>
  <blockquote id="Q1pg">Phind</blockquote>
  <blockquote id="tuTl">Хорошо, чтобы создать метод, который будет использовать оружие &#x27;weapon_pist&#x27; для атаки сущности &#x27;NPCgude&#x27;, мы можем использовать метод &#x27;ENT:FireBullets()&#x27; в Garrys Mod Lua API, чтобы стрелять пулями с оружия.</blockquote>
  <blockquote id="ZGBS">Вам понадобится определить этот метод внутри своей сущности (Entity) и передать как аргументы используемое оружие и цель для атаки.</blockquote>
  <blockquote id="AN2r">Вот пример, как выглядит метод, который вы можете использовать:</blockquote>
  <pre id="BtP7" data-lang="lua">function ENT:AttackNPCgude()
    local weapon = self:GetWeapon(&quot;weapon_pist&quot;) -- Получить ссылку на оружие &#x27;weapon_pist&#x27;
    local target = ents.FindByClass(&quot;NPCgude&quot;)[1] -- Найти первую сущность класса &#x27;NPCgude&#x27;

    if IsValid(weapon) and IsValid(target) then
        local bullet = {}
        bullet.Num = 1 -- Количество пуль
        bullet.Src = self:GetShootPos() -- Позиция выстрела из оружия
        bullet.Dir = (target:GetPos() - self:GetShootPos()):GetNormalized() -- Направление стрельбы
        bullet.Spread = Vector(0, 0, 0) -- Разброс пуль
        bullet.Tracer = 1 -- Включить трассировку
        bullet.Force = 10 -- Сила пули
        bullet.Damage = 10 -- Урон пули

        weapon:FireBullets(bullet) -- Выстрелить пулями
    end
end
</pre>
  <blockquote id="xxYX">В этом примере мы используем метод &#x27;<code>self:GetWeapon()</code>&#x27; для получения ссылки на оружие &#x27;<code>weapon_pist</code>&#x27;, а также метод &#x27;<code>ents.FindByClass()</code>&#x27; для поиска первой сущности класса &#x27;<code>NPCgude</code>&#x27;. Затем настраиваем параметры пули и используем метод &#x27;<code>weapon:FireBullets()</code>&#x27; для стрельбы.</blockquote>
  <blockquote id="DvOg">Вы можете вызвать этот метод из другой части кода своей сущности, как например из метода &#x27;<code>ENT:Think()</code>&#x27;, чтобы атаковать &#x27;<code>NPCgude</code>&#x27; с помощью оружия &#x27;<code>weapon_pist</code>&#x27;.</blockquote>
  <blockquote id="O9Yf">Надеюсь, это помогает вам создать метод для вашей задачи. Если у вас есть ещё вопросы, не стесняйтесь задавать.</blockquote>
  <p id="9Iy8"></p>
  <hr />
  <p id="lF9t"></p>
  <h3 id="HRsx">Итог в фото:</h3>
  <figure id="CdfH" class="m_original">
    <img src="https://img3.teletype.in/files/af/99/af99d93d-e503-433e-9643-c47cf7b828c1.png" width="832" />
  </figure>
  <figure id="QaH2" class="m_original">
    <img src="https://img2.teletype.in/files/15/52/1552c924-c1ba-4f03-a864-63db7239453f.png" width="935" />
  </figure>
  <figure id="ws07" class="m_original">
    <img src="https://img2.teletype.in/files/df/a2/dfa2d89e-a199-499e-a0fd-0e1c1c90ce92.png" width="841" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@garrys_mod_lua_api/gmod_lua_api</guid><link>https://teletype.in/@garrys_mod_lua_api/gmod_lua_api?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api</link><comments>https://teletype.in/@garrys_mod_lua_api/gmod_lua_api?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=garrys_mod_lua_api#comments</comments><dc:creator>garrys_mod_lua_api</dc:creator><title>Что такое Glua Garrys Mod Lua API </title><pubDate>Sun, 06 Aug 2023 12:02:03 GMT</pubDate><description><![CDATA[<img src="https://img3.teletype.in/files/ab/b3/abb32e7f-efee-45da-972e-6aacdbe233e9.jpeg"></img>Garry's Mod Lua API (Application Programming Interface) - это набор функций, классов и методов, доступных для использования в Lua-скриптах в Garry's Mod. Lua API позволяет разработчикам создавать пользовательские режимы игры, сущности, оружие и многое другое в Garry's Mod.]]></description><content:encoded><![CDATA[
  <figure id="gVMP" class="m_custom">
    <img src="https://img3.teletype.in/files/ab/b3/abb32e7f-efee-45da-972e-6aacdbe233e9.jpeg" width="446.1486325802616" />
  </figure>
  <nav>
    <ul>
      <li class="m_level_1"><a href="#FQbr">Вступление:</a></li>
      <li class="m_level_2"><a href="#524u">IDE среды разработки для использования в программировании:</a></li>
      <li class="m_level_2"><a href="#QJBj">Отладка кода:</a></li>
      <li class="m_level_2"><a href="#krkZ">Расположение папок в директории Garrys Mod:</a></li>
      <li class="m_level_2"><a href="#buJl">Расположение папок в папке Lua:</a></li>
    </ul>
  </nav>
  <h2 id="FQbr">Вступление:</h2>
  <p id="L4XX">Garry&#x27;s Mod Lua API (Application Programming Interface) - это набор функций, классов и методов, доступных для использования в Lua-скриптах в Garry&#x27;s Mod. Lua API позволяет разработчикам создавать пользовательские режимы игры, сущности, оружие и многое другое в Garry&#x27;s Mod.</p>
  <ol id="4M5g">
    <li id="OBQl">Garry&#x27;s Mod Lua API основан на языке программирования Lua и использует версию 5.1. Он включает в себя как стандартные функции Lua, так и дополнительные функции, специфичные для Garry&#x27;s Mod.</li>
    <li id="DZM4">Garry&#x27;s Mod Lua API подробно документирован на официальной вики Garry&#x27;s Mod. Эта вики предоставляет учебники, ресурсы и документацию о Garry&#x27;s Mod и его Lua API. Это ценный ресурс для изучения и понимания Garry&#x27;s Mod Lua API.</li>
  </ol>
  <h3 id="524u">IDE среды разработки для использования в программировании:</h3>
  <ul id="Q6JU">
    <li id="sVxW">Редакторы Lua: Для разработки Lua-скриптов для Garry&#x27;s Mod вы можете использовать различные текстовые редакторы или интегрированные среды разработки (IDE). Некоторые популярные варианты включают Notepad++, <u>Sublime Text</u> и <u>Visual Studio Code.</u> Эти редакторы часто предоставляют подсветку синтаксиса и другие функции, которые помогают в разработке GLua.</li>
  </ul>
  <h3 id="QJBj">Отладка кода:</h3>
  <ul id="Ff6N">
    <li id="0Skj">Отладка Lua: При работе с Lua-скриптами в Garry&#x27;s Mod важно иметь возможность отлаживать и устранять любые проблемы, которые могут возникнуть. Консоль в Garry&#x27;s Mod предоставляет сообщения об ошибках, которые указывают на файл, номер строки и возможные причины ошибок. Кроме того, ошибки Lua, с которыми сталкиваются игроки, регистрируются в файле clientside_errors.txt.</li>
  </ul>
  <h3 id="krkZ" data-align="center">Расположение папок в директории Garrys Mod:</h3>
  <figure id="Fwtv" class="m_custom" data-caption-align="center">
    <img src="https://img2.teletype.in/files/10/a7/10a7d73d-d19c-4ab1-86fc-530c776de6d0.jpeg" width="362.36749116607774" />
  </figure>
  <p id="RSz5">В Garry&#x27;s Mod Lua-скрипты и аддоны размещаются в определенных папках. Вот некоторые полезные расположения папок:</p>
  <ul id="QNCC">
    <li id="n12C">garrysmod\garrysmod\lua\ : </li>
  </ul>
  <p id="zxLh">&quot;garrysmod\garrysmod\lua\&quot; - Этот каталог используется для отдельных скриптовых файлов, которые можно открыть непосредственно в игре без дополнительной конфигурации.</p>
  <ul id="2FdP">
    <li id="NwSS">garrysmod\garrysmod\addons\ : </li>
  </ul>
  <p id="MeG5">&quot;garrysmod\garrysmod\addons\&quot; - Эта папка предназначена для аддонов, включая созданные вами пользовательские аддоны.</p>
  <ul id="gZ9S">
    <li id="meWp">garrysmod\garrysmod\gamemodes\ : </li>
  </ul>
  <p id="fT4G">&quot;garrysmod\garrysmod\gamemodes\&quot; - Эта папка используется для загрузки и установки игровых режимов, таких как DarkRP.</p>
  <p id="AJjV"></p>
  <h3 id="buJl" data-align="center">Расположение папок в папке Lua:</h3>
  <figure id="Yfkz" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/ac/65/ac656b49-e7e1-48ed-a0ac-ede5589d2e41.png" width="144" />
  </figure>
  <p id="qqPI">Наша целевая папка по теме - &quot;Lua&quot;. То что там написано касается кодинга &quot;Garry&#x27;s Mod Lua API&quot;.</p>
  <p id="OXqW">в данной папке размещаются следующие папки.</p>
  <ol id="545z">
    <li id="dGPi">autorun/ - Папка для автоматической загрузки и включения скриптов при запуске Lua, как на стороне клиента, так и на стороне сервера.</li>
    <li id="r9u2">autorun/client/ - Сценарии автозапуска только на стороне клиента.</li>
    <li id="1SjM">autorun/server/ - Скрипты только на сервере.</li>
    <li id="HSLR">autorun/properties/ - Папка для свойств в <a href="https://wiki.facepunch.com/gmod/The_Context_Menu" target="_blank">контекстном меню</a>.</li>
    <li id="a611">bin/ - Папка для внешних двоичных модулей. (<a href="https://wiki.facepunch.com/gmod/Creating_Binary_Modules" target="_blank">Создание двоичных модулей</a>)</li>
    <li id="dBlW">derma/ - Папка для утилит <a href="https://wiki.facepunch.com/gmod/derma" target="_blank">derma</a>.</li>
    <li id="MguQ">drive/ - Папка для системных классов <a href="https://wiki.facepunch.com/gmod/drive" target="_blank">диска</a>.</li>
    <li id="E0au">effects/ - Скрипты, размещенные здесь, будут автоматически загружены как эффекты Lua. (<a href="https://wiki.facepunch.com/gmod/util.Effect" target="_blank">использование.Эффект</a>)</li>
    <li id="W3cD">entities/ - Скрипты, размещенные здесь, будут автоматически загружены как SENTs. (<a href="https://wiki.facepunch.com/gmod/Structures/ENT" target="_blank">Structures/ENT</a>)</li>
    <li id="8sM9">includes/ - Папка для библиотек Lua и дополнительных материалов, используемых в других скриптах. Запускается первой.</li>
    <li id="vL8z">includes/extensions/ - находится в папке &quot;includes&quot; Папка для расширенных библиотек. Например, библиотека <a href="https://wiki.facepunch.com/gmod/table" target="_blank">таблиц</a> уже существует, но &quot;extensions/table.lua&quot; она расширяется.</li>
    <li id="eGNq">includes/modules/ - находится в папке &quot;includes&quot; Папка для библиотек.</li>
    <li id="IG7P">matproxy/ - Папка для материалов <a href="https://wiki.facepunch.com/gmod/matproxy" target="_blank">matproxy</a>.</li>
    <li id="0uyx">men/ - Папка, используемая для определения <a href="https://wiki.facepunch.com/gmod/States" target="_blank">состояния меню</a>.</li>
    <li id="S8Ea">postprocess/ - Запускается клиентом при запуске, обычно содержит эффекты постобработки в песочнице.</li>
    <li id="qaNH">skins/ - Папка для пользовательских <a href="https://wiki.facepunch.com/gmod/Derma_Skin_Creation" target="_blank">скинов derma</a>.</li>
    <li id="XdUG">vgui/ - Клиентская папка для панелей пользовательского интерфейса.</li>
    <li id="Nwdr">weapons/ - Скрипты, размещенные здесь, будут автоматически загружены в качестве оружия. (<a href="https://wiki.facepunch.com/gmod/Structures/SWEP" target="_blank">Structures/SWEP</a>)</li>
    <li id="EZg1">weapons/gmod_tool/stools/ - (Только для песочницы) Размещенные здесь скрипты будут автоматически загружены как инструменты. (<a href="https://wiki.facepunch.com/gmod/Structures/TOOL" target="_blank">Structures/TOOL</a>)</li>
  </ol>

]]></content:encoded></item></channel></rss>