Created
March 9, 2011 22:52
-
-
Save FloooD/863184 to your computer and use it in GitHub Desktop.
Lua Lag Comp v1.0.1 + wallbang mod
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ---------------------------------------------------------------- | |
| --LUA Lag Compensation + wallbanging 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.- | |
| ---------------------------------------------------------------- | |
| --visit cs2d.nl/index.php?mod=board&action=thread&where=120 for- | |
| -- the lastest version and information----------------------- | |
| ---------------------------------------------------------------- | |
| --[[initialization, arrays, reseting]]-------------------------- | |
| WB_DMG = 0.6 --damage reduction upon each wall collision | |
| WB_RANGE = 0.3 --range reduction upon each wall collision | |
| math.randomseed(os.time()) | |
| math.randomseed(os.time() * math.sin(os.time() * math.random())) | |
| ping = {} --array of filtered pings of living players | |
| mode = {{}, {}, {}} --glock burst, famas burst, zoom | |
| buffer = {{}, {}} --buffer of current and past positions in x and y coordinates | |
| enable = {} --whether lag comp is enabled for one player | |
| disabled = {} --weapons whose bullets are not compensated | |
| for i, v in ipairs({0, 47, 51, 72, 73, 75, 76, 77, 86, 87, 253, 254, 255}) do | |
| disabled[v] = true | |
| end | |
| armor = {} --special armor protection values | |
| for i, v in ipairs({25, 50, 75, 50, 95}) do | |
| armor[200 + i] = 1 - (v / 100) | |
| end | |
| 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 disabled[wpn] or id == 0 or enable[id] ~= 1 then --preserve cs2d's internal hit system in these cases | |
| return 0 | |
| end | |
| return 1 | |
| end | |
| addhook("attack", "onattack") | |
| function onattack(id) | |
| local wpn = player(id, "weapon") | |
| if disabled[wpn] or enable[id] ~= 1 then --preserve cs2d's internal hit system in these cases | |
| 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 impact_x = {} | |
| local impact_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 walls 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 true do | |
| if tile(tile_x, tile_y, "wall") then | |
| local i_x, i_y = intersect(start_x, start_y, end_x, end_y, topixel(tile_x), topixel(tile_y), 16) | |
| if not (i_x and i_y) then break end | |
| impact_x[#impact_x + 1] = i_x | |
| impact_y[#impact_y + 1] = i_y | |
| end_x = end_x * WB_RANGE + i_x * (1 - WB_RANGE) | |
| end_y = end_y * WB_RANGE + i_y * (1 - WB_RANGE) | |
| end | |
| 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 | |
| local collisions = #impact_x | |
| impact_x[#impact_x + 1] = end_x | |
| impact_y[#impact_y + 1] = end_y | |
| impact_x[0] = start_x | |
| impact_y[0] = start_y | |
| --part 2 - detect hits | |
| local frames = math.floor(ping[id] / 20) | |
| if frames > (BUFFER_SIZE - 1) then | |
| frames = (BUFFER_SIZE - 1) | |
| end | |
| local victims = {} | |
| if game("sv_friendlyfire") == "0" and game("sv_gamemode") ~= "1" 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 n = 0, collisions do | |
| for i in pairs(victims) do | |
| if intersect(impact_x[n], impact_y[n], impact_x[n + 1], impact_y[n + 1], buffer[1][i][frame - frames], buffer[2][i][frame - frames], 12) then | |
| parse("sv_sound2 "..id.." player/hit"..math.ceil(3 * math.random())..".wav") | |
| parse("sv_sound2 "..i.." player/hit"..math.ceil(3 * math.random())..".wav") | |
| local newhealth | |
| local newarmor = player(i, "armor") | |
| if newarmor <= 200 then | |
| newarmor = newarmor - dmg | |
| if newarmor < 0 then | |
| newarmor = 0 | |
| end | |
| newhealth = player(i, "health") - (dmg - math.floor(game("mp_kevlar") * (player(i, "armor") - newarmor))) | |
| parse("setarmor "..i.." "..newarmor) | |
| else --special armor values | |
| newhealth = player(i, "health") - math.floor((dmg * (armor[newarmor] or 1))) | |
| end | |
| if newhealth > 0 then | |
| parse("sethealth "..i.." "..newhealth) | |
| else | |
| parse("customkill "..id.." "..itemtype(wpn, "name").." "..i) | |
| end | |
| end | |
| end | |
| dmg = dmg * WB_DMG | |
| 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 not (bx and by) then return end --fixes rare lua error | |
| 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 | |
| ---------------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey FlooD... Silent here! Wow I started programming recently for Engineering and I went back looking for cs2d lua scripts... and I somehow found you here!