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 )