zcnpci/lua/entities/npc_ragdoll_target.lua

120 lines
3.9 KiB
Lua
Raw Permalink Normal View History

2026-05-30 22:42:24 +00:00
AddCSLuaFile()
ENT.Type = "ai"
ENT.Base = "base_ai"
ENT.AutomaticFrameAdvance = true
local debug_show_ragdoll_targets = CreateConVar("zcnpci_debug_show_ragdoll_targets", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local should_follow_head = CreateConVar("zcnpci_target_should_follow_head", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local stop_targeting_when_unconscious = CreateConVar("zcnpci_no_unconscious_targeting", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local vector_offset_to_shoot_at = Vector(0, 0, 8)
2026-05-30 22:42:24 +00:00
local function UpdateRelationship(ent, me)
if !IsValid(ent) or !ent:IsNPC() or (ent:GetClass() == "npc_ragdoll_target") then return end
2026-05-30 22:42:24 +00:00
if ent:Disposition(me.dummy_entity) == D_HT then
--print("Ragdoll target of class "..me.ragdoll_to_follow.class_in_previous_life.." is hated by a "..ent:GetClass())
2026-05-31 01:35:28 +00:00
ent:AddEntityRelationship(me, D_HT, -1)
else
ent:AddEntityRelationship(me, D_NU, -1)
2026-05-30 22:42:24 +00:00
end
end
local function RemoveRelationship(ent, me)
if !IsValid(ent) or !ent:IsNPC() or (ent:GetClass() == "npc_ragdoll_target") then return end
2026-05-30 22:42:24 +00:00
ent:AddEntityRelationship(me, D_NU, -1)
ent:ClearEnemyMemory(me)
2026-05-31 01:35:28 +00:00
if ent:GetEnemy() == me then
ent:SetEnemy(nil)
ent:ClearSchedule()
2026-05-30 22:42:24 +00:00
end
end
function ENT:Classify()
return CLASS_NONE
end
2026-05-30 22:42:24 +00:00
function ENT:Initialize()
if SERVER then
self:SetModel("models/maxofs2d/hover_basic.mdl")
self:SetCollisionGroup(COLLISION_GROUP_NONE)
2026-05-30 22:42:24 +00:00
self:SetHullType(HULL_TINY_CENTERED)
self:SetNoDraw(!debug_show_ragdoll_targets:GetBool())
2026-05-30 22:42:24 +00:00
self.dummy_entity = ents.Create(self.ragdoll_to_follow.class_in_previous_life)
2026-05-31 01:35:28 +00:00
self.last_stop_targeting = nil
2026-05-30 22:42:24 +00:00
-- Have to use this collision group otherwise ragdoll will obstruct visibility of target
self.ragdoll_to_follow:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
2026-05-30 22:42:24 +00:00
hook.Add("OnEntityCreated", "zcnpci-"..self:GetCreationID(), function(new_entity)
if !IsValid(new_entity) or !new_entity:IsNPC() then return end
if !self.last_stop_targeting then
UpdateRelationship(new_entity, self)
end
end)
end
end
function ENT:Think()
if SERVER then
local ragdoll = self.ragdoll_to_follow
if !IsValid(ragdoll) then self:Remove(); return end
2026-05-30 22:42:24 +00:00
if should_follow_head:GetBool() then
local head = ragdoll:GetPhysicsObjectNum(ragdoll:TranslateBoneToPhysBone(ragdoll:LookupBone("ValveBiped.Bip01_Head1")))
self:SetPos(head:GetPos() + vector_offset_to_shoot_at)
else
self:SetPos(ragdoll:GetPos())
end
2026-05-30 22:42:24 +00:00
self:SetNoDraw(!debug_show_ragdoll_targets:GetBool())
if !ragdoll.organism then return true end
if !ragdoll.organism.alive then self:Remove(); return end
2026-06-02 20:52:55 +00:00
local should_stop_targeting = !stop_targeting_when_unconscious:GetBool() or (
2026-05-30 22:42:24 +00:00
(ragdoll.organism.consciousness <= 0.4) or
(ragdoll.organism.critical)
)
if (should_stop_targeting != self.last_stop_targeting) then
2026-05-30 22:42:24 +00:00
self.last_stop_targeting = should_stop_targeting
if should_stop_targeting then
self:SetColor(Color(255, 0, 0))
for i,ent in ipairs(ents.GetAll()) do
RemoveRelationship(ent, self)
end
else
2026-05-31 01:35:28 +00:00
self:SetColor(Color(0, 255, 0))
2026-05-30 22:42:24 +00:00
for i,ent in ipairs(ents.GetAll()) do
UpdateRelationship(ent, self)
end
end
end
self:NextThink(CurTime())
end
return true
end
function ENT:OnRemove()
if SERVER then
for i,ent in ipairs(ents.GetAll()) do
RemoveRelationship(ent, self)
end
2026-05-31 01:35:28 +00:00
self.dummy_entity:Remove()
2026-05-30 22:42:24 +00:00
hook.Remove("OnEntityCreated", "zcnpci-"..self:GetCreationID())
end
end