Kain2030

Good Evade - v0.9x.lua

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