Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- AddCSLuaFile( "cl_init.lua" )
- AddCSLuaFile("shared.lua")
- include('shared.lua')
- /*-----------------------------------------------
- *** Copyright (c) 2012-2018 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.
- -----------------------------------------------*/
- ENT.HullType = HULL_MEDIUM
- ENT.HasHull = true -- Set to false to disable HULL
- ENT.HullSizeNormal = true -- set to false to cancel out the self:SetHullSizeNormal()
- ENT.MovementType = VJ_MOVETYPE_AERIAL -- How does the SNPC move?
- ENT.VJ_NPC_Class = {"CLASS_SENTINEL", "CLASS_PLAYER_ALLY", "CLASS_HUMAN_PASSIVE", "CLASS_EARTH_FAUNA"} -- NPCs with the same class with be allied to each other
- ENT.SoundTbl_Breath = {}
- ENT.Aerial_AnimTbl_Calm = {"idleRelaxed"} -- Animations it plays when it's wandering around while idle
- ENT.Aerial_AnimTbl_Alerted = {"idleCombat"} -- Animations it plays when it's moving while alerted
- ENT.CanFlinch = 1 -- 0 = Don't flinch | 1 = Flinch at any damage | 2 = Flinch only from certain damages
- ENT.FlinchChance = 1 -- Chance of it flinching from 1 to x | 1 will make it always flinch
- ENT.NextMoveAfterFlinchTime = 0
- ENT.NextFlinchTime = 0.5 -- How much time until it can flinch again?
- ENT.AnimTbl_CallForHelp = {} -- Call For Help Animations
- ENT.AnimTbl_Flinch = {"hurt01", "hurt02", "hurt03"}
- --Fly Variables
- ENT.flyRadius = 150 //weird but necessary variable. Both controls at what range the sentinel will flee from target, and how much they can move around above their target
- ENT.maintainHeight = Vector(0, 0, 350 + ENT.flyRadius) //How far above should we aim to be above the target
- ENT.maxPitch = 25
- ENT.maxRoll = 25
- ENT.enableAI=true
- --Damaged
- ENT.Bleeds = false -- Does the SNPC bleed? (Blood decal, particle, etc.)
- ENT.GibOnDeathDamagesTable = {"All"} -- Damages that it gibs from | "UseDefault" = Uses default damage types | "All" = Gib from any damage
- ENT.BloodColor = "Oil"
- ENT.HasGibDeathParticles = false -- Does it spawn particles on death or when it gibs? | Mostly used for the settings menu
- ENT.HasDeathRagdoll = true -- If set to false, it will not spawn the regular ragdoll of the SNPC
- ENT.DeathCorpseModel = {""} -- The corpse model that it will spawn when it dies | Leave empty to use the NPC's model | Put as many models as desired, the base will pick a random one.
- ENT.BecomeEnemyToPlayer = true
- ENT.BecomeEnemyToPlayerLevel = 4 -- How many times does the player have to hit the SNPC for it to become enemy?
- ENT.SoundTbl_Death = {"npc_vj_sent_sentinel/sentinel_death/quick1.wav", "npc_vj_sent_sentinel/sentinel_death/quick2.wav", "npc_vj_sent_sentinel/sentinel_death/quick3.wav", "npc_vj_sent_sentinel/sentinel_death/quick4.wav"}
- ENT.HasItemDropsOnDeath = true -- Should it drop items on death?
- ENT.ItemDropsOnDeathChance = 1
- ENT.ItemDropsOnDeath_EntityList = {"weapon_vj_sent_sentinelbeam"}
- ENT.AnimTbl_Death = {""}
- ENT.HasDeathAnimation = true
- ENT.DeathAnimationTime = 0
- --Vision--
- ENT.NoChaseAfterCertainRange = true -- Should the SNPC not be able to chase when it's between number x and y?
- ENT.SightDistance = 10000 -- How far it can see
- ENT.SightAngle = 240 -- The sight angle | Example: 180 would make the it see all around it | Measured in degrees and then converted to radians
- ENT.ConstantlyFaceEnemy = true
- ENT.ConstantlyFaceEnemy_IfAttacking = true -- Should it face the enemy when attacking?
- ENT.NoChaseAfterCertainRange_FarDistance = ENT.maintainHeight.z - ENT.flyRadius -- How far until it can chase again?
- ENT.NoChaseAfterCertainRange_CloseDistance = 0
- --Movement--
- ENT.Aerial_FlyingSpeed_Calm = 160 -- The speed it should fly with, when it's wandering, moving slowly, etc. | Basically walking campared to ground SNPCs
- ENT.Aerial_FlyingSpeed_Alerted = 160 --
- ENT.TurningSpeed = 15 -- How fast it can turn
- ENT.AA_ConstantlyMove = true
- ENT.PoseParameterLooking_TurningSpeed = 1 -- How fast does the parameter turn?
- --Ranged Attack--
- ENT.HasMeleeAttack = false -- Should the SNPC have a melee attack?
- ENT.HasRangeAttack = true -- Should the SNPC have a range attack?
- ENT.AnimTbl_RangeAttack = {}
- ENT.RangeDistance = 1500
- ENT.damage = 30 --How much damage is dealt
- ENT.beamDuration = 2
- ENT.beamTickRate = 0.1 --How often (in seconds) the damage is dealt
- ENT.TimeUntilRangeAttackProjectileRelease = ENT.beamTickRate -- How much time until the projectile code is ran?
- ENT.RangeAttackReps = (ENT.beamDuration/ENT.beamTickRate)
- ENT.NextRangeAttackTime = 4 -- How much time until it can use a range attack?
- ENT.NextRangeAttackTime_DoRand = false -- False = Don't use random time | Number = Picks a random number between the regular timer and this timer
- ENT.RangeAttackExtraTimers = {}
- ENT.RangeAttackAnimationFaceEnemy = false
- ENT.DisableRangeAttackAnimation = true -- if true, it will disable the animation code
- ENT.DisableDefaultRangeAttackCode = true -- When true, it won't spawn the range attack entity, allowing you to make your own
- ENT.RangeAttackAnimationStopMovement = false -- Should it stop moving when performing a range attack?
- ENT.AnimTbl_RangeAttack = {} -- Range Attack Animations
- ENT.RangeToMeleeDistance = 0 -- How close does it have to be until it uses melee?
- --Death Variables
- ENT.dead = false
- ENT.fall = false
- ENT.gib = false
- ENT.timeDeath = false
- ENT.ignite = false
- ENT.randomFire = false
- ENT.uniqueId = ""
- --Variant Code--
- ENT.Model = {"models/sentinels/sentinel_agressor.mdl"} -- The game will pick a random model from the table when the SNPC is spawned | Add as many as you want
- ENT.hullMaxHealth = 10
- ENT.hullHealth = ENT.hullMaxHealth
- ENT.shieldMaxHealth = 30
- ENT.shieldHealth = ENT.shieldMaxHealth
- ENT.shieldRegenAmount = 1
- ENT.shieldRegenSpeed = .1
- ENT.shieldRegenDelay = 5
- ENT.shieldRegen = false
- ENT.modelColor = Color(255, 255, 255, 255)
- ENT.trailColor = Color(100,170,225,150)
- ENT.shieldColor = Color(255, 255, 255, 255)
- ENT.corpseColor = Color(100, 100, 100, 255)
- ENT.StartHealth = ENT.hullMaxHealth + ENT.shieldMaxHealth//GetConVarNumber("vj_dum_dummy_h")
- ENT.soundTable = {
- engineSound = "npc_vj_sent_sentinel/sent_eng1loop.wav",
- enginePitch = 100,
- engineVolume = 0.4,
- firingSound = "npc_vj_sent_sentinel/sentinel_gun/sentGunLoop1.wav",
- firingPitch = 100,
- firingVolume = 1,
- }
- ENT.gibTable = {
- "models/sentinels/sentinel_a_fuselage.mdl",
- "models/sentinels/sentinel_a_head.mdl",
- "models/sentinels/sentinel_a_arm.mdl",
- "models/sentinels/sentinel_a_arm.mdl",
- "models/gibs/metal_gib5.mdl",
- "models/gibs/metal_gib5.mdl",
- "models/gibs/metal_gib5.mdl",
- "models/gibs/metal_gib5.mdl",
- "models/combine_helicopter/bomb_debris_3.mdl",
- "models/combine_helicopter/bomb_debris_3.mdl",
- "models/combine_helicopter/bomb_debris_3.mdl"
- }
- ENT.engineSound = "npc_vj_sent_sentinel/sent_eng1loop.wav"
- ENT.engine = ""
- ENT.sentRepeat = ""
- ENT.spriteTrail = ""
- ENT.corpseModel = ""
- local attacker = ""
- local spawnParticles = true
- function ENT:CustomOnInitialize()
- self.uniqueId = tostring(self:GetCreationID()) //convenient unique identifier for timers
- timer.Create("randomChase"..self.uniqueId, 5, 0, function() if (IsValid(self)) then self.maintainHeight = Vector(math.random(-700, 700),math.random(-700, 700), 150 + math.random(-100, 300) + self.flyRadius) end end)
- self.engine = CreateSound(self, self.engineSound)
- self.corpseModel = self:GetModel()
- self.damage = self.damage * GetConVarNumber("vj_sent_sentinelDamageModifier")
- self:UseConvars()
- self:SpawnLights()
- self:TypeOfDeath()
- self:InitializeSound()
- self:SetColor(self.modelColor)
- self:SetCollisionBounds(Vector(33, 33, 26), Vector(-33, -33, -30))
- self.spriteTrail = util.SpriteTrail(self, 0,self.trailColor,true,50,10,2,20,"trails/smoke")
- end
- function ENT:InitializeSound()
- self.sentRepeat = CreateSound(self, self.soundTable["firingSound"])
- self.engine = CreateSound(self, self.soundTable["engineSound"])
- self.engine:Play()
- self.engine:ChangePitch(self.soundTable["enginePitch"])
- self.engine:ChangeVolume(self.soundTable["engineVolume"])
- end
- function ENT:CustomOnAlert(argent)
- //self:SetSequence("idleToCombat")
- //timer.Simple(1, function() self:SetSequence("idleCombat") end)
- end
- function ENT:TypeOfDeath()
- if (math.random(0, 100)) <= GetConVar("vj_sent_chanceFall"):GetInt() then self.fall=true end
- if (math.random(0, 100)) <= GetConVar("vj_sent_chanceGib"):GetInt() then self.gib=true end
- if (math.random(0, 100)) <= GetConVar("vj_sent_chanceTimedDeath"):GetInt() then self.timeDeath=true end
- if (math.random(0, 100)) <= GetConVar("vj_sent_chanceRandomFire"):GetInt() then self.randomFire=true end
- if (math.random(0, 100)) <= GetConVar("vj_sent_chanceFire"):GetInt() then self.ignite=true end
- end
- ENT.vAlive = 0
- function ENT:CustomOnTakeDamage_BeforeDamage(dmginfo,hitgroup)
- self.vAlive = self:GetVelocity() * 2.5
- attacker = dmginfo:GetAttacker()
- self.shieldRegen = false //disable any current active shield regen
- if (self.shieldHealth <= dmginfo:GetDamage() && self.shieldHealth > 0) then
- if (spawnParticles == true) then
- local effect = EffectData()
- effect:SetOrigin(self:GetPos())
- self:SphereEffect(true)
- timer.Simple(0.1, function()
- if (IsValid(self)) then
- self:SphereEffect(false)
- util.Effect("shieldBreakFX", effect)
- end
- end)
- end
- end
- if (self.shieldHealth > 0) then
- self.shieldHealth = math.Clamp(self.shieldHealth - dmginfo:GetDamage(), 0, self.shieldMaxHealth)
- elseif (self.shieldHealth <= 0 or self:Health() < dmginfo:GetDamage()) then
- self.hullHealth = self.hullHealth - dmginfo:GetDamage()
- end
- if (self.hullHealth + self.shieldHealth < dmginfo:GetDamage() && !self.dead && self.fall) then
- self:FallDeath()
- elseif (self.shieldHealth > 0 && self.shieldHealth > dmginfo:GetDamage() && !self.dead) then
- self:SphereEffect(true)
- end
- if (timer.Exists("regendelay"..self.uniqueId)) then
- timer.Destroy("regendelay"..self.uniqueId)
- end
- timer.Create("regendelay"..self.uniqueId, self.shieldRegenDelay,0, function() if(IsValid(self)) then self:RegenShield() end end)
- end
- function ENT:RegenShield() //Regenerate the shield
- self.shieldRegen = true
- timer.Create("regen"..self.uniqueId, self.shieldRegenSpeed, (self.shieldMaxHealth - self.shieldHealth)/self.shieldRegenAmount , function()
- if (self.shieldRegen && !self.dead && (self.shieldHealth < self.shieldMaxHealth)) then
- self.shieldHealth = self.shieldHealth + self.shieldRegenAmount
- self:SetHealth(self:Health() + self.shieldRegenAmount)
- self:SphereEffect(true)
- end
- end)
- end
- /* //copy-paste used to test certain variables
- PrintMessage(3, "-------------------")
- PrintMessage(3, "[var]: "..tostring([var]))
- PrintMessage(3, "-------------------")
- */
- function ENT:FallDeath() //Make NPC limp and fall to their death
- self.enableAI=false
- self:AddCallback("PhysicsCollide", function()
- if (self.dead && !self.timeDeath) then
- self:TakeDamage(99999, attacker)
- util.ScreenShake( self:GetPos(), 50, 500, 1.2, 500 )
- elseif (self.dead && self.timeDeath) then
- if !(timer.Exists("destroy"..self.uniqueId)) then
- timer.Create("destroy"..self.uniqueId,math.random(0.5,3),1,function() if (IsValid(self)) then self:TakeDamage(99999, attacker) util.ScreenShake( self:GetPos(), 50, 500, 1.2, 500 ) end end)
- end
- end end)
- local effect = EffectData()
- self.spriteTrail:Remove()
- if (GetConVarNumber("vj_sent_useParticles")==1) then timer.Create("FireFallFX"..self.uniqueId, 0.05, 100, function() if (IsValid(self) && self:GetVelocity().z<-100) then effect:SetOrigin(self:GetPos()) util.Effect("fireFallFX", effect) end end) end
- self.RangeAttackReps = 0
- self.ConstantlyFaceEnemy = false
- self.Behavior = VJ_BEHAVIOR_PASSIVE
- if (self.randomFire) then self:RandomFire() end
- self.CanFlinch = 0
- self.dead = true
- self:SetHealth(99999)
- self:SetMoveType(MOVETYPE_VPHYSICS)
- self:PhysicsInit(SOLID_VPHYSICS)
- self:GetPhysicsObject():Wake()
- self:GetPhysicsObject():AddAngleVelocity(Vector(math.random(0, 500), math.random(0, 500), math.random(0, 500)))
- self:GetPhysicsObject():AddVelocity(self.vAlive)
- self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
- end
- function ENT:UseConvars()
- if (GetConVar("vj_sent_sentinelsDropWeapon"):GetInt() == 1) then
- self.HasItemDropsOnDeath = true
- elseif (GetConVar("vj_sent_sentinelsDropWeapon"):GetInt() == 0) then
- self.HasItemDropsOnDeath = false
- end
- if (GetConVar("vj_sent_sentinelsFriendly"):GetInt() == 1) then
- self.PlayerFriendly = true
- self.FriendsWithAllPlayerAllies = true
- self.VJ_NPC_Class = {"CLASS_SENTINEL", "CLASS_PLAYER_ALLY", "CLASS_HUMAN_PASSIVE", "CLASS_EARTH_FAUNA"}
- elseif (GetConVar("vj_sent_sentinelsFriendly"):GetInt() == 0) then
- self.PlayerFriendly = false
- self.FriendsWithAllPlayerAllies = false
- self.VJ_NPC_Class = {"CLASS_SENTINEL", "CLASS_EARTH_FAUNA"}
- for _,v in pairs(ents.GetAll()) do
- if v:IsNPC() && (v.PlayerFriendly) then
- if (string.StartWith(v:GetClass(), "npc_vj_sent")) then
- table.insert(v.VJ_AddCertainEntityAsEnemy,self)
- v:VJ_DoSetEnemy(self,true,true)
- v:SetEnemy(self)
- end
- end
- //test code for making sentinels hunt each other
- end
- end
- if (GetConVar("vj_sent_useParticles"):GetInt() == 0) then
- spawnParticles = false
- elseif (GetConVar("vj_sent_useParticles"):GetInt() == 1) then
- spawnParticles = true
- end
- end
- ENT.shieldFXEnt = ""
- ENT.shieldIsOn = false
- function ENT:SphereEffect(FXOn) //Spawn a sphere around sentinel when taking damage and quickly remove it
- if (FXOn==true) then
- if (self.shieldIsOn==false) then
- self.shieldIsOn=true
- self.shieldFXEnt = ents.Create("prop_physics")
- self.shieldFXEnt:SetModel( "models/sentinels/sentinel_a_shield.mdl" )
- self.shieldFXEnt:SetMaterial("models/alyx/emptool_glow")
- self.shieldFXEnt.RenderGroup = RENDERGROUP_TRANSLUCENT
- self.shieldFXEnt:SetColor(self.shieldColor)
- self.shieldFXEnt:SetModelScale(1.2,0)
- self.shieldFXEnt:SetCollisionGroup(1) //allows NPC to see through it's shield
- self.shieldFXEnt:SetMoveParent(self)
- if (self.shieldRegen) then
- self.shieldFXEnt:SetMaterial("models/props_combine/portalball001_sheet")
- end
- self.shieldFXEnt:SetPos(self:GetPos())
- self.shieldFXEnt:Spawn()
- //timer.Simple(.5,function() if (IsValid(self)) then self.shieldFXEnt:Remove() end end)
- end
- if (timer.Exists("shieldFX"..self.uniqueId)) then
- timer.Remove("shieldFX"..self.uniqueId)
- timer.Create("shieldFX"..self.uniqueId, .5, 1, function()
- if (IsValid(self) && IsValid(self.shieldFXEnt)) then
- self.shieldFXEnt:Remove()
- self.shieldIsOn=false
- end
- end)
- else
- timer.Create("shieldFX"..self.uniqueId, .5, 1, function()
- if (IsValid(self) && IsValid(self.shieldFXEnt)) then
- self.shieldFXEnt:Remove()
- self.shieldIsOn=false
- end
- end)
- end
- elseif (FXOn==false) then
- if (IsValid(self.shieldFXEnt)) then self.shieldFXEnt:Remove() self.shieldIsOn=false end
- end
- end
- function ENT:SpawnLights() //Spawn any light sprites around the sentinel
- local light = ents.Create("env_glow")
- light:SetParent(self, 1)
- light:SetKeyValue("rendermode", "5")
- light:SetKeyValue("renderamt", "150")
- light:SetKeyValue("model","orangecore2.vmt")
- light:SetKeyValue("rendercolor","0 155 255")
- light:SetKeyValue("scale","0.2")
- light:Spawn()
- light:Activate()
- light:SetPos(self:GetShootPos() + self:GetForward() * 31 + Vector(0, 0, -2))
- end
- // Code to force the sentinel to look at the enemy (in pitch). Doesn't work while actively firing at the enemy currently and/or if the sentinel is falling.
- //Test for pitch, yaw when moving
- function ENT:CustomOn_PoseParameterLookingCode(pitch,yaw,roll) //helicopter-like movement, finally working!
- if (self.VJ_IsBeingControlled) then return end
- if (self:GetVelocity():Length() <= 0) then return end
- if (self:GetAimVector():Length() <= 0) then return end
- if (self:GetVelocity():Length() > 0) then
- local forwardFlat = Vector(self:GetVelocity().x, self:GetVelocity().y, 0) + Vector(1, 1, 0)
- local rightOrLeft = 1
- local aimFlat = Vector(self:GetAimVector().x, self:GetAimVector().y, 0) Vector(1.1, 1, 0) //adding something stops a nil math error, needs fixing
- if ((forwardFlat:Cross(aimFlat)).z > 0) then
- rightOrLeft = 1
- elseif ((forwardFlat:Cross(aimFlat)).z <= 0) then
- rightOrLeft = -1
- end
- local totResult = math.deg(math.acos((forwardFlat:Dot(aimFlat))/(forwardFlat:Length()*aimFlat:Length())))
- self:SetAngles(Angle(math.Clamp((self:GetAngles().x + self:Lerp3(totResult/180, self.maxPitch, 0, -self.maxPitch)), -self.maxPitch, self.maxPitch), self:GetAngles().y, (self:GetAngles().z + self:Lerp3((totResult)/180, 0, self.maxRoll*rightOrLeft, 0)), -self.maxRoll, self.maxRoll))
- end
- end
- function ENT:CreateCustomCorpse()
- local corpse = ents.Create("prop_physics")
- corpse:SetModel(self.corpseModel)
- corpse:SetColor(self.corpseColor)
- corpse:PhysicsInit(SOLID_VPHYSICS)
- corpse:GetPhysicsObject():Wake()
- corpse:SetPos(self:GetPos())
- corpse:SetAngles(self:GetAngles())
- corpse:GetPhysicsObject():AddAngleVelocity(Vector(math.random(0, 500), math.random(0, 500), math.random(0, 500)))
- corpse:GetPhysicsObject():AddVelocity(self.vAlive)
- corpse.RenderGroup = RENDERGROUP_BOTH
- corpse.ignite = self.ignite
- local effect = EffectData()
- effect:SetOrigin(corpse:GetPos())
- timer.Create("corpse"..self.uniqueId,2.5,16,function () if (IsValid(corpse)) then effect:SetOrigin(corpse:GetPos()) if (spawnParticles == true) then util.Effect("cball_explode",effect) end corpse:EmitSound(Sound("npc_vj_sent_sentinel/sentinel_welder_impact/weld13.wav")) end end)
- timer.Simple(2.5,function() if (IsValid(corpse) && corpse.ignite) then corpse:Ignite() end end)
- timer.Simple(40, function () if (IsValid(corpse)) then corpse:Remove() end end)
- end
- function ENT:CustomOnPriorToKilled(dmginfo,hitgroup) //spark effects messing up
- util.BlastDamage(self,self,self:GetPos(),50,200)
- if (spawnParticles == true) then
- local effect = EffectData()
- effect:SetOrigin(self:GetPos())
- util.Effect("deathFireFX", effect)
- util.Effect("cball_explode",effect)
- end
- ParticleEffect("explosion_turret_break",self:GetPos(),Angle(0,0,0),nil)
- if (!self.gib) then
- self:CreateCustomCorpse()
- end
- end
- function ENT:Lerp3(t, a, b, c)
- if (t < 0.5) then
- return Lerp(t*2, a, b)
- elseif (t >= 0.5) then
- return Lerp((t-0.5)*2, b, c)
- end
- end
- function ENT:SetUpGibesOnDeath(dmginfo,hitgroup) //Gib a bunch on death
- local ent = {}
- if (self.gib) then
- for k,v in pairs(self.gibTable) do
- ent[k] = self:CreateGibEntity("obj_vj_sent_gib",self.gibTable[k])
- ent[k]:SetColor(self.corpseColor)
- ent[k]:GetPhysicsObject():AddAngleVelocity(Vector(math.random(-100, 100),math.random(-100, 100), math.random(75, 250)))
- ent[k]:GetPhysicsObject():AddVelocity(Vector(math.random(-100, 100),math.random(-100, 100), math.random(75, 250)))
- local effect=EffectData()
- if (GetConVarNumber("vj_sent_useParticles")==1) then timer.Create("FireFallFXSmall"..self.uniqueId..k, 0.025, 300, function() if (IsValid(ent[k]) && ent[k]:GetVelocity():Length()>50) then effect:SetOrigin(ent[k]:GetPos()) util.Effect("fireFallFXSmall", effect) end end) end
- end
- if (self.ignite) then ent[1]:Ignite() end
- end
- end
- function ENT:CustomRangeAttackCode()
- if (self.dead) then self:BeamThing(false) return end
- if IsValid(self:GetEnemy()) && !self:GetEnemy():Visible(self) then
- self:SetNWBool("firing",true)
- return false
- end
- self:SetNWVector("testvector",self:GetEnemy():GetPos()+self:GetEnemy():OBBCenter()) --used to draw a beam from current pos to enemy pos in cl_init.lua
- self:GetEnemy():TakeDamage((self.beamTickRate*self.damage/self.beamDuration),self,self)
- if (!timer.Exists("firing"..self.uniqueId)) then
- self:BeamThing(true)
- timer.Create("firing"..self.uniqueId, self.beamDuration,0, function() //purely visual
- if (IsValid(self)) then
- self:BeamThing(false)
- timer.Destroy("firing"..self.uniqueId)
- end
- end)
- end
- return false
- end
- function ENT:RandomFire()
- local timesToFire = math.random(3, 12)
- timer.Create("RandomFireOn"..self.uniqueId, .4, timesToFire, function()
- if (IsValid(self)) then
- self:SetNWVector("testvector", self:GetShootPos() + self:GetForward()*1500)
- self:BeamThing(true)
- end
- end)
- timer.Create("RandomFireOff"..self.uniqueId, .5, timesToFire, function()
- if (IsValid(self)) then
- self:BeamThing(false)
- end
- end)
- end
- function ENT:CustomOnRemove()
- self.engine:Stop()
- if (self.sentRepeat:IsPlaying()) then self.sentRepeat:Stop() end
- if (timer.Exists("FireFallFX"..self.uniqueId)) then timer.Destroy("FireFallFX"..self.uniqueId) end
- if (timer.Exists("regen"..self.uniqueId)) then timer.Destroy("regen"..self.uniqueId) end
- if (timer.Exists("regendelay"..self.uniqueId)) then timer.Destroy("regendelay"..self.uniqueId) end
- end
- //function ENT:Construct()
- //end
- function ENT:BeamThing(beamOn)
- if (beamOn) then
- self:SetNWBool("firing",true)
- self:EmitSound("npc_vj_sent_sentinel/sentinel_gun/in.wav")
- self.sentRepeat:Play()
- self.sentRepeat:ChangePitch(self.soundTable["firingPitch"])
- self.sentRepeat:ChangeVolume(self.soundTable["firingVolume"])
- elseif (!beamOn) then
- self:SetNWBool("firing", false)
- self.sentRepeat:Stop()
- self:EmitSound("npc_vj_sent_sentinel/sentinel_gun/out.wav")
- end
- end
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------
- -------------------------------------------Modified Existing Functions-------------------------------------------------------------------------
- function ENT:CreateGibEntity(Ent,Models,Tbl_Features,CustomCode)
- // self:CreateGibEntity("prop_ragdoll","",{Pos=self:LocalToWorld(Vector(0,3,0)),Ang=self:GetAngles(),Vel=})
- if self.AllowedToGib == false then return end
- Ent = Ent or "prop_ragdoll"
- if Models == "UseAlien_Small" then Models = {"models/gibs/xenians/sgib_01.mdl","models/gibs/xenians/sgib_02.mdl","models/gibs/xenians/sgib_03.mdl"} end
- if Models == "UseAlien_Big" then Models = {"models/gibs/xenians/mgib_01.mdl","models/gibs/xenians/mgib_02.mdl","models/gibs/xenians/mgib_03.mdl","models/gibs/xenians/mgib_04.mdl","models/gibs/xenians/mgib_05.mdl","models/gibs/xenians/mgib_06.mdl","models/gibs/xenians/mgib_07.mdl"} end
- if Models == "UseHuman_Small" then Models = {"models/gibs/humans/sgib_01.mdl","models/gibs/humans/sgib_02.mdl","models/gibs/humans/sgib_03.mdl"} end
- if Models == "UseHuman_Big" then Models = {"models/gibs/humans/mgib_01.mdl","models/gibs/humans/mgib_02.mdl","models/gibs/humans/mgib_03.mdl","models/gibs/humans/mgib_04.mdl","models/gibs/humans/mgib_05.mdl","models/gibs/humans/mgib_06.mdl","models/gibs/humans/mgib_07.mdl"} end
- Models = VJ_PICKRANDOMTABLE(Models)
- local vTbl_BloodType = "Red"
- if VJ_HasValue({"models/gibs/xenians/sgib_01.mdl","models/gibs/xenians/sgib_02.mdl","models/gibs/xenians/sgib_03.mdl","models/gibs/xenians/mgib_01.mdl","models/gibs/xenians/mgib_02.mdl","models/gibs/xenians/mgib_03.mdl","models/gibs/xenians/mgib_04.mdl","models/gibs/xenians/mgib_05.mdl","models/gibs/xenians/mgib_06.mdl","models/gibs/xenians/mgib_07.mdl"},Models) then
- vTbl_BloodType = "Yellow"
- end
- vTbl_Features = Tbl_Features or {}
- vTbl_Position = vTbl_Features.Pos or self:GetPos() +self:OBBCenter()
- vTbl_Angle = vTbl_Features.Ang or Angle(math.Rand(-180,180),math.Rand(-180,180),math.Rand(-180,180)) //self:GetAngles()
- vTbl_Velocity_NoDamageForce = vTbl_Features.Vel_NoDmgForce or false -- If set to true, it won't add the damage force to the given velocity
- vTbl_Velocity = vTbl_Features.Vel or Vector(math.Rand(-100,100),math.Rand(-100,100),math.Rand(150,250)) -- Used to set the velocity | "UseDamageForce" = To use the damage's force only
- if self.LatestDmgInfo != nil then
- local dmgforce = self.LatestDmgInfo:GetDamageForce()/70
- if vTbl_Velocity_NoDamageForce == false && vTbl_Features.Vel != "UseDamageForce" then
- vTbl_Velocity = vTbl_Velocity + dmgforce
- end
- if vTbl_Features.Vel == "UseDamageForce" then
- vTbl_Velocity = dmgforce
- end
- end
- vTbl_AngleVelocity = vTbl_Features.AngVel or Vector(math.Rand(-200,200),math.Rand(-200,200),math.Rand(-200,200)) -- Angle velocity, how fast it rotates as it's flying
- vTbl_BloodType = vTbl_Features.BloodType or vTbl_BloodType -- Certain entities such as the VJ Gib entity, you can use this to set its gib type
- vTbl_BloodDecal = vTbl_Features.BloodDecal or "Default" -- The decal it spawns when it collides with something, leave empty to let the base decide
- vTbl_NoFade = vTbl_Features.NoFade or false -- Should it fade away and delete?
- vTbl_RemoveOnCorpseDelete = vTbl_Features.RemoveOnCorpseDelete or false -- Should the entity get removed if the corpse is removed?
- local gib = ents.Create(Ent)
- gib:SetModel(Models)
- gib:SetPos(vTbl_Position)
- gib:SetAngles(vTbl_Angle)
- if gib:GetClass() == "obj_vj_gib" then
- gib.BloodType = vTbl_BloodType
- gib.Collide_Decal = vTbl_BloodDecal
- end
- gib:Spawn()
- gib:Activate()
- gib.IsVJBase_Gib = true
- gib.RemoveOnCorpseDelete = vTbl_RemoveOnCorpseDelete
- if GetConVarNumber("vj_npc_gibcollidable") == 0 then gib:SetCollisionGroup(1) end
- local phys = gib:GetPhysicsObject()
- if IsValid(phys) then
- //phys:SetMass(60)
- phys:AddVelocity(vTbl_Velocity)
- phys:AddAngleVelocity(vTbl_AngleVelocity)
- end
- cleanup.ReplaceEntity(gib)
- if GetConVarNumber("vj_npc_fadegibs") == 1 && vTbl_NoFade == false then
- if gib:GetClass() == "prop_ragdoll" then gib:Fire("FadeAndRemove","",GetConVarNumber("vj_npc_fadegibstime")) end
- if gib:GetClass() == "prop_physics" then gib:Fire("kill","",GetConVarNumber("vj_npc_fadegibstime")) end
- end
- if vTbl_RemoveOnCorpseDelete == true then//self.Corpse:DeleteOnRemove(extraent)
- self.ExtraCorpsesToRemove_Transition[#self.ExtraCorpsesToRemove_Transition+1] = gib
- end
- if (CustomCode) then CustomCode(gib) end
- return gib
- end
- ---------------------------------------------------------------------------------------------------------------------
- //this function needs fixing or deleting for hovering capability
- function ENT:AAMove_ChaseEnemy(ShouldPlayAnim,UseCalmVariables)
- if self.Dead == true or (self.NextChaseTime > CurTime()) or !IsValid(self:GetEnemy()) then return end
- local ShouldPlayAnim = ShouldPlayAnim or false
- local UseCalmVariables = UseCalmVariables or false
- local Debug = self.AA_EnableDebug
- local MoveSpeed = self.Aerial_FlyingSpeed_Alerted
- if self.MovementType == VJ_MOVETYPE_AQUATIC then
- if Debug == true then
- print("--------")
- print("ME WL: "..self:WaterLevel())
- print("ENEMY WL: "..self:GetEnemy():WaterLevel())
- end
- -- Yete chouri e YEV leman marmine chourin mech-e che, ere vor gena yev kharen kal e
- if self:WaterLevel() <= 2 && self:GetVelocity():Length() > 0 then return end
- if self:WaterLevel() <= 1 && self:GetVelocity():Length() > 0 then self:AAMove_Wander(true,true) return end
- if self:GetEnemy():WaterLevel() == 0 then self:DoIdleAnimation(1) return end -- Yete teshnamin chouren tours e, getsour
- if self:GetEnemy():WaterLevel() <= 1 then -- Yete 0-en ver e, ere vor nayi yete gerna teshanmi-in gerna hasnil
- local trene = util.TraceLine({
- start = self:GetEnemy():GetPos() + self:OBBCenter(),
- endpos = (self:GetEnemy():GetPos() + self:OBBCenter()) + self:GetEnemy():GetUp()*-20,
- filter = self,
- mins = self:OBBMins(),
- maxs = self:OBBMaxs()
- })
- //PrintTable(trene)
- //VJ_CreateTestObject(trene.HitPos,self:GetAngles(),Color(0,255,0),5)
- if trene.Hit == true then return end
- end
- MoveSpeed = self.Aquatic_SwimmingSpeed_Alerted
- end
- if UseCalmVariables == true then
- if self.MovementType == VJ_MOVETYPE_AQUATIC then
- MoveSpeed = self.Aquatic_SwimmingSpeed_Calm
- else
- MoveSpeed = self.Aerial_FlyingSpeed_Calm
- end
- end
- self:FaceCertainEntity(self:GetEnemy(),true)
- if ShouldPlayAnim == true && self.NextChaseTime < CurTime() then
- self.AA_CanPlayMoveAnimation = true
- if UseCalmVariables == true then
- self.AA_CurrentMoveAnimationType = "Calm"
- else
- self.AA_CurrentMoveAnimationType = "Alert"
- end
- else
- self.AA_CanPlayMoveAnimation = false
- end
- -- Main Calculations
- local vel_for = 1
- local vel_stop = false
- local nearpos = self:VJ_GetNearestPointToEntity(self:GetEnemy())
- local startpos = nearpos.MyPosition // self:GetPos()
- local endpos = nearpos.EnemyPosition // self:GetEnemy():GetPos()+self:GetEnemy():OBBCenter()
- local tr = util.TraceHull({
- start = startpos,
- endpos = endpos,
- filter = self,
- mins = self:OBBMins(),
- maxs = self:OBBMaxs()
- })
- local tr_hitpos = tr.HitPos
- local dist_selfhit = startpos:Distance(tr_hitpos)
- if Debug == true then util.ParticleTracerEx("Weapon_Combine_Ion_Cannon_Beam",tr.StartPos,tr_hitpos,false,self:EntIndex(),0) end //vortigaunt_beam
- if dist_selfhit <= 16 && tr.HitWorld == true then
- if Debug == true then print("AA: Forward Blocked! [CHASE]") end
- vel_for = 1
- //vel_for = -200
- //vel_stop = true
- end
- local enepos = self:GetEnemy():GetPos()+self:GetEnemy():OBBCenter() + self.maintainHeight
- if self.MovementType == VJ_MOVETYPE_AQUATIC && self:GetEnemy():WaterLevel() < 3 then
- enepos = self:GetEnemy():GetPos()
- end
- -- X Calculations
- -- Coming soon!
- -- Z Calculations
- local vel_up = MoveSpeed
- local dist_selfhit_z = enepos.z - startpos.z -- Get the distance between the hit position and the start position
- if dist_selfhit_z > 0 then -- Yete 0-en ver e, ere vor 20-en minchev sahmani tive hasni
- if Debug == true then print("AA: GOING UP [CHASE]") end
- vel_up = math.Clamp(dist_selfhit_z, 20, MoveSpeed)
- elseif dist_selfhit_z < 0 then -- Yete 0-en var e, ere vor nevaz 20-en minchev nevaz sahmani tive hasni
- if Debug == true then print("AA: GOING DOWN [CHASE]") end
- vel_up = -math.Clamp(math.abs(dist_selfhit_z), 20, MoveSpeed)
- else
- vel_up = 0
- end
- if dist_selfhit < 100 then -- Yete 100-en var e tive, esel e vor modig e, ere vor gamatsna
- MoveSpeed = math.Clamp(dist_selfhit, 100, MoveSpeed)
- end
- -- Final velocity
- if vel_stop == false then
- self.CurrentTurningAngle = false
- local vel_set = ((enepos + self.maintainHeight) - (self:GetPos() + self:OBBCenter())):GetNormal()*MoveSpeed + self:GetUp()*vel_up + self:GetForward()*vel_for
- //local vel_set_yaw = vel_set:Angle().y
- self:SetLocalVelocity(vel_set)
- local vel_len = CurTime() + (dist_selfhit / vel_set:Length())
- self.AA_MoveLength_Wander = 0
- if vel_len == vel_len then -- Check for NaN
- self.AA_MoveLength_Chase = vel_len
- self.NextIdleTime = vel_len
- end
- if Debug == true then ParticleEffect("vj_impact1_centaurspit", enepos, Angle(0,0,0), self) end
- else
- self:AAMove_Stop()
- end
- //self.NextChaseTime = CurTime() + 0.1
- end
- function ENT:Think()
- if (self.enableAI==true) then
- //self:SetPoseParameter("move_yaw",180)
- //print(self:GetBlockingEntity())// end
- // if self:IsUnreachable(self:GetEnemy()) && enemy noclipping then...
- //if self.AA_TargetPos.x == self:GetPos().x then
- -- to be coded..
- //end
- //print(self:GetPos())
- //print("-------------------------------")
- //if self.CurrentSchedule != nil then PrintTable(self.CurrentSchedule) end
- //if self.CurrentTask != nil then PrintTable(self.CurrentTask) end
- if self:GetVelocity():Length() <= 0 && self.MovementType == VJ_MOVETYPE_GROUND /*&& CurSched.IsMovingTask == true*/ then self:DropToFloor() end
- local CurSched = self.CurrentSchedule
- if CurSched != nil then
- if self:IsMoving() then
- if CurSched.IsMovingTask_Walk == true && !VJ_HasValue(self.AnimTbl_Walk,self:GetMovementActivity()) then
- self:SetMovementActivity(VJ_PICK(self.AnimTbl_Walk))
- end
- if CurSched.IsMovingTask_Run == true && !VJ_HasValue(self.AnimTbl_Run,self:GetMovementActivity()) then
- self:SetMovementActivity(VJ_PICK(self.AnimTbl_Run))
- end
- end
- if CurSched.StopScheduleIfNotMoving == true && (!self:IsMoving() or (self:GetBlockingEntity() != nil && self:GetBlockingEntity():IsNPC())) then // (self:GetGroundSpeedVelocity():Length() <= 0) == true
- self:ScheduleFinished(CurSched)
- //self:SetCondition(35)
- //self:StopMoving()
- end
- if self:HasCondition(35) && CurSched.AlreadyRanCode_OnFail == false then
- if self:DoRunCode_OnFail(CurSched) == true then
- self:ClearCondition(35)
- end
- end
- if CurSched.ResetOnFail == true && self:HasCondition(35) == true then
- self:StopMoving()
- //self:SelectSchedule()
- self:ClearCondition(35)
- //print("VJ Base: Task Failed Condition Identified! "..self:GetName())
- end
- end
- /*if CurTime() > self.TestT then
- self:AddLayeredSequence(self:SelectWeightedSequence(ACT_IDLE),1)
- self:SetLayerPlaybackRate(1,0.1)
- self:SetLayerLooping(1,true)
- timer.Simple(0.5,function() print(self:IsValidLayer(1)) end)
- self.TestT = CurTime() + 2 end*/
- //self:SetPlaybackRate(1)
- //self:AddGesture(ACT_IDLE)
- //print(self:IsPlayingGesture(ACT_IDLE))
- //print(self:GetArrivalActivity())
- //self:SetArrivalActivity(ACT_MELEE_ATTACK1)
- /*if CurTime() > self.OldMeleeTimer then
- for _, backwards in ipairs({"_as_*", "_dmvj_", "_eye_", "_zss_", "_nmrih_"}) do
- if string.find(self:GetClass(), backwards) then
- self.IsUsingOldMeleeAttackSystem = true
- print("found string") else
- if self.IsUsingOldMeleeAttackSystem == false then
- print("didn't find string")
- self.IsUsingOldMeleeAttackSystem = false end
- end end
- self.OldMeleeTimer = CurTime() + 999999999999999999 *999999999999999999 +999999999999999 *99
- end*/
- //print(self.CurrentTask)
- //self:GetBonePosition(self:LookupBone("Bip01 R Hand")
- //print(#util.VJ_GetSNPCsWithActiveSoundTracks())
- //util.ParticleTracerEx( "vortigaunt_beam", self:GetPos(), lpos, false, self:EntIndex(), 2)
- //self:SetColor(Color(0,0,0))
- //self:ConvarsOnThink()
- self:CustomOnThink()
- if self.HasSounds == false or self.Dead == true then VJ_STOPSOUND(self.CurrentBreathSound) end
- if self.Dead == false && self.HasBreathSound == true && self.HasSounds == true then
- if CurTime() > self.NextBreathSoundT then
- local brsd = VJ_PICK(self.SoundTbl_Breath)
- local dur = math.Rand(self.NextSoundTime_Breath1,self.NextSoundTime_Breath2)
- if brsd != false then
- VJ_STOPSOUND(self.CurrentBreathSound)
- if self.NextSoundTime_Breath_BaseDecide == true then
- dur = SoundDuration(brsd)
- end
- self.CurrentBreathSound = VJ_CreateSound(self,brsd,self.BreathSoundLevel,self:VJ_DecideSoundPitch(self.BreathSoundPitch1,self.BreathSoundPitch2))
- end
- self.NextBreathSoundT = CurTime() + dur
- end
- end
- --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
- if GetConVarNumber("ai_disabled") == 0 then
- if self:GetArrivalActivity() == -1 then
- self:SetArrivalActivity(self.CurrentAnim_IdleStand)
- end
- //if !self:IsOnGround() then self:ClearGoal() end
- self:CustomOnThink_AIEnabled()
- if self.MovementType == VJ_MOVETYPE_AERIAL or self.MovementType == VJ_MOVETYPE_AQUATIC then -- Yete terogh gam chouri SNPC ene...
- -- Yete chouri e YEV leman marmine chourin mech-e che, ere vor gena yev kharen kal e
- if self.MovementType == VJ_MOVETYPE_AQUATIC && self:WaterLevel() <= 2 && self:GetVelocity():Length() > 0 then self:AAMove_Wander(true,true) end
- if self.AA_CanPlayMoveAnimation == true && self:GetVelocity():Length() > 0 then
- self:AAMove_Animation()
- //elseif self:GetSequence() != 0 && self.PlayingAttackAnimation == false then
- //self:VJ_ACT_PLAYACTIVITY(ACT_IDLE,false,0,false,0,{AlwaysUseSequence=true,SequenceDuration=false})
- end
- end
- //self:DoCustomIdleAnimation()
- //if !IsValid(self:GetEnemy()) then self.Alerted = false end
- if self.VJDEBUG_SNPC_ENABLED == true then
- if GetConVarNumber("vj_npc_printcurenemy") == 1 then print(self:GetClass().."'s Enemy: ",self:GetEnemy()," Alerted? ",self.Alerted) end
- if GetConVarNumber("vj_npc_printalerted") == 1 then if self.Alerted == true then print(self:GetClass().." Is Alerted!") else print(self:GetClass().." Is Not Alerted!") end end
- if GetConVarNumber("vj_npc_printtakingcover") == 1 then if CurTime() > self.TakingCoverT == true then print(self:GetClass().." Is Not Taking Cover") else print(self:GetClass().." Is Taking Cover ("..self.TakingCoverT-CurTime()..")") end end
- if GetConVarNumber("vj_npc_printlastseenenemy") == 1 then PrintMessage(HUD_PRINTTALK, self.LastSeenEnemyTime.." ("..self:GetName()..")") end
- end
- self:IdleSoundCode()
- if self.DisableFootStepSoundTimer == false then self:FootStepSoundCode() end
- self:WorldShakeOnMoveCode()
- if self.FollowingPlayer == true then
- //print(self:GetTarget())
- //print(self.FollowPlayer_Entity)
- if GetConVarNumber("ai_ignoreplayers") == 0 then
- if !IsValid(self.FollowPlayer_Entity) or !self.FollowPlayer_Entity:Alive() or self:Disposition(self.FollowPlayer_Entity) != D_LI then self:FollowPlayerReset() end
- if CurTime() > self.NextFollowPlayerT && IsValid(self.FollowPlayer_Entity) && self.FollowPlayer_Entity:Alive() && self.AlreadyBeingHealedByMedic == false then
- local DistanceToPly = self:GetPos():Distance(self.FollowPlayer_Entity:GetPos())
- local busy = self:BusyWithActivity()
- local abletomove = true
- self:SetTarget(self.FollowPlayer_Entity)
- if busy == true && DistanceToPly < (self.FollowPlayerCloseDistance * 4) then
- abletomove = false
- end
- if DistanceToPly > self.FollowPlayerCloseDistance then
- if abletomove == true then
- self.FollowPlayer_GoingAfter = true
- self.AlreadyDone_RunSelectSchedule_FollowPlayer = false
- if busy == false then
- local movetype = "TASK_RUN_PATH"
- if DistanceToPly < 220 then
- movetype = "TASK_WALK_PATH"
- end
- self:VJ_TASK_GOTO_TARGET(movetype,function(x)
- x.CanShootWhenMoving = true
- if self:VJ_HasActiveWeapon() == true then
- x.ConstantlyFaceEnemyVisible = true
- end
- end)
- end
- end
- elseif self.AlreadyDone_RunSelectSchedule_FollowPlayer == false then
- if busy == false then
- self:StopMoving()
- self:SelectSchedule()
- end
- self.FollowPlayer_GoingAfter = false
- self.AlreadyDone_RunSelectSchedule_FollowPlayer = true
- end
- self.NextFollowPlayerT = CurTime() + self.NextFollowPlayerTime
- end
- else
- self:FollowPlayerReset()
- end
- end
- /*
- //if CurTime() > self.TestT then
- //if type(vACT_Name) != "string" && self:SelectWeightedSequence(vACT_Name) == -1 && self:GetSequenceName(self:SelectWeightedSequence(vACT_Name)) == "Not Found!" then
- //print(self:GetSequenceName(self:GetSequence()))
- //print(self:VJ_GetNPCSchedule())
- local idleanim = self.AnimTbl_IdleStand
- local ideanimrand = VJ_PICK(idleanim)
- if type(ideanimrand) == "number" then ideanimrand = self:GetSequenceName(self:SelectWeightedSequence(ideanimrand)) end
- print(ideanimrand)
- // self:IsCurrentSchedule(SCHED_IDLE_STAND) == true &&
- if !IsValid(self:GetEnemy()) && !self:IsMoving() && !self.CurrentSchedule && table.Count(idleanim) > 0 && self:GetSequenceName(self:SelectWeightedSequence(ACT_IDLE)) == self:GetSequenceName(self:GetSequence()) && self:GetSequenceName(self:GetSequence()) != ideanimrand then
- //print("Should Change Anim!")
- self:VJ_ACT_PLAYACTIVITY(ideanimrand,false,0,true,0)
- end
- //self.TestT = CurTime() + VJ_GetSequenceDuration(self,ideanimrand)
- //end
- */
- /*if IsValid(self:GetEnemy()) then
- if self:GetEnemy():GetClass() == "player" then
- //if !self:GetEnemy():Alive() then
- self:SetEnemy(NULL)
- self.MyEnemy = NULL
- //self:AddEntityRelationship(self:GetEnemy(),4,10)
- print("Working")
- end
- //end
- end*/
- //print(self:GetPathTimeToGoal())
- //print(self:GetPathDistanceToGoal())
- /*if self.PlayedResetEnemyRunSchedule == true && !self:IsCurrentSchedule(SCHED_FORCED_GO_RUN) == true && (!self.IsVJBaseSNPC_Tank) then
- self.PlayedResetEnemyRunSchedule = false
- if self.Alerted == false then
- //self:VJ_SetSchedule(SCHED_ALERT_SCAN)
- //self:VJ_ACT_PLAYACTIVITY(ACT_RANGE_ATTACK1,true,2,false)
- timer.Simple(5,function()
- if self:IsValid() && self.DisableWandering == false then
- self:DoIdleAnimation(1)
- end
- end)
- end
- end*/
- if self.CurrentTurningAngle != false then
- self:SetAngles(Angle(math.ApproachAngle(self:GetAngles().p, self.CurrentTurningAngle.p, self.TurningSpeed),math.ApproachAngle(self:GetAngles().y, self.CurrentTurningAngle.y, self.TurningSpeed),math.ApproachAngle(self:GetAngles().r, self.CurrentTurningAngle.r, self.TurningSpeed)))
- end
- local ene = self:GetEnemy()
- if IsValid(ene) then
- if self.IsDoingFaceEnemy == true /*&& self.VJ_IsBeingControlled == false*/ then self:SetAngles(self:VJ_ReturnAngle((ene:GetPos()-self:GetPos()):Angle())) end
- self:DoConstantlyFaceEnemyCode()
- if (self.CurrentSchedule != nil && ((self.CurrentSchedule.ConstantlyFaceEnemy == true) or (self.CurrentSchedule.ConstantlyFaceEnemyVisible == true && self:Visible(ene))) /*&& self.VJ_IsBeingControlled == false*/) then self:SetAngles(self:VJ_ReturnAngle((ene:GetPos()-self:GetPos()):Angle())) end
- self.ResetedEnemy = false
- self:UpdateEnemyMemory(ene,ene:GetPos())
- self.LatestEnemyPosition = ene:GetPos()
- self.LatestEnemyDistance = self:GetPos():Distance(ene:GetPos())
- self.LatestEnemyClass = ene
- self.TimeSinceLastSeenEnemy = 0
- self.TimeSinceSeenEnemy = self.TimeSinceSeenEnemy + 0.1
- if (self:GetForward():Dot((ene:GetPos() - self:GetPos()):GetNormalized()) > math.cos(math.rad(self.SightAngle))) && (self.LatestEnemyDistance < self.SightDistance) then
- local seentr = util.TraceLine({start = self:NearestPoint(self:GetPos() +self:OBBCenter()),endpos = ene:EyePos(),filter = function(ent) if (ent:GetClass() == self:GetClass() or self:Disposition(ent) == D_LI) then return false end end})
- if (ene:Visible(self) or (IsValid(seentr.Entity) && seentr.Entity:GetClass() == ene)) then
- self.LastSeenEnemyTime = 0
- self.LatestVisibleEnemyPosition = ene:GetPos()
- else
- self.LastSeenEnemyTime = self.LastSeenEnemyTime + 0.1
- end
- else
- self.LastSeenEnemyTime = self.LastSeenEnemyTime + 0.1
- end
- if self.CallForHelp == true && self.Dead == false then
- if CurTime() > self.NextCallForHelpT then
- self:CallForHelpCode(self.CallForHelpDistance)
- self.NextCallForHelpT = CurTime() + self.NextCallForHelpTime
- end
- end
- if self.NoChaseAfterCertainRange == true && ((self.NoChaseAfterCertainRange_Type == "OnlyRange" && self.HasRangeAttack == true) or (self.NoChaseAfterCertainRange_Type == "Regular")) then
- local fardist = self.NoChaseAfterCertainRange_FarDistance
- local closedist = self.NoChaseAfterCertainRange_CloseDistance
- if fardist == "UseRangeDistance" then fardist = self.RangeDistance end
- if closedist == "UseRangeDistance" then closedist = self.RangeToMeleeDistance end
- if (self.LatestEnemyDistance + self.maintainHeight.z < fardist) && (self.LatestEnemyDistance+self.maintainHeight.z > closedist) && ene:Visible(self) /*&& self:CanDoCertainAttack("RangeAttack") == true*/ then
- self.RangeAttack_DisableChasingEnemy = true
- if self.CurrentSchedule != nil && self.CurrentSchedule.Name == "vj_chase_enemy" then self:StopMoving() end
- if self.MovementType == VJ_MOVETYPE_GROUND && !self:IsMoving() then self:SetAngles(self:VJ_ReturnAngle((ene:GetPos()-self:GetPos()):Angle())) end
- if (self.MovementType == VJ_MOVETYPE_AERIAL or self.MovementType == VJ_MOVETYPE_AQUATIC) && CurTime() > self.AA_MoveLength_Wander /*&& ((self.AA_CurrentMoveAnimationType != "Calm") or (self.AA_CurrentMoveAnimationType == "Calm" && self:GetVelocity():Length() > 0))*/ then self:AAMove_Wander(true,false) /*self:AAMove_Stop()*/ end
- else
- self.RangeAttack_DisableChasingEnemy = false
- if self.CurrentSchedule != nil && self.CurrentSchedule.Name != "vj_chase_enemy" then self:DoChaseAnimation() end
- //if GetConVarNumber("vj_npc_nochasingenemy") == 0 then self.DisableChasingEnemy = true end else
- //if GetConVarNumber("vj_npc_nochasingenemy") == 0 then self.DisableChasingEnemy = false end
- end
- end
- end
- if CurTime() > self.NextProcessT then
- self:DoEntityRelationshipCheck()
- self:DoMedicCode_FindAllies()
- self:DoMedicCode_HealAlly()
- self.NextProcessT = CurTime() + self.NextProcessTime
- end
- if self.ResetedEnemy == false then
- if self.LastSeenEnemyTime > self.LastSeenEnemyTimeUntilReset && (!self.IsVJBaseSNPC_Tank) then
- self:LostEnemySoundCode()
- self.ResetedEnemy = true
- self:ResetEnemy(true)
- end
- if (!IsValid(self:GetEnemy())) or (IsValid(self:GetEnemy()) && self:GetEnemy():Health() <= 0) then
- self.ResetedEnemy = true
- self:ResetEnemy(true)
- end
- end
- /*if CurTime() > self.TestT then
- self.VJ_PlayingSequence = true
- self:ClearSchedule()
- timer.Simple(0.2,function()
- if self:IsValid() then
- self:VJ_PlaySequence("infectionrise",1,true,self:SequenceDuration(self:LookupSequence("specialidle_sleep")) +3) end end)
- self.TestT = CurTime() + self:SequenceDuration("specialidle_sleep") +10 end*/
- --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
- -- Attack Timers --
- if self.MovementType == VJ_MOVETYPE_AERIAL or self.MovementType == VJ_MOVETYPE_AQUATIC then self:SelectSchedule() end
- ene = self:GetEnemy()
- if IsValid(ene) then
- //if self.MovementType == VJ_MOVETYPE_AERIAL then self:SelectSchedule() end//self:AAMove_ChaseEnemy(true) end
- //if self.VJ_IsBeingControlled == false then
- if self.MovementType == VJ_MOVETYPE_STATIONARY && self.CanTurnWhileStationary == true then self:FaceCertainEntity(ene,true) end
- if self.MeleeAttackAnimationFaceEnemy == true && self.MeleeAttack_DoingPropAttack == false && self.Dead == false && self.MeleeAttacking == true /*&& timer.Exists("timer_melee_start"..self:EntIndex()) && timer.TimeLeft("timer_melee_start"..self:EntIndex()) > 0*/ then self:FaceCertainEntity(ene,true) end
- if self.RangeAttackAnimationFaceEnemy == true && self.Dead == false && self.RangeAttacking == true /*&& timer.Exists("timer_range_start"..self:EntIndex()) && timer.TimeLeft("timer_range_start"..self:EntIndex()) > 0*/ then self:FaceCertainEntity(ene,true) end
- if self.LeapAttackAnimationFaceEnemy == true && self.Dead == false && self.LeapAttacking == true /*&& timer.Exists("timer_leap_start"..self:EntIndex()) && timer.TimeLeft("timer_leap_start"..self:EntIndex()) > 0*/ then self:FaceCertainEntity(ene,true) end
- //end
- //if self.PlayingAttackAnimation == true then self:FaceCertainEntity(ene,true) end
- self.ResetedEnemy = false
- self.NearestPointToEnemyDistance = self:VJ_GetNearestPointToEntityDistance(ene)
- //self:SetMovementActivity(6.5)
- //self:SetMovementActivity(ACT_WALK)
- self:CustomAttack() -- Custom attack
- if self.Dead == false then
- self:PoseParameterLookingCode()
- end
- -- Melee Attack --------------------------------------------------------------------------------------------------------------------------------------------
- if self.HasMeleeAttack == true then
- //print(self:NearestPoint(ene:GetPos() +self:OBBCenter()):Distance(ene:NearestPoint(self:GetPos() +ene:OBBCenter())))
- //PrintMessage(HUD_PRINTTALK,self:VJ_GetNearestPointToEntityDistance(ene))
- // ene:GetPos():Distance(self:GetPos())
- if self:CanDoCertainAttack("MeleeAttack") == true then
- self:MultipleMeleeAttacks()
- local getproppushorattack = self:PushOrAttackPropsCode()
- local ispropattack = false
- local isnormalattack = false
- local isbeingcontrolled = false
- if self.VJ_IsBeingControlled == true then isbeingcontrolled = true end
- if getproppushorattack == true then ispropattack = true end
- if isbeingcontrolled == false && self.NearestPointToEnemyDistance < self.MeleeAttackDistance && ene:Visible(self) then ispropattack = false isnormalattack = true end
- if isbeingcontrolled == true && self.VJ_TheController:KeyDown(IN_ATTACK) then ispropattack = false isnormalattack = true end
- if (isbeingcontrolled == true && isnormalattack == true && self:CustomAttackCheck_MeleeAttack() == true) or (isbeingcontrolled == false && self:CustomAttackCheck_MeleeAttack() == true && (isnormalattack == true or (ispropattack == true && self.MeleeAttack_NoProps == false)) && (self:GetForward():Dot((ene:GetPos() -self:GetPos()):GetNormalized()) > math.cos(math.rad(self.MeleeAttackAngleRadius)))) then
- self.MeleeAttacking = true
- self.RangeAttacking = false
- self.AlreadyDoneMeleeAttackFirstHit = false
- self.IsAbleToMeleeAttack = false
- self.AlreadyDoneFirstMeleeAttack = false
- if /*self.VJ_IsBeingControlled == false &&*/ ispropattack == false then self:FaceCertainEntity(ene,true) end
- self:CustomOnMeleeAttack_BeforeStartTimer()
- timer.Simple(self.BeforeMeleeAttackSounds_WaitTime,function() if IsValid(self) then self:BeforeMeleeAttackSoundCode() end end)
- self.NextAlertSoundT = CurTime() + 0.4
- if self.DisableMeleeAttackAnimation == false then
- self.CurrentAttackAnimation = VJ_PICK(self.AnimTbl_MeleeAttack)
- self.CurrentAttackAnimationDuration = VJ_GetSequenceDuration(self,self.CurrentAttackAnimation) -self.MeleeAttackAnimationDecreaseLengthAmount
- if self.MeleeAttackAnimationAllowOtherTasks == false then
- self.PlayingAttackAnimation = true
- timer.Simple(self.CurrentAttackAnimationDuration,function()
- if IsValid(self) then
- self.PlayingAttackAnimation = false
- //if self.TimeUntilMeleeAttackDamage == false then self:StopAttacks() end
- end
- end)
- end
- self:VJ_ACT_PLAYACTIVITY(self.CurrentAttackAnimation,false,0,false,self.MeleeAttackAnimationDelay,{SequenceDuration=self.CurrentAttackAnimationDuration})
- end
- if ispropattack == true then self.MeleeAttack_DoingPropAttack = true else self.MeleeAttack_DoingPropAttack = false end
- if self.TimeUntilMeleeAttackDamage == false then
- self:MeleeAttackCode_DoFinishTimers()
- else
- timer.Create("timer_melee_start"..self:EntIndex(), self.TimeUntilMeleeAttackDamage, self.MeleeAttackReps, function() if ispropattack == true then self:MeleeAttackCode(true) else self:MeleeAttackCode() end end)
- for tk, tv in ipairs(self.MeleeAttackExtraTimers) do
- self:DoAddExtraAttackTimers("timer_melee_start_"..math.Round(CurTime())+math.random(1,99999999),tv,1,"MeleeAttack")
- end
- end
- self:CustomOnMeleeAttack_AfterStartTimer()
- end
- end
- end
- -- Range Attack --------------------------------------------------------------------------------------------------------------------------------------------
- if self.HasRangeAttack == true then
- if self:CanDoCertainAttack("RangeAttack") == true then
- self:MultipleRangeAttacks()
- local isbeingcontrolled = false
- local isbeingcontrolled_attack = false
- if self.VJ_IsBeingControlled == true then isbeingcontrolled = true end
- if isbeingcontrolled == true && self.VJ_TheController:KeyDown(IN_ATTACK2) then isbeingcontrolled_attack = true end
- if (isbeingcontrolled == true && isbeingcontrolled_attack == true && self:CustomAttackCheck_RangeAttack() == true) or (isbeingcontrolled == false && self:CustomAttackCheck_RangeAttack() == true && (self.LatestEnemyDistance < self.RangeDistance) && (self.LatestEnemyDistance > self.RangeToMeleeDistance) && (self:GetForward():Dot((ene:GetPos() -self:GetPos()):GetNormalized()) > math.cos(math.rad(self.RangeAttackAngleRadius)))) then
- if self.RangeAttackAnimationStopMovement == true then self:StopMoving() end
- self.RangeAttacking = true
- self.IsAbleToRangeAttack = false
- self.AlreadyDoneRangeAttackFirstProjectile = false
- self:CustomOnRangeAttack_BeforeStartTimer()
- self:BeforeRangeAttackSoundCode()
- if self.DisableRangeAttackAnimation == false then
- if self.RangeAttackAnimationStopMovement == true then
- self:ClearSchedule()
- self:StopMoving()
- end
- self.CurrentAttackAnimation = VJ_PICK(self.AnimTbl_RangeAttack)
- self.CurrentAttackAnimationDuration = VJ_GetSequenceDuration(self,self.CurrentAttackAnimation) -self.RangeAttackAnimationDecreaseLengthAmount
- self.PlayingAttackAnimation = true
- timer.Simple(self.CurrentAttackAnimationDuration,function()
- if IsValid(self) then
- self.PlayingAttackAnimation = false
- //if self.RangeAttacking == true then self:VJ_SetSchedule(SCHED_CHASE_ENEMY) end
- //if self.TimeUntilRangeAttackProjectileRelease == false then self:StopAttacks() end
- end
- end)
- self:VJ_ACT_PLAYACTIVITY(self.CurrentAttackAnimation,false,0,false,self.RangeAttackAnimationDelay,{SequenceDuration=self.CurrentAttackAnimationDuration})
- end
- if self.TimeUntilRangeAttackProjectileRelease == false then
- self:RangeAttackCode_DoFinishTimers()
- else
- timer.Create("timer_range_start"..self:EntIndex(), self.TimeUntilRangeAttackProjectileRelease, self.RangeAttackReps, function() self:RangeAttackCode() end)
- for tk, tv in ipairs(self.RangeAttackExtraTimers) do
- self:DoAddExtraAttackTimers("timer_range_start_"..math.Round(CurTime())+math.random(1,99999999),tv,1,"RangeAttack")
- end
- end
- self:CustomOnRangeAttack_AfterStartTimer()
- end
- end
- end
- -- Leap Attack --------------------------------------------------------------------------------------------------------------------------------------------
- if self.HasLeapAttack == true then
- if self:CanDoCertainAttack("LeapAttack") == true then
- self:MultipleLeapAttacks()
- local isbeingcontrolled = false
- local isbeingcontrolled_attack = false
- if self.VJ_IsBeingControlled == true then isbeingcontrolled = true end
- if isbeingcontrolled == true && self.VJ_TheController:KeyDown(IN_JUMP) then isbeingcontrolled_attack = true end
- if (isbeingcontrolled == true && isbeingcontrolled_attack == true && self:CustomAttackCheck_LeapAttack() == true) or (isbeingcontrolled == false && self:CustomAttackCheck_LeapAttack() == true && (self:IsOnGround() && self.LatestEnemyDistance < self.LeapDistance) && (self.LatestEnemyDistance > self.LeapToMeleeDistance)) then
- self.LeapAttacking = true
- self.AlreadyDoneLeapAttackFirstHit = false
- self.AlreadyDoneFirstLeapAttack = false
- self.IsAbleToLeapAttack = false
- self.JumpLegalLandingTime = 0
- self:FaceCertainEntity(ene,true)
- self:CustomOnLeapAttack_BeforeStartTimer()
- self:BeforeLeapAttackSoundCode()
- timer.Create( "timer_leap_start_jump"..self:EntIndex(), self.TimeUntilLeapAttackVelocity, 1, function() self:LeapAttackVelocityCode() end)
- if self.DisableLeapAttackAnimation == false then
- self.CurrentAttackAnimation = VJ_PICK(self.AnimTbl_LeapAttack)
- self.CurrentAttackAnimationDuration = VJ_GetSequenceDuration(self,self.CurrentAttackAnimation) -self.LeapAttackAnimationDecreaseLengthAmount
- self.PlayingAttackAnimation = true
- timer.Simple(self.CurrentAttackAnimationDuration,function()
- if IsValid(self) then
- self.PlayingAttackAnimation = false
- //if self.TimeUntilLeapAttackDamage == false then self:StopAttacks() end
- end
- end)
- self:VJ_ACT_PLAYACTIVITY(self.CurrentAttackAnimation,false,0,false,self.LeapAttackAnimationDelay,{SequenceDuration=self.CurrentAttackAnimationDuration})
- end
- if self.TimeUntilLeapAttackDamage == false then
- self:LeapAttackCode_DoFinishTimers()
- else
- timer.Create( "timer_leap_start"..self:EntIndex(), self.TimeUntilLeapAttackDamage, self.LeapAttackReps, function() self:LeapDamageCode() end)
- for tk, tv in ipairs(self.LeapAttackExtraTimers) do
- self:DoAddExtraAttackTimers("timer_leap_start_"..math.Round(CurTime())+math.random(1,99999999),tv,1,"LeapAttack")
- end
- end
- self:CustomOnLeapAttack_AfterStartTimer()
- end
- end
- end
- else
- if self.VJ_IsBeingControlled == false && self.Dead == false then
- self:PoseParameterLookingCode(true)
- //self:ClearPoseParameters()
- end
- self.TimeSinceSeenEnemy = 0
- self.TimeSinceLastSeenEnemy = self.TimeSinceLastSeenEnemy + 0.1
- if self.ResetedEnemy == false && (!self.IsVJBaseSNPC_Tank) then self:LostEnemySoundCode() self.ResetedEnemy = true self:ResetEnemy(true) end
- //self:NextThink(CurTime()+10)
- /*if CurTime() > self.NextFindEnemyT then
- if self.DisableFindEnemy == false then self:FindEnemy() end
- self.NextFindEnemyT = CurTime() + self.NextFindEnemyTime end*/
- //self.LeapAttacking = false
- //self.MeleeAttacking = false
- //self.RangeAttacking = false
- end
- else
- if self.MovementType == VJ_MOVETYPE_AERIAL or self.MovementType == VJ_MOVETYPE_AQUATIC then self:AAMove_Stop() end
- //self:StopAttacks()
- //self:SelectSchedule()
- end
- self:NextThink(CurTime()+(0.069696968793869+FrameTime()))
- return true
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement