Created
May 23, 2011 18:26
-
-
Save FloooD/987224 to your computer and use it in GitHub Desktop.
look at where other people are aiming.
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 version 2.0 + pointer speccing 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----------------------- | |
---------------------------------------------------------------- | |
math.randomseed(os.time()) | |
math.randomseed(os.time() * math.sin(os.time() * math.random())) | |
ping = {} | |
mode = {{}, {}, {}} | |
buffer = {{}, {}} | |
pointer_loc = {{}, {}, {}} | |
specced = {} | |
for i = 1, 32 do specced[i] = {} end | |
disabled = {} | |
for i, v in ipairs({0, 47, 51, 72, 73, 75, 76, 77, 86, 87, 253, 254, 255}) do | |
disabled[v] = true | |
end | |
armor = {} | |
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] = {} | |
pointer_loc[1][id] = nil | |
pointer_loc[2][id] = nil | |
ping[id] = nil | |
clear_specs(id) | |
end | |
function clear_draw(spec) | |
for i = 1, 32 do | |
if specced[spec][i] then | |
freeimage(specced[spec][i]) | |
end | |
end | |
specced[spec] = {} | |
end | |
addhook("spawn", "clear_draw") | |
function clear_specs(player) | |
for i = 1, 32 do | |
if specced[i][0] and specced[i][0] == player then | |
init_draw(i, player) | |
end | |
end | |
end | |
addhook("spawn", "clear_specs") | |
function clear(id) | |
reset(id) | |
clear_draw(id) | |
pointer_loc[3][id] = nil | |
end | |
for i = 1, 32 do 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 | |
ping[id] = actualping | |
else | |
ping[id] = 0.7 * lastping + 0.3 * actualping | |
end | |
end | |
end | |
addhook("spawn", "updateping") | |
frame = 1 | |
BUFFER_SIZE = 15 | |
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 | |
if pointer_loc[3][i] then reqcld(i, 0) end | |
end | |
for i = 1, 32 do | |
if specced[i][0] then update_draw(i) end | |
end | |
end | |
addhook("always", "updatebuffer") | |
function cl_data(id, m, x, y) | |
if pointer_loc[3][id] then | |
pointer_loc[1][id] = x | |
pointer_loc[2][id] = y | |
end | |
end | |
addhook("clientdata", "cl_data") | |
function onsecond() | |
for i in pairs(ping) do | |
updateping(i) | |
end | |
end | |
addhook("second", "onsecond") | |
addhook("hit", "onhit") | |
function onhit(v, id, wpn) | |
if disabled[wpn] or id == 0 then | |
return 0 | |
end | |
return 1 | |
end | |
addhook("attack", "onattack") | |
function onattack(id) | |
local wpn = player(id, "weapon") | |
if disabled[wpn] then return end | |
local rot = pointer_loc[3][id] and math.deg(math.atan2(pointer_loc[1][id] - 320, 240 - pointer_loc[2][id])) or player(id, "rot") | |
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 | |
dmg = math.floor(dmg * 0.64 + 0.5) | |
simulate_attack(id, wpn, dmg, rot - 6 + 12 * math.random()) | |
simulate_attack(id, wpn, dmg, rot + 6 + 8 * math.random()) | |
simulate_attack(id, wpn, dmg, rot - 6 - 8 * math.random()) | |
return | |
elseif wpn == 10 or wpn == 11 then | |
for i = 1, 5 do | |
simulate_attack(id, wpn, dmg, rot - 20 + 40 * math.random()) | |
end | |
return | |
end | |
if mode[3][id] == 1 then | |
dmg = itemtype(wpn, "dmg_z1") * game("mp_damagefactor") | |
elseif mode[3][id] == 2 then | |
dmg = itemtype(wpn, "dmg_z2") * game("mp_damagefactor") | |
end | |
rot = 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 | |
simulate_attack(id, wpn, itemtype(wpn, "dmg_z1") * game("mp_damagefactor")) | |
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) | |
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 | |
function simulate_attack(id, wpn, dmg, rot) | |
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 | |
local range = itemtype(wpn, "range") | |
local start_x = player(id, "x") | |
local start_y = player(id, "y") | |
local end_x = (3 * range) * math.sin(math.rad(rot)) | |
local end_y = -(3 * range) * math.cos(math.rad(rot)) | |
local tile_x = math.floor(start_x / 32) | |
local tile_y = math.floor(start_y / 32) | |
local inc_x, inc_y | |
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(end_x, end_y, topixel(temp_x + inc_x) - start_x, topixel(temp_y) - start_y, 16) then | |
tile_x = temp_x + inc_x | |
end | |
if inc_y and intersect(end_x, end_y, topixel(temp_x) - start_x, topixel(temp_y + inc_y) - start_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(end_x, end_y, topixel(tile_x) - start_x, topixel(tile_y) - start_y, 16) | |
end | |
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 i in pairs(victims) do | |
if intersect(end_x, end_y, buffer[1][i][frame - frames] - start_x, buffer[2][i][frame - frames] - start_y, 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 | |
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 | |
end | |
function topixel(tile) | |
return (tile * 32) + 16 | |
end | |
function intersect(ex, ey, bx, by, bl) | |
if not (bx and by) then return end | |
local cx, cy = (math.abs(bx) <= bl), (math.abs(by) <= bl) | |
if cx and cy then | |
if math.abs(ex - bx) <= bl and math.abs(ey - by) <= bl then | |
return ex, ey | |
end | |
bl = -bl | |
end | |
local ox = (ex >= 0) and bx - bl or bx + bl | |
local oy = (ey >= 0) and by - bl or by + bl | |
local flip | |
if (ex == 0 or (cx ~= cy or ((math.abs(ey * ox) >= math.abs(ex * oy)) == (bl < 0)))) and ((not cy) or cx) then | |
if ey == 0 then return end | |
ex, ey, bx, by, ox, oy = ey, ex, by, bx, oy, ox | |
flip = true | |
end | |
if (ox * ex) >= 0 and math.abs(ox) <= math.abs(ex) then | |
oy = ox * ey / ex | |
if math.abs(oy - by) <= math.abs(bl) then | |
if flip then return oy, ox end | |
return ox, oy | |
end | |
end | |
end | |
addhook("serveraction", "onserveraction") | |
function onserveraction(id, action) | |
if action == 1 then | |
msg2(id, "This server runs Lua Lag Compensation version 2.0.1") | |
msg2(id, "Your current ping: "..(ping[id] or player(id, "ping"))) | |
elseif action == 2 then | |
if pointer_loc[3][id] then | |
pointer_loc[3][id] = nil | |
for i = 1, 32 do | |
if specced[i][0] and specced[i][0] == id then | |
clear_draw(i) | |
end | |
end | |
msg2(id, "LC: using standard rotation.") | |
msg2(id, "note: spectators won't be able to see your pointer position.") | |
else | |
pointer_loc[3][id] = true | |
msg2(id, "LC: using pointer position to calculate rotation.") | |
msg2(id, "LC: this fixes the rotation bug but will increase your ping by 5.") | |
msg2(id, "note: spectators can look at where your pointer is by saying !spec "..id) | |
end | |
end | |
end | |
POINTER="gfx/pointer.png" | |
HITBOX="gfx/hitbox.png" | |
addhook("say", "select_specced") | |
function select_specced(id, text) | |
if string.sub(text, 1, 6) == "!spec " then | |
if player(id, "health") > 0 then | |
msg2(id, "you must be a spectator for this") | |
return 1 | |
end | |
local s = tonumber(string.sub(text, 7)) | |
if s == 0 then | |
msg2(id, "you are now not spectating anyone's pointer.") | |
clear_draw(id) | |
elseif pointer_loc[3][s] then | |
init_draw(id, s) | |
else | |
msg2(id, "player with id "..s.." does not exist or hasn't toggled F3.") | |
msg2(id, "(if you want to disable pointer-spectating, say !spec 0)") | |
end | |
return 1 | |
end | |
end | |
function init_draw(spec, player) | |
clear_draw(spec) | |
specced[spec][0] = player | |
end | |
function update_draw(spec) | |
if player(spec, "health") and player(spec, "health") > 0 then return end | |
local p = specced[spec][0] | |
if (not p) or not player(p, "health") or player(p, "health") == 0 then return end | |
local frames = math.floor(ping[p] / 20) | |
if frames > (BUFFER_SIZE - 1) then | |
frames = (BUFFER_SIZE - 1) | |
end | |
if not specced[spec][p] then | |
specced[spec][p] = image(POINTER, pointer_loc[1][p], pointer_loc[2][p], 2, spec) | |
else | |
imagepos(specced[spec][p], pointer_loc[1][p], pointer_loc[2][p], 0) | |
end | |
for i = 1, 32 do | |
if player(i, "exists") and player(i, "health") > 0 and player(i, "team") ~= player(p, "team") then | |
local x = buffer[1][i][frame - frames] - player(p, "x") | |
local y = buffer[2][i][frame - frames] - player(p, "y") | |
if math.abs(x) <= 320 and math.abs(y) <= 240 then | |
x = x + 320 | |
y = y + 240 | |
if specced[spec][i] then | |
imagepos(specced[spec][i], x, y, 0) | |
else | |
specced[spec][i] = image(HITBOX, x, y, 2, spec) | |
end | |
elseif specced[spec][i] then | |
freeimage(specced[spec][i]) | |
specced[spec][i] = nil | |
end | |
elseif i ~= p and specced[spec][i] then | |
freeimage(specced[spec][i]) | |
specced[spec][i] = nil | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment