Guest User

LUA Lag Compensation

a guest
Nov 20th, 2010
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.93 KB | None | 0 0
  1. --LUA Lag Compensation version 0.5 by FlooD
  2. --thx to Jermuk for his custom server, which first encouraged me to make lag compensation.
  3. --thx to lasthope and def3ct for initial testing.
  4. --thx to 3rr0r for ideas and suggestions for refining the code.
  5.  
  6. mode = {{}, {}, {}} --glock burst, famas burst, zoom
  7.  
  8. frame = 0
  9. BUFFER_SIZE = 25
  10. buffer = {}
  11. buffer[1] = {} --x buffer
  12. buffer[2] = {} --y buffer
  13. function updatebuffer()
  14.     frame = frame + 1
  15.     for i = 1, 32 do
  16.         buffer[1][i][frame], buffer[2][i][frame] = player(i, "x"), player(i, "y")
  17.         buffer[1][i][frame - BUFFER_SIZE], buffer[2][i][frame - BUFFER_SIZE] = nil, nil
  18.     end
  19. end
  20. addhook("always", "updatebuffer")
  21.  
  22. addhook("hit", "onhit")
  23. function onhit(v,id,wpn)
  24.     if wpn ~= 51 then
  25.         return 1
  26.     end
  27. end
  28.  
  29. math.randomseed(os.time())
  30. math.randomseed(os.time() * math.sin(os.time() * math.random()))
  31. addhook("attack", "onattack")
  32. function onattack(id)
  33.     local wpn = player(id, "weapon")
  34.     if wpn == 51 then --HEs processed normally
  35.         return
  36.     end
  37.  
  38.     local dmg = itemtype(wpn, "dmg") * game("mp_damagefactor")
  39.  
  40.     if (wpn == 2 and mode[1][id] == 1) or (wpn == 39 and mode[2][id] == 1) then --burst weapons
  41.         dmg = math.floor(dmg * 0.64 + 0.5)
  42.         local rot1 = player(id, "rot") - 6 + 12 * math.random()
  43.         local rot2 = player(id, "rot") + 6 + 8 * math.random()
  44.         local rot3 = player(id, "rot") - 6 - 8 * math.random()
  45.         simulate_attack(id, wpn, dmg, rot1)
  46.         simulate_attack(id, wpn, dmg, rot2)
  47.         simulate_attack(id, wpn, dmg, rot3)
  48.         return
  49.     elseif wpn == 10 or wpn == 11 then
  50.         for i=1,5 do
  51.             simulate_attack(id, wpn, dmg, player(id, "rot") - 20 + 40 * math.random(), 180)
  52.         end
  53.         return
  54.     end
  55.    
  56.     if mode[3][id] == 1 then --scoped weapons
  57.         dmg = itemtype(wpn, "dmg_z1") * game("mp_damagefactor")
  58.     elseif mode[3][id] == 2 then
  59.         dmg = itemtype(wpn, "dmg_z2") * game("mp_damagefactor")
  60.     end
  61.  
  62.     local rot = player(id, "rot") + itemtype(wpn, "dispersion") * (2 * math.random() - 1)
  63.     simulate_attack(id, wpn, dmg, rot)
  64. end
  65.  
  66. addhook("attack2", "onattack2")
  67. function onattack2(id, m)
  68.     local wpn = player(id, "weapon")
  69.     if wpn == 50 or wpn == 69 then
  70.         simulate_attack(id, wpn, itemtype(wpn, "dmg_z1") * game("mp_damagefactor"))
  71.     elseif wpn == 2 then
  72.         mode[1][id] = m
  73.     elseif wpn == 39 then
  74.         mode[2][id] = m
  75.     elseif wpn ~= 32 and wpn >= 31 and wpn <= 37 then
  76.         mode[3][id] = m
  77.     end
  78. end
  79.  
  80. addhook("reload", "unzoom")
  81. addhook("select", "unzoom")
  82. function unzoom(id)
  83.     mode[3][id] = 0
  84. end
  85.  
  86. addhook("drop", "ondrop")
  87. function ondrop(id,iid,wpn,ain,a,m)
  88.     mode[3][id] = 0
  89.     if wpn == 2 then
  90.         mode[1][id] = 0
  91.     elseif wpn == 39 then
  92.         mode[2][id] = 0
  93.     end
  94. end
  95.  
  96. addhook("collect", "oncollect")
  97. function oncollect(id,iid,wpn,ain,a,m)
  98.     if wpn == 2 then
  99.         mode[1][id] = m
  100.     elseif wpn == 39 then
  101.         mode[2][id] = m
  102.     end
  103. end
  104.  
  105. function reset(id)
  106.     mode[1][id] = 0
  107.     mode[2][id] = 0
  108.     mode[3][id] = 0
  109.     buffer[1][id] = {}
  110.     buffer[2][id] = {}
  111. end
  112. for i = 1, 32 do
  113.     reset(i)
  114. end
  115. addhook("leave", "reset")
  116. addhook("die", "reset")
  117. addhook("spawn", "reset")
  118.  
  119. --[[simulates the shooting of a bullet of damage (dmg) from (wpn) by (id) with
  120. angle (rot) and range (range). it has two parts. part 1 finds bullet's path before
  121. hitting a wall; part 2 calculates hits on other players (with lag compensation).]]
  122. function simulate_attack(id, wpn, dmg, rot, range)
  123.     if not wpn then wpn = player(id, "weapon") end
  124.     if not dmg then dmg = itemtype(wpn, "dmg") * game("mp_damagefactor") end
  125.     if not rot then rot = player(id, "rot") end
  126.     if not range then range = itemtype(wpn, "range") end
  127.  
  128.     local start_x = player(id, "x")
  129.     local start_y = player(id, "y")
  130.     local end_x = start_x + (3 * range) * math.sin(math.rad(rot))
  131.     local end_y = start_y - (3 * range) * math.cos(math.rad(rot))
  132.     local tile_x = math.floor(start_x / 32)
  133.     local tile_y = math.floor(start_y / 32)
  134.  
  135.     --part 1 - find the intersection of the bullet with the first wall it hits.
  136.     local inc_x, inc_y --specifies the direction in which to search.
  137.  
  138.     if rot < 0 then
  139.         inc_x = -1
  140.     elseif rot > 0 and rot ~= 180 then
  141.         inc_x = 1
  142.     end
  143.  
  144.     if math.abs(rot) > 90 then
  145.         inc_y = 1
  146.     elseif math.abs(rot) < 90 then
  147.         inc_y = -1
  148.     end
  149.  
  150.     while not tile(tile_x, tile_y, "wall") do
  151.         local temp_x, temp_y = tile_x, tile_y
  152.         if inc_x and intersect(start_x, start_y, end_x, end_y, topixel(temp_x + inc_x), topixel(temp_y), 16) then
  153.             tile_x = temp_x + inc_x
  154.         end
  155.         if inc_y and intersect(start_x, start_y, end_x, end_y, topixel(temp_x), topixel(temp_y + inc_y), 16) then
  156.             tile_y = temp_y + inc_y
  157.         end
  158.         if tile_x == temp_x and tile_y == temp_y then
  159.             break
  160.         end
  161.     end
  162.  
  163.     if tile(tile_x, tile_y, "wall") then
  164.         end_x, end_y = intersect(start_x, start_y, end_x, end_y, topixel(tile_x), topixel(tile_y), 16)
  165.     end
  166.  
  167.     --part 2 - detect hits
  168.     local frames = math.floor(player(id, "ping") / 20)
  169.     if frames > (BUFFER_SIZE - 1) then
  170.         frames = (BUFFER_SIZE - 1)
  171.     end
  172.  
  173.     local alive = player(0, "tableliving")
  174.     for _, v in ipairs(alive) do
  175.         if intersect(start_x, start_y, end_x, end_y, buffer[1][v][frame - frames], buffer[2][v][frame - frames], 12) and ((player(v, "team") ~= player(id, "team")) or (game("sv_friendlyfire") == 1)) and (v ~= id) then
  176.             local newarmor = player(v, "armor") - dmg
  177.             if newarmor < 0 then
  178.                 newarmor = 0
  179.             end
  180.             local newhealth = player(v, "health") - (dmg - math.floor(game("mp_kevlar") * (player(v, "armor") - newarmor)))
  181.             if newhealth > 0 then
  182.                 parse("sethealth "..v.." "..newhealth)
  183.                 parse("setarmor "..v.." "..newarmor)
  184.             else
  185.                 parse("customkill "..id.." "..itemtype(wpn, "name").." "..v)
  186.             end
  187.         end
  188.     end
  189. end
  190.  
  191. --the following three functions are used in simulate_attack.
  192.  
  193. --converts a tile number to the tile's center pixel.
  194. function topixel(tile)
  195.     return (tile * 32) + 16
  196. end
  197.  
  198. --quick test to see if i is in between s and e. used in intersect().
  199. function isinorder(s, i, e)
  200.     return (e >= i and i >= s) or (e <= i and i <= s)
  201. end
  202.  
  203. --[[returns the first point of intersection between a box centered at (bx, by) with
  204. half side length (bl) and a line segment starting from (sx, sy) and ending at (ex, ey).
  205. if the line segment is enclosed by the box, (ex, ey) is returned.]]
  206. function intersect(sx, sy, ex, ey, bx, by, bl)
  207.     if math.abs(sx - bx) <= bl and math.abs(sy - by) <= bl then
  208.         if math.abs(ex - bx) <= bl and math.abs(ey - by) <= bl then
  209.             return ex, ey
  210.         else
  211.             return intersect(ex, ey, sx, sy, bx, by, bl)
  212.         end
  213.     end
  214.  
  215.     local i_x, i_y
  216.  
  217.     if ey > sy then
  218.         i_y = by - bl
  219.     elseif ey < sy then
  220.         i_y = by + bl
  221.     end
  222.     if i_y and isinorder(sy, i_y, ey) then
  223.         i_x = ((ex - sx) * i_y + (sx * ey - sy * ex)) / (ey - sy)
  224.         if math.abs(i_x - bx) <= bl and isinorder(sx, i_x, ex) then
  225.             return i_x, i_y
  226.         end
  227.     end
  228.  
  229.     if ex > sx then
  230.         i_x = bx - bl
  231.     elseif ex < sx then
  232.         i_x = bx + bl
  233.     end
  234.     if i_x and isinorder(sx, i_x, ex) then
  235.         i_y = ((ey - sy) * i_x + (sy * ex - sx * ey)) / (ex - sx)
  236.         if math.abs(i_y - by) <= bl and isinorder(sy, i_y, ey) then
  237.             return i_x, i_y
  238.         end
  239.     end
  240. end
Advertisement
Add Comment
Please, Sign In to add comment