local Entity = FindMetaTable( "Entity" )
Entity.OldFireBullets = Entity.OldFireBullets or Entity.FireBullets
local toFire = {}
function Entity:FireBullets( bullet )
local copy = table.Copy( bullet )
copy.Tracer = 0
toFire[ self ] = toFire[ self ] or {}
table.insert( toFire[ self ], copy )
end
local function Tick()
local npcs = ents.FindByClass( "npc_*" )
-- Loop through all bullets to fire.
for ply, list in pairs( toFire ) do
if ( #list > 0 ) then
local reset = {}
local ping = ply:Ping() / 1000
for _, npc in pairs( npcs ) do
local backTime = CurTime() - ping
for _, info in ipairs( npc.Position or {} ) do
if ( info[ 1 ] > backTime ) then
reset[ npc ] = { npc:GetPos(), npc:GetAngles() }
npc:SetPos( info[ 2 ] )
npc:SetAngles( info[ 3 ] )
break
end
end
end
-- Fire the bullets.
for i, bullet in pairs( list ) do
ply:OldFireBullets( bullet )
list[ i ] = nil
end
-- Reset the NPCs positions.
for npc, info in pairs( reset ) do
npc:SetPos( info[ 1 ] )
npc:SetAngles( info[ 2 ] )
end
end
-- Saves time next tick by not having to loop through any more if there aren't any added.
toFire[ ply ] = nil
end
-- Save the NPCs positions.
for _, npc in pairs( npcs ) do
npc.Position = npc.Position or {}
table.insert( npc.Position, 1, { CurTime(), npc:GetPos(), npc:GetAngles() } )
npc.Position[ 100 ] = nil -- We only want to store a maximum of 100 entries.
end
end
hook.Add( "Tick", "NPCLagCompensation.Tick", Tick )