Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ----------------------------------------------------------------
- --LUA Lag Compensation version 0.6 by FlooD---------------------
- ----------------------------------------------------------------
- --thx to Jermuk for his custom server, which first encouraged---
- -- me to make lag compensation.------------------------------
- --thx to lasthope and def3ct for initial testing.---------------
- --thx to 3rr0r for ideas and suggestions for refining the code.-
- ----------------------------------------------------------------
- --[[initialization, arrays, reseting]]--------------------------
- ping = {} --array of filtered pings of living players
- mode = {{}, {}, {}} --glock burst, famas burst, zoom
- buffer = {} --buffer of current and past positions
- buffer[1] = {} --x coordinate
- buffer[2] = {} --y coordinate
- enable = {}
- function reset(id)
- mode[1][id] = 0
- mode[2][id] = 0
- mode[3][id] = 0
- buffer[1][id] = {}
- buffer[2][id] = {}
- ping[id] = nil
- end
- function clear(id)
- reset(id)
- enable[id] = 1
- end
- for i = 1, 32 do --initial
- clear(i)
- end
- addhook("leave", "clear")
- addhook("die", "reset")
- function updateping(id)
- local actualping = player(id, "ping")
- local lastping = ping[id]
- if not lastping then lastping = 0 end
- if actualping then
- if actualping - lastping <= 30 or lastping == 0 then --regular
- ping[id] = actualping
- else --spike is "damped"
- ping[id] = 0.7 * lastping + 0.3 * actualping
- end
- end
- end
- addhook("spawn", "updateping")
- ----------------------------------------------------------------
- --[[periodic functions]]----------------------------------------
- frame = 1
- BUFFER_SIZE = 25
- function updatebuffer()
- frame = frame + 1
- for i in pairs(ping) do
- buffer[1][i][frame], buffer[2][i][frame] = player(i, "x"), player(i, "y")
- buffer[1][i][frame - BUFFER_SIZE], buffer[2][i][frame - BUFFER_SIZE] = nil, nil
- end
- end
- addhook("always", "updatebuffer")
- function onsecond()
- for i in pairs(ping) do
- updateping(i)
- end
- end
- addhook("second", "onsecond")
- ----------------------------------------------------------------
- --[[new hit system]]--------------------------------------------
- addhook("hit", "onhit")
- function onhit(v, id, wpn)
- if wpn ~= 51 and wpn ~= 0 and wpn ~= 47 and id ~= 0 and enable[id] == 1 then --override cs2d's internal hit system for most instances.
- return 1
- end
- end
- math.randomseed(os.time())
- math.randomseed(os.time() * math.sin(os.time() * math.random()))
- addhook("attack", "onattack")
- function onattack(id)
- local wpn = player(id, "weapon")
- if wpn == 51 or wpn == 47 or enable[id] ~= 1 then --HEs and RPGs processed normally.
- return
- end
- local dmg = itemtype(wpn, "dmg") * game("mp_damagefactor")
- if (wpn == 2 and mode[1][id] == 1) or (wpn == 39 and mode[2][id] == 1) then --burst weapons
- dmg = math.floor(dmg * 0.64 + 0.5)
- local rot1 = player(id, "rot") - 6 + 12 * math.random()
- local rot2 = player(id, "rot") + 6 + 8 * math.random()
- local rot3 = player(id, "rot") - 6 - 8 * math.random()
- simulate_attack(id, wpn, dmg, rot1)
- simulate_attack(id, wpn, dmg, rot2)
- simulate_attack(id, wpn, dmg, rot3)
- return
- elseif wpn == 10 or wpn == 11 then
- for i=1,5 do
- simulate_attack(id, wpn, dmg, player(id, "rot") - 20 + 40 * math.random(), 180)
- end
- return
- end
- if mode[3][id] == 1 then --scoped weapons
- dmg = itemtype(wpn, "dmg_z1") * game("mp_damagefactor")
- elseif mode[3][id] == 2 then
- dmg = itemtype(wpn, "dmg_z2") * game("mp_damagefactor")
- end
- local rot = player(id, "rot") + itemtype(wpn, "dispersion") * (2 * math.random() - 1)
- simulate_attack(id, wpn, dmg, rot)
- end
- addhook("attack2", "onattack2")
- function onattack2(id, m)
- local wpn = player(id, "weapon")
- if wpn == 50 or wpn == 69 then
- if enable[id] == 1 then
- simulate_attack(id, wpn, itemtype(wpn, "dmg_z1") * game("mp_damagefactor"))
- end
- ----------------------------------------------------------------
- --[[syncs burst/zoom for each player to actual cs2d burst/zoom]]
- elseif wpn == 2 then
- mode[1][id] = m
- elseif wpn == 39 then
- mode[2][id] = m
- elseif wpn ~= 32 and wpn >= 31 and wpn <= 37 then
- mode[3][id] = m
- end
- end
- addhook("reload", "unzoom")
- addhook("select", "unzoom")
- function unzoom(id)
- mode[3][id] = 0
- end
- addhook("drop", "ondrop")
- function ondrop(id,iid,wpn,ain,a,m)
- mode[3][id] = 0
- if wpn == 2 then
- mode[1][id] = 0
- elseif wpn == 39 then
- mode[2][id] = 0
- end
- end
- addhook("collect", "oncollect")
- function oncollect(id,iid,wpn,ain,a,m)
- if wpn == 2 then
- mode[1][id] = m
- elseif wpn == 39 then
- mode[2][id] = m
- end
- end
- ----------------------------------------------------------------
- --[[bullet simulation]]-----------------------------------------
- --[[simulates the shooting of a bullet of damage (dmg) from
- (wpn) by (id) with angle (rot) and range (range). it has two
- parts. part 1 finds bullet's path before hitting a wall; part 2
- calculates hits on other players (with lag compensation).]]
- function simulate_attack(id, wpn, dmg, rot, range)
- if not wpn then wpn = player(id, "weapon") end
- if not dmg then dmg = itemtype(wpn, "dmg") * game("mp_damagefactor") end
- if not rot then rot = player(id, "rot") end
- if not range then range = itemtype(wpn, "range") end
- local start_x = player(id, "x")
- local start_y = player(id, "y")
- local end_x = start_x + (3 * range) * math.sin(math.rad(rot))
- local end_y = start_y - (3 * range) * math.cos(math.rad(rot))
- local tile_x = math.floor(start_x / 32)
- local tile_y = math.floor(start_y / 32)
- --part 1 - find the intersection of the bullet with the first wall it hits.
- local inc_x, inc_y --specifies the direction in which to search.
- if rot < 0 then
- inc_x = -1
- elseif rot > 0 and rot ~= 180 then
- inc_x = 1
- end
- if math.abs(rot) > 90 then
- inc_y = 1
- elseif math.abs(rot) < 90 then
- inc_y = -1
- end
- while not tile(tile_x, tile_y, "wall") do
- local temp_x, temp_y = tile_x, tile_y
- if inc_x and intersect(start_x, start_y, end_x, end_y, topixel(temp_x + inc_x), topixel(temp_y), 16) then
- tile_x = temp_x + inc_x
- end
- if inc_y and intersect(start_x, start_y, end_x, end_y, topixel(temp_x), topixel(temp_y + inc_y), 16) then
- tile_y = temp_y + inc_y
- end
- if tile_x == temp_x and tile_y == temp_y then
- break
- end
- end
- if tile(tile_x, tile_y, "wall") then
- end_x, end_y = intersect(start_x, start_y, end_x, end_y, topixel(tile_x), topixel(tile_y), 16)
- end
- --part 2 - detect hits
- local frames = math.floor(player(id, "ping") / 20)
- if frames > (BUFFER_SIZE - 1) then
- frames = (BUFFER_SIZE - 1)
- end
- local victims = {}
- if game("sv_friendlyfire") == "0" then
- for i in pairs(ping) do
- if player(i, "team") ~= player(id, "team") then
- victims[i] = true
- end
- end
- else
- for i in pairs(ping) do
- victims[i] = true
- end
- victims[id] = nil
- end
- for i in pairs(victims) do
- if intersect(start_x, start_y, end_x, end_y, buffer[1][i][frame - frames], buffer[2][i][frame - frames], 12) then
- local newarmor = player(i, "armor") - dmg
- if newarmor < 0 then
- newarmor = 0
- end
- local newhealth = player(i, "health") - (dmg - math.floor(game("mp_kevlar") * (player(i, "armor") - newarmor)))
- if newhealth > 0 then
- parse("sethealth "..i.." "..newhealth)
- parse("setarmor "..i.." "..newarmor)
- else
- parse("customkill "..id.." "..itemtype(wpn, "name").." "..i)
- end
- end
- end
- end
- --the following three functions are used in simulate_attack.
- --converts a tile number to the tile's center pixel.
- function topixel(tile)
- return (tile * 32) + 16
- end
- --quick test to see if i is in between s and e. used in intersect().
- function isinorder(s, i, e)
- return (e >= i and i >= s) or (e <= i and i <= s)
- end
- --[[returns the first point of intersection between a box centered at (bx, by) with
- half side length (bl) and a line segment starting from (sx, sy) and ending at (ex, ey).
- if the line segment is enclosed by the box, (ex, ey) is returned.]]
- function intersect(sx, sy, ex, ey, bx, by, bl)
- if math.abs(sx - bx) <= bl and math.abs(sy - by) <= bl then
- if math.abs(ex - bx) <= bl and math.abs(ey - by) <= bl then
- return ex, ey
- else
- sx, sy, ex, ey = ex, ey, sx, sy
- end
- end
- local i_x, i_y
- if ey > sy then
- i_y = by - bl
- elseif ey < sy then
- i_y = by + bl
- end
- if i_y and isinorder(sy, i_y, ey) then
- i_x = ((ex - sx) * i_y + (sx * ey - sy * ex)) / (ey - sy)
- if math.abs(i_x - bx) <= bl and isinorder(sx, i_x, ex) then
- return i_x, i_y
- end
- end
- if ex > sx then
- i_x = bx - bl
- elseif ex < sx then
- i_x = bx + bl
- end
- if i_x and isinorder(sx, i_x, ex) then
- i_y = ((ey - sy) * i_x + (sy * ex - sx * ey)) / (ex - sx)
- if math.abs(i_y - by) <= bl and isinorder(sy, i_y, ey) then
- return i_x, i_y
- end
- end
- end
- ----------------------------------------------------------------
- --[[debug stuff]]-----------------------------------------------
- addhook("serveraction","onserveraction")
- function onserveraction(id, action)
- if action == 2 then
- if enable[id] == 1 then
- enable[id] = 0
- msg2(id, "©255100000Lag comp. disabled (for yourself).")
- else
- enable[id] = 1
- msg2(id, "©255100000Lag comp. enabled (for yourself).")
- end
- elseif action == 1 then
- msg2(id, "©255100000current ping: "..(ping[id] or (player(id, "ping").." (dead)")))
- end
- end
- ----------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement