SHARE
TWEET

LaserMod v1.1.0

a guest Sep 20th, 2011 136 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ----------------------------------------------------------------
  2. --LUA Lag Compensation version 1.0.1 + LaserMod 1.1.0 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. -- modded by Kiffer-Opa: added colorful laser beams
  9. ----------------------------------------------------------------
  10. --visit cs2d.nl/index.php?mod=board&action=thread&where=120 for-
  11. --    the lastest version and information-----------------------
  12. ----------------------------------------------------------------
  13.  
  14. lm = {}         -- main table
  15.  
  16. --[[initialization, arrays, lm.reseting]]--------------------------
  17. math.randomseed(os.time())
  18. math.randomseed(os.time() * math.sin(os.time() * math.random()))
  19.  
  20. --[[ SETTINS ]]
  21. lm.max_images = 100     --lower to decrease lag
  22. lm.IOR = {1, 1.5, 0}    --index of refraction of ground, obstacle, wall. < 1 means mirror.
  23. lm.power_threshold=0.01 --raise to decrease lag
  24. lm.gamma = 1 / 2.2      --how bright faint lines are
  25. lm.fade_factor = 33.333 --how long lines last
  26. lm.meleelaser = false   --wheather melee weapons have laser physics, too or not
  27. lm.selfhurt = false     --wheather players can hurt themselves with their mirrored shots or not
  28. lm.spawntimer = 150     --how many frames a player gets protected after spawn (should be as long as the original CS2D spawn protection, which is 150, as of CS2D 0.1.1.9)
  29. lm.notcompensated = {0, 46, 47, 48, 49, 77, 86, 87, 253, 254, 255}
  30.                         -- weapons whose bullets are not compensated (item IDs)
  31.                  
  32. --[[ END OF SETTINS ]]
  33.  
  34. lm.images = 0
  35. lm.ping = {} --array of filtered lm.pings of living players
  36. lm.mode = {{}, {}, {}, {}} --glock burst, famas burst, zoom, laser color
  37. lm.spawnprotection = {} -- how many frames spawn protection are left for each player
  38. lm.buffer = {{}, {}} --lm.buffer of current and past positions in x and y coordinates
  39. lm.enable = {} --whether lag comp is lm.enabled for one player
  40. lm.disabled = {} --weapons whose bullets are not compensated
  41. for i, v in ipairs(lm.notcompensated) do
  42.         lm.disabled[v] = true
  43. end
  44.  
  45. lm.armor = {} --special lm.armor protection values
  46. for i, v in ipairs({25, 50, 75, 50, 95}) do
  47.         lm.armor[200 + i] = 1 - (v / 100)
  48. end
  49.  
  50. function lm.reset(id)
  51.         lm.mode[1][id] = 0
  52.         lm.mode[2][id] = 0
  53.         lm.mode[3][id] = 0
  54.         lm.mode[4][id] = 0
  55.         lm.buffer[1][id] = {}
  56.         lm.buffer[2][id] = {}
  57.         lm.ping[id] = nil
  58.         lm.spawnprotection[id] = 0
  59. end
  60.  
  61. function lm.clear(id)
  62.         lm.reset(id)
  63.         lm.enable[id] = 1
  64. end
  65.  
  66. for i = 1, 32 do --initial
  67.         lm.clear(i)
  68. end
  69. addhook("leave", "lm.clear")
  70. addhook("die", "lm.reset")
  71.  
  72. function lm.updateping(id)
  73.         local actualping = player(id, "ping")
  74.         local lastping = lm.ping[id]
  75.         if not lastping then lastping = 0 end
  76.         if actualping then
  77.                 if actualping - lastping <= 30 or lastping == 0 then --regular
  78.                         lm.ping[id] = actualping
  79.                 else --spike is "damped"
  80.                         lm.ping[id] = 0.7 * lastping + 0.3 * actualping
  81.                 end
  82.         end
  83. end
  84. addhook("spawn", "lm.updateping")
  85. ----------------------------------------------------------------
  86.  
  87. function lm.startspawnprotection(id)
  88.         if (game("sv_gamemode")~="0") then
  89.                 lm.spawnprotection[id]=lm.spawntimer
  90.         end
  91. end
  92. addhook("spawn","lm.startspawnprotection")
  93.  
  94.  
  95. --[[periodic functions]]----------------------------------------
  96. lm.frame = 1
  97. lm.BUFFER_SIZE = 25
  98. function lm.updatebuffer()
  99.         lm.frame = lm.frame + 1
  100.         for i in pairs(lm.ping) do
  101.                 lm.buffer[1][i][lm.frame], lm.buffer[2][i][lm.frame] = player(i, "x"), player(i, "y")
  102.                 lm.buffer[1][i][lm.frame - lm.BUFFER_SIZE], lm.buffer[2][i][lm.frame - lm.BUFFER_SIZE] = nil, nil
  103.         end
  104.         lm.images = 0
  105. end
  106. addhook("always", "lm.updatebuffer")
  107.  
  108. function lm.onsecond()
  109.         for i in pairs(lm.ping) do
  110.                 lm.updateping(i)
  111.         end
  112. end
  113. addhook("second", "lm.onsecond")
  114. ----------------------------------------------------------------
  115.  
  116.  
  117. --[[new hit system]]--------------------------------------------
  118. function lm.uselaserhitsystem(id, wpn)
  119.         local slot=itemtype(wpn,"slot")
  120.  
  121.         --cs2d's internal hit system will be preserved in these cases
  122.         return (lm.disabled[wpn] or lm.enable[id] ~= 1 or (slot==3 and not lm.meleelaser) or slot==4 or slot==5)
  123. end
  124.  
  125. addhook("always","lm.reducespawnprotectiontimer")
  126. function lm.reducespawnprotectiontimer()
  127.         local players = player(0,"tableliving")
  128.         for i=1,#players do
  129.                 local p = players[i]
  130.                 lm.spawnprotection[p] = lm.spawnprotection[p] - 1
  131.         end
  132. end
  133.  
  134.  
  135. addhook("hit", "lm.onhit")
  136. function lm.onhit(v, id, wpn)
  137.         local slot=itemtype(wpn,"slot")
  138.         if lm.uselaserhitsystem(id,wpn) or id == 0 then
  139.                 return 0
  140.         end
  141.         return 1
  142. end
  143.  
  144. addhook("attack", "lm.onattack")
  145. function lm.onattack(id)
  146.         local wpn = player(id, "weapon")
  147.        
  148.         if lm.uselaserhitsystem(id,wpn) then
  149.                 return
  150.         end
  151.  
  152.         local dmg = itemtype(wpn, "dmg") * game("mp_damagefactor")
  153.  
  154.         if (wpn == 2 and lm.mode[1][id] == 1) or (wpn == 39 and lm.mode[2][id] == 1) then --burst weapons
  155.                 dmg = math.floor(dmg * 0.64 + 0.5)
  156.                 local rot1 = player(id, "rot") - 6 + 12 * math.random()
  157.                 local rot2 = player(id, "rot") + 6 + 8 * math.random()
  158.                 local rot3 = player(id, "rot") - 6 - 8 * math.random()
  159.                 lm.simulate_attack(id, wpn, dmg, rot1)
  160.                 lm.simulate_attack(id, wpn, dmg, rot2)
  161.                 lm.simulate_attack(id, wpn, dmg, rot3)
  162.                 return
  163.         elseif wpn == 10 or wpn == 11 then
  164.                 for i=1,5 do
  165.                         lm.simulate_attack(id, wpn, dmg, player(id, "rot") - 20 + 40 * math.random(), 180)
  166.                 end
  167.                 return
  168.         end
  169.        
  170.         if lm.mode[3][id] == 1 then --scoped weapons
  171.                 dmg = itemtype(wpn, "dmg_z1") * game("mp_damagefactor")
  172.         elseif lm.mode[3][id] == 2 then
  173.                 dmg = itemtype(wpn, "dmg_z2") * game("mp_damagefactor")
  174.         end
  175.  
  176.         local rot = player(id, "rot") + itemtype(wpn, "dispersion") * (2 * math.random() - 1)
  177.         lm.simulate_attack(id, wpn, dmg, rot)
  178. end
  179.  
  180. addhook("attack2", "lm.onattack2")
  181. function lm.onattack2(id, m)
  182.         local wpn = player(id, "weapon")
  183.         if wpn == 50 or wpn == 69 then
  184.                 if lm.enable[id] == 1 then
  185.                         lm.simulate_attack(id, wpn, itemtype(wpn, "dmg_z1") * game("mp_damagefactor"))
  186.                 end
  187. ----------------------------------------------------------------
  188.  
  189.  
  190. --[[syncs burst/zoom for each player to actual cs2d burst/zoom]]
  191.         elseif wpn == 2 then
  192.                 lm.mode[1][id] = m
  193.         elseif wpn == 39 then
  194.                 lm.mode[2][id] = m
  195.         elseif wpn ~= 32 and wpn >= 31 and wpn <= 37 then
  196.                 lm.mode[3][id] = m
  197.         elseif wpn == 45 then
  198.                 lm.mode[4][id] = m
  199.         end
  200. end
  201.  
  202. addhook("reload", "lm.unzoom")
  203. addhook("select", "lm.unzoom")
  204. function lm.unzoom(id)
  205.         lm.mode[3][id] = 0
  206. end
  207.  
  208. addhook("drop", "lm.ondrop")
  209. function lm.ondrop(id,iid,wpn,ain,a,m)
  210.         lm.mode[3][id] = 0
  211.         if wpn == 2 then
  212.                 lm.mode[1][id] = 0
  213.         elseif wpn == 39 then
  214.                 lm.mode[2][id] = 0
  215.         end
  216. end
  217.  
  218. addhook("collect", "lm.oncollect")
  219. function lm.oncollect(id,iid,wpn,ain,a,m)
  220.         if wpn == 2 then
  221.                 lm.mode[1][id] = m
  222.         elseif wpn == 39 then
  223.                 lm.mode[2][id] = m
  224.         elseif wpn == 45 then
  225.                 lm.mode[4][id] = m
  226.         end
  227. end
  228. ----------------------------------------------------------------
  229.  
  230. --[[bullet simulation]]-----------------------------------------
  231.  
  232. --[[simulates the shooting of a bullet of damage (dmg) from
  233. (wpn) by (id) with angle (rot) and range (range). it has two
  234. parts. part 1 finds bullet's path before hitting a wall; part 2
  235. calculates hits on other players (with lag compensation).]]
  236. function lm.simulate_attack(id, wpn, dmg, rot, range)
  237.         if not wpn then wpn = player(id, "weapon") end
  238.         if not dmg then dmg = itemtype(wpn, "dmg") * game("mp_damagefactor") end
  239.         if not rot then rot = player(id, "rot") end
  240.         if not range then range = itemtype(wpn, "range") end
  241.        
  242.         local start_x = player(id, "x") + math.sin(math.rad(rot))*lm.muzzledistance(wpn) + 1
  243.         local start_y = player(id, "y") - math.cos(math.rad(rot))*lm.muzzledistance(wpn) - 1
  244.         local color, scale
  245.         if wpn==45 then                         -- laser
  246.                 color = lm.mode[4][id]
  247.                 scale = 0.25
  248.         elseif itemtype(wpn,"slot")==3 then     -- meelee weapons
  249.                 color = 4
  250.                 scale = 0.1
  251.         else
  252.                 color = 5
  253.                 scale = 0.1
  254.         end
  255.         local duration = math.floor(itemtype(wpn,"rate") * lm.fade_factor)
  256.  
  257.         local tilex = math.floor(start_x/32)
  258.         local tiley = math.floor(start_y/32)
  259.        
  260.         -- part 1: check if beam starts inside a wall
  261.         local beams
  262.         if tile(tilex,tiley,"wall") == true then
  263.                 -- if so, do not shoot any beams
  264.                 beams = {}
  265.         else
  266.                 -- else calculate the beams
  267.                 beams = lm.flattenbeam(lm.get_rays(start_x, start_y, rot, 3 * range, 1, color, scale, duration))
  268.         end
  269.  
  270.         --part 2 - detect hits
  271.         local frames = math.floor(lm.ping[id] / 20)
  272.         if frames > (lm.BUFFER_SIZE - 1) then
  273.                 frames = (lm.BUFFER_SIZE - 1)
  274.         end
  275.  
  276.         local victims = {}
  277.         if game("sv_friendlyfire") == "0" and game("sv_gamemode") ~= "1" then
  278.                 for i in pairs(lm.ping) do
  279.                         if player(i, "team") ~= player(id, "team") then
  280.                                 if lm.spawnprotection[i]<=0 then
  281.                                         victims[i] = true
  282.                                 end
  283.                         end
  284.                 end
  285.         else
  286.                 for i in pairs(lm.ping) do
  287.                         if lm.spawnprotection[i]<=0 then
  288.                                 victims[i] = true
  289.                         end
  290.                 end
  291.                 if lm.selfhurt==false or lm.spawnprotection[id]>0 then
  292.                         victims[id] = nil
  293.                 end
  294.         end
  295.         local olddmg = dmg
  296.         for _, beam in ipairs(beams) do
  297.                 dmg = olddmg * (beam[5] or 1)
  298.                 for i in pairs(victims) do
  299.                         if lm.intersect(beam[1], beam[2], beam[3], beam[4], lm.buffer[1][i][lm.frame - frames], lm.buffer[2][i][lm.frame - frames], 12) then
  300.                                 parse("sv_sound2 "..id.." player/hit"..math.ceil(3 * math.random())..".wav")
  301.                                 parse("sv_sound2 "..i.." player/hit"..math.ceil(3 * math.random())..".wav")
  302.                                 local newhealth
  303.                                 local newarmor = player(i, "armor")
  304.  
  305.                                 if newarmor <= 200 then
  306.                                         newarmor = newarmor - dmg
  307.                                         if newarmor < 0 then
  308.                                                 newarmor = 0
  309.                                         end
  310.                                         newhealth = player(i, "health") - (dmg - math.floor(game("mp_kevlar") * (player(i, "armor") - newarmor)))
  311.                                         parse("setarmor "..i.." "..newarmor)
  312.                                 else --special lm.armor values
  313.                                         newhealth = player(i, "health") - math.floor((dmg * (lm.armor[newarmor] or 1)))
  314.                                 end
  315.  
  316.                                 if newhealth > 0 then
  317.                                         parse("sethealth "..i.." "..newhealth)
  318.                                 else
  319.                                         parse("customkill "..id.." \""..itemtype(wpn, "name").."\" "..i)
  320.                                 end
  321.                         end
  322.                 end
  323.         end
  324. end
  325.  
  326. --the following functions are used in lm.simulate_attack.
  327. function lm.get_rays(start_x, start_y, rot, range, power, color, scale, duration)
  328.         if range <= 0 then return end
  329.         if power <= lm.power_threshold then return end
  330.         if not rot then return end
  331.         local end_x = start_x + (range) * math.sin(math.rad(rot))
  332.         local end_y = start_y - (range) * math.cos(math.rad(rot))
  333.  
  334.         local inc_x, inc_y
  335.         if rot < 0 then
  336.                 inc_x = -1
  337.         elseif rot > 0 and rot ~= 180 then
  338.                 inc_x = 1
  339.         end
  340.         if math.abs(rot) > 90 then
  341.                 inc_y = 1
  342.         elseif math.abs(rot) < 90 then
  343.                 inc_y = -1
  344.         end
  345.  
  346.         local tile_x = math.floor(start_x / 32)
  347.         local tile_y = math.floor(start_y / 32)
  348.         if (inc_x or 0) == -1 and start_x % 32 == 0 then tile_x = tile_x - 1 end
  349.         if (inc_y or 0) == -1 and start_y % 32 == 0 then tile_y = tile_y - 1 end
  350.  
  351.         local beams = {}
  352.         local n2 = lm.tileIOR(tile_x, tile_y)
  353.         while true do
  354.                 n1 = n2
  355.                 n2 = lm.tileIOR(tile_x, tile_y)
  356.                 if n2 < 1 then --mirror, 100% reflection.
  357.                         local i
  358.                         end_x, end_y, i = lm.intersect(start_x, start_y, end_x, end_y, lm.topixel(tile_x), lm.topixel(tile_y), 16)
  359.                         if i == 1 then --vertical reflection
  360.                                 rot = -rot
  361.                         elseif i == 0 then --horizontal reflection
  362.                                 rot = ((1 + (inc_x or 1)) * 180 - rot) % 360 - 180
  363.                         else
  364.                                 --msg("wtf")
  365.                                 break
  366.                         end
  367.                         range = range - math.sqrt((end_x - start_x) ^ 2 + (end_y - start_y) ^ 2)
  368.                         beams[#beams + 1] = {start_x, start_y, end_x, end_y, power, color, scale, duration} --incident
  369.                         beams[#beams + 1] = lm.get_rays(end_x, end_y, rot, range, power, color, scale, duration) --reflected
  370.                         break
  371.                 elseif n1 ~= n2 then --interface. fresnel + snell.
  372.                         local i
  373.                         end_x, end_y, i = lm.intersect(start_x, start_y, end_x, end_y, lm.topixel(tile_x), lm.topixel(tile_y), 16)
  374.                        
  375.                         local rot_r, rot_t --reflection and transmission angles
  376.                         local R --fraction of power reflected. T = 1 - R by conservation of energy.
  377.                         local a, b --helpers
  378.                         if i == 1 then
  379.                                 rot_r = -rot
  380.                                 local something = n1 / n2 * math.sin(math.rad(rot - (inc_x or 1) * 90))
  381.                                 if math.abs(something) <=1 then
  382.                                         rot_t = (inc_x or 1) * 90 + math.deg(math.asin(something)) --snell's law
  383.                                 end
  384.                                 a = rot_t and n1 * math.cos(math.rad(rot - (inc_x or 1) * 90)) or 1
  385.                                 b = rot_t and n2 * math.cos(math.rad(rot_t - (inc_x or 1) * 90)) or 0
  386.                         elseif i == 0 then
  387.                                 rot_r = (inc_x or 1) * 180 - rot
  388.                                 local something = n1 / n2 * math.sin(math.rad(90 * (1 + (inc_y or 1)) - rot))
  389.                                 if math.abs(something) <= 1 then
  390.                                         rot_t = (90 * (3 + (inc_y or 1)) - math.deg(math.asin(something))) % 360 - 180
  391.                                 end
  392.                                 a = rot_t and n1 * math.cos(math.rad(90 * (1 + (inc_y or 1)) - rot)) or 1
  393.                                 b = rot_t and n2 * math.cos(math.rad(90 * (1 + (inc_y or 1)) - rot_t)) or 0
  394.                         else
  395.                                 --msg("debug: wtf")
  396.                                 break
  397.                         end
  398.                         R = ((a - b) / (a + b)) ^ 2 -- fresnel's equation
  399.                         range = range - math.sqrt((end_x - start_x) ^ 2 + (end_y - start_y) ^ 2)
  400.                         beams[#beams + 1] = {start_x, start_y, end_x, end_y, power, color, scale, duration} --incident
  401.                         if R < 0.5 then --this makes sure beam is sorted by power
  402.                                 rot_r, rot_t = rot_t, rot_r
  403.                                 R = 1 - R
  404.                         end
  405.                         beams[#beams + 1] = lm.get_rays(end_x, end_y, rot_r, range, power * R, color, scale, duration)
  406.                         beams[#beams + 1] = lm.get_rays(end_x, end_y, rot_t, range, power * (1 - R), color, scale, duration)
  407.                         break
  408.                 end
  409.                 local temp_x, temp_y = tile_x, tile_y
  410.                 if inc_x and lm.intersect(start_x, start_y, end_x, end_y, lm.topixel(temp_x + inc_x), lm.topixel(temp_y), 16) then
  411.                         tile_x = temp_x + inc_x
  412.                 end
  413.                 if inc_y and lm.intersect(start_x, start_y, end_x, end_y, lm.topixel(temp_x), lm.topixel(temp_y + inc_y), 16) then
  414.                         tile_y = temp_y + inc_y
  415.                 end
  416.                 if tile_x == temp_x and tile_y == temp_y then
  417.                         --msg("range")
  418.                         beams[#beams + 1] = {start_x, start_y, end_x, end_y, power, color, scale, duration}
  419.                         break
  420.                 end
  421.         end
  422.         return beams
  423. end
  424.  
  425. function lm.tileIOR(tile_x, tile_y)
  426.         if tile(tile_x, tile_y, "wall") then
  427.                 return lm.IOR[3]
  428.         elseif tile(tile_x, tile_y, "obstacle") then
  429.                 return lm.IOR[2]
  430.         else
  431.                 return lm.IOR[1]
  432.         end
  433. end
  434.  
  435. function lm.isbeam(tab)
  436.         if type(tab) ~= "table" or #tab ~= 8 then return false end
  437.         for i, v in ipairs(tab) do
  438.                 if type(v) == "table" then return false end
  439.         end
  440.         return true
  441. end
  442.  
  443. function lm.flattenbeam(tab) --also draws them :D
  444.         local flat = {}
  445.         for i, v in ipairs(tab) do
  446.                 if lm.isbeam(v) then
  447.                         lm.drawbeam(v)
  448.                         flat[#flat + 1] = {}
  449.                         for a, b in ipairs(v) do
  450.                                 flat[#flat][a] = b
  451.                         end
  452.                 else
  453.                         for c, d in ipairs(lm.flattenbeam(v)) do
  454.                                 flat[#flat + 1] = {}
  455.                                 for e, f in ipairs(d) do
  456.                                         flat[#flat][e] = f
  457.                                 end
  458.                         end
  459.                 end
  460.         end
  461.         return flat
  462. end
  463.  
  464. function lm.drawbeam(beam)
  465.         if lm.images <= lm.max_images then
  466.                 lm.images = lm.images + 1
  467.                 local x, y = (beam[1] + beam[3]) / 2, (beam[2] + beam[4]) / 2
  468.                 local id = image("gfx/sprites/laserbeam1.bmp", x, y, 1)
  469.                 imagealpha(id, beam[5] ^ lm.gamma) --crude srgb lm.gamma correction
  470.                 if(beam[6]==0) then                    
  471.                         imagecolor(id,   0, 255,   0)   -- green
  472.                 elseif(beam[6]==1) then                
  473.                         imagecolor(id, 255,  25,   0)   -- red
  474.                 elseif(beam[6]==2) then                
  475.                         imagecolor(id, 255, 255,   0)   -- yellow
  476.                 elseif(beam[6]==3) then                
  477.                         imagecolor(id,  50, 150, 255)   -- blue
  478.                 elseif(beam[6]==4) then
  479.                         imagecolor(id, 255, 255, 255)   -- white
  480.                 elseif(beam[6]==5) then
  481.                         imagecolor(id, 255, 255, 63)    -- light yellow
  482.                 end
  483.                 imagescale(id, beam[7], math.sqrt((beam[4] - beam[2]) ^ 2 + (beam[3] - beam[1]) ^ 2) / 32)
  484.                 imagepos(id, x, y, 90 + math.deg(math.atan2((beam[4] - beam[2]) , (beam[3] - beam[1]))))
  485.                 tween_alpha(id, beam[8], 0)
  486.                 timer(beam[8], "freeimage", id)
  487.         end
  488. end
  489.  
  490. --converts a tile number to the tile's center pixel.
  491. function lm.topixel(tile)
  492.         return (tile * 32) + 16
  493. end
  494.  
  495. -- takes a weapon ID as input and returns the pixel distance of the muzzle of this weapon from the center player position, in pixels
  496. function lm.muzzledistance(wpntype)
  497.         -- TODO: enter more weapon types...
  498.         if wpntype==45 then
  499.         -- laser
  500.                 return 20
  501.         else
  502.         -- all other weapons have 16; this is just a "best bet" and may not perfectly fit
  503.                 return 16
  504.         end
  505. end
  506.  
  507. --quick test to see if i is in between s and e. used in lm.intersect().
  508. function lm.isinorder(s, i, e)
  509.         return (e >= i and i >= s) or (e <= i and i <= s)
  510. end
  511.  
  512. --[[returns the first point of intersection between a box centered at (bx, by) with
  513. half side length (bl) and a line segment starting from (sx, sy) and ending at (ex, ey).
  514. if the line segment is enclosed by the box, (ex, ey) is returned.]]
  515. function lm.intersect(sx, sy, ex, ey, bx, by, bl)
  516.         if not (bx and by) then return end --fixes rare lua error
  517.  
  518.         if math.abs(sx - bx) <= bl and math.abs(sy - by) <= bl then
  519.                 if math.abs(ex - bx) <= bl and math.abs(ey - by) <= bl then
  520.                         if math.abs(ey - by) == bl then
  521.                                 return ex, ey, 0
  522.                         end
  523.                         return ex, ey, 1
  524.                 else
  525.                         sx, sy, ex, ey = ex, ey, sx, sy
  526.                 end
  527.         end
  528.  
  529.         local i_x, i_y
  530.  
  531.         if ey > sy then
  532.                 i_y = by - bl
  533.         elseif ey < sy then
  534.                 i_y = by + bl
  535.         end
  536.         if i_y and lm.isinorder(sy, i_y, ey) then
  537.                 i_x = ((ex - sx) * i_y + (sx * ey - sy * ex)) / (ey - sy)
  538.                 if math.abs(i_x - bx) <= bl and lm.isinorder(sx, i_x, ex) then
  539.                         return i_x, i_y, 0 -- collision with horizontal edge
  540.                 end
  541.         end
  542.  
  543.         if ex > sx then
  544.                 i_x = bx - bl
  545.         elseif ex < sx then
  546.                 i_x = bx + bl
  547.         end
  548.         if i_x and lm.isinorder(sx, i_x, ex) then
  549.                 i_y = ((ey - sy) * i_x + (sy * ex - sx * ey)) / (ex - sx)
  550.                 if math.abs(i_y - by) <= bl and lm.isinorder(sy, i_y, ey) then
  551.                         return i_x, i_y, 1 -- collision with vertical edge
  552.                 end
  553.         end
  554. end
  555. ----------------------------------------------------------------
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top