• Invisible NPCs
    0 replies, posted
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.