Skip to content

Instantly share code, notes, and snippets.

@brandonsturgeon
Created June 2, 2020 02:58
Show Gist options
  • Save brandonsturgeon/c88ca76d0b22726253303a43b736f036 to your computer and use it in GitHub Desktop.
Save brandonsturgeon/c88ca76d0b22726253303a43b736f036 to your computer and use it in GitHub Desktop.
local RED = Color(255, 0, 0, 235)
local BLUE = Color(0, 0, 255, 235)
local WHITE = Color(255, 255, 255, 230)
local beamColor = RED
local beams = {}
local claws = ents.FindByClass("npc_clawscanner")
local Sounds = {
Pursuing = {
name = "npc_clawscanner_pursuing",
channel = CHAN_STATIC,
volume = 1.0,
level = 60,
pitch = 100,
sound = "ambient/alarms/apc_alarm_loop1.wav"
}
}
sound.Add( Sounds.Pursuing )
local function setRelationship(claw, ply, relationship)
if claw:Disposition( ply ) == relationship then return end
if not claw.RelationshipPriorities then
claw.RelationshipPriorities = {}
end
-- Our global AddRelationship starts at 45
claw.RelationshipPriorities[ply] = claw.RelationshipPriorities[ply] or 45
local prioIndex = claw.RelationshipPriorities[ply] + 1
print(prioIndex)
claw:AddEntityRelationship(ply, relationship, prioIndex)
claw.RelationshipPriorities[ply] = prioIndex
end
local function newScanner( claw )
claw:SetSaveValue("m_flModelScale", 0.5)
claw:SetSaveValue("m_flAttackRange", 2000)
claw:SetSaveValue("m_flAttackFarDist", 1600)
claw:SetSaveValue("SpotlightLength", 450)
claw:SetSaveValue("SpotlightWidth", 125)
claw:SetSaveValue("ignoreunseenenemies", true)
claw:SetSaveValue("OnlyInspectPlayers", true)
claw:AddRelationship("player D_LI 45")
for k, ply in pairs(player.GetHumans()) do
local isWanted = ply:getDarkRPVar("wanted")
if isWanted then
setRelationship(claw, ply, D_HT)
end
if claw:TestPVS(ply) then
claw:UpdateEnemyMemory(ply, ply:GetPos())
end
end
table.insert(claws, claw)
end
hook.Remove("OnEntityCreated", "dothethingtothescanners")
hook.Add("OnEntityCreated", "dothethingtothescanners", function( ent )
if not IsValid( ent ) then return end
if ent:GetClass() ~= "npc_clawscanner" then return end
timer.Simple(0, function()
newScanner( ent )
end)
end )
local function setOpen( claw )
local isOpen = claw:GetSaveTable()["m_bIsOpen"]
if not isOpen then
claw:SetSaveValue("m_bIsOpen", true)
end
end
local function setClosed( claw )
local isOpen = claw:GetSaveTable()["m_bIsOpen"]
if isOpen then
claw:SetSaveValue("m_bIsOpen", false)
end
end
local function targetEvaded(claw)
local target = claw:GetTarget()
claw:MarkEnemyAsEluded()
setRelationship(claw, target, D_LI)
claw:ClearEnemyMemory()
claw:ClearSchedule()
claw:ExitScriptedSequence()
claw:ClearGoal()
claw:LostEnemySound()
claw:SetSaveValue( "ShouldInspect", false )
claw:Fire("ClearFollowTarget")
claw:SetSchedule( SCHED_IDLE_WANDER )
-- Probably doesn't work
-- TODO: How the hell do we get this thing to clear its target
claw:SetSaveValue("m_hTargetEnt", NULL )
setClosed( claw )
end
local function stopSound(claw)
if claw.IsPlaying then
claw.IsPlaying = false
claw:StopSound( Sounds.Pursuing.name )
end
end
local function startSound(claw)
if not claw.IsPlaying then
claw.IsPlaying = true
claw:EmitSound(Sounds.Pursuing.name)
end
end
local function setClawBeamColor(claw, col)
if IsValid( claw.beam ) then claw.beam:SetColor( col ) end
end
local function handleTargetInteraction(claw)
local target = claw:GetTarget()
if not IsValid( target ) then
stopSound(claw)
setClawBeamColor(claw, WHITE)
return
end
if not target:IsPlayer() then
stopSound(claw)
targetEvaded(claw)
setClawBeamColor(claw, WHITE)
return
end
local targetIsWanted = target:getDarkRPVar( "wanted" )
local canSeeTarget = claw:TestPVS( target )
if not targetIsWanted then
stopSound(claw)
targetEvaded(claw)
setClawBeamColor(claw, WHITE)
return
end
if canSeeTarget then
startSound(claw)
setOpen( claw )
setClawBeamColor(claw, beamColor)
claw:SetSaveValue( "ShouldInspect", true )
claw.lastSeenTarget = CurTime()
for k, v in pairs(claws) do
claw:UpdateEnemyMemory(target, target:GetPos())
end
return
end
local hasEvaded = claw.lastSeenTarget and claw.lastSeenTarget <= CurTime() - 5
if hasEvaded then
print("Target evaded us (last seen too long ago")
stopSound(claw)
targetEvaded(claw)
setClawBeamColor(claw, WHITE)
end
end
timer.Remove("claw-target-think")
timer.Create("claw-target-think", 0.5, 0, function()
beamColor = ( beamColor == RED and BLUE ) or RED
for k, claw in pairs(claws) do
if IsValid( claw ) then
handleTargetInteraction( claw )
else
table.remove( claws, k )
end
end
end)
--[[
hook.Add("Think", "ClearClawTargets", function()
for k, claw in pairs( claws ) do
if IsValid( claw ) then
local target = claw:GetTarget()
if not ( target and IsValid( target ) and target:IsPlayer() and target:getDarkRPVar( "wanted" ) == true ) then
print("Target isn't valid or isn't wanted. Clearing")
targetEvaded( claw )
print("Ran Target Evaded")
if claw:GetCurrentSchedule() ~= SCHED_IDLE_WANDER then
print("Forcing IDLE WANDER")
claw:ClearSchedule()
claw:SetSchedule(SCHED_IDLE_WANDER)
end
end
else
table.remove( claws, k )
end
end
end )
--]]
timer.Remove("clawtest")
timer.Create("clawtest", 0.1, 0, function()
for k, claw in pairs(claws) do
if IsValid( claw ) then
local target = claw:GetTarget()
if target and IsValid( target ) and target:IsPlayer() then
local isWanted = target:getDarkRPVar( "wanted" )
if isWanted then
-- Next attack is the next Flash, setting it to 0 seems to force an instant flash
claw:SetSaveValue("m_flNextAttack", math.Rand(0, 0.1))
claw:SetSaveValue( "m_flNextFlinchTime", 0 )
-- Seems to fire at -9ish seconds for some reason
claw:SetSaveValue("m_fNextSpotlightTime", -9)
claw:SetSaveValue( "m_bPerformAvoidance", true )
claw:SetSaveValue( "m_bPlayerAvoidState", true )
else
targetEvaded( claw )
end
end
else
table.remove( claws, k )
end
end
end)
hook.Remove("OnEntityCreated", "ClawTest")
hook.Add("OnEntityCreated", "ClawTest", function(ent)
if ent:GetClass() ~= "beam" then return end
timer.Simple( 0, function()
if not IsValid( ent ) then return end
local ownerEnt = ent:GetSaveTable()["m_hOwnerEntity"]
if not IsValid( ownerEnt ) then return end
if ownerEnt:GetClass() ~= "npc_clawscanner" then return end
beams[ent] = true
ownerEnt.beam = ent
end)
end)
hook.Remove("EntityRemoved", "ClawTest3")
hook.Add("EntityRemoved", "ClawTest3", function(ent)
if beams[ent] then
beams[ent] = nil
local ownerEnt = ent:GetSaveTable()["m_pParent"]
if not IsValid( ownerEnt ) then return end
ownerEnt.beam = nil
return
end
if table.HasValue(claws, ent) then
stopSound( ent )
table.RemoveByValue( claws, ent )
end
end)
hook.Remove("DarkRPVarChanged", "Clawtest4")
hook.Add("DarkRPVarChanged", "Clawtest4", function(ply, var, old, new)
if var ~= "wanted" then return end
-- Has become wanted
if new == true then
for k, claw in pairs( claws ) do
if IsValid( claw ) then
claw:ClearEnemyMemory()
setRelationship(claw, ply, D_HT)
claw:UpdateEnemyMemory(ply, ply:GetPos())
claw:NavSetGoalTarget( ply, Vector(100,100,100) )
if not claw:GetTarget() then
claw:SetTarget( ply )
claw:SetSaveValue( "ShouldInspect", true )
end
end
end
return
end
-- Has become unwanted
for k, claw in pairs( claws ) do
if IsValid( claw ) then
if claw:GetTarget() == ply then
targetEvaded( claw )
end
setRelationship(claw, ply, D_LI)
else
table.remove( claws, k )
end
end
end)
hook.Add("PostEntityTakeDamage", "ClawTakeDamage", function( ent, dmg, took )
if not took then return end
if ent:GetClass() ~= "npc_clawscanner" then return end
local attacker = dmg:GetAttacker()
if not IsValid( attacker ) then return end
if not attacker:IsPlayer() then return end
local isWanted = attacker:getDarkRPVar( "wanted" )
if isWanted then return end
attacker:setDarkRPVar( "wanted", true )
attacker:setDarkRPVar( "wantedReason", "Attacking government property" )
end )
local recipientJobs = { ["Civil Protection"] = true, ["Civil Protection Chief"] = true, ["Mayor"] = true }
-- Destruction detection
hook.Remove("OnNPCKilled", "ClawScannerDestroyed")
hook.Add("OnNPCKilled", "ClawScannerDestroyed", function( killedEnt, attacker, inflictor )
print("Ent killed: " .. killedEnt:GetClass())
if not IsValid( killedEnt ) then return end
if killedEnt:GetClass() ~= "npc_clawscanner" then return end
local recipients = {}
for k, ply in pairs(player.GetAll()) do
local job = team.GetName( ply:Team() )
if recipientJobs[job] then table.insert(recipients, ply) end
end
--[[
net.Start("CPScannerKilled")
net.WriteEntity(killedEnt)
net.Send(recipients)
--]]
end)
for k, claw in pairs( claws ) do
if IsValid( claw ) then
newScanner( claw )
else
table.remove( claws, k )
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment