Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require "MapPosition"
- --[[
- Perfect Evade 0.99.7b by Husky
- ========================================================================
- This script enables you to evade nearly all skillshots by simply moving
- your champion out of the way. While evading it will move just the required
- distance and choose the best path so you will hardly notice the script.
- It will automatically resume your last command so that it seamlessly fits
- to any playstyle. Other scripts that modify your movement will work with
- this script (like Orbwalker).
- Supported Enemy Champions (current version):
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Lux (without ultimate)
- Nidalee
- Kennen
- Amumu
- Lee Sin
- Morgana
- Ezreal
- Ahri
- Olaf
- Leona
- Karthus
- Chogath
- Blitzcrank
- Anivia
- Zyra
- Gragas
- Nautilus
- Urgot
- Changelog
- ~~~~~~~~~
- 0.98 (beta) - automatically evades all skillshots (only line skillshots atm and only a few champions - all champions will be supported in version 1.0)
- - works even when you click spam
- - continues your last order (attack/movement) after finishing the evasion
- - optimized path finding makes you take the best evasion path
- - allows you to change your direction while evading if there is enough time to reach your new destination
- - works for predicted spells that are not directly cast to your position
- 0.99 (beta) - added support for circular skillshots
- - added evasion for shots from bushes
- - added smoothing to make the evasion look more legit
- 0.99.1 (beta) - reworked to fully utilize the 2D Geometry library
- - dodging is disabled now if your champion is dead
- - added more champions
- - removed a bug with circular spells ignoring the spell delay (champ went back into the dangerous area too early)
- - removed a bug that made you dodge spells of teammates
- 0.99.2 (beta) - removed a bug in the path finding algorithm, that made you take the wrong path and go into the wrong direction when dodging linear skill shots (back to the enemy or not the shortest path)
- - removed a bug that made you go back into circular skill shots befor the spell has ended
- - after evading a circular skillshot you will instantly start to approach your destination through walking "around" the dangerous area
- - modified the script to work vor non-vip users with some limitations: doesnt continue attacks after an evasion but continues the movement; doesn't evade if another script takes control over your movement - like sida's auto carry
- - draws the path of linear skillshots and projectiles now
- - added more champions
- 0.99.3 (beta) - fixed a few problems that made the game bugsplat
- - removed a bug that made you take the wrong path when evading while auto attacking creeps or champions with a ranged champion
- - the script will now continue spell casts after an evasion
- - fixed a problem with walking back to you starting location when casting a spell while evading
- - fixed a bug that made you go back into the dangerous area when casting a spell
- - fixed a few errors in the champion database
- - fixed a bug that made you stop to attack the tower after an evasion
- - skillshots from bushes can not be disabled anymore since the bugsplats got fixed and get always dodged now
- - while channeling spells like katarina ultimate, dodging is disabled (will be enabled again if the incoming skillshot is a cc that would abort your channeling anyway [in a later version of the script])
- 0.99.4 (beta) - fixed a problem with mundos axes not getting determined correctly
- - updated the script to work with the new version of Bot of Legends
- 0.99.5 (beta) - fixed a bug that stopped dodging when recalling
- - if the script isnt able to dodge a spell it doesn't try it anymore (better team fights)
- - added a way to enable/disable doding and drawing of skillshots ingame (by using allclass menu <press shift>)
- - script uses the Packet library now, to faster address packet changes in the future
- - the script doesnt require any additional libraries anymore
- 0.99.7 (beta) - MapPosition support, vayne Q dodge, more champs
- ]]
- -- Config ----------------------------------------------------------------------
- local isVayne = false
- local evadeBuffer = 10 -- expand the dangerous area (safer evades in laggy situations)
- local moveBuffer = 25 -- additional movement distance (champions stop a few pixels before their destination)
- local smoothing = 0 -- make movements smoother by moving further between evasion phases
- local mapPosition = MapPosition()
- _G.evade = 0
- SEARCH_RADIUS = 50
- K1 = SEARCH_RADIUS*math.cos(2*math.pi / 3)
- K2 = SEARCH_RADIUS*math.sin(2*math.pi / 3)
- K3 = SEARCH_RADIUS*math.cos(4*math.pi / 3)
- K4 = SEARCH_RADIUS*math.sin(4*math.pi / 3)
- if myHero.charName == "Vayne" then
- isVayne = true
- smoothing = 70
- end
- champions = {
- ["Lux"] = {charName = "Lux", skillshots = {
- ["Light Binding"] = {name = "Light Binding", spellName = "LuxLightBinding", spellDelay = 250, projectileName = "LuxLightBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 80, type = "line", cc = "true"},
- }},
- ["Nidalee"] = {charName = "Nidalee", skillshots = {
- ["Javelin Toss"] = {name = "Javelin Toss", spellName = "JavelinToss", spellDelay = 100, projectileName = "nidalee_javelinToss_mis.troy", projectileSpeed = 1300, range = 1500, radius = 60, type = "line", cc = "false"}
- }},
- ["Kennen"] = {charName = "Kennen", skillshots = {
- ["Thundering Shuriken"] = {name = "Thundering Shuriken", spellName = "KennenShurikenHurlMissile1", spellDelay = 180, projectileName = "kennen_ts_mis.troy", projectileSpeed = 1640, range = 1050, radius = 53, type = "line", cc = "false"}
- }},
- ["Amumu"] = {charName = "Amumu", skillshots = {
- ["Bandage Toss"] = {name = "Bandage Toss", spellName = "BandageToss", spellDelay = 250, projectileName = "Bandage_beam.troy", projectileSpeed = 2000, range = 1100, radius = 80, type = "line", cc = "true"}
- }},
- ["Lee Sin"] = {charName = "LeeSin", skillshots = {
- ["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"}
- }},
- ["Morgana"] = {charName = "Morgana", skillshots = {
- ["Dark Binding"] = {name = "Dark Binding", spellName = "DarkBindingMissile", spellDelay = 250, projectileName = "DarkBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 70, type = "line", cc = "true"}
- }},
- ["Ezreal"] = {charName = "Ezreal", skillshots = {
- ["Mystic Shot"] = {name = "Mystic Shot", spellName = "EzrealMysticShotMissile", spellDelay = 250, projectileName = "Ezreal_mysticshot_mis.troy", projectileSpeed = 1975, range = 1200, radius = 80, type = "line", cc = "false"},
- ["Trueshot Barrage"] = {name = "Trueshot Barrage", spellName = "EzrealTrueshotBarrage", spellDelay = 1000, projectileName = "Ezreal_TrueShot_mis.troy", projectileSpeed = 1990, range = 20000, radius = 250, type = "line", cc = "false"},
- ["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"}
- }},
- ["Ahri"] = {charName = "Ahri", skillshots = {
- ["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"},
- ["Charm"] = {name = "Charm", spellName = "AhriSeduce", spellDelay = 250, projectileName = "Ahri_Charm_mis.troy", projectileSpeed = 1535, range = 1000, radius = 50, type = "line", cc = "true"}
- }},
- ["Leona"] = {charName = "Leona", skillshots = {
- ["Zenith Blade"] = {name = "Zenith Blade", spellName = "LeonaZenithBladeMissile", spellDelay = 250, projectileName = "Leona_ZenithBlade_mis.troy", projectileSpeed = 2000, range = 900, radius = 90, type = "line", cc = "true"}
- }},
- ["Chogath"] = {charName = "Chogath", skillshots = {
- ["Rupture"] = {name = "Rupture", spellName = "Rupture", spellDelay = 290, projectileName = "rupture_cas_01_red_team.troy", projectileSpeed = 900, range = 950, radius = 190, type = "circular", cc = "true"}
- }},
- ["Blitzcrank"] = {charName = "Blitzcrank", skillshots = {
- ["Rocket Grab"] = {name = "Rocket Grab", spellName = "RocketGrabMissile", spellDelay = 125, projectileName = "FistGrab_mis.troy", projectileSpeed = 1800, range = 1050, radius = 70, type = "line", cc = "true"}
- }},
- ["Anivia"] = {charName = "Anivia", skillshots = {
- ["Flash Frost"] = {name = "Flash Frost", spellName = "FlashFrostSpell", spellDelay = 250, projectileName = "Cryo_FlashFrost_mis.troy", projectileSpeed = 850, range = 1100, radius = 110, type = "line", cc = "true"}
- }},
- ["Zyra"] = {charName = "Zyra", skillshots = {
- ["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"},
- ["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"},
- }},
- ["Nautilus"] = {charName = "Nautilus", skillshots = {
- ["Dredge Line"] = {name = "Dredge Line", spellName = "NautilusAnchorDragMissile", spellDelay = 250, projectileName = "Nautilus_Q_mis.troy", projectileSpeed = 1965, range = 1075, radius = 60, type = "line", cc = "true"}
- }},
- --["Urgot"] = {charName = "Urgot", skillshots = {
- -- ["Plasma Grenade"] = {name = "Plasma Grenade", spellName = "UrgotPlasmaGrenade", spellDelay = 250, projectileName = "UrgotPlasmaGrenade_mis.troy", projectileSpeed = 1440, range = 850, radius = 180, type = "line", cc = "false"},
- --}},
- ["Caitlyn"] = {charName = "Caitlyn", skillshots = {
- ["Piltover Peacemaker"] = {name = "Piltover Peacemaker", spellName = "CaitlynPiltoverPeacemaker", spellDelay = 625, projectileName = "caitlyn_Q_mis.troy", projectileSpeed = 2150, range = 1300, radius = 60, type = "line", cc = "false"}
- }},
- ["Mundo"] = {charName = "DrMundo", skillshots = {
- ["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"}
- }},
- ["Brand"] = {charName = "Brand", skillshots = {
- ["Brand Missile"] = {name = "BrandBlazeMissile", spellName = "BrandBlazeMissile", spellDelay = 250, projectileName = "BrandBlaze_mis.troy", projectileSpeed = 1565, range = 1100, radius = 50, type = "line", cc = "false"},
- }},
- ["Corki"] = {charName = "Corki", skillshots = {
- ["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"},
- ["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"}
- }},
- ["Swain"] = {charName = "Swain", skillshots = {
- ["Nevermove"] = {name = "Nevermove", spellName = "SwainShadowGrasp", spellDelay = 250, projectileName = "swain_shadowGrasp_transform.troy", projectileSpeed = 1000, range = 900, radius = 180, type = "circular", cc = "false"}
- }},
- ["Ashe"] = {charName = "Ashe", skillshots = {
- ["Enchanted Arrow"] = {name = "Enchanted Arrow", spellName = "EnchantedCrystalArrow", spellDelay = 125, projectileName = "EnchantedCrystalArrow_mis.troy", projectileSpeed = 1600, range = 25000, radius = 130, type="line", cc = "true"}
- }},
- ["KogMaw"] = {charName = "KogMaw", skillshots = {
- ["Living Artillery"] = {name = "Living Artillery", spellName = "KogMawLivingArtillery", spellDelay = 250, projectileName = "KogMawLivingArtillery_cas_green.troy", projectileSpeed = 1050, range = 2200, radius = 180, type="circular", cc = "false"}
- }},
- ["KhaZix"] = {charName = "KhaZix", skillshots = {
- ["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"},
- }},
- ["Zed"] = {charName = "Zed", skillshots = {
- ["ZedShuriken"] = {name = "ZedShuriken", spellName = "ZedShuriken", spellDelay = 0, projectileName = "Zed_Q_Mis.troy", projectileSpeed = 1700, range = 925, radius = 50, type="line", cc = "false"}
- }},
- ["Leblanc"] = {charName = "Leblanc", skillshots = {
- ["Ethereal Chains"] = {name = "Ethereal Chains", spellName = "LeblancSoulShackle", spellDelay = 250, projectileName = "leBlanc_shackle_mis.troy", projectileSpeed = 1585, range = 960, radius = 50, type = "line", cc = "true"},
- ["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"},
- }},
- ["Elise"] = {charName = "Elise", skillshots = {
- ["Cocoon"] = {name = "Cocoon", spellName = "EliseHumanE", spellDelay = 250, projectileName = "Elise_human_E_mis.troy", projectileSpeed = 1450, range = 1100, radius = 70, type="line", cc = "true"}
- }},
- ["Lulu"] = {charName = "Lulu", skillshots = {
- ["luluQ1"] = {name = "luluQ1", spellName = "LuluQMissile", spellDelay = 100, projectileName = "Lulu_Q_Mis.troy", projectileSpeed = 1450, range = 1000, radius = 50, type="line", cc = "false"},
- ["luluQ2"] = {name = "luluQ2", spellName = "LuluQ", spellDelay = 250, projectileName = "Lulu_Q_Mis.troy", projectileSpeed = 1375, range = 1000, radius = 50, type="line", cc = "false"}
- }},
- ["Thresh"] = {charName = "Thresh", skillshots = {
- -- ["ThreshQ"] = {name = "ThreshQ", spellName = "ThreshQMissile", spellDelay = 500, projectileName = "Thresh_Q_whip_beam.troy", projectileSpeed = 1900, range = 1100, radius = 70, type="line"},
- -- ["ThreshQ"] = {name = "ThreshQ", spellName = "ThreshQMissile2", spellDelay = 500, projectileName = "Thresh_Q_whip_beam.troy", projectileSpeed = 1900, range = 1100, radius = 70, type="line"},
- -- ["ThreshQ"] = {name = "ThreshQ", spellName = "ThreshQInternal", spellDelay = 500, projectileName = "Thresh_Q_whip_beam.troy", projectileSpeed = 1900, range = 1100, radius = 70, type="line"},
- ["ThreshQ"] = {name = "ThreshQ", spellName = "ThreshQ", spellDelay = 500, projectileName = "Thresh_Q_whip_beam.troy", projectileSpeed = 1900, range = 1100, radius = 70, type="line", cc = "true"}
- }},
- ["Shen"] = {charName = "Shen", skillshots = {
- ["ShadowDash"] = {name = "ShadowDash", spellName = "ShenShadowDash", spellDelay = 125, projectileName = "shen_shadowDash_mis.troy", projectileSpeed = 2000, range = 575, radius = 50, type="line", cc = "true"}
- }},
- ["Quinn"] = {charName = "Quinn", skillshots = {
- ["QuinnQ"] = {name = "QuinnQ", spellName = "QuinnQ", spellDelay = 100, projectileName = "Quinn_Q_missile.troy", projectileSpeed = 1550, range = 1050, radius = 80, type="line", cc = "true"}
- }},
- ["Jayce"] = {charName = "Jayce", skillshots = {
- ["JayceShockBlastCharged"] = {name = "JayceShockBlastCharged", spellName = "JayceShockBlast", spellDelay = 100, projectileName = "JayceOrbLightningCharged.troy", projectileSpeed = 2350, range = 2000, radius = 70, type="line", cc = "false"},
- }},
- ["Nami"] = {charName = "Nami", skillshots = {
- ["NamiQ"] = {name = "NamiQ", spellName = "NamiQ", spellDelay = 700, projectileName = "Nami_Q_mis.troy", projectileSpeed = math.huge, range = 875, radius = 225, type="circular", cc = "true"},
- }},
- }
- -- Globals ---------------------------------------------------------------------
- evading = false
- allowCustomMovement = true
- captureMovements = true
- lastMovement = {}
- possibleTargets = {}
- detectedSkillshots = {}
- moveKeyPressed = false
- packageApiAvailable = false
- nCount = 0
- -- Code ------------------------------------------------------------------------
- function getTarget(targetId)
- if targetId ~= 0 and targetId ~= nil then
- for i = 1, heroManager.iCount, 1 do
- object = heroManager:GetHero(i)
- if object ~= nil and object.valid and object.networkID == lastMovement.targetId then
- return object
- end
- end
- for i,object in ipairs(possibleTargets) do
- if object == nil or not object.valid or object.dead then
- table.remove(possibleTargets, i)
- i = i - 1
- elseif object.networkID == lastMovement.targetId then
- return object
- end
- end
- end
- return nil
- end
- function getLastMovementDestination()
- if lastMovement.type == 3 then
- heroPosition = Point(myHero.x, myHero.z)
- target = getTarget(lastMovement.targetId)
- if target ~= nil then
- targetPosition = Point(target.x, target.z)
- local attackRange = (myHero.range + GetDistance(myHero.minBBox, myHero.maxBBox) / 2 + GetDistance(target.minBBox, target.maxBBox) / 2)
- if attackRange <= heroPosition:distance(targetPosition) then
- return targetPosition + (heroPosition - targetPosition):normalized() * attackRange
- else
- return heroPosition
- end
- else
- return heroPosition
- end
- elseif lastMovement.type == 7 then
- heroPosition = Point(myHero.x, myHero.z)
- target = getTarget(lastMovement.targetId)
- if target ~= nil then
- targetPosition = Point(target.x, target.z)
- local castRange = myHero:GetSpellData(lastMovement.spellId).range
- if castRange <= heroPosition:distance(targetPosition) then
- return targetPosition + (heroPosition - targetPosition):normalized() * castRange
- else
- return heroPosition
- end
- else
- local castRange = myHero:GetSpellData(lastMovement.spellId).range
- if castRange <= heroPosition:distance(lastMovement.destination) then
- return lastMovement.destination + (heroPosition - lastMovement.destination):normalized() * castRange
- else
- return heroPosition
- end
- end
- else
- return lastMovement.destination
- end
- end
- function OnLoad()
- for i = 1, objManager.maxObjects, 1 do
- local object = objManager:getObject(i)
- if object ~= nil and (object.type == "obj_AI_Minion" or object.type == "obj_AI_Turret") and object.team ~= myHero.team then
- table.insert(possibleTargets, object)
- end
- end
- hitboxSize = GetDistance(myHero.minBBox, myHero.maxBBox)
- lastMovement = {
- destination = Point(myHero.x, myHero.z),
- moveCommand = Point(myHero.x, myHero.z),
- type = 2,
- targetId = nil,
- spellId = nil,
- approachedPoint = nil
- }
- PerfectEvadeConfig = scriptConfig("Perfect Evade", "perfectEvade")
- PerfectEvadeConfig:addParam("dodgeEnabled", "Dodge Skillshots", SCRIPT_PARAM_ONOFF, true)
- PerfectEvadeConfig:addParam("drawEnabled", "Draw Skillshots", SCRIPT_PARAM_ONOFF, true)
- PerfectEvadeConfig:addParam("dodgeCC", "Dodge CC only", SCRIPT_PARAM_ONKEYDOWN, false, 32)
- PerfectEvadeConfig:permaShow("dodgeEnabled")
- PerfectEvadeConfig.dodgeEnabled = true
- PrintChat(" >> Good Evade 0.99.7 loaded")
- end
- function OnSendPacket(p)
- packageApiAvailable = true
- local packet = Packet(p)
- if packet:get('name') == 'S_MOVE' then
- if packet:get('sourceNetworkId') == myHero.networkID then
- if captureMovements then
- lastMovement.destination = Point(packet:get('x'), packet:get('y'))
- lastMovement.type = packet:get('type')
- lastMovement.targetId = packet:get('targetNetworkId')
- if evading then
- for i, detectedSkillshot in ipairs(detectedSkillshots) do
- if detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point(myHero.x, myHero.z)) then
- dodgeSkillshot(detectedSkillshot)
- break
- end
- end
- end
- end
- if not allowCustomMovement then
- packet:block()
- end
- end
- elseif packet:get('name') == 'S_CAST' then
- if captureMovements then
- lastMovement.spellId = packet:get('spellId')
- lastMovement.type = 7
- lastMovement.targetId = packet:get('targetNetworkId')
- lastMovement.destination = Point(packet:get('toX'), packet:get('toY'))
- if evading then
- for i, detectedSkillshot in ipairs(detectedSkillshots) do
- if detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point(myHero.x, myHero.z)) then
- dodgeSkillshot(detectedSkillshot)
- break
- end
- end
- end
- end
- if not allowCustomMovement then
- packet:block()
- end
- end
- end
- function OnWndMsg(msg,key)
- if not packageApiAvailable then
- if (msg == WM_RBUTTONDOWN) or (msg == WM_RBUTTONUP) or (msg == WM_MOUSEMOVE and moveKeyPressed) then
- if captureMovements then
- lastMovement.destination = Point(mousePos.x, mousePos.z)
- lastMovement.type = 2
- lastMovement.targetId = nil
- if evading then
- for i, detectedSkillshot in ipairs(detectedSkillshots) do
- if detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point(myHero.x, myHero.z)) then
- dodgeSkillshot(detectedSkillshot)
- break
- end
- end
- end
- end
- if not allowCustomMovement then
- myHero:MoveTo(lastMovement.moveCommand.x, lastMovement.moveCommand.y)
- else
- lastMovement.moveCommand = Point(mousePos.x, mousePos.z)
- end
- end
- if msg == WM_RBUTTONDOWN then
- moveKeyPressed = true
- elseif msg == WM_RBUTTONUP then
- moveKeyPressed = false
- end
- end
- end
- function getSideOfLine(linePoint1, linePoint2, point)
- result = ((linePoint2.x - linePoint1.x) * (point.y - linePoint1.y) - (linePoint2.y - linePoint1.y) * (point.x - linePoint1.x))
- if result < 0 then
- return -1
- elseif result > 0 then
- return 1
- else
- return 0
- end
- end
- function dodgeSkillshot(skillshot)
- --lag temp fix
- if GetDistance(skillshot.startPosition) < 200 then return end
- if PerfectEvadeConfig.dodgeEnabled and not myHero.dead and (myHero.casting == 0 or lastMovement.spellId == RECALL) then
- -- if PerfectEvadeConfig.dodgeCC and skillshot.skillshot.cc == "true" then -- space pressed
- -- if skillshot.skillshot.type == "line" then
- -- dodgeLineShot(skillshot)
- -- else
- -- dodgeCircularShot(skillshot)
- -- end
- if not PerfectEvadeConfig.dodgeCC or (isVayne and myHero:CanUseSpell(_Q) == READY) then -- def mode, space not pressed
- if skillshot.skillshot.type == "line" then
- dodgeLineShot(skillshot)
- else
- dodgeCircularShot(skillshot)
- end
- end
- end
- end
- function dodgeCircularShot(skillshot)
- skillshot.evading = true
- heroPosition = Point(myHero.x, myHero.z)
- moveableDistance = myHero.ms * math.max(skillshot.endTick - GetTickCount() - GetLatency(), 0) / 1000
- evadeRadius = skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer
- safeTarget = skillshot.endPosition + (heroPosition - skillshot.endPosition):normalized() * evadeRadius
- if getLastMovementDestination():distance(skillshot.endPosition) <= evadeRadius then
- closestTarget = skillshot.endPosition + (getLastMovementDestination() - skillshot.endPosition):normalized() * evadeRadius
- else
- closestTarget = nil
- end
- lineDistance = Line(heroPosition, getLastMovementDestination()):distance(skillshot.endPosition)
- directionTarget = heroPosition + (getLastMovementDestination() - heroPosition):normalized() * (math.sqrt(heroPosition:distance(skillshot.endPosition)^2 - lineDistance^2) + math.sqrt(evadeRadius^2 - lineDistance^2))
- if directionTarget:distance(skillshot.endPosition) >= evadeRadius + 1 then
- directionTarget = heroPosition + (getLastMovementDestination() - heroPosition):normalized() * (math.sqrt(evadeRadius^2 - lineDistance^2) - math.sqrt(heroPosition:distance(skillshot.endPosition)^2 - lineDistance^2))
- end
- possibleMovementTargets = {}
- intersectionPoints = Circle(skillshot.endPosition, evadeRadius):intersectionPoints(Circle(heroPosition, moveableDistance))
- if #intersectionPoints == 2 then
- leftTarget = intersectionPoints[1]
- rightTarget = intersectionPoints[2]
- local theta = ((-skillshot.endPosition + leftTarget):polar() - (-skillshot.endPosition + rightTarget):polar()) % 360
- 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
- table.insert(possibleMovementTargets, directionTarget)
- end
- if closestTarget ~= nil 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
- table.insert(possibleMovementTargets, closestTarget)
- end
- table.insert(possibleMovementTargets, safeTarget)
- table.insert(possibleMovementTargets, leftTarget)
- table.insert(possibleMovementTargets, rightTarget)
- else
- if skillshot.skillshot.radius <= moveableDistance then
- table.insert(possibleMovementTargets, closestTarget)
- table.insert(possibleMovementTargets, directionTarget)
- table.insert(possibleMovementTargets, safeTarget)
- end
- end
- closestPoint = findBestDirectionOld(getLastMovementDestination(), possibleMovementTargets)
- if closestPoint ~= nil then
- closestPoint = closestPoint + (closestPoint - heroPosition):normalized() * smoothing
- evadeTo(closestPoint.x, closestPoint.y)
- else
- if not evading then
- -- CAN NOT EVADE - STILL TRY IT
- PrintChat("Evade move 666")
- if isVayne and myHero:CanUseSpell(_Q) == READY then
- safeTarget = safeTarget + (safeTarget - heroPosition):normalized() * smoothing
- evadeTo(safeTarget.x, safeTarget.y)
- end
- end
- end
- end
- function InsideTheWall(evadeTestPoint)
- nCount = nCount + 1
- p0 = Point(myHero.x, myHero.z)
- p1 = Point(evadeTestPoint.x + SEARCH_RADIUS, evadeTestPoint.y)
- p2 = Point(evadeTestPoint.x + K1, evadeTestPoint.y + K2)
- p3 = Point(evadeTestPoint.x + K3, evadeTestPoint.y + K4)
- InsideTheWall1 = mapPosition:intersectsWall( p1 )
- InsideTheWall2 = mapPosition:intersectsWall( p2 )
- InsideTheWall3 = mapPosition:intersectsWall( p3 )
- if not InsideTheWall1 and not InsideTheWall2 and not InsideTheWall3 then
- return false
- else
- return true
- end
- end
- function dodgeLineShot(skillshot)
- skillshot.evading = true
- heroPosition = Point(myHero.x, myHero.z)
- skillshotLine = Line(skillshot.startPosition, skillshot.endPosition)
- distanceFromSkillshotPath = skillshotLine:distance(heroPosition)
- evadeDistance = skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer
- normalVector = Point(skillshot.directionVector.y, -skillshot.directionVector.x):normalized()
- nessecaryMoveWidth = evadeDistance - distanceFromSkillshotPath
- evadeTo1 = heroPosition + normalVector * nessecaryMoveWidth
- evadeTo2 = heroPosition - normalVector * nessecaryMoveWidth
- if skillshotLine:distance(evadeTo1) >= skillshotLine:distance(evadeTo2) then
- longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, nessecaryMoveWidth)
- if longitudinalApproachLength >= 0 then
- evadeToTarget1 = evadeTo1 - skillshot.directionVector * longitudinalApproachLength
- end
- longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, evadeDistance + distanceFromSkillshotPath)
- if longitudinalApproachLength >= 0 then
- evadeToTarget2 = heroPosition - normalVector * (evadeDistance + distanceFromSkillshotPath) - skillshot.directionVector * longitudinalApproachLength
- end
- longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, nessecaryMoveWidth)
- if longitudinalRetreatLength >= 0 then
- evadeToTarget3 = evadeTo1 + skillshot.directionVector * longitudinalRetreatLength
- end
- longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, evadeDistance + distanceFromSkillshotPath)
- if longitudinalRetreatLength >= 0 then
- evadeToTarget4 = heroPosition - normalVector * (evadeDistance + distanceFromSkillshotPath) + skillshot.directionVector * longitudinalRetreatLength
- end
- safeTarget = evadeTo1
- closestPoint = getLastMovementDestination() + normalVector * (evadeDistance - skillshotLine:distance(getLastMovementDestination()))
- closestPoint2 = getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) + normalVector * evadeDistance
- else
- longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, nessecaryMoveWidth)
- if longitudinalApproachLength >= 0 then
- evadeToTarget1 = evadeTo2 - skillshot.directionVector * longitudinalApproachLength
- end
- longitudinalApproachLength = calculateLongitudinalApproachLength(skillshot, evadeDistance + distanceFromSkillshotPath)
- if longitudinalApproachLength >= 0 then
- evadeToTarget2 = heroPosition + normalVector * (evadeDistance + distanceFromSkillshotPath) - skillshot.directionVector * longitudinalApproachLength
- end
- longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, nessecaryMoveWidth)
- if longitudinalRetreatLength >= 0 then
- evadeToTarget3 = evadeTo2 + skillshot.directionVector * longitudinalRetreatLength
- end
- longitudinalRetreatLength = calculateLongitudinalRetreatLength(skillshot, evadeDistance + distanceFromSkillshotPath)
- if longitudinalRetreatLength >= 0 then
- evadeToTarget4 = heroPosition + normalVector * (evadeDistance + distanceFromSkillshotPath) + skillshot.directionVector * longitudinalRetreatLength
- end
- safeTarget = evadeTo2
- closestPoint = getLastMovementDestination() - normalVector * (evadeDistance - skillshotLine:distance(getLastMovementDestination()))
- closestPoint2 = getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) - normalVector * evadeDistance
- end
- if skillshotLine:distance(getLastMovementDestination()) <= evadeDistance then
- directionTarget = findBestDirection(getLastMovementDestination(), {closestPoint, closestPoint2, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) - normalVector * evadeDistance, getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) + normalVector * evadeDistance})
- else
- if getSideOfLine(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) == getSideOfLine(skillshot.startPosition, skillshot.endPosition, heroPosition) then
- if skillshotLine:distance(heroPosition) <= skillshotLine:distance(getLastMovementDestination()) then
- directionTarget = heroPosition + (getLastMovementDestination()-heroPosition):normalized() * ((evadeDistance - distanceFromSkillshotPath) * heroPosition:distance(getLastMovementDestination())) / (skillshotLine:distance(getLastMovementDestination()) - distanceFromSkillshotPath)
- else
- directionTarget = heroPosition + (getLastMovementDestination()-heroPosition):normalized() * ((evadeDistance + distanceFromSkillshotPath) * heroPosition:distance(getLastMovementDestination())) / (distanceFromSkillshotPath - skillshotLine:distance(getLastMovementDestination()))
- end
- else
- directionTarget = heroPosition + (getLastMovementDestination() - heroPosition):normalized() * (evadeDistance + distanceFromSkillshotPath) * heroPosition:distance(getLastMovementDestination()) / (skillshotLine:distance(getLastMovementDestination()) + distanceFromSkillshotPath)
- end
- end
- evadeTarget = nil
- if directionTarget and ((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
- evadeTarget = directionTarget
- else
- possibleMovementTargets = {}
- 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
- table.insert(possibleMovementTargets, closestPoint2)
- end
- if evadeToTarget1 ~= nil then
- table.insert(possibleMovementTargets, evadeToTarget1)
- end
- if evadeToTarget2 ~= nil then
- table.insert(possibleMovementTargets, evadeToTarget2)
- end
- if evadeToTarget3 ~= nil then
- table.insert(possibleMovementTargets, evadeToTarget3)
- end
- if evadeToTarget4 ~= nil then
- table.insert(possibleMovementTargets, evadeToTarget4)
- end
- evadeTarget = findBestDirection(getLastMovementDestination(), possibleMovementTargets)
- end
- -- try to evade until spellshields are implemented -- TEMPORARY OVERRIDE !!!
- if evadeTarget == nil then
- --evadeTarget = safeTarget
- end
- if evadeTarget ~= nil then
- if getSideOfLine(skillshot.startPosition, skillshot.endPosition, evadeTarget) == getSideOfLine(skillshot.startPosition, skillshot.endPosition, getLastMovementDestination()) and skillshotLine:distance(getLastMovementDestination()) > evadeDistance then
- pathDirectionVector = (evadeTarget - heroPosition)
- if getSideOfLine(skillshot.startPosition, skillshot.endPosition, heroPosition) == getSideOfLine(skillshot.startPosition, skillshot.endPosition, evadeTarget) then
- evadeTarget = evadeTarget + pathDirectionVector:normalized() * (pathDirectionVector:len() + smoothing / (evadeDistance - distanceFromSkillshotPath) * pathDirectionVector:len())
- else
- evadeTarget = evadeTarget + pathDirectionVector:normalized() * (pathDirectionVector:len() + smoothing / (evadeDistance + distanceFromSkillshotPath) * pathDirectionVector:len())
- end
- end
- evadeTo(evadeTarget.x, evadeTarget.y)
- else
- -- USE SPELLSHIELDS AND ABILITES TO EVADE
- end
- end
- function findBestDirectionOld(referencePoint, possiblePoints)
- closestPoint = nil
- closestDistance = nil
- for i, point in ipairs(possiblePoints) do
- if point ~= nil then
- distance = point:distance(referencePoint)
- if (closestDistance == nil or distance <= closestDistance) then
- closestDistance = distance
- closestPoint = point
- end
- end
- end
- return closestPoint
- end
- function findBestDirection(referencePoint, possiblePoints)
- closestPoint = nil
- closestDistance = nil
- for i, point in ipairs(possiblePoints) do
- if point ~= nil then
- distance = point:distance(referencePoint)
- if (closestDistance == nil or distance <= closestDistance) and not InsideTheWall(point) then
- closestDistance = distance
- closestPoint = point
- end
- end
- end
- return closestPoint
- end
- function calculateLongitudinalApproachLength(skillshot, d)
- v1 = skillshot.skillshot.projectileSpeed
- v2 = myHero.ms
- 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
- preResult = -d^2 * v1^4 + d^2 * v2^2 * v1^2 + longitudinalDistance^2 * v2^2 * v1^2
- if preResult >= 0 then
- result = (math.sqrt(preResult) - longitudinalDistance * v2^2) / (v1^2 - v2^2)
- if result >= 0 then
- return result
- end
- end
- return -1
- end
- function calculateLongitudinalRetreatLength(skillshot, d)
- v1 = skillshot.skillshot.projectileSpeed
- v2 = myHero.ms
- 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
- preResult = -d^2 * v1^4 + d^2 * v2^2 * v1^2 + longitudinalDistance^2 * v2^2 * v1^2
- if preResult >= 0 then
- result = (math.sqrt(preResult) + longitudinalDistance * v2^2) / (v1^2 - v2^2)
- if result >= 0 then
- return result
- end
- end
- return -1
- end
- function inDangerousArea(skillshot, coordinate)
- if skillshot.skillshot.type == "line" then
- return inRange(skillshot, coordinate) and not skillshotHasPassed(skillshot, coordinate) and Line(skillshot.startPosition, skillshot.endPosition):distance(coordinate) < (skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer) and coordinate:distance(skillshot.startPosition + skillshot.directionVector) <= coordinate:distance(skillshot.startPosition - skillshot.directionVector)
- else
- return coordinate:distance(skillshot.endPosition) <= skillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer
- end
- end
- function inRange(skillshot, coordinate)
- return getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, coordinate):distance(skillshot.startPosition) <= skillshot.skillshot.range
- end
- function OnCreateObj(object)
- if object ~= nil and (object.type == "obj_AI_Minion" or object.type == "obj_AI_Turret") and object.team ~= myHero.team then
- table.insert(possibleTargets, object)
- elseif object.team ~= myHero.team then
- for i, skillShotChampion in pairs(champions) do
- for i, skillshot in pairs(skillShotChampion.skillshots) do
- if skillshot.projectileName == object.name then
- for i, detectedSkillshot in ipairs(detectedSkillshots) do
- if detectedSkillshot.skillshot.projectileName == skillshot.projectileName then
- return
- end
- end
- for i = 1, heroManager.iCount, 1 do
- currentHero = heroManager:GetHero(i)
- if currentHero.team == myHero.team and skillShotChampion.charName == currentHero.charName then
- return
- end
- end
- startPosition = Point(object.x, object.z)
- if skillshot.type == "line" then
- skillshotToAdd = {object = object, startPosition = startPosition, endPosition = nil, directionVector = nil, startTick = GetTickCount(), endTick = GetTickCount() + skillshot.range/skillshot.projectileSpeed*1000, skillshot = skillshot, evading = false}
- else
- endPosition = Point(object.x, object.z)
- table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition, directionVector = (endPosition - startPosition):normalized(), startTick = GetTickCount() + skillshot.spellDelay, endTick = GetTickCount() + skillshot.spellDelay + skillshot.projectileSpeed, skillshot = skillshot, evading = false})
- end
- return
- end
- end
- end
- end
- end
- function OnProcessSpell(object, spell)
- if lastMovement.type == 7 and myHero.team == object.team and object.name == myHero.name then
- lastMovement.type = 3
- end
- if not myHero.dead and object.team ~= myHero.team then
- for i, skillShotChampion in pairs(champions) do
- if skillShotChampion.charName == object.charName then
- for i, skillshot in pairs(skillShotChampion.skillshots) do
- if skillshot.spellName == spell.name then
- startPosition = Point(object.x, object.z)
- endPosition = Point(spell.endPos.x, spell.endPos.z)
- directionVector = (endPosition - startPosition):normalized()
- if skillshot.type == "line" then
- table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = startPosition + directionVector * skillshot.range, directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay, endTick = GetTickCount() + skillshot.spellDelay + skillshot.range/skillshot.projectileSpeed*1000, skillshot = skillshot, evading = false})
- else
- table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition, directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay, endTick = GetTickCount() + skillshot.spellDelay + skillshot.projectileSpeed, skillshot = skillshot, evading = false})
- end
- return
- end
- end
- end
- end
- end
- end
- function skillshotPosition(skillshot, tickCount)
- if skillshot.skillshot.type == "line" then
- return skillshot.startPosition + skillshot.directionVector * math.max(tickCount - skillshot.startTick, 0) * skillshot.skillshot.projectileSpeed / 1000
- else
- return skillshot.endPosition
- end
- end
- function skillshotHasPassed(skillshot, coordinate)
- footOfPerpendicular = getPerpendicularFootpoint(skillshot.startPosition, skillshot.endPosition, coordinate)
- currentSkillshotPosition = skillshotPosition(skillshot, GetTickCount() - 2 * GetLatency())
- return (getSideOfLine(coordinate, footOfPerpendicular, currentSkillshotPosition) ~= getSideOfLine(coordinate, footOfPerpendicular, skillshot.startPosition)) and currentSkillshotPosition:distance(footOfPerpendicular) >= ((skillshot.skillshot.radius + hitboxSize / 2))
- end
- function getPerpendicularFootpoint(linePoint1, linePoint2, point)
- distanceFromLine = Line(linePoint1, linePoint2):distance(point)
- directionVector = (linePoint2 - linePoint1):normalized()
- footOfPerpendicular = point + Point(-directionVector.y, directionVector.x) * distanceFromLine
- if Line(linePoint1, linePoint2):distance(footOfPerpendicular) > distanceFromLine then
- footOfPerpendicular = point - Point(-directionVector.y, directionVector.x) * distanceFromLine
- end
- return footOfPerpendicular
- end
- function OnTick()
- if skillshotToAdd ~= nil and skillshotToAdd.object ~= nil and skillshotToAdd.object.valid and (GetTickCount() - skillshotToAdd.startTick) >= GetLatency() then
- skillshotToAdd.directionVector = (Point(skillshotToAdd.object.x, skillshotToAdd.object.z) - skillshotToAdd.startPosition):normalized()
- skillshotToAdd.endPosition = skillshotToAdd.startPosition + skillshotToAdd.directionVector * skillshotToAdd.skillshot.range
- table.insert(detectedSkillshots, skillshotToAdd)
- skillshotToAdd = nil
- end
- heroPosition = Point(myHero.x, myHero.z)
- for i, detectedSkillshot in ipairs(detectedSkillshots) do
- if detectedSkillshot.endTick <= GetTickCount() then
- table.remove(detectedSkillshots, i)
- i = i-1
- if detectedSkillshot.evading then
- continueMovement(detectedSkillshot)
- end
- else
- if evading then
- if detectedSkillshot.evading and not inDangerousArea(detectedSkillshot, heroPosition) then
- if detectedSkillshot.skillshot.type == "line" then
- -- SKILLSHOT PASSED
- if skillshotHasPassed(detectedSkillshot, heroPosition) then
- continueMovement(detectedSkillshot)
- -- DESTINATION SAFE
- elseif not inDangerousArea(detectedSkillshot, getLastMovementDestination()) and (getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, heroPosition) == getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, getLastMovementDestination())) then
- continueMovement(detectedSkillshot)
- -- OUT OF RANGE
- elseif not inRange(detectedSkillshot, heroPosition) and not inRange(detectedSkillshot, getLastMovementDestination()) then
- continueMovement(detectedSkillshot)
- -- APPROACH TARGET
- else
- if lastMovement.approachedPoint ~= getLastMovementDestination() then
- footpoint = getPerpendicularFootpoint(detectedSkillshot.startPosition, detectedSkillshot.endPosition, getLastMovementDestination())
- closestSafePoint = footpoint + Point(-detectedSkillshot.directionVector.y, detectedSkillshot.directionVector.x) * (detectedSkillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer)
- if (getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, heroPosition) ~= getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, closestSafePoint)) then
- closestSafePoint = footpoint - Point(-detectedSkillshot.directionVector.y, detectedSkillshot.directionVector.x) * (detectedSkillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer)
- end
- captureMovements = false
- allowCustomMovement = true
- myHero:MoveTo(closestSafePoint.x, closestSafePoint.y)
- lastMovement.moveCommand = Point(closestSafePoint.x, closestSafePoint.y)
- allowCustomMovement = false
- captureMovements = true
- lastMovement.approachedPoint = getLastMovementDestination()
- end
- end
- else
- evadeRadius = detectedSkillshot.skillshot.radius + hitboxSize / 2 + evadeBuffer + moveBuffer
- directionVector = (heroPosition - detectedSkillshot.endPosition):normalized()
- tangentDirectionVector = Point(-directionVector.y, directionVector.x)
- movementTargetSideOfLine = getSideOfLine(heroPosition, heroPosition + tangentDirectionVector, getLastMovementDestination())
- skillshotSideOfLine = getSideOfLine(heroPosition, heroPosition + tangentDirectionVector, detectedSkillshot.endPosition)
- -- DESTINATION SAFE
- if movementTargetSideOfLine == 0 or movementTargetSideOfLine ~= skillshotSideOfLine then
- continueMovement(detectedSkillshot)
- else
- if getLastMovementDestination():distance(detectedSkillshot.endPosition) <= evadeRadius then
- closestTarget = detectedSkillshot.endPosition + (getLastMovementDestination() - detectedSkillshot.endPosition):normalized() * evadeRadius
- else
- closestTarget = nil
- end
- dx = detectedSkillshot.endPosition.x - heroPosition.x
- dy = detectedSkillshot.endPosition.y - heroPosition.y
- D_squared = dx * dx + dy * dy
- if D_squared < evadeRadius * evadeRadius then
- safePoint1 = heroPosition - tangentDirectionVector * (evadeRadius / 2 + smoothing)
- safePoint2 = heroPosition + tangentDirectionVector * (evadeRadius / 2 + smoothing)
- else
- intersectionPoints = Circle(detectedSkillshot.endPosition, evadeRadius):intersectionPoints(Circle(heroPosition, math.sqrt(D_squared - evadeRadius * evadeRadius)))
- if #intersectionPoints == 2 then
- safePoint1 = heroPosition - (heroPosition - intersectionPoints[1]):normalized() * (evadeRadius / 2 + smoothing)
- safePoint2 = heroPosition - (heroPosition - intersectionPoints[2]):normalized() * (evadeRadius / 2 + smoothing)
- else
- safePoint1 = heroPosition - tangentDirectionVector * (evadeRadius / 2 + smoothing)
- safePoint2 = heroPosition + tangentDirectionVector * (evadeRadius / 2 + smoothing)
- end
- end
- local theta = ((-detectedSkillshot.endPosition + safePoint2):polar() - (-detectedSkillshot.endPosition + safePoint1):polar()) % 360
- if closestTarget ~= nil and (
- (
- theta < 180 and (
- getSideOfLine(detectedSkillshot.endPosition, safePoint2, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint2, heroPosition) and
- getSideOfLine(detectedSkillshot.endPosition, safePoint1, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint1, heroPosition)
- )
- ) or (
- theta > 180 and (
- getSideOfLine(detectedSkillshot.endPosition, safePoint2, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint2, heroPosition) or
- getSideOfLine(detectedSkillshot.endPosition, safePoint1, closestTarget) == getSideOfLine(detectedSkillshot.endPosition, safePoint1, heroPosition)
- )
- )
- ) then
- possibleMovementTargets = {closestTarget, safePoint1, safePoint2}
- else
- possibleMovementTargets = {safePoint1, safePoint2}
- end
- closestPoint = findBestDirection(getLastMovementDestination(), possibleMovementTargets)
- if closestPoint ~= nil then
- captureMovements = false
- allowCustomMovement = true
- myHero:MoveTo(closestPoint.x, closestPoint.y)
- lastMovement.moveCommand = Point(closestPoint.x, closestPoint.y)
- allowCustomMovement = false
- captureMovements = true
- end
- end
- end
- end
- elseif inDangerousArea(detectedSkillshot, heroPosition) then
- dodgeSkillshot(detectedSkillshot)
- end
- end
- end
- end
- function evadeTo(x, y)
- evadePoint = Point(x, y)
- if isVayne and myHero:CanUseSpell(_Q) == READY then
- CastSpell(_Q, x, y)
- end
- allowCustomMovement = true
- captureMovements = false
- myHero:MoveTo(0, 0)
- myHero:MoveTo(x, y)
- lastMovement.moveCommand = Point(x, y)
- captureMovements = true
- allowCustomMovement = false
- evading = true
- _G.evade = 1
- evadingTick = GetTickCount()
- end
- function continueMovement(skillshot)
- if evading then
- skillshot.evading = false
- lastMovement.approachedPoint = nil
- allowCustomMovement = true
- evading = false
- _G.evade = 0
- if lastMovement.type == 2 then
- captureMovements = false
- myHero:MoveTo(0, 0)
- myHero:MoveTo(getLastMovementDestination().x, getLastMovementDestination().y)
- captureMovements = true
- elseif lastMovement.type == 3 then
- target = getTarget(lastMovement.targetId)
- if target ~= nil then
- captureMovements = false
- myHero:Attack(target)
- captureMovements = true
- else
- captureMovements = false
- myHero:MoveTo(myHero.x, myHero.z)
- captureMovements = true
- end
- elseif lastMovement.type == 10 then
- myHero:HoldPosition()
- elseif lastMovement.type == 7 then
- if myHero.userdataObject ~= nil and myHero.userdataObject:CanUseSpell(lastMovement.spellId) then
- target = getTarget(lastMovement.targetId)
- if target ~= nil then
- CastSpell(lastMovement.spellId, target)
- else
- CastSpell(lastMovement.spellId, lastMovement.destination.x, lastMovement.destination.y)
- end
- end
- lastMovement.type = 3
- end
- end
- end
- function OnDraw()
- if PerfectEvadeConfig.drawEnabled then
- for i, detectedSkillshot in ipairs(detectedSkillshots) do
- skillshotPos = skillshotPosition(detectedSkillshot, GetTickCount())
- if detectedSkillshot.skillshot.type == "line" then
- directionVector = detectedSkillshot.endPosition - detectedSkillshot.startPosition
- 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))
- DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius + 10, 0x00FF00)
- DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0xFFFFFF)
- DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius - 10, 0xFFFFFF)
- DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius - 20, 0xFFFFFF)
- DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius - 30, 0xFFFFFF)
- else
- DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0x00FF00)
- end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment