Advertisement
Guest User

Lua Lag Compensation v0.6

a guest
Dec 1st, 2010
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.37 KB | None | 0 0
  1. ----------------------------------------------------------------
  2. --LUA Lag Compensation version 0.6 by FlooD---------------------
  3. ----------------------------------------------------------------
  4. --thx to Jermuk for his custom server, which first encouraged---
  5. --    me to make lag compensation.------------------------------
  6. --thx to lasthope and def3ct for initial testing.---------------
  7. --thx to 3rr0r for ideas and suggestions for refining the code.-
  8. ----------------------------------------------------------------
  9.  
  10.  
  11. --[[initialization, arrays, reseting]]--------------------------
  12. ping = {} --array of filtered pings of living players
  13.  
  14. mode = {{}, {}, {}} --glock burst, famas burst, zoom
  15.  
  16. buffer = {} --buffer of current and past positions
  17. buffer[1] = {} --x coordinate
  18. buffer[2] = {} --y coordinate
  19.  
  20. enable = {}
  21.  
  22. function reset(id)
  23.     mode[1][id] = 0
  24.     mode[2][id] = 0
  25.     mode[3][id] = 0
  26.     buffer[1][id] = {}
  27.     buffer[2][id] = {}
  28.     ping[id] = nil
  29. end
  30.  
  31. function clear(id)
  32.     reset(id)
  33.     enable[id] = 1
  34. end
  35.  
  36. for i = 1, 32 do --initial
  37.     clear(i)
  38. end
  39. addhook("leave", "clear")
  40. addhook("die", "reset")
  41.  
  42. function updateping(id)
  43.     local actualping = player(id, "ping")
  44.     local lastping = ping[id]
  45.     if not lastping then lastping = 0 end
  46.     if actualping then
  47.         if actualping - lastping <= 30 or lastping == 0 then --regular
  48.             ping[id] = actualping
  49.         else --spike is "damped"
  50.             ping[id] = 0.7 * lastping + 0.3 * actualping
  51.         end
  52.     end
  53. end
  54. addhook("spawn", "updateping")
  55. ----------------------------------------------------------------
  56.  
  57.  
  58. --[[periodic functions]]----------------------------------------
  59. frame = 1
  60. BUFFER_SIZE = 25
  61. function updatebuffer()
  62.     frame = frame + 1
  63.     for i in pairs(ping) do
  64.         buffer[1][i][frame], buffer[2][i][frame] = player(i, "x"), player(i, "y")
  65.         buffer[1][i][frame - BUFFER_SIZE], buffer[2][i][frame - BUFFER_SIZE] = nil, nil
  66.     end
  67. end
  68. addhook("always", "updatebuffer")
  69.  
  70. function onsecond()
  71.     for i in pairs(ping) do
  72.         updateping(i)
  73.     end
  74. end
  75. addhook("second", "onsecond")
  76. ----------------------------------------------------------------
  77.  
  78.  
  79. --[[new hit system]]--------------------------------------------
  80. addhook("hit", "onhit")
  81. function onhit(v, id, wpn)
  82.     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.
  83.         return 1
  84.     end
  85. end
  86.  
  87. math.randomseed(os.time())
  88. math.randomseed(os.time() * math.sin(os.time() * math.random()))
  89. addhook("attack", "onattack")
  90. function onattack(id)
  91.     local wpn = player(id, "weapon")
  92.     if wpn == 51 or wpn == 47 or enable[id] ~= 1 then --HEs and RPGs processed normally.
  93.         return
  94.     end
  95.  
  96.     local dmg = itemtype(wpn, "dmg") * game("mp_damagefactor")
  97.  
  98.     if (wpn == 2 and mode[1][id] == 1) or (wpn == 39 and mode[2][id] == 1) then --burst weapons
  99.         dmg = math.floor(dmg * 0.64 + 0.5)
  100.         local rot1 = player(id, "rot") - 6 + 12 * math.random()
  101.         local rot2 = player(id, "rot") + 6 + 8 * math.random()
  102.         local rot3 = player(id, "rot") - 6 - 8 * math.random()
  103.         simulate_attack(id, wpn, dmg, rot1)
  104.         simulate_attack(id, wpn, dmg, rot2)
  105.         simulate_attack(id, wpn, dmg, rot3)
  106.         return
  107.     elseif wpn == 10 or wpn == 11 then
  108.         for i=1,5 do
  109.             simulate_attack(id, wpn, dmg, player(id, "rot") - 20 + 40 * math.random(), 180)
  110.         end
  111.         return
  112.     end
  113.    
  114.     if mode[3][id] == 1 then --scoped weapons
  115.         dmg = itemtype(wpn, "dmg_z1") * game("mp_damagefactor")
  116.     elseif mode[3][id] == 2 then
  117.         dmg = itemtype(wpn, "dmg_z2") * game("mp_damagefactor")
  118.     end
  119.  
  120.     local rot = player(id, "rot") + itemtype(wpn, "dispersion") * (2 * math.random() - 1)
  121.     simulate_attack(id, wpn, dmg, rot)
  122. end
  123.  
  124. addhook("attack2", "onattack2")
  125. function onattack2(id, m)
  126.     local wpn = player(id, "weapon")
  127.     if wpn == 50 or wpn == 69 then
  128.         if enable[id] == 1 then
  129.             simulate_attack(id, wpn, itemtype(wpn, "dmg_z1") * game("mp_damagefactor"))
  130.         end
  131. ----------------------------------------------------------------
  132.  
  133.  
  134. --[[syncs burst/zoom for each player to actual cs2d burst/zoom]]
  135.     elseif wpn == 2 then
  136.         mode[1][id] = m
  137.     elseif wpn == 39 then
  138.         mode[2][id] = m
  139.     elseif wpn ~= 32 and wpn >= 31 and wpn <= 37 then
  140.         mode[3][id] = m
  141.     end
  142. end
  143.  
  144. addhook("reload", "unzoom")
  145. addhook("select", "unzoom")
  146. function unzoom(id)
  147.     mode[3][id] = 0
  148. end
  149.  
  150. addhook("drop", "ondrop")
  151. function ondrop(id,iid,wpn,ain,a,m)
  152.     mode[3][id] = 0
  153.     if wpn == 2 then
  154.         mode[1][id] = 0
  155.     elseif wpn == 39 then
  156.         mode[2][id] = 0
  157.     end
  158. end
  159.  
  160. addhook("collect", "oncollect")
  161. function oncollect(id,iid,wpn,ain,a,m)
  162.     if wpn == 2 then
  163.         mode[1][id] = m
  164.     elseif wpn == 39 then
  165.         mode[2][id] = m
  166.     end
  167. end
  168. ----------------------------------------------------------------
  169.  
  170.  
  171. --[[bullet simulation]]-----------------------------------------
  172.  
  173. --[[simulates the shooting of a bullet of damage (dmg) from
  174. (wpn) by (id) with angle (rot) and range (range). it has two
  175. parts. part 1 finds bullet's path before hitting a wall; part 2
  176. calculates hits on other players (with lag compensation).]]
  177. function simulate_attack(id, wpn, dmg, rot, range)
  178.     if not wpn then wpn = player(id, "weapon") end
  179.     if not dmg then dmg = itemtype(wpn, "dmg") * game("mp_damagefactor") end
  180.     if not rot then rot = player(id, "rot") end
  181.     if not range then range = itemtype(wpn, "range") end
  182.  
  183.     local start_x = player(id, "x")
  184.     local start_y = player(id, "y")
  185.     local end_x = start_x + (3 * range) * math.sin(math.rad(rot))
  186.     local end_y = start_y - (3 * range) * math.cos(math.rad(rot))
  187.     local tile_x = math.floor(start_x / 32)
  188.     local tile_y = math.floor(start_y / 32)
  189.  
  190.     --part 1 - find the intersection of the bullet with the first wall it hits.
  191.     local inc_x, inc_y --specifies the direction in which to search.
  192.  
  193.     if rot < 0 then
  194.         inc_x = -1
  195.     elseif rot > 0 and rot ~= 180 then
  196.         inc_x = 1
  197.     end
  198.  
  199.     if math.abs(rot) > 90 then
  200.         inc_y = 1
  201.     elseif math.abs(rot) < 90 then
  202.         inc_y = -1
  203.     end
  204.  
  205.     while not tile(tile_x, tile_y, "wall") do
  206.         local temp_x, temp_y = tile_x, tile_y
  207.         if inc_x and intersect(start_x, start_y, end_x, end_y, topixel(temp_x + inc_x), topixel(temp_y), 16) then
  208.             tile_x = temp_x + inc_x
  209.         end
  210.         if inc_y and intersect(start_x, start_y, end_x, end_y, topixel(temp_x), topixel(temp_y + inc_y), 16) then
  211.             tile_y = temp_y + inc_y
  212.         end
  213.         if tile_x == temp_x and tile_y == temp_y then
  214.             break
  215.         end
  216.     end
  217.  
  218.     if tile(tile_x, tile_y, "wall") then
  219.         end_x, end_y = intersect(start_x, start_y, end_x, end_y, topixel(tile_x), topixel(tile_y), 16)
  220.     end
  221.  
  222.     --part 2 - detect hits
  223.     local frames = math.floor(player(id, "ping") / 20)
  224.     if frames > (BUFFER_SIZE - 1) then
  225.         frames = (BUFFER_SIZE - 1)
  226.     end
  227.  
  228.     local victims = {}
  229.     if game("sv_friendlyfire") == "0" then
  230.         for i in pairs(ping) do
  231.             if player(i, "team") ~= player(id, "team") then
  232.                 victims[i] = true
  233.             end
  234.         end
  235.     else
  236.         for i in pairs(ping) do
  237.             victims[i] = true
  238.         end
  239.         victims[id] = nil
  240.     end
  241.  
  242.     for i in pairs(victims) do
  243.         if intersect(start_x, start_y, end_x, end_y, buffer[1][i][frame - frames], buffer[2][i][frame - frames], 12) then
  244.             local newarmor = player(i, "armor") - dmg
  245.             if newarmor < 0 then
  246.                 newarmor = 0
  247.             end
  248.             local newhealth = player(i, "health") - (dmg - math.floor(game("mp_kevlar") * (player(i, "armor") - newarmor)))
  249.             if newhealth > 0 then
  250.                 parse("sethealth "..i.." "..newhealth)
  251.                 parse("setarmor "..i.." "..newarmor)
  252.             else
  253.                 parse("customkill "..id.." "..itemtype(wpn, "name").." "..i)
  254.             end
  255.         end
  256.     end
  257. end
  258.  
  259. --the following three functions are used in simulate_attack.
  260.  
  261. --converts a tile number to the tile's center pixel.
  262. function topixel(tile)
  263.     return (tile * 32) + 16
  264. end
  265.  
  266. --quick test to see if i is in between s and e. used in intersect().
  267. function isinorder(s, i, e)
  268.     return (e >= i and i >= s) or (e <= i and i <= s)
  269. end
  270.  
  271. --[[returns the first point of intersection between a box centered at (bx, by) with
  272. half side length (bl) and a line segment starting from (sx, sy) and ending at (ex, ey).
  273. if the line segment is enclosed by the box, (ex, ey) is returned.]]
  274. function intersect(sx, sy, ex, ey, bx, by, bl)
  275.     if math.abs(sx - bx) <= bl and math.abs(sy - by) <= bl then
  276.         if math.abs(ex - bx) <= bl and math.abs(ey - by) <= bl then
  277.             return ex, ey
  278.         else
  279.             sx, sy, ex, ey = ex, ey, sx, sy
  280.         end
  281.     end
  282.  
  283.     local i_x, i_y
  284.  
  285.     if ey > sy then
  286.         i_y = by - bl
  287.     elseif ey < sy then
  288.         i_y = by + bl
  289.     end
  290.     if i_y and isinorder(sy, i_y, ey) then
  291.         i_x = ((ex - sx) * i_y + (sx * ey - sy * ex)) / (ey - sy)
  292.         if math.abs(i_x - bx) <= bl and isinorder(sx, i_x, ex) then
  293.             return i_x, i_y
  294.         end
  295.     end
  296.  
  297.     if ex > sx then
  298.         i_x = bx - bl
  299.     elseif ex < sx then
  300.         i_x = bx + bl
  301.     end
  302.     if i_x and isinorder(sx, i_x, ex) then
  303.         i_y = ((ey - sy) * i_x + (sy * ex - sx * ey)) / (ex - sx)
  304.         if math.abs(i_y - by) <= bl and isinorder(sy, i_y, ey) then
  305.             return i_x, i_y
  306.         end
  307.     end
  308. end
  309. ----------------------------------------------------------------
  310.  
  311.  
  312. --[[debug stuff]]-----------------------------------------------
  313. addhook("serveraction","onserveraction")
  314. function onserveraction(id, action)
  315.     if action == 2 then
  316.         if enable[id] == 1 then
  317.             enable[id] = 0
  318.             msg2(id, "©255100000Lag comp. disabled (for yourself).")
  319.         else
  320.             enable[id] = 1
  321.             msg2(id, "©255100000Lag comp. enabled (for yourself).")
  322.         end
  323.     elseif action == 1 then
  324.         msg2(id, "©255100000current ping: "..(ping[id] or (player(id, "ping").." (dead)")))
  325.     end
  326. end
  327. ----------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement