Hi people, I'm working on a stealth mod, and everything seems to be working fine overall. NPCs stay neutral to the player, until he's detected and the enemies start chasing him. However, sometimes when an enemy spots a player, the npc becomes completely invisible, and if he dies, the game crash. Its weird, because my mod doesn't manipulate NPC models in any way, it just messes with relationships. Here's some code:
This is the main "AI" timer. Its probably too much stuff for a timer running every .2 seconds, but nobody has reported FPS drops yet.
[CODE]
timer.Create("NPCStealthThink",.2,0,function() --Keep checking what npcs are alert to
if GetConVarNumber("stealth_enabled") == 0 then return end
-- Check Player LOS
for k = #npctable, 1, -1 do
local v = npctable[k]
if IsValid(v) then
-- This only runs once, it sets initial position
if v.initpos == nil then v.initpos = v:GetPos() end
if v.initangles == nil then v.initangles = v:GetAngles() end
-- checkLOS is a long function that doesn't writes anything
-- It just does calculations and then executes alert() or investigate()
for o,p in pairs(player.GetAll()) do
checkLOS(p,v)
end
-- Check corpse LOS
-- This makes them move to investigate corpses
if GetConVarNumber("stealth_enabled") != 0 then
local nearestcorpse = nil
local nearestdistance = -1
for o = #corpsetable, 1, -1 do
local p = corpsetable[o]
if IsValid(p) then
if !table.HasValue(v.seencorpses,p) then
local dist = checkEntityLOS(p,v)
if dist != -1 then
table.insert(v.seencorpses,p)
if nearestdistance == -1 or dist < nearestdistance then
nearestdistance = dist
nearestcorpse = p
end
end
end
else
table.remove(corpsetable,o)
end
end
if IsValid(nearestcorpse) then investigate(v, nearestcorpse:GetPos(), true, false) end
end
-- Remove null enemies from npc memory
for o = #v.MEnemies, 1, -1 do
local p = v.MEnemies[o]
if !IsValid(p) then table.remove(v.MEnemies,o) end
end
else
table.remove(npctable,k)
-- Send Clients the signal to remove NPC
umsg.Start( "RemoveNPCfromTable" )
umsg.Entity( v )
umsg.End();
end
end
-- More stuff that really doesn't matter
[/CODE]
This function is executed when an enemy is alerted:
[CODE]
local function alert(ply, npc, silent)
if not npc.MEnemies or table.HasValue(npc.MEnemies, ply) then return end
if !ply:Alive() then return end
table.insert(npc.MEnemies,ply)
npc:AddEntityRelationship(ply, D_HT, 0)
npc.investigating = 0
npc.targetpos = nil
npc.running = false
-- Tell player that he alerted someone
umsg.Start( "NPCAlerted", ply )
umsg.Entity( npc )
umsg.Bool( silent )
umsg.End();
-- Broadcast alert effect
umsg.Start( "NPCEffect" )
umsg.Entity( npc )
umsg.String( "alert" )
umsg.End();
-- When an enemy spots the player, he alerts nearby enemies after a few seconds.
-- When a nearby enemy is alerted, "silent" is true, and it wont alert nearby enemies again
if silent == false then
timer.Simple(GetConVarNumber("stealth_backuptime"), function()
if IsValid(npc) and IsValid(ply) then
for k, v in pairs(npctable) do
if IsValid(v) and v != npc and npc:GetPos():Distance(v:GetPos()) <= GetConVarNumber("stealth_backuprange") then alert(ply, v, true) end
end
end
end)
end
end
[/CODE]
Finally, this is the function that tells enemies to investigate something.
[CODE]
local function investigate(npc, pos, run, nearest)
-- Ignore the "nearest" parameter, is old
if #npc.MEnemies != 0 then return end
if npc.invdelay > CurTime() then return end
npc.invdelay = CurTime() + 3
if npc.investigating == 0 then
-- Broadcast alert effect
umsg.Start( "NPCEffect" )
umsg.Entity( npc )
umsg.String( "caution" )
umsg.End();
end
npc.investigating = 1
--if nearest == false or (nearest == true and (npc.targetpos == nil or npc:GetPos():Distance(npc.targetpos) >= npc:GetPos():Distance(pos))) then
npc.targetpos = pos
npc:SetLastPosition(pos)
if run == false and npc.running == false then
npc:SetSchedule( SCHED_FORCED_GO )
else
npc:SetSchedule( SCHED_FORCED_GO_RUN )
npc.running = true
end
--end
end
[/CODE]
Any idea of what could be wrong?
EDIT: It happens quite often. Once one enemy spots the player, any other enemy that detects the player from a certain distance, has a high chance of becoming invisible. They reappear randomly for a second and hide again. I don't know why is this happening.
[editline]10th February 2016[/editline]
Nevermind, I solved it myself. I removed this:
[CODE]npc:SetTarget(npc)
npc:SetEnemy(npc)[/CODE]
I have no idea why this was causing that issue, but it's fixed now.
Sorry, you need to Log In to post a reply to this thread.