Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local AI = {}
- AI.Name = "Librarian"
- function AI:Spawn(pos)
- local ENT = ents.Create("rp_enemy")
- ENT:SetModel("models/zombie/poison.mdl")
- ENT:SetPos(pos + Vector(0,0,30))
- ENT.Damage = 40
- ENT.BumpSpeed = 700
- ENT.AnimSpeed = 0.3
- ENT.AttackTime = 0.2
- ENT.AttackDelay = 1
- ENT.BaseHealth = 2000
- ENT:SetHealth(ENT.BaseHealth)
- ENT.MaxAttackDelay = 0.6
- ENT.MeleeDistance = 84
- ENT.BreakableDistance = 86
- ENT.MoveSpeed = 60
- ENT.RunSpeed = 200
- ENT:SetColor(Color(255,255,255,255))
- ENT:SetCollisionBounds(Vector(-1,-1,0),Vector(1,1,50))
- ENT.AttackRow = 0
- --local e = RP:HandleClothing(ENT,"models/zombie/classic_torso.mdl",5)
- -- e:SetColor(Color(50,50,50,255))
- --[[
- local ent = ents.Create("status_overridemodel")
- if ent:IsValid() then
- ent:Spawn()
- ent:SetPlayer(ENT)
- if ent and ent:IsValid() then
- ent:SetModel("models/zombie/poison.mdl")
- end
- end
- ]]--
- ENT.NextFoot = nil
- ENT.oldposzslaaa = Vector(0,0,0)
- ENT.pitchy = math.random(90,110);
- function ENT:OnInjured( dmginfo )
- self.lastDmginfo = dmginfo
- self.NoEnemyTime = 0
- self.AggLevel = self.AggLevel + 20
- if not self.Angered then
- for k,v in pairs(ents.FindInSphere(self:GetPos(),800)) do if v.IsZombie then v.Angered = true end end
- self.Angered = true
- end
- self:SetAngles(self:GetAngles() + Angle(0,math.random(-60,60),0))
- self.washeadshot = false
- if self.Climbing then
- self:UnClimb()
- self:KnockDown(3)
- end
- if IsValid(dmginfo:GetAttacker()) then
- if dmginfo:GetAttacker():IsPlayer() then self.Injured = true
- self.Enemy = dmginfo:GetAttacker() self.EnemyCur = CurTime() + 10 end
- if dmginfo:GetDamagePosition().z > self:GetPos().z + 60 then
- dmginfo:ScaleDamage(3)
- self.washeadshot = true
- self:SetHeadshotter(dmginfo:GetAttacker(),true)
- else
- self:SetHeadshotter(dmginfo:GetAttacker(),false)
- end
- end
- if dmginfo:IsDamageType(DMG_BURN) and self.FireProof then
- dmginfo:SetDamage(0) return
- end
- if dmginfo:IsBulletDamage() then
- if dmginfo:GetDamage() > 30 then
- self:EmitSound("npc/infected/gore/bullets/bullet_gib_0" .. math.random(1,8) .. ".wav",70,math.random(90,110))
- else
- self:EmitSound("npc/infected/gore/bullets/bullet_impact_0" .. math.random(1,8) .. ".wav",70,math.random(90,110))
- end
- end
- if dmginfo:IsExplosionDamage() then
- dmginfo:ScaleDamage( 1.75 )
- elseif not self.Entity:IsOnFire() then
- local snd = "physics/flesh/flesh_impact_bullet" .. math.random(1,5) .. ".wav"
- sound.Play( snd, self.Entity:GetPos() + Vector(0,0,50), 75, math.random( 90, 110 ), 1.0 )
- end
- //self.Entity:SetHealth( math.Clamp( self.Entity:Health() - dmginfo:GetDamage(), 0, 1000 ) )
- self.Entity:AddDamageTaken( dmginfo:GetAttacker(), dmginfo:GetDamage() )
- if ( IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():GetClass() == "trigger_hurt") or self:Health() < 0 or self:Health() <= dmginfo:GetDamage() then
- self.Entity:OnKilled(dmginfo)
- return
- end
- end
- function ENT:OnDeath()
- end
- function ENT:CanTarget( v )
- return ( ( v:IsPlayer() and v:Alive() and ( v:CanBeTarget(self) or self.Injured or self:GetPos():Distance(v:GetPos()) < 200) ) or ( v.NextBot ) or (not v:IsPlayer() ))
- end
- ENT:SetName("rp_librarian")
- function ENT:SpawnRagdoll( damageinfo, model, pos, override )
- if IsValid(self._ragdoll) then self:SetPos(self._ragdoll:GetPos()) end
- timer.Simple( 0.2, function() if IsValid( self.Entity ) then self.Entity:Remove() end end )
- if not model and damageinfo:GetDamage() <= 300 then
- --[[umsg.Start( "Ragdoll" )
- umsg.Vector( self.Entity:GetPos() )
- if self.Entity:OnFire() then
- umsg.Short(2)
- else
- umsg.Short(1)
- end
- umsg.Short( self.Entity:EntIndex() )
- umsg.End()
- //self:Fire( "BecomeRagdoll", "", 0 ) ]]
- if not damageinfo:IsDamageType(DMG_CLUB) and not damageinfo:IsDamageType(DMG_SLASH) then
- local e = self.Entity if IsValid(damageinfo:GetAttacker()) then e = damageinfo:GetAttacker() end
- local sc = math.max(10,1000 - self.Entity:GetPos():Distance(e:GetPos()))
- if not self.washeadshot then
- damageinfo:SetDamageForce( damageinfo:GetDamageForce():Angle():Forward() * (damageinfo:GetDamage() * sc * 0.1 ))
- end end self.Entity:EmitSound("npc/infected/gore/bullets/bullet_gib_0" .. math.random(1,9) .. ".wav",100,math.random(90,110))
- if self.washeadshot then
- local pofs,fasa = self:GetBonePosition(self:LookupBone("ValveBiped.Bip01_Head1"))
- if pofs then
- local dmginfo = damageinfo
- local effectdata = EffectData()
- effectdata:SetOrigin(dmginfo:GetDamagePosition())
- local force = dmginfo:GetDamageForce()
- effectdata:SetMagnitude(force:Length() * 3)
- effectdata:SetNormal(force:GetNormalized())
- effectdata:SetEntity(self.Entity)
- effectdata:SetScale(0.5)
- util.Effect("headshot", effectdata, true, true)
- end
- end
- local a = ents.Create("prop_ragdoll")
- a:SetModel(self:GetModel())
- a:SetSkin(self:GetSkin())
- a:SetMaterial(self:GetMaterial())
- a:SetColor(self:GetColor())
- a:SetPos(self:GetPos())
- a:SetAngles(self:GetAngles())
- a:Spawn()
- a.notFound = true
- a.Heal = 3000
- a:SetCollisionGroup(COLLISION_GROUP_WORLD)
- local ENT = a
- local head = RP.HandleGears(ENT,"models/Gibs/Antlion_gib_Large_2.mdl","chest",Vector(20,2,0),Angle( 0, 10,-90),Vector(0.6,0.7,0.6) * 1.1)
- local head2 = RP.HandleGears(ENT,"models/Gibs/Antlion_gib_Large_2.mdl","chest",Vector(20,-2,0),Angle( 0, -10, 90),Vector(0.6,0.7,0.6 ) * 1.1)
- head:SetColor(Color(150,110,0,255))
- head2:SetColor(Color(150,110,0,255))
- ENT:ManipulateBoneScale(ENT:LookupBone("ValveBiped.Bip01_L_UpperArm"),Vector(2,2,2))
- ENT:ManipulateBoneScale(ENT:LookupBone("ValveBiped.Bip01_R_UpperArm"),Vector(2,2,2))
- ENT:ManipulateBoneScale(ENT:LookupBone("ValveBiped.Bip01_L_Foot"),Vector(2,2,2))
- ENT:ManipulateBoneScale(ENT:LookupBone("ValveBiped.Bip01_R_Foot"),Vector(2,2,2))
- local ply = self
- local rag = a
- -- position the bones
- local num = rag:GetPhysicsObjectCount()-1
- local v = ply:GetVelocity() + ( damageinfo:GetDamageForce() )
- -- bullets have a lot of force, which feels better when shooting props,
- -- but makes bodies fly, so dampen that here
- if pofs then
- if math.random(1,2) == 2 then
- local f = ents.Create("prop_physics")
- f:SetModel("models/gibs/hgibs.mdl")
- f:SetPos(pofs + Vector(0,0,30))
- f:SetAngles(self:GetAngles())
- f:Spawn()
- f:SetCollisionGroup(COLLISION_GROUP_WORLD)
- a:EmitSound("runner/nhzombie_headexplode_jet.wav")
- timer.Create("bloodysak",0.4,6,function()
- if IsValid(f) then
- util.Blood(f:GetPos(), math.random(2), Vector(0, 0, 1), 100, 1, true)
- end
- end)
- f:SetMaterial("models/flesh")
- f:GetPhysicsObject():Wake()
- local v = v * 2
- v.z = math.max(100,v.z)
- f:GetPhysicsObject():SetVelocity(v )
- f:Fire("kill",5,5,5)
- end
- end if damageinfo:IsDamageType(DMG_BULLET) or damageinfo:IsDamageType(DMG_SLASH) then
- v = v / 10
- end
- for i=0, num do
- local bone = rag:GetPhysicsObjectNum(i)
- if IsValid(bone) then
- local bp, ba = ply:GetBonePosition(rag:TranslatePhysBoneToBone(i))
- if bp and ba then
- bone:SetPos(bp)
- bone:SetAngles(ba)
- end
- -- not sure if this will work:
- bone:SetVelocity(v)
- end
- end
- if pofs then
- if v:Length() <= 50 then
- rag:Fire("disablemotion")
- rag:Fire("enablemotion",0.2,0.2,0.2) end
- local d = self:LookupBone("ValveBiped.Bip01_Head1")
- rag:ManipulateBoneScale(d,Vector(0,0,0))
- end
- rag:Fire("kill",15,15,15)
- self:Remove()
- else
- local ang = self.Entity:GetAngles()
- if IsValid(self._ragdoll) then self._ragdoll:Remove() end
- if self.alrey then return end
- self.alrey = true
- if (ZSL.NextGib or 0) < CurTime() or #ents.FindByClass("env_shooter") < 5 then
- ZSL.NextGib = CurTime() + 1
- local shooter = ents.Create( "env_shooter" )
- shooter:SetPos( pos or self.Entity:GetPos() )
- shooter:SetKeyValue( "m_iGibs", "1" )
- shooter:SetKeyValue( "shootsounds", "3" )
- shooter:SetKeyValue( "gibangles", ang.p.." "..ang.y.." "..ang.r )
- shooter:SetKeyValue( "angles", ang.p.." "..ang.y.." "..ang.r )
- shooter:SetKeyValue( "model",model)
- shooter:SetKeyValue( "simulation", "2" )
- shooter:SetKeyValue( "gibanglevelocity", math.random(-50,50).." "..math.random(-150,150).." "..math.random(-150,150) )
- shooter:SetKeyValue( "m_flVelocity", tostring( math.Rand( -20, 20 ) ) )
- shooter:SetKeyValue( "m_flVariance", tostring( math.Rand( -2, 2 ) ) )
- shooter:SetName("zenv_shooter")
- shooter:Spawn()
- shooter:Fire( "shoot", 0, 0 )
- shooter:Fire( "kill", 0.1, 0.1 )
- end
- if not override then
- self.Entity:Remove()
- end
- end
- end
- ENT.NoFriendTable = {}
- ENT.FriendTable = {}
- ENT.NoEnemyTime = 0
- ENT.FriendMeter = 0
- function ENT:FindEnemy()
- if self.OnFindEnemy then
- local e = self:OnFindEnemy() if e and IsValid(e) then return e end end
- local tbl = RP:GetCharacterPlayers()
- if IsValid(self.Enemy) and (self.EnemyCur or 0) >= CurTime() then
- return self.Enemy
- else
- self.EnemyCur = 0
- end
- self.EnemyTable = tbl
- if #tbl < 1 then
- self.wasshot = false;
- return NULL,true
- else
- local enemy = NULL
- local dist = self.Angered and 1000 or 800
- if self.NoEnemyTime > CurTime() then
- dist = 150
- end
- for k,v in pairs( tbl ) do
- local compare = v:GetPos():Distance( self.Entity:GetPos() )
- if compare < dist and self.Entity:CanTarget( v ) and not v.notFound then
- if self.FriendTable[v:EntIndex()] and self.FriendTable[v:EntIndex()][2] >= CurTime() and compare > 150 then
- else
- self.FriendTable[v:EntIndex()] = nil
- enemy = v
- dist = compare
- end
- end
- end
- if IsValid(enemy) then
- if self.Target != enemy then
- self.IgnoreTime = CurTime() + 5
- self.FriendMeter = 0
- self:Growl()
- self.AggLevel = (self.AggLevel + 4)
- self.FoundEnemy = true
- if IsValid(self.Target) then
- self.NoFriendTable[self.Target:EntIndex()] = self.AggLevel
- end
- if self.NoFriendTable[enemy:EntIndex()] then
- self.AggLevel = self.NoFriendTable[enemy:EntIndex()]
- end
- -- self:EmitSound("runner/nhguard_charge" .. math.random(1,2) .. ".mp3",100,100)
- else
- end
- self.LastKnownPos = enemy:GetPos()
- self.Target = enemy
- return enemy
- end end
- end
- function ENT:CanAttack( ent )
- return IsValid( ent ) and self.Entity:CanTarget( ent ) and ent:GetPos():Distance( self.Entity:GetPos() + Vector(0,0,50) ) <= (self.MeleeDistance + math.Clamp( ent:GetVelocity():Length() ,0,50)) * 1.2 and (not ent:IsPlayer() or self.Entity:MeleeTrace( ent ))
- end
- function ENT:MeleeTrace( ent )
- if (ent:GetPos():Distance(self:GetPos()) < 100) then return true end
- local trace = {}
- trace.start = self.Entity:GetPos() + Vector(0,0,67)
- trace.endpos = ent:GetPos() + Vector(0,0,67)
- trace.filter = { ent, self.Entity }
- local tr = util.TraceLine( trace )
- if not tr.Hit then
- return true
- end
- if tr.Entity == ent then return true end
- if tr.HitWorld or tr.Entity:GetClass() == "prop_door_rotating" or tr.Entity:GetClass() == "func_breakable" or tr.Entity:GetClass() == "func_physbox" or tr.Entity:GetClass() == "func_breakable_surf" then
- return false
- end
- return true
- end
- ENT.CollisionCode = 2338
- function ENT:CanAttackEnemy( ent )
- if self.Entity:CanAttack( ent ) then
- return ent
- end
- if #self.EnemyTable < 1 then return end
- for k,v in pairs( self.EnemyTable ) do
- if self.Entity:CanAttack( v ) then
- return v
- end
- end
- end
- function ENT:GetBreakable()
- --
- --local tbl = ents.FindByModel( "models/props_debris/wood_board04a.mdl" )
- -- tbl = table.Add(tbl,ents.FindByClass("func_physbox"))
- --tbl = table.Add( tbl, table.Copy( GAMEMODE.Breakables ) )
- local remove
- local p = self:GetPos()
- for k,v in pairs(ents.FindInSphere(p + Vector(0,0,50), self.BreakableDistance * 0.7 )) do
- if IsValid(v) and (table.HasValue( RP.Breakables, v) or table.HasValue( RP.PropBreakableClasses,v:GetClass())) and v:Visible(self) then
- return v
- end
- end
- --[[
- for k,v in pairs( tbl ) do
- if IsValid( v ) and v:GetPos() != Vector(0,0,0) and v:GetPos():Distance( self.Entity:GetPos() ) <= self.BreakableDistance then
- return v
- end
- end
- ]]--
- local trace = {}
- trace.start = self.Entity:GetPos() + Vector(0,0,50)
- trace.endpos = trace.start + self.Entity:GetForward() * self.BreakableDistance
- trace.filter = self.Entity
- local tr = util.TraceLine( trace )
- if table.HasValue( RP.Breakables, tr.Entity ) or (IsValid(tr.Entity) and table.HasValue( RP.PropBreakableClasses,tr.Entity:GetClass() )) then
- return tr.Entity
- end
- return NULL
- end
- ENT.isZombie = true
- function ENT:OnStuck()
- local ent = self.Entity:GetBreakable()
- if IsValid( ent ) then
- self.Obstructed = true
- else
- self.Obstructed = false
- self.loco:SetDesiredSpeed( self.BumpSpeed )
- self.loco:Jump()
- self.loco:SetDesiredSpeed( self.BumpSpeed )
- end
- self.loco:ClearStuck()
- end
- function ENT:OnUnStuck()
- self.Obstructed = false
- end
- function ENT:BreakableRoutine() if IsValid(self._ragdoll) then
- return
- end
- if self.CurAttackDelay >= CurTime() then self:PlaySequenceAndWait("ACT_HL2MP_IDLE_ZOMBIE",1.5) return end
- local ent = self.Entity:GetBreakable()
- if IsValid(ent) and self:WorldToLocal(ent:GetPos()).x > 0 then
- local anim = "ACT_IDLE"
- --if self.Entity:CanAttackEnemy( ent ) then
- if (not self.CurAttack or self.CurAttack <= CurTime()) and (self.CurAttackDelay <= CurTime()) then
- self.Entity:StartAttack( ent )
- self.CurAttackDelay = CurTime() + 0.1
- end
- -- ent = self.Entity:GetBreakable()
- --else
- --break
- --end
- end
- end
- ENT.CurAttackDelay = 0
- function ENT:FindSpots( tbl )
- local tbl = tbl or {}
- tbl.pos = tbl.pos or self:WorldSpaceCenter()
- tbl.radius = tbl.radius or 1000
- tbl.stepdown = tbl.stepdown or 20
- tbl.stepup = tbl.stepup or 20
- tbl.type = tbl.type or 'hiding'
- -- Use a path to find the length
- local path = Path( "Follow" )
- -- Find a bunch of areas within this distance
- local areas = navmesh.Find( tbl.pos, tbl.radius, tbl.stepdown, tbl.stepup )
- local found = {}
- -- In each area
- for _, area in pairs( areas ) do
- -- get the spots
- local spots
- if ( tbl.type == 'hiding' ) then spots = area:GetHidingSpots() end
- for k, vec in pairs( spots ) do
- -- Work out the length, and add them to a table
- path:Invalidate()
- path:Compute( self, vec, 1 ) -- TODO: This is bullshit - it's using 'self.pos' not tbl.pos
- table.insert( found, { vector = vec, distance = (path:GetLength() == 0 and vec:Distance(pos) or path:GetLength()) } )
- end
- end
- return found
- end
- function ENT:StartAttack( enemy )
- self.Stuck = CurTime() + 10
- self.CurAttack = CurTime() + self.AttackTime
- self.AttackRow = self.AttackRow + 1
- self.CurEnemy = enemy
- --self.Entity:SetPlaybackRate(0.8)
- self.Entity:RestartGesture(ACT_MELEE_ATTACK1)
- self.CurAttackDelay = CurTime() + self.AttackDelay
- --self.Entity:SetPlaybackRate(0.8)
- -- self.Entity:sVoiceSound( self.VoiceSounds.Attack )
- end
- ENT.DmgTable = {}
- function ENT:OnHitEnemy( enemy )
- local dmg = DamageInfo()
- self.AggLevel = self.AggLevel - 5
- local dd = IsValid(self.weapon) and self.weapon.Damage or self.Damage
- if enemy:GetPos().z > self:GetPos().z + 50 then return end
- if enemy:IsPlayer() then
- -- if self.Targetsa != enemy then
- -- self.Targetsa = enemy
- -- enemy:SendLua("LocalPlayer():EmitSound([[runner/weird1.wav]],500,90)")
- -- end
- -- if (enemy.lastAttacked or 0) < CurTime() then
- -- enemy.lastAttacked = CurTime() + 15
- --end
- if (enemy.nextBeingPushed or 0) < CurTime() then enemy.nextBeingPushed = CurTime() + 0.5 enemy:ViewPunch(Angle(math.random(-6,6) ,math.random(-6,6),math.random(-2,2)) * self.Damage)
- local tac = {}
- tac.start = enemy:GetShootPos()
- tac.endpos = tac.start - ((enemy:GetForward() * 200) + Vector(0,0,200))
- tac.filter = {enemy,self}
- local tr = util.TraceLine(tac)
- local f = 300
- if tr.HitPos.z + 120 < tac.start.z then f = 500 end
- enemy.was_pushed = self
- enemy.last_pushed = CurTime() + 2
- enemy:SetVelocity(((enemy:GetPos() + Vector(0,0,5)) - self:GetPos()):Angle():Forward() * (f)) end
- if enemy:WorldToLocal(self:GetPos()).x < 0 then
- dd = dd * 4
- end
- else
- dd = dd * 3
- end
- enemy:SetLocalVelocity(Vector(0,0,0))
- dmg:SetDamage(dd + (enemy:IsPlayer() and enemy:Armor() > 0 and 0 or 5))
- dmg:SetAttacker(self)
- dmg:SetInflictor(self.Inflictor and self.Inflictor or self)
- dmg:SetDamageType(self.DamageType and self.DamageType or DMG_CLUB)
- dmg:SetDamageForce(self:GetForward() * 50)
- enemy:TakeDamageInfo(dmg)
- end
- function ENT:PlayHitSound()
- self:EmitSound("npc/infected/hit/hit_punch_0" .. math.random(1,8) .. ".wav",70) end
- function ENT:EnemyRoutine() if IsValid(self._ragdoll) then
- return
- end
- local closest = self.Entity:CanAttackEnemy( enemy )
- -- if self:GetVelocity():Length() <= 4 then self:SetVelocity((self:GetForward() + Vector(0,0,0.01)) * 400) end
- if closest and (not self.CurAttack or self.CurAttack <= CurTime()) and (self.CurAttackDelay <= CurTime()) then
- -- local anim = "ACT_HL2MP_IDLE_ZOMBIE" -- table.Random( self.AttackAnims )
- self.Entity:StartAttack( closest )
- //self.Entity:StartActivity( ACT_MELEE_ATTACK1 )
- end
- end
- ENT.LastPos = ENT:GetPos()
- ENT.sLastPos = ENT:GetPos()
- function ENT:StuckThink()
- -- if self.LastPos:Distance( self.Entity:GetPos() ) < 50 then
- --self:DropToFloor()
- -- self.Entity:StartRespawn()
- -- end
- end
- ENT.AggLevel = 0
- ENT.Aggrm = 0
- ENT.Aggr = 0
- ENT.ClawMiss = {"npc/zombie/claw_miss1.wav","npc/zombie/claw_miss2.wav"}
- ENT.IgnoreTime = 0
- ENT.ClawHit = {"physics/flesh/phys_bullet_impact_flesh_01.wav","physics/flesh/phys_bullet_impact_flesh_02.wav","physics/flesh/phys_bullet_impact_flesh_03.wav"}
- function ENT:Think()
- if IsValid(self._ragdoll) then
- return
- end
- self.Entity:OnThink()
- if self.NextFoot and self.NextFoot < CurTime() then
- local enemy = self.Enemy
- local pos = self:GetPos()
- if IsValid(enemy) and (not self:Visible(enemy) or ( enemy:IsPlayer() and CanSee(enemy,pos + (self:GetForward() * 40) + Vector(0,0,60),40) and (enemy:GetPos() - pos):Length() > 150)) then
- self.FriendMeter = self.FriendMeter + 1
- if self.FriendMeter >= 40 and (not self.FriendTable[enemy:EntIndex()] or self.FriendTable[enemy:EntIndex()][2] < CurTime()) then
- self.FriendTable[enemy:EntIndex()] = {enemy,CurTime() + 30}
- self.NoEnemyTime = CurTime() + 10
- self.FriendMeter = 0
- self:EmitSound("npc/zombie_poison/pz_idle4.wav",150,90)
- end
- if self.AggLevel > 0 then
- self.AggLevel = self.AggLevel - 1
- end
- self.Aggr = 1
- self.NoFriendTable[enemy:EntIndex()] = self.AggLevel
- elseif IsValid(enemy) and (enemy:GetPos():Distance(pos) < 600) and self.IgnoreTime < CurTime() then
- self.AggLevel = math.Clamp(self.AggLevel + 5,0,20)
- self.FriendMeter = 0
- self.Aggr = 2
- self.NoFriendTable[enemy:EntIndex()] = self.AggLevel
- end
- if self.Aggrm != self.Aggr then
- self.Aggrm = self.Aggr
- if self.Aggr == 2 then
- self:EmitSound("npc/zombie_poison/pz_idle2.wav",100,95)
- else
- self:EmitSound("npc/zombie_poison/pz_idle3.wav",100,95)
- end
- end
- if self.AggLevel > 10 and not self.Aggressive then
- self.Aggressive = true
- elseif (self.AggLevel <= 0 ) then
- self.Aggressive = false
- end
- self.NextFoot = nil if self:Health() <= 0 and self.LastDmginfo then self:OnKilled(self.LastDmginfo) end
- if self:OnGround() and self:GetActivity() == ACT_RUN then
- self.oldposzslaaa = self:GetPos()
- self:EmitSound("npc/antlion_guard/foot_heavy" .. math.random(1,2) .. ".wav",60,98)
- end
- elseif not self.NextFoot then
- self.NextFoot = CurTime() + 0.4
- end
- if ( self.IdleTalk or 0 ) < CurTime() then
- local cs = {}
- for k,v in pairs(ents.FindInSphere(self:GetPos(),10)) do
- if v.IsZombie and not v:IsPlayer() and v != self then
- self:SetSolid(SOLID_NONE)
- timer.Simple(4,function() if IsValid(self) then self:SetSolid(SOLID_BBOX) end end)
- return
- end
- end
- if not self:OnGround() and not self.Isjumping and not self.Climbing then self:DropToFloor() end
- --[[if self:GetSequence() != self.Zombie_Run then
- self:ResetSequence(self.Zombie_Run)
- end]]--
- local vis = IsValid(self.Enemy) and (self.Enemy:Visible(self))
- --self.Entity:sVoiceSound( self.VoiceSounds.Taunt )
- local ps = self:GetPos()
- self.IdleTalk = CurTime() + (self.IdleTalkDelay or vis and math.Rand(1,3) or math.Rand(3,6))
- local ac = {}
- ac.start = pos
- if vis then
- if vis != self.LastVis then self.LastVis = vis
- self:Growl()
- else
- self:Growl()
- end
- elseif IsValid(self.Enemy) then
- self:Growl() else
- self.IdleTalk = CurTime() + math.random(3,5) end
- end
- if ( self.Stuck or 0 ) < CurTime() then
- self.Entity:StuckThink()
- self.Stuck = CurTime() + 5
- self.LastPos = self.Entity:GetPos()
- end
- if self.CurAttack and self.CurAttack <= CurTime() then
- self.CurAttack = nil
- self:Growl(true)
- -- self:sVoiceSound("npc/infected/action/rageat/" .. self.Gender .. "/rage_at_victim" .. math.random(20,34) .. ".wav",100,self.pitchy)
- if IsValid( self.CurEnemy ) then
- if self.CurEnemy:IsPlayer() then
- local enemy = self.Entity:CanAttackEnemy( self.CurEnemy )
- if IsValid( enemy ) then
- if self.PlayHitSound then self:PlayHitSound() else
- local snd = table.Random( self.ClawHit )
- self.Entity:EmitSound( snd, 100, math.random(90,110) ) end
- self.Entity:OnHitEnemy( enemy )
- else
- self.Entity.CurAttackDelay = 0
- local snd = table.Random( self.ClawMiss )
- self.Entity:EmitSound( snd, 100, math.random(90,110) )
- end
- elseif self.CurEnemy.NextBot then
- local enemy = self.Entity:CanAttackEnemy( self.CurEnemy )
- if IsValid( enemy ) then
- local snd = table.Random( self.ClawHit )
- self.Entity:EmitSound( snd, 100, math.random(90,110) )
- self.Entity:OnHitBot( enemy )
- else
- local snd = table.Random( self.ClawMiss )
- self.Entity:EmitSound( snd, 100, math.random(90,110) )
- end
- elseif ( self.CurEnemy:GetPos():Distance( self.Entity:GetPos() ) <= (self.BreakableDistance * 1.4) ) or self.CurEnemy == self.Entity:GetBreakable() then
- --local enemy = self.Entity:CanAttackEnemy( self.CurEnemy )
- -- if enemy then
- local snd = table.Random( self.ClawMiss )
- self.Entity:EmitSound( snd, 100, math.random(90,110) )
- -- self.CurEnemy:EmitSound( self.DoorHit, 100, math.random(90,110) )
- self.Entity:OnHitBreakable( self.CurEnemy ) end
- -- end
- else
- local snd = table.Random( self.ClawMiss )
- self.Entity:EmitSound( snd, 100, math.random(90,110) )
- end
- end
- end
- ENT.ForcePower = 1.5
- ENT.PropDamage = 5
- ENT.MuscleLimit = 200
- function ENT:OnHitBot( enemy )
- local dmg = DamageInfo()
- self:EmitSound("npc/infected/hit/hit_punch_0" .. math.random(1,8) .. ".wav",100,self.pitchy)
- local dd = self.Damage
- enemy:SetLocalVelocity(( (enemy:GetPos() + Vector(0,0,30)) - self:GetPos()):Angle():Forward() * 150)
- dmg:SetDamage(dd)
- dmg:SetAttacker(self)
- dmg:SetInflictor(self.Inflictor and self.Inflictor or self)
- dmg:SetDamageType(self.DamageType and self.DamageType or DMG_CLUB)
- dmg:SetDamageForce(self:GetForward() * 50)
- enemy:EmitSound("npc/infected/hit/hit_punch_0" .. math.random(1,8) .. ".wav",70)
- enemy:TakeDamageInfo(dmg)
- end
- function ENT:OnHitBreakable( ent )
- if not IsValid( ent ) or ent.NextBot or ent.NoBreak then return end
- if IsValid(ent:GetPhysicsObject()) then
- local targpos = self:GetForward() + Vector(0,0,0.3) -- (ent:GetPos() + Vector(0,0,20)) - self:GetPos()
- if IsValid(self.Target) then
- targpos = (self.Target:GetPos() + Vector(0,0,60)) - self:GetPos()
- end
- if ent:GetPhysicsObject():GetMass() <= self.MuscleLimit and not ent.NoPush then
- ent:GetPhysicsObject():SetVelocity((targpos):Angle():Forward() * (math.random(100,300) * self.ForcePower))
- end
- local d = DamageInfo()
- d:SetDamage(IsValid(self.weapon) and self.weapon.Damage or self.Damage)
- d:SetDamageType(DMG_CLUB)
- d:SetAttacker(self)
- ent:TakeDamageInfo(d)
- if string.find(ent:GetModel(),"explosive") then
- ent:Ignite(10)
- ent:SetHealth(ent:Health() * 0.3)
- end
- end
- if string.find( ent:GetClass(), "func_breakable" ) or string.find( ent:GetClass(), "func_physbox") then
- if ent:GetClass() == "func_breakable_surf" then
- ent:Fire( "shatter", "1 1 1", 0 )
- else
- ent:EmitSound( self.WoodBust )
- local d = DamageInfo()
- d:SetDamage(self.Damage * 10 )
- d:SetDamageType(DMG_CLUB)
- d:SetAttacker(self)
- ent:TakeDamageInfo(d)
- end
- elseif string.find( ent:GetClass(), "func_door" ) then
- ent:Remove()
- elseif string.find(ent:GetClass(),"prop_door") then
- local d = DamageInfo()
- d:SetDamage(self.Damage )
- d:SetDamageType(DMG_CLUB)
- d:SetAttacker(self)
- ent:TakeDamageInfo(d)
- elseif ent:GetClass() == "prop_ragdoll" then
- ent.Mutilated = (ent.Mutilated or 0) + 1
- local f = EffectData()
- self:SetHealth(math.Clamp(self:Health() + 20,0,self.BaseHealth * 2))
- f:SetOrigin(ent:GetPos() )
- f:SetScale(2)
- util.Effect("Blood",f)
- util.StartBleeding(ent,30,30)
- local jitter = VectorRand() * 30
- jitter.z = 20
- util.PaintDown(ent:GetPos() + jitter, "Blood", ent)
- ent:EmitSound("runner/nhzombie_headexplode.wav")
- ent:ManipulateBoneScale(math.random(1,30),Vector(0,0,0))
- ent:ManipulateBoneScale(math.random(1,30),Vector(0,0,0))
- local d = DamageInfo()
- d:SetDamage(self.Damage )
- d:SetDamageType(DMG_CLUB)
- d:SetAttacker(self)
- ent:TakeDamageInfo(d)
- else
- if not ent.Hits then
- ent.Hits = 1
- ent.MaxHits = math.random(10,20)
- elseif IsValid(ent) and IsValid(ent:GetPhysicsObject()) and ent.GetModel then
- ent.Hits = ent.Hits + 1
- if ent.Hits > ent.MaxHits then
- if ent:GetModel() != "models/props_debris/wood_board04a.mdl" then
- local prop = ents.Create( "prop_physics" )
- prop:SetModel( ent:GetModel() )
- prop:SetPos( ent:GetPos() )
- prop:SetAngles( ent:GetAngles() + Angle( math.random(-10,10), math.random(-5,5), math.random(-5,5) ) )
- prop:SetSkin( ent:GetSkin() )
- prop:SetCollisionGroup( COLLISION_GROUP_DEBRIS )
- prop:Spawn()
- local dir = ( ent:GetPos() - self.Entity:GetPos() ):Normalize()
- local phys = prop:GetPhysicsObject()
- if IsValid( phys ) and dir then
- phys:ApplyForceCenter( dir * phys:GetMass() * 800 )
- phys:AddAngleVelocity( VectorRand() * 200 )
- end
- ent:EmitSound( self.WoodBust )
- ent:Remove()
- else
- ent:Fire( "break", "", 0 )
- end
- else
- end
- end
- end
- end
- ENT.NextTeleport = 0
- ENT.SpawnedAt = CurTime()
- ENT.NextAnim = 0
- ENT.RunAnim = ACT_WALK
- ENT.MoveAnim = ACT_WALK
- ENT.loco:SetAcceleration(800)
- function ENT:Growl(t)
- if t then
- self:EmitSound("npc/antlion_guard/angry" .. math.random(1,3) .. ".wav",80,90)
- else
- self:EmitSound("npc/antlion_guard/angry" .. math.random(1,3) .. ".wav",30,90)
- end
- --self:EmitSound("runner/nhguard_alert" .. math.random(2,7) .. ".mp3",100,110)
- end
- function ENT:TeleportVent(ply)
- local f = nil
- if IsValid(ply) then
- f = self:FindSpot( "random", { type = "hiding", pos = ply:GetPos() , radius = ply:GetPos():Distance(self:GetPos()) * 1.2,stepup = 300 } )
- else
- f = ply
- end
- if f then
- local ac = {}
- ac.start = f
- ac.endpos = ac.start + Vector(0,0,500)
- if IsValid(ply) then
- ac.filter = {self,ply}
- else
- ac.filter = {self}
- end
- ac.mask = MASK_SOLID
- local tr = util.TraceLine(ac)
- if tr.HitPos.z - ac.start.z >= 70 then
- local e = ents.Create("prop_physics")
- e:SetModel("models/props_junk/vent001.mdl")
- e:SetPos(tr.HitPos)
- e:Spawn()
- e:EmitSound("physics/metal/metal_box_break" .. math.random(1,2) .. ".wav")
- e:Fire("break")
- local dd = "zskclimb" .. self:EntIndex()
- self:SetPos(tr.HitPos - Vector(0,0,70))
- end
- end
- end
- function ENT:BehaveUpdate( fInterval )
- if ( !self.BehaveThread ) then return end
- local ok, message = coroutine.resume( self.BehaveThread )
- if ( ok == false ) then
- self.BehaveThread = nil
- end
- end
- function ENT:RunBehaviour()
- while ( true ) do
- if IsValid(self._ragdoll) then
- coroutine.yield()
- end
- local enemy = self.Entity:FindEnemy()
- if not IsValid( enemy ) then
- self.Enemy = enemy
- local ac = {}
- if self.LastKnownPos then
- self.Entity:StartActivity( self.MoveAnim )
- self.loco:SetDesiredSpeed( self.MoveSpeed )
- local age = math.Clamp( math.min( self.LastKnownPos:Distance(self:GetPos()), 1000 ) / 1000, 0.2, 1 )
- local opts = { lookahead = 600, draw = self.ShouldDrawPath, maxage = 10 * age, tolerance = 101 }
- local pos = self:GetPos()
- local p = self.LastKnownPos
- if pos.z + 20 < p.z then
- local k = p
- k.z = pos.z
- local z = math.max(100,p.z - pos.z)
- local a = {}
- a.start = self:GetPos()
- a.endpos = a.start + Vector(0,0,z)
- a.mask = MASK_SOLID
- a.filter = {self,enemy}
- if not a.HitWorld then
- self.loco:SetDesiredSpeed( self.BumpSpeed * 3)
- self:SetAngles(Angle(0, (p - pos):Angle().yaw,0))
- self.loco:SetJumpHeight(z + 40)
- self.loco:Jump()
- self.loco:SetDesiredSpeed( self.RunSpeed ) end
- end
- self.Entity:MoveToPos( self.LastKnownPos ,opts)
- if self.Entity:GetPos():Distance(self.LastKnownPos) < 100 then
- self.LastKnownPos = nil
- self:EmitSound("npc/antlion_guard/angry" .. math.random(1,3) .. ".wav",80,80)
- end
- else
- self.Entity:StartActivity( self.MoveAnim )
- self.loco:SetDesiredSpeed( self.MoveSpeed )
- ac.start = self:GetPos() + Vector(0,0,10)
- ac.endpos = (ac.start + (Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 300) ) - Vector(0,0,15)
- ac.filter = {self}
- local tr = util.TraceLine(ac)
- if tr.Hit then
- local age = math.Clamp( math.min( tr.HitPos:Distance(ac.start), 1000 ) / 1000, 0.2, 1 )
- local opts = { lookahead = 600, draw = self.ShouldDrawPath, maxage = 10 * age, tolerance = 11 }
- self.Entity:MoveToPos( tr.HitPos ,opts)
- self:BreakableRoutine()
- end end
- coroutine.yield()
- else
- if self.MustTel then
- local f= false
- for k,v in pairs(player.GetAll()) do if v:GetMoveType() != MOVETYPE_NOCLIP and v:Alive() and v:Visible(self) then
- f = true
- break
- end
- end if not f then self:TeleportVent(enemy) self.MustTel = nil end end
- if not self:Visible(enemy) then
- self.NotVisibleCount = (self.NotVisibleCount or 0) + 1
- if (self.NotVisibleCount >= 4) then
- local f= false
- for k,v in pairs(player.GetAll()) do if v:GetMoveType() != MOVETYPE_NOCLIP and v:Alive() and v:Visible(self) then
- f = true
- break
- end
- end
- if not f then
- self.loco:SetJumpHeight(550)
- self:SetNoDraw(true)
- self.loco:Jump()
- local a = self:FindSpot( "random", { type = "hiding", pos = enemy:GetPos() , radius = enemy:GetPos():Distance(self:GetPos()) * 1.2,stepup = 300 } )
- if a then
- local c = {}
- c.start = a
- c.endpos = a +Vector(0,0,300)
- c.mask = MASK_SOLID
- local tr = util.TraceLine(c)
- a = tr.HitPos
- timer.Create("ventStepping" .. self:EntIndex(),0.2,8,function()
- if IsValid(self ) then sound.Play("MetalVent.StepLeft",a + (Vector(math.random(-50,50),math.random(-50,50),0)),150,100) end
- end)
- end
- coroutine.wait(math.random(1,3))
- self:SetNoDraw(false)
- self:TeleportVent(enemy)
- self.NotVisibleCount = 0
- end
- end
- else
- self.NotVisibleCount = 0
- end
- self.Angered = true
- self.Enemy = enemy
- -- local dd = (enemy:GetPos() - self:GetPos()):Length() > 200
- self.Entity:StartActivity( (dd and self.RunAnim or self.MoveAnim) )
- local pos = self.Entity:GetPos()
- local r = (self.Aggressive and self.RunSpeed or self.MoveSpeed) --+ ((self:Visible(self.Enemy) or dd) and 50 or 0)
- self.loco:SetDesiredSpeed( r)
- local p = enemy:GetPos()
- if self.Obstructed2 and self.Obstructed and pos:Distance(p) > 60 and self.Aggressive then
- self.Obstructed2 = nil
- self.loco:SetDesiredSpeed( self.BumpSpeed )
- self.loco:Jump()
- self.loco:SetDesiredSpeed(r)
- end
- if self.Climbing then
- self:PlaySequenceAndWait("ACT_CLIMB_UP",1)
- self:ResetSequence(10)
- coroutine.yield()
- end
- if self.Obstructed then
- self.Obstructed2 = true
- self.Obstructed = nil
- self.Entity:BreakableRoutine()
- coroutine.yield()
- end
- self.Obstructed2 = nil
- local pos = self.Entity:GetPos()
- self.loco:SetDesiredSpeed( r)
- local p = enemy:GetPos()
- local age = math.Clamp( math.min( enemy:GetPos():Distance( pos), 1000 ) / 1000, 0.2, 1 )
- self.loco:FaceTowards( p)
- if pos.z + 20 < p.z and self.Aggressive then
- local k = p
- k.z = pos.z
- if ( k - p):Length() < 400 then
- local trace = {}
- trace.start = self.Entity:GetPos() + Vector(0,0,37)
- trace.endpos = trace.start + (self.Entity:GetForward() * 400)
- trace.filter = { self}
- local tr = util.TraceLine( trace )
- if tr.Hit then
- local z = math.max(100,p.z - pos.z)
- local a = {}
- a.start = self:GetPos()
- a.endpos = a.start + Vector(0,0,z)
- a.mask = MASK_SOLID
- a.filter = {self,enemy}
- if not a.HitWorld then
- self.loco:SetDesiredSpeed( self.BumpSpeed * 3)
- self:SetAngles(Angle(0, (p - pos):Angle().yaw,0))
- self.loco:SetJumpHeight(z + 150)
- self.loco:Jump()
- self.loco:SetDesiredSpeed( self.RunSpeed ) end
- end
- end
- end
- local opts = { lookahead = 1600, draw = self.ShouldDrawPath, maxage = 10 * age, tolerance = (self.Aggressive and 40 or 200) }
- local p = enemy:GetPos()
- local d = enemy:GetPos():Distance( pos)
- local age = math.Clamp( math.min(d, 1000 ) / 1000, 0.2, 1 )
- local c = 200
- if math.random(1,30) == 2 then c = 50 end
- local ff = (p - pos):Length()
- if ff > 11 and (self.Aggressive or ff > c) then
- self.loco:Approach(p,1)
- self.Entity:MoveToPos( p, opts )
- else
- self.Entity:StartActivity( ACT_IDLE)
- if math.random(1,10) <= self.AggLevel then
- self:Growl(true)
- self.Entity:RestartGesture(ACT_MELEE_ATTACK1)
- coroutine.wait(2)
- end
- end
- self.Entity:BreakableRoutine()
- if self:GetPos():Distance(enemy:GetPos()) <= self.MeleeDistance then
- self.Entity:EnemyRoutine()
- end
- end
- coroutine.yield()
- end
- end
- function ENT:MakeClimbing(tr)
- self.ClimbPos = self:GetPos()
- self.Climbing = ( -1 * tr.HitNormal):Angle()
- self:SetAngles(self.Climbing)
- self.ClimbingTR = tr
- if not IsValid(self.status_overridemodel) then
- local ent = ents.Create("status_overridemodel")
- if ent:IsValid() then
- ent:Spawn()
- ent:SetPlayer(self)
- self.status_overridemodels = ent
- if ent and ent:IsValid() then
- ent:SetModel(self:GetModel() )
- self:SetModel("models/zombie/fast.mdl")
- self:PlaySequenceAndWait("ACT_CLIMB_UP",0.5)
- end
- end
- end
- end
- ENT:SetCollisionGroup(COLLISION_GROUP_NPC)
- ENT:Spawn()
- ENT:Activate()
- ENT.StartPos = ENT:GetPos()
- -- local head = RP.HandleGears(ENT,"models/Gibs/HGIBS.mdl","chest",Vector(20,2,0),Angle( 0, 10,-90),Vector(1.2,0.7,0.6) * 1.1)
- -- local head2 = RP.HandleGears(ENT,"models/Gibs/Antlion_gib_Large_2.mdl","chest",Vector(20,-2,0),Angle( 0, -10, 90),Vector(0.6,0.7,0.6 ) * 1.1)
- -- head:SetColor(Color(150,110,0,255))
- -- head2:SetColor(Color(150,110,0,255))
- --ENT:ManipulateBoneScale(ENT:LookupBone("ValveBiped.Bip01_Spine"),Vector(2,2,2))
- ENT:ManipulateBonePosition(ENT:LookupBone("ValveBiped.Bip01_L_ForeArm"),Vector(10,0,0))
- ENT:ManipulateBonePosition(ENT:LookupBone("ValveBiped.Bip01_R_ForeArm"),Vector(10,0,0))
- ENT:ManipulateBoneScale(ENT:LookupBone("ValveBiped.Bip01_L_Foot"),Vector(2,2,2))
- ENT:ManipulateBoneScale(ENT:LookupBone("ValveBiped.Bip01_R_Foot"),Vector(2,2,2))
- ENT:SetModelScale(1.3,0)
- ENT:SetMaterial(table.Random({"models/Barnacle/Barnacle_sheet","models/antlion_guard/bodyside"}))
- return ENT
- end
- print("Load")
- RP:RegisterAI(AI)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement