Advertisement
Kain2030

goodEvade - v013.5.lua

Aug 19th, 2013
352
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 73.94 KB | None | 0 0
  1. --[[
  2.     Good Evade 0.13.5
  3. V08:
  4. - smoothness
  5. - more skillshots
  6. - improved wall detection
  7. - slightly improved evasion from FOG skillshots
  8. - improved multiple skillshots dodging
  9. - nil error fixes
  10. - priority to cc dodging
  11. - draw optimizations
  12. V09:
  13. - leona E dodge improving
  14. - will dodge noncc more often now
  15. - turrets check
  16. - perfomance optimizations
  17. - smooth oprimizations (less hp -> less smooth)
  18. - cass Q, karthus Q
  19. V010-012:
  20.  - bugfixes
  21. V013:
  22.  - more dashes (Graves / Ezreal / Kassadin / Riven / Corki / Tristana / Renekton) with custom logic
  23.  (check code, ex Ez will only use E on blitz / ashe / leona)
  24. V013.5:
  25.  - Changed player count logic to allow for games with less than 5 players.
  26.  - Added Lux, Orianna, and Ziggs advoidances.
  27. ]]
  28.  
  29. -- Config ----------------------------------------------------------------------
  30. if not VIP_USER then return end
  31.  
  32. NONE = 0
  33. ALLY = 1
  34. ENEMY = 2
  35. NEUTRAL = 4
  36. ALL = 7
  37.  
  38. class 'Turrets' -- {
  39.     Turrets.tables = {
  40.         [ALLY] = {},
  41.         [ENEMY] = {},
  42.         [NEUTRAL] = {}
  43.     }
  44.  
  45.     Turrets.instance = ""
  46.  
  47.     function Turrets:__init()
  48.         self.modeCount = 7
  49.  
  50.         for i = 1, objManager.maxObjects, 1 do
  51.             local turret = objManager:GetObject(i)
  52.             self:AddObject(turret)
  53.         end
  54.  
  55.         AddCreateObjCallback(function(obj) self:OnCreateObj(obj) end)
  56.     end
  57.  
  58.     function Turrets:OnCreateObj(obj)
  59.         self:AddObject(obj)
  60.     end
  61.  
  62.     function Turrets.GetObjects(mode, range, pFrom)
  63.         return Turrets.Instance():GetObjectsFromTable(mode, range, pFrom)
  64.     end
  65.  
  66.     function Turrets.Instance()
  67.         if Turrets.instance == "" then Turrets.instance = Turrets() end return Turrets.instance
  68.     end
  69.  
  70.     function Turrets:AddObject(obj)
  71.         if obj ~= nil and obj.valid and obj.type == "obj_AI_Turret" then
  72.             DelayAction(function(obj)
  73.                 if obj.team == myHero.team then table.insert(Turrets.tables[ALLY], obj) return end
  74.                 if obj.team == TEAM_ENEMY then table.insert(Turrets.tables[ENEMY], obj) return end
  75.                 if obj.team == TEAM_NEUTRAL then table.insert(Turrets.tables[NEUTRAL], obj) return end
  76.             end, 0, {obj})
  77.         end
  78.     end
  79.  
  80.     function Turrets:GetObjectsFromTable(mode, range, pFrom)
  81.         if mode > self.modeCount then mode = self.modeCount end
  82.         if range == nil or range < 0 then range = math.huge end
  83.         if pFrom == nil then pFrom = myHero end
  84.         tempTable = {}
  85.  
  86.         for i, tableType in pairs(Turrets.tables) do
  87.             if bit32.band(mode, i) == i then
  88.                 for k,v in pairs(tableType) do
  89.                     if v and v.valid then
  90.                         if v.visible and GetDistance(v, pFrom) <= range then table.insert(tempTable, v) end
  91.                     else table.remove(tableType, k) k = k - 1 end
  92.                 end
  93.             end
  94.         end
  95.         return tempTable
  96.     end
  97. -- }
  98.  
  99. class 'CollisionPE' -- {
  100.     HERO_ALL = 1
  101.     HERO_ENEMY = 2
  102.     HERO_ALLY = 3
  103.  
  104.  
  105.     function CollisionPE:__init(sRange, projSpeed, sDelay, sWidth)
  106.         uniqueId = uniqueId + 1
  107.         self.uniqueId = uniqueId
  108.  
  109.         self.sRange = sRange
  110.         self.projSpeed = projSpeed
  111.         self.sDelay = sDelay
  112.         self.sWidth = sWidth/2
  113.  
  114.         self.enemyMinions = minionManager(MINION_ALL, 2000, myHero, MINION_SORT_HEALTH_ASC)
  115.         self.minionupdate = 0
  116.     end
  117.  
  118.     function CollisionPE:GetMinionCollision(pStart, pEnd)
  119.         self.enemyMinions:update()
  120.  
  121.         local distance =  GetDistance(pStart, pEnd)
  122.         local prediction = TargetPredictionVIP(self.sRange, self.projSpeed, self.sDelay, self.sWidth)
  123.         local mCollision = {}
  124.  
  125.         if distance > self.sRange then
  126.             distance = self.sRange
  127.         end
  128.  
  129.         local V = Vector(pEnd) - Vector(pStart)
  130.         local k = V:normalized()
  131.         local P = V:perpendicular2():normalized()
  132.  
  133.         local t,i,u = k:unpack()
  134.         local x,y,z = P:unpack()
  135.  
  136.         local startLeftX = pStart.x + (x *self.sWidth)
  137.         local startLeftY = pStart.y + (y *self.sWidth)
  138.         local startLeftZ = pStart.z + (z *self.sWidth)
  139.         local endLeftX = pStart.x + (x * self.sWidth) + (t * distance)
  140.         local endLeftY = pStart.y + (y * self.sWidth) + (i * distance)
  141.         local endLeftZ = pStart.z + (z * self.sWidth) + (u * distance)
  142.        
  143.         local startRightX = pStart.x - (x * self.sWidth)
  144.         local startRightY = pStart.y - (y * self.sWidth)
  145.         local startRightZ = pStart.z - (z * self.sWidth)
  146.         local endRightX = pStart.x - (x * self.sWidth) + (t * distance)
  147.         local endRightY = pStart.y - (y * self.sWidth) + (i * distance)
  148.         local endRightZ = pStart.z - (z * self.sWidth)+ (u * distance)
  149.  
  150.         local startLeft = WorldToScreen(D3DXVECTOR3(startLeftX, startLeftY, startLeftZ))
  151.         local endLeft = WorldToScreen(D3DXVECTOR3(endLeftX, endLeftY, endLeftZ))
  152.         local startRight = WorldToScreen(D3DXVECTOR3(startRightX, startRightY, startRightZ))
  153.         local endRight = WorldToScreen(D3DXVECTOR3(endRightX, endRightY, endRightZ))
  154.        
  155.         local poly = Polygon(Point(startLeft.x, startLeft.y),  Point(endLeft.x, endLeft.y), Point(startRight.x, startRight.y),   Point(endRight.x, endRight.y))
  156.  
  157.          for index, minion in pairs(self.enemyMinions.objects) do
  158.             if minion ~= nil and minion.valid and not minion.dead then
  159.                 if GetDistance(pStart, minion) < distance then
  160.                     local pos, t, vec = prediction:GetPrediction(minion)
  161.                     local lineSegmentLeft = LineSegment(Point(startLeftX,startLeftZ), Point(endLeftX, endLeftZ))
  162.                     local lineSegmentRight = LineSegment(Point(startRightX,startRightZ), Point(endRightX, endRightZ))
  163.                     local toScreen, toPoint
  164.                     if pos ~= nil then
  165.                         toScreen = WorldToScreen(D3DXVECTOR3(minion.x, minion.y, minion.z))
  166.                         toPoint = Point(toScreen.x, toScreen.y)
  167.                     else
  168.                         toScreen = WorldToScreen(D3DXVECTOR3(minion.x, minion.y, minion.z))
  169.                         toPoint = Point(toScreen.x, toScreen.y)
  170.                     end
  171.  
  172.  
  173.                     if poly:contains(toPoint) then
  174.                         table.insert(mCollision, minion)
  175.                     else
  176.                         if pos ~= nil then
  177.                             distance1 = Point(pos.x, pos.z):distance(lineSegmentLeft)
  178.                             distance2 = Point(pos.x, pos.z):distance(lineSegmentRight)
  179.                         else
  180.                             distance1 = Point(minion.x, minion.z):distance(lineSegmentLeft)
  181.                             distance2 = Point(minion.x, minion.z):distance(lineSegmentRight)
  182.                         end
  183.                         if (distance1 < (getHitBoxRadius(minion)*2+10) or distance2 < (getHitBoxRadius(minion) *2+10)) then
  184.                             table.insert(mCollision, minion)
  185.                         end
  186.                     end
  187.                 end
  188.             end
  189.         end
  190.         if #mCollision > 0 then return true, mCollision else return false, mCollision end
  191.     end
  192.  
  193.     function CollisionPE:GetHeroCollision(pStart, pEnd, mode)
  194.         if mode == nil then mode = HERO_ENEMY end
  195.         local heros = {}
  196.  
  197.         for i = 1, heroManager.iCount do
  198.             local hero = heroManager:GetHero(i)
  199.             if (mode == HERO_ENEMY or mode == HERO_ALL) and hero.team ~= myHero.team then
  200.                 table.insert(heros, hero)
  201.             elseif (mode == HERO_ALLY or mode == HERO_ALL) and hero.team == myHero.team and not hero.isMe then
  202.                 table.insert(heros, hero)
  203.             end
  204.         end
  205.  
  206.         local distance =  GetDistance(pStart, pEnd)
  207.         local prediction = TargetPredictionVIP(self.sRange, self.projSpeed, self.sDelay, self.sWidth)
  208.         local hCollision = {}
  209.  
  210.         if distance > self.sRange then
  211.             distance = self.sRange
  212.         end
  213.  
  214.         local V = Vector(pEnd) - Vector(pStart)
  215.         local k = V:normalized()
  216.         local P = V:perpendicular2():normalized()
  217.  
  218.         local t,i,u = k:unpack()
  219.         local x,y,z = P:unpack()
  220.  
  221.         local startLeftX = pStart.x + (x *self.sWidth)
  222.         local startLeftY = pStart.y + (y *self.sWidth)
  223.         local startLeftZ = pStart.z + (z *self.sWidth)
  224.         local endLeftX = pStart.x + (x * self.sWidth) + (t * distance)
  225.         local endLeftY = pStart.y + (y * self.sWidth) + (i * distance)
  226.         local endLeftZ = pStart.z + (z * self.sWidth) + (u * distance)
  227.        
  228.         local startRightX = pStart.x - (x * self.sWidth)
  229.         local startRightY = pStart.y - (y * self.sWidth)
  230.         local startRightZ = pStart.z - (z * self.sWidth)
  231.         local endRightX = pStart.x - (x * self.sWidth) + (t * distance)
  232.         local endRightY = pStart.y - (y * self.sWidth) + (i * distance)
  233.         local endRightZ = pStart.z - (z * self.sWidth)+ (u * distance)
  234.  
  235.         local startLeft = WorldToScreen(D3DXVECTOR3(startLeftX, startLeftY, startLeftZ))
  236.         local endLeft = WorldToScreen(D3DXVECTOR3(endLeftX, endLeftY, endLeftZ))
  237.         local startRight = WorldToScreen(D3DXVECTOR3(startRightX, startRightY, startRightZ))
  238.         local endRight = WorldToScreen(D3DXVECTOR3(endRightX, endRightY, endRightZ))
  239.        
  240.         local poly = Polygon(Point(startLeft.x, startLeft.y),  Point(endLeft.x, endLeft.y), Point(startRight.x, startRight.y),   Point(endRight.x, endRight.y))
  241.  
  242.         for index, hero in pairs(heros) do
  243.             if hero ~= nil and hero.valid and not hero.dead then
  244.                 if GetDistance(pStart, hero) < distance then
  245.                     local pos, t, vec = prediction:GetPrediction(hero)
  246.                     local lineSegmentLeft = LineSegment(Point(startLeftX,startLeftZ), Point(endLeftX, endLeftZ))
  247.                     local lineSegmentRight = LineSegment(Point(startRightX,startRightZ), Point(endRightX, endRightZ))
  248.                     local toScreen, toPoint
  249.                     if pos ~= nil then
  250.                         toScreen = WorldToScreen(D3DXVECTOR3(pos.x, hero.y, pos.z))
  251.                         toPoint = Point(toScreen.x, toScreen.y)
  252.                     else
  253.                         toScreen = WorldToScreen(D3DXVECTOR3(hero.x, hero.y, hero.z))
  254.                         toPoint = Point(toScreen.x, toScreen.y)
  255.                     end
  256.  
  257.  
  258.                     if poly:contains(toPoint) then
  259.                         table.insert(hCollision, hero)
  260.                     else
  261.                         if pos ~= nil then
  262.                             distance1 = Point(pos.x, pos.z):distance(lineSegmentLeft)
  263.                             distance2 = Point(pos.x, pos.z):distance(lineSegmentRight)
  264.                         else
  265.                             distance1 = Point(hero.x, hero.z):distance(lineSegmentLeft)
  266.                             distance2 = Point(hero.x, hero.z):distance(lineSegmentRight)
  267.                         end
  268.                         if (distance1 < (getHitBoxRadius(hero)*2+10) or distance2 < (getHitBoxRadius(hero) *2+10)) then
  269.                             table.insert(hCollision, hero)
  270.                         end
  271.                     end
  272.                 end
  273.             end
  274.         end
  275.         if #hCollision > 0 then return true, hCollision else return false, hCollision end
  276.     end
  277.  
  278.     function CollisionPE:GetCollision(pStart, pEnd)
  279.         local b , minions = self:GetMinionCollision(pStart, pEnd)
  280.         local t , heros = self:GetHeroCollision(pStart, pEnd, HERO_ENEMY)
  281.  
  282.         if not b then return t, heros end
  283.         if not t then return b, minions end
  284.  
  285.         local all = {}
  286.  
  287.         for index, hero in pairs(heros) do
  288.             table.insert(all, hero)
  289.         end
  290.  
  291.         for index, minion in pairs(minions) do
  292.             table.insert(all, minion)
  293.         end
  294.  
  295.         return true, all
  296.     end
  297.  
  298.     function getHitBoxRadius(target)
  299.         return GetDistance(target, target.minBBox)/2
  300.     end
  301. -- }
  302.  
  303. _G.evade = false
  304. evadeBuffer = 15 -- expand the dangerous area (safer evades in laggy situations)
  305. moveBuffer = 25 -- additional movement distance (champions stop a few pixels before their destination)
  306. smoothing = 75 -- make movements smoother by moving further between evasion phases
  307. local collizion = CollisionPE(500, 400, 0, 100)
  308. champions = {
  309.     ["Lux"] = {charName = "Lux", skillshots = {
  310.         ["Light Binding"] =  {name = "Light Binding", spellName = "LuxLightBinding", spellDelay = 250, projectileName = "LuxLightBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 80, type = "line", cc = "true"},
  311.         ["Lucent Singularity"] =  {name = "Lucent Singularity", spellName = "LuxLightStrikeKugel", spellDelay = 237, projectileName = "LuxLightstrike_mis.troy", projectileSpeed = 1310, range = 1100, radius = 187.5, type = "circular", cc = "false"}
  312.     }},
  313.     ["Nidalee"] = {charName = "Nidalee", skillshots = {
  314.         ["Javelin Toss"] = {name = "Javelin Toss", spellName = "JavelinToss", spellDelay = 100, projectileName = "nidalee_javelinToss_mis.troy", projectileSpeed = 1300, range = 1500, radius = 60, type = "line", cc = "false"}
  315.     }},
  316.     ["Kennen"] = {charName = "Kennen", skillshots = {
  317.         ["Thundering Shuriken"] = {name = "Thundering Shuriken", spellName = "KennenShurikenHurlMissile1", spellDelay = 180, projectileName = "kennen_ts_mis.troy", projectileSpeed = 1640, range = 1050, radius = 53, type = "line", cc = "false"}
  318.     }},
  319.     ["Amumu"] = {charName = "Amumu", skillshots = {
  320.         ["Bandage Toss"] = {name = "Bandage Toss", spellName = "BandageToss", spellDelay = 250, projectileName = "Bandage_beam.troy", projectileSpeed = 2000, range = 1100, radius = 80, type = "line", cc = "true"}
  321.     }},
  322.     ["Lee Sin"] = {charName = "LeeSin", skillshots = {
  323.         ["Sonic Wave"] = {name = "Sonic Wave", spellName = "BlindMonkQOne", spellDelay = 250, projectileName = "blindMonk_Q_mis_01.troy", projectileSpeed = 1800, range = 1100, radius = 60, type = "line", cc = "false"}
  324.     }},
  325.     ["Morgana"] = {charName = "Morgana", skillshots = {
  326.         ["Dark Binding"] = {name = "Dark Binding", spellName = "DarkBindingMissile", spellDelay = 250, projectileName = "DarkBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 70, type = "line", cc = "true"}
  327.     }},
  328.     ["Ezreal"] = {charName = "Ezreal", skillshots = {
  329.         ["Mystic Shot"]             = {name = "Mystic Shot",      spellName = "EzrealMysticShotMissile",      spellDelay = 250,  projectileName = "Ezreal_mysticshot_mis.troy",  projectileSpeed = 1975, range = 1200,  radius = 80,  type = "line", cc = "false"},
  330.         --["Essence Flux"]            = {name = "Essence Flux",     spellName = "EzrealEssenceFluxMissile",     spellDelay = 250,  projectileName = "Ezreal_essenceflux_mis.troy", projectileSpeed = 1510, range = 1050,  radius = 60,  type = "line", cc = "false"},        
  331.         ["Trueshot Barrage"]        = {name = "Trueshot Barrage", spellName = "EzrealTrueshotBarrage",        spellDelay = 1000, projectileName = "Ezreal_TrueShot_mis.troy",    projectileSpeed = 1990, range = 20000, radius = 250, type = "line", cc = "false"},
  332.         ["Mystic Shot (Pulsefire)"] = {name = "Mystic Shot",      spellName = "EzrealMysticShotPulseMissile", spellDelay = 250,  projectileName = "Ezreal_mysticshot_mis.troy",  projectileSpeed = 1975, range = 1200,  radius = 80,  type = "line", cc = "false"}
  333.     }},
  334.     ["Ahri"] = {charName = "Ahri", skillshots = {
  335.         ["Orb of Deception"] = {name = "Orb of Deception", spellName = "AhriOrbofDeception", spellDelay = 250, projectileName = "Ahri_Orb_mis.troy",   projectileSpeed = 1660, range = 1000, radius = 50, type = "line", cc = "false"},
  336.         ["Charm"]            = {name = "Charm",            spellName = "AhriSeduce",         spellDelay = 250, projectileName = "Ahri_Charm_mis.troy", projectileSpeed = 1535, range = 1000, radius = 50, type = "line", cc = "true"}
  337.     }},
  338.     ["Leona"] = {charName = "Leona", skillshots = {
  339.         ["Zenith Blade"] = {name = "LeonaZenithBlade", spellName = "LeonaZenithBlade", spellDelay = 250, projectileName = "Leona_ZenithBlade_mis.troy", projectileSpeed = 2000, range = 900, radius = 90, type = "line", cc = "true"},
  340.         ["Solar Flare"] = {name = "SolarFlare", spellName = "LeonaSolarFlare", spellDelay = 250, projectileName = "TEST", projectileSpeed = 1000, range = 1200, radius = 250, type = "circular", cc = "true"}
  341.     }},
  342.     ["Chogath"] = {charName = "Chogath", skillshots = {
  343.         ["Rupture"] = {name = "Rupture", spellName = "Rupture", spellDelay = 290, projectileName = "rupture_cas_01_red_team.troy", projectileSpeed = 1000, range = 950, radius = 190, type = "circular", cc = "true"}
  344.     }},
  345.     ["Blitzcrank"] = {charName = "Blitzcrank", skillshots = {
  346.         ["RocketGrab"] = {name = "RocketGrab", spellName = "RocketGrabMissile", spellDelay = 125, projectileName = "FistGrab_mis.troy", projectileSpeed = 1800, range = 1050, radius = 70, type = "line", cc = "true"}
  347.     }},
  348.     ["Anivia"] = {charName = "Anivia", skillshots = {
  349.         ["Flash Frost"] = {name = "Flash Frost", spellName = "FlashFrostSpell", spellDelay = 250, projectileName = "Cryo_FlashFrost_mis.troy", projectileSpeed = 850, range = 1100, radius = 110, type = "line", cc = "true"}
  350.     }},
  351.     ["Zyra"] = {charName = "Zyra", skillshots = {
  352.         ["Grasping Roots"] = {name = "Grasping Roots", spellName = "ZyraGraspingRoots", spellDelay = 250, projectileName = "Zyra_E_sequence_impact.troy", projectileSpeed = 1150, range = 1150, radius = 70,  type = "line", cc = "true"},
  353.         ["Zyra Passive Death"] = {name = "Zyra Passive", spellName = "ZyraPassiveDeathMissile", spellDelay = 250, projectileName = "zyra_passive_plant_mis_fire.troy", projectileSpeed = 1900, range = 1474, radius = 70,  type = "line", cc = "false"},
  354.     }},
  355.     ["Nautilus"] = {charName = "Nautilus", skillshots = {
  356.         ["Dredge Line"] = {name = "Dredge Line", spellName = "NautilusAnchorDragMissile", spellDelay = 250, projectileName = "Nautilus_Q_mis.troy", projectileSpeed = 1965, range = 1075, radius = 60, type = "line", cc = "true"}
  357.     }},
  358.     ["Caitlyn"] = {charName = "Caitlyn", skillshots = {
  359.         ["Piltover Peacemaker"] = {name = "Piltover Peacemaker", spellName = "CaitlynPiltoverPeacemaker", spellDelay = 625, projectileName = "caitlyn_Q_mis.troy", projectileSpeed = 2150, range = 1300, radius = 60, type = "line", cc = "false"}
  360.     }},
  361.     ["Mundo"] = {charName = "DrMundo", skillshots = {
  362.         ["Infected Cleaver"] = {name = "Infected Cleaver", spellName = "InfectedCleaverMissile", spellDelay = 250, projectileName = "dr_mundo_infected_cleaver_mis.troy", projectileSpeed = 1975, range = 1050, radius = 70, type = "line", cc = "false"}
  363.     }},
  364.     ["Brand"] = {charName = "Brand", skillshots = {
  365.         ["Brand Missile"] = {name = "BrandBlazeMissile", spellName = "BrandBlazeMissile", spellDelay = 250, projectileName = "BrandBlaze_mis.troy", projectileSpeed = 1565, range = 1100, radius = 50, type = "line", cc = "false"},
  366.     }},
  367.     ["Corki"] = {charName = "Corki", skillshots = {
  368.         ["Missile Barrage small"] = {name = "Missile Barrage small", spellName = "MissileBarrageMissile", spellDelay = 175, projectileName = "corki_MissleBarrage_mis.troy", projectileSpeed = 1950, range = 1250, radius = 50, type = "line", cc = "false"},
  369.         ["Missile Barrage big"] = {name = "Missile Barrage big", spellName = "MissileBarrageMissile2", spellDelay = 175, projectileName = "corki_MissleBarrage_DD_mis.troy", projectileSpeed = 1950, range = 1250, radius = 50, type = "line", cc = "false"}
  370.     }},
  371.     ["Swain"] = {charName = "Swain", skillshots = {
  372.         ["Nevermove"] = {name = "Nevermove", spellName = "SwainShadowGrasp", spellDelay = 250, projectileName = "swain_shadowGrasp_transform.troy", projectileSpeed = 1000, range = 900, radius = 180, type = "circular", cc = "true"}
  373.     }},
  374.     ["Ashe"] = {charName = "Ashe", skillshots = {
  375.         ["EnchantedArrow"] = {name = "EnchantedArrow", spellName = "EnchantedCrystalArrow", spellDelay = 125, projectileName = "EnchantedCrystalArrow_mis.troy", projectileSpeed = 1600, range = 25000, radius = 150, type="line", cc = "true"}
  376.     }},
  377.     ["KogMaw"] = {charName = "KogMaw", skillshots = {
  378.         ["Living Artillery"] = {name = "Living Artillery", spellName = "KogMawLivingArtillery", spellDelay = 250, projectileName = "KogMawLivingArtillery_cas_green.troy", projectileSpeed = 1050, range = 2200, radius = 180, type="circular", cc = "false"}
  379.     }},
  380.     ["KhaZix"] = {charName = "KhaZix", skillshots = {
  381.         ["KhaZix W Missile"] = {name = "KhaZix W Enhanced", spellName = "KhaZixW", spellDelay = 250, projectileName = "Khazix_W_mis.troy", projectileSpeed = 1700, range = 1025, radius = 70, type="line", cc = "false"},
  382.     }},
  383.     ["Zed"] = {charName = "Zed", skillshots = {
  384.         ["ZedShuriken"] = {name = "ZedShuriken", spellName = "ZedShuriken", spellDelay = 0, projectileName = "Zed_Q_Mis.troy", projectileSpeed = 1700, range = 925, radius = 50, type="line", cc = "false"}
  385.     }},
  386.     ["Leblanc"] = {charName = "Leblanc", skillshots = {
  387.         ["Ethereal Chains"] = {name = "Ethereal Chains", spellName = "LeblancSoulShackle", spellDelay = 250, projectileName = "leBlanc_shackle_mis.troy", projectileSpeed = 1585, range = 960, radius = 50, type = "line", cc = "true"},
  388.         ["Ethereal Chains R"] = {name = "Ethereal Chains R", spellName = "LeblancSoulShackleM", spellDelay = 250, projectileName = "leBlanc_shackle_mis_ult.troy", projectileSpeed = 1585, range = 960, radius = 50, type = "line", cc = "true"},
  389.     }},
  390.     ["Elise"] = {charName = "Elise", skillshots = {
  391.         ["Cocoon"] = {name = "Cocoon", spellName = "EliseHumanE", spellDelay = 250, projectileName = "Elise_human_E_mis.troy", projectileSpeed = 1450, range = 1100, radius = 70, type="line", cc = "true"}
  392.     }},
  393.     ["Lulu"] = {charName = "Lulu", skillshots = {
  394.         ["luluQ1"] = {name = "luluQ1", spellName = "LuluQMissile", spellDelay = 100, projectileName = "Lulu_Q_Mis.troy", projectileSpeed = 1450, range = 1000, radius = 50, type="line", cc = "false"},
  395.         ["luluQ2"] = {name = "luluQ2", spellName = "LuluQ", spellDelay = 250, projectileName = "Lulu_Q_Mis.troy", projectileSpeed = 1375, range = 1000, radius = 50, type="line", cc = "false"}
  396.     }},
  397.     ["Thresh"] = {charName = "Thresh", skillshots = {
  398.         ["ThreshQ"] = {name = "ThreshQ", spellName = "ThreshQ", spellDelay = 500, projectileName = "Thresh_Q_whip_beam.troy", projectileSpeed = 1900, range = 1100, radius = 70, type="line", cc = "true"}
  399.     }},
  400.     ["Shen"] = {charName = "Shen", skillshots = {
  401.         ["ShadowDash"] = {name = "ShadowDash", spellName = "ShenShadowDash", spellDelay = 125, projectileName = "shen_shadowDash_mis.troy", projectileSpeed = 2000, range = 575, radius = 50, type="line", cc = "true"}
  402.     }},
  403.     ["Quinn"] = {charName = "Quinn", skillshots = {
  404.         ["QuinnQ"] = {name = "QuinnQ", spellName = "QuinnQ", spellDelay = 100, projectileName = "Quinn_Q_missile.troy", projectileSpeed = 1550, range = 1050, radius = 80, type="line", cc = "true"}
  405.     }},
  406.     ["Nami"] = {charName = "Nami", skillshots = {
  407.         ["NamiQ"] = {name = "NamiQ", spellName = "NamiQ", spellDelay = 700, projectileName = "Nami_Q_mis.troy", projectileSpeed = 800, range = 875, radius = 225, type="circular", cc = "true"},    
  408.     }},
  409.     ["Malphite"] = {charName = "Malphite", skillshots = {
  410.         ["UFSlash"] = {name = "UFSlash", spellName = "UFSlash", spellDelay = 250, projectileName = "TEST", projectileSpeed = 1800, range = 1000, radius = 160, type="line", cc = "true"},    
  411.     }},
  412.     ["Sejuani"] = {charName = "Sejuani", skillshots = {
  413.         ["SejuaniR"] = {name = "SejuaniR", spellName = "SejuaniGlacialPrisonCast", spellDelay = 250, projectileName = "Sejuani_R_mis.troy", projectileSpeed = 1600, range = 1200, radius = 110, type="line", cc = "true"},    
  414.     }},
  415.     ["Varus"] = {charName = "Varus", skillshots = {
  416.         ["VarusR"] = {name = "VarusR", spellName = "VarusR", spellDelay = 250, projectileName = "VarusRMissile.troy", projectileSpeed = 2000, range = 1250, radius = 100, type="line", cc = "true"},
  417.     }},
  418.     ["Fizz"] = {charName = "Fizz", skillshots = {
  419.         ["FizzR1"] = {name = "FizzR1", spellName = "FizzMarinerDoom", spellDelay = 250, projectileName = "Fizz_UltimateMissile.troy", projectileSpeed = 1375, range = 1300, radius = 80, type = "line", cc = "true"}, -- line part
  420.     }},
  421.     ["Karthus"] = {charName = "Karthus", skillshots = {
  422.         ["Lay Waste"] = {name = "Lay Waste", spellName = "LayWaste", spellDelay = 390, projectileName = "LayWaste_point.troy", projectileSpeed = 500, range = 875, radius = 140, type = "circular", cc = "false"}
  423.     }},
  424.     ["Cassiopeia"] = {charName = "Cassiopeia", skillshots = {
  425.         ["Noxious Blast"] = {name = "Noxious Blast", spellName = "CassiopeiaNoxiousBlast", spellDelay = 200, projectileName = "CassNoxiousSnakePlane_green.troy", projectileSpeed = 460, range = 850, radius = 150, type = "circular", cc = "false"},
  426.     }},
  427.     ["Orianna"] = {charName = "Orianna", skillshots = {
  428.         -- Not sure if this is correct.
  429.         ["Command: Dissonance"] = {name = "Command: Dissonance", spellName = "OrianaDissonanceCommand", spellDelay = 250, projectileName = "Orianadissonance_Cas_Green.troy", projectileSpeed = 1050, range = 250, radius = 250, type="circular", cc = "true"}
  430.     }},
  431.     ["Ziggs"] = {charName = "Ziggs", skillshots = {
  432.         -- Not sure if this is correct.
  433.         ["Bouncing Bomb"] = {name = "Bouncing Bomb", spellName = "ZiggsQSpell", spellDelay = 218, projectileName = "ZiggsQBounce.troy", projectileSpeed = 1722, range = 850, radius = 150, type="line", cc = "false"}
  434.     }}
  435. }
  436.  
  437. -- Globals ---------------------------------------------------------------------
  438. enemyes = {}
  439. nAllies = 0
  440. allies = {}
  441. nEnemies = 0
  442. evading             = false
  443. allowCustomMovement = true
  444. captureMovements    = true
  445. lastMovement        = {}
  446. detectedSkillshots  = {}
  447. nSkillshots = 0
  448.  
  449. -- Code ------------------------------------------------------------------------
  450. function getTarget(targetId)
  451.     if targetId ~= 0 and targetId ~= nil then
  452.         return objManager:GetObjectByNetworkId(targetId)
  453.     end
  454.     return nil
  455. end
  456.  
  457. function getLastMovementDestination()
  458.     if lastMovement.type == 3 then
  459.         heroPosition = Point(myHero.x, myHero.z)
  460.  
  461.         target = getTarget(lastMovement.targetId)
  462.         if _isValidTarget(target) then
  463.             targetPosition = Point(target.x, target.z)
  464.  
  465.             local attackRange = (myHero.range + GetDistance(myHero.minBBox, myHero.maxBBox) / 2 + GetDistance(target.minBBox, target.maxBBox) / 2)
  466.  
  467.             if attackRange <= heroPosition:distance(targetPosition) then
  468.                 return targetPosition + (heroPosition - targetPosition):normalized() * attackRange
  469.             else
  470.                 return heroPosition
  471.             end
  472.         else
  473.             return heroPosition
  474.         end
  475.     elseif lastMovement.type == 7 then
  476.         heroPosition = Point(myHero.x, myHero.z)
  477.  
  478.         target = getTarget(lastMovement.targetId)
  479.         if _isValidTarget(target) then
  480.             targetPosition = Point(target.x, target.z)
  481.  
  482.             local castRange = myHero:GetSpellData(lastMovement.spellId).range
  483.  
  484.             if castRange <= heroPosition:distance(targetPosition) then
  485.                 return targetPosition + (heroPosition - targetPosition):normalized() * castRange
  486.             else
  487.                 return heroPosition
  488.             end
  489.         else
  490.             local castRange = myHero:GetSpellData(lastMovement.spellId).range
  491.  
  492.             if castRange <= heroPosition:distance(lastMovement.destination) then
  493.                 return lastMovement.destination + (heroPosition - lastMovement.destination):normalized() * castRange
  494.             else
  495.                 return heroPosition
  496.             end
  497.         end
  498.     else
  499.         return lastMovement.destination
  500.     end
  501. end
  502.  
  503. function OnLoad()
  504.     stopEvade()
  505.  
  506.     isVayne = false
  507.     if myHero.charName == "Vayne" then
  508.         isVayne = true
  509.     end
  510.     isGraves = false
  511.     if myHero.charName == "Graves" then
  512.         isGraves = true
  513.     end
  514.     isEzreal = false
  515.     if myHero.charName == "Ezreal" then
  516.         isEzreal = true
  517.     end
  518.     isKassadin = false
  519.     if myHero.charName == "Kassadin" then
  520.         isKassadin = true
  521.     end
  522.     isRiven = false
  523.     if myHero.charName == "Riven" then
  524.         isRiven = true
  525.     end
  526.     isRenekton = false         
  527.     if myHero.charName == "Renekton" then
  528.         isRenekton = true
  529.     end
  530.     isTristana = false
  531.     if myHero.charName == "Tristana" then
  532.         isTristana = true
  533.     end
  534.     isCorki = false
  535.     if myHero.charName == "Corki" then
  536.         isCorki = true
  537.     end
  538.  
  539.     lastMovement = {
  540.         destination = Point(myHero.x, myHero.z),
  541.         moveCommand = Point(myHero.x, myHero.z),
  542.         type = 2,
  543.         targetId = nil,
  544.         spellId = nil,
  545.         approachedPoint = nil
  546.     }
  547.  
  548.     PerfectEvadeConfig = scriptConfig("Good Evade", "goodEvade")
  549.     PerfectEvadeConfig:addParam("dodgeEnabled", "Dodge Skillshots", SCRIPT_PARAM_ONOFF, true)
  550.     PerfectEvadeConfig:addParam("drawEnabled", "Draw Skillshots", SCRIPT_PARAM_ONOFF, true)
  551.     PerfectEvadeConfig:addParam("dodgeCConly", "Dodge CC only spells", SCRIPT_PARAM_ONKEYDOWN, false, 32)
  552.     PerfectEvadeConfig:permaShow("dodgeEnabled")
  553.  
  554.     for i = 1, heroManager.iCount do
  555.         local hero = heroManager:GetHero(i)
  556.         if hero.team ~= myHero.team then
  557.             table.insert(enemyes, hero)
  558.         elseif hero.team == myHero.team and hero.nEnemies ~= myHero.networkID then
  559.             table.insert(allies, hero)
  560.         end
  561.     end
  562.  
  563.     if #enemyes > 0 then
  564.         for i, skillShotChampion in pairs(champions) do
  565.             local noChampionFound = true
  566.             for j, enemy in ipairs(enemyes) do
  567.                 if skillShotChampion.charName == enemyes[j].charName then
  568.                     noChampionFound = false
  569.                 end
  570.             end
  571.             if noChampionFound then champions[i] = nil end
  572.         end
  573.     end
  574.  
  575.     PerfectEvadeConfig.dodgeEnabled = true
  576.  
  577.     PrintChat(" >> Good Evade 0.13 loaded")
  578. end
  579.  
  580. function OnSendPacket(p)
  581.     local packet = Packet(p)
  582.     if packet:get('name') == 'S_MOVE' then
  583.         if packet:get('sourceNetworkId') == myHero.networkID then
  584.             if captureMovements then
  585.                 lastMovement.destination = Point(packet:get('x'), packet:get('y'))
  586.                 lastMovement.type = packet:get('type')
  587.                 lastMovement.targetId = packet:get('targetNetworkId')
  588.  
  589.                 if evading then
  590.                     for i, detectedSkillshot in pairs(detectedSkillshots) do
  591.                         if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point(myHero.x, myHero.z)) then
  592.                             dodgeSkillshot(detectedSkillshot)
  593.                             break
  594.                         end
  595.                     end
  596.                 end
  597.             end
  598.             if not allowCustomMovement then
  599.                 packet:block()
  600.             end          
  601.         end
  602.     elseif packet:get('name') == 'S_CAST' then
  603.         if captureMovements then
  604.             lastMovement.spellId = packet:get('spellId')
  605.             lastMovement.type = 7
  606.             lastMovement.targetId = packet:get('targetNetworkId')
  607.             lastMovement.destination = Point(packet:get('toX'), packet:get('toY'))
  608.  
  609.             if evading then
  610.                 for i, detectedSkillshot in pairs(detectedSkillshots) do
  611.                     if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point(myHero.x, myHero.z)) then
  612.                         dodgeSkillshot(detectedSkillshot)
  613.                         break
  614.                     end
  615.                 end
  616.             end
  617.         end
  618.  
  619.         if not allowCustomMovement then
  620.             packet:block()
  621.         end
  622.     end
  623. end
  624.  
  625. function getSideOfLine(linePoint1, linePoint2, point)
  626.     if not point then return 0 end
  627.     result = ((linePoint2.x - linePoint1.x) * (point.y - linePoint1.y) - (linePoint2.y - linePoint1.y) * (point.x - linePoint1.x))
  628.     if result < 0 then
  629.         return -1
  630.     elseif result > 0 then
  631.         return 1
  632.     else
  633.         return 0
  634.     end
  635. end
  636.  
  637. function dodgeSkillshot(skillshot)
  638.     if PerfectEvadeConfig.dodgeEnabled and not myHero.dead and (myHero.casting == 0 or lastMovement.spellId == RECALL) then
  639.         if skillshot.skillshot.type == "line" then
  640.             dodgeLineShot(skillshot)
  641.         else
  642.             dodgeCircularShot(skillshot)
  643.         end
  644.     end
  645. end
  646.  
  647. function dodgeCircularShot(skillshot)
  648.     smoothing = 0
  649.     skillshot.evading = true
  650.  
  651.     heroPosition = Point(myHero.x, myHero.z)
  652.  
  653.     moveableDistance = myHero.ms * math.max(skillshot.endTick - GetTickCount() - GetLatency(), 0) / 1000
  654.     evadeRadius = skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer
  655.  
  656.     safeTarget = skillshot.endPosition + (heroPosition - skillshot.endPosition):normalized() * evadeRadius
  657.  
  658.     if getLastMovementDestination():distance(skillshot.endPosition) <= evadeRadius then
  659.         closestTarget = skillshot.endPosition + (getLastMovementDestination() - skillshot.endPosition):normalized() * evadeRadius
  660.     else
  661.         closestTarget = nil
  662.     end
  663.        
  664.     lineDistance = Line(heroPosition, getLastMovementDestination()):distance(skillshot.endPosition)
  665.     directionTarget = heroPosition + (getLastMovementDestination() - heroPosition):normalized() * (math.sqrt(heroPosition:distance(skillshot.endPosition)^2 - lineDistance^2) + math.sqrt(evadeRadius^2 - lineDistance^2))
  666.     if directionTarget:distance(skillshot.endPosition) >= evadeRadius + 1 then
  667.         directionTarget = heroPosition + (getLastMovementDestination() - heroPosition):normalized() * (math.sqrt(evadeRadius^2 - lineDistance^2) - math.sqrt(heroPosition:distance(skillshot.endPosition)^2 - lineDistance^2))
  668.     end
  669.  
  670.     possibleMovementTargets = {}
  671.     intersectionPoints = Circle(skillshot.endPosition, evadeRadius):intersectionPoints(Circle(heroPosition, moveableDistance))
  672.     if #intersectionPoints == 2 then
  673.         leftTarget = intersectionPoints[1]
  674.         rightTarget = intersectionPoints[2]
  675.  
  676.         local theta = ((-skillshot.endPosition + leftTarget):polar() - (-skillshot.endPosition + rightTarget):polar()) % 360
  677.         if ((theta >= 180 and getSideOfLine(skillshot.endPosition, leftTarget, directionTarget)
  678.             == getSideOfLine(skillshot.endPosition, leftTarget, heroPosition)
  679.             and getSideOfLine(skillshot.endPosition, rightTarget, directionTarget)
  680.             == getSideOfLine(skillshot.endPosition, rightTarget, heroPosition))
  681.         or (theta <= 180 and (getSideOfLine(skillshot.endPosition, leftTarget, directionTarget)
  682.             == getSideOfLine(skillshot.endPosition, leftTarget, heroPosition)
  683.             or getSideOfLine(skillshot.endPosition, rightTarget, directionTarget)
  684.             == getSideOfLine(skillshot.endPosition, rightTarget, heroPosition)))) then
  685.             table.insert(possibleMovementTargets, directionTarget)
  686.         end
  687.  
  688.         if _isValidTarget(closestTarget) and ((theta >= 180 and getSideOfLine(skillshot.endPosition, leftTarget, closestTarget) == getSideOfLine(skillshot.endPosition, leftTarget, heroPosition) and getSideOfLine(skillshot.endPosition, rightTarget, closestTarget) == getSideOfLine(skillshot.endPosition, rightTarget, heroPosition)) or (theta <= 180 and (getSideOfLine(skillshot.endPosition, leftTarget, closestTarget) == getSideOfLine(skillshot.endPosition, leftTarget, heroPosition) or getSideOfLine(skillshot.endPosition, rightTarget, closestTarget) == getSideOfLine(skillshot.endPosition, rightTarget, heroPosition)))) then
  689.             table.insert(possibleMovementTargets, closestTarget)
  690.         end
  691.  
  692.         table.insert(possibleMovementTargets, safeTarget)
  693.         table.insert(possibleMovementTargets, leftTarget)
  694.         table.insert(possibleMovementTargets, rightTarget)
  695.     else
  696.         if skillshot.skillshot.radius <= moveableDistance then
  697.             table.insert(possibleMovementTargets, closestTarget)
  698.             table.insert(possibleMovementTargets, directionTarget)
  699.             table.insert(possibleMovementTargets, safeTarget)
  700.         end
  701.     end
  702.  
  703.     closestPoint = findBestDirection(getLastMovementDestination(), possibleMovementTargets)
  704.     if closestPoint ~= nil then
  705.         closestPoint = closestPoint + (closestPoint - heroPosition):normalized() * smoothing
  706.         evadeTo(closestPoint.x, closestPoint.y, skillshot.skillshot.cc == "true")
  707.     elseif NeedDash(skillshot, true) then
  708.         if not evading then
  709.             -- CAN NOT EVADE - STILL TRY IT
  710.             --safeTarget = safeTarget + (safeTarget - heroPosition):normalized() * smoothing
  711.             evadeTo(safeTarget.x, safeTarget.y, true)
  712.         end
  713.     end
  714. end
  715.  
  716. function dodgeLineShot(skillshot)
  717.     heroPosition = Point(myHero.x, myHero.z)
  718.    
  719.     _setSmoothing(skillshot)
  720.  
  721.     skillshot.evading = true
  722.  
  723.     skillshotLine = Line(skillshot.startPosition, skillshot.endPosition)
  724.     distanceFromSkillshotPath = skillshotLine:distance(heroPosition)
  725.     evadeDistance = skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer
  726.  
  727.     normalVector = Point(skillshot.directionVector.y, -skillshot.directionVector.x):normalized()
  728.     nessecaryMoveWidth = evadeDistance - distanceFromSkillshotPath
  729.  
  730.     evadeTo1 = heroPosition + normalVector * nessecaryMoveWidth
  731.     evadeTo2 = heroPosition - normalVector * nessecaryMoveWidth
  732.     if skillshotLine:distance(evadeTo1) >= skillshotLine:distance(evadeTo2) then
  733.         longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, nessecaryMoveWidth)
  734.         if longitudinalApproachLength >= 0 then
  735.             evadeToTarget1 = evadeTo1 - skillshot.directionVector * longitudinalApproachLength
  736.         end
  737.  
  738.         longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, evadeDistance + distanceFromSkillshotPath)
  739.         if longitudinalApproachLength >= 0 then
  740.             evadeToTarget2 = heroPosition - normalVector * (evadeDistance + distanceFromSkillshotPath) - skillshot.directionVector * longitudinalApproachLength
  741.         end
  742.  
  743.         longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, nessecaryMoveWidth)
  744.         if longitudinalRetreatLength >= 0 then
  745.             evadeToTarget3 = evadeTo1 + skillshot.directionVector * longitudinalRetreatLength
  746.         end
  747.  
  748.         longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, evadeDistance + distanceFromSkillshotPath)
  749.         if longitudinalRetreatLength >= 0 then
  750.             evadeToTarget4 = heroPosition - normalVector * (evadeDistance + distanceFromSkillshotPath) + skillshot.directionVector * longitudinalRetreatLength
  751.         end
  752.  
  753.         safeTarget = evadeTo1
  754.  
  755.         closestPoint = getLastMovementDestination() + normalVector * (evadeDistance - skillshotLine:distance(getLastMovementDestination()))
  756.         closestPoint2 = getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) + normalVector * evadeDistance
  757.     else
  758.         longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, nessecaryMoveWidth)
  759.         if longitudinalApproachLength >= 0 then
  760.             evadeToTarget1 = evadeTo2 - skillshot.directionVector * longitudinalApproachLength
  761.         end
  762.  
  763.         longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, evadeDistance + distanceFromSkillshotPath)
  764.         if longitudinalApproachLength >= 0 then
  765.             evadeToTarget2 = heroPosition + normalVector * (evadeDistance + distanceFromSkillshotPath) - skillshot.directionVector * longitudinalApproachLength
  766.         end
  767.  
  768.         longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, nessecaryMoveWidth)
  769.         if longitudinalRetreatLength >= 0 then
  770.             evadeToTarget3 = evadeTo2 + skillshot.directionVector * longitudinalRetreatLength
  771.         end
  772.  
  773.         longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, evadeDistance + distanceFromSkillshotPath)
  774.         if longitudinalRetreatLength >= 0 then
  775.             evadeToTarget4 = heroPosition + normalVector * (evadeDistance + distanceFromSkillshotPath) + skillshot.directionVector * longitudinalRetreatLength
  776.         end
  777.  
  778.         safeTarget = evadeTo2
  779.  
  780.         closestPoint = getLastMovementDestination() - normalVector * (evadeDistance - skillshotLine:distance(getLastMovementDestination()))
  781.         closestPoint2 = getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) - normalVector * evadeDistance
  782.     end
  783.  
  784.     if skillshotLine:distance(getLastMovementDestination()) <= evadeDistance then
  785.         directionTarget = findBestDirection(getLastMovementDestination(), {closestPoint, closestPoint2, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) - normalVector * evadeDistance, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) + normalVector * evadeDistance})
  786.     else
  787.         if getSideOfLine(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) == getSideOfLine(skillshot.startPosition, skillshot.endPosition, heroPosition) then
  788.             if skillshotLine:distance(heroPosition) <= skillshotLine:distance(getLastMovementDestination()) then
  789.                 directionTarget = heroPosition + (getLastMovementDestination()-heroPosition):normalized() * ((evadeDistance - distanceFromSkillshotPath) * heroPosition:distance(getLastMovementDestination())) / (skillshotLine:distance(getLastMovementDestination()) - distanceFromSkillshotPath)
  790.             else
  791.                 directionTarget = heroPosition + (getLastMovementDestination()-heroPosition):normalized() * ((evadeDistance + distanceFromSkillshotPath) * heroPosition:distance(getLastMovementDestination())) / (distanceFromSkillshotPath - skillshotLine:distance(getLastMovementDestination()))
  792.             end
  793.         else
  794.             directionTarget = heroPosition + (getLastMovementDestination() - heroPosition):normalized() * (evadeDistance + distanceFromSkillshotPath) * heroPosition:distance(getLastMovementDestination()) / (skillshotLine:distance(getLastMovementDestination()) + distanceFromSkillshotPath)
  795.         end
  796.     end
  797.  
  798.     evadeTarget = nil
  799.     --[[if (evadeToTarget1 ~= nil and evadeToTarget3 ~= nil and Line(evadeToTarget1, evadeToTarget3):distance(directionTarget) <= 1 and getSideOfLine(evadeToTarget1, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget1), directionTarget) ~= getSideOfLine(evadeToTarget3, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget3), directionTarget)) or (evadeToTarget2 ~= nil and evadeToTarget4 ~= nil and Line(evadeToTarget2, evadeToTarget4):distance(directionTarget) <= 1 and getSideOfLine(evadeToTarget2, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget2), directionTarget) ~= getSideOfLine(evadeToTarget4, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget4), directionTarget)) or (evadeToTarget1 ~= nil and evadeToTarget3 == nil and getSideOfLine(heroPosition, evadeToTarget1, skillshot.startPosition) ~= getSideOfLine(heroPosition, evadeToTarget1, directionTarget)) or (evadeToTarget2 ~= nil and evadeToTarget4 == nil and getSideOfLine(heroPosition, evadeToTarget2, skillshot.startPosition) ~= getSideOfLine(heroPosition, evadeToTarget2, directionTarget)) then
  800.         evadeTarget = directionTarget
  801.     else]]
  802.         possibleMovementTargets = {}
  803.  
  804.     if (evadeToTarget1 ~= nil and evadeToTarget3 ~= nil and Line(evadeToTarget1, evadeToTarget3):distance(closestPoint2) <= 1 and getSideOfLine(evadeToTarget1, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget1), closestPoint2) ~= getSideOfLine(evadeToTarget3, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget3), closestPoint2)) or (evadeToTarget2 ~= nil and evadeToTarget4 ~= nil and Line(evadeToTarget2, evadeToTarget4):distance(closestPoint2) <= 1 and getSideOfLine(evadeToTarget2, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget2), closestPoint2) ~= getSideOfLine(evadeToTarget4, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, evadeToTarget4), closestPoint2)) or (evadeToTarget1 ~= nil and evadeToTarget3 == nil and getSideOfLine(heroPosition, evadeToTarget1, skillshot.startPosition) ~= getSideOfLine(heroPosition, evadeToTarget1, closestPoint2)) or (evadeToTarget2 ~= nil and evadeToTarget4 == nil and getSideOfLine(heroPosition, evadeToTarget2, skillshot.startPosition) ~= getSideOfLine(heroPosition, evadeToTarget2, closestPoint2)) then
  805.         table.insert(possibleMovementTargets, closestPoint2)
  806.     end
  807.  
  808.     if evadeToTarget1 ~= nil then
  809.         table.insert(possibleMovementTargets, evadeToTarget1)
  810.     end
  811.  
  812.     if evadeToTarget2 ~= nil then
  813.         --table.insert(possibleMovementTargets, evadeToTarget2)
  814.     end
  815.  
  816.     if evadeToTarget3 ~= nil then
  817.         table.insert(possibleMovementTargets, evadeToTarget3)
  818.     end
  819.  
  820.     if evadeToTarget4 ~= nil then
  821.         --table.insert(possibleMovementTargets, evadeToTarget4)
  822.     end
  823.  
  824.     evadeTarget = findBestDirection(getLastMovementDestination(), possibleMovementTargets)
  825.     --end
  826.  
  827.     -- try to evade until spellshields are implemented -- TEMPORARY OVERRIDE !!!
  828.     if evadeTarget == nil then
  829.         --evadeTarget = safeTarget
  830.     end
  831.  
  832.     if _isValidTarget(evadeTarget) then
  833.         if getSideOfLine(skillshot.startPosition, skillshot.endPosition, evadeTarget) == getSideOfLine(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) and skillshotLine:distance(getLastMovementDestination()) > evadeDistance then
  834.             pathDirectionVector = (evadeTarget - heroPosition)
  835.             if getSideOfLine(skillshot.startPosition, skillshot.endPosition, heroPosition) == getSideOfLine(skillshot.startPosition, skillshot.endPosition, evadeTarget) then
  836.                 evadeTarget = evadeTarget + pathDirectionVector:normalized() * (pathDirectionVector:len() + smoothing / (evadeDistance - distanceFromSkillshotPath) * pathDirectionVector:len())
  837.             else
  838.                 evadeTarget = evadeTarget + pathDirectionVector:normalized() * (pathDirectionVector:len() + smoothing / (evadeDistance + distanceFromSkillshotPath) * pathDirectionVector:len())
  839.             end
  840.         end
  841.         evadeTo(evadeTarget.x, evadeTarget.y, NeedDash(skillshot, false))
  842.     elseif NeedDash(skillshot, true) then
  843.         -- USE SPELLSHIELDS AND ABILITES TO EVADE
  844.         evadeTo(safeTarget.x, safeTarget.y, true)
  845.     end
  846. end
  847.  
  848. function _setSmoothing(skillshot)
  849.     heroPosition = Point(myHero.x, myHero.z)
  850.     local m1 = heroPosition:distance(skillshot.startPosition)
  851.     local m2 = skillshot.endPosition:distance(skillshot.startPosition)
  852.     smoothing = m1 / m2 * 100
  853.     smoothing = math.max(smoothing, 0)
  854.     smoothing = math.min(smoothing, 100)
  855.     if _isDangerSkillshot(skillshot) then
  856.         smoothing = 0
  857.     end
  858.     if not isVayne and not isRiven and not isCorki and not isGraves
  859.         and not isRenekton and not isEzreal and not isTristana and not isKassadin then
  860.         smoothing = 0
  861.     end
  862. end
  863. function _isDangerSkillshot(skillshot)
  864.     if skillshot.skillshot.name == "LeonaZenithBlade"
  865.         or skillshot.skillshot.name == "EnchantedArrow"
  866.         or skillshot.skillshot.name == "RocketGrab"
  867.         or skillshot.skillshot.name == "Command: Dissonance" then
  868.         return true
  869.     else
  870.         return false
  871.     end
  872. end
  873.  
  874. function InsideTheWall(evadeTestPoint)
  875.     local heroPosition = Point(myHero.x, myHero.z)
  876.     local dist = evadeTestPoint:distance(heroPosition)
  877.     local interval = 50
  878.     local nChecks = math.ceil((dist+50)/50)
  879.  
  880.     if evadeTestPoint.x == 0 or evadeTestPoint.y == 0 then
  881.         return true
  882.     end
  883.     for k=1, nChecks, 1 do
  884.         local checksPos = evadeTestPoint + (evadeTestPoint - heroPosition):normalized()*(interval*k)
  885.         if IsWall(D3DXVECTOR3(checksPos.x, myHero.y, checksPos.y)) then
  886.             return true
  887.         end
  888.     end
  889.     if IsWall(D3DXVECTOR3(evadeTestPoint.x + 20, myHero.y, evadeTestPoint.y + 20)) then return true end
  890.     if IsWall(D3DXVECTOR3(evadeTestPoint.x + 20, myHero.y, evadeTestPoint.y - 20)) then return true end
  891.     if IsWall(D3DXVECTOR3(evadeTestPoint.x - 20, myHero.y, evadeTestPoint.y - 20)) then return true end
  892.     if IsWall(D3DXVECTOR3(evadeTestPoint.x - 20, myHero.y, evadeTestPoint.y + 20)) then return true end
  893.  
  894.     return false
  895. end
  896.  
  897. function GetCollision(evadeTestPoint)
  898.     local collizionPos = {x = evadeTestPoint.x, y = myHero.y, z = evadeTestPoint.y}
  899.     return collizion:GetMinionCollision(myHero, collizionPos)
  900. end
  901.  
  902. --[[function findBestDirectionOld(referencePoint, possiblePoints) --old
  903.     closestPoint = nil
  904.     closestDistance = nil
  905.     for i, point in pairs(possiblePoints) do
  906.         if point ~= nil then
  907.             distance = point:distance(referencePoint)
  908.             if (closestDistance == nil or distance <= closestDistance) and not InsideTheWall(point) then
  909.                 closestDistance = distance
  910.                 closestPoint = point
  911.             end
  912.         end
  913.     end
  914.    
  915.     return closestPoint
  916. end]]
  917.  
  918. function findBestDirection(referencePoint, possiblePoints)
  919.     local closestPoint = nil
  920.     local closestDistance = nil
  921.  
  922.     local turrets = Turrets.GetObjects(ENEMY, 1500, myHero)
  923.     local turret = nil
  924.     if #turrets >= 1 then turret = Point(turrets[1].x, turrets[1].z) end
  925.     local enemy = nil
  926.     if #enemyes >= 1 then enemy = Point(enemyes[1].x, enemyes[1].z) end
  927.  
  928.     for i, point in pairs(possiblePoints) do
  929.         if point ~= nil then
  930.             distance = point:distance(referencePoint)
  931.             if (closestDistance == nil or distance <= closestDistance) and not InsideTheWall(point)
  932.             and (not turret or (turret and point:distance(turret) > 800)) then
  933.                 closestDistance = distance
  934.                 closestPoint = point
  935.             end
  936.         end
  937.     end    
  938.  
  939.     if not closestPoint and turret then
  940.         for i, point in pairs(possiblePoints) do
  941.             if point ~= nil then
  942.                 distance = point:distance(referencePoint)
  943.                 if (closestDistance == nil or distance <= closestDistance) and not InsideTheWall(point) then
  944.                     closestDistance = distance
  945.                     closestPoint = point
  946.                 end
  947.             end
  948.         end -- dodging under turret too
  949.     end
  950.  
  951.     return closestPoint
  952. end
  953.  
  954. function calculateLongitudinalApproachLength(skillshot, d)
  955.     v1 = skillshot.skillshot.projectileSpeed
  956.     v2 = myHero.ms
  957.     longitudinalDistance = math.max(skillshotPosition(skillshot, GetTickCount()):distance(getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, Point(myHero.x, myHero.z))) - hitboxSize / 2 - skillshot.skillshot.radius, 0)  + v1 * math.max(skillshot.startTick - GetTickCount(), 0) / 1000
  958.  
  959.     preResult = -d^2 * v1^4 + d^2 * v2^2 * v1^2 + longitudinalDistance^2 * v2^2 * v1^2
  960.     if preResult >= 0 then
  961.         result = (math.sqrt(preResult) - longitudinalDistance * v2^2) / (v1^2 - v2^2)
  962.         if result >= 0 then
  963.             return result
  964.         end
  965.     end
  966.  
  967.     return -1
  968. end
  969.  
  970. function calculateLongitudinalRetreatLength(skillshot, d)
  971.     v1 = skillshot.skillshot.projectileSpeed
  972.     v2 = myHero.ms
  973.     longitudinalDistance = math.max(skillshotPosition(skillshot, GetTickCount()):distance(getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, Point(myHero.x, myHero.z))) - hitboxSize / 2 - skillshot.skillshot.radius, 0) + v1 * math.max(skillshot.startTick - GetTickCount(), 0) / 1000
  974.  
  975.     preResult = -d^2 * v1^4 + d^2 * v2^2 * v1^2 + longitudinalDistance^2 * v2^2 * v1^2
  976.     if preResult >= 0 then
  977.         result = (math.sqrt(preResult) + longitudinalDistance * v2^2) / (v1^2 - v2^2)
  978.         if result >= 0 then
  979.             return result
  980.         end
  981.     end
  982.  
  983.     return -1
  984. end
  985.  
  986. function inDangerousArea(skillshot, coordinate)
  987.     if skillshot.skillshot.type == "line" then
  988.         return inRange(skillshot, coordinate)
  989.         and not skillshotHasPassed(skillshot, coordinate)
  990.         and Line(skillshot.startPosition, skillshot.endPosition):distance(coordinate) < (skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer)
  991.         and coordinate:distance(skillshot.startPosition + skillshot.directionVector) <= coordinate:distance(skillshot.startPosition - skillshot.directionVector)
  992.     else
  993.         return coordinate:distance(skillshot.endPosition) <= skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer
  994.     end
  995. end
  996.  
  997. function inRange(skillshot, coordinate)
  998.     return getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, coordinate):distance(skillshot.startPosition) <= skillshot.skillshot.range
  999. end
  1000.  
  1001. function OnCreateObj(object)
  1002.     if object ~= nil and object.type == "obj_GeneralParticleEmmiter" then
  1003.         --if not object.name:lower():find("odin") and not object.name:lower():find("drawfx") then print(object.name) end
  1004.         for i, skillShotChampion in pairs(champions) do
  1005.             for i, skillshot in pairs(skillShotChampion.skillshots) do
  1006.                 if skillshot.projectileName == object.name then
  1007.                     for i, detectedSkillshot in pairs(detectedSkillshots) do
  1008.                         if detectedSkillshot.skillshot.projectileName == skillshot.projectileName then
  1009.                             return
  1010.                         end
  1011.                     end
  1012.  
  1013.                     for i = 1, heroManager.iCount, 1 do
  1014.                         currentHero = heroManager:GetHero(i)
  1015.                         if currentHero.team == myHero.team and skillShotChampion.charName == currentHero.charName then
  1016.                             return
  1017.                         end
  1018.                     end
  1019.  
  1020.                     startPosition = Point(object.x, object.z)
  1021.                     if skillshot.cc == "true" or (nEnemies <= 2 and not PerfectEvadeConfig.dodgeCConly) then
  1022.                         if skillshot.type == "line" then
  1023.                             skillshotToAdd = {object = object, startPosition = startPosition, endPosition = nil, directionVector = nil,
  1024.                             startTick = GetTickCount(), endTick = GetTickCount() + skillshot.range/skillshot.projectileSpeed*1000,
  1025.                             skillshot = skillshot, evading = false}
  1026.                         else
  1027.                             endPosition = Point(object.x, object.z)
  1028.                             table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition,
  1029.                             directionVector = (endPosition - startPosition):normalized(), startTick = GetTickCount() + skillshot.spellDelay,
  1030.                             endTick = GetTickCount() + skillshot.spellDelay + skillshot.projectileSpeed, skillshot = skillshot, evading = false})
  1031.                         end
  1032.                     end
  1033.                     return
  1034.                 end
  1035.             end
  1036.         end
  1037.     end
  1038. end
  1039.  
  1040. function OnProcessSpell(object, spell)
  1041.     if lastMovement.type == 7 and myHero.team == object.team and object.name == myHero.name then
  1042.         lastMovement.type = 3
  1043.     end
  1044.     --print(spell.name)
  1045.     if not myHero.dead and object.team ~= myHero.team then
  1046.         for i, skillShotChampion in pairs(champions) do
  1047.             if skillShotChampion.charName == object.charName then
  1048.                 for i, skillshot in pairs(skillShotChampion.skillshots) do
  1049.                     if skillshot.spellName == spell.name then
  1050.                         startPosition = Point(object.x, object.z)
  1051.                         endPosition = Point(spell.endPos.x, spell.endPos.z)
  1052.                         directionVector = (endPosition - startPosition):normalized()
  1053.                         if skillshot.cc == "true" or (nEnemies <= 2 and not PerfectEvadeConfig.dodgeCConly) then
  1054.                             if skillshot.type == "line" then
  1055.                                 table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = startPosition + directionVector * skillshot.range,
  1056.                                 directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay,
  1057.                                 endTick = GetTickCount() + skillshot.spellDelay + skillshot.range/skillshot.projectileSpeed*1000, skillshot = skillshot, evading = false})
  1058.                             else
  1059.                                 table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition,
  1060.                                 directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay,
  1061.                                 endTick = GetTickCount() + skillshot.spellDelay + skillshot.projectileSpeed, skillshot = skillshot, evading = false})
  1062.                             end
  1063.                         end
  1064.                         return
  1065.                     end
  1066.                 end
  1067.             end
  1068.         end
  1069.     end
  1070. end
  1071.  
  1072. function skillshotPosition(skillshot, tickCount)
  1073.     if skillshot.skillshot.type == "line" then
  1074.         return skillshot.startPosition + skillshot.directionVector * math.max(tickCount - skillshot.startTick, 0) * skillshot.skillshot.projectileSpeed / 1000
  1075.     else
  1076.         return skillshot.endPosition
  1077.     end
  1078. end
  1079.  
  1080. function skillshotHasPassed(skillshot, coordinate)
  1081.     footOfPerpendicular = getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, coordinate)
  1082.     currentSkillshotPosition = skillshotPosition(skillshot, GetTickCount() - 2 * GetLatency())
  1083.  
  1084.     return (getSideOfLine(coordinate, footOfPerpendicular, currentSkillshotPosition) ~= getSideOfLine(coordinate, footOfPerpendicular, skillshot.startPosition)) and currentSkillshotPosition:distance(footOfPerpendicular) >= ((skillshot.skillshot.radius + hitboxSize / 2))
  1085. end
  1086.  
  1087. function getPerpendicularFootpoint(linePoint1, linePoint2, point)
  1088.     distanceFromLine = Line(linePoint1, linePoint2):distance(point)
  1089.     directionVector = (linePoint2 - linePoint1):normalized()
  1090.  
  1091.     footOfPerpendicular = point + Point(-directionVector.y, directionVector.x) * distanceFromLine
  1092.     if Line(linePoint1, linePoint2):distance(footOfPerpendicular) > distanceFromLine then
  1093.         footOfPerpendicular = point - Point(-directionVector.y, directionVector.x) * distanceFromLine
  1094.     end
  1095.  
  1096.     return footOfPerpendicular
  1097. end
  1098.  
  1099. function OnTick()
  1100.     nSkillshots = 0
  1101.     for _, detectedSkillshot in pairs(detectedSkillshots) do
  1102.         if detectedSkillshot then nSkillshots = nSkillshots + 1 end
  1103.     end
  1104.  
  1105.     if not allowCustomMovement and nSkillshots == 0 then
  1106.         stopEvade()
  1107.     end
  1108.  
  1109.     hitboxSize = GetDistance(myHero.minBBox, myHero.maxBBox)
  1110.  
  1111.     nEnemies = CountEnemyHeroInRange(1500)
  1112.     table.sort(enemyes, function(x,y) return GetDistance(x) < GetDistance(y) end)
  1113.  
  1114.     if skillshotToAdd ~= nil and skillshotToAdd.object ~= nil and skillshotToAdd.object.valid and (GetTickCount() - skillshotToAdd.startTick) >= GetLatency() then
  1115.         skillshotToAdd.directionVector = (Point(skillshotToAdd.object.x, skillshotToAdd.object.z) - skillshotToAdd.startPosition):normalized()
  1116.         skillshotToAdd.endPosition = skillshotToAdd.startPosition + skillshotToAdd.directionVector * skillshotToAdd.skillshot.range
  1117.  
  1118.         table.insert(detectedSkillshots, skillshotToAdd)
  1119.  
  1120.         skillshotToAdd = nil
  1121.     end
  1122.  
  1123.     heroPosition = Point(myHero.x, myHero.z)
  1124.     for i, detectedSkillshot in ipairs(detectedSkillshots) do
  1125.         if detectedSkillshot.endTick <= GetTickCount() then
  1126.             table.remove(detectedSkillshots, i)
  1127.             i = i-1
  1128.             if detectedSkillshot.evading then
  1129.                 continueMovement(detectedSkillshot)
  1130.             end
  1131.         else
  1132.             if evading then
  1133.                 if detectedSkillshot.evading and not inDangerousArea(detectedSkillshot, heroPosition) then
  1134.                     if detectedSkillshot.skillshot.type == "line" then
  1135.                         -- SKILLSHOT PASSED
  1136.                         if skillshotHasPassed(detectedSkillshot, heroPosition) then
  1137.                             continueMovement(detectedSkillshot)
  1138.  
  1139.                         -- DESTINATION SAFE
  1140.                         elseif not inDangerousArea(detectedSkillshot, getLastMovementDestination()) and (getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, heroPosition) == getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, getLastMovementDestination())) then
  1141.                             continueMovement(detectedSkillshot)
  1142.  
  1143.                         -- OUT OF RANGE
  1144.                         elseif not inRange(detectedSkillshot, heroPosition) and not inRange(detectedSkillshot, getLastMovementDestination()) then
  1145.                             continueMovement(detectedSkillshot)
  1146.  
  1147.                         -- APPROACH TARGET
  1148.                         else
  1149.                             if lastMovement.approachedPoint ~= getLastMovementDestination() then
  1150.                                 footpoint = getPerpendicularFootpoint(detectedSkillshot.startPosition, detectedSkillshot.endPosition, getLastMovementDestination())
  1151.                                 closestSafePoint = footpoint + Point(-detectedSkillshot.directionVector.y, detectedSkillshot.directionVector.x) * (detectedSkillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer)
  1152.                                 if (getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, heroPosition) ~= getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, closestSafePoint)) then
  1153.                                     closestSafePoint = footpoint - Point(-detectedSkillshot.directionVector.y, detectedSkillshot.directionVector.x) * (detectedSkillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer)
  1154.                                 end
  1155.  
  1156.                                 captureMovements = false
  1157.                                 allowCustomMovement = true
  1158.                                 if detectedSkillshot.skillshot.cc == "true" and (nSkillshots > 1 or GetCollision(closestPoint)) then DashTo(x, y) end
  1159.                                 myHero:MoveTo(closestSafePoint.x, closestSafePoint.y)
  1160.                                 lastMovement.moveCommand = Point(closestSafePoint.x, closestSafePoint.y)
  1161.                                 allowCustomMovement = false
  1162.                                 captureMovements = true
  1163.  
  1164.                                 lastMovement.approachedPoint = getLastMovementDestination()
  1165.                             end
  1166.                         end
  1167.                     else
  1168.                         evadeRadius = detectedSkillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer
  1169.                         directionVector = (heroPosition - detectedSkillshot.endPosition):normalized()
  1170.                         tangentDirectionVector = Point(-directionVector.y, directionVector.x)
  1171.                         movementTargetSideOfLine = getSideOfLine(heroPosition, heroPosition + tangentDirectionVector, getLastMovementDestination())
  1172.                         skillshotSideOfLine = getSideOfLine(heroPosition, heroPosition + tangentDirectionVector, detectedSkillshot.endPosition)
  1173.                        
  1174.                         -- DESTINATION SAFE
  1175.                         if movementTargetSideOfLine == 0 or movementTargetSideOfLine ~= skillshotSideOfLine then
  1176.                             continueMovement(detectedSkillshot)
  1177.                         else
  1178.                             if getLastMovementDestination():distance(detectedSkillshot.endPosition) <= evadeRadius then
  1179.                                 closestTarget = detectedSkillshot.endPosition + (getLastMovementDestination() - detectedSkillshot.endPosition):normalized() * evadeRadius
  1180.                             else
  1181.                                 closestTarget = nil
  1182.                             end
  1183.  
  1184.                             dx = detectedSkillshot.endPosition.x - heroPosition.x
  1185.                             dy = detectedSkillshot.endPosition.y - heroPosition.y
  1186.                             D_squared = dx * dx + dy * dy
  1187.                             if D_squared < evadeRadius * evadeRadius then
  1188.                                 safePoint1 = heroPosition - tangentDirectionVector * (evadeRadius / 2 + smoothing)
  1189.                                 safePoint2 = heroPosition + tangentDirectionVector * (evadeRadius / 2 + smoothing)
  1190.                             else
  1191.                                 intersectionPoints = Circle(detectedSkillshot.endPosition, evadeRadius):intersectionPoints(Circle(heroPosition, math.sqrt(D_squared - evadeRadius * evadeRadius)))
  1192.                                 if #intersectionPoints == 2 then
  1193.                                     safePoint1 = heroPosition - (heroPosition - intersectionPoints[1]):normalized() * (evadeRadius / 2 + smoothing)
  1194.                                     safePoint2 = heroPosition - (heroPosition - intersectionPoints[2]):normalized() * (evadeRadius / 2 + smoothing)
  1195.                                 else
  1196.                                     safePoint1 = heroPosition - tangentDirectionVector * (evadeRadius / 2 + smoothing)
  1197.                                     safePoint2 = heroPosition + tangentDirectionVector * (evadeRadius / 2 + smoothing)
  1198.                                 end
  1199.                             end
  1200.  
  1201.                             local theta = ((-detectedSkillshot.endPosition + safePoint2):polar() - (-detectedSkillshot.endPosition + safePoint1):polar()) % 360
  1202.                             if _isValidTarget(closestTarget) and (
  1203.                                 (
  1204.                                     theta < 180 and (
  1205.                                         getSideOfLine(detectedSkillshot.endPosition, safePoint2, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint2, heroPosition) and
  1206.                                         getSideOfLine(detectedSkillshot.endPosition, safePoint1, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint1, heroPosition)
  1207.                                     )
  1208.                                 ) or (
  1209.                                     theta > 180 and (
  1210.                                         getSideOfLine(detectedSkillshot.endPosition, safePoint2, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint2, heroPosition) or
  1211.                                         getSideOfLine(detectedSkillshot.endPosition, safePoint1, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint1, heroPosition)
  1212.                                     )
  1213.                                 )
  1214.                             ) then
  1215.                                 possibleMovementTargets = {closestTarget, safePoint1, safePoint2}
  1216.                             else
  1217.                                 possibleMovementTargets = {safePoint1, safePoint2}
  1218.                             end
  1219.  
  1220.                             closestPoint = findBestDirection(getLastMovementDestination(), possibleMovementTargets)
  1221.                             if closestPoint ~= nil then
  1222.                                 captureMovements = false
  1223.                                 allowCustomMovement = true
  1224.                                 if detectedSkillshot.skillshot.cc == "true" and (nSkillshots > 1 or GetCollision(closestPoint)) then DashTo(x, y) end
  1225.                                 myHero:MoveTo(closestPoint.x, closestPoint.y)
  1226.                                 lastMovement.moveCommand = Point(closestPoint.x, closestPoint.y)
  1227.                                 allowCustomMovement = false
  1228.                                 captureMovements = true
  1229.                             end
  1230.                         end
  1231.                     end
  1232.                 end
  1233.             elseif inDangerousArea(detectedSkillshot, heroPosition) then
  1234.                 dodgeSkillshot(detectedSkillshot)
  1235.             end
  1236.         end
  1237.     end
  1238. end
  1239.  
  1240. function DashTo(x, y)
  1241.     if isVayne and  myHero:CanUseSpell(_Q) == READY then
  1242.         CastSpell(_Q, x, y)
  1243.     end
  1244.     if isRiven and  myHero:CanUseSpell(_E) == READY then
  1245.         CastSpell(_E, x, y)
  1246.     end
  1247.     if isGraves and myHero:CanUseSpell(_E) == READY then
  1248.         CastSpell(_E, x, y)
  1249.     end
  1250.     if isEzreal and myHero:CanUseSpell(_E) == READY then
  1251.         CastSpell(_E, x, y)
  1252.     end
  1253.     if isKassadin and myHero:CanUseSpell(_R) == READY then
  1254.         CastSpell(_R, x, y)
  1255.     end
  1256.     if isCorki and myHero:CanUseSpell(_W) == READY then
  1257.         CastSpell(_W, x, y)
  1258.     end
  1259.     if isRenekton and myHero:CanUseSpell(_E) == READY then
  1260.         CastSpell(_E, x, y)
  1261.     end
  1262.     if isTristana and myHero:CanUseSpell(_W) == READY then
  1263.         CastSpell(_W, x, y)
  1264.     end                          
  1265. end
  1266. function NeedDash(skillshot, forceDash)
  1267.     local hp = myHero.health / myHero.maxHealth
  1268.     if isVayne and myHero:CanUseSpell(_Q) == READY and skillshot.skillshot.cc == "true" then
  1269.         if forceDash or hp < 0.4 then return true end
  1270.         if GetCollision(evadeTarget) or nSkillshots > 1 or _isDangerSkillshot(skillshot) then return true end
  1271.     end
  1272.     if isRiven and myHero:CanUseSpell(_E) == READY and skillshot.skillshot.cc == "true" then
  1273.         if forceDash or hp < 0.4 then return true end
  1274.         if GetCollision(evadeTarget) or nSkillshots > 1 or _isDangerSkillshot(skillshot) then return true end
  1275.     end
  1276.     if isGraves and myHero:CanUseSpell(_E) == READY and skillshot.skillshot.cc == "true" then
  1277.         if forceDash or hp < 0.4 then return true end
  1278.         if _isDangerSkillshot(skillshot) then return true end
  1279.     end
  1280.     if isEzreal and myHero:CanUseSpell(_E) == READY and skillshot.skillshot.cc == "true" then
  1281.         if forceDash or hp < 0.4 then return true end
  1282.         if _isDangerSkillshot(skillshot) then return true end
  1283.     end
  1284.     if isKassadin and myHero:CanUseSpell(_R) == READY and skillshot.skillshot.cc == "true" then
  1285.         if forceDash or hp < 0.4 then return true end
  1286.         if _isDangerSkillshot(skillshot) then return true end
  1287.     end
  1288.     if isRenekton and myHero:CanUseSpell(_E) == READY and skillshot.skillshot.cc == "true" then
  1289.         if forceDash or hp < 0.4 then return true end
  1290.         if _isDangerSkillshot(skillshot) then return true end
  1291.     end
  1292.     if isTristana and myHero:CanUseSpell(_W) == READY and skillshot.skillshot.cc == "true" then
  1293.         if _isDangerSkillshot(skillshot) then return true end
  1294.     end
  1295.     if isCorki and myHero:CanUseSpell(_W) == READY and skillshot.skillshot.cc == "true" then
  1296.         if _isDangerSkillshot(skillshot) then return true end
  1297.     end                                
  1298.     return false
  1299. end
  1300.  
  1301. function evadeTo(x, y, forceDash)
  1302.     startEvade()
  1303.     evadePoint = Point(x, y)
  1304.     allowCustomMovement = true
  1305.     captureMovements = false
  1306.     if forceDash then DashTo(x, y) end    
  1307.     myHero:MoveTo(x, y)
  1308.     lastMovement.moveCommand = Point(x, y)
  1309.     captureMovements = true
  1310.     allowCustomMovement = false
  1311.     evading = true
  1312.     evadingTick = GetTickCount()
  1313. end
  1314.  
  1315. function continueMovement(skillshot)
  1316.     if evading then
  1317.         skillshot.evading = false
  1318.         lastMovement.approachedPoint = nil
  1319.        
  1320.         stopEvade()
  1321.        
  1322.         if lastMovement.type == 2 then
  1323.             captureMovements = false
  1324.             myHero:MoveTo(getLastMovementDestination().x, getLastMovementDestination().y)
  1325.             captureMovements = true
  1326.         elseif lastMovement.type == 3 then
  1327.             target = getTarget(lastMovement.targetId)
  1328.  
  1329.             if _isValidTarget(target) then
  1330.                 captureMovements = false
  1331.                 myHero:Attack(target)
  1332.                 captureMovements = true
  1333.             else
  1334.                 captureMovements = false
  1335.                 myHero:MoveTo(myHero.x, myHero.z)
  1336.                 captureMovements = true
  1337.             end
  1338.         elseif lastMovement.type == 10 then
  1339.             myHero:HoldPosition()
  1340.         elseif lastMovement.type == 7 then
  1341.             if myHero.userdataObject ~= nil and myHero.userdataObject:CanUseSpell(lastMovement.spellId) then
  1342.                 target = getTarget(lastMovement.targetId)
  1343.                 if _isValidTarget(target) then
  1344.                     CastSpell(lastMovement.spellId, target)
  1345.                 else
  1346.                     CastSpell(lastMovement.spellId, lastMovement.destination.x, lastMovement.destination.y)
  1347.                 end
  1348.             end
  1349.             lastMovement.type = 3
  1350.         end
  1351.     end
  1352. end
  1353.  
  1354. function OnDraw()
  1355.     if PerfectEvadeConfig.drawEnabled then
  1356.         for i, detectedSkillshot in pairs(detectedSkillshots) do
  1357.             skillshotPos = skillshotPosition(detectedSkillshot, GetTickCount())
  1358.  
  1359.             if detectedSkillshot.skillshot.type == "line" then
  1360.                 directionVector = detectedSkillshot.endPosition - detectedSkillshot.startPosition
  1361.                 DrawArrow(D3DXVECTOR3(detectedSkillshot.startPosition.x, myHero.y, detectedSkillshot.startPosition.y), D3DXVECTOR3(directionVector.x, myHero.y, directionVector.y), detectedSkillshot.startPosition:distance(detectedSkillshot.endPosition) + 170, detectedSkillshot.skillshot.radius, -10000000000000000000000, RGBA(255,255,255,0))
  1362.  
  1363.                 --DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius + 10, 0x00FF00)
  1364.                 --DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0xFFFFFF)
  1365.                 --DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius - 10, 0xFFFFFF)
  1366.                 --DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius - 20, 0xFFFFFF)
  1367.                 --DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius - 30, 0xFFFFFF)
  1368.             else
  1369.                 DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0x00FF00)
  1370.             end
  1371.         end
  1372.     end
  1373. end
  1374.  
  1375. function _isValidTarget(target)
  1376.     return target ~= nil and not target.dead
  1377. end
  1378.  
  1379. function startEvade()
  1380.     allowCustomMovement = false
  1381.     if AutoCarry then
  1382.         AutoCarry.CanAttack = false
  1383.         AutoCarry.CanMove = false
  1384.     end
  1385.     _G.evade = true
  1386.     evading = true  
  1387. end
  1388.  
  1389. function stopEvade()
  1390.     --detectedSkillshots = {}
  1391.     allowCustomMovement = true
  1392.     if AutoCarry then
  1393.         AutoCarry.CanAttack = true
  1394.         AutoCarry.CanMove = true
  1395.     end
  1396.     _G.evade = false
  1397.     evading = false
  1398. end
  1399.  
  1400. function OnWndMsg(msg, key) -- move with Ctrl
  1401.     if key == 17 then
  1402.         if msg == KEY_DOWN then
  1403.             stopEvade()
  1404.         end
  1405.     end
  1406. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement