Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Weeping Angel
- -- Original stalking entity by that Tetris guy.
- -- All credit to TheSniper9 for the models & textures. Keep up the great work! :D
- -- Credit to Darth Telac for helping me out with the code.
- --So yeah, very minor code change to make this thing silent.
- -- Now in addon form... muahahahaha
- AddCSLuaFile( 'cl_init.lua' )
- AddCSLuaFile( 'shared.lua' )
- include('shared.lua')
- local COOLDOWN_TIME = 1
- local THINK_DELAY = 0.2
- local TELEPORT_PROB = 0.09
- local TELEPORT_COOLDOWN = 1
- local TELEPORT_MAX_DIST = 3000
- local TELEPORT_MAX_DIST_FROM_PLR = 450
- local TELEPORT_MIN_DIST_FROM_PLR = 100
- local TELEPORT_MAX_TRIES = 20
- local CREEP_PROB = 0.09
- local CREEP_COOLDOWN = 0.5
- local CREEP_DISTANCE_FRACTION = 0.5
- local STAB_MAX_DIST = 80
- local STAB_PROB = 0.1
- local STAB_COOLDOWN = 2
- local STAB_FORCE = 12000
- local STAB_DAMAGE = 500
- local EMITSOUND_MAX_DIST = 2200
- local EMITSOUND_PROB = 0.08
- local EMITSOUND_COOLDOWN = 4
- local CREEPY_SOUNDS =
- {
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 11
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 2
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 2
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 3
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 7
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 2
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 2
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 3
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 2
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 1
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 5
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 4
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 3
- },
- {
- Snd = Sound( "silentangel.mp3" ),
- Dur = 3
- }
- }
- local sndDrawKnife = Sound( "" )
- local sndStab = Sound( "silentangel.mp3" )
- function ENT:SpawnFunction( plr, tr )
- if not tr.Hit then return end
- local ent = ents.Create( ClassName )
- ent:SetPos( tr.HitPos + tr.HitNormal * 24 )
- ent:Spawn()
- ent:Activate()
- ent:SetVictim( plr )
- ent:DropToFloor()
- return ent
- end
- function ENT:Initialize()
- self:SetModel( "models/The_Sniper_9/DoctorWho/Extras/Angels/angelidle.mdl " )
- self:PhysicsInit( SOLID_VPHYSICS )
- local phys = self:GetPhysicsObject()
- if phys:IsValid() then
- phys:Wake()
- end
- self.Width = self:BoundingRadius() * 0.5
- self.CurSound = ""
- self.NextTeleport = 0
- self.NextCreep = 0
- self.NextEmit = 0
- self.NextStab = 0
- self.Knife = NULL
- self.IsBeingCreepy = false
- self:SetMoveType(MOVETYPE_NONE)
- end
- function ENT:SetVictim( plr )
- self.Victim = plr
- end
- function ENT:HasVictimLOS()
- local tr = util.TraceLine(
- {
- start = self:GetPos(),
- endpos = self.Victim:LocalToWorld( self.Victim:OBBCenter() ),
- filter = { self, self.Kinfe },
- mask = CONTENTS_SOLID | CONTENTS_OPAQUE | CONTENTS_MOVEABLE
- } )
- if tr.Fraction > 0.98 then return true end
- return false
- end
- function ENT:CanVictimSeeUs()
- local ViewEnt = self.Victim:GetViewEntity()
- if ViewEnt == self.Victim and not self:HasVictimLOS() then return false end
- local fov = self.Victim:GetFOV()
- local Disp = self:GetPos() - ViewEnt:GetPos()
- local Dist = Disp:Length()
- local MaxCos = math.abs( math.cos( math.acos( Dist / math.sqrt( Dist * Dist + self.Width * self.Width ) ) + fov * ( math.pi / 180 ) ) )
- Disp:Normalize()
- if Disp:Dot( ViewEnt:EyeAngles():Forward() ) > MaxCos then
- return true
- end
- return false
- end
- function ENT:DrawKnife( vec )
- self:SetModel( "models/The_Sniper_9/DoctorWho/Extras/Angels/angelattack.mdl" )
- vec.z = 0
- vec:Normalize()
- local knifepos = self:GetPos() + vec * self.Width + Vector( 0, 0, 0.5 * self.Width )
- self.Knife = ents.Create( "prop_physics" )
- self.Knife:SetPos( knifepos )
- self.Knife:SetModel( "models/weapons/w_knife_t.mdl" )
- self.Knife:SetAngles( vec:Angle() )
- self.Knife:Spawn()
- self.Knife:SetColor(0, 0 ,0 ,0)
- self.Knife:SetParent( self )
- self:EmitSound( sndDrawKnife, 300, 100 )
- end
- function ENT:TeleportToPos( pos )
- self:SetModel( "models/The_Sniper_9/DoctorWho/Extras/Angels/angelidle.mdl " )
- for i=1, TELEPORT_MAX_TRIES do
- local tr = util.TraceLine(
- {
- start = pos,
- endpos = pos - Vector( 0, 0, 64),
- filter = { self, self.Kinfe },
- mask = MASK_NPCSOLID
- } )
- local spawnpos = tr.HitPos + Vector( 0, 0, self.Width + 8 )
- if util.PointContents( spawnpos ) & MASK_SOLID == 0 then
- self:SetPos( spawnpos )
- -- Jostle it a bit in case it's stuck
- local phys = self:GetPhysicsObject()
- phys:ApplyForceCenter( VectorRand() * 2 )
- break
- end
- pos = pos + Vector( math.Rand( -20, 20 ), math.Rand( -20, 20 ), math.Rand( -5, 5 ) )
- end
- end
- function ENT:TeleportBehindVictim()
- self:SetModel( "models/The_Sniper_9/DoctorWho/Extras/Angels/angelpoint.mdl" )
- if CurTime() < self.NextTeleport then return end
- local plraim = self.Victim:GetAimVector()
- plraim.z = 0
- plraim:Normalize()
- local plrpos = self.Victim:GetShootPos()
- local tr = util.TraceLine(
- {
- start = plrpos - plraim * TELEPORT_MIN_DIST_FROM_PLR,
- endpos = plrpos - plraim * TELEPORT_MAX_DIST_FROM_PLR,
- filter = { self, self.Kinfe, self.Victim },
- mask = MASK_NPCSOLID
- } )
- self:TeleportToPos( tr.HitPos + tr.HitNormal * self.Width )
- self.NextTeleport = CurTime() + TELEPORT_COOLDOWN
- end
- function ENT:CreepForward( disp )
- if CurTime() < self.NextCreep then return end
- self:TeleportToPos( self:GetPos() + disp * CREEP_DISTANCE_FRACTION )
- self.NextCreep = CurTime() + CREEP_COOLDOWN
- end
- function ENT:EmitCreepySounds()
- if CurTime() < self.NextEmit then return end
- local tSnd = CREEPY_SOUNDS[ math.random( 1, #CREEPY_SOUNDS ) ]
- self:EmitSound( tSnd.Snd, 500, 100 )
- self.CurSound = tSnd.Snd
- self.NextEmit = CurTime() + EMITSOUND_COOLDOWN + tSnd.Dur
- end
- function ENT:StabbyLunge( vec )
- if CurTime() < self.NextStab then return end
- local phys = self:GetPhysicsObject()
- local stabvec = vec * STAB_FORCE + Vector( 0, 0, 0.4 * STAB_FORCE )
- phys:ApplyForceCenter( stabvec )
- local vicpos = self.Victim:GetShootPos()
- self.Victim:TakeDamage( STAB_DAMAGE, self, self.Knife )
- self:EmitSound( sndStab, 500, 100 )
- self.NextStab = CurTime() + STAB_COOLDOWN
- end
- function ENT:KillSounds()
- self:StopSound( self.CurSound )
- end
- function ENT:FaceVictim()
- local x = self:GetPos().x - self.Victim:GetPos().x
- local y = self:GetPos().y - self.Victim:GetPos().y
- local fullAng = (90/(math.abs(x)+math.abs(y)))*x
- if y > 0 then
- fullAng = -(fullAng) -180
- end
- self:SetAngles(Angle(0,fullAng+90,0) )
- end
- function ENT:PlayDead()
- if not self.IsBeingCreepy then return end
- -- Be on ground!
- self:DropToFloor()
- -- Face the victim!
- self:FaceVictim()
- -- Act normal!
- self.IsBeingCreepy = false
- -- Be quiet!
- self:KillSounds()
- -- Hide your knife!
- if self.Knife:IsValid() then self.Knife:Remove() end
- -- Reset everything since we stopped doing them
- self.NextTeleport = 0
- self.NextCreep = 0
- self.NextEmit = 0
- self.NextStab = 0
- end
- function ENT:BeCreepy()
- self.IsBeingCreepy = true
- -- Oh no, I already calculated these this frame. I guess that makes my code innefficient. Woe is me.
- local Disp = self.Victim:GetShootPos() - self:GetPos()
- local Dist = Disp:Length()
- local Vec = Disp:GetNormalized()
- -- Randomly decide what creepy things we should do
- local randnum = math.random()
- if Dist > TELEPORT_MAX_DIST or not self:HasVictimLOS() then -- We're too far away or we don't have line of sight. Teleport behind our victim.
- if TELEPORT_PROB > randnum then
- self:TeleportBehindVictim()
- end
- elseif Dist > EMITSOUND_MAX_DIST then -- We're too far away. Start creeping towards our victim...
- if CREEP_PROB > randnum then
- self:CreepForward( Disp )
- end
- elseif Dist > STAB_MAX_DIST then -- Creep the fuck out of them now.
- if CREEP_PROB > randnum then
- self:CreepForward( Disp )
- elseif CREEP_PROB + EMITSOUND_PROB > randnum then
- self:EmitCreepySounds()
- end
- else -- We're close enough to attack! mwahahahaha!
- if not self.Knife:IsValid() then
- self:DrawKnife( Vec )
- end
- if EMITSOUND_PROB > randnum then
- self:EmitCreepySounds()
- elseif EMITSOUND_PROB + STAB_PROB > randnum then
- self:StabbyLunge( Vec )
- end
- end
- self:DropToFloor()
- self:FaceVictim()
- end
- function ENT:Think()
- if not ValidEntity( self.Victim ) or not self.Victim:Alive() then return end
- -- OHSHI.. he sees us!
- if self:CanVictimSeeUs() then
- -- Pretend like nothing happened
- self:PlayDead()
- self:NextThink( CurTime() + COOLDOWN_TIME )
- else
- self:BeCreepy()
- self:NextThink( CurTime() + THINK_DELAY )
- end
- return true
- end
- function ENT:OnRemove()
- self:KillSounds()
- end
- function ENT:Draw()
- self:DrawModel()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement