Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Najprzydatniejsze nie płatne skrypty VIP.


Rekomendowane odpowiedzi

Opublikowano

Witam, czy mógłby mi ktoś przedstawić na jakiej zasadzie działa VIP?

 

Mogę wcześniej używać BOL'a po patchu, mogę używać więcej niż 5 custom skryptów na raz i co jeszcze?

 

Z tego co się orientuje to, żeby mieć dostęp do najlepszych skryptów trzeba mieć VIP + kupić sobie tego skrypta za jakieś 2x tyle co kosztuje VIP.

 

 

 

  • Extra private scripts

 O jakie skrypty chodzi? 

 

Może już powstał jakiś temat ?

Jeżeli tak to byłbym wdzięczny za podlinkowanie.

 

Mam jeszcze jedno pytanko, słyszałem, że jest możliwość po jednym zakupie VIP'a mieć go  na zawsze, mógłby mi ktoś przybliżyć na jakiej zasadzie to działa?

 

Zapraszam na PW jakąś dobrą duszyczkę :))

 

Pozdrawiam.

 

Opublikowano

Nie, nikt Ci tego nie wytłumaczy.

Po zakupie VIPa masz dostęp do skryptów z działu VIP, których jest od cholery.

Opublikowano

A mógłby ktoś podesłać link do jakiegoś skryptu co unika skillshotów dla Vipów?

 

Chciałem pobrać Freaking Good Evaade, ale niestety w głównym temacie link do skryptu nie działa..

Opublikowano

A mógłby ktoś podesłać link do jakiegoś skryptu co unika skillshotów dla Vipów?

 

Chciałem pobrać Freaking Good Evaade, ale niestety w głównym temacie link do skryptu nie działa..

http://scr.hu/0ew/aomqy
http://botoflegends.com/forum/topic/10469-freaking-good-evade-skillshot-evader-and-drawer-for-everyone/

Owszem warto kupić vipa dla lepszego predicion, revamped, evadeee.

Opublikowano

 

 

local version = "9"

require "old2dgeo"

class 'CollisionPE'
HERO_ALL = 1
HERO_ENEMY = 2
HERO_ALLY = 3


function CollisionPE:__init(sRange, projSpeed, sDelay, sWidth)
    uniqueId = uniqueId + 1
    self.uniqueId = uniqueId
    
    self.sRange = sRange
    self.projSpeed = projSpeed
    self.sDelay = sDelay
    self.sWidth = sWidth/2
    
    self.enemyMinions = minionManager(MINION_ALLY, 2000, myHero, MINION_SORT_HEALTH_ASC)
    self.minionupdate = 0
end

function CollisionPE:GetMinionCollision(pStart, pEnd)
    self.enemyMinions:update()
    
    local distance = GetDistance(pStart, pEnd)
    local prediction = TargetPredictionVIP(self.sRange, self.projSpeed, self.sDelay, self.sWidth)
    local mCollision = {}
    
    if distance > self.sRange then
        distance = self.sRange
    end
    
    local V = Vector(pEnd) - Vector(pStart)
    local k = V:normalized()
    local P = V:perpendicular2():normalized()
    
    local t,i,u = k:unpack()
    local x,y,z = P:unpack()
    
    local startLeftX = pStart.x + (x *self.sWidth)
    local startLeftY = pStart.y + (y *self.sWidth)
    local startLeftZ = pStart.z + (z *self.sWidth)
    local endLeftX = pStart.x + (x * self.sWidth) + (t * distance)
    local endLeftY = pStart.y + (y * self.sWidth) + (i * distance)
    local endLeftZ = pStart.z + (z * self.sWidth) + (u * distance)
    
    local startRightX = pStart.x - (x * self.sWidth)
    local startRightY = pStart.y - (y * self.sWidth)
    local startRightZ = pStart.z - (z * self.sWidth)
    local endRightX = pStart.x - (x * self.sWidth) + (t * distance)
    local endRightY = pStart.y - (y * self.sWidth) + (i * distance)
    local endRightZ = pStart.z - (z * self.sWidth)+ (u * distance)
    
    local startLeft = WorldToScreen(D3DXVECTOR3(startLeftX, startLeftY, startLeftZ))
    local endLeft = WorldToScreen(D3DXVECTOR3(endLeftX, endLeftY, endLeftZ))
    local startRight = WorldToScreen(D3DXVECTOR3(startRightX, startRightY, startRightZ))
    local endRight = WorldToScreen(D3DXVECTOR3(endRightX, endRightY, endRightZ))
    
    local poly = Polygon(Point(startLeft.x, startLeft.y), Point(endLeft.x, endLeft.y), Point(startRight.x, startRight.y), Point(endRight.x, endRight.y))
    
    for index, minion in pairs(self.enemyMinions.objects) do
        if minion ~= nil and minion.valid and not minion.dead then
            if GetDistance(pStart, minion) < distance then
                local pos, t, vec = prediction:GetPrediction(minion)
                local lineSegmentLeft = LineSegment(Point(startLeftX,startLeftZ), Point(endLeftX, endLeftZ))
                local lineSegmentRight = LineSegment(Point(startRightX,startRightZ), Point(endRightX, endRightZ))
                local toScreen, toPoint
                if pos ~= nil then
                    toScreen = WorldToScreen(D3DXVECTOR3(minion.x, minion.y, minion.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                else
                    toScreen = WorldToScreen(D3DXVECTOR3(minion.x, minion.y, minion.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                end
                
                
                if poly:contains(toPoint) then
                    table.insert(mCollision, minion)
                else
                    if pos ~= nil then
                        distance1 = Point(pos.x, pos.z):distance(lineSegmentLeft)
                        distance2 = Point(pos.x, pos.z):distance(lineSegmentRight)
                    else
                        distance1 = Point(minion.x, minion.z):distance(lineSegmentLeft)
                        distance2 = Point(minion.x, minion.z):distance(lineSegmentRight)
                    end
                    if (distance1 < (getHitBoxRadius(minion)*2+10) or distance2 < (getHitBoxRadius(minion) *2+10)) then
                        table.insert(mCollision, minion)
                    end
                end
            end
        end
    end
    if #mCollision > 0 then return true, mCollision else return false, mCollision end
end

function CollisionPE:GetHeroCollision(pStart, pEnd, mode)
    if mode == nil then mode = HERO_ENEMY end
    local heros = {}
    
    for i = 1, heroManager.iCount do
        local hero = heroManager:GetHero(i)
        if (mode == HERO_ENEMY or mode == HERO_ALL) and hero.team ~= myHero.team then
            table.insert(heros, hero)
            elseif (mode == HERO_ALLY or mode == HERO_ALL) and hero.team == myHero.team and not hero.isMe then
            table.insert(heros, hero)
        end
    end
    
    local distance = GetDistance(pStart, pEnd)
    local prediction = TargetPredictionVIP(self.sRange, self.projSpeed, self.sDelay, self.sWidth)
    local hCollision = {}
    
    if distance > self.sRange then
        distance = self.sRange
    end
    
    local V = Vector(pEnd) - Vector(pStart)
    local k = V:normalized()
    local P = V:perpendicular2():normalized()
    
    local t,i,u = k:unpack()
    local x,y,z = P:unpack()
    
    local startLeftX = pStart.x + (x *self.sWidth)
    local startLeftY = pStart.y + (y *self.sWidth)
    local startLeftZ = pStart.z + (z *self.sWidth)
    local endLeftX = pStart.x + (x * self.sWidth) + (t * distance)
    local endLeftY = pStart.y + (y * self.sWidth) + (i * distance)
    local endLeftZ = pStart.z + (z * self.sWidth) + (u * distance)
    
    local startRightX = pStart.x - (x * self.sWidth)
    local startRightY = pStart.y - (y * self.sWidth)
    local startRightZ = pStart.z - (z * self.sWidth)
    local endRightX = pStart.x - (x * self.sWidth) + (t * distance)
    local endRightY = pStart.y - (y * self.sWidth) + (i * distance)
    local endRightZ = pStart.z - (z * self.sWidth)+ (u * distance)
    
    local startLeft = WorldToScreen(D3DXVECTOR3(startLeftX, startLeftY, startLeftZ))
    local endLeft = WorldToScreen(D3DXVECTOR3(endLeftX, endLeftY, endLeftZ))
    local startRight = WorldToScreen(D3DXVECTOR3(startRightX, startRightY, startRightZ))
    local endRight = WorldToScreen(D3DXVECTOR3(endRightX, endRightY, endRightZ))
    
    local poly = Polygon(Point(startLeft.x, startLeft.y), Point(endLeft.x, endLeft.y), Point(startRight.x, startRight.y), Point(endRight.x, endRight.y))
    
    for index, hero in pairs(heros) do
        if hero ~= nil and hero.valid and not hero.dead then
            if GetDistance(pStart, hero) < distance then
                local pos, t, vec = prediction:GetPrediction(hero)
                local lineSegmentLeft = LineSegment(Point(startLeftX,startLeftZ), Point(endLeftX, endLeftZ))
                local lineSegmentRight = LineSegment(Point(startRightX,startRightZ), Point(endRightX, endRightZ))
                local toScreen, toPoint
                if pos ~= nil then
                    toScreen = WorldToScreen(D3DXVECTOR3(pos.x, hero.y, pos.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                else
                    toScreen = WorldToScreen(D3DXVECTOR3(hero.x, hero.y, hero.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                end
                
                
                if poly:contains(toPoint) then
                    table.insert(hCollision, hero)
                else
                    if pos ~= nil then
                        distance1 = Point(pos.x, pos.z):distance(lineSegmentLeft)
                        distance2 = Point(pos.x, pos.z):distance(lineSegmentRight)
                    else
                        distance1 = Point(hero.x, hero.z):distance(lineSegmentLeft)
                        distance2 = Point(hero.x, hero.z):distance(lineSegmentRight)
                    end
                    if (distance1 < (getHitBoxRadius(hero)*2+10) or distance2 < (getHitBoxRadius(hero) *2+10)) then
                        table.insert(hCollision, hero)
                    end
                end
            end
        end
    end
    if #hCollision > 0 then return true, hCollision else return false, hCollision end
end

function CollisionPE:GetCollision(pStart, pEnd)
    local b , minions = self:GetMinionCollision(pStart, pEnd)
    local t , heros = self:GetHeroCollision(pStart, pEnd, HERO_ENEMY)
    
    if not b then return t, heros end
    if not t then return b, minions end
    
    local all = {}
    
    for index, hero in pairs(heros) do
        table.insert(all, hero)
    end
    
    for index, minion in pairs(minions) do
        table.insert(all, minion)
    end
    
    return true, all
end


function getHitBoxRadius(target)
    return GetDistance(target, target.minBBox)/2
end

_G.evade = false
moveBuffer = 25
smoothing = 75
dashrange = 0


champions = {}
champions2 = {
["Lux"] = {charName = "Lux", skillshots = {
["Light Binding"] = {name = "LightBinding", spellName = "LuxLightBinding", spellDelay = 250, projectileName = "LuxLightBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["Lux LightStrike Kugel"] = {name = "LuxLightStrikeKugel", spellName = "LuxLightStrikeKugel", spellDelay = 250, projectileName = "LuxLightstrike_mis.troy", projectileSpeed = 1400, range = 1100, radius = 275, type = "circle", cc = "false", collision = "false", shieldnow = "false"},
["Lux Malice Cannon"] = {name = "LuxMaliceCannon", spellName = "LuxMaliceCannon", spellDelay = 1375, projectileName = "LuxMaliceCannon_cas.troy", projectileSpeed = 50000, range = 3500, radius = 190, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Nidalee"] = {charName = "Nidalee", skillshots = {
["Javelin Toss"] = {name = "JavelinToss", spellName = "JavelinToss", spellDelay = 125, projectileName = "nidalee_javelinToss_mis.troy", projectileSpeed = 1300, range = 1500, radius = 60, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Kennen"] = {charName = "Kennen", skillshots = {
["Thundering Shuriken"] = {name = "ThunderingShuriken", spellName = "KennenShurikenHurlMissile1", spellDelay = 180, projectileName = "kennen_ts_mis.troy", projectileSpeed = 1700, range = 1050, radius = 50, type = "line", cc = "false", collision = "true", shieldnow = "true"}
}},
["Amumu"] = {charName = "Amumu", skillshots = {
["Bandage Toss"] = {name = "BandageToss", spellName = "BandageToss", spellDelay = 250, projectileName = "Bandage_beam.troy", projectileSpeed = 2000, range = 1100, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Lee Sin"] = {charName = "LeeSin", skillshots = {
["Sonic Wave"] = {name = "SonicWave", spellName = "BlindMonkQOne", spellDelay = 250, projectileName = "blindMonk_Q_mis_01.troy", projectileSpeed = 1800, range = 1100, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Morgana"] = {charName = "Morgana", skillshots = {
["Dark Binding Missile"] = {name = "DarkBinding", spellName = "DarkBindingMissile", spellDelay = 250, projectileName = "DarkBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Sejuani"] = {charName = "Sejuani", skillshots = {
["SejuaniR"] = {name = "SejuaniR", spellName = "SejuaniGlacialPrisonCast", spellDelay = 250, projectileName = "Sejuani_R_mis.troy", projectileSpeed = 1600, range = 1200, radius = 110, type="line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Sona"] = {charName = "Sona", skillshots = {
["Crescendo"] = {name = "Crescendo", spellName = "SonaCrescendo", spellDelay = 240, projectileName = "SonaCrescendo_mis.troy", projectileSpeed = 2400, range = 1000, radius = 160, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Gragas"] = {charName = "Gragas", skillshots = {
["Barrel Roll"] = {name = "BarrelRoll", spellName = "GragasBarrelRoll", spellDelay = 250, projectileName = "gragas_barrelroll_mis.troy", projectileSpeed = 1000, range = 1115, radius = 180, type = "circle", cc = "false", collision = "false", shieldnow = "false"},
["Barrel Roll Missile"] = {name = "BarrelRollMissile", spellName = "GragasBarrelRollMissile", spellDelay = 0, projectileName = "gragas_barrelroll_mis.troy", projectileSpeed = 1000, range = 1115, radius = 180, type = "circle", cc = "false", collision = "false", shieldnow = "false"},
}},
["Syndra"] = {charName = "Syndra", skillshots = {
["Q"] = {name = "Q", spellName = "SyndraQ", spellDelay = 250, projectileName = "Syndra_Q_fall.troy", projectileSpeed = 500, range = 825, radius = 175, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
["W"] = {name = "W", spellName = "syndrawcast", spellDelay = 250, projectileName = "Syndra_W_fall.troy", projectileSpeed = 500, range = 950, radius = 200, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
}},
["Malphite"] = {charName = "Malphite", skillshots = {
["UFSlash"] = {name = "UFSlash", spellName = "UFSlash", spellDelay = 0, projectileName = "UnstoppableForce_cas.troy", projectileSpeed = 550, range = 1000, radius = 300, type="circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Ezreal"] = {charName = "Ezreal", skillshots = {
["Mystic Shot"] = {name = "MysticShot", spellName = "EzrealMysticShot", spellDelay = 250, projectileName = "Ezreal_mysticshot_mis.troy", projectileSpeed = 2000, range = 1200, radius = 80, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["Essence Flux"] = {name = "EssenceFlux", spellName = "EzrealEssenceFlux", spellDelay = 250, projectileName = "Ezreal_essenceflux_mis.troy", projectileSpeed = 1500, range = 1050, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Mystic Shot (Pulsefire)"] = {name = "MysticShot", spellName = "EzrealMysticShotPulse", spellDelay = 250, projectileName = "Ezreal_mysticshot_mis.troy", projectileSpeed = 2000, range = 1200, radius = 80, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["Trueshot Barrage"] = {name = "TrueshotBarrage", spellName = "EzrealTrueshotBarrage", spellDelay = 1000, projectileName = "Ezreal_TrueShot_mis.troy", projectileSpeed = 2000, range = 20000, radius = 160, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Ahri"] = {charName = "Ahri", skillshots = {
["Orb of Deception"] = {name = "OrbofDeception", spellName = "AhriOrbofDeception", spellDelay = 250, projectileName = "Ahri_Orb_mis.troy", projectileSpeed = 2500, range = 900, radius = 100, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Orb of Deception Back"] = {name = "OrbofDeceptionBack", spellName = "AhriOrbofDeceptionherpityderp", spellDelay = 250+360, projectileName = "Ahri_Orb_mis_02.troy", projectileSpeed = 915, range = 900, radius = 100, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Charm"] = {name = "Charm", spellName = "AhriSeduce", spellDelay = 250, projectileName = "Ahri_Charm_mis.troy", projectileSpeed = 1000, range = 1000, radius = 60, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Olaf"] = {charName = "Olaf", skillshots = {
["Undertow"] = {name = "Undertow", spellName = "OlafAxeThrow", spellDelay = 250, projectileName = "olaf_axe_mis.troy", projectileSpeed = 1600, range = 1000, radius = 90, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Leona"] = {charName = "Leona", skillshots = {
["Zenith Blade"] = {name = "LeonaZenithBlade", spellName = "LeonaZenithBlade", spellDelay = 250, projectileName = "Leona_ZenithBlade_mis.troy", projectileSpeed = 2000, range = 950, radius = 110, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["Leona Solar Flare"] = {name = "LeonaSolarFlare", spellName = "LeonaSolarFlare", spellDelay = 250, projectileName = "Leona_SolarFlare_cas.troy", projectileSpeed = 1500, range = 1200, radius = 300, type = "circular", cc = "true", collision = "false", shieldnow = "true"}
}},
["Karthus"] = {charName = "Karthus", skillshots = {
["Lay Waste"] = {name = "LayWaste", spellName = "LayWaste", spellDelay = 250, projectileName = "LayWaste_point.troy", projectileSpeed = 1750, range = 875, radius = 140, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Chogath"] = {charName = "Chogath", skillshots = {
["Rupture"] = {name = "Rupture", spellName = "Rupture", spellDelay = 0, projectileName = "rupture_cas_01_red_team.troy", projectileSpeed = 950, range = 950, radius = 250, type = "circular", cc = "true", collision = "false", shieldnow = "true"}
}},
["Blitzcrank"] = {charName = "Blitzcrank", skillshots = {
["Rocket Grab"] = {name = "RocketGrab", spellName = "RocketGrabMissile", spellDelay = 250, projectileName = "FistGrab_mis.troy", projectileSpeed = 1800, range = 1050, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Anivia"] = {charName = "Anivia", skillshots = {
["Flash Frost"] = {name = "FlashFrost", spellName = "FlashFrostSpell", spellDelay = 250, projectileName = "cryo_FlashFrost_mis.troy", projectileSpeed = 850, range = 1100, radius = 110, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Zyra"] = {charName = "Zyra", skillshots = {
["Grasping Roots"] = {name = "GraspingRoots", spellName = "ZyraGraspingRoots", spellDelay = 250, projectileName = "Zyra_E_sequence_impact.troy", projectileSpeed = 1150, range = 1150, radius = 70, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["Zyra Passive Death"] = {name = "ZyraPassive", spellName = "zyrapassivedeathmanager", spellDelay = 500, projectileName = "zyra_passive_plant_mis.troy", projectileSpeed = 2000, range = 1474, radius = 60, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Deadly Bloom"] = {name = "DeadlyBloom", spellName = "ZyraQFissure", spellDelay = 1000, projectileName = "Zyra_Q_cas.troy", projectileSpeed = 0, range = 800, radius = 250, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Nautilus"] = {charName = "Nautilus", skillshots = {
["Dredge Line"] = {name = "DredgeLine", spellName = "NautilusAnchorDrag", spellDelay = 250, projectileName = "Nautilus_Q_mis.troy", projectileSpeed = 2000, range = 1080, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Caitlyn"] = {charName = "Caitlyn", skillshots = {
["Piltover Peacemaker"] = {name = "PiltoverPeacemaker", spellName = "CaitlynPiltoverPeacemaker", spellDelay = 625, projectileName = "caitlyn_Q_mis.troy", projectileSpeed = 2200, range = 1300, radius = 90, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Caitlyn Entrapment"] = {name = "CaitlynEntrapment", spellName = "CaitlynEntrapment", spellDelay = 150, projectileName = "caitlyn_entrapment_mis.troy", projectileSpeed = 2000, range = 950, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Mundo"] = {charName = "DrMundo", skillshots = {
["Infected Cleaver"] = {name = "InfectedCleaver", spellName = "InfectedCleaverMissile", spellDelay = 250, projectileName = "dr_mundo_infected_cleaver_mis.troy", projectileSpeed = 2000, range = 1050, radius = 75, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Brand"] = {charName = "Brand", skillshots = {
["BrandBlaze"] = {name = "BrandBlaze", spellName = "BrandBlaze", spellDelay = 250, projectileName = "BrandBlaze_mis.troy", projectileSpeed = 1600, range = 1100, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Pillar of Flame"] = {name = "PillarofFlame", spellName = "BrandFissure", spellDelay = 250, projectileName = "BrandPOF_tar_green.troy", projectileSpeed = 900, range = 1100, radius = 240, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Corki"] = {charName = "Corki", skillshots = {
["Missile Barrage"] = {name = "MissileBarrage", spellName = "MissileBarrage", spellDelay = 250, projectileName = "corki_MissleBarrage_mis.troy", projectileSpeed = 2000, range = 1300, radius = 40, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["Missile Barrage big"] = {name = "MissileBarragebig", spellName = "MissileBarrage!", spellDelay = 250, projectileName = "Corki_MissleBarrage_DD_mis.troy", projectileSpeed = 2000, range = 1300, radius = 40, type = "line", cc = "false", collision = "true", shieldnow = "true"}
}},
["TwistedFate"] = {charName = "TwistedFate", skillshots = {
["Loaded Dice"] = {name = "LoadedDice", spellName = "WildCards", spellDelay = 250, projectileName = "Roulette_mis.troy", projectileSpeed = 1000, range = 1450, radius = 40, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["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 = "true", collision = "false", shieldnow = "true"}
}},
["Cassiopeia"] = {charName = "Cassiopeia", skillshots = {
["Noxious Blast"] = {name = "NoxiousBlast", spellName = "CassiopeiaNoxiousBlast", spellDelay = 250, projectileName = "CassNoxiousSnakePlane_green.troy", projectileSpeed = 500, range = 850, radius = 130, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
}},
["Sivir"] = {charName = "Sivir", skillshots = {
["Boomerang Blade"] = {name = "BoomerangBlade", spellName = "SivirQ", spellDelay = 250, projectileName = "Sivir_Base_Q_mis.troy", projectileSpeed = 1350, range = 1150, radius = 101, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Ashe"] = {charName = "Ashe", skillshots = {
["Enchanted Arrow"] = {name = "EnchantedArrow", spellName = "EnchantedCrystalArrow", spellDelay = 250, projectileName = "Ashe_Base_R_mis.troy", projectileSpeed = 1600, range = 25000, radius = 120, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["KogMaw"] = {charName = "KogMaw", skillshots = {
["Living Artillery"] = {name = "LivingArtillery", spellName = "KogMawLivingArtillery", spellDelay = 250, projectileName = "KogMawLivingArtillery_mis.troy", projectileSpeed = 1050, range = 2200, radius = 225, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Khazix"] = {charName = "Khazix", skillshots = {
["KhazixW"] = {name = "KhazixW", spellName = "KhazixW", spellDelay = 250, projectileName = "Khazix_W_mis_enhanced.troy", projectileSpeed = 1700, range = 1025, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["khazixwlong"] = {name = "khazixwlong", spellName = "khazixwlong", spellDelay = 250, projectileName = "Khazix_W_mis_enhanced.troy", projectileSpeed = 1700, range = 1025, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Zed"] = {charName = "Zed", skillshots = {
["ZedShuriken"] = {name = "ZedShuriken", spellName = "ZedShuriken", spellDelay = 250, projectileName = "Zed_Q_Mis.troy", projectileSpeed = 1700, range = 925, radius = 50, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Leblanc"] = {charName = "Leblanc", skillshots = {
["Ethereal Chains"] = {name = "EtherealChains", spellName = "LeblancSoulShackle", spellDelay = 250, projectileName = "leBlanc_shackle_mis.troy", projectileSpeed = 1600, range = 960, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Ethereal Chains R"] = {name = "EtherealChainsR", spellName = "LeblancSoulShackleM", spellDelay = 250, projectileName = "leBlanc_shackle_mis_ult.troy", projectileSpeed = 1600, range = 960, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Draven"] = {charName = "Draven", skillshots = {
["Stand Aside"] = {name = "StandAside", spellName = "DravenDoubleShot", spellDelay = 250, projectileName = "Draven_E_mis.troy", projectileSpeed = 1400, range = 1100, radius = 130, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["DravenR"] = {name = "DravenR", spellName = "DravenRCast", spellDelay = 500, projectileName = "Draven_R_mis!.troy", projectileSpeed = 2000, range = 25000, radius = 160, type = "line", cc = "false", collision = "false", shieldnow = "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", collision = "true", shieldnow = "true"}
}},
["Lulu"] = {charName = "Lulu", skillshots = {
["LuluQ"] = {name = "LuluQ", spellName = "LuluQ", spellDelay = 250, projectileName = "Lulu_Q_Mis.troy", projectileSpeed = 1450, range = 1000, radius = 50, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Thresh"] = {charName = "Thresh", skillshots = {
["ThreshQ"] = {name = "ThreshQ", spellName = "ThreshQ", spellDelay = 500, projectileName = "Thresh_Q_whip_beam.troy", projectileSpeed = 1900, range = 1100, radius = 65, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Shen"] = {charName = "Shen", skillshots = {
["ShadowDash"] = {name = "ShadowDash", spellName = "ShenShadowDash", spellDelay = 0, projectileName = "shen_shadowDash_mis.troy", projectileSpeed = 3000, range = 575, radius = 50, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Quinn"] = {charName = "Quinn", skillshots = {
["QuinnQ"] = {name = "QuinnQ", spellName = "QuinnQ", spellDelay = 250, projectileName = "Quinn_Q_missile.troy", projectileSpeed = 1550, range = 1050, radius = 80, type = "line", cc = "false", collision = "true", shieldnow = "true"}
}},
["Veigar"] = {charName = "Veigar", skillshots = {
["Dark Matter"] = {name = "VeigarDarkMatter", spellName = "VeigarDarkMatter", spellDelay = 250, projectileName = "!", projectileSpeed = 900, range = 900, radius = 225, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Jayce"] = {charName = "Jayce", skillshots = {
["JayceShockBlast"] = {name = "JayceShockBlast", spellName = "jayceshockblast", spellDelay = 250, projectileName = "JayceOrbLightning.troy", projectileSpeed = 1450, range = 1050, radius = 70, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["JayceShockBlastCharged"] = {name = "JayceShockBlastCharged", spellName = "jayceshockblast", spellDelay = 250, projectileName = "JayceOrbLightningCharged.troy", projectileSpeed = 2350, range = 1600, radius = 70, type = "line", cc = "false", collision = "true", shieldnow = "true"},
}},
["Nami"] = {charName = "Nami", skillshots = {
["NamiQ"] = {name = "NamiQ", spellName = "NamiQ", spellDelay = 250, projectileName = "Nami_Q_mis.troy", projectileSpeed = 1500, range = 1625, radius = 225, type = "circle", cc = "true", collision = "false", shieldnow = "true"}
}},
["Fizz"] = {charName = "Fizz", skillshots = {
["Fizz Ultimate"] = {name = "FizzULT", spellName = "FizzMarinerDoom", spellDelay = 250, projectileName = "Fizz_UltimateMissile.troy", projectileSpeed = 1350, range = 1275, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Varus"] = {charName = "Varus", skillshots = {
["Varus Q Missile"] = {name = "VarusQMissile", spellName = "somerandomspellnamethatwillnevergetcalled", spellDelay = 0, projectileName = "VarusQ_mis.troy", projectileSpeed = 1900, range = 1600, radius = 70, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["VarusR"] = {name = "VarusR", spellName = "VarusR", spellDelay = 250, projectileName = "VarusRMissile.troy", projectileSpeed = 1950, range = 1250, radius = 100, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Karma"] = {charName = "Karma", skillshots = {
["KarmaQ"] = {name = "KarmaQ", spellName = "KarmaQ", spellDelay = 250, projectileName = "TEMP_KarmaQMis.troy", projectileSpeed = 1700, range = 1050, radius = 90, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Aatrox"] = {charName = "Aatrox", skillshots = {
["Blade of Torment"] = {name = "BladeofTorment", spellName = "AatroxE", spellDelay = 250, projectileName = "AatroxBladeofTorment_mis.troy", projectileSpeed = 1200, range = 1075, radius = 75, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["AatroxQ"] = {name = "AatroxQ", spellName = "AatroxQ", spellDelay = 250, projectileName = "AatroxQ.troy", projectileSpeed = 450, range = 650, radius = 145, type = "circle", cc = "true", collision = "false", shieldnow = "true"},
}},
["Xerath"] = {charName = "Xerath", skillshots = {
["Xerath Arcanopulse"] = {name = "xeratharcanopulse21", spellName = "xeratharcanopulse2", spellDelay = 400, projectileName = "hiu", projectileSpeed = 25000, range = 0, radius = 100, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["XerathArcaneBarrage2"] = {name = "XerathArcaneBarrage2", spellName = "XerathArcaneBarrage2", spellDelay = 500, projectileName = "Xerath_Base_W_cas.troy", projectileSpeed = 0, range = 1100, radius = 325, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
["XerathMageSpear"] = {name = "XerathMageSpear", spellName = "XerathMageSpear", spellDelay = 250, projectileName = "Xerath_Base_E_mis.troy", projectileSpeed = 1600, range = 1050, radius = 125, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["xerathlocuspulse"] = {name = "xerathlocuspulse", spellName = "xerathlocuspulse", spellDelay = 250, projectileName = "Xerath_Base_R_mis.troy", projectileSpeed = 300, range = 5600, radius = 265, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
}},
["Lucian"] = {charName = "Lucian", skillshots = {
["LucianQ"] = {name = "LucianQ", spellName = "LucianQ", spellDelay = 350, projectileName = "Lucian_Q_laser.troy", projectileSpeed = 25000, range = 570*2, radius = 65, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["LucianW"] = {name = "LucianW", spellName = "LucianW", spellDelay = 300, projectileName = "Lucian_W_mis.troy", projectileSpeed = 1600, range = 1000, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Viktor"] = {charName = "Viktor", skillshots = {
["ViktorDeathRay1"] = {name = "ViktorDeathRay1", spellName = "ViktorDeathRay!", spellDelay = 500, projectileName = "Viktor_DeathRay_Fix_Mis.troy", projectileSpeed = 780, range = 700, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["ViktorDeathRay2"] = {name = "ViktorDeathRay2", spellName = "ViktorDeathRay!", spellDelay = 500, projectileName = "Viktor_DeathRay_Fix_Mis_Augmented.troy", projectileSpeed = 780, range = 700, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Rumble"] = {charName = "Rumble", skillshots = {
["RumbleGrenade"] = {name = "RumbleGrenade", spellName = "RumbleGrenade", spellDelay = 250, projectileName = "rumble_taze_mis.troy", projectileSpeed = 2000, range = 950, radius = 90, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Nocturne"] = {charName = "Nocturne", skillshots = {
["NocturneDuskbringer"] = {name = "NocturneDuskbringer", spellName = "NocturneDuskbringer", spellDelay = 250, projectileName = "NocturneDuskbringer_mis.troy", projectileSpeed = 1400, range = 1125, radius = 60, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Yasuo"] = {charName = "Yasuo", skillshots = {
["yasuoq3"] = {name = "yasuoq3", spellName = "yasuoq3w", spellDelay = 250, projectileName = "Yasuo_Q_wind_mis.troy", projectileSpeed = 1200, range = 1000, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["yasuoq1"] = {name = "yasuoq1", spellName = "yasuoQW", spellDelay = 250, projectileName = "Yasuo_Q_WindStrike.troy", projectileSpeed = 25000, range = 475, radius = 40, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["yasuoq2"] = {name = "yasuoq2", spellName = "yasuoq2w", spellDelay = 250, projectileName = "Yasuo_Q_windstrike_02.troy", projectileSpeed = 25000, range = 475, radius = 40, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Orianna"] = {charName = "Orianna", skillshots = {
["OrianaIzunaCommand"] = {name = "OrianaIzunaCommand", spellName = "OrianaIzunaCommand", spellDelay = 0, projectileName = "Oriana_Ghost_mis.troy", projectileSpeed = 1300, range = 800, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["OrianaDetonateCommand"] = {name = "OrianaDetonateCommand", spellName = "OrianaDetonateCommand", spellDelay = 100, projectileName = "Oriana_Shockwave_nova.troy", projectileSpeed = 400, range = 2000, radius = 400, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Ziggs"] = {charName = "Ziggs", skillshots = {
["ZiggsQ"] = {name = "ZiggsQ", spellName = "ZiggsQ", spellDelay = 250, projectileName = "ZiggsQ.troy", projectileSpeed = 1700, range = 1400, radius = 155, type = "line", cc = "false", collision = "true", shieldnow = "true"},
}},
["Annie"] = {charName = "Annie", skillshots = {
["AnnieR"] = {name = "AnnieR", spellName = "InfernalGuardian", spellDelay = 100, projectileName = "nothing", projectileSpeed = 0, range = 600, radius = 300, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Galio"] = {charName = "Galio", skillshots = {
["GalioResoluteSmite"] = {name = "GalioResoluteSmite", spellName = "GalioResoluteSmite", spellDelay = 250, projectileName = "galio_concussiveBlast_mis.troy", projectileSpeed = 850, range = 2000, radius = 200, type = "circle", cc = "true", collision = "false", shieldnow = "true"},
}},
["Jinx"] = {charName = "Jinx", skillshots = {
["W"] = {name = "Zap", spellName = "JinxW", spellDelay = 600, projectileName = "Jinx_W_Beam.troy", projectileSpeed = 3300, range = 1450, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["R"] = {name = "SuperMegaDeathRocket", spellName = "JinxRWrapper", spellDelay = 600, projectileName = "Jinx_R_Mis.troy", projectileSpeed = 1700, range = 20000, radius = 120, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Velkoz"] = {charName = "Velkoz", skillshots = {
["PlasmaFission"] = {name = "PlasmaFission", spellName = "VelKozQ", spellDelay = 250, projectileName = "Velkoz_Base_Q_mis.troy", projectileSpeed = 1200, range = 1050, radius = 120, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Plasma Fission Split"] = {name = "VelKozQSplit", spellName = "VelKozQ", spellDelay = 250, projectileName = "Velkoz_Base_Q_Split_mis.troy", projectileSpeed = 1200, range = 1050, radius = 120, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Void Rift"] = {name = "VelkozW", spellName = "VelkozW", spellDelay = 250, projectileName = "Velkoz_Base_W_Turret.troy", projectileSpeed = 1200, range = 1050, radius = 125, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Tectonic Disruption"] = {name = "VelkozE", spellName = "VelkozE", spellDelay = 250, projectileName = "DarkBinding_mis.troy", projectileSpeed = 1200, range = 800, radius = 225, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Heimerdinger"] = {charName = "Heimerdinger", skillshots = {
--["Micro-Rockets"] = {name = "MicroRockets", spellName = "HeimerdingerW1", spellDelay = 500, projectileName = "Heimerdinger_Base_w_Mis.troy", projectileSpeed = 902, range = 1325, radius = 100, type = "line", cc = "false", collision = "true", shieldnow = "true"},
--["Storm Grenade"] = {name = "StormGrenade", spellName = "HeimerdingerE", spellDelay = 250, projectileName = "Heimerdinger_Base_E_Mis.troy", projectileSpeed = 2500, range = 970, radius = 180, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
--["Micro-RocketsUlt"] = {name = "MicroRocketsUlt", spellName = "HeimerdingerW2", spellDelay = 500, projectileName = "Heimerdinger_Base_W_Mis_Ult.troy", projectileSpeed = 902, range = 1325, radius = 100, type = "line", cc = "false", collision = "true", shieldnow = "true"},
--["Storm Grenade"] = {name = "StormGrenade", spellName = "HeimerdingerE2", spellDelay = 250, projectileName = "Heimerdinger_Base_E_Mis_Ult.troy", projectileSpeed = 2500, range = 970, radius = 180, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Malzahar"] = {charName = "Malzahar", skillshots = {
["Call Of The Void"] = {name = "CallOfTheVoid", spellName ="AlZaharCalloftheVoid1", spellDelay = 0, projectileName = "AlzaharCallofthevoid_mis.troy", projectileSpeed = 1600, range = 450, radius = 100, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}}    ,
["Janna"] = {charName = "Janna", skillshots = {
["Howling Gale"] = {name = "HowlingGale", spellName ="HowlingGale", spellDelay = 0, projectileName = "HowlingGale_mis.troy", projectileSpeed = 500, range = 0, radius = 100, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}}
}
champions3 = {
["Aatrox"] = "AatroxW AatroxW2",
["Amumu"] = "AuraOfDespair",
["Anivia"] = "GlacialStorm",
["Annie"] = "MoltenShield",
["Ashe"] = "FrostShot",
["Blitzcrank"] = "Overdrive",
["Chogath"] = "VorpalSpikes",
["Corki"] = "GGun",
["Darius"] = "DariusCleave",
["DrMundo"] = "BurningAgony Masochism",
["Draven"] = "DravenSpinning DravenFury",
["Elise"] = "EliseSpiderW EliseRSpider EliseRHuman",
["Evelynn"] = "EvelynnQ EvelynnW",
["Fiora"] = "FioraRiposte FioraFlurry",
["Fizz"] = "FizzSeastonePassive",
["Galio"] = "GalioBulwark",
["Garen"] = "GarenQ GarenW GarenE",
["Gragas"] = "GragasBarrelRollToggle",
["Hecarim"] = "HecarimRapidSlash HecarimW HecarimRamp",
["Heimerdinger"] = "HeimerdingerR",
["Irelia"] = "IreliaHitenStyle IreliaTranscendentBlades",
["Janna"] = "HowlingGale SowTheWind EyeOfTheStorm",
["JarvanIV"] = "JarvanIVGoldenAegis JarvanIVDemacianStandard",
["Jax"] = "JaxEmpowerTwo JaxCounterStrike JaxRelentlessAssault",
["Jayce"] = "JayceStaticField JayceHyperCharge JayceAccelerationGate JayceStanceGtH JayceStanceHtG",
["Jinx"] = "JinxQ JinxE",
["Karma"] = "KarmaSolKimShield KarmaMantra",
["Karthus"] = "Defile",
["Kassadin"] = "NetherBlade",
["Katarina"] = "KatarinaW",
["Kayle"] = "JudicatorDivineBlessing JudicatorRighteousFury JudicatorIntervention",
["Kennen"] = "KennenLightningRush",
["KhaZix"] = "KhaZixR",
["KogMaw"] = "KogMawBioArcaneBarrage",
["Leona"] = "LeonaShieldOfDaybreak LeonaSolarBarrier",
["Lissandra"] = "LissandraW",
["Lucian"] = "LucianR",
["Lulu"] = "LuluW LuluE LuluR",
["Lux"] = "LuxLightStrikeToggle",
["Malphite"] = "Obduracy",
["Malzahar"] = "AlZaharNullZone",
["Maokai"] = "MaokaiDrain3Toggle",
["MasterYi"] = "WujuStyle Highlander",
["MissFortune"] = "MissFortuneViciousStrikes",
["Mordekaiser"] = "MordekaiserCreepingDeathCast",
["Morgana"] = "BlackShield",
["Nami"] = "NamiE",
["Nautilus"] = "NautilusPiercingGaze",
["Nidalee"] = "Takedown PrimalSurge AspectOfTheCougar",
["Nocturne"] = "NocturneShroudOfDarkness NocturneParanoia",
["Nunu"] = "BloodBoil",
["Olaf"] = "OlafFrenziedStrikes OlafRagnarok",
["Orianna"] = "OrianalzunaCommand OrianaDissonanceCommand OrianaRedactCommand OrianaDetonateCommand",
["Poppy"] = "PoppyDevastatingBlow PoppyParagonOfDemacia",
["Quinn"] = "QuinnW QuinnR QuinnValorQ QuinnRFinale",
["Rammus"] = "PowerBall DefensiveBallCurl Tremors2",
["Renekton"] = "RenektonPreExecute",
["Rengar"] = "RengarW RengarR",
["Rumble"] = "RumbleFlameThrower RumbleShield",
["Ryze"] = "DesperatePower",
["Sejuani"] = "SejuaniNorthernWinds",
["Shaco"] = "HallucinateGuide",
["Shen"] = "ShenFeint",
["Shyvana"] = "ShyvanaDoubleAttack ShyvanaImmolationAura",
["Singed"] = "PoisonTrail InsanityPotion",
["Sion"] = "DeathsCaressFull Enrage",
["Sivir"] = "SivirW SivirE SivirR",
["Skarner"] = "SkarnerExoskeleton",
["Sona"] = "SonaHymOfValor SonaAiraOfPerseverance SonaSongOfDiscord",
["Swain"] = "SwainMetamorphism",
["Syndra"] = "SyndraQ SyndraW SyndraR",
["Talon"] = "TalonNoxianDiplomacy",
["Teemo"] = "MoveQuick",
["Tristana"] = "RapidFire",
["Trundle"] = "TrundleTrollSmash",
["Tryndamere"] = "Bloodlust UndyingRage",
["Twisted Fate"] = "PickACard BlueCardLock RedCardLock GoldCardLock Destiny",
["Twitch"] = "HideInShadows FullAutomatic",
["Udyr"] = "UdyrTigerStance UdyrTurtleStance UdyrBearStance UdyrPhoenixStance",
["Urgot"] = "UrgotTerrorCapacitorActive2",
["Vayne"] = "VayneInquisition",
["Vi"] = "ViE",
["Vladimir"] = "VladimirSanguinePool",
["Volibear"] = "VolibearQ VolibearW",
["Warwick"] = "HuntersCall BloodScent",
["Wukong"] = "WukongQ WukongW WukongR",
["Xin Zhao"] = "XenZhaoComboTarget ZenZhaoBattleCry",
["Zac"] = "ZacW",
["Zed"] = "ZedPBAOEDummy",
["Ziggs"] = "ZiggsWToggle",
["Zilean"] = "Rewind TimeWarp",
["Zyra"] = "ZyraSeed"

}

wrotedisclaimer = false
enemies = {}
nAllies = 0
allies = {}
XerathQTickCount = 0
nEnemies = 0
evading = false
allowCustomMovement = true
captureMovements = true
lastMovement = {}
detectedSkillshots = {}
nSkillshots = 0
CastingSpell = false
HowlingGale = false
lastset = 0
trueWidth = {}
trueSpeed = {}
trueDelay = {}
haveflash = false
flashSlot = nil
flashready = false
lastspell = "Q"
useflash = false
shieldslot = _E
shieldtick = nil
alreadywritten = false
thatfile = SCRIPT_PATH.."movementblock.txt"
currentbuffer = 0
bufferset = false
lastnonattack = 0
hitboxTable = {['Yasuo'] = 65, ['VelKoz'] = 65, ['Xerath'] = 65, ['Kassadin'] = 65, ['Rengar'] = 65, ['Thresh'] = 55.0, ['Ziggs'] = 55.0, ['KogMaw'] = 65, ['Katarina'] = 65, ['Riven'] = 65, ['Ashe'] = 65, ['Soraka'] = 65, ['Jinx'] = 65, ['JarvanIV'] = 65, ['Tryndamere'] = 65, ['Singed'] = 65, ['Diana'] = 65, ['Ahri'] = 65, ['Lulu'] = 65, ['MasterYi'] = 65, ['Lissandra'] = 65, ['Draven'] = 65, ['FiddleSticks'] = 65, ['Maokai'] = 80.0, ['Sivir'] = 65, ['Corki'] = 65, ['Janna'] = 65, ['Nasus'] = 80.0, ['LeeSin'] = 65, ['Jax'] = 65, ['Blitzcrank'] = 80.0, ['Shen'] = 65, ['Nocturne'] = 65, ['Sona'] = 65, ['Caitlyn'] = 65, ['Trundle'] = 65, ['Malphite'] = 80.0, ['Mordekaiser'] = 80.0, ['Vi'] = 50, ['Renekton'] = 80.0, ['Anivia'] = 65, ['Fizz'] = 65, ['Heimerdinger'] = 55.0, ['Evelynn'] = 65, ['Rumble'] = 80.0, ['Leblanc'] = 65, ['Darius'] = 80.0, ['Viktor'] = 65, ['XinZhao'] = 65, ['Orianna'] = 65, ['Vladimir'] = 65, ['Nidalee'] = 65, ['Syndra'] = 65, ['Zac'] = 80.0, ['Olaf'] = 65, ['Veigar'] = 55.0, ['Twitch'] = 65, ['Alistar'] = 80.0, ['Akali'] = 65, ['Urgot'] = 80.0, ['Leona'] = 65, ['Talon'] = 65, ['Karma'] = 65, ['Jayce'] = 65, ['Galio'] = 80.0, ['Shaco'] = 65, ['Taric'] = 65, ['TwistedFate'] = 65, ['Varus'] = 65, ['Garen'] = 65, ['Swain'] = 65, ['Vayne'] = 65, ['Fiora'] = 65, ['Quinn'] = 65, ['Kayle'] = 65, ['Brand'] = 65, ['Teemo'] = 55.0, ['Amumu'] = 55.0, ['Annie'] = 55.0, ['Elise'] = 65, ['Nami'] = 65, ['Poppy'] = 55.0, ['AniviaEgg'] = 65, ['Tristana'] = 55.0, ['Graves'] = 65, ['Morgana'] = 65, ['Gragas'] = 80.0, ['MissFortune'] = 65, ['Warwick'] = 65, ['Cassiopeia'] = 65, ['DrMundo'] = 80.0, ['Volibear'] = 80.0, ['Irelia'] = 65, ['Lucian'] = 65, ['Yorick'] = 80.0, ['Udyr'] = 65, ['MonkeyKing'] = 65, ['Kennen'] = 55.0, ['Nunu'] = 65, ['Ryze'] = 65, ['Zed'] = 65, ['Nautilus'] = 80.0, ['Gangplank'] = 65, ['shopevo'] = 65, ['Lux'] = 65, ['Sejuani'] = 80.0, ['Ezreal'] = 65, ['Khazix'] = 65, ['Sion'] = 80.0, ['Aatrox'] = 65, ['Hecarim'] = 80.0, ['Pantheon'] = 65, ['Shyvana'] = 50.0, ['Zyra'] = 65, ['Karthus'] = 65, ['Rammus'] = 65, ['Zilean'] = 65, ['Chogath'] = 80.0, ['Malzahar'] = 65, ['KogMawDead'] = 65, ['QuinnValor'] = 65, ['Nidalee_Cougar'] = 65}


function getTarget(targetId)
        if targetId ~= 0 and targetId ~= nil then
        return objManager:GetObjectByNetworkId(targetId)
    end
    return nil
end

function OnSendPacket(p)
        if VIP_USER then
        local packet = Packet(p)
        if packet:get('name') == 'S_MOVE' then
            if packet:get('sourceNetworkId') == myHero.networkID then
                if captureMovements then
                    if packet:get('targetNetworkId') == 0 then
                        lastMovement.destination = Point2(packet:get('x'), packet:get('y'))
                        lastMovement.type = packet:get('type')
                        lastMovement.targetId = packet:get('targetNetworkId')
                        lastnonattack = GetTickCount()
                        elseif lastnonattack + 1000 < GetTickCount() then
                        lastMovement.destination = Point2(packet:get('x'), packet:get('y'))
                        lastMovement.type = packet:get('type')
                        lastMovement.targetId = packet:get('targetNetworkId')
                    end
                    
                    if evading then
                        for i, detectedSkillshot in pairs(detectedSkillshots) do
                            if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                                dodgeSkillshot(detectedSkillshot)
                                break
                            end
                        end
                    end
                end
                if not allowCustomMovement then
                        for i, detectedSkillshot in pairs(detectedSkillshots) do
                            if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                                packet:block()
                                break
                            end
                        end
                end
            end
            elseif packet:get('name') == 'S_CAST' then
            if captureMovements and lastnonattack + 1000 < GetTickCount() then
                lastMovement.spellId = packet:get('spellId')
                lastMovement.type = 7
                lastMovement.targetId = packet:get('targetNetworkId')
                lastMovement.destination = Point2(packet:get('toX'), packet:get('toY'))
                
                if evading then
                    for i, detectedSkillshot in pairs(detectedSkillshots) do
                        if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                            dodgeSkillshot(detectedSkillshot)
                            break
                        end
                    end
                end
            end
            if not (allowCustomMovement or
                    spellStopMovement(GetMyHero().charName, packet:get('spellId'),
                    packet.targetNetworkId == GetMyHero().NetworkId)) then
                if packet:get('spellId') == 12 then
                else
                    for i, detectedSkillshot in pairs(detectedSkillshots) do
                        if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                            packet:block()
                            break
                        end
                    end
                end
            end
        end
    end
end

function spellStopMovement(champName, champSkill, selfCast)
    if GoodEvadeConfig.allowMove == false then
        return false
    end
    local champSkill2
    if(champSkill == 0) then
        champSkill2 = GetMyHero():GetSpellData(0).name
        if GoodEvadeConfig.stopCCMoves and (GetMyHero().charName == "Varus" or GetMyHero().charName == "Vi" or GetMyHero().charName == "Xerath") then
            return true
        else
            return false
        end
    elseif(champSkill == 1) then
        champSkill2 = GetMyHero():GetSpellData(1).name
        if(GetMyHero().charName) == "LeeSin" and selfCast then
            return true
        end
    elseif(champSkill == 2) then
        champSkill2 = GetMyHero():GetSpellData(2).name
    elseif(champSkill == 3) then
        champSkill2 = GetMyHero():GetSpellData(3).name
    else
        champSkill2 = "null"
    end
    if(champions3[champName] ~= nil) then
        return string.find(string.lower(champions3[champName]), string.lower(champSkill2)) ~= nil
    end
    return false
end

function getLastMovementDestination()
    mousePosition = Point2(mousePos.x, mousePos.z)
    if VIP_USER then
        if lastMovement.type == 3 then
            heroPosition = Point2(myHero.x, myHero.z)
            mousePosition = Point2(mousePos.x, mousePos.z)
            
            target = getTarget(lastMovement.targetId)
            if _isValidTarget(target) then
                targetPosition = Point2(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 mousePosition
                end
            else
                return mousePosition
            end
            elseif lastMovement.type == 7 then
            heroPosition = Point2(myHero.x, myHero.z)
            mousePosition = Point2(mousePos.x, mousePos.z)
            target = getTarget(lastMovement.targetId)
            if _isValidTarget(target) then
                targetPosition = Point2(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 mousePosition
                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 mousePosition
                end
            end
        else
            return lastMovement.destination
        end
        else return lastMovement.destination
    end
end
function CheckBall(obj)
    if obj == nil or obj.name == nil then return end
    
    if (obj.name:find("Oriana_Ghost_mis") or obj.name:find("Oriana_Ghost_mis_protect") ) then
        ball = nil            
        return
    end
    
    if obj.name:find("yomu_ring_red") then
        ball = obj
        return
    end
    
    if obj.name:find("Oriana_Ghost_bind") then
        for i, target in pairs(enemies) do
            if GetDistance(target, obj) < 40 then
                ball = target
            end
        end
    end
end

local AutoUpdate = true
local SELF = SCRIPT_PATH..GetCurrentEnv().FILE_NAME
local URL = "https://raw.githubusercontent.com/Whatefang/FreakingGoodEvade/master/FreakingGoodEvade.lua"
local UPDATE_TMP_FILE = LIB_PATH.."FGETmp.txt"
local versionmessage = "<font color=\"#81BEF7\" >Changelog: Added various AOE CC ults to dangerous ults; fixed handling (should now Spellshield > Dash > Flash out) of those spells. Added dash to dodge spells % HP slider. Swapped around menu items. Added a new drawing system; will draw a rectangle around the length of each skillshot to better show the hitbox. </font>"

function Update()
DownloadFile(URL, UPDATE_TMP_FILE, UpdateCallback)
end

function UpdateCallback()
file = io.open(UPDATE_TMP_FILE, "rb")
if file ~= nil then
content = file:read("*all")
file:close()
os.remove(UPDATE_TMP_FILE)
if content then
tmp, sstart = string.find(content, "local version = \"")
if sstart then
send, tmp = string.find(content, "\"", sstart+1)
end
if send then
Version = tonumber(string.sub(content, sstart+1, send-1))
end
if (Version ~= nil) and (Version > tonumber(version)) and content:find("--EOS--") then
file = io.open(SELF, "w")
if file then
file:write(content)
file:flush()
file:close()
PrintChat("<font color=\"#81BEF7\" >FreakingGoodEvade:</font> <font color=\"#00FF00\">Successfully updated to: v"..Version..". Please reload the script with F9.</font>")
else
PrintChat("<font color=\"#81BEF7\" >FreakingGoodEvade:</font> <font color=\"#FF0000\">Error updating to new version (v"..Version..")</font>")
end
elseif (Version ~= nil) and (Version == tonumber(version)) then
PrintChat("<font color=\"#81BEF7\" >FreakingGoodEvade:</font> <font color=\"#00FF00\">No updates found, latest version: v"..Version.." </font>")
end
end
end
end

function OnLoad()
    hitboxSize = hitboxTable[GetMyHero().charName]
    
    if hitboxSize == nil then
        hitboxSize = 80.0
    end

    ball = nil
    GoodEvadeConfig = scriptConfig("Freaking Good Evade", "Freaking Good Evade")
    GoodEvadeConfig:addParam("evadeBuffer", "Increase Skillshot width by", SCRIPT_PARAM_SLICE, 15, 0, 50, 0)
    GoodEvadeConfig:addParam("fowdelay", "Delay for skillshots from FOW", SCRIPT_PARAM_SLICE, 1, 1, 20, 0)
    GoodEvadeConfig:addParam("dodgeEnabled", "Dodge Skillshots", SCRIPT_PARAM_ONKEYTOGGLE, false, 192)
    GoodEvadeConfig:addParam("dodgeCConly", "Dodge CC only spells", SCRIPT_PARAM_ONKEYDOWN, false, 32)
    GoodEvadeConfig:addParam("dodgeCConly2", "Toggle dodge CC only spells", SCRIPT_PARAM_ONKEYTOGGLE, false, 77)
    GoodEvadeConfig:addParam("usedashes", "Dash to dodge spells", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("dashMouse", "Always dash toward your mouse", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("dashPercent", "Use dashes below what % HP", SCRIPT_PARAM_SLICE, 100, 0, 100)
    GoodEvadeConfig:addParam("lineallways", "Always try to dodge line skillshots", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("useSummonerFlash", "Flash to dodge dangerous spells", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("drawEnabled", "Draw Skillshots", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("resetdodge", "Reset Dodge", SCRIPT_PARAM_ONKEYDOWN, false, 17)
    GoodEvadeConfig:addParam("allowMove", "Allow use of 0 cast time spells", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("stopCCMoves", "Use 0 cast time spells with self cc", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("freemovementblock", "Free Users Movement Block", SCRIPT_PARAM_ONOFF, false)
    GoodEvadeConfig:addParam("oldDrawing", "Use old drawing", SCRIPT_PARAM_ONOFF, false)
    GoodEvadeConfig:permaShow("dodgeEnabled")
    for i = 1, heroManager.iCount do
        local hero = heroManager:GetHero(i)
        if hero.team ~= myHero.team then
            for i, skillShotChampion in pairs(champions2) do
                if skillShotChampion.charName == hero.charName then
                    table.insert(champions, skillShotChampion)
                end
            end
        end
    end
    GoodEvadeSkillshotConfig = scriptConfig("FGE skillshots", "FGE skillshots config")
    for i, skillShotChampion in pairs(champions) do
        for i, skillshot in pairs(skillShotChampion.skillshots) do
            name = tostring(skillshot.name)
            name2 = tostring(skillshot.name)
            if skillshot.cc == "true" then
                GoodEvadeSkillshotConfig:addParam(name, "Dodge "..name2, SCRIPT_PARAM_SLICE, 2, 0, 2, 0)
                elseif skillshot.cc == "false" then GoodEvadeSkillshotConfig:addParam(name, "Dodge "..name2, SCRIPT_PARAM_SLICE, 1, 0, 2, 0)
                elseif skillshot.cc == "never" then GoodEvadeSkillshotConfig:addParam(name, "Dodge "..name2, SCRIPT_PARAM_SLICE, 0, 0, 2, 0)
            end
        end
    end
    
    stopEvade()
    isSivir = false
    if myHero.charName == "Sivir" then
        isSivir = true
    end
    isNocturne = false
    if myHero.charName == "Nocturne" then
        isNocturne = true
    end
    isVayne = false
    if myHero.charName == "Vayne" then
        isVayne = true
    end
    isGraves = false
    if myHero.charName == "Graves" then
        isGraves = true
    end
    isEzreal = false
    if myHero.charName == "Ezreal" then
        isEzreal = true
    end
    if myHero.charName == "Caitlyn"
        then isCaitlyn = true
    end
    isLeblanc = false
    if myHero.charName == "Leblanc" then
        isLeblanc = true
    end
    isRiven = false
    if myHero.charName == "Riven" then
        isRiven = true
    end
    isFizz = false
    if myHero.charName == "Fizz" then
        isFizz = true
    end
    isShen = false
    if myHero.charName == "Shen" then
        isShen = true
    end
    isShaco = false
    if myHero.charName == "Shaco" then
        isShaco = true
    end
    isRenekton = false
    if myHero.charName == "Renekton" then
        isRenekton = true
    end
    isTristana = false
    if myHero.charName == "Tristana" then
        isTristana = true
    end
    isTryndamere = false
    if myHero.charName == "Tryndamere" then
        isTryndamere = true
    end
    isCorki = false
    if myHero.charName == "Corki" then
        isCorki = true
    end
    isLucian = false
    if myHero.charName == "Lucian" then
        isLucian = true
    end
    if myHero:GetSpellData(SUMMONER_1).name:find("SummonerFlash") then
        haveflash = true
        flashSlot = SUMMONER_1
        elseif myHero:GetSpellData(SUMMONER_2).name:find("SummonerFlash") then
        flashSlot = SUMMONER_2
        haveflash = true
    end
    
    lastMovement = {
    destination = Point2(myHero.x, myHero.z),
    moveCommand = Point2(myHero.x, myHero.z),
    type = 2,
    targetId = nil,
    spellId = nil,
    approachedPoint = nil
    }
    
    for i = 1, heroManager.iCount do
        local hero = heroManager:GetHero(i)
        if hero.team ~= myHero.team then
            table.insert(enemies, hero)
            elseif hero.team == myHero.team and hero.nEnemies ~= myHero.networkID then
            table.insert(allies, hero)
        end
    end
    isOrianna = false
    for i, enemy in pairs(enemies) do
        if enemy.charName == "Orianna" then
            isOrianna = true
        end
    end
    if #enemies == 5 then
        for i, skillShotChampion in pairs(champions) do
            if skillShotChampion.charName ~= enemies[1].charName and skillShotChampion.charName ~= enemies[2].charName and skillShotChampion.charName ~= enemies[3].charName
                and skillShotChampion.charName ~= enemies[4].charName and skillShotChampion.charName ~= enemies[5].charName then
                champions[i] = nil
            end
        end
    end
    
    player:RemoveCollision()
    player:SetVisionRadius(1700)
    
    GoodEvadeConfig.dodgeEnabled = true
    currentbuffer = GoodEvadeConfig.evadeBuffer
    PrintChat(versionmessage)
    if AutoUpdate then
        DelayAction(Update, 3)
    end
end

function getSideOfLine(linePoint1, linePoint2, point)
    if not point then return 0 end
    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

colstartpos = nil
colendpos = nil

function dodgeSkillshot(skillshot)
    if GoodEvadeConfig.dodgeEnabled and not myHero.dead and CastingSpell == false then
        if GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 2 or (GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 1 and nEnemies <= 2 and not (GoodEvadeConfig.dodgeCConly == skillshot.skillshot.cc or GoodEvadeConfig.dodgeCConly2 == skillshot.skillshot.cc)) then
            if skillshot.skillshot.type == "line" then
                if skillshot.skillshot.collision == "true" and VIP_USER then
                    heropos = Point2(myHero.x, myHero.z)
                    endposition = skillshot.startPosition + (skillshot.endPosition - skillshot.startPosition):normalized() * (heropos:distance(skillshot.startPosition))
                    colstartpos = Vector(skillshot.startPosition.x, myHero.y, skillshot.startPosition.y)
                    colendpos = Vector(endposition.x, myHero.y, endposition.y)
                    collisionshit = CollisionPE(skillshot.skillshot.range, skillshot.skillshot.projectileSpeed, skillshot.skillshot.spellDelay, skillshot.skillshot.radius)
                    if collisionshit:GetMinionCollision(colstartpos, colendpos) then return end
                end
                dodgeLineShot(skillshot)
            else
                dodgeCircularShot(skillshot)
            end
        end
    end
end

function dodgeCircularShot(skillshot)
    skillshot.evading = true
    alreadydodged = false
    heroPosition = Point2(myHero.x, myHero.z)
    
    moveableDistance = myHero.ms * math.max(skillshot.endTick - GetTickCount() - GetLatency()/2, 0) / 1000
    evadeRadius = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.evadeBuffer + moveBuffer
    
    safeTarget = skillshot.endPosition + (heroPosition - skillshot.endPosition):normalized() * evadeRadius

    if false and isreallydangerous(skillshot) then
        if mainCircularskillshot1(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget) then
            alreadydodged = true
        elseif dodgeDangerousCircle1(skillshot) then
            alreadydodged = true
        elseif dodgeDangerousCircle2(skillshot, safeTarget) then
            alreadydodged = true
        elseif dodgeDangerousCircle3(skillshot, safeTarget) then
            alreadydodged = true
        end
    end

    if not alreadydodged then
        if mainCircularskillshot1(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget) then
            alreadydodged = true
            elseif mainCircularskillshot2(skillshot) then
            alreadydodged = true
            elseif mainCircularskillshot3(skillshot, heroPosition) then
            alreadydodged = true
            elseif mainCircularskillshot4(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget) then
            alreadydodged = true
            elseif mainCircularskillshot5(skillshot, safeTarget) then
            alreadydodged = true
        end
    end
end

function haveShield()
    if isSivir and myHero:CanUseSpell(_E) == READY then
        return true
    elseif isNocturne and myHero:CanUseSpell(_W) == READY then
        return true
    end
    return false
end

function FlashTo(x, y)

    if GoodEvadeConfig.dashMouse then
    
        local evadePos = Point2(mousePos.x, mousePos.z)
        local myPos = Point2(myHero.x, myHero.z)
        local ourdistance = evadePos:distance(myPos)
        local dashPos = myPos - (myPos - evadePos):normalized() * 400
    
        x = dashPos.x
        y = dashPos.y
    end

    CastSpell(flashSlot, x, y)
end


function dodgeLineShot(skillshot)
    alreadydodged = false
    heroPosition = Point2(myHero.x, myHero.z)
    local evadeTo1
    local evadeTo2
    skillshot.evading = true
    skillshotLine = Line2(skillshot.startPosition, skillshot.endPosition)
    distanceFromSkillshotPath = skillshotLine:distance(heroPosition)
    evadeDistance = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.evadeBuffer + moveBuffer
    normalVector = Point2(skillshot.directionVector.y, -skillshot.directionVector.x):normalized()
    nessecaryMoveWidth = evadeDistance - distanceFromSkillshotPath
    evadeTo1 = heroPosition + normalVector * nessecaryMoveWidth
    evadeTo2 = heroPosition - normalVector * nessecaryMoveWidth
    
    if isreallydangerous(skillshot) then
        if lineSkillshot1(skillshot, heroPosition, skillshotLine, distanceFromSkillshotPath, evadeDistance, normalVector, nessecaryMoveWidth, evadeTo1, evadeTo2)
            then alreadydodged = true
        elseif dodgeDangerousLine1(skillshot) then
            alreadydodged = true
        elseif dodgeDangerousLine2(skillshot, evadeTo1, evadeTo2) then
            alreadydodged = true
        end
    end
    
    if not alreadydodged then
        if lineSkillshot1(skillshot, heroPosition, skillshotLine, distanceFromSkillshotPath, evadeDistance, normalVector, nessecaryMoveWidth, evadeTo1, evadeTo2)
            then alreadydodged = true
        elseif lineSkillshot2(skillshot)
            then alreadydodged = true
        elseif lineSkillshot3(skillshot, evadeTo1, evadeTo2)
            then alreadydodged = true
        elseif lineSkillshot4(skillshot, evadeTo1, evadeTo2)
            then alreadydodged = true
        end
    end
    
end

function _isDangerSkillshot(skillshot)
        if skillshot.skillshot.name == "LeonaZenithBlade"
        or skillshot.skillshot.name == "EnchantedArrow"
        or skillshot.skillshot.name == "LuxMaliceCannon"
        or skillshot.skillshot.name == "SejuaniR"
        or skillshot.skillshot.name == "Crescendo"
        or skillshot.skillshot.name == "TrueshotBarrage"
        or skillshot.skillshot.name == "RocketGrab"
        or skillshot.skillshot.name == "DredgeLine"
        or skillshot.skillshot.name == "ShadowDash"
        or skillshot.skillshot.name == "FizzULT"
        or skillshot.skillshot.name == "VarusR"
        or skillshot.skillshot.name == "SuperMegaDeathRocket"
        or skillshot.skillshot.name == "UFSlash"
        or skillshot.skillshot.name == "LeonaSolarFlare"
        or skillshot.skillshot.name == "AnnieR"
        or skillshot.skillshot.name == "OrianaDetonateCommand"
        then
        return true
    else
        return false
    end
end

function isreallydangerous(skillshot)
        if skillshot.skillshot.name == "UFSlash"
        or skillshot.skillshot.name == "Crescendo"
        or skillshot.skillshot.name == "FizzULT"
        or skillshot.skillshot.name == "EnchantedArrow"
        or skillshot.skillshot.name == "AnnieR"
        or skillshot.skillshot.name == "OrianaDetonateCommand"
        or skillshot.skillshot.name == "LeonaSolarFlare"
        or skillshot.skillshot.name == "VarusR"
        or skillshot.skillshot.name == "EnchantedArrow"
        or skillshot.skillshot.name == "SejuaniR"
        then return true
    else
        return false
    end
end

function InsideTheWall(evadeTestPoint)
    local heroPosition = Point2(myHero.x, myHero.z)
    local dist = evadeTestPoint:distance(heroPosition)
    local interval = 50
    local nChecks = math.ceil((dist+50)/50)
    
    if evadeTestPoint.x == 0 or evadeTestPoint.y == 0 then
        return true
    end
    for k=1, nChecks, 1 do
        local checksPos = evadeTestPoint + (evadeTestPoint - heroPosition):normalized()*(interval*k)
        if IsWall(D3DXVECTOR3(checksPos.x, myHero.y, checksPos.y)) then
            return true
        end
    end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x + 20, myHero.y, evadeTestPoint.y + 20)) then return true end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x + 20, myHero.y, evadeTestPoint.y - 20)) then return true end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x - 20, myHero.y, evadeTestPoint.y - 20)) then return true end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x - 20, myHero.y, evadeTestPoint.y + 20)) then return true end
    
    return false
end

function findBestDirection(skillshot, referencePoint, possiblePoints)
    if not skillshot then return closestPoint end
    closestPoint = nil
    closestDistance = nil
    side1 = getSideOfLine(skillshot.startPosition, skillshot.endPosition, Point2(myHero.x, myHero.z))
    for i, point in pairs(possiblePoints) do
        if point ~= nil and skillshot ~= nil then
            side2 = getSideOfLine(skillshot.startPosition, skillshot.endPosition, point)
            distToSkillshot = Line2(skillshot.startPosition, skillshot.endPosition):distance(point)
            mindistSkillshot = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.evadeBuffer
            distance = point:distance(referencePoint)
            if (closestDistance == nil or distance <= closestDistance) and not InsideTheWall(point)
                and distToSkillshot > mindistSkillshot and (side1 == side2 or side1 == 0) 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, Point2(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, Point2(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 Line2(skillshot.startPosition, skillshot.endPosition):distance(coordinate) < (skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.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 + GoodEvadeConfig.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_GeneralParticleEmmiter" then
        for i, skillShotChampion in pairs(champions) do
            for i, skillshot in pairs(skillShotChampion.skillshots) do
                if GoodEvadeSkillshotConfig[tostring(skillshot.name)] == 2 then
                    if skillshot.projectileName == object.name then
                            for i, detectedSkillshot in pairs(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
                            
                            if skillshot.type == "line" then
                                if(skillshotToAdd ~= nil) then
                                    skillshotToAdd2 = {object = object, startPosition = nil, endPosition = nil, directionVector = nil, startTick = GetTickCount(), endTick = GetTickCount() + skillshot.range/skillshot.projectileSpeed*1000, skillshot = skillshot, evading = false, drawit = true, alreadydashed = false}
                                else
                                    skillshotToAdd = {object = object, startPosition = nil, endPosition = nil, directionVector = nil, startTick = GetTickCount(), endTick = GetTickCount() + skillshot.range/skillshot.projectileSpeed*1000, skillshot = skillshot, evading = false, drawit = true, alreadydashed = false}
                                end
                                elseif skillshot.type == "circular" then
                                endPosition = Point2(object.x, object.z)
                                startPosition = Point2(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, drawit = false, alreadydashed = false})
                            end
                        end
                        return
                    end
            end
        end
    end
end
function OnAnimation(unit, animationName)
        if CastingSpell == true then
        if unit.isMe and (animationName == "Idle1" or animationName == "Run") then CastingSpell = false end
    end
end

function OnProcessSpell(unit, spell)    
        if unit.isMe and myHero.charName == "MasterYi" and spell.name == myHero:GetSpellData(_W).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Nunu" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "MissFortune" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Malzahar" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Katarina" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Janna" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Galio" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "FiddleSticks" and spell.name == myHero:GetSpellData(_W).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "FiddleSticks" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
    end
    if unit.isMe and isLeblanc then
        if spell.name == myHero:GetSpellData(_Q).name then lastspell = "Q"
            elseif spell.name == myHero:GetSpellData(_W).name then lastspell = "W"
            elseif spell.name == myHero:GetSpellData(_E).name then lastspell = "E"
        end
    end
    if not myHero.dead and unit.team ~= myHero.team then
            for i, skillShotChampion in pairs(champions) do
                if skillShotChampion.charName == unit.charName then
                    for i, skillshot in pairs(skillShotChampion.skillshots) do
                        if skillshot.spellName == spell.name then
                            startPosition = Point2(spell.startPos.x, spell.startPos.z)
                            endPosition = Point2(spell.endPos.x, spell.endPos.z)
                            if(spell.name == "xeratharcanopulse2") then
                                skillshot.range = startPosition:distance(endPosition)
                            end
                            
                            if(spell.name == "HowlingGale" and HowlingGale) then
                                skillshot.range = startPosition:distance(endPosition)
                                HowlingGale = false
                            else
                                if(spell.name == "HowlingGale")then
                                    HowlingGale = true
                                end
                            end
                            
                            if isOrianna and unit.charName == "Orianna" then
                                ball = nil
                                for i = 1, objManager.maxObjects, 1 do
                                    local obj = objManager:GetObject(i)
                                    CheckBall(obj)
                                end
                                if ball ~= nil then
                                    startPosition = Point2(ball.x, ball.z)
                                    if skillshot.spellName == "OrianaDetonateCommand" then
                                        endPosition = Point2(ball.x, ball.z)
                                    end
                                end
                            end
                            directionVector = (endPosition - startPosition):normalized()
                            if isOrianna and unit.charName == "Orianna" then
                                if skillshot.spellName == "OrianaIzunaCommand" then skillshot.range = startPosition:distance(endPosition) end
                            end

                            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, drawit = true, alreadydashed = false})
                                elseif skillshot.type == "circular" then
                                table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition,
                                directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay,
                                endTick = GetTickCount() + skillshot.spellDelay + skillshot.projectileSpeed, skillshot = skillshot, evading = false, drawit = true, alreadydashed = false})
                            else
                                local ssrange = endPosition:distance(startPosition)
                                table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition,
                                directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay,
                                endTick = GetTickCount() + skillshot.spellDelay + (skillshot.projectileSpeed * (ssrange/skillshot.range)), skillshot = skillshot, evading = false, drawit = true, alreadydashed = 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())
    side1 = getSideOfLine(coordinate, footOfPerpendicular, currentSkillshotPosition)
    side2 = getSideOfLine(coordinate, footOfPerpendicular, skillshot.startPosition)
    return side1 ~= side2 and currentSkillshotPosition:distance(footOfPerpendicular) >= (skillshot.skillshot.radius + hitboxSize / 2)
end

function getPerpendicularFootpoint(linePoint1, linePoint2, point)
    distanceFromLine = Line2(linePoint1, linePoint2):distance(point)
    directionVector = (linePoint2 - linePoint1):normalized()
    
    footOfPerpendicular = point + Point2(-directionVector.y, directionVector.x) * distanceFromLine
    if Line2(linePoint1, linePoint2):distance(footOfPerpendicular) > distanceFromLine then
        footOfPerpendicular = point - Point2(-directionVector.y, directionVector.x) * distanceFromLine
    end
    
    return footOfPerpendicular
end

function OnTick()
    if GoodEvadeConfig.freemovementblock then
        if evading and not alreadywritten then
            local file = io.open(thatfile, "w")
            file:write("1")
            file:close()
            alreadywritten = true
            elseif not evading and alreadywritten then
            local file = io.open(thatfile, "w")
            file:write("0")
            file:close()
            alreadywritten = false
        end
        if not wrotedisclaimer then
            PrintChat("<font color=\"#FF0000\" >You just enabled free user movement block, this function will only work if you followed tutorial in main thread of the script before allowing it.</font>")
            wrotedisclaimer = true
        end
    end
    if skillshotToAdd ~= nil and skillshotToAdd.object ~= nil and skillshotToAdd.object.valid and (GetTickCount() - skillshotToAdd.startTick) >= GoodEvadeConfig.fowdelay and skillshotToAdd.startPosition == nil then
            skillshotToAdd.startPosition = Point2(skillshotToAdd.object.x, skillshotToAdd.object.z)
        elseif skillshotToAdd ~= nil and skillshotToAdd.object ~= nil and skillshotToAdd.object.valid and (GetTickCount() - skillshotToAdd.startTick) >= (GoodEvadeConfig.fowdelay+1) then
            skillshotToAdd.directionVector = (Point2(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
    if skillshotToAdd2 ~= nil and skillshotToAdd2.object ~= nil and skillshotToAdd2.object.valid and (GetTickCount() - skillshotToAdd2.startTick) >= GoodEvadeConfig.fowdelay and skillshotToAdd2.startPosition == nil then
            skillshotToAdd2.startPosition = Point2(skillshotToAdd2.object.x, skillshotToAdd2.object.z)
        elseif skillshotToAdd2 ~= nil and skillshotToAdd2.object ~= nil and skillshotToAdd2.object.valid and (GetTickCount() - skillshotToAdd2.startTick) >= (GoodEvadeConfig.fowdelay+1) then
            skillshotToAdd2.directionVector = (Point2(skillshotToAdd2.object.x, skillshotToAdd2.object.z) - skillshotToAdd2.startPosition):normalized()
            skillshotToAdd2.endPosition = skillshotToAdd2.startPosition + skillshotToAdd2.directionVector * skillshotToAdd2.skillshot.range
            table.insert(detectedSkillshots, skillshotToAdd2)
            skillshotToAdd2 = nil
    end

    if shieldtick ~= nil then
        if GetTickCount() >= shieldtick then
            if haveShield() then
                if isSivir then
                    CastSpell(_E)
                elseif isNocturne then
                    CastSpell(_W)
                end
                shieldtick = nil
            end
        end
    end
    if evading then
        for i, detectedSkillshot in pairs(detectedSkillshots) do
            if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                dodgeSkillshot(detectedSkillshot)
            end
        end
    end
    if haveflash then
        if myHero:CanUseSpell(flashSlot) == READY then
            flashready = true
            else flashready = false
        end
    end
    if GoodEvadeConfig.resetdodge then
        stopEvade()
        detectedSkillshots = {}
    end
    if AutoCarry ~= nil then
        if AutoCarry.MainMenu ~= nil then
            if AutoCarry.MainMenu.AutoCarry or AutoCarry.MainMenu.LastHit or AutoCarry.MainMenu.MixedMode or AutoCarry.MainMenu.LaneClear
                then
                if not bufferset then
                    currentbuffer = GoodEvadeConfig.evadeBuffer
                    bufferset = true
                end
                if not VIP_USER then
                    if lastset < GetTickCount()
                        then lastMovement.destination = Point2(mousePos.x, mousePos.z)
                        lastset = GetTickCount() + 100
                    end
                end
            end
            elseif AutoCarry.Keys ~= nil then
            if AutoCarry.Keys.AutoCarry or AutoCarry.Keys.MixedMode or AutoCarry.Keys.LastHit or AutoCarry.Keys.LaneClear then
                if not bufferset then
                    currentbuffer = GoodEvadeConfig.evadeBuffer
                    bufferset = true
                end
                if not VIP_USER then
                    if lastset < GetTickCount()
                        then lastMovement.destination = Point2(mousePos.x, mousePos.z)
                        lastset = GetTickCount() + 100
                    end
                end
            end
        end
        elseif MMA_Loaded ~= nil then
        if _G.MMA_Orbwalker or _G.MMA_HybridMode or _G.MMA_LaneClear or _G.MMA_LastHit then
            if not bufferset then
                currentbuffer = GoodEvadeConfig.evadeBuffer
                bufferset = true
            end
            if not VIP_USER then
                if lastset < GetTickCount()
                    then lastMovement.destination = Point2(mousePos.x, mousePos.z)
                    lastset = GetTickCount() + 100
                end
            end
        end
    end
    nSkillshots = 0
    for _, detectedSkillshot in pairs(detectedSkillshots) do
        if detectedSkillshot then
            nSkillshots = nSkillshots + 1
        end
    end
    
    if not allowCustomMovement and nSkillshots == 0 then
        stopEvade()
    end
    
    hitboxSize = hitboxTable[GetMyHero().charName]
    
    if hitboxSize == nil then
        hitboxSize = 80.0
    end
    
    nEnemies = CountEnemyHeroInRange(1500)
    table.sort(enemies, function(x,y) return GetDistance(x) < GetDistance(y) end)
    
    
    heroPosition = Point2(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.skillshot.name == "BoomerangBlade" and detectedSkillshot.done ~= true) then
                directionVector = (detectedSkillshot.startPosition - detectedSkillshot.endPosition):normalized()
                newSkillshot = {startPosition = detectedSkillshot.endPosition, endPosition = detectedSkillshot.startPosition,
                                directionVector = directionVector, startTick = GetTickCount(),
                                endTick = GetTickCount() + detectedSkillshot.skillshot.range/detectedSkillshot.skillshot.projectileSpeed*1000, skillshot = detectedSkillshot.skillshot, evading = detectedSkillshot.evading, drawit = true, alreadydashed = detectedSkillshot.alreadydashed, done = true}
                
                table.insert(detectedSkillshots, newSkillshot)
            end    
            if(detectedSkillshot.skillshot.name == "AhriOrbofDeception" and detectedSkillshot.done ~= true) then
                directionVector = (detectedSkillshot.startPosition - detectedSkillshot.endPosition):normalized()
                newSkillshot = {startPosition = detectedSkillshot.endPosition, endPosition = detectedSkillshot.startPosition,
                                directionVector = directionVector, startTick = GetTickCount(),
                                endTick = GetTickCount() + detectedSkillshot.skillshot.range/detectedSkillshot.skillshot.projectileSpeed*1000, skillshot = detectedSkillshot.skillshot, evading = detectedSkillshot.evading, drawit = true, alreadydashed = detectedSkillshot.alreadydashed, done = true}
                
                table.insert(detectedSkillshots, newSkillshot)
            end    
            
            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
                        side1 = getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, heroPosition)
                        side2 = getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, getLastMovementDestination())
                        if skillshotHasPassed(detectedSkillshot, heroPosition) then
                            continueMovement(detectedSkillshot)
                            
                        elseif not inDangerousArea(detectedSkillshot, getLastMovementDestination()) and (side1 == side2) and (side1 ~= 0) then
                            continueMovement(detectedSkillshot)
                            
                        elseif not inRange(detectedSkillshot, heroPosition) and not inRange(detectedSkillshot, getLastMovementDestination()) then
                            continueMovement(detectedSkillshot)
                            
                        elseif lastMovement.approachedPoint ~= getLastMovementDestination() then
                            dodgeSkillshot(detectedSkillshot)
                        end
                    else
                        dodgeSkillshot(detectedSkillshot)
                    end
                end
            elseif inDangerousArea(detectedSkillshot, heroPosition) then
                dodgeSkillshot(detectedSkillshot)
            end
        end
    end
end

function DashTo(x, y)
    if GoodEvadeConfig.usedashes then
        
        if GoodEvadeConfig.dashMouse then
        
            local evadePos = Point2(mousePos.x, mousePos.z)
            local myPos = Point2(myHero.x, myHero.z)
            local ourdistance = evadePos:distance(myPos)
            local dashPos = myPos - (myPos - evadePos):normalized() * dashrange
        
            x = dashPos.x
            y = dashPos.y
            
        end
        
        if isVayne and myHero:CanUseSpell(_Q) == READY then
            CastSpell(_Q, x, y)
            elseif isRiven and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isGraves and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isEzreal and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isKassadin and myHero:CanUseSpell(_R) == READY then
            CastSpell(_R, x, y)
            elseif isLeblanc and myHero:CanUseSpell(_W) == READY then
            CastSpell(_W, x, y)
            elseif isLeblanc and myHero:CanUseSpell(_R) == READY and lastspell == "W" then
            CastSpell(_R, x, y)
            elseif isFizz and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isShaco and myHero:CanUseSpell(_Q) == READY then
            CastSpell(_Q, x, y)
            elseif isCorki and myHero:CanUseSpell(_W) == READY then
            CastSpell(_W, x, y)
            elseif isRenekton and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isLucian and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif haveflash and flashready and useflash and GoodEvadeConfig.useSummonerFlash then
            CastSpell(flashSlot, x, y)
            useflash = false
            elseif isCaitlyn and myHero:CanUseSpell(_E) == READY then
            myPos = Point2(myHero.x, myHero.z)
            castpos = myPos + (myPos - (Point2(x, y)))
            CastSpell(_E, castpos.x, castpos.y)
            elseif isTristana and myHero:CanUseSpell(_W) == READY then
            CastSpell(_W, x, y)
            elseif isShen and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isTryndamere and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
        end
    end
end

function NeedDash(skillshot, forceDash)
    if (GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 2 or (GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 1 and nEnemies <= 2 and not (skillshot.skillshot.cc and ((GoodEvadeConfig.dodgeCConly == skillshot.skillshot.cc or GoodEvadeConfig.dodgeCConly2 == skillshot.skillshot.cc))))) then
        if GoodEvadeConfig.usedashes then
            useflash = false
            local hp = myHero.health / myHero.maxHealth
            if isVayne and myHero:CanUseSpell(_Q) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 300
                    return true
                end
                if nSkillshots > 1 or _isDangerSkillshot(skillshot) then
                    dashrange = 300
                    return true
                end
            elseif isRiven and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 325
                return true end
                if nSkillshots > 1 or _isDangerSkillshot(skillshot) then
                    dashrange = 325
                return true end
                elseif isGraves and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 425
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 425
                return true end
                elseif isShaco and myHero:CanUseSpell(_Q) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 400
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 400
                return true end
                elseif isEzreal and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 450
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 450
                return true end
                elseif isFizz and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 400
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 400
                return true end
                elseif isKassadin and myHero:CanUseSpell(_R) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 700
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 700
                return true end
                elseif isLeblanc and myHero:CanUseSpell(_W) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 600
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 600
                return true end
                elseif isLeblanc and myHero:CanUseSpell(_R) == READY and lastspell == "W" then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 600
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 600
                return true end
                elseif isRenekton and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 450
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 450
                return true end
                elseif isCorki and myHero:CanUseSpell(_W) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 800
                end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 800
                return true end
                elseif isLucian and myHero:CanUseSpell(_E) == READY then
                    if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                        dashrange = 425
                        return true
                    end
                    if _isDangerSkillshot(skillshot) then
                        dashrange = 425
                        return true
                    end
                elseif isTryndamere and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 660
                return true end
                elseif isCaitlyn and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 400
                return true end
                elseif isTristana and myHero:CanUseSpell(_W) == READY then
                if _isDangerSkillshot(skillshot) then
                    dashrange = 900
                return true end
                elseif isShen and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 600
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 600
                return true end
                elseif GoodEvadeConfig.useSummonerFlash and haveflash and flashready and isreallydangerous(skillshot) then
                dashrange = 400
                useflash = true
                return true
            end
        end
    end
    return false
end

function evadeTo(x, y, forceDash)
    startEvade()
    evadePoint = Point2(x, y)
    allowCustomMovement = true
    captureMovements = false
    if forceDash then
        local evadePos = Point2(x, y)
        local myPos = Point2(myHero.x, myHero.z)
        local ourdistance = evadePos:distance(myPos)
        local dashPos = myPos - (myPos - evadePos):normalized() * dashrange
        DashTo(dashPos.x, dashPos.y)
    else
        myHero:MoveTo(x, y)
    end
    lastMovement.moveCommand = Point2(x, y)
    captureMovements = true
    allowCustomMovement = false
    evading = true
    evadingTick = GetTickCount()
end

function continueMovement(skillshot)
        if VIP_USER then
        if evading then
            skillshot.evading = false
            lastMovement.approachedPoint = nil
            
            stopEvade()
            
            if lastMovement.type == 2 then
                captureMovements = false
                myHero:MoveTo(getLastMovementDestination().x, getLastMovementDestination().y)
                captureMovements = true
            elseif lastMovement.type == 3 then
                target = getTarget(lastMovement.targetId)
                
                if _isValidTarget(target) 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
                lastMovement.type = 3
            end
        end
        elseif evading then
        skillshot.evading = false
        lastMovement.approachedPoint = nil
        stopEvade()
        if continuetarget == nil then
            captureMovements = false
            myHero:MoveTo(getLastMovementDestination().x, getLastMovementDestination().y)
            captureMovements = true
            elseif continuetarget ~= nil then
            target = continuetarget
            if _isValidTarget(target) then
                captureMovements = false
                myHero:Attack(target)
                captureMovements = true
            else
                captureMovements = false
                myHero:MoveTo(myHero.x, myHero.z)
                captureMovements = true
            end
        end
    end
end

function GetAngleOfLineBetweenTwoPoints(p1, p2)
     local xDiff = p2.x - p1.x
     local yDiff = p2.y - p1.y
     return math.atan2(yDiff, xDiff)
end

function drawLineshit(point1, point2, color, width1, skillshot)

    if(GoodEvadeConfig["oldDrawing"])then
        apoint = WorldToScreen(D3DXVECTOR3(point1.x, 0, point1.y))
        bpoint = WorldToScreen(D3DXVECTOR3(point2.x, 0, point2.y))
        
        DrawLine(apoint.x, apoint.y, bpoint.x, bpoint.y, width1, color)
    else
        
        local Height = skillshot.skillshot.radius * 2
        local Width = skillshot.skillshot.range
        
        A = GetAngleOfLineBetweenTwoPoints(point1, point2)
        
        x = math.floor((point2.x + point1.x) / 2)
        y = math.floor((point2.y + point1.y) / 2)

        UL = Point2((math.cos(A) * ((x + Width / 2) - x)) - (math.sin(A) * ((y + Height / 2) - y)) + x, (math.cos(A) * ((y + Height / 2) - y)) + (math.sin(A) * ((x + Width / 2) - x)) + y)
        UR = Point2((math.cos(A) * ((x - Width / 2) - x)) - (math.sin(A) * ((y + Height / 2) - y)) + x, (math.cos(A) * ((y + Height / 2) - y)) + (math.sin(A) * ((x - Width / 2) - x)) + y)
        BL = Point2((math.cos(A) * ((x + Width / 2) - x)) - (math.sin(A) * ((y - Height / 2) - y)) + x, (math.cos(A) * ((y - Height / 2) - y)) + (math.sin(A) * ((x + Width / 2) - x)) + y)
        BR = Point2((math.cos(A) * ((x - Width / 2) - x)) - (math.sin(A) * ((y - Height / 2) - y)) + x, (math.cos(A) * ((y - Height / 2) - y)) + (math.sin(A) * ((x - Width / 2) - x)) + y)
    
        UL2 = WorldToScreen(D3DXVECTOR3(UL.x, -175, UL.y))
        UR2 = WorldToScreen(D3DXVECTOR3(UR.x, -175, UR.y))
        BL2 = WorldToScreen(D3DXVECTOR3(BL.x, -175, BL.y))
        BR2 = WorldToScreen(D3DXVECTOR3(BR.x, -175, BR.y))
        
        DrawLine(UL2.x, UL2.y, UR2.x, UR2.y, 1, 0xFFFF0000)
        DrawLine(UL2.x, UL2.y, BL2.x, BL2.y, 1, 0xFFFF0000)
        DrawLine(BR2.x, BR2.y, UR2.x, UR2.y, 1, 0xFFFF0000)
        DrawLine(BR2.x, BR2.y, BL2.x, BL2.y, 1, 0xFFFF0000)
        
        
    end
end

function OnDraw()
    if GoodEvadeConfig.drawEnabled then
        DrawCircle(GetMyHero().x, GetMyHero().y, GetMyHero().z, hitboxSize, 0xFFFFFF)
        for i, detectedSkillshot in pairs(detectedSkillshots) do
            skillshotPos = skillshotPosition(detectedSkillshot, GetTickCount())
            if detectedSkillshot.drawit == true then
                if detectedSkillshot.skillshot.type == "line" then
                    drawLineshit(detectedSkillshot.startPosition, detectedSkillshot.endPosition, 0xFFFF0000, 3, detectedSkillshot)
                    DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0xFFFFFF)
                else
                    DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0x00FF00)
                end
            end
        end
    end
end

function _isValidTarget(target)
    return target ~= nil and target.valid and target.dead == false and target.bTargetable and target.bMagicImunebMagicImune ~= true and target.bInvulnerable ~= true and target.visible
end

function startEvade()
    allowCustomMovement = false
    if AutoCarry
        then if AutoCarry.MainMenu ~= nil then
            if AutoCarry.CanAttack ~= nil then
                _G.AutoCarry.CanAttack = false
                _G.AutoCarry.CanMove = false
            end
            elseif AutoCarry.Keys ~= nil then
            if AutoCarry.MyHero ~= nil then
                _G.AutoCarry.MyHero:MovementEnabled(false)
                _G.AutoCarry.MyHero:AttacksEnabled(false)
            end
        end
        elseif MMA_Loaded then
        _G.MMA_AttackAvailable = false
        _G.MMA_AbleToMove = false
    end
    _G.evade = true
    evading = true
end

function stopEvade()
    allowCustomMovement = true
    if AutoCarry then if AutoCarry.MainMenu ~= nil then
            if AutoCarry.CanAttack ~= nil then
                _G.AutoCarry.CanAttack = true
                _G.AutoCarry.CanMove = true
            end
            elseif AutoCarry.Keys ~= nil then
            if AutoCarry.MyHero ~= nil then
                _G.AutoCarry.MyHero:MovementEnabled(true)
                _G.AutoCarry.MyHero:AttacksEnabled(true)
            end
        end
        elseif MMA_Loaded then
        _G.MMA_AttackAvailable = true
        _G.MMA_AbleToMove = true
    end
    _G.evade = false
    evading = false
end

function OnWndMsg(msg, key)
        if not VIP_USER then
        if msg == WM_RBUTTONDOWN then
            if evading then
                for i, detectedSkillshot in pairs(detectedSkillshots) do
                    if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                        dodgeSkillshot(detectedSkillshot)
                    end
                end
            end
            lastMovement.destination = Point2(mousePos.x, mousePos.z)
        end
    end
end
-- beggining of circular skillshot dodging functions --
function mainCircularskillshot5(skillshot, safeTarget)
        if NeedDash(skillshot, true) and not skillshot.alreadydashed then
        evadeTo(safeTarget.x, safeTarget.y, true)
        skillshot.alreadydashed = true
        return true
        else return false
    end
    return false
end

function mainCircularskillshot4(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget)
        if NeedDash(skillshot, true) and not skillshot.alreadydashed then
        moveableDistance = (myHero.ms * math.max(skillshot.endTick - GetTickCount() - GetLatency()/2, 0) / 1000) + dashrange
        evadeRadius = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.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 = Line2(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 = Circle2(skillshot.endPosition, evadeRadius):intersectionPoints(Circle2(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 = findBestDirection(skillshot, getLastMovementDestination(), possibleMovementTargets)
        if closestPoint ~= nil then
            closestPoint = closestPoint + (closestPoint - heroPosition):normalized() * smoothing
            evadeTo(closestPoint.x, closestPoint.y, true)
            skillshot.alreadydashed = true
            return true
            else return false
        end
        else return false
    end
    return false
end

function mainCircularskillshot3(skillshot, heroPosition)
        if getLastMovementDestination():distance(heroPosition) > 20 and NeedDash(skillshot, true) and not skillshot.alreadydashed then
        dashpos = getLastMovementDestination() + (getLastMovementDestination() - heroPosition):normalized() * dashrange
        if dashpos:distance(skillshot.endPosition) > skillshot.skillshot.radius and not InsideTheWall(dashpos) then
            evadeTo(dashpos.x, dashpos.y, true)
            skillshot.alreadydashed = true
            return true
            else return false
        end
        else return false
    end
    return false
end

function mainCircularskillshot2(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if skillshot.skillshot.shieldnow == "true" then
            if isSivir then
                CastSpell(_E)
                elseif isNocturne then
                CastSpell(_W)
            end
            return true
            elseif skillshot.skillshot.shieldnow == "false" then
            shieldtick = skillshot.endTick - 50 - GetLatency()
            return true
        end
        else return false
    end
    return false
end

function mainCircularskillshot1(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget)
    if getLastMovementDestination():distance(skillshot.endPosition) <= evadeRadius then
        closestTarget = skillshot.endPosition + (getLastMovementDestination() - skillshot.endPosition):normalized() * evadeRadius
    else
        closestTarget = nil
    end
    
    lineDistance = Line2(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 = Circle2(skillshot.endPosition, evadeRadius):intersectionPoints(Circle2(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 = findBestDirection(skillshot, getLastMovementDestination(), possibleMovementTargets)
    if closestPoint ~= nil then
        closestPoint = closestPoint + (closestPoint - heroPosition):normalized() * smoothing
        evadeTo(closestPoint.x, closestPoint.y)
        return true
        else return false
    end
    return false
end

function dodgeDangerousCircle1(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if isSivir then
            CastSpell(_E)
            elseif isNocturne then
            CastSpell(_W)
        end
        return true
        else return false
    end
    return false
end

function dodgeDangerousCircle2(skillshot, safeTarget)

    if NeedDash(skillshot, true) and getLastMovementDestination():distance(safeTarget) > 20 and not skillshot.alreadydashed then
        
        if safeTarget:distance(skillshot.endPosition) > skillshot.skillshot.radius and not InsideTheWall(safeTarget) then
            local evadePos = safeTarget
            local myPos = Point2(myHero.x, myHero.z)
            local ourdistance = evadePos:distance(myPos)
            local dashPos = myPos - (myPos - evadePos):normalized() * dashrange
            DashTo(dashPos.x, dashPos.y)
            skillshot.alreadydashed = true
            for i, detectedSkillshot in ipairs(detectedSkillshots) do
                if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                    table.remove(detectedSkillshots, i)
                    i = i-1
                    if detectedSkillshot.evading then
                        continueMovement(detectedSkillshot)
                    end
                end
            end
            return true
        else
            return false
        end else
            return false
    end
    
    return false
end

function dodgeDangerousCircle3(skillshot, safeTarget)
        if GoodEvadeConfig.useSummonerFlash and flashready and not skillshot.alreadydashed then
        FlashTo(safeTarget.x, safeTarget.y)
        skillshot.alreadydashed = true
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        return true
        else return false
    end
    return false
end


-- end of circular skillshot dodging functions --
-- beggining of line skillshot dodging functions --
function lineSkillshot1(skillshot, heroPosition, skillshotLine, distanceFromSkillshotPath, evadeDistance, normalVector, nessecaryMoveWidth, evadeTo1, evadeTo2)
    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(skillshot,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 (evadeToTarget1 ~= nil and evadeToTarget3 ~= nil and Line2(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 Line2(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 Line2(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 Line2(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(skillshot,getLastMovementDestination(), possibleMovementTargets)
    end
    
    if evadeTarget 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)
        return true
        else return false
    end
    return false
end

function lineSkillshot2(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if isSivir then
            CastSpell(_E)
            elseif isNocturne then
            CastSpell(_W)
        end
        return true
        else return false
    end
    return false
end

function lineSkillshot3(skillshot, evadeTo1, evadeTo2)
        if not skillshot.alreadydashed then
        local safeTarget = nil
        if NeedDash(skillshot, true)
            then if (evadeTo1:distance(lastMovement.destination) > evadeTo2:distance(lastMovement.destination)) and not InsideTheWall(evadeTo2) then
                safeTarget = evadeTo2
                elseif (evadeTo2:distance(lastMovement.destination) > evadeTo1:distance(lastMovement.destination)) and not InsideTheWall(evadeTo1) then
                safeTarget = evadeTo1
                elseif InsideTheWall(evadeTo2) then
                safeTarget = evadeTo1
                elseif InsideTheWall(evadeTo1) then
                safeTarget = evadeTo2
            end
            if safeTarget ~= nil then
                evadeTo(safeTarget.x, safeTarget.y, true)
                skillshot.alreadydashed = true
                return true
                else return false
            end
            else return false
        end
        else return false
    end
    return false
end

function lineSkillshot4(skillshot, evadeTo1, evadeTo2)
        if GoodEvadeConfig.lineallways then
        if skillshotLine:distance(evadeTo1) >= skillshotLine:distance(evadeTo2) then
            if not InsideTheWall(evadeTo1) then
                safeTarget = evadeTo1
                elseif not InsideTheWall(evadeTo2) then
                safeTarget = evadeTo2
            else
                safeTarget = getLastMovementDestination()
            end
            
        else
            if not InsideTheWall(evadeTo2) then
                safeTarget = evadeTo2
                elseif not InsideTheWall(evadeTo1) then
                safeTarget = evadeTo1
            else
                safeTarget = getLastMovementDestination()
            end
        end
        
        if safeTarget ~= nil then
            evadeTo(safeTarget.x, safeTarget.y)
            return true
            else return false
        end
        else return false
    end
    return false
end

function dodgeDangerousLine1(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if isSivir then
            CastSpell(_E)
        elseif isNocturne then
            CastSpell(_W)
        end
        return true
        else return false
    end
    return false
end

function dodgeDangerousLine2(skillshot, evadeTo1, evadeTo2)
    local safeTarget = nil
    if haveflash and useflash and GoodEvadeConfig.useSummonerFlash and not skillshot.alreadydashed
        then if (evadeTo1:distance(lastMovement.destination) > evadeTo2:distance(lastMovement.destination)) and not InsideTheWall(evadeTo2) then
            safeTarget = evadeTo2
            elseif (evadeTo2:distance(lastMovement.destination) > evadeTo1:distance(lastMovement.destination)) and not InsideTheWall(evadeTo1) then
            safeTarget = evadeTo1
            elseif InsideTheWall(evadeTo2) then
            safeTarget = evadeTo1
            elseif InsideTheWall(evadeTo1) then
            safeTarget = evadeTo2
        end
        if safeTarget ~= nil then
            FlashTo(safeTarget.x, safeTarget.y)
            skillshot.alreadydashed = true
            return true
            else return false
        end
        else return false
    end
    return false
end
-- end of line skillshot dodging functions --

 

 

Opublikowano

 

 

local version = "9"

require "old2dgeo"

class 'CollisionPE'
HERO_ALL = 1
HERO_ENEMY = 2
HERO_ALLY = 3


function CollisionPE:__init(sRange, projSpeed, sDelay, sWidth)
    uniqueId = uniqueId + 1
    self.uniqueId = uniqueId
    
    self.sRange = sRange
    self.projSpeed = projSpeed
    self.sDelay = sDelay
    self.sWidth = sWidth/2
    
    self.enemyMinions = minionManager(MINION_ALLY, 2000, myHero, MINION_SORT_HEALTH_ASC)
    self.minionupdate = 0
end

function CollisionPE:GetMinionCollision(pStart, pEnd)
    self.enemyMinions:update()
    
    local distance = GetDistance(pStart, pEnd)
    local prediction = TargetPredictionVIP(self.sRange, self.projSpeed, self.sDelay, self.sWidth)
    local mCollision = {}
    
    if distance > self.sRange then
        distance = self.sRange
    end
    
    local V = Vector(pEnd) - Vector(pStart)
    local k = V:normalized()
    local P = V:perpendicular2():normalized()
    
    local t,i,u = k:unpack()
    local x,y,z = P:unpack()
    
    local startLeftX = pStart.x + (x *self.sWidth)
    local startLeftY = pStart.y + (y *self.sWidth)
    local startLeftZ = pStart.z + (z *self.sWidth)
    local endLeftX = pStart.x + (x * self.sWidth) + (t * distance)
    local endLeftY = pStart.y + (y * self.sWidth) + (i * distance)
    local endLeftZ = pStart.z + (z * self.sWidth) + (u * distance)
    
    local startRightX = pStart.x - (x * self.sWidth)
    local startRightY = pStart.y - (y * self.sWidth)
    local startRightZ = pStart.z - (z * self.sWidth)
    local endRightX = pStart.x - (x * self.sWidth) + (t * distance)
    local endRightY = pStart.y - (y * self.sWidth) + (i * distance)
    local endRightZ = pStart.z - (z * self.sWidth)+ (u * distance)
    
    local startLeft = WorldToScreen(D3DXVECTOR3(startLeftX, startLeftY, startLeftZ))
    local endLeft = WorldToScreen(D3DXVECTOR3(endLeftX, endLeftY, endLeftZ))
    local startRight = WorldToScreen(D3DXVECTOR3(startRightX, startRightY, startRightZ))
    local endRight = WorldToScreen(D3DXVECTOR3(endRightX, endRightY, endRightZ))
    
    local poly = Polygon(Point(startLeft.x, startLeft.y), Point(endLeft.x, endLeft.y), Point(startRight.x, startRight.y), Point(endRight.x, endRight.y))
    
    for index, minion in pairs(self.enemyMinions.objects) do
        if minion ~= nil and minion.valid and not minion.dead then
            if GetDistance(pStart, minion) < distance then
                local pos, t, vec = prediction:GetPrediction(minion)
                local lineSegmentLeft = LineSegment(Point(startLeftX,startLeftZ), Point(endLeftX, endLeftZ))
                local lineSegmentRight = LineSegment(Point(startRightX,startRightZ), Point(endRightX, endRightZ))
                local toScreen, toPoint
                if pos ~= nil then
                    toScreen = WorldToScreen(D3DXVECTOR3(minion.x, minion.y, minion.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                else
                    toScreen = WorldToScreen(D3DXVECTOR3(minion.x, minion.y, minion.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                end
                
                
                if poly:contains(toPoint) then
                    table.insert(mCollision, minion)
                else
                    if pos ~= nil then
                        distance1 = Point(pos.x, pos.z):distance(lineSegmentLeft)
                        distance2 = Point(pos.x, pos.z):distance(lineSegmentRight)
                    else
                        distance1 = Point(minion.x, minion.z):distance(lineSegmentLeft)
                        distance2 = Point(minion.x, minion.z):distance(lineSegmentRight)
                    end
                    if (distance1 < (getHitBoxRadius(minion)*2+10) or distance2 < (getHitBoxRadius(minion) *2+10)) then
                        table.insert(mCollision, minion)
                    end
                end
            end
        end
    end
    if #mCollision > 0 then return true, mCollision else return false, mCollision end
end

function CollisionPE:GetHeroCollision(pStart, pEnd, mode)
    if mode == nil then mode = HERO_ENEMY end
    local heros = {}
    
    for i = 1, heroManager.iCount do
        local hero = heroManager:GetHero(i)
        if (mode == HERO_ENEMY or mode == HERO_ALL) and hero.team ~= myHero.team then
            table.insert(heros, hero)
            elseif (mode == HERO_ALLY or mode == HERO_ALL) and hero.team == myHero.team and not hero.isMe then
            table.insert(heros, hero)
        end
    end
    
    local distance = GetDistance(pStart, pEnd)
    local prediction = TargetPredictionVIP(self.sRange, self.projSpeed, self.sDelay, self.sWidth)
    local hCollision = {}
    
    if distance > self.sRange then
        distance = self.sRange
    end
    
    local V = Vector(pEnd) - Vector(pStart)
    local k = V:normalized()
    local P = V:perpendicular2():normalized()
    
    local t,i,u = k:unpack()
    local x,y,z = P:unpack()
    
    local startLeftX = pStart.x + (x *self.sWidth)
    local startLeftY = pStart.y + (y *self.sWidth)
    local startLeftZ = pStart.z + (z *self.sWidth)
    local endLeftX = pStart.x + (x * self.sWidth) + (t * distance)
    local endLeftY = pStart.y + (y * self.sWidth) + (i * distance)
    local endLeftZ = pStart.z + (z * self.sWidth) + (u * distance)
    
    local startRightX = pStart.x - (x * self.sWidth)
    local startRightY = pStart.y - (y * self.sWidth)
    local startRightZ = pStart.z - (z * self.sWidth)
    local endRightX = pStart.x - (x * self.sWidth) + (t * distance)
    local endRightY = pStart.y - (y * self.sWidth) + (i * distance)
    local endRightZ = pStart.z - (z * self.sWidth)+ (u * distance)
    
    local startLeft = WorldToScreen(D3DXVECTOR3(startLeftX, startLeftY, startLeftZ))
    local endLeft = WorldToScreen(D3DXVECTOR3(endLeftX, endLeftY, endLeftZ))
    local startRight = WorldToScreen(D3DXVECTOR3(startRightX, startRightY, startRightZ))
    local endRight = WorldToScreen(D3DXVECTOR3(endRightX, endRightY, endRightZ))
    
    local poly = Polygon(Point(startLeft.x, startLeft.y), Point(endLeft.x, endLeft.y), Point(startRight.x, startRight.y), Point(endRight.x, endRight.y))
    
    for index, hero in pairs(heros) do
        if hero ~= nil and hero.valid and not hero.dead then
            if GetDistance(pStart, hero) < distance then
                local pos, t, vec = prediction:GetPrediction(hero)
                local lineSegmentLeft = LineSegment(Point(startLeftX,startLeftZ), Point(endLeftX, endLeftZ))
                local lineSegmentRight = LineSegment(Point(startRightX,startRightZ), Point(endRightX, endRightZ))
                local toScreen, toPoint
                if pos ~= nil then
                    toScreen = WorldToScreen(D3DXVECTOR3(pos.x, hero.y, pos.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                else
                    toScreen = WorldToScreen(D3DXVECTOR3(hero.x, hero.y, hero.z))
                    toPoint = Point(toScreen.x, toScreen.y)
                end
                
                
                if poly:contains(toPoint) then
                    table.insert(hCollision, hero)
                else
                    if pos ~= nil then
                        distance1 = Point(pos.x, pos.z):distance(lineSegmentLeft)
                        distance2 = Point(pos.x, pos.z):distance(lineSegmentRight)
                    else
                        distance1 = Point(hero.x, hero.z):distance(lineSegmentLeft)
                        distance2 = Point(hero.x, hero.z):distance(lineSegmentRight)
                    end
                    if (distance1 < (getHitBoxRadius(hero)*2+10) or distance2 < (getHitBoxRadius(hero) *2+10)) then
                        table.insert(hCollision, hero)
                    end
                end
            end
        end
    end
    if #hCollision > 0 then return true, hCollision else return false, hCollision end
end

function CollisionPE:GetCollision(pStart, pEnd)
    local b , minions = self:GetMinionCollision(pStart, pEnd)
    local t , heros = self:GetHeroCollision(pStart, pEnd, HERO_ENEMY)
    
    if not b then return t, heros end
    if not t then return b, minions end
    
    local all = {}
    
    for index, hero in pairs(heros) do
        table.insert(all, hero)
    end
    
    for index, minion in pairs(minions) do
        table.insert(all, minion)
    end
    
    return true, all
end


function getHitBoxRadius(target)
    return GetDistance(target, target.minBBox)/2
end

_G.evade = false
moveBuffer = 25
smoothing = 75
dashrange = 0


champions = {}
champions2 = {
["Lux"] = {charName = "Lux", skillshots = {
["Light Binding"] = {name = "LightBinding", spellName = "LuxLightBinding", spellDelay = 250, projectileName = "LuxLightBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["Lux LightStrike Kugel"] = {name = "LuxLightStrikeKugel", spellName = "LuxLightStrikeKugel", spellDelay = 250, projectileName = "LuxLightstrike_mis.troy", projectileSpeed = 1400, range = 1100, radius = 275, type = "circle", cc = "false", collision = "false", shieldnow = "false"},
["Lux Malice Cannon"] = {name = "LuxMaliceCannon", spellName = "LuxMaliceCannon", spellDelay = 1375, projectileName = "LuxMaliceCannon_cas.troy", projectileSpeed = 50000, range = 3500, radius = 190, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Nidalee"] = {charName = "Nidalee", skillshots = {
["Javelin Toss"] = {name = "JavelinToss", spellName = "JavelinToss", spellDelay = 125, projectileName = "nidalee_javelinToss_mis.troy", projectileSpeed = 1300, range = 1500, radius = 60, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Kennen"] = {charName = "Kennen", skillshots = {
["Thundering Shuriken"] = {name = "ThunderingShuriken", spellName = "KennenShurikenHurlMissile1", spellDelay = 180, projectileName = "kennen_ts_mis.troy", projectileSpeed = 1700, range = 1050, radius = 50, type = "line", cc = "false", collision = "true", shieldnow = "true"}
}},
["Amumu"] = {charName = "Amumu", skillshots = {
["Bandage Toss"] = {name = "BandageToss", spellName = "BandageToss", spellDelay = 250, projectileName = "Bandage_beam.troy", projectileSpeed = 2000, range = 1100, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Lee Sin"] = {charName = "LeeSin", skillshots = {
["Sonic Wave"] = {name = "SonicWave", spellName = "BlindMonkQOne", spellDelay = 250, projectileName = "blindMonk_Q_mis_01.troy", projectileSpeed = 1800, range = 1100, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Morgana"] = {charName = "Morgana", skillshots = {
["Dark Binding Missile"] = {name = "DarkBinding", spellName = "DarkBindingMissile", spellDelay = 250, projectileName = "DarkBinding_mis.troy", projectileSpeed = 1200, range = 1300, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Sejuani"] = {charName = "Sejuani", skillshots = {
["SejuaniR"] = {name = "SejuaniR", spellName = "SejuaniGlacialPrisonCast", spellDelay = 250, projectileName = "Sejuani_R_mis.troy", projectileSpeed = 1600, range = 1200, radius = 110, type="line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Sona"] = {charName = "Sona", skillshots = {
["Crescendo"] = {name = "Crescendo", spellName = "SonaCrescendo", spellDelay = 240, projectileName = "SonaCrescendo_mis.troy", projectileSpeed = 2400, range = 1000, radius = 160, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Gragas"] = {charName = "Gragas", skillshots = {
["Barrel Roll"] = {name = "BarrelRoll", spellName = "GragasBarrelRoll", spellDelay = 250, projectileName = "gragas_barrelroll_mis.troy", projectileSpeed = 1000, range = 1115, radius = 180, type = "circle", cc = "false", collision = "false", shieldnow = "false"},
["Barrel Roll Missile"] = {name = "BarrelRollMissile", spellName = "GragasBarrelRollMissile", spellDelay = 0, projectileName = "gragas_barrelroll_mis.troy", projectileSpeed = 1000, range = 1115, radius = 180, type = "circle", cc = "false", collision = "false", shieldnow = "false"},
}},
["Syndra"] = {charName = "Syndra", skillshots = {
["Q"] = {name = "Q", spellName = "SyndraQ", spellDelay = 250, projectileName = "Syndra_Q_fall.troy", projectileSpeed = 500, range = 825, radius = 175, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
["W"] = {name = "W", spellName = "syndrawcast", spellDelay = 250, projectileName = "Syndra_W_fall.troy", projectileSpeed = 500, range = 950, radius = 200, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
}},
["Malphite"] = {charName = "Malphite", skillshots = {
["UFSlash"] = {name = "UFSlash", spellName = "UFSlash", spellDelay = 0, projectileName = "UnstoppableForce_cas.troy", projectileSpeed = 550, range = 1000, radius = 300, type="circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Ezreal"] = {charName = "Ezreal", skillshots = {
["Mystic Shot"] = {name = "MysticShot", spellName = "EzrealMysticShot", spellDelay = 250, projectileName = "Ezreal_mysticshot_mis.troy", projectileSpeed = 2000, range = 1200, radius = 80, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["Essence Flux"] = {name = "EssenceFlux", spellName = "EzrealEssenceFlux", spellDelay = 250, projectileName = "Ezreal_essenceflux_mis.troy", projectileSpeed = 1500, range = 1050, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Mystic Shot (Pulsefire)"] = {name = "MysticShot", spellName = "EzrealMysticShotPulse", spellDelay = 250, projectileName = "Ezreal_mysticshot_mis.troy", projectileSpeed = 2000, range = 1200, radius = 80, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["Trueshot Barrage"] = {name = "TrueshotBarrage", spellName = "EzrealTrueshotBarrage", spellDelay = 1000, projectileName = "Ezreal_TrueShot_mis.troy", projectileSpeed = 2000, range = 20000, radius = 160, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Ahri"] = {charName = "Ahri", skillshots = {
["Orb of Deception"] = {name = "OrbofDeception", spellName = "AhriOrbofDeception", spellDelay = 250, projectileName = "Ahri_Orb_mis.troy", projectileSpeed = 2500, range = 900, radius = 100, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Orb of Deception Back"] = {name = "OrbofDeceptionBack", spellName = "AhriOrbofDeceptionherpityderp", spellDelay = 250+360, projectileName = "Ahri_Orb_mis_02.troy", projectileSpeed = 915, range = 900, radius = 100, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Charm"] = {name = "Charm", spellName = "AhriSeduce", spellDelay = 250, projectileName = "Ahri_Charm_mis.troy", projectileSpeed = 1000, range = 1000, radius = 60, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Olaf"] = {charName = "Olaf", skillshots = {
["Undertow"] = {name = "Undertow", spellName = "OlafAxeThrow", spellDelay = 250, projectileName = "olaf_axe_mis.troy", projectileSpeed = 1600, range = 1000, radius = 90, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Leona"] = {charName = "Leona", skillshots = {
["Zenith Blade"] = {name = "LeonaZenithBlade", spellName = "LeonaZenithBlade", spellDelay = 250, projectileName = "Leona_ZenithBlade_mis.troy", projectileSpeed = 2000, range = 950, radius = 110, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["Leona Solar Flare"] = {name = "LeonaSolarFlare", spellName = "LeonaSolarFlare", spellDelay = 250, projectileName = "Leona_SolarFlare_cas.troy", projectileSpeed = 1500, range = 1200, radius = 300, type = "circular", cc = "true", collision = "false", shieldnow = "true"}
}},
["Karthus"] = {charName = "Karthus", skillshots = {
["Lay Waste"] = {name = "LayWaste", spellName = "LayWaste", spellDelay = 250, projectileName = "LayWaste_point.troy", projectileSpeed = 1750, range = 875, radius = 140, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Chogath"] = {charName = "Chogath", skillshots = {
["Rupture"] = {name = "Rupture", spellName = "Rupture", spellDelay = 0, projectileName = "rupture_cas_01_red_team.troy", projectileSpeed = 950, range = 950, radius = 250, type = "circular", cc = "true", collision = "false", shieldnow = "true"}
}},
["Blitzcrank"] = {charName = "Blitzcrank", skillshots = {
["Rocket Grab"] = {name = "RocketGrab", spellName = "RocketGrabMissile", spellDelay = 250, projectileName = "FistGrab_mis.troy", projectileSpeed = 1800, range = 1050, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Anivia"] = {charName = "Anivia", skillshots = {
["Flash Frost"] = {name = "FlashFrost", spellName = "FlashFrostSpell", spellDelay = 250, projectileName = "cryo_FlashFrost_mis.troy", projectileSpeed = 850, range = 1100, radius = 110, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Zyra"] = {charName = "Zyra", skillshots = {
["Grasping Roots"] = {name = "GraspingRoots", spellName = "ZyraGraspingRoots", spellDelay = 250, projectileName = "Zyra_E_sequence_impact.troy", projectileSpeed = 1150, range = 1150, radius = 70, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["Zyra Passive Death"] = {name = "ZyraPassive", spellName = "zyrapassivedeathmanager", spellDelay = 500, projectileName = "zyra_passive_plant_mis.troy", projectileSpeed = 2000, range = 1474, radius = 60, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Deadly Bloom"] = {name = "DeadlyBloom", spellName = "ZyraQFissure", spellDelay = 1000, projectileName = "Zyra_Q_cas.troy", projectileSpeed = 0, range = 800, radius = 250, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Nautilus"] = {charName = "Nautilus", skillshots = {
["Dredge Line"] = {name = "DredgeLine", spellName = "NautilusAnchorDrag", spellDelay = 250, projectileName = "Nautilus_Q_mis.troy", projectileSpeed = 2000, range = 1080, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Caitlyn"] = {charName = "Caitlyn", skillshots = {
["Piltover Peacemaker"] = {name = "PiltoverPeacemaker", spellName = "CaitlynPiltoverPeacemaker", spellDelay = 625, projectileName = "caitlyn_Q_mis.troy", projectileSpeed = 2200, range = 1300, radius = 90, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Caitlyn Entrapment"] = {name = "CaitlynEntrapment", spellName = "CaitlynEntrapment", spellDelay = 150, projectileName = "caitlyn_entrapment_mis.troy", projectileSpeed = 2000, range = 950, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Mundo"] = {charName = "DrMundo", skillshots = {
["Infected Cleaver"] = {name = "InfectedCleaver", spellName = "InfectedCleaverMissile", spellDelay = 250, projectileName = "dr_mundo_infected_cleaver_mis.troy", projectileSpeed = 2000, range = 1050, radius = 75, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Brand"] = {charName = "Brand", skillshots = {
["BrandBlaze"] = {name = "BrandBlaze", spellName = "BrandBlaze", spellDelay = 250, projectileName = "BrandBlaze_mis.troy", projectileSpeed = 1600, range = 1100, radius = 80, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Pillar of Flame"] = {name = "PillarofFlame", spellName = "BrandFissure", spellDelay = 250, projectileName = "BrandPOF_tar_green.troy", projectileSpeed = 900, range = 1100, radius = 240, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Corki"] = {charName = "Corki", skillshots = {
["Missile Barrage"] = {name = "MissileBarrage", spellName = "MissileBarrage", spellDelay = 250, projectileName = "corki_MissleBarrage_mis.troy", projectileSpeed = 2000, range = 1300, radius = 40, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["Missile Barrage big"] = {name = "MissileBarragebig", spellName = "MissileBarrage!", spellDelay = 250, projectileName = "Corki_MissleBarrage_DD_mis.troy", projectileSpeed = 2000, range = 1300, radius = 40, type = "line", cc = "false", collision = "true", shieldnow = "true"}
}},
["TwistedFate"] = {charName = "TwistedFate", skillshots = {
["Loaded Dice"] = {name = "LoadedDice", spellName = "WildCards", spellDelay = 250, projectileName = "Roulette_mis.troy", projectileSpeed = 1000, range = 1450, radius = 40, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["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 = "true", collision = "false", shieldnow = "true"}
}},
["Cassiopeia"] = {charName = "Cassiopeia", skillshots = {
["Noxious Blast"] = {name = "NoxiousBlast", spellName = "CassiopeiaNoxiousBlast", spellDelay = 250, projectileName = "CassNoxiousSnakePlane_green.troy", projectileSpeed = 500, range = 850, radius = 130, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
}},
["Sivir"] = {charName = "Sivir", skillshots = {
["Boomerang Blade"] = {name = "BoomerangBlade", spellName = "SivirQ", spellDelay = 250, projectileName = "Sivir_Base_Q_mis.troy", projectileSpeed = 1350, range = 1150, radius = 101, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Ashe"] = {charName = "Ashe", skillshots = {
["Enchanted Arrow"] = {name = "EnchantedArrow", spellName = "EnchantedCrystalArrow", spellDelay = 250, projectileName = "Ashe_Base_R_mis.troy", projectileSpeed = 1600, range = 25000, radius = 120, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["KogMaw"] = {charName = "KogMaw", skillshots = {
["Living Artillery"] = {name = "LivingArtillery", spellName = "KogMawLivingArtillery", spellDelay = 250, projectileName = "KogMawLivingArtillery_mis.troy", projectileSpeed = 1050, range = 2200, radius = 225, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Khazix"] = {charName = "Khazix", skillshots = {
["KhazixW"] = {name = "KhazixW", spellName = "KhazixW", spellDelay = 250, projectileName = "Khazix_W_mis_enhanced.troy", projectileSpeed = 1700, range = 1025, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["khazixwlong"] = {name = "khazixwlong", spellName = "khazixwlong", spellDelay = 250, projectileName = "Khazix_W_mis_enhanced.troy", projectileSpeed = 1700, range = 1025, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Zed"] = {charName = "Zed", skillshots = {
["ZedShuriken"] = {name = "ZedShuriken", spellName = "ZedShuriken", spellDelay = 250, projectileName = "Zed_Q_Mis.troy", projectileSpeed = 1700, range = 925, radius = 50, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Leblanc"] = {charName = "Leblanc", skillshots = {
["Ethereal Chains"] = {name = "EtherealChains", spellName = "LeblancSoulShackle", spellDelay = 250, projectileName = "leBlanc_shackle_mis.troy", projectileSpeed = 1600, range = 960, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Ethereal Chains R"] = {name = "EtherealChainsR", spellName = "LeblancSoulShackleM", spellDelay = 250, projectileName = "leBlanc_shackle_mis_ult.troy", projectileSpeed = 1600, range = 960, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Draven"] = {charName = "Draven", skillshots = {
["Stand Aside"] = {name = "StandAside", spellName = "DravenDoubleShot", spellDelay = 250, projectileName = "Draven_E_mis.troy", projectileSpeed = 1400, range = 1100, radius = 130, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["DravenR"] = {name = "DravenR", spellName = "DravenRCast", spellDelay = 500, projectileName = "Draven_R_mis!.troy", projectileSpeed = 2000, range = 25000, radius = 160, type = "line", cc = "false", collision = "false", shieldnow = "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", collision = "true", shieldnow = "true"}
}},
["Lulu"] = {charName = "Lulu", skillshots = {
["LuluQ"] = {name = "LuluQ", spellName = "LuluQ", spellDelay = 250, projectileName = "Lulu_Q_Mis.troy", projectileSpeed = 1450, range = 1000, radius = 50, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Thresh"] = {charName = "Thresh", skillshots = {
["ThreshQ"] = {name = "ThreshQ", spellName = "ThreshQ", spellDelay = 500, projectileName = "Thresh_Q_whip_beam.troy", projectileSpeed = 1900, range = 1100, radius = 65, type = "line", cc = "true", collision = "true", shieldnow = "true"}
}},
["Shen"] = {charName = "Shen", skillshots = {
["ShadowDash"] = {name = "ShadowDash", spellName = "ShenShadowDash", spellDelay = 0, projectileName = "shen_shadowDash_mis.troy", projectileSpeed = 3000, range = 575, radius = 50, type = "line", cc = "true", collision = "false", shieldnow = "true"}
}},
["Quinn"] = {charName = "Quinn", skillshots = {
["QuinnQ"] = {name = "QuinnQ", spellName = "QuinnQ", spellDelay = 250, projectileName = "Quinn_Q_missile.troy", projectileSpeed = 1550, range = 1050, radius = 80, type = "line", cc = "false", collision = "true", shieldnow = "true"}
}},
["Veigar"] = {charName = "Veigar", skillshots = {
["Dark Matter"] = {name = "VeigarDarkMatter", spellName = "VeigarDarkMatter", spellDelay = 250, projectileName = "!", projectileSpeed = 900, range = 900, radius = 225, type = "circular", cc = "false", collision = "false", shieldnow = "true"}
}},
["Jayce"] = {charName = "Jayce", skillshots = {
["JayceShockBlast"] = {name = "JayceShockBlast", spellName = "jayceshockblast", spellDelay = 250, projectileName = "JayceOrbLightning.troy", projectileSpeed = 1450, range = 1050, radius = 70, type = "line", cc = "false", collision = "true", shieldnow = "true"},
["JayceShockBlastCharged"] = {name = "JayceShockBlastCharged", spellName = "jayceshockblast", spellDelay = 250, projectileName = "JayceOrbLightningCharged.troy", projectileSpeed = 2350, range = 1600, radius = 70, type = "line", cc = "false", collision = "true", shieldnow = "true"},
}},
["Nami"] = {charName = "Nami", skillshots = {
["NamiQ"] = {name = "NamiQ", spellName = "NamiQ", spellDelay = 250, projectileName = "Nami_Q_mis.troy", projectileSpeed = 1500, range = 1625, radius = 225, type = "circle", cc = "true", collision = "false", shieldnow = "true"}
}},
["Fizz"] = {charName = "Fizz", skillshots = {
["Fizz Ultimate"] = {name = "FizzULT", spellName = "FizzMarinerDoom", spellDelay = 250, projectileName = "Fizz_UltimateMissile.troy", projectileSpeed = 1350, range = 1275, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Varus"] = {charName = "Varus", skillshots = {
["Varus Q Missile"] = {name = "VarusQMissile", spellName = "somerandomspellnamethatwillnevergetcalled", spellDelay = 0, projectileName = "VarusQ_mis.troy", projectileSpeed = 1900, range = 1600, radius = 70, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["VarusR"] = {name = "VarusR", spellName = "VarusR", spellDelay = 250, projectileName = "VarusRMissile.troy", projectileSpeed = 1950, range = 1250, radius = 100, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Karma"] = {charName = "Karma", skillshots = {
["KarmaQ"] = {name = "KarmaQ", spellName = "KarmaQ", spellDelay = 250, projectileName = "TEMP_KarmaQMis.troy", projectileSpeed = 1700, range = 1050, radius = 90, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Aatrox"] = {charName = "Aatrox", skillshots = {
["Blade of Torment"] = {name = "BladeofTorment", spellName = "AatroxE", spellDelay = 250, projectileName = "AatroxBladeofTorment_mis.troy", projectileSpeed = 1200, range = 1075, radius = 75, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["AatroxQ"] = {name = "AatroxQ", spellName = "AatroxQ", spellDelay = 250, projectileName = "AatroxQ.troy", projectileSpeed = 450, range = 650, radius = 145, type = "circle", cc = "true", collision = "false", shieldnow = "true"},
}},
["Xerath"] = {charName = "Xerath", skillshots = {
["Xerath Arcanopulse"] = {name = "xeratharcanopulse21", spellName = "xeratharcanopulse2", spellDelay = 400, projectileName = "hiu", projectileSpeed = 25000, range = 0, radius = 100, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["XerathArcaneBarrage2"] = {name = "XerathArcaneBarrage2", spellName = "XerathArcaneBarrage2", spellDelay = 500, projectileName = "Xerath_Base_W_cas.troy", projectileSpeed = 0, range = 1100, radius = 325, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
["XerathMageSpear"] = {name = "XerathMageSpear", spellName = "XerathMageSpear", spellDelay = 250, projectileName = "Xerath_Base_E_mis.troy", projectileSpeed = 1600, range = 1050, radius = 125, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["xerathlocuspulse"] = {name = "xerathlocuspulse", spellName = "xerathlocuspulse", spellDelay = 250, projectileName = "Xerath_Base_R_mis.troy", projectileSpeed = 300, range = 5600, radius = 265, type = "circular", cc = "false", collision = "false", shieldnow = "true"},
}},
["Lucian"] = {charName = "Lucian", skillshots = {
["LucianQ"] = {name = "LucianQ", spellName = "LucianQ", spellDelay = 350, projectileName = "Lucian_Q_laser.troy", projectileSpeed = 25000, range = 570*2, radius = 65, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["LucianW"] = {name = "LucianW", spellName = "LucianW", spellDelay = 300, projectileName = "Lucian_W_mis.troy", projectileSpeed = 1600, range = 1000, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Viktor"] = {charName = "Viktor", skillshots = {
["ViktorDeathRay1"] = {name = "ViktorDeathRay1", spellName = "ViktorDeathRay!", spellDelay = 500, projectileName = "Viktor_DeathRay_Fix_Mis.troy", projectileSpeed = 780, range = 700, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["ViktorDeathRay2"] = {name = "ViktorDeathRay2", spellName = "ViktorDeathRay!", spellDelay = 500, projectileName = "Viktor_DeathRay_Fix_Mis_Augmented.troy", projectileSpeed = 780, range = 700, radius = 80, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Rumble"] = {charName = "Rumble", skillshots = {
["RumbleGrenade"] = {name = "RumbleGrenade", spellName = "RumbleGrenade", spellDelay = 250, projectileName = "rumble_taze_mis.troy", projectileSpeed = 2000, range = 950, radius = 90, type = "line", cc = "true", collision = "true", shieldnow = "true"},
}},
["Nocturne"] = {charName = "Nocturne", skillshots = {
["NocturneDuskbringer"] = {name = "NocturneDuskbringer", spellName = "NocturneDuskbringer", spellDelay = 250, projectileName = "NocturneDuskbringer_mis.troy", projectileSpeed = 1400, range = 1125, radius = 60, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Yasuo"] = {charName = "Yasuo", skillshots = {
["yasuoq3"] = {name = "yasuoq3", spellName = "yasuoq3w", spellDelay = 250, projectileName = "Yasuo_Q_wind_mis.troy", projectileSpeed = 1200, range = 1000, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["yasuoq1"] = {name = "yasuoq1", spellName = "yasuoQW", spellDelay = 250, projectileName = "Yasuo_Q_WindStrike.troy", projectileSpeed = 25000, range = 475, radius = 40, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["yasuoq2"] = {name = "yasuoq2", spellName = "yasuoq2w", spellDelay = 250, projectileName = "Yasuo_Q_windstrike_02.troy", projectileSpeed = 25000, range = 475, radius = 40, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Orianna"] = {charName = "Orianna", skillshots = {
["OrianaIzunaCommand"] = {name = "OrianaIzunaCommand", spellName = "OrianaIzunaCommand", spellDelay = 0, projectileName = "Oriana_Ghost_mis.troy", projectileSpeed = 1300, range = 800, radius = 80, type = "line", cc = "true", collision = "false", shieldnow = "true"},
["OrianaDetonateCommand"] = {name = "OrianaDetonateCommand", spellName = "OrianaDetonateCommand", spellDelay = 100, projectileName = "Oriana_Shockwave_nova.troy", projectileSpeed = 400, range = 2000, radius = 400, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Ziggs"] = {charName = "Ziggs", skillshots = {
["ZiggsQ"] = {name = "ZiggsQ", spellName = "ZiggsQ", spellDelay = 250, projectileName = "ZiggsQ.troy", projectileSpeed = 1700, range = 1400, radius = 155, type = "line", cc = "false", collision = "true", shieldnow = "true"},
}},
["Annie"] = {charName = "Annie", skillshots = {
["AnnieR"] = {name = "AnnieR", spellName = "InfernalGuardian", spellDelay = 100, projectileName = "nothing", projectileSpeed = 0, range = 600, radius = 300, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Galio"] = {charName = "Galio", skillshots = {
["GalioResoluteSmite"] = {name = "GalioResoluteSmite", spellName = "GalioResoluteSmite", spellDelay = 250, projectileName = "galio_concussiveBlast_mis.troy", projectileSpeed = 850, range = 2000, radius = 200, type = "circle", cc = "true", collision = "false", shieldnow = "true"},
}},
["Jinx"] = {charName = "Jinx", skillshots = {
["W"] = {name = "Zap", spellName = "JinxW", spellDelay = 600, projectileName = "Jinx_W_Beam.troy", projectileSpeed = 3300, range = 1450, radius = 70, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["R"] = {name = "SuperMegaDeathRocket", spellName = "JinxRWrapper", spellDelay = 600, projectileName = "Jinx_R_Mis.troy", projectileSpeed = 1700, range = 20000, radius = 120, type = "line", cc = "false", collision = "false", shieldnow = "true"},
}},
["Velkoz"] = {charName = "Velkoz", skillshots = {
["PlasmaFission"] = {name = "PlasmaFission", spellName = "VelKozQ", spellDelay = 250, projectileName = "Velkoz_Base_Q_mis.troy", projectileSpeed = 1200, range = 1050, radius = 120, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Plasma Fission Split"] = {name = "VelKozQSplit", spellName = "VelKozQ", spellDelay = 250, projectileName = "Velkoz_Base_Q_Split_mis.troy", projectileSpeed = 1200, range = 1050, radius = 120, type = "line", cc = "true", collision = "true", shieldnow = "true"},
["Void Rift"] = {name = "VelkozW", spellName = "VelkozW", spellDelay = 250, projectileName = "Velkoz_Base_W_Turret.troy", projectileSpeed = 1200, range = 1050, radius = 125, type = "line", cc = "false", collision = "false", shieldnow = "true"},
["Tectonic Disruption"] = {name = "VelkozE", spellName = "VelkozE", spellDelay = 250, projectileName = "DarkBinding_mis.troy", projectileSpeed = 1200, range = 800, radius = 225, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
}},
["Heimerdinger"] = {charName = "Heimerdinger", skillshots = {
--["Micro-Rockets"] = {name = "MicroRockets", spellName = "HeimerdingerW1", spellDelay = 500, projectileName = "Heimerdinger_Base_w_Mis.troy", projectileSpeed = 902, range = 1325, radius = 100, type = "line", cc = "false", collision = "true", shieldnow = "true"},
--["Storm Grenade"] = {name = "StormGrenade", spellName = "HeimerdingerE", spellDelay = 250, projectileName = "Heimerdinger_Base_E_Mis.troy", projectileSpeed = 2500, range = 970, radius = 180, type = "circular", cc = "true", collision = "false", shieldnow = "true"},
--["Micro-RocketsUlt"] = {name = "MicroRocketsUlt", spellName = "HeimerdingerW2", spellDelay = 500, projectileName = "Heimerdinger_Base_W_Mis_Ult.troy", projectileSpeed = 902, range = 1325, radius = 100, type = "line", cc = "false", collision = "true", shieldnow = "true"},
--["Storm Grenade"] = {name = "StormGrenade", spellName = "HeimerdingerE2", spellDelay = 250, projectileName = "Heimerdinger_Base_E_Mis_Ult.troy", projectileSpeed = 2500, range = 970, radius = 180, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}},
["Malzahar"] = {charName = "Malzahar", skillshots = {
["Call Of The Void"] = {name = "CallOfTheVoid", spellName ="AlZaharCalloftheVoid1", spellDelay = 0, projectileName = "AlzaharCallofthevoid_mis.troy", projectileSpeed = 1600, range = 450, radius = 100, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}}    ,
["Janna"] = {charName = "Janna", skillshots = {
["Howling Gale"] = {name = "HowlingGale", spellName ="HowlingGale", spellDelay = 0, projectileName = "HowlingGale_mis.troy", projectileSpeed = 500, range = 0, radius = 100, type = "line", cc = "true", collision = "false", shieldnow = "true"},
}}
}
champions3 = {
["Aatrox"] = "AatroxW AatroxW2",
["Amumu"] = "AuraOfDespair",
["Anivia"] = "GlacialStorm",
["Annie"] = "MoltenShield",
["Ashe"] = "FrostShot",
["Blitzcrank"] = "Overdrive",
["Chogath"] = "VorpalSpikes",
["Corki"] = "GGun",
["Darius"] = "DariusCleave",
["DrMundo"] = "BurningAgony Masochism",
["Draven"] = "DravenSpinning DravenFury",
["Elise"] = "EliseSpiderW EliseRSpider EliseRHuman",
["Evelynn"] = "EvelynnQ EvelynnW",
["Fiora"] = "FioraRiposte FioraFlurry",
["Fizz"] = "FizzSeastonePassive",
["Galio"] = "GalioBulwark",
["Garen"] = "GarenQ GarenW GarenE",
["Gragas"] = "GragasBarrelRollToggle",
["Hecarim"] = "HecarimRapidSlash HecarimW HecarimRamp",
["Heimerdinger"] = "HeimerdingerR",
["Irelia"] = "IreliaHitenStyle IreliaTranscendentBlades",
["Janna"] = "HowlingGale SowTheWind EyeOfTheStorm",
["JarvanIV"] = "JarvanIVGoldenAegis JarvanIVDemacianStandard",
["Jax"] = "JaxEmpowerTwo JaxCounterStrike JaxRelentlessAssault",
["Jayce"] = "JayceStaticField JayceHyperCharge JayceAccelerationGate JayceStanceGtH JayceStanceHtG",
["Jinx"] = "JinxQ JinxE",
["Karma"] = "KarmaSolKimShield KarmaMantra",
["Karthus"] = "Defile",
["Kassadin"] = "NetherBlade",
["Katarina"] = "KatarinaW",
["Kayle"] = "JudicatorDivineBlessing JudicatorRighteousFury JudicatorIntervention",
["Kennen"] = "KennenLightningRush",
["KhaZix"] = "KhaZixR",
["KogMaw"] = "KogMawBioArcaneBarrage",
["Leona"] = "LeonaShieldOfDaybreak LeonaSolarBarrier",
["Lissandra"] = "LissandraW",
["Lucian"] = "LucianR",
["Lulu"] = "LuluW LuluE LuluR",
["Lux"] = "LuxLightStrikeToggle",
["Malphite"] = "Obduracy",
["Malzahar"] = "AlZaharNullZone",
["Maokai"] = "MaokaiDrain3Toggle",
["MasterYi"] = "WujuStyle Highlander",
["MissFortune"] = "MissFortuneViciousStrikes",
["Mordekaiser"] = "MordekaiserCreepingDeathCast",
["Morgana"] = "BlackShield",
["Nami"] = "NamiE",
["Nautilus"] = "NautilusPiercingGaze",
["Nidalee"] = "Takedown PrimalSurge AspectOfTheCougar",
["Nocturne"] = "NocturneShroudOfDarkness NocturneParanoia",
["Nunu"] = "BloodBoil",
["Olaf"] = "OlafFrenziedStrikes OlafRagnarok",
["Orianna"] = "OrianalzunaCommand OrianaDissonanceCommand OrianaRedactCommand OrianaDetonateCommand",
["Poppy"] = "PoppyDevastatingBlow PoppyParagonOfDemacia",
["Quinn"] = "QuinnW QuinnR QuinnValorQ QuinnRFinale",
["Rammus"] = "PowerBall DefensiveBallCurl Tremors2",
["Renekton"] = "RenektonPreExecute",
["Rengar"] = "RengarW RengarR",
["Rumble"] = "RumbleFlameThrower RumbleShield",
["Ryze"] = "DesperatePower",
["Sejuani"] = "SejuaniNorthernWinds",
["Shaco"] = "HallucinateGuide",
["Shen"] = "ShenFeint",
["Shyvana"] = "ShyvanaDoubleAttack ShyvanaImmolationAura",
["Singed"] = "PoisonTrail InsanityPotion",
["Sion"] = "DeathsCaressFull Enrage",
["Sivir"] = "SivirW SivirE SivirR",
["Skarner"] = "SkarnerExoskeleton",
["Sona"] = "SonaHymOfValor SonaAiraOfPerseverance SonaSongOfDiscord",
["Swain"] = "SwainMetamorphism",
["Syndra"] = "SyndraQ SyndraW SyndraR",
["Talon"] = "TalonNoxianDiplomacy",
["Teemo"] = "MoveQuick",
["Tristana"] = "RapidFire",
["Trundle"] = "TrundleTrollSmash",
["Tryndamere"] = "Bloodlust UndyingRage",
["Twisted Fate"] = "PickACard BlueCardLock RedCardLock GoldCardLock Destiny",
["Twitch"] = "HideInShadows FullAutomatic",
["Udyr"] = "UdyrTigerStance UdyrTurtleStance UdyrBearStance UdyrPhoenixStance",
["Urgot"] = "UrgotTerrorCapacitorActive2",
["Vayne"] = "VayneInquisition",
["Vi"] = "ViE",
["Vladimir"] = "VladimirSanguinePool",
["Volibear"] = "VolibearQ VolibearW",
["Warwick"] = "HuntersCall BloodScent",
["Wukong"] = "WukongQ WukongW WukongR",
["Xin Zhao"] = "XenZhaoComboTarget ZenZhaoBattleCry",
["Zac"] = "ZacW",
["Zed"] = "ZedPBAOEDummy",
["Ziggs"] = "ZiggsWToggle",
["Zilean"] = "Rewind TimeWarp",
["Zyra"] = "ZyraSeed"

}

wrotedisclaimer = false
enemies = {}
nAllies = 0
allies = {}
XerathQTickCount = 0
nEnemies = 0
evading = false
allowCustomMovement = true
captureMovements = true
lastMovement = {}
detectedSkillshots = {}
nSkillshots = 0
CastingSpell = false
HowlingGale = false
lastset = 0
trueWidth = {}
trueSpeed = {}
trueDelay = {}
haveflash = false
flashSlot = nil
flashready = false
lastspell = "Q"
useflash = false
shieldslot = _E
shieldtick = nil
alreadywritten = false
thatfile = SCRIPT_PATH.."movementblock.txt"
currentbuffer = 0
bufferset = false
lastnonattack = 0
hitboxTable = {['Yasuo'] = 65, ['VelKoz'] = 65, ['Xerath'] = 65, ['Kassadin'] = 65, ['Rengar'] = 65, ['Thresh'] = 55.0, ['Ziggs'] = 55.0, ['KogMaw'] = 65, ['Katarina'] = 65, ['Riven'] = 65, ['Ashe'] = 65, ['Soraka'] = 65, ['Jinx'] = 65, ['JarvanIV'] = 65, ['Tryndamere'] = 65, ['Singed'] = 65, ['Diana'] = 65, ['Ahri'] = 65, ['Lulu'] = 65, ['MasterYi'] = 65, ['Lissandra'] = 65, ['Draven'] = 65, ['FiddleSticks'] = 65, ['Maokai'] = 80.0, ['Sivir'] = 65, ['Corki'] = 65, ['Janna'] = 65, ['Nasus'] = 80.0, ['LeeSin'] = 65, ['Jax'] = 65, ['Blitzcrank'] = 80.0, ['Shen'] = 65, ['Nocturne'] = 65, ['Sona'] = 65, ['Caitlyn'] = 65, ['Trundle'] = 65, ['Malphite'] = 80.0, ['Mordekaiser'] = 80.0, ['Vi'] = 50, ['Renekton'] = 80.0, ['Anivia'] = 65, ['Fizz'] = 65, ['Heimerdinger'] = 55.0, ['Evelynn'] = 65, ['Rumble'] = 80.0, ['Leblanc'] = 65, ['Darius'] = 80.0, ['Viktor'] = 65, ['XinZhao'] = 65, ['Orianna'] = 65, ['Vladimir'] = 65, ['Nidalee'] = 65, ['Syndra'] = 65, ['Zac'] = 80.0, ['Olaf'] = 65, ['Veigar'] = 55.0, ['Twitch'] = 65, ['Alistar'] = 80.0, ['Akali'] = 65, ['Urgot'] = 80.0, ['Leona'] = 65, ['Talon'] = 65, ['Karma'] = 65, ['Jayce'] = 65, ['Galio'] = 80.0, ['Shaco'] = 65, ['Taric'] = 65, ['TwistedFate'] = 65, ['Varus'] = 65, ['Garen'] = 65, ['Swain'] = 65, ['Vayne'] = 65, ['Fiora'] = 65, ['Quinn'] = 65, ['Kayle'] = 65, ['Brand'] = 65, ['Teemo'] = 55.0, ['Amumu'] = 55.0, ['Annie'] = 55.0, ['Elise'] = 65, ['Nami'] = 65, ['Poppy'] = 55.0, ['AniviaEgg'] = 65, ['Tristana'] = 55.0, ['Graves'] = 65, ['Morgana'] = 65, ['Gragas'] = 80.0, ['MissFortune'] = 65, ['Warwick'] = 65, ['Cassiopeia'] = 65, ['DrMundo'] = 80.0, ['Volibear'] = 80.0, ['Irelia'] = 65, ['Lucian'] = 65, ['Yorick'] = 80.0, ['Udyr'] = 65, ['MonkeyKing'] = 65, ['Kennen'] = 55.0, ['Nunu'] = 65, ['Ryze'] = 65, ['Zed'] = 65, ['Nautilus'] = 80.0, ['Gangplank'] = 65, ['shopevo'] = 65, ['Lux'] = 65, ['Sejuani'] = 80.0, ['Ezreal'] = 65, ['Khazix'] = 65, ['Sion'] = 80.0, ['Aatrox'] = 65, ['Hecarim'] = 80.0, ['Pantheon'] = 65, ['Shyvana'] = 50.0, ['Zyra'] = 65, ['Karthus'] = 65, ['Rammus'] = 65, ['Zilean'] = 65, ['Chogath'] = 80.0, ['Malzahar'] = 65, ['KogMawDead'] = 65, ['QuinnValor'] = 65, ['Nidalee_Cougar'] = 65}


function getTarget(targetId)
        if targetId ~= 0 and targetId ~= nil then
        return objManager:GetObjectByNetworkId(targetId)
    end
    return nil
end

function OnSendPacket(p)
        if VIP_USER then
        local packet = Packet(p)
        if packet:get('name') == 'S_MOVE' then
            if packet:get('sourceNetworkId') == myHero.networkID then
                if captureMovements then
                    if packet:get('targetNetworkId') == 0 then
                        lastMovement.destination = Point2(packet:get('x'), packet:get('y'))
                        lastMovement.type = packet:get('type')
                        lastMovement.targetId = packet:get('targetNetworkId')
                        lastnonattack = GetTickCount()
                        elseif lastnonattack + 1000 < GetTickCount() then
                        lastMovement.destination = Point2(packet:get('x'), packet:get('y'))
                        lastMovement.type = packet:get('type')
                        lastMovement.targetId = packet:get('targetNetworkId')
                    end
                    
                    if evading then
                        for i, detectedSkillshot in pairs(detectedSkillshots) do
                            if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                                dodgeSkillshot(detectedSkillshot)
                                break
                            end
                        end
                    end
                end
                if not allowCustomMovement then
                        for i, detectedSkillshot in pairs(detectedSkillshots) do
                            if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                                packet:block()
                                break
                            end
                        end
                end
            end
            elseif packet:get('name') == 'S_CAST' then
            if captureMovements and lastnonattack + 1000 < GetTickCount() then
                lastMovement.spellId = packet:get('spellId')
                lastMovement.type = 7
                lastMovement.targetId = packet:get('targetNetworkId')
                lastMovement.destination = Point2(packet:get('toX'), packet:get('toY'))
                
                if evading then
                    for i, detectedSkillshot in pairs(detectedSkillshots) do
                        if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                            dodgeSkillshot(detectedSkillshot)
                            break
                        end
                    end
                end
            end
            if not (allowCustomMovement or
                    spellStopMovement(GetMyHero().charName, packet:get('spellId'),
                    packet.targetNetworkId == GetMyHero().NetworkId)) then
                if packet:get('spellId') == 12 then
                else
                    for i, detectedSkillshot in pairs(detectedSkillshots) do
                        if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                            packet:block()
                            break
                        end
                    end
                end
            end
        end
    end
end

function spellStopMovement(champName, champSkill, selfCast)
    if GoodEvadeConfig.allowMove == false then
        return false
    end
    local champSkill2
    if(champSkill == 0) then
        champSkill2 = GetMyHero():GetSpellData(0).name
        if GoodEvadeConfig.stopCCMoves and (GetMyHero().charName == "Varus" or GetMyHero().charName == "Vi" or GetMyHero().charName == "Xerath") then
            return true
        else
            return false
        end
    elseif(champSkill == 1) then
        champSkill2 = GetMyHero():GetSpellData(1).name
        if(GetMyHero().charName) == "LeeSin" and selfCast then
            return true
        end
    elseif(champSkill == 2) then
        champSkill2 = GetMyHero():GetSpellData(2).name
    elseif(champSkill == 3) then
        champSkill2 = GetMyHero():GetSpellData(3).name
    else
        champSkill2 = "null"
    end
    if(champions3[champName] ~= nil) then
        return string.find(string.lower(champions3[champName]), string.lower(champSkill2)) ~= nil
    end
    return false
end

function getLastMovementDestination()
    mousePosition = Point2(mousePos.x, mousePos.z)
    if VIP_USER then
        if lastMovement.type == 3 then
            heroPosition = Point2(myHero.x, myHero.z)
            mousePosition = Point2(mousePos.x, mousePos.z)
            
            target = getTarget(lastMovement.targetId)
            if _isValidTarget(target) then
                targetPosition = Point2(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 mousePosition
                end
            else
                return mousePosition
            end
            elseif lastMovement.type == 7 then
            heroPosition = Point2(myHero.x, myHero.z)
            mousePosition = Point2(mousePos.x, mousePos.z)
            target = getTarget(lastMovement.targetId)
            if _isValidTarget(target) then
                targetPosition = Point2(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 mousePosition
                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 mousePosition
                end
            end
        else
            return lastMovement.destination
        end
        else return lastMovement.destination
    end
end
function CheckBall(obj)
    if obj == nil or obj.name == nil then return end
    
    if (obj.name:find("Oriana_Ghost_mis") or obj.name:find("Oriana_Ghost_mis_protect") ) then
        ball = nil            
        return
    end
    
    if obj.name:find("yomu_ring_red") then
        ball = obj
        return
    end
    
    if obj.name:find("Oriana_Ghost_bind") then
        for i, target in pairs(enemies) do
            if GetDistance(target, obj) < 40 then
                ball = target
            end
        end
    end
end

local AutoUpdate = true
local SELF = SCRIPT_PATH..GetCurrentEnv().FILE_NAME
local URL = "https://raw.githubusercontent.com/Whatefang/FreakingGoodEvade/master/FreakingGoodEvade.lua"
local UPDATE_TMP_FILE = LIB_PATH.."FGETmp.txt"
local versionmessage = "<font color=\"#81BEF7\" >Changelog: Added various AOE CC ults to dangerous ults; fixed handling (should now Spellshield > Dash > Flash out) of those spells. Added dash to dodge spells % HP slider. Swapped around menu items. Added a new drawing system; will draw a rectangle around the length of each skillshot to better show the hitbox. </font>"

function Update()
DownloadFile(URL, UPDATE_TMP_FILE, UpdateCallback)
end

function UpdateCallback()
file = io.open(UPDATE_TMP_FILE, "rb")
if file ~= nil then
content = file:read("*all")
file:close()
os.remove(UPDATE_TMP_FILE)
if content then
tmp, sstart = string.find(content, "local version = \"")
if sstart then
send, tmp = string.find(content, "\"", sstart+1)
end
if send then
Version = tonumber(string.sub(content, sstart+1, send-1))
end
if (Version ~= nil) and (Version > tonumber(version)) and content:find("--EOS--") then
file = io.open(SELF, "w")
if file then
file:write(content)
file:flush()
file:close()
PrintChat("<font color=\"#81BEF7\" >FreakingGoodEvade:</font> <font color=\"#00FF00\">Successfully updated to: v"..Version..". Please reload the script with F9.</font>")
else
PrintChat("<font color=\"#81BEF7\" >FreakingGoodEvade:</font> <font color=\"#FF0000\">Error updating to new version (v"..Version..")</font>")
end
elseif (Version ~= nil) and (Version == tonumber(version)) then
PrintChat("<font color=\"#81BEF7\" >FreakingGoodEvade:</font> <font color=\"#00FF00\">No updates found, latest version: v"..Version.." </font>")
end
end
end
end

function OnLoad()
    hitboxSize = hitboxTable[GetMyHero().charName]
    
    if hitboxSize == nil then
        hitboxSize = 80.0
    end

    ball = nil
    GoodEvadeConfig = scriptConfig("Freaking Good Evade", "Freaking Good Evade")
    GoodEvadeConfig:addParam("evadeBuffer", "Increase Skillshot width by", SCRIPT_PARAM_SLICE, 15, 0, 50, 0)
    GoodEvadeConfig:addParam("fowdelay", "Delay for skillshots from FOW", SCRIPT_PARAM_SLICE, 1, 1, 20, 0)
    GoodEvadeConfig:addParam("dodgeEnabled", "Dodge Skillshots", SCRIPT_PARAM_ONKEYTOGGLE, false, 192)
    GoodEvadeConfig:addParam("dodgeCConly", "Dodge CC only spells", SCRIPT_PARAM_ONKEYDOWN, false, 32)
    GoodEvadeConfig:addParam("dodgeCConly2", "Toggle dodge CC only spells", SCRIPT_PARAM_ONKEYTOGGLE, false, 77)
    GoodEvadeConfig:addParam("usedashes", "Dash to dodge spells", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("dashMouse", "Always dash toward your mouse", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("dashPercent", "Use dashes below what % HP", SCRIPT_PARAM_SLICE, 100, 0, 100)
    GoodEvadeConfig:addParam("lineallways", "Always try to dodge line skillshots", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("useSummonerFlash", "Flash to dodge dangerous spells", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("drawEnabled", "Draw Skillshots", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("resetdodge", "Reset Dodge", SCRIPT_PARAM_ONKEYDOWN, false, 17)
    GoodEvadeConfig:addParam("allowMove", "Allow use of 0 cast time spells", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("stopCCMoves", "Use 0 cast time spells with self cc", SCRIPT_PARAM_ONOFF, true)
    GoodEvadeConfig:addParam("freemovementblock", "Free Users Movement Block", SCRIPT_PARAM_ONOFF, false)
    GoodEvadeConfig:addParam("oldDrawing", "Use old drawing", SCRIPT_PARAM_ONOFF, false)
    GoodEvadeConfig:permaShow("dodgeEnabled")
    for i = 1, heroManager.iCount do
        local hero = heroManager:GetHero(i)
        if hero.team ~= myHero.team then
            for i, skillShotChampion in pairs(champions2) do
                if skillShotChampion.charName == hero.charName then
                    table.insert(champions, skillShotChampion)
                end
            end
        end
    end
    GoodEvadeSkillshotConfig = scriptConfig("FGE skillshots", "FGE skillshots config")
    for i, skillShotChampion in pairs(champions) do
        for i, skillshot in pairs(skillShotChampion.skillshots) do
            name = tostring(skillshot.name)
            name2 = tostring(skillshot.name)
            if skillshot.cc == "true" then
                GoodEvadeSkillshotConfig:addParam(name, "Dodge "..name2, SCRIPT_PARAM_SLICE, 2, 0, 2, 0)
                elseif skillshot.cc == "false" then GoodEvadeSkillshotConfig:addParam(name, "Dodge "..name2, SCRIPT_PARAM_SLICE, 1, 0, 2, 0)
                elseif skillshot.cc == "never" then GoodEvadeSkillshotConfig:addParam(name, "Dodge "..name2, SCRIPT_PARAM_SLICE, 0, 0, 2, 0)
            end
        end
    end
    
    stopEvade()
    isSivir = false
    if myHero.charName == "Sivir" then
        isSivir = true
    end
    isNocturne = false
    if myHero.charName == "Nocturne" then
        isNocturne = true
    end
    isVayne = false
    if myHero.charName == "Vayne" then
        isVayne = true
    end
    isGraves = false
    if myHero.charName == "Graves" then
        isGraves = true
    end
    isEzreal = false
    if myHero.charName == "Ezreal" then
        isEzreal = true
    end
    if myHero.charName == "Caitlyn"
        then isCaitlyn = true
    end
    isLeblanc = false
    if myHero.charName == "Leblanc" then
        isLeblanc = true
    end
    isRiven = false
    if myHero.charName == "Riven" then
        isRiven = true
    end
    isFizz = false
    if myHero.charName == "Fizz" then
        isFizz = true
    end
    isShen = false
    if myHero.charName == "Shen" then
        isShen = true
    end
    isShaco = false
    if myHero.charName == "Shaco" then
        isShaco = true
    end
    isRenekton = false
    if myHero.charName == "Renekton" then
        isRenekton = true
    end
    isTristana = false
    if myHero.charName == "Tristana" then
        isTristana = true
    end
    isTryndamere = false
    if myHero.charName == "Tryndamere" then
        isTryndamere = true
    end
    isCorki = false
    if myHero.charName == "Corki" then
        isCorki = true
    end
    isLucian = false
    if myHero.charName == "Lucian" then
        isLucian = true
    end
    if myHero:GetSpellData(SUMMONER_1).name:find("SummonerFlash") then
        haveflash = true
        flashSlot = SUMMONER_1
        elseif myHero:GetSpellData(SUMMONER_2).name:find("SummonerFlash") then
        flashSlot = SUMMONER_2
        haveflash = true
    end
    
    lastMovement = {
    destination = Point2(myHero.x, myHero.z),
    moveCommand = Point2(myHero.x, myHero.z),
    type = 2,
    targetId = nil,
    spellId = nil,
    approachedPoint = nil
    }
    
    for i = 1, heroManager.iCount do
        local hero = heroManager:GetHero(i)
        if hero.team ~= myHero.team then
            table.insert(enemies, hero)
            elseif hero.team == myHero.team and hero.nEnemies ~= myHero.networkID then
            table.insert(allies, hero)
        end
    end
    isOrianna = false
    for i, enemy in pairs(enemies) do
        if enemy.charName == "Orianna" then
            isOrianna = true
        end
    end
    if #enemies == 5 then
        for i, skillShotChampion in pairs(champions) do
            if skillShotChampion.charName ~= enemies[1].charName and skillShotChampion.charName ~= enemies[2].charName and skillShotChampion.charName ~= enemies[3].charName
                and skillShotChampion.charName ~= enemies[4].charName and skillShotChampion.charName ~= enemies[5].charName then
                champions[i] = nil
            end
        end
    end
    
    player:RemoveCollision()
    player:SetVisionRadius(1700)
    
    GoodEvadeConfig.dodgeEnabled = true
    currentbuffer = GoodEvadeConfig.evadeBuffer
    PrintChat(versionmessage)
    if AutoUpdate then
        DelayAction(Update, 3)
    end
end

function getSideOfLine(linePoint1, linePoint2, point)
    if not point then return 0 end
    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

colstartpos = nil
colendpos = nil

function dodgeSkillshot(skillshot)
    if GoodEvadeConfig.dodgeEnabled and not myHero.dead and CastingSpell == false then
        if GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 2 or (GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 1 and nEnemies <= 2 and not (GoodEvadeConfig.dodgeCConly == skillshot.skillshot.cc or GoodEvadeConfig.dodgeCConly2 == skillshot.skillshot.cc)) then
            if skillshot.skillshot.type == "line" then
                if skillshot.skillshot.collision == "true" and VIP_USER then
                    heropos = Point2(myHero.x, myHero.z)
                    endposition = skillshot.startPosition + (skillshot.endPosition - skillshot.startPosition):normalized() * (heropos:distance(skillshot.startPosition))
                    colstartpos = Vector(skillshot.startPosition.x, myHero.y, skillshot.startPosition.y)
                    colendpos = Vector(endposition.x, myHero.y, endposition.y)
                    collisionshit = CollisionPE(skillshot.skillshot.range, skillshot.skillshot.projectileSpeed, skillshot.skillshot.spellDelay, skillshot.skillshot.radius)
                    if collisionshit:GetMinionCollision(colstartpos, colendpos) then return end
                end
                dodgeLineShot(skillshot)
            else
                dodgeCircularShot(skillshot)
            end
        end
    end
end

function dodgeCircularShot(skillshot)
    skillshot.evading = true
    alreadydodged = false
    heroPosition = Point2(myHero.x, myHero.z)
    
    moveableDistance = myHero.ms * math.max(skillshot.endTick - GetTickCount() - GetLatency()/2, 0) / 1000
    evadeRadius = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.evadeBuffer + moveBuffer
    
    safeTarget = skillshot.endPosition + (heroPosition - skillshot.endPosition):normalized() * evadeRadius

    if false and isreallydangerous(skillshot) then
        if mainCircularskillshot1(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget) then
            alreadydodged = true
        elseif dodgeDangerousCircle1(skillshot) then
            alreadydodged = true
        elseif dodgeDangerousCircle2(skillshot, safeTarget) then
            alreadydodged = true
        elseif dodgeDangerousCircle3(skillshot, safeTarget) then
            alreadydodged = true
        end
    end

    if not alreadydodged then
        if mainCircularskillshot1(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget) then
            alreadydodged = true
            elseif mainCircularskillshot2(skillshot) then
            alreadydodged = true
            elseif mainCircularskillshot3(skillshot, heroPosition) then
            alreadydodged = true
            elseif mainCircularskillshot4(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget) then
            alreadydodged = true
            elseif mainCircularskillshot5(skillshot, safeTarget) then
            alreadydodged = true
        end
    end
end

function haveShield()
    if isSivir and myHero:CanUseSpell(_E) == READY then
        return true
    elseif isNocturne and myHero:CanUseSpell(_W) == READY then
        return true
    end
    return false
end

function FlashTo(x, y)

    if GoodEvadeConfig.dashMouse then
    
        local evadePos = Point2(mousePos.x, mousePos.z)
        local myPos = Point2(myHero.x, myHero.z)
        local ourdistance = evadePos:distance(myPos)
        local dashPos = myPos - (myPos - evadePos):normalized() * 400
    
        x = dashPos.x
        y = dashPos.y
    end

    CastSpell(flashSlot, x, y)
end


function dodgeLineShot(skillshot)
    alreadydodged = false
    heroPosition = Point2(myHero.x, myHero.z)
    local evadeTo1
    local evadeTo2
    skillshot.evading = true
    skillshotLine = Line2(skillshot.startPosition, skillshot.endPosition)
    distanceFromSkillshotPath = skillshotLine:distance(heroPosition)
    evadeDistance = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.evadeBuffer + moveBuffer
    normalVector = Point2(skillshot.directionVector.y, -skillshot.directionVector.x):normalized()
    nessecaryMoveWidth = evadeDistance - distanceFromSkillshotPath
    evadeTo1 = heroPosition + normalVector * nessecaryMoveWidth
    evadeTo2 = heroPosition - normalVector * nessecaryMoveWidth
    
    if isreallydangerous(skillshot) then
        if lineSkillshot1(skillshot, heroPosition, skillshotLine, distanceFromSkillshotPath, evadeDistance, normalVector, nessecaryMoveWidth, evadeTo1, evadeTo2)
            then alreadydodged = true
        elseif dodgeDangerousLine1(skillshot) then
            alreadydodged = true
        elseif dodgeDangerousLine2(skillshot, evadeTo1, evadeTo2) then
            alreadydodged = true
        end
    end
    
    if not alreadydodged then
        if lineSkillshot1(skillshot, heroPosition, skillshotLine, distanceFromSkillshotPath, evadeDistance, normalVector, nessecaryMoveWidth, evadeTo1, evadeTo2)
            then alreadydodged = true
        elseif lineSkillshot2(skillshot)
            then alreadydodged = true
        elseif lineSkillshot3(skillshot, evadeTo1, evadeTo2)
            then alreadydodged = true
        elseif lineSkillshot4(skillshot, evadeTo1, evadeTo2)
            then alreadydodged = true
        end
    end
    
end

function _isDangerSkillshot(skillshot)
        if skillshot.skillshot.name == "LeonaZenithBlade"
        or skillshot.skillshot.name == "EnchantedArrow"
        or skillshot.skillshot.name == "LuxMaliceCannon"
        or skillshot.skillshot.name == "SejuaniR"
        or skillshot.skillshot.name == "Crescendo"
        or skillshot.skillshot.name == "TrueshotBarrage"
        or skillshot.skillshot.name == "RocketGrab"
        or skillshot.skillshot.name == "DredgeLine"
        or skillshot.skillshot.name == "ShadowDash"
        or skillshot.skillshot.name == "FizzULT"
        or skillshot.skillshot.name == "VarusR"
        or skillshot.skillshot.name == "SuperMegaDeathRocket"
        or skillshot.skillshot.name == "UFSlash"
        or skillshot.skillshot.name == "LeonaSolarFlare"
        or skillshot.skillshot.name == "AnnieR"
        or skillshot.skillshot.name == "OrianaDetonateCommand"
        then
        return true
    else
        return false
    end
end

function isreallydangerous(skillshot)
        if skillshot.skillshot.name == "UFSlash"
        or skillshot.skillshot.name == "Crescendo"
        or skillshot.skillshot.name == "FizzULT"
        or skillshot.skillshot.name == "EnchantedArrow"
        or skillshot.skillshot.name == "AnnieR"
        or skillshot.skillshot.name == "OrianaDetonateCommand"
        or skillshot.skillshot.name == "LeonaSolarFlare"
        or skillshot.skillshot.name == "VarusR"
        or skillshot.skillshot.name == "EnchantedArrow"
        or skillshot.skillshot.name == "SejuaniR"
        then return true
    else
        return false
    end
end

function InsideTheWall(evadeTestPoint)
    local heroPosition = Point2(myHero.x, myHero.z)
    local dist = evadeTestPoint:distance(heroPosition)
    local interval = 50
    local nChecks = math.ceil((dist+50)/50)
    
    if evadeTestPoint.x == 0 or evadeTestPoint.y == 0 then
        return true
    end
    for k=1, nChecks, 1 do
        local checksPos = evadeTestPoint + (evadeTestPoint - heroPosition):normalized()*(interval*k)
        if IsWall(D3DXVECTOR3(checksPos.x, myHero.y, checksPos.y)) then
            return true
        end
    end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x + 20, myHero.y, evadeTestPoint.y + 20)) then return true end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x + 20, myHero.y, evadeTestPoint.y - 20)) then return true end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x - 20, myHero.y, evadeTestPoint.y - 20)) then return true end
    if IsWall(D3DXVECTOR3(evadeTestPoint.x - 20, myHero.y, evadeTestPoint.y + 20)) then return true end
    
    return false
end

function findBestDirection(skillshot, referencePoint, possiblePoints)
    if not skillshot then return closestPoint end
    closestPoint = nil
    closestDistance = nil
    side1 = getSideOfLine(skillshot.startPosition, skillshot.endPosition, Point2(myHero.x, myHero.z))
    for i, point in pairs(possiblePoints) do
        if point ~= nil and skillshot ~= nil then
            side2 = getSideOfLine(skillshot.startPosition, skillshot.endPosition, point)
            distToSkillshot = Line2(skillshot.startPosition, skillshot.endPosition):distance(point)
            mindistSkillshot = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.evadeBuffer
            distance = point:distance(referencePoint)
            if (closestDistance == nil or distance <= closestDistance) and not InsideTheWall(point)
                and distToSkillshot > mindistSkillshot and (side1 == side2 or side1 == 0) 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, Point2(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, Point2(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 Line2(skillshot.startPosition, skillshot.endPosition):distance(coordinate) < (skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.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 + GoodEvadeConfig.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_GeneralParticleEmmiter" then
        for i, skillShotChampion in pairs(champions) do
            for i, skillshot in pairs(skillShotChampion.skillshots) do
                if GoodEvadeSkillshotConfig[tostring(skillshot.name)] == 2 then
                    if skillshot.projectileName == object.name then
                            for i, detectedSkillshot in pairs(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
                            
                            if skillshot.type == "line" then
                                if(skillshotToAdd ~= nil) then
                                    skillshotToAdd2 = {object = object, startPosition = nil, endPosition = nil, directionVector = nil, startTick = GetTickCount(), endTick = GetTickCount() + skillshot.range/skillshot.projectileSpeed*1000, skillshot = skillshot, evading = false, drawit = true, alreadydashed = false}
                                else
                                    skillshotToAdd = {object = object, startPosition = nil, endPosition = nil, directionVector = nil, startTick = GetTickCount(), endTick = GetTickCount() + skillshot.range/skillshot.projectileSpeed*1000, skillshot = skillshot, evading = false, drawit = true, alreadydashed = false}
                                end
                                elseif skillshot.type == "circular" then
                                endPosition = Point2(object.x, object.z)
                                startPosition = Point2(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, drawit = false, alreadydashed = false})
                            end
                        end
                        return
                    end
            end
        end
    end
end
function OnAnimation(unit, animationName)
        if CastingSpell == true then
        if unit.isMe and (animationName == "Idle1" or animationName == "Run") then CastingSpell = false end
    end
end

function OnProcessSpell(unit, spell)    
        if unit.isMe and myHero.charName == "MasterYi" and spell.name == myHero:GetSpellData(_W).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Nunu" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "MissFortune" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Malzahar" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Katarina" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Janna" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "Galio" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "FiddleSticks" and spell.name == myHero:GetSpellData(_W).name then
        CastingSpell = true
        elseif unit.isMe and myHero.charName == "FiddleSticks" and spell.name == myHero:GetSpellData(_R).name then
        CastingSpell = true
    end
    if unit.isMe and isLeblanc then
        if spell.name == myHero:GetSpellData(_Q).name then lastspell = "Q"
            elseif spell.name == myHero:GetSpellData(_W).name then lastspell = "W"
            elseif spell.name == myHero:GetSpellData(_E).name then lastspell = "E"
        end
    end
    if not myHero.dead and unit.team ~= myHero.team then
            for i, skillShotChampion in pairs(champions) do
                if skillShotChampion.charName == unit.charName then
                    for i, skillshot in pairs(skillShotChampion.skillshots) do
                        if skillshot.spellName == spell.name then
                            startPosition = Point2(spell.startPos.x, spell.startPos.z)
                            endPosition = Point2(spell.endPos.x, spell.endPos.z)
                            if(spell.name == "xeratharcanopulse2") then
                                skillshot.range = startPosition:distance(endPosition)
                            end
                            
                            if(spell.name == "HowlingGale" and HowlingGale) then
                                skillshot.range = startPosition:distance(endPosition)
                                HowlingGale = false
                            else
                                if(spell.name == "HowlingGale")then
                                    HowlingGale = true
                                end
                            end
                            
                            if isOrianna and unit.charName == "Orianna" then
                                ball = nil
                                for i = 1, objManager.maxObjects, 1 do
                                    local obj = objManager:GetObject(i)
                                    CheckBall(obj)
                                end
                                if ball ~= nil then
                                    startPosition = Point2(ball.x, ball.z)
                                    if skillshot.spellName == "OrianaDetonateCommand" then
                                        endPosition = Point2(ball.x, ball.z)
                                    end
                                end
                            end
                            directionVector = (endPosition - startPosition):normalized()
                            if isOrianna and unit.charName == "Orianna" then
                                if skillshot.spellName == "OrianaIzunaCommand" then skillshot.range = startPosition:distance(endPosition) end
                            end

                            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, drawit = true, alreadydashed = false})
                                elseif skillshot.type == "circular" then
                                table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition,
                                directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay,
                                endTick = GetTickCount() + skillshot.spellDelay + skillshot.projectileSpeed, skillshot = skillshot, evading = false, drawit = true, alreadydashed = false})
                            else
                                local ssrange = endPosition:distance(startPosition)
                                table.insert(detectedSkillshots, {startPosition = startPosition, endPosition = endPosition,
                                directionVector = directionVector, startTick = GetTickCount() + skillshot.spellDelay,
                                endTick = GetTickCount() + skillshot.spellDelay + (skillshot.projectileSpeed * (ssrange/skillshot.range)), skillshot = skillshot, evading = false, drawit = true, alreadydashed = 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())
    side1 = getSideOfLine(coordinate, footOfPerpendicular, currentSkillshotPosition)
    side2 = getSideOfLine(coordinate, footOfPerpendicular, skillshot.startPosition)
    return side1 ~= side2 and currentSkillshotPosition:distance(footOfPerpendicular) >= (skillshot.skillshot.radius + hitboxSize / 2)
end

function getPerpendicularFootpoint(linePoint1, linePoint2, point)
    distanceFromLine = Line2(linePoint1, linePoint2):distance(point)
    directionVector = (linePoint2 - linePoint1):normalized()
    
    footOfPerpendicular = point + Point2(-directionVector.y, directionVector.x) * distanceFromLine
    if Line2(linePoint1, linePoint2):distance(footOfPerpendicular) > distanceFromLine then
        footOfPerpendicular = point - Point2(-directionVector.y, directionVector.x) * distanceFromLine
    end
    
    return footOfPerpendicular
end

function OnTick()
    if GoodEvadeConfig.freemovementblock then
        if evading and not alreadywritten then
            local file = io.open(thatfile, "w")
            file:write("1")
            file:close()
            alreadywritten = true
            elseif not evading and alreadywritten then
            local file = io.open(thatfile, "w")
            file:write("0")
            file:close()
            alreadywritten = false
        end
        if not wrotedisclaimer then
            PrintChat("<font color=\"#FF0000\" >You just enabled free user movement block, this function will only work if you followed tutorial in main thread of the script before allowing it.</font>")
            wrotedisclaimer = true
        end
    end
    if skillshotToAdd ~= nil and skillshotToAdd.object ~= nil and skillshotToAdd.object.valid and (GetTickCount() - skillshotToAdd.startTick) >= GoodEvadeConfig.fowdelay and skillshotToAdd.startPosition == nil then
            skillshotToAdd.startPosition = Point2(skillshotToAdd.object.x, skillshotToAdd.object.z)
        elseif skillshotToAdd ~= nil and skillshotToAdd.object ~= nil and skillshotToAdd.object.valid and (GetTickCount() - skillshotToAdd.startTick) >= (GoodEvadeConfig.fowdelay+1) then
            skillshotToAdd.directionVector = (Point2(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
    if skillshotToAdd2 ~= nil and skillshotToAdd2.object ~= nil and skillshotToAdd2.object.valid and (GetTickCount() - skillshotToAdd2.startTick) >= GoodEvadeConfig.fowdelay and skillshotToAdd2.startPosition == nil then
            skillshotToAdd2.startPosition = Point2(skillshotToAdd2.object.x, skillshotToAdd2.object.z)
        elseif skillshotToAdd2 ~= nil and skillshotToAdd2.object ~= nil and skillshotToAdd2.object.valid and (GetTickCount() - skillshotToAdd2.startTick) >= (GoodEvadeConfig.fowdelay+1) then
            skillshotToAdd2.directionVector = (Point2(skillshotToAdd2.object.x, skillshotToAdd2.object.z) - skillshotToAdd2.startPosition):normalized()
            skillshotToAdd2.endPosition = skillshotToAdd2.startPosition + skillshotToAdd2.directionVector * skillshotToAdd2.skillshot.range
            table.insert(detectedSkillshots, skillshotToAdd2)
            skillshotToAdd2 = nil
    end

    if shieldtick ~= nil then
        if GetTickCount() >= shieldtick then
            if haveShield() then
                if isSivir then
                    CastSpell(_E)
                elseif isNocturne then
                    CastSpell(_W)
                end
                shieldtick = nil
            end
        end
    end
    if evading then
        for i, detectedSkillshot in pairs(detectedSkillshots) do
            if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                dodgeSkillshot(detectedSkillshot)
            end
        end
    end
    if haveflash then
        if myHero:CanUseSpell(flashSlot) == READY then
            flashready = true
            else flashready = false
        end
    end
    if GoodEvadeConfig.resetdodge then
        stopEvade()
        detectedSkillshots = {}
    end
    if AutoCarry ~= nil then
        if AutoCarry.MainMenu ~= nil then
            if AutoCarry.MainMenu.AutoCarry or AutoCarry.MainMenu.LastHit or AutoCarry.MainMenu.MixedMode or AutoCarry.MainMenu.LaneClear
                then
                if not bufferset then
                    currentbuffer = GoodEvadeConfig.evadeBuffer
                    bufferset = true
                end
                if not VIP_USER then
                    if lastset < GetTickCount()
                        then lastMovement.destination = Point2(mousePos.x, mousePos.z)
                        lastset = GetTickCount() + 100
                    end
                end
            end
            elseif AutoCarry.Keys ~= nil then
            if AutoCarry.Keys.AutoCarry or AutoCarry.Keys.MixedMode or AutoCarry.Keys.LastHit or AutoCarry.Keys.LaneClear then
                if not bufferset then
                    currentbuffer = GoodEvadeConfig.evadeBuffer
                    bufferset = true
                end
                if not VIP_USER then
                    if lastset < GetTickCount()
                        then lastMovement.destination = Point2(mousePos.x, mousePos.z)
                        lastset = GetTickCount() + 100
                    end
                end
            end
        end
        elseif MMA_Loaded ~= nil then
        if _G.MMA_Orbwalker or _G.MMA_HybridMode or _G.MMA_LaneClear or _G.MMA_LastHit then
            if not bufferset then
                currentbuffer = GoodEvadeConfig.evadeBuffer
                bufferset = true
            end
            if not VIP_USER then
                if lastset < GetTickCount()
                    then lastMovement.destination = Point2(mousePos.x, mousePos.z)
                    lastset = GetTickCount() + 100
                end
            end
        end
    end
    nSkillshots = 0
    for _, detectedSkillshot in pairs(detectedSkillshots) do
        if detectedSkillshot then
            nSkillshots = nSkillshots + 1
        end
    end
    
    if not allowCustomMovement and nSkillshots == 0 then
        stopEvade()
    end
    
    hitboxSize = hitboxTable[GetMyHero().charName]
    
    if hitboxSize == nil then
        hitboxSize = 80.0
    end
    
    nEnemies = CountEnemyHeroInRange(1500)
    table.sort(enemies, function(x,y) return GetDistance(x) < GetDistance(y) end)
    
    
    heroPosition = Point2(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.skillshot.name == "BoomerangBlade" and detectedSkillshot.done ~= true) then
                directionVector = (detectedSkillshot.startPosition - detectedSkillshot.endPosition):normalized()
                newSkillshot = {startPosition = detectedSkillshot.endPosition, endPosition = detectedSkillshot.startPosition,
                                directionVector = directionVector, startTick = GetTickCount(),
                                endTick = GetTickCount() + detectedSkillshot.skillshot.range/detectedSkillshot.skillshot.projectileSpeed*1000, skillshot = detectedSkillshot.skillshot, evading = detectedSkillshot.evading, drawit = true, alreadydashed = detectedSkillshot.alreadydashed, done = true}
                
                table.insert(detectedSkillshots, newSkillshot)
            end    
            if(detectedSkillshot.skillshot.name == "AhriOrbofDeception" and detectedSkillshot.done ~= true) then
                directionVector = (detectedSkillshot.startPosition - detectedSkillshot.endPosition):normalized()
                newSkillshot = {startPosition = detectedSkillshot.endPosition, endPosition = detectedSkillshot.startPosition,
                                directionVector = directionVector, startTick = GetTickCount(),
                                endTick = GetTickCount() + detectedSkillshot.skillshot.range/detectedSkillshot.skillshot.projectileSpeed*1000, skillshot = detectedSkillshot.skillshot, evading = detectedSkillshot.evading, drawit = true, alreadydashed = detectedSkillshot.alreadydashed, done = true}
                
                table.insert(detectedSkillshots, newSkillshot)
            end    
            
            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
                        side1 = getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, heroPosition)
                        side2 = getSideOfLine(detectedSkillshot.startPosition, detectedSkillshot.endPosition, getLastMovementDestination())
                        if skillshotHasPassed(detectedSkillshot, heroPosition) then
                            continueMovement(detectedSkillshot)
                            
                        elseif not inDangerousArea(detectedSkillshot, getLastMovementDestination()) and (side1 == side2) and (side1 ~= 0) then
                            continueMovement(detectedSkillshot)
                            
                        elseif not inRange(detectedSkillshot, heroPosition) and not inRange(detectedSkillshot, getLastMovementDestination()) then
                            continueMovement(detectedSkillshot)
                            
                        elseif lastMovement.approachedPoint ~= getLastMovementDestination() then
                            dodgeSkillshot(detectedSkillshot)
                        end
                    else
                        dodgeSkillshot(detectedSkillshot)
                    end
                end
            elseif inDangerousArea(detectedSkillshot, heroPosition) then
                dodgeSkillshot(detectedSkillshot)
            end
        end
    end
end

function DashTo(x, y)
    if GoodEvadeConfig.usedashes then
        
        if GoodEvadeConfig.dashMouse then
        
            local evadePos = Point2(mousePos.x, mousePos.z)
            local myPos = Point2(myHero.x, myHero.z)
            local ourdistance = evadePos:distance(myPos)
            local dashPos = myPos - (myPos - evadePos):normalized() * dashrange
        
            x = dashPos.x
            y = dashPos.y
            
        end
        
        if isVayne and myHero:CanUseSpell(_Q) == READY then
            CastSpell(_Q, x, y)
            elseif isRiven and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isGraves and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isEzreal and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isKassadin and myHero:CanUseSpell(_R) == READY then
            CastSpell(_R, x, y)
            elseif isLeblanc and myHero:CanUseSpell(_W) == READY then
            CastSpell(_W, x, y)
            elseif isLeblanc and myHero:CanUseSpell(_R) == READY and lastspell == "W" then
            CastSpell(_R, x, y)
            elseif isFizz and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isShaco and myHero:CanUseSpell(_Q) == READY then
            CastSpell(_Q, x, y)
            elseif isCorki and myHero:CanUseSpell(_W) == READY then
            CastSpell(_W, x, y)
            elseif isRenekton and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isLucian and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif haveflash and flashready and useflash and GoodEvadeConfig.useSummonerFlash then
            CastSpell(flashSlot, x, y)
            useflash = false
            elseif isCaitlyn and myHero:CanUseSpell(_E) == READY then
            myPos = Point2(myHero.x, myHero.z)
            castpos = myPos + (myPos - (Point2(x, y)))
            CastSpell(_E, castpos.x, castpos.y)
            elseif isTristana and myHero:CanUseSpell(_W) == READY then
            CastSpell(_W, x, y)
            elseif isShen and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
            elseif isTryndamere and myHero:CanUseSpell(_E) == READY then
            CastSpell(_E, x, y)
        end
    end
end

function NeedDash(skillshot, forceDash)
    if (GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 2 or (GoodEvadeSkillshotConfig[tostring(skillshot.skillshot.name)] == 1 and nEnemies <= 2 and not (skillshot.skillshot.cc and ((GoodEvadeConfig.dodgeCConly == skillshot.skillshot.cc or GoodEvadeConfig.dodgeCConly2 == skillshot.skillshot.cc))))) then
        if GoodEvadeConfig.usedashes then
            useflash = false
            local hp = myHero.health / myHero.maxHealth
            if isVayne and myHero:CanUseSpell(_Q) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 300
                    return true
                end
                if nSkillshots > 1 or _isDangerSkillshot(skillshot) then
                    dashrange = 300
                    return true
                end
            elseif isRiven and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 325
                return true end
                if nSkillshots > 1 or _isDangerSkillshot(skillshot) then
                    dashrange = 325
                return true end
                elseif isGraves and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 425
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 425
                return true end
                elseif isShaco and myHero:CanUseSpell(_Q) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 400
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 400
                return true end
                elseif isEzreal and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 450
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 450
                return true end
                elseif isFizz and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 400
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 400
                return true end
                elseif isKassadin and myHero:CanUseSpell(_R) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 700
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 700
                return true end
                elseif isLeblanc and myHero:CanUseSpell(_W) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 600
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 600
                return true end
                elseif isLeblanc and myHero:CanUseSpell(_R) == READY and lastspell == "W" then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 600
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 600
                return true end
                elseif isRenekton and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 450
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 450
                return true end
                elseif isCorki and myHero:CanUseSpell(_W) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 800
                end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 800
                return true end
                elseif isLucian and myHero:CanUseSpell(_E) == READY then
                    if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                        dashrange = 425
                        return true
                    end
                    if _isDangerSkillshot(skillshot) then
                        dashrange = 425
                        return true
                    end
                elseif isTryndamere and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 660
                return true end
                elseif isCaitlyn and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 400
                return true end
                elseif isTristana and myHero:CanUseSpell(_W) == READY then
                if _isDangerSkillshot(skillshot) then
                    dashrange = 900
                return true end
                elseif isShen and myHero:CanUseSpell(_E) == READY then
                if hp < (GoodEvadeConfig["dashPercent"] / 100) then
                    dashrange = 600
                return true end
                if _isDangerSkillshot(skillshot) then
                    dashrange = 600
                return true end
                elseif GoodEvadeConfig.useSummonerFlash and haveflash and flashready and isreallydangerous(skillshot) then
                dashrange = 400
                useflash = true
                return true
            end
        end
    end
    return false
end

function evadeTo(x, y, forceDash)
    startEvade()
    evadePoint = Point2(x, y)
    allowCustomMovement = true
    captureMovements = false
    if forceDash then
        local evadePos = Point2(x, y)
        local myPos = Point2(myHero.x, myHero.z)
        local ourdistance = evadePos:distance(myPos)
        local dashPos = myPos - (myPos - evadePos):normalized() * dashrange
        DashTo(dashPos.x, dashPos.y)
    else
        myHero:MoveTo(x, y)
    end
    lastMovement.moveCommand = Point2(x, y)
    captureMovements = true
    allowCustomMovement = false
    evading = true
    evadingTick = GetTickCount()
end

function continueMovement(skillshot)
        if VIP_USER then
        if evading then
            skillshot.evading = false
            lastMovement.approachedPoint = nil
            
            stopEvade()
            
            if lastMovement.type == 2 then
                captureMovements = false
                myHero:MoveTo(getLastMovementDestination().x, getLastMovementDestination().y)
                captureMovements = true
            elseif lastMovement.type == 3 then
                target = getTarget(lastMovement.targetId)
                
                if _isValidTarget(target) 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
                lastMovement.type = 3
            end
        end
        elseif evading then
        skillshot.evading = false
        lastMovement.approachedPoint = nil
        stopEvade()
        if continuetarget == nil then
            captureMovements = false
            myHero:MoveTo(getLastMovementDestination().x, getLastMovementDestination().y)
            captureMovements = true
            elseif continuetarget ~= nil then
            target = continuetarget
            if _isValidTarget(target) then
                captureMovements = false
                myHero:Attack(target)
                captureMovements = true
            else
                captureMovements = false
                myHero:MoveTo(myHero.x, myHero.z)
                captureMovements = true
            end
        end
    end
end

function GetAngleOfLineBetweenTwoPoints(p1, p2)
     local xDiff = p2.x - p1.x
     local yDiff = p2.y - p1.y
     return math.atan2(yDiff, xDiff)
end

function drawLineshit(point1, point2, color, width1, skillshot)

    if(GoodEvadeConfig["oldDrawing"])then
        apoint = WorldToScreen(D3DXVECTOR3(point1.x, 0, point1.y))
        bpoint = WorldToScreen(D3DXVECTOR3(point2.x, 0, point2.y))
        
        DrawLine(apoint.x, apoint.y, bpoint.x, bpoint.y, width1, color)
    else
        
        local Height = skillshot.skillshot.radius * 2
        local Width = skillshot.skillshot.range
        
        A = GetAngleOfLineBetweenTwoPoints(point1, point2)
        
        x = math.floor((point2.x + point1.x) / 2)
        y = math.floor((point2.y + point1.y) / 2)

        UL = Point2((math.cos(A) * ((x + Width / 2) - x)) - (math.sin(A) * ((y + Height / 2) - y)) + x, (math.cos(A) * ((y + Height / 2) - y)) + (math.sin(A) * ((x + Width / 2) - x)) + y)
        UR = Point2((math.cos(A) * ((x - Width / 2) - x)) - (math.sin(A) * ((y + Height / 2) - y)) + x, (math.cos(A) * ((y + Height / 2) - y)) + (math.sin(A) * ((x - Width / 2) - x)) + y)
        BL = Point2((math.cos(A) * ((x + Width / 2) - x)) - (math.sin(A) * ((y - Height / 2) - y)) + x, (math.cos(A) * ((y - Height / 2) - y)) + (math.sin(A) * ((x + Width / 2) - x)) + y)
        BR = Point2((math.cos(A) * ((x - Width / 2) - x)) - (math.sin(A) * ((y - Height / 2) - y)) + x, (math.cos(A) * ((y - Height / 2) - y)) + (math.sin(A) * ((x - Width / 2) - x)) + y)
    
        UL2 = WorldToScreen(D3DXVECTOR3(UL.x, -175, UL.y))
        UR2 = WorldToScreen(D3DXVECTOR3(UR.x, -175, UR.y))
        BL2 = WorldToScreen(D3DXVECTOR3(BL.x, -175, BL.y))
        BR2 = WorldToScreen(D3DXVECTOR3(BR.x, -175, BR.y))
        
        DrawLine(UL2.x, UL2.y, UR2.x, UR2.y, 1, 0xFFFF0000)
        DrawLine(UL2.x, UL2.y, BL2.x, BL2.y, 1, 0xFFFF0000)
        DrawLine(BR2.x, BR2.y, UR2.x, UR2.y, 1, 0xFFFF0000)
        DrawLine(BR2.x, BR2.y, BL2.x, BL2.y, 1, 0xFFFF0000)
        
        
    end
end

function OnDraw()
    if GoodEvadeConfig.drawEnabled then
        DrawCircle(GetMyHero().x, GetMyHero().y, GetMyHero().z, hitboxSize, 0xFFFFFF)
        for i, detectedSkillshot in pairs(detectedSkillshots) do
            skillshotPos = skillshotPosition(detectedSkillshot, GetTickCount())
            if detectedSkillshot.drawit == true then
                if detectedSkillshot.skillshot.type == "line" then
                    drawLineshit(detectedSkillshot.startPosition, detectedSkillshot.endPosition, 0xFFFF0000, 3, detectedSkillshot)
                    DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0xFFFFFF)
                else
                    DrawCircle(skillshotPos.x, myHero.y, skillshotPos.y, detectedSkillshot.skillshot.radius, 0x00FF00)
                end
            end
        end
    end
end

function _isValidTarget(target)
    return target ~= nil and target.valid and target.dead == false and target.bTargetable and target.bMagicImunebMagicImune ~= true and target.bInvulnerable ~= true and target.visible
end

function startEvade()
    allowCustomMovement = false
    if AutoCarry
        then if AutoCarry.MainMenu ~= nil then
            if AutoCarry.CanAttack ~= nil then
                _G.AutoCarry.CanAttack = false
                _G.AutoCarry.CanMove = false
            end
            elseif AutoCarry.Keys ~= nil then
            if AutoCarry.MyHero ~= nil then
                _G.AutoCarry.MyHero:MovementEnabled(false)
                _G.AutoCarry.MyHero:AttacksEnabled(false)
            end
        end
        elseif MMA_Loaded then
        _G.MMA_AttackAvailable = false
        _G.MMA_AbleToMove = false
    end
    _G.evade = true
    evading = true
end

function stopEvade()
    allowCustomMovement = true
    if AutoCarry then if AutoCarry.MainMenu ~= nil then
            if AutoCarry.CanAttack ~= nil then
                _G.AutoCarry.CanAttack = true
                _G.AutoCarry.CanMove = true
            end
            elseif AutoCarry.Keys ~= nil then
            if AutoCarry.MyHero ~= nil then
                _G.AutoCarry.MyHero:MovementEnabled(true)
                _G.AutoCarry.MyHero:AttacksEnabled(true)
            end
        end
        elseif MMA_Loaded then
        _G.MMA_AttackAvailable = true
        _G.MMA_AbleToMove = true
    end
    _G.evade = false
    evading = false
end

function OnWndMsg(msg, key)
        if not VIP_USER then
        if msg == WM_RBUTTONDOWN then
            if evading then
                for i, detectedSkillshot in pairs(detectedSkillshots) do
                    if detectedSkillshot and detectedSkillshot.evading and inDangerousArea(detectedSkillshot, Point2(myHero.x, myHero.z)) then
                        dodgeSkillshot(detectedSkillshot)
                    end
                end
            end
            lastMovement.destination = Point2(mousePos.x, mousePos.z)
        end
    end
end
-- beggining of circular skillshot dodging functions --
function mainCircularskillshot5(skillshot, safeTarget)
        if NeedDash(skillshot, true) and not skillshot.alreadydashed then
        evadeTo(safeTarget.x, safeTarget.y, true)
        skillshot.alreadydashed = true
        return true
        else return false
    end
    return false
end

function mainCircularskillshot4(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget)
        if NeedDash(skillshot, true) and not skillshot.alreadydashed then
        moveableDistance = (myHero.ms * math.max(skillshot.endTick - GetTickCount() - GetLatency()/2, 0) / 1000) + dashrange
        evadeRadius = skillshot.skillshot.radius + hitboxSize / 2 + GoodEvadeConfig.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 = Line2(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 = Circle2(skillshot.endPosition, evadeRadius):intersectionPoints(Circle2(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 = findBestDirection(skillshot, getLastMovementDestination(), possibleMovementTargets)
        if closestPoint ~= nil then
            closestPoint = closestPoint + (closestPoint - heroPosition):normalized() * smoothing
            evadeTo(closestPoint.x, closestPoint.y, true)
            skillshot.alreadydashed = true
            return true
            else return false
        end
        else return false
    end
    return false
end

function mainCircularskillshot3(skillshot, heroPosition)
        if getLastMovementDestination():distance(heroPosition) > 20 and NeedDash(skillshot, true) and not skillshot.alreadydashed then
        dashpos = getLastMovementDestination() + (getLastMovementDestination() - heroPosition):normalized() * dashrange
        if dashpos:distance(skillshot.endPosition) > skillshot.skillshot.radius and not InsideTheWall(dashpos) then
            evadeTo(dashpos.x, dashpos.y, true)
            skillshot.alreadydashed = true
            return true
            else return false
        end
        else return false
    end
    return false
end

function mainCircularskillshot2(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if skillshot.skillshot.shieldnow == "true" then
            if isSivir then
                CastSpell(_E)
                elseif isNocturne then
                CastSpell(_W)
            end
            return true
            elseif skillshot.skillshot.shieldnow == "false" then
            shieldtick = skillshot.endTick - 50 - GetLatency()
            return true
        end
        else return false
    end
    return false
end

function mainCircularskillshot1(skillshot, heroPosition, moveableDistance, evadeRadius, safeTarget)
    if getLastMovementDestination():distance(skillshot.endPosition) <= evadeRadius then
        closestTarget = skillshot.endPosition + (getLastMovementDestination() - skillshot.endPosition):normalized() * evadeRadius
    else
        closestTarget = nil
    end
    
    lineDistance = Line2(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 = Circle2(skillshot.endPosition, evadeRadius):intersectionPoints(Circle2(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 = findBestDirection(skillshot, getLastMovementDestination(), possibleMovementTargets)
    if closestPoint ~= nil then
        closestPoint = closestPoint + (closestPoint - heroPosition):normalized() * smoothing
        evadeTo(closestPoint.x, closestPoint.y)
        return true
        else return false
    end
    return false
end

function dodgeDangerousCircle1(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if isSivir then
            CastSpell(_E)
            elseif isNocturne then
            CastSpell(_W)
        end
        return true
        else return false
    end
    return false
end

function dodgeDangerousCircle2(skillshot, safeTarget)

    if NeedDash(skillshot, true) and getLastMovementDestination():distance(safeTarget) > 20 and not skillshot.alreadydashed then
        
        if safeTarget:distance(skillshot.endPosition) > skillshot.skillshot.radius and not InsideTheWall(safeTarget) then
            local evadePos = safeTarget
            local myPos = Point2(myHero.x, myHero.z)
            local ourdistance = evadePos:distance(myPos)
            local dashPos = myPos - (myPos - evadePos):normalized() * dashrange
            DashTo(dashPos.x, dashPos.y)
            skillshot.alreadydashed = true
            for i, detectedSkillshot in ipairs(detectedSkillshots) do
                if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                    table.remove(detectedSkillshots, i)
                    i = i-1
                    if detectedSkillshot.evading then
                        continueMovement(detectedSkillshot)
                    end
                end
            end
            return true
        else
            return false
        end else
            return false
    end
    
    return false
end

function dodgeDangerousCircle3(skillshot, safeTarget)
        if GoodEvadeConfig.useSummonerFlash and flashready and not skillshot.alreadydashed then
        FlashTo(safeTarget.x, safeTarget.y)
        skillshot.alreadydashed = true
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        return true
        else return false
    end
    return false
end


-- end of circular skillshot dodging functions --
-- beggining of line skillshot dodging functions --
function lineSkillshot1(skillshot, heroPosition, skillshotLine, distanceFromSkillshotPath, evadeDistance, normalVector, nessecaryMoveWidth, evadeTo1, evadeTo2)
    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(skillshot,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 (evadeToTarget1 ~= nil and evadeToTarget3 ~= nil and Line2(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 Line2(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 Line2(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 Line2(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(skillshot,getLastMovementDestination(), possibleMovementTargets)
    end
    
    if evadeTarget 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)
        return true
        else return false
    end
    return false
end

function lineSkillshot2(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if isSivir then
            CastSpell(_E)
            elseif isNocturne then
            CastSpell(_W)
        end
        return true
        else return false
    end
    return false
end

function lineSkillshot3(skillshot, evadeTo1, evadeTo2)
        if not skillshot.alreadydashed then
        local safeTarget = nil
        if NeedDash(skillshot, true)
            then if (evadeTo1:distance(lastMovement.destination) > evadeTo2:distance(lastMovement.destination)) and not InsideTheWall(evadeTo2) then
                safeTarget = evadeTo2
                elseif (evadeTo2:distance(lastMovement.destination) > evadeTo1:distance(lastMovement.destination)) and not InsideTheWall(evadeTo1) then
                safeTarget = evadeTo1
                elseif InsideTheWall(evadeTo2) then
                safeTarget = evadeTo1
                elseif InsideTheWall(evadeTo1) then
                safeTarget = evadeTo2
            end
            if safeTarget ~= nil then
                evadeTo(safeTarget.x, safeTarget.y, true)
                skillshot.alreadydashed = true
                return true
                else return false
            end
            else return false
        end
        else return false
    end
    return false
end

function lineSkillshot4(skillshot, evadeTo1, evadeTo2)
        if GoodEvadeConfig.lineallways then
        if skillshotLine:distance(evadeTo1) >= skillshotLine:distance(evadeTo2) then
            if not InsideTheWall(evadeTo1) then
                safeTarget = evadeTo1
                elseif not InsideTheWall(evadeTo2) then
                safeTarget = evadeTo2
            else
                safeTarget = getLastMovementDestination()
            end
            
        else
            if not InsideTheWall(evadeTo2) then
                safeTarget = evadeTo2
                elseif not InsideTheWall(evadeTo1) then
                safeTarget = evadeTo1
            else
                safeTarget = getLastMovementDestination()
            end
        end
        
        if safeTarget ~= nil then
            evadeTo(safeTarget.x, safeTarget.y)
            return true
            else return false
        end
        else return false
    end
    return false
end

function dodgeDangerousLine1(skillshot)
        if haveShield() then
        for i, detectedSkillshot in ipairs(detectedSkillshots) do
            if detectedSkillshot.skillshot.name == skillshot.skillshot.name then
                table.remove(detectedSkillshots, i)
                i = i-1
                if detectedSkillshot.evading then
                    continueMovement(detectedSkillshot)
                end
            end
        end
        if isSivir then
            CastSpell(_E)
        elseif isNocturne then
            CastSpell(_W)
        end
        return true
        else return false
    end
    return false
end

function dodgeDangerousLine2(skillshot, evadeTo1, evadeTo2)
    local safeTarget = nil
    if haveflash and useflash and GoodEvadeConfig.useSummonerFlash and not skillshot.alreadydashed
        then if (evadeTo1:distance(lastMovement.destination) > evadeTo2:distance(lastMovement.destination)) and not InsideTheWall(evadeTo2) then
            safeTarget = evadeTo2
            elseif (evadeTo2:distance(lastMovement.destination) > evadeTo1:distance(lastMovement.destination)) and not InsideTheWall(evadeTo1) then
            safeTarget = evadeTo1
            elseif InsideTheWall(evadeTo2) then
            safeTarget = evadeTo1
            elseif InsideTheWall(evadeTo1) then
            safeTarget = evadeTo2
        end
        if safeTarget ~= nil then
            FlashTo(safeTarget.x, safeTarget.y)
            skillshot.alreadydashed = true
            return true
            else return false
        end
        else return false
    end
    return false
end
-- end of line skillshot dodging functions --

 

 

 na jaką postać ten skrypt ?

Opublikowano

Pozwala uniknąć większości (Bo wiadomo, każdego nie uniknie, szczególnie darmowy skrypt) skillshotów (Tych, których da się uniknąć) bez ingerencji użytkownika.

Opublikowano

Serdecznie dziękuje za pomoc :)

VIP kupiony. Większość tych podstawowych skryptów już ogarnięta, jakbyście mieli jakieś jeszcze must to have to proszę o linka :P

Opublikowano

polecam evadee i cassio od hondy chociaż prawie się nie różni od darmowego. Jak jeszcze chcesz małych wspomagaczy to są tam ciekawe rzeczy jak timery itd i wiele takich funkcji widziałem w jakimś jednym skrypcie spakowanych i wlasnie też tego teraz szukam, bo zamiast 10 skryptów osobnych masz wszystko w jednym ;p

Opublikowano

Mam jeszcze jedno pytanie, a mianowicie przy chyba wszystkich skryptach hondy potrzeba Prodiction.lua, inaczej skrypt działa źle, albo się w ogóle nie odpala, bo wyskakuje error, że nie zlokalizowano tego Prodiction.lua.

 

Z tego co się orientuję to Prodiction jest płatny, czy da się to jakoś ominąć, aby skrypty działały?

 

Wydaje mi się, że zamiast Prodiction jest VPrediction od Hondy, w 1 skrypcie się dało ustawić, aby skrypt korzystał z VPrediction, a nie Prodiction.

 

Jak zrobić, aby mi działały normalnie skrypty od Hondy ? :)

Opublikowano


-- Prodiction by Klokje

-- Set _G.AutoUpdater = true to _G.AutoUpdater = false if you dont want to receive auto-updates.

--Version 0.03

_G.AutoUpdater = true

 

 

 

LoadVIPScript('VjUjKAJMMjdwT015VOpbQ0pGMzN0S0V5TXlWSFRGMzN0TUU5TX4WCVAKM3N0DMW5TdxWSVBEs7P1zUU4TZwWSVDG87P2VEX5TX9WSVBINjN0SygYORFWTVVMMzMSJiodTX1QSVBMVV8bJDd5SX1WSVA+UAd0T0Z5TXkJDlBIODN0SzYYKxw6JjEoVkF0SUV5TX1WSVBWMzN0SkVydXhWSRZMczP0S0V5EPlWSEgM8zNji0T5BnlWSdYMczPzywV4jXlWSc1MMzIQC0V5FjlWSUeMMrM/S0V5y7kWSddMcjK0S0V5TDhXSQVNMzPpS0V7KTlWSdtMPzP+ywT6xzmXy9qM8rD+Swf9xzmUzdrMcbb+i4f8x3kVz9oM8LX+ywb+x7mVztpMd7v+C4Hxx/kSwNqM97r+SwDzxzmTw9rMdrj+i4Dyx3kQxdoM9b/+ywP0x7mQxNpMdL3+C4L3x/kRxtqM9Lz+Sw3pxzme2drMe6L+i43ox3kf29oM+qH+ywzqx7mf2tpMeaf+C4/tx/kc3NqM+ab+Sw7vxzmd39rMeKT+i47ux3ka0doM/6v+ywngx7ma0NpMfqn+C4jjx/kb0tqM/qj+SwvlxzmY1drMfa7+i4vkx3kZ19oM/K3+ywrmx7mZ1tpMY5P+C5XZx/kG6NqM45L+SxTbxzmH69rMYpD+i5Tax3kE7doM4Zf+yxfcx7mE7NpMYJX+C5bfx/kF7tqM4JT+SxHRxzmC4drMZ5r+i5HQx3kD49oM5pn+yxDSx7mD4tpMZZ/+C5PVx/kA5NqM5Z7+SxLXxzmB59rMZJz+i5LWx3kO+doM64P+yx3Ix7mO+NpMaoH+C5zLx/kP+tqM6oD+Sx/NxzmM/drMaYb+i5/Mx3kN/9oM6IX+yx7Ox7mN/tpMb4v+C5nBx/kK8NqM74r+SxjDxzmL89rMboj+i5jCx3kI9doM7Y/+yxvEx7mI9NpMbI3+C5rHx/kJ9tqM7Iz+SyW5xzm2idrMU/L+i6W4x3k3i9oM0vH+yyS6x7m3itpMUff+C6e9x/k0jNqM0fb+Sya/xzm1j9rMUPT+i6a+x3kygdoM1/v+yyGwx7mygNpMVvn+C6Czx/kzgtqM1vj+SyO1xzmwhdrMVf7+i6O0x3kxh9oM1P3+yyK2x7mxhtpMW+P+C62px/k+mNqM2+L+Syyrxzm/m9rMWuD+i6yqx3k8ndoM2ef+yy+sx7m8nNpMWOX+C66vx/k9ntqM2OT+Symhxzm6kdrMX+r+i6mgx3k7k9oM3un+yyiix7m7ktpMXe/+C6ulx/k4lNqM3e7+Syqnxzm5l9rMXOz+i6qmx3kmqdoMw9P+yzWYx7mmqNpMQtH+C7Sbx/knqtqMwtD+SzedxzmkrdrMQdb+i7ecx3klr9oMwNX+yzaex7mlrtpMR9v+C7GRx/kioNqMx9r+SzCTxzmjo9rMRtj+i7CSx3kgpdoMxd/+yzOUx7mgpNpMRN3+C7KXx/khptqMxNz+Sz2JxzmuudrMS8L+i72Ix3kvu9oMysH+yzyKx7mvutpMScf+C7+Nx/ksvNqMycb+Sz6Pxzmtv9rMSMT+i76Ox3kqsdoMz8v+yzmAx7mqsNpMTsn+C7iDx/krstqMzsj+SzuFxzmotdrMTc7+i7uEx3kpt9oMzM3+yzqGx7mptpFMczN1SgV5x3nXSJEMczN1CgV5x3nXSJHMczN1ygV5x3nXSJGMczN1igV5x3nXSJFMcjN1SgR5x3nXSJHMMjNhSsV5DPhXSdFNcjO1CkR5LLhUyRdOMTI5Ccd43HtXTd0Ocjbzycd5APvUTdEOcjOly8d9CrtWSNdOMTL+y8d4xzlUTTDNz0w1ykR5jPlXSfVNMzPrSkV4UnnWSVZNMzNwTkV5TQ0vOTVMNzV0S0UNLBs6LFBINDN0SzAXPRg1IlBINDN0SzYNPxA4LlBINjN0SycAORxWSlBMMzN0S7VGTnlWSVBMMzN0SEV5TXlWSVAMMDN0S0V5TXEWSlBMMzN0S1U5TnlWSVBMMyc0SEV5TXlWSUgMMDN0S0V5TWUWSlBMMzN0S2U5TnlWSVBMMxE0SEV5TXlWSXQMMDN0S0V5TV8WSlBMMzN0S205TnlWSVBMMxk0SEV5TXlWSXwMMDN0S0V5TVcWSlBMMzN0S3U5TnlWSVBMMwI0SEV5TXlWSWIMMDN0S0V5TUoWSlBMMzN0S3E5TnlWSVBMMwY0SEV5TXlWSWYMMDN0S0V5TU4WSlBMMzN0S305TnlWSVBMMwo0SEV5TXlWSWoMMDN0S0V5TUIWSlBMMzN0S3k5TnlWSVBMMw40SEV5TXlWSW4MMDN0S0V5TUYWSlBMMzN0SwU5TnlWSVBMs3M0SEV5TXlWSREMMDN0S0V5zTgWSlBMMzN0Swc5TnlWSVBMs3E0SEV5TXlWSRMMMDN0S0V5zToWSlBMMzN0SwE5TnlWSVBMs3c0SEV5TXlWSRUMMDN0S0V5zTwWSlBMMzN0SwM5TnlWSVBMs3U0SEV5TXlWSRcMMDN0S0V5zT4WSlBMMzN0Sw05TnlWSVBMs3s0SEV5TXlWSRkMMDN0S0V5zTAWSlBMMzN0Sw85TnlWSVBMs3k0SEV5TXlWSRsMMDN0S0V5zTIWSlBMMzN0Swk5TnlWSVBMs380SEV5TXlWSR0MMDN0S0V5zTQWSlBMMzN0Sws5TnlWSVBMs300SEV5TXlWSR8MMDN0S0V5zTYWSlBMMzN0SxU5TnlWSVBMc2M0SEV5TXlWyQAMMDN0S0V5jSkWSlBMMzN0SxQ5TnlWSVBMc2I0SEV5TXlWyQEMMDN0S0V5jSgWSlBMMzN0Sxc5TnlWSVBMc2E0SEV5TXlWyQIMMDN0S0V5jSsWSlBMMzN0SxY5TnlWSVBMc2A0SEV5TXlWyQMMMDN0S0V5jSoWSlBMMzN0SxE5TnlWSVBMc2c0SEV5TXlWyQQMMDN0S0V5jS0WSlBMMzN0SxA5TnlWSVBMc2Y0SEV5TXlWyQUMMDN0S0V5jSwWSlBMMzN0SxM5TnlWSVBMc2U0SEV5TXlWyQYMMDN0S0V5jS8WSlBMMzN0SxI5TnlWSVBMc2Q0SEV5TXlWyQcMMDN0S0V5jS4WSlBMMzN0Sx05TnlWSVBMc2s0SEV5TXlWyQgMMDN0S0V5jSEWSlBMMzN0Sxw5TnlWSVBMc2o0SEV5TXlWyQkMMDN0S0V5jSAWSlBMMzN0Sx85TnlWSVBMc2k0SEV5TXlWyQoMMDN0S0V5jSMWSlBMMzN0Sx45TnlWSVBMc2g0SEV5TXlWyQsMMDN0S0V5jSIWSlBMMzN0Sxk5TnlWSVBMc280SEV5TXlWyQwMMDN0S0V5jSUWSlBMMzN0Sxg5TnlWSVBMc240SEV5TXlWyQ0MMDN0S0V5jSQWSlBMMzN0Sxs5TnlWSVBMc200SEV5TXlWyQ4MMDN0S0V5jScWSlBMMzN0Sxo5TnlWSVBMc2w0SEV5TXlWyQ8MMDN0S0V5jSYWSlBMMzN0SyU5TnlWSVBME1M0SEV5TXlWCTAMMDN0S0V5LRkWSlBMMzN0yyU5TnlWSVBMk1M0SEV5TXlWiTAMMDN0S0V5rRkWSlBMMzN0SyQ5TnlWSVBME1I0SEV5TXlWCTEMMDN0S0V5LRgWSlBMMzN0yyQ5TnlWSVBMk1I0SEV5TXlWiTEMMDN0S0V5rRgWSlBMMzN0Syc5TnlWSVBME1E0SEV5TXlWCTIMMDN0S0V5LRsWSlBMMzN0yyc5TnlWSVBMk1E0SEV5TXlWiTIMMDN0S0V5rRsWSlBMMzN0SyY5TnlWSVBME1A0SEV5TXlWCTMMMDN0S0V5LRoWSlBMMzN0yyY5TnlWSVBMk1A0SEV5TXlWiTMMMDN0S0V5rRoWSlBMMzN0SyE5TnlWSVBME1c0SEV5TXlWCTQMMDN0S0V5LR0WSlBMMzN0yyE5TnlWSVBMk1c0SEV5TXlWiTQMMDN0S0V5rR0WSlBMMzN0SyA5TnlWSVBME1Y0SEV5TXlWCTUMMDN0S0V5LRwWSlBMMzN0yyA5TnlWSVBMk1Y0SEV5TXlWiTUMMDN0S0V5rRwWSlBMMzN0SyM5TnlWSVBME1U0SEV5TXlWCTYMMDN0S0V5LR8WSlBMMzN0yyM5TnlWSVBMk1U0SEV5TXlWiTYMMDN0S0V5rR8WSlBMMzN0SyI5TnlWSVBME1Q0SEV5TXlWCTcMMDN0S0V5LR4WSlBMMzN0yyI5TnlWSVBMk1Q0SEV5TXlWiTcMMDN0S0V5rR4WSlBMMzN0Sy05TnlWSVBME1s0SEV5TXlWCTgMMDN0S0V5LREWSlBMMzN0yy05TnlWSVBMk1s0SEV5TXlWiTgMMDN0S0V5rREWSlBMMzN0Syw5TnlWSVBME1o0SEV5TXlWCTkMMDN0S0V5LRAWSlBMMzN0yyw5TnlWSVBMk1o0SEV5TXlWiTkMMDN0S0V5rRAWSlBMMzN0Sy85TnlWSVBME1k0SEV5TXlWCToMMDN0S0V5LRMWSlBMMzN0yy85TnlWSVBMk1k0SEV5TXlWiToMMDN0S0V5rRMWSlBMMzN0Sy45TnlWSVBME1g0SEV5TXlWCTsMMDN0S0V5LRIWSlBMMzN0yy45TnlWSVBMk1g0SEV5TXlWiTsMMDN0S0V5rRIWSlBMMzN0Syk5TnlWSVBME180SEV5TXlWCTwMMDN0S0V5LRUWSlBMMzN0yyk5TnlWSVBMk180SEV5TXlWiTwMMDN0S0V5rRUWSlBMMzN0Syg5TnlWSVBME140SEV5TXlWCT0MMDN0S0V5LRQWSlBMMzN0yyg5TnlWSVBMk140SEV5TXlWiT0MMDN0S0V5rRQWSlBMMzN0Sys5TnlWSVBME100SEV5TXlWCT4MMDN0S0V5LRcWSlBMMzN0yys5TnlWSVBMk100SEV5TXlWiT4MMDN0S0V5rRcWSlBMMzN0Syo5TnlWSVBME1w0SEV5TXlWCT8MMDN0S0V5LRYWSlBMMzN0yyo5TnlWSVBMk1w0SEV5TXlWiT8MMDN0S0V5rRYWSlBMMzN0SzU5THlWSV1MMzNtS0V5THldBFBMM3V0C0X5TXlWFNBMMis0i0VujXjWAlBMM7U0C0X+zTlXiVBMM650S0QdDXlWEhBMMyS0SsUyTXlWz5AMM7R0CkS5TXlWSBFNM2Z1S0XkTXlULRBMM7B0S0W4DXhWXFHMM3I1SkWYTXDWjFHMM/41ikaozLhVgFHMM/Z1S0R8T/lWT1LOMv51yUaozLhVgFFMMvZ1y0V8T3lXDFJMMnU2yUT8T/lWz9LOMvv0SUGxDftVj5ENM/R1iUZ8T/lWT1LOMnZ2S0Q/D/tXRBJONyL2CkF/T/tXDtLNM+71y0QzjXhVjtHNM2q0ysFuzXnWjtHNMyv0iUZuTXnWylDMM9M0vTriTXlWXhBMs+80y0VuzXjWj5AMM/S0iUR/DDlWTtEMMXN1y0VkTHlXlNBMM+x0S0RmTflWRVBMMzdxS0V5OQAmLFBINTN0SzEYLxUzSVRLMzN0PisJLBo9SVRLMzN0ODELJBcxSVRJMzN0KTwNKHlVSVBMMzN0u3p6TXlWSVBMQ3NwTUV5TRs/PWN+MzdxS0V5LwE5O1BPMzN0S0W5EjlVSVBMMzN0YQV9SHlWSTMkUkF0S0V5TX1WSVBMMzJxSkZ4T3lWSVBMMzN0S0V5TXlWSVBNMzN0S0V5TXlWSVBMMzN0S0V5TXlWVVBMM2Z0S0V7TXS3SVBMO3M0y8P5DXmQiRBMrjN1SlI5XfmQSBFM9HK1SET7THkXi1FM7rL0Sl15j3pBiVLM9XI2S4L4j3pQixJMcjF3S5j4zXiRCJNPa7O3SFK5TfmQiBNMMjFwS5g4TXhJSdBM9TI1S4I4jHpXy1FMcvF1S5j4zXhOCZRPJPN2y4M4D3mRyJJPNbEwSwR7TnmLyNBN9HK3SB25iXpBiVDM9fI3S0R7SHmLCFBNLDP0S4M4CHlWS1BP7rJ0Sl35iHpByVXM9XI2S4L4j3pWS1BPcvFxS5j4zXiRSJZPa7P1SFK5TfmQiBNMMnFyS5g4TXhJSdBM9XI2S4L4j3pWS1BPcjF3S5j4zXiRCJNPK7O3SFL5TfmQSBBM/rK1SE25TPn0yVBMEPKaNMN5DXmQSRFM9HO1SkT4S3kXiFZM7rP0Sou5TfcPiVBNJDN2y8N5DXmQSRFM9HO1SkT4S3kXiFZM7rP0Soi5TfdPydBNJPN0y8O5DnmXCVdMrnN0Slp5zXnQCRJMtLM2SoO5DXmRyZdN9POzSkR4TnnLydBNtHM3Sh35DnhBiVDMtfM3S4R5RXnLCVBNLDP0S8M5D3nRyRJN9fM0S4I5hXhXSFNMrrP0SsI5DngOyRNNJPN0y8O5DnmXyVhMrnN0Slp5zXnQCRJMtLM2SoO5DXmRiZhNMjJ3S9j5zXjRCRNNa7M3SlK5TfnQiRNM8jN9S9g5TXhJSdBMtXM9S8L5BHiXiVlMrrN0SoR5R3lQCBpMdTI1SwI4jHvXyFpM8vJ+Sxh4zXhLyFBMpTN1SoP5CnmRiZdNMzJ0SgR4RnmLydBNP3K/SsV4zXlLCNBNP7K/Slg4TXhdSFBMdfI/S8P4CnnRiBdP8zJ0SkR7QXnLSNBNbrJ0S4V5zXsaCJxN8jJ2Sxj4zXgOyZxOJPN1y9B4TXvbyBFP9fI4S0V7zXsXS11M7rL0Sk+4THpByawzf7K/Shg4TXgQCB1MszJ0Shj4TXgNSFBMJPN0ywM4BHkRyJ1OszJ0Shg4TXgQiB1MsjJ6S4Q4Q3lXy15MpTJ2SBj4TXjWSNBO8zJ0Sdj4TXiQSBFM9HK1SES7Q3kXS19M7rL0SkQ7QnkQSxFMdHG1T8S7THmXy19MbrH0SpM4z3pQCxhMdfE8S8V7TXoLy1BNszH0SIF7TXlWSlBMLrH0SQV7TX0LC9BMtzP0SwF4zXhJSdBMDDN0S0F6TXlWJxNMMDN0S0V5TXlWTVZMMzMEKiwLPnlSSlBMM2wzS0F8TXlWJDE4WzNwTEV5TQs3JzQjXjN3S0V5TXlWuW9PMzN0S0V5aTlVSVBMMzN0SwV9S3lWSTQpUUYTS0FxTXlWLjU4Wl0SJEV9QHlWSRcpR2cdKC46Igw4PVBIMTN0SxZ5SXxWSVA7W1IAS0F7TXlWClBINTN0SzULJBciSVRLMzN0LjcLbRJnSVNMMzN0S0VlDX1fSVBMcFIHPwwNKBRWTVRMMzM4PiR5SX5WSVApQUFUIHd5SXxWSVA4SkMRS0FwTXlWLyUiUEcdJCt5SXtWSVAqMzdxS0V5Kww4KlBINDN0SyALP1k9elBPMzN0S0V5WTlVSVBMMzN0ZQV6TXlWSVDMUXNwTEV5TRwkO3AnBzNwSEV5TRA5SVRJMzN0JDUcI3lSTlBMM1YGOWUSeHlSTFBMM18bKiF5SX5WSVApQUFUIHN5SXRWSVAOUkARfXE9KBo5LTVMNzR0S0UcPwt2ImdMNzB0S0UWPnlSTlBMM1QRPyAXO3lSQVBMM3IkGwE4GThWTVVMMzMoKSoVTX1fSVBMR1wHPzcQIx5WSlBMMzP0z2s4TnlWSbCDIVA1T0Z5TXkhK1BINTN0SzILJA0zSVRKMzN0KCkWPhxWTVdMMzMVODYcPw1WTVNMMzMGKUV9SHlWSSIpUld0S0FwTXlWPT8iRl4WLjd5TnlWSVBMMwM0T095TXkQIDwpdksdODF5SX5WSVA+Vl4bPSB5SX1WSVA+UAd0T055TXlle2V9CwpAenZOTX1DSVBMV1IVe3FBdExkLWZ5VwcWe3Abf05WTVtMMzMWf3McekxheWZ5MzB0S0V5TXkPCVNMMzN0S332DX1RSVBMQFAGIjUNTXpWSVBMM/MsC0V5TXlXSVBMMzN0S0V5TXlWSVBMMzN0S0V5THlWSVFMMzN0S0V5TXlWSVBMMzN0Sw==04DC87886CD14CDA5F24A724B1696EAC')

safeloader(_ENV, "da08a7ce8c8d184ce83214c207fe758270191101932553719497738b65d16211fb8fa84c8e907c81550241440051b8697d194723a12ad874f7eff2c2e8602a3c0a269f27a8247c242cc556031ae6ee383df8cb33a4d5043fd7b45336588fa533320179bbb8ef49eb157ff33579451cb603205526b84efe2ab46e501243c9ab732fe95accd2a9f0b2754a6eaa7150041303eff7351858a19d6df4fc19dd4da0fe10d9857956e33fcccd3ca245f03957ad8b132f4b227d928edd78e9834941a3b4f405af366e02da1d0922391de934ffa5c63fce8a46b7879caed62fb8dbc1eedb70dc8943c6b604570e22afa9ea09c36952fdc9d26d398c40b43f999b04b1feef2c589e47ca990d2d20d37427287db0677eceb1658f84141ea56fe108f496d0601acfbeb526020270026ce352cbe0dd951563c44df5d8c882b387c21a3334d5be40dfd3254600bd9a8faf0eea839ddb514416de7c64b3e6e8ba7aee8615268a1a51e07cee4f8cec46beb0ad4620df8b382cf6247b591dc7ee04214ca718610697d1b63afe5229bd37fe2c209eb6b7b2a8d763dd1ee6c262b299773a06d8f948105d20f249d1ebff26633c1471f5ef0e7b567ad5c2554bbab1411a7ff195f0601b8e84aa8f1850af70c15fdce85da760c622956a7f014d6e82d570f705b99be9173234fbbd8c193670495315f22194ed7a95db0a1b5a24aa007e8ca0b8e16f0ec1b29228203598489f2553f0807ab042b01ad5fc76aad09890214fc39246ae83b7493cd3be77d931bfb91263858c288cdc2718e305d5fdbb92084d6a69fe846a0b119161ab7d2f413b471c9b13f56f71723aa78cf6b0f3ded84eb5e353e6c25b536bdd57af589ebeff2f96305d83b42814dff70d0776f5a791bbf04870a3f24ad20e19620c8c9654ef07e136705e9dac0a1252e88a28eb4cb3f37c42cd132bb2e9bd5556bb3426be96fbc6592d966fa1d1dc3d819443a88e79f826460e86e6fe5f9dc4ffa35f60293931363d755b0856ced6a900408cf8334ff344fac2fccf1b87295d3ce5f969e4a82d09eec2f133d7df04d1c94db29da1773d94ebb28124908189f161c1d24247d5062e68a8db927040fa0850022fa667742a98fe9193374f03ed2f7f11649cfb8e63a4423eb16c54a733f16ef2340d594e0a29a2637e2e9a1ce41cc62f08ba3e51f567285482808160e2f2094f0270f086af4fde523cad961e9b8ae090c15ff1fce1bc131f2e768bc171cb18bc0d1d4c5f7b4e147f498d74ce397caec508e946f4f6f0125c63bbc0eda0ee821d777344112adbda33028abff604cc5fb569c6d9724416096e57810b5455607a30c5420f78e32c66012c479365bc0b2d9cc543cdcd057c6b58f5a98765a2922eb7706ee970cef55123ed4a1c9fcf0481076f4c5a42cae2578d774ba596b8fa9dbde0b0279f791f46e853e9429424f78245b022f8b2b22015bec4ce9f74c1ba64f1b7b77c1a548699d3a90ec98d1e88c8e90f379f4ee0a40025ec7646f8eb3754e36b954ccf1e7c79757664a3837500855af02f42da19c167b2ea67e6eb97411119d676f96251469ed33b17b8b7a9e2a51ec5f7cc139ea83185eac9ca3e6c5e0b0c7548235c534390e59676fcb685edfa4e7e46a25c9c1ddc1776312d41e89abe00a267ec30476685e1c4a1a30f09eda2581382afedb4f4b6c9dc854ff1c36876fee5a1067e5cc87d99880d194e773fed0a96203b70144ccf620636d74d4adcf25e7b2f6ac77782ad43efbf880326180c839d9261861ece9452b77a281c31cfac79127e8c13a7d86ef8918e1dd9ac536fd4cdfd2fc6b69a552f496bff484be45813aca9a5622a2111f118233605b61bde4067e27511c10164952cfa4131885c3398351fc8738fd62bb542c3044b767b97e1118837eb3a5a9e823c7c668b2a0a428911c892c5d9b5628b0b66117bfac4e90fe6862933ed6b052cbc262bb80c3126a5e881f41b11e38390cccb81a680bfad06e2f520ab4e27507ea5a8181b1c01f00d404fb72bc468fcda3d10f1fbb22963aaea086a55f8e671c79fc7a3ba9bfa893338dd13414cb32ae6805b715da4b7db3c0e0faf57a3fa22ef6f71bef68eeac01b7b2b707c25d1500233d25865dbde127d1fbb9ea9e57aa7fbbd28f63ab5c6864dce76b9ca2a2b32f7689a17fdf0b535e6df31e9545da48babb8fdc282d996016acf0bde2796b9cadbb6dce121b4b26c25675239beb160d26106484dc39f89954985b9ebf084da83a43de97863be2038d5483b71a580ea40bcd267a6427df57805f3f0ef951751f95c682f53c186de678e362c652b57da362762de158796e2b541818506c81c0c06311107686dd71655eeaea2e01ba3e8a5e5cf36f8a80c1754bb28028e4fa3f315a004fe45c0cad8ae3f1aedda7c189218d21b199a612d03074396dfda935303c5e3a0566ca502acd88038fc1b63880b843f6d608e59db0ead39a77f1aee24cba9bb0b0f46e3e156a791fc0fa55c8a12e8b8e72bae60dc96726ef08af95601032c9843605165105828ed3a7e0a916b81147b317b160eb2c287c6f677e9986848ddcf5e1131686b3a4dbcd4060131ab0169148cb2b8e88165ded32acf34261b399d472b492835e9e82dc8f94f0add348c3cd932122a2952e7d6027a37ee8463f6096ce881789f6e879c7edfa5aa5cec9d1f74457f77c5f4b0171aea08d642efda3c72ee3616eb2d00ab88cd692b21552c9c333e0ee6debd7ef93200b9db0266cae2724973eb5373e1137865039ba5473e80e8aedb16c50f428a48f80089fbfe6f43ee18f4faba0899d76c5f71ad848a6a901de603d3b37463bf530dcb17a2711b03917b4152530f808618c3f7c4da52dc81dd379035e4e6f908a0b4824d9b2f542f11b2a37c0289d36c88aec83e745ab77bd175177064441c155514f86857dd6f2efbb87f7b3f3cc6725456fd198948814206a3184fa7afdc0822e693c84d4679318ddc29b828ff46a723200bd888cbe0ba4af253ddf1c6a6cde54998e2a1d49a1d2c4ec727ec2c4073f3465759caff19f957a996c7f807239c2214481e79e44dd8b569d29df70a985fd7ff93d7aefc7bb77dc05c4708c1ced517792672e6dee51b4b4d9f75c06f3536c888ae648378dc48a37eb08d0b19db3809fb4ed81d044810ea2686ea2f149e0aa45299eabd338270388e9e34132e465c6a62ec6ab7fc056f18dd25660fa05a34885a339f17119762616d080889809a5d956bc7b2246a36defcd84ba39497d2ee2e86e91d2f43762cd5801f376caf968ca8081c5465c2024cfc8e47471345c330a8ee181bdd07d174660cbb080d28c5a21cfe00313a324a16a981bf13702c48db9349cf2e265837885cd47dfcdec8053c09112ffe32a3e709f269563ef8dabb02241ca328d3ce3ab3f7f6734f0ef318e6bd14a3e5ed3f620156025c300a7b949d09d538a3a5aeb110f9c3390fb54a7b8b249c187abf492b015751b2c0da5912e5c5603cc9b575ee8d10603c92dfed7d0eaea1788be775ad3d2fe55719a3572f0baac3d9849281fe8d708ea4b3e469d2920bf37d4b53b32822cc6cfaee87a0d5ccb146658c14785370b9fa253cea1d8bb0f7edf43aa311748c63bca7e725ba18a0457aaf3cd30cc1e5c5633153217ec4809cf2b60df1c0614e40b5687f9a6669cd6b8359e8988b4058a8542207ea367527e0e3b5879aec626a053aa99011cf8aedb2dc47b46f2779859264d87aeea0b817dbae47391ca30708d5d9bfb1ff8a957d994cf160524575dd7d10fd4ea5d8e5ed53a8cecb9208d37a18d94f3f809f3e1fc155e6d75b5e360230ccb530173755efcae1944cd7f115d6fe6d0980b591937b9efe9b04cf50913edb2a46f2eea875ba3f692aaf7ad88f21cc23ddfc770ccacb6e4cfb7e9d8fb4db052ca448ec97f600d7201af1490db111e43ac82965d9afb0a4acc77366229c5416df488ab670d81db179054974c96784ee0a6366b72a4fa8be423a5f8ce91cea428533bf09fbcd138d53c1375fde803f05eca2e2721f7b65d1b2c0cc84b6541b49c7dab0e4bc14dbfc78db55899fa2e5c806883e70307705cc256333942e6b0675d6654820c6c3b846f7ed7a0b89d27035d1a65dac4f3fbbddab38713f91d9037029c419c34d952cf967d7c194d73a3d5e2d5ac5e9707586623f580e2dc689d93189207cbfa56ed7f309eabbf56da4360ab1612dd34c24d17fab35c7f3115688b2261cf9def76979e4cfcc2666fe15eff493ecca9a0e67d130f3747ee25da5ca0efc1c07a499abf9e0c1baf8353478b9b264a0aacf8adb91e8c24006d8a3e3beaad81851bf34af3a82df107992a44dc95693b335da818a291e219a5d7f822202d2ec661a7a83c6f66449d7f633408408b360fe049c7e775d0d8ccf1478532c07f5cdbdd33680d784131b1f5ff8603348b1ece2320409693ddf2d1155238337449186934bdcce5a76f39ef1f4090e59593b1e9dccf030d579cf73a5e14a7a2b4b2ce8f5efc2ad8235f19f41c4963757fb3e6075568410479e416a6836d441a367822908f93058cab2d4f0f0d49bbf423c63181e7bf1108768e895c058a01ac8d1656354e9a0c98e5d93a4a154de56c885f87792ebc89dd3167d022a615204cb8cbbfb508b30421a5d58faf010fe995f0f549a5ea444fa9861ed2f7c29459fc7fd8149e50568008b764ddcfa5620157bc1e052c433d3eaf9911ba034c15cb6d75546a5fc471b75fed3ee3225b9c255718cd5806215957fd4519b596ae6342556f21474f6ff17e2e4f38825ebf53568a64ff446b3c67d96d58e42fb304d578684b0d1890d2e4a04de8b5212dd7ca959ba468d856cbc248bd1e6b2927055dfa45c34aefa0dae9ca3408220b9eb07566f7b502a9f05b6a580dea95ed2536a623691defea48ef6ce0d0c39b8d8b02f07801e5dbdd11dc0fffcea165101c86c0f2f4610546e9da520bb22f56d62e44429ff493dd7b8bdb7322b1ff0f2c05c7bb05bb5291761785464aea0c263bee0c4c043a01eb056161843dd9f81f4d7f62acb3548269cbc9b8d5f9ab7144a677321168f672c7665b1efe12fa095cc9769b11146af656e496ff8e45743014723c0a63499534a3e648f036889a1d6a7a174f83ed4b1e45724960d2fbb6641f160abf89a6ff84ddf511b9ab203022a0cba442dfa0ccd5cd5c839c6230427f820028895020a216d23a6f1a79fa4f593e0414477ebd754746230a5388ead25632bcd810546546be856ebb07431b4a97ac3058f008da18cbf192625e44e14af955d09d4a21eeaedc0dd1bd91a67cfa2cfe832423845ef51c75a993a28ce4f9f8a97ef577ab6ef52b6bbcaad28d282a302c53d4a450b30115ee80709e3200ba6bf820981e1da9ab3a85fec62b495b68e7d3c0bedb1c5108b9b6e2d20b501eccef503695255ae55a004c940bed46c03cdeec15aff5d00bdcaf0a7657689dd4023b4c6e4037ef8264d6e600ad89300c037e7c1ffa8ba4f2911d3e87572778a6700c23f2a78e1a9e5c288e3e458b71051c6208836cda2f199112b1b472bae939dda76b0e625a85380559cd33907d361cb06791df0476ecc19d0c87e3d92895880a6cb47ec1d10d5e6caebc8426633690ade3240e699d0cd4bcddae6892b7d0886b91cf1d11cdadddd48fb845489b599cb735124048f64ec9b93a2321e89f596f20432c5bea5282375d51fdecb64485f316adaaec2cebd0e2b6d9821603b99d51f0395c959be9f1f78f10344dd3017438979d9f75690af11c12c1b93023e81a49a819299cbfe5d74d8d4e8c3f6b8549b418c0dbc0de646f687791c89176f71136642fe87c0869abbeae1146ce570a2876c3ec5c8e9df98136b01efdf2f9056e2848b2b0f44fbcfc9f558d53839bf6f7aa92e20b88974e451f7416fadf6eddae18c38d0990793cef0a20c405f36536eac1411e7f47aa1f0d7e5db4cb6e0f914f01ae65d5f9d6433702ec0e349f6ab54e25b3c57d4aa35f2232bd5e0f4efeff39857a72773875a540841f2dcb969bf631863f71ea0a221a1aa4c472b3e3a656cd2ec5a8da796b360cb39f4a8f7f38bc14ec43e0293be39fac59e1b530a4aacf5a10e00230e5dd4ab3772e6a094de2d441abcfa5aba388429948c09459ad36c76adf4922bb2c982e6456121913d34c3f55dddc5474d307a9c7e618bcd3a14bbe46f534a2664cfe64a47cd97e60a34f7c772712bef81613ce237db897cd641977ffd594cccdd4a8a41262706599ed4acb5b1b34f17bb62a19133425d267fdfe9bc916e8994973b423eb1af849e7891384fe1bf0839cb3d2871523f4e40012ec89f1431eee8b5f1e25b57f2ee31556d6e3a943b7990cde6d101d0b66b1f708cf4684730a4ec4cba05a7b131e055e82e2e5b0b62ff090f1961c0a2e5ca3c3a86b5164eeea838ddaffecbb0b38943b366be2b9a469e10a879443da150f714f4c2a27dfbbf9751b296197d885a34704472cb3c28c749c1592899ea4f55e4f80d714238fbf0c0a29b69c300da530beb5e1c3e090686e7df3b992f42b2dc5992de9b37c97b2b4534dbdb49fc66cae036eb928274ceb75c7b95058b242d378782c8f51fa4ec042c34d9055600fdfa7aafbe6a29ac4f9e771b7c0cc3dddb7585f5871ff0d02b8934725e22c00e86613e536dd2d3cea0437eb551c3091909a9852aa61b4a12c17079b8d66c158dd570679a9e6d9c14d812b3a3e3d923da531dda1e3a163f0429065628c68ba5b9e82f71c0ff7f9d74a592e8718c76f54c75f7ab49f2f975035699ac0626ed55deaf5b3b94d45fead801efc309a2faf36ff3db5cd699799f927b9b0003438765d422e8bc990864648b436b7d1e02ab69e0a680aa55df0a6c9d8aa0c9a7cd44ac13e8cf1c4312836e66ff7916232f98110f0b0a4f551e37ad12258037f59577a01ede642f8f917cfe2500b451be2daabc67526ae9ec3e5e22991785b3771d7c2f8b13428fc38ebf0499e53b4f6823797f8a69a4402fd988ceed5fcc7ceafd19aadeb2c5a42d36954e02c3e0937744bd19bf827f696e7336d7be6a07e6b51295fb5464bb69d34939d6d7c000756ccba3b9ddcea334a918cfb40e3191fd1e6f650114d4da8fe6a210a59d371cd3850bf2abf9da823a08ae5a1d31d5befa325fd0ae1c0c8a893b5af5faa98b293dd0e3613f2542b4c6f6fd0a80fe6d40499374ad7dedb475b5db62bffd62a0481f048ce8e6e20cb09ef774ed0b4955d125e0a55c1d891dab1ffe6649fc68191ab6ea9b5fad6a42f141a3508cccf2d2105af3b8206dc030f444cd0934ac632eb482cd049da1b5abc4472e9098b79049e852f6be151c0fb62334b585f355edb446d2613b0dcab11a3a80ebb5da58d8b2bad137ea7dc9b814bc6adc5570692118f6af50ca70226db46a0d628290679f3cdaca1c1aa8710ffe283e5e966c643b15b28e9eb6f7843e9364b1c5dd631d37fa805e5251a8d83c69e20dd97a5368d7f93f874790f984127144577255f106520da0742765ca28a25dd299333be75811dd20b851e28b23b13d047f94ff0176f5f70ff90b6b2d8093c40a6747b5f8e5b71ba146eec673e3ca4fe4f7375398fecbff9899ae3dd447b11e6cd92e2bc56b9070bf4fa194b6b5a373b0016fb097ec8aa91182bb3659af398b3d300f66cee05b5481366329b93871dd1f5efefd1611239fbce13fcbcb2ca4a7f04d65a826f1b661797d4b982c43949a03132c1b0c461d49b9fcc4b15fea98f908d95ee6df3ca4a8b8b30dd41390e034d377ce2a9880daf0da49533536584883ee2c6eef78ef8f05d2ce884bd86ca79a991b4087f26ed506f762be2f213f9f5df2de6664fd64f8a0a7dbfa75e6fde3c3e29ff6dc49a5263fab2dd7954112d06f3bb701270346f193a003028bf57f41a660a7c5b8dae02ad37afbe3b7cf62fcaab2c437e3a941c6a67a184804cb9a41e4273d6f7a406baca23459500205502c9b0e1eaab3d8ca105c5b8871443a8344bc03d00b6a54f05088b0cc24c665d65541c21f2444e6766acccc7586b4e35ada93e8b5578942fe97a76b4692a518ac9359cfe1d6976468b4a35ae42e454922e9fde69f7933b8b23b03b6086203af39dafb1a53aa145021635edd581bb6b564c135165b3f53be7fd599cd3153eea5a0f625691ab60a709ae4ce387cd6f95745946f8d7cd681714e6807afec0bce5898c7e6c4bed138dfc56206f08560581c49e369e7c385e4640b45b5886ad2207026a3e7d644172f5ed523c63883ca258915a1eeb2b30b38c84db8b4714b1b823b782b109f29d6c8bea0f2c7adae02225beb8f08169436ebd4957779ad1c9de1c308a06c5b823bcb1b756a3e4a7ba150bc147a4fd09b7c54026d6aeeb722bff6eb0cfff697ce829a81f351ce0ebbe1ce46bb195a0a19cdaa2d68290d022607e43fbe19d6d0e196675f85a7c7a95be1f5b8fa615b776d1383eeafc8a8e633fe655206138bded951c8580e9c5ba93be695e57563c9129793669cfd1abfcfc0b00cccfb031981797d3db2bcc0cda4ff1a6ce1ce113fc33957d38e388947e76790609c7208c466057d045df64c91c80559520fbb95108946806f9332b86546ac14dbb6c91e865cf07b93b676c399fe49d5f58f18f66d01f306d6d8d68abd75e1ea202fba187b769f1dd593aa6ac6e0834065d88a571cc1793841bbe6f099a6599d6b9de9eaf327035d119136b81173194beb021c9eaf04f32f2b5854381b828008488e35a9d5eb1c41abab1744035065e1fe219a7ab87a8e28de99051d5316a828fff37ae72f2fa9404fb2c1cc94b9b83347d1ca3157a382e1a126a98e84c3c58ba9cf87fc67fb64d66fb29a64e6b56a1932735413bb7e4343fa0f3301ad2af93bea1a2d8db1eaf608e86c585d67024915aaa6534c65dfaf126dee033aec35b221df08c3d771925d5b3955c781c416639ba3aa1329e529cf634aa05d369e58260a16f2c3670bf248860a9a73d56c42244a26851ade831fccd87a808ee101e632adf5811a946121b76d9ece1347a6d87d4c49737b327b20cb070f81d0ca2a7bdfbdd775abd245951497d0ddb2729db3dfbfa903cd039450846ea5f3e8d3567eb32d4dde45154423f55367af2b679113ffb7bfb092d592918bdf3791195621d0d5c3db9ac48c16b13233a68f15f8ca9e7233587ece0fa1743e8ba6d4783ffafb3a39d0a30d06f6aa1f99c497e24b72706778f0923a1b5f9bb010ad94b6a980da40f88d7829d23f080c5f9c5fd0f3dc54af0a8a03df97f51577f812ae9c2ab13bc504d1228a3fd141e68cebe0e3b8fa0d9cd50d2fcf749cec402a017022d8c8e9701ccce9e467a7e190277279a61f4180e7780f00500b01e2953dbbecdbf97e553439c8f90c9e56e05c8dbbf27504a2b7f369f96ea9a285587b62beaf9adee28019ad86a58bddc2cf00dbaa34f8a7b0ed8de911986551fc0c3e65ace5b0c6f7b0f42e372b5b59c7674cf6d869147bedcaef21cee9d0b6ebd05748fc9ab1e2b4634ec0023115c7a6365add8551844ee454fade1e3ed095f8026ed9a6696ce90f55f2e89e8ba18ab508053a3f350f51e2071800ac6bbb610064c9a6ec276d83a4f198960f6c212b95b27c9fa1eca35218ea62bc771e44153f04f3b79cb225c602ac3fc3b469983d8250150497de73f0cc385a82383c3a0c4ce51f064af6e64ce66dd535af7f336cb4ee7cedabb931ef0ebcb9b35ad101333061e3c1b7281736808f58918e4b754dffa85be1d0203a93870e71dc755aa92a0077bba0b8bd636c48353a450a140fb8f76e9609f0e4b603a24fa505850efcacb456abb7ea7a585e0c2b1574bc15fe8914b40801daea1aebef5a5b2f67132cf0b22f4159bd962bf67753ad78e93e6e0e4e880c9b6a5b2a84ca002b2e3b2e969bc828e1b1fd77917797e86c1aa23bcd990a87c52260e448210d5d056cc9b4afd3a9204c4ecb533e119aa64395cbbe4d31ffa78a5a90ff43f802cb583d3d2369966a15ed907ed12073e161ce75a4b3147d2f09761bafc6f2797cc171d4009954be8fbc6561844dedcfdb3042fed5889a971f8f523c39fd8fbd10c8079d7074fcfcff03a8e22e6f06869aad15c8940aa4d58a2ae209bdee571e100c7b62fb253b79538f28fce04d616b91a526d032f784bfa025be362297da4f56cadb8384f14c093c8cda456e6261b1f983295bd1af937e570911b73c10d7f6212675d10866fb7cb0f1df89c5d7fdfe4f99bf081e94876e2ed44c7690e1ad5dd4631a32c867c12bc039ccc7e311ab8ccb8d5a81415b79f6b04f4306415f8506a8ba6b6328fa0fb2e88c9eb6b4e2f917632b8c4a11af99a97bafb2bb60222b43d0e18d0d6f85b317508900a872c0fc50fc32b1a9dd6517b1406651437b02c793af813e8d5eda735b5cd5f5c2a32693b9987ea89514bf625ef441d90f12c2575d57f05cc814b5f225182d8be0b87522dfd8796714f5ad59c7c903516cd15c1ac9e5382bdaa759803a124fb05b66e867e8c29bef4f2ac27d2d3b208dd4a2709f9991d0e8faf1060e2ea645a22e7a80c6a42b1df839f1c910d8a099604aca6d6ef7a35292f1e2dd5bd99a910df1e31e3c61573e0ad371af4d8c437002f5abb0c56ac54003cdf640576e85196fdabc904e1f20516f98d22328512c2be1546cffa7562e2ca474d761790702eb27a663e366a629d960d45966b55b8c252b14c45418d7636435fbb3c067298dd55a9986eefb28d7aa9039187e5b9447341eb982b6488c51294f826d66291fa3aaad0e26d387b704ab3ad5b8025966e4e47e01e876675060ecae66ad90d538a28ae7bcacf10cee10d430207bf8ee41ffb32cc4b9cb471936021236be011a42e01bcf15cd9e59b356c0c72603f5d42458c37aa359c48d5dbd70214e6108da8dd4ec28f658d8e1363ace9a0cb9173a2790d13ac9a2e5323173acb9b201db111e6e527d4d910f2262f2c0b605de09a2b40f645dea48338936b0393d326ba12b8c08b7283a7611e814405c8399399039656067d6dd2e94ecc7aee8f62e17b30b6a3d5775e8b1e4f56e2d5d2e13b248646b1ac5485a54a86a5a863e4a60da8bbe78558b5bdbe53dba0c834bbaffdb9515b14efa644587061473a2a64e2d9fc6b85473be27c723bf0b0ebd93ac217a8fca6750c2efc4267d2df07a5b805c0decfbb9a5d7e388c83efadc6a3bc609b119ca6700520db0961a49d4867793f620db344a2fb75ce8c559bb518b62b273853079cabc816948cee23fca4120200700b6f8d74d863d7523a3edc81edf4b019e741d18bf4acd7312e41436a187d638ed64870e9079790bcf353a480f92d31834eea3b8c368f8e68f202556843bd441561392e75343fd34705ed84a60b1727e5fdca621781794432a48ddc01e66405e3712f14780700530bb9fc46f954b15afc15172784cefa961a5b4e81a18d55458b35f529b5f63a74858f76f50a5a49287afc8690a0cb4577acb500142d7b854fda3b640e3d11a340a1e6ee701dd8a7153b9234682f97418242a2ead37e210d885c806f0c8de70338fa44076f57ae01e4a46a75c17f2b94f3f5ac331739c2e4f85f6bc42d6d6607ec99498497efc94b2c09da2f19bcf31bb37e222ee0f2d3609066152052a23768065ed5c30d3ad179cd993616caf5b785c36e77410a833cf8e84b87b44df0355b9d5685b495f77d8110f0945ce4b8ce5e350ab4532b0e7e7f441797e45b38149931786de5d8b9ca39c337fb8739175b20440f43862fc202e7c0bbe5f706a658b27c286bd09978b47d17016f6828afb21bcaadcc08c7297be1f3d5dbab819226565fda24013ec45309489b608fb31aba1bcc12d8cebaccc546385f1d673d867299544c0ccd3387f5b641451f8dcda8a3bc4691949f74d1dc3f1212c76e94799d2a99dceff9579f7ff083ae945661ff247f6066263058a611e989b3bf7d4de5af78a55b70e4754a4aaaea25b3801fef18db2631c655306695ac5a0ff655fff4a2c597a83de57a8ea80e438fece58cc822c04f713162115541b9aee825326adaa2d1ad37e6bdab5c060662cdf4cacf2b2cddd4a6176b127902bfe0947533a330ee1cf9b3d8b4a2e4f287e7a98b65979da3a5725d008cd719b2455d6f82a0630626ac36f0a880ada4741123ada0edf54584062f4b701bb60a9e1b5f50061864c91b945ffd1cb217d19c33e68fa9c195d762af67b183056ec4741516fa99cf6c4eb21d1f6a1e88c39a978eb316ea1a15c7d0a822a53861ecc08904a110b643e2c333029417d913ac916f2abcf81ee18f13b8b13991b994c0b79c890e5ff3fa0e5c654a4cea779b624a6c1286b312960275ee8e436bc29394afab4ccb144b118b69192ca579a7624032274558981d1a3e0809583e57ec8b800eed4d72f9478332f336bc172b325fa7c519245350970035fb8dd83f59aa7f26b995487ebbe34e61fed59ffc7fa1f3e6628d7cf623720b488e205299bf51b0352a7c9f19f35b45c7731e59067c2717ff0f23d62acf20eedd33731428d7763ffa6333bca83af254547146b6d6b2c146657dc9977872b45f2fd26bd389f627c15fe8b393dacb001ebc8df3ef610a9c4633ff3e4b6ba3ba2084460f28688e6d93701f4184aac41d228262f75173adf0ace243d605fe090a2c269ac01bf6a9947fc2cc14770a68b0ac8bcc4a4c848a7626aebbd921eaa19e69de3cb8de250d836e7cf6d96326ab54c6c3d4d70d5584cf95f5998233da65d126aa7b15421e8218bb14b686fdf954a97052465dff89ac995439ac6afd27d7c6a259625617c74c98ec12774a0e7698aeaea9a9678ff2bbc51ded818b129c2560605ab417f90d5101db9674a9c46e4114843baaa051292895e0c32b1df2892a08fac06464daf140839a2f87b37c6c523f6ea6b7f030d360b2a507f30c56db85b45a5f086adc2d0178dc65dfe83f60aba3e405316d2b3099b957ce464ad58cb6c848fa1c5f23b94ee0f5fe09299b914079ffe26f3d4da90b7016224a726dde65e36898d890c62ca32895cd3e87d97c4126ec039eb60fc5c17e191f9626a91f74c04570800dba1012575837a3c122cb8b9cdb0458519f654a7b1d91908ff270e85b36981dbcef3e1ef4d9e7b821ce21f05bcc2772611a1c54de068cbb0bfc5615d9c4fa8dcda47219f87a678b3187a31a0faf5f407c52aa898d5a7a70ae6b4ae8423f56a175db3e3b2b879022c7962ea9bc7620d96c532a2950b44c476554f100a6c1c16ffbca13ebde14a19723a35b275794bfa7ad7f165a2f0a21b50bdcbe1fdb900535ed4f53f5ae546420dc25d78aa709535a825bf1025ddc56e192266e66c9748b5f3a1d166e6f6a0c01f77c07fb7249a6181179be37d6e0c6d472af5145fcabe7e35b05050e48d48d5222afa3cdc759c5b5be7f0183e6e049406ddef01d8dde64c1a667562f80811a32d42b38fb12c604cdca804b771722c559ba126d1eedc96b15c679cf390a647adb0e298eebc723ebb89d44dc26389a629890f962ecfa902131ebea5e02759afa4f166706536e77661fab8533f5aaf9b2edfddffb450fbd62bcf8626be0900642fceede5d3f2e2f83e3d25386a29f6c4c2e2175ab650d6ab66fe9c872ef27033b78448912a92df44a4bd25b7517e4829ec086dd55f12983d420c66d19193e729b4b16bed7731171f525c6e5bfd0779d9e8344623804a9b81d4ef713da0a78d80dcb377b0ae927da3d3db316aa4ec62ee16aa905b48924ae2387a7c7b06ccd74b307fcb762d3348aaa851800359031296bffd0b95bb9334015147b20b40c8cae40ad2854333461320c42802d9962c9d079f31841c005d9b1a4ccad02db1ffb9206befd85d824457f1a4a9c1a0fd1473b1ea1496b3437475145b3620d29126f972224971eaed437ae16c0ca1ec34ed6cab2e12f8a7d956a4fe2b73266c167ad19e5425ff9201f5e856bd4564ce4d43bf77ae5d580b646f1d8518cddfac3360c12108a8664bf94ee5ca4c0062257d89e8ecf92f68f7d6dc0daade3c5e7a8951d083f3dbae9556acff19e583077940c718218e7d056d44ee763306c3238b4196bf8d4fc6df04ac20a0db32dffd0a970089ab380a115892493506233e33e9b060dbbf45356a06ba06faf871a46189dc7c9c164d38845375fc64ccc5bd8e216d02115c9ca58dd3a55be154ae8b0ea1a755302ff0461cb8b13407129b8715b9292f712d78088ba52d10361d4b233d3642015871e10e9fd1244b201a0f4bd3e013b4ac8801e1d1465054c16266f381329b5c4d8d0ae2b66c44ca5a539336081f20f8ff7bc62755604e645f4a37f8600d02b9b2f22b03e70fcc08c4d2310fcfaf3cf37b6fbe20639dd011a4843635275cb881ad8990c848837bc58a546038d6d90e02279f9b4beb3d72221162c9a51862e1ff1cf26a4dc643ce6083aed9fbe011dd65f61d66e9a37919447edddf4a0033c1769cbc99c285e7f943cfdb99361eea51761676f9b6f7b1bbd19ae0e04aa7cc871b4f8aad7111c70ef44fa6996d0f7b00db81f6133300b1861d05cbfe9b4cdee14a6e7a61b0163eb2f973b7c6da8f48f0acedeba1bd4d65536c85c4c5af8869f9159f0caafc5e8de85c1158c32ca60c3c66d809f9d5583cf9f462279e811c025f5983b94186e7bed3770d3ca559ac3ef1d00b1689f8b274c026fa1a37db4c06203efbfff2949b5f42b9ae643950104ef235c05a0670216677086e5ad5f88aaae5345aaf17290df870727ec7f632a0c31d071d789c49a6d4e8bd137eedc5db81937f6b7191612c61e84f925e7952b458c5a082e47ccf000e2c9b7e9c61ca063ad3db67affeb35dce1cb6eeea5704f10a3fadaefadd1e3572d208ca346752138d68c5c4a168374666e89c7cd1878d338ceed3b56cd9fdf0a3f11ef8db70cccaf173861629283e7fe194795a0cb1e1e65e4068bb3531379a1119ceebaa331109c297ea3800fa9e9632d38d86fcd5009def2c3d932cbda4a8b3187f2ed3b636537389c1ad014f318ecaffc7932459dda851d162e29861e97b5bcff9ba69a83fc90e0e766123bb6e27fe147608103dfb64c7969e15b35b06cef53f4e5f19103cef14b273ec363c96cd2d195f08122de9bd02ce65d02a6eec26363f89c4fea8da7f844649f2e4f4d7f86274b0991c5a596a55760ff5971666f4d5558376b64aca989ac9f107163270ecf5957628cb748df1790e75870102a690ffa343df417c251cad456125fa86b3d8560e37d5c6b863f7ce1993c36858dc45496592b7f6330fe5e6e99194750e084c571aa362647035bf71912f64d403380a33cee5df4629952e40814f41fe4ae6b714b6df1e294089d889b2c008f3ae417e43413de41bebfb1121e63da2ae40f1ac3c635c12799ac2b1dda8e29d776d49c87e71e740fb2674dd6d299036f517d41e420c6b8c3e434aab01f873e6e2b1215eb809d8d65d865e3825f445a2ac680e96235a47abd9d07e8b6a356d74384c98b306156270eba6fa0268549284eacd50fa4e69d0c278ded7a282b9c4b1dffc498c18992b1f46f6143cb9ac245abd9e05719fc1d6666f935c34feaea885eaeda7a3c6319b39b07fadb95b0ea51b43016a1643a582ad0015c749e9d9bc9b192c5d013abdb00eb03ee81380aea8d7fb4c54edd8812c7299c762f93adcb0dfd3890533d587b4ffee184bbe1a5d6b712edd0df33dacfafa5b17f5cdd0085be183e01a2712b0f0a28941685ad5c20a04543e6b61e9ef6a417939efb786260f95ae37167d1d773e410cd45450ffdd3c09fbb2dcdebe1ad276e64c3618c79525c8373d4127f6df2983221a65192cb0dae52dc68ddd62ec98d801342b9eeea4718f1765e66d70b1cd9d5a3cf95c14059d3daee3efb6db9499c1b6ec7778ae3d15609ab75625cf3b0b5730eccfdf90286236a40f652670cf839f6a6352421aec8a0488064038a630a735c82a9ee5af1b5b2141bc0c300ae95c3cbbb92e2af24a944d420ccc12e21463c9f92fdbddc1ec5175a9c4f2232148200266cc12eab2cd7a4115cb4c1528eaa3d52cded7dcea649bd7098a5500b3fea9bf949c4edf243dbfb89ed3c566f0555f5467d9d9b04644f886a94260332a4698653d6da2926a150d94479a995a9c1412871d4e9b075d1e019527b009b3bc86b5ee72e1d47a702cf8c556cfba9e80f3eae61407c9f05534dc6fe769d7a3588918181afd1e1e0ab077c8faf12b2a131306eaf3ccaaa9799e5527f5bfcca65773f4a0b615317c9edbfbcd77ea3cacb9dc8a35660622330bbea04db6f118e502913795883f83408211f71316414a3c57944f49ec75ae9ac5fa900578429e3c1e13fcb3efbecd9c41390832ab8d28700ca8c70f75b0a033fd3389bdeaf2961190ba47f78576ef7f6f996780c5173e4c8661008eab36cd5b0e8312f3e0f8d4f84eb6ef03f2b756a11010cc95a524f8c928c93e9df906fd3a962870e4229dd065866f67f2e214a41aa50742c7c66616273ddb90b1fa2ee01dfa84dfcc41a30baa5e8dffbb05f3d95173f85d43d43909489e7a92b20d54d7bcb61472773c6da80bfe9825cf9a4d33f8b2b4338cd34cc8f7bd07563b3bfb3feb0a1e27470f320d5aec073d750cd82f6d2d2a830c722d0e67f04adf8839fcba9bf6ba8555bc802130460edee357c4f6e793d7ae7d07db3923c068b81bc796a46d185b8ecfc4d1a2597abd853582a25684d61808950ebe34ffb37434c19c8527e632ceece60ee4b09b3484b6e9c2c597b76b1f94f0b13f4a7d8e1f0ef08c5d71accdb1350aafee41ff2fff1bf18ab7834d277b588da0b35b76d4f68a1ad7dfc641e35b17dc087f2d0960c9a5532fc9e2b8f7101666d139c5a440d2023b679a70c009c3d14cd82c7171a0cd0cc4d1ed3f88efcc800dc7cc05b3391b035cdf1d54e8ae5f91607ede9283af5e83be9407fa8a327d1721532e2b868fdd6926d76fa42458b63571694a2d4272d9776d4f8327fc60150e3e55aa2c999dd6bf00e251fda0d99907fe89b50ed9955a393586cd41ac64b187238c08e22fa2ad87e1928336455da1ff43fb6827e9be1aed1bdd0def57e2319e4b629e7388cb5cbd44aff9c75713efbc8a59b945f4e6a9e76403783dd3bd548cf1e272bc97728347b4d1d9912c0dffeeaffdec8e949d8aa5464f6e26400ee0b94117cb29e99391707c94da954bd2e6f2fb42ab9f726eaadd14f12ef6d4d85b197e5bfab86ca54b65b1a5d5d22ecb40184ca9e63bc5b2f7a00f74760afa61bb708a11c850bdabf1bd4379820fbb81db022884d29b742310b6745c0541b08d74b630ac8209f2136bb5a9f79add5d1072ca2ac3fecf2b63103d62ae7a6c74d116e6ebe681261ae5fd068a557e97b3ecc3f34b266b6d158602cce48647b8f7f8df2b6d5b4811fde8e17f235bb4dce1a7cdf454c952469e43e9e942b50c8142a1c03f9422307451e9276c5a18a179ef4c998c3e301cc7ee90ea524e0b6861fc78e0cde4053b7e92a75c1f82b83a55f08993e548c90fb914498be2c72ff4ee5e5bc1d87ea2170cc6ffdc54d255a76ac6ab95358c0cef6dfd6dffc46e236bf24390a6232d86435f23791db9f9a61bb40315f00d5a26b3fd12c50bc71c8c49ba32002e58a4ead37763a5679c460f2dace9ba7336b8e9aaeb5eaf1c6bc678f9b33d9ce12e25215722acffbe28ac9f26c6eb372f5319ca3d9b97661bbb22d7b6c296b995c7c656baa9690b9fe54af1eb4bf2b006300bc7c0e89317394eebaa4c2609286080ead9c31d3771ffa9e9f215fedd9c3e6684835fd0380a1137c49fe5db4503b4e7e33d22f61755f3e6c031225382c1c81b592e3020bd30691b01c29144524278aa61daaba1fda350e38004c6f81fdd892e30aaf0cef971c1c488152c922b90c1e74709e102bac87896eb25fb00a9f730c9e293e525c4339b667863667d4c9d304d1a55994f83ac1d5786625e714841b1292c71bae8835a366fdf4350b6c2eea35265c379a3f24a61f3fccc8b08a948b622a0c3423ea2436f1c1050813c695dca3ceb68d5a8ab7996e97e70f91b545a4fab57e125ebf34b74b92606a85b43cfc191a27cce8bb2878b0d055e47390af83f13c6191fbd704eb6b0ed9bc3d1987b55873594b26c59acb92ae404f82d15b31b2d7964bf414d7456693b5157bbed2088dad1a097706a89654a84798e8e877d465ac9a74d31da22de3ddbe7886ab8fcdd3e1575aa6aa4fb4a77331dd0cd1db7300cde6e5b6455d584a175691e3d145113bef9cb69373b03127947ac946c6ba96be948c12fd98e14186f10e672930fcc5ad93c98fc71434b6a76b804368c7b4be4ccf0c58b2f498f6f87132ccb2cc39ad967ee93606e06a6b2d1979db33fb5da2687e19ad620842b2e23f453c0620b4f9994cc636bbe7f0b19993f7e94bc65e19a5c01d8bdaefe0b6bdd7dfad27c5497d9b47fdf047f7e8bf2a3f8b2c8e4469e5e7c05eb285b6c92c3f2f24a60fdc99ac0ee097439863e94a39fcca58debe4cb7c1d84d50a617d823d55ff9d731567e8d31248053e9f097ea978304d3e264bed10aaa7dbec1dadb71ddf0b7d9dcbc1c5276ebbf4e28a964ab5a71308546cdce50fb0b680d7646131dfb0f2888e20e1fb861d54637cefb0f6211524ee43b78ca40fe0030b603e1e261b4a6076a066b0fe1ba6714660b4f57feb0636298c6e1dd549d32e52651a5eb6d6cbacb14aad077ceb2310864676c1eeb69ac56251f48389d228d8b99a9a7e473bb4a778375481103e581c0f960d74d02cc67ccd61c9b035a9d4b7b49118a4a2a14649ff4ee4058591a915e5de446d25d60a95ec89034ba94d4d9e3bf92d19f83c33cd9e2090f6f0ea22f25a93536b43de9ceb6cb336a105a557b28c6f7f9a3d7f07343ab20daeb23478ef4e7b5030cb087440d458a1f08f0dfb1a5d491f1e9257c64c8c71158fb4f5d7ec9343b88c4d7d8e0df553a16d101707d80246e6b3811a0ba942fdbd6b2b9b561a57f037f382485cfbddf97ba9f9fb2a504fd0540df2e4ac0c5a1a4e9f3892a3c5b2179ca0f1eb4e91456c22a89e4454afa00dc790289523f832ea6f9b508b60b448c3d734ef1f9797c22641ac506813d699cb83916685bebe8e00ffc52cfdd4b5aba752bd6a0547730aca9d4ead827c817d45c45f7d6d684a39a6ccfd49be047e5b2e8274002bed415e7c49603e8129284903085f57be8ca6941d098c92c687b35a8b6b37b60b073ec3528661a94c2c141ce4e812901ef77b6a8c140d22a5631e7a137969eca6946f54af58f85d5cd2c68088b9d054a23eb951aaac8f26476b337f0b5bc3e7fe17ae2b31f2c74fc6defe2f27e49606bfbc62379c63bd5344298fe0e4ea353ff5b7a5da572a01da6b12d955b357852f9b6b6c4b056a23b7fe94384727e5ebb51f04f9e21d7e656819ec2aa7fa8098061f9d63f28e96ccd176fdf0f90e0eb8e2bf9e7d7deb3e171740688349a20b741dd072a1bdeb1888e42d03f365d8284fb833f362a094c137b06f8836085c0ae072d7fe995796cd9c9c242bd6830446af68c0dc20ae10bc731819b39a8a17394c7d17f24b72e2f5185bffd80cd6d4228431b27f2096606b9a8f90b77e8c4d32cbef96d893344d72932c85d56c8e14d8b51b60b681fc49823d09db8445af004d02a000e581f1bdc04723884d89acef65d256a61ff6b3555f372673aac64afa5c476ece4cbeb1f7ec44f8e7b555e97ff959a61ef922faf4a9966c2213a60a228e70b397892d15672867b83b3b286682bf04e43963ea8850bd1de441e88e4dfe9e918f3069fb1c02f6225c4bac717ac1b2095972e0c849f58a232aa1f14d0038ff33c5d9353b3c586742ff894aebfb4af8f8f2a374882fe9936600ace9133a99d6d5ec2e91ceadd4f246eed81303f51a533bd05a6e5b7f5af844032265122551bf196553461f3206dc634300a65e0c602add5ad29856b3b1a86744d5e9e21e8a77cc76120f02e3bde46fc68d7bda7baa0cf2680bcd30c9a7298a050bc1d831c81b026e5cbf53d3bec00842270362955caa58db8b6e68fdee99cd4eccc4f2eae83e13d5d657e7722484619b9c29a55c105ff8f236be0136c3a7289ffd58d32d05e2cae535d00e1a3b357bbef8350e42d4817d3442157a4197f7b83e793b48b53abf57b933cb652625e3a69294db0fe074ec73a81fc87df13ce41178d3eeda5965dccaf669c8f6497eb7898c7eb738120c5881a169a8d12a3f6caa74ef66ccd17b58ff5befc1723eb94758e2285f90af0d05cf96c093756f91a20677315e0b9c356cf865d57c1b672f4a68e51cae6cea97314bbbacc3cc911ac02075e7d223e8cff6287e5ade4f865b0c1ef8c82f49fe0afb963e55338bb97712daae634ca2b17f2031e65ed880f106d68f1b25b138a120ccd6462913c71c3acb1e1ec6b11801c60aa54078cf5e3ab7a3323868a1f64bbac218a1c4e801afd38aeb5941a848fb6b8f00b98086fca496f5afbb6a693e0a6a288150a9d52be7f41d90a677a06c0e6663507707b36c8349137ff0c68a32277b8a07128ba37c334637e3e67320e7654e011af2b06440d0d260cbfb07418054972902c54b798d8f390ae8bb8cc7e5dbb1e622dc02b6f11cc47790d8e8fac81a905b2a0f961e5d0f4a3fb39f2dbba6cfe43243ed4303baeac1c6a4bec6a2643596571e4e1c6ee407e47f87402a03c398b26b555899e46d0a3e8054cc8b685cb186859d50aeb9cfc726242cafbe926ae1a8fb3de7e835644ff053aef7c55b7e1000b8dff3d2098eb2cc1aaf5c1b9b75cfcff46cfcb7f498336ffc5665c60cb6284ebf53878dad48ee85c603a0208bc14ae9216f0fcfa46f55ff913ddb15ecc4c361660b470f7393455e1552a3af2ae7555a1613c4af285438ba522d341d5335a2a16bb8b3f5465d18842c26b849a50da63e6b11135a92ee18334247c7e3dc1bced3319f583aca5b57f619a939ef2c6df6777eb0ec75710c8e43e9d8fa538afa3261baad702a0fc8df26cac86e1e4e3667e0e6e924bb49d7adaba44814aacc82fea9387d832b92b4371b1cb1502549015e87eedc1bcb987f8a9907b92bebd3ee422065c87d89d8a9a97998330375681ffa8fef1ea9df2156b0e97117e1987e7a1db51afc66f0920dda221c9bd66cf21b6ed333840fa0a49d11b9da0a44d19aaaf3643284cae04bfb4ee1fd4f46b259d99904d575bc25da1a69e8bf0c1d5cc83054119d2b674ad7554803df7678add828b02493b21b9179871c20a45d9dd9219e3ff656e758ec4b1220e840c6f55e5a473b82d3847783ea61c563a1fa7eb40516ab9234db3349bff3d9ca8ae47cc272caf49e1bb31cb351e135d343c81ebbcdd13b1d27e28975592a1ae0a75fb7c6018ae42ebb32cac91e5e6ce3de85a88b801df7c86acf83b5c326b77cb72ceb0fc526bbb10206df25edf435c34a5d8db7b004d533ef0b59f3de0a8e1a1cef2d980aa08993c7271254cf32531c5acde4efbe092beae94222b5db0fb9f67e3a68f723a729f1c21904d762353aa80e54f3d6be3390898839bb1fabf776fa4c42e039863c63df03248c25d6490999d90ead2c36a4744e613c380125b491696b8b0ae30bcff8304a4d925842f0c1ee30071ddc3e1296c73962bb81336c2e16c93960c6eb3c10d409f5d3090df82e9b64934f8af99cb0aa6b103c9246a16b262461ba9e8d1dc30acfe5ccf97cf537627162f875ef692689492a2e5bc49c2262c28f5fc822c5e086f0b1612687f0b277dd655fba9a3e395af5dc1d027ffb7e93dce9a0d05e1593d7310925e83d74291ff8fe948095f5619feae3faeff364ae1b553466d97152f78cf799b9972c426349bc71e65b4493190b87142cace7265625d917d9292af152f0fd594040cc4161c5162697082edaa8b18e1307b7dc8edbda5f2555123710a07e7c30e39acc6ae62762ae53b1991d720ebd3afd7260d4a79e67b2db1c4c07622936d79ab1158eac3069b69277188557dfc4f61bd1bb37bae0560b470688b2487a62b409b2885b4683d931b4cb17c387e7ea70841fe031b8ec01911ae38a3c2d495e5baa89048cc79419f03bbcd578593e0d066f700816cd0cce6ee78ca7dbc6dc35073dd2f10726fe34193a8ecd0e3bcbed005200ea8cf7a23c6f11657f4bd331f5765f5847c191fa4ad73c9341cf83f316ebdc4c4e6fb6250df0e09187796211d1fc6acdf601febb5923c38a137595b91e60671c92e2d04dc8d334c50f4987c98af9e93a1901fc34562d48bb66d10b2d76ab592a5889e5afdc726ea1aa832db299e86147992a1c9119ea07cdeef6435bc4fc3f7e2ddf0b0369b4604440095706ae194fe919f88f8633d8b66f8f83af5a89046584668d9792c88074085e4696091fc5d471705001184004c21b3226fbb5d4065d44509dddaf455b60c127dbb9c6e46a33c928f3d735e364664c046764b8ba01f441ca9d51de4f852f3d9acb4844e3db9bc3dd333543b70082baec402292374c3acbdd44b8f0360d9213a2403beda4a5e5c7cbc5df02bc8f75faa5f9d6087f5e8d467da0cffedf868918f3348e671f9bd53c9ade45537f1f272c6622a0c941bd7f54afcd2fef31b01a93a32ba9950141a8bc700366254d02f1cf424b91fb68a0463cbac2775102d5537441a1f213696af81b2c6a0b869d5ae24ed8d081fe04ba37cb41b6ba6a39372bc39bd57b73fe2632308f33d35b18f58b8425b1ef6744929613b38f74e4f679fb00ab4e3e64e5d3b8158c9dcd96bc78303770706745b1c29be2a414fc764290fdee07d4bdd4655a7b19477c8fbbfbd8c651baa8a3517da1abcb7c7f34b9738b815fc1028f2d3d430eb22435e4f0fbd0b103414e9134607194db56d8c13b1d8e158668777e3ba90f45fa933abd4cd1c00fb183fabab08fdf34a4c0752850574be2482659919632d604077ed58b9ea88111ab359250ba25c4494dfeb92f7c42e2cc0df2340129461653330d35e698f86fc9e4a9cb45ffb8b0b13d23dbd3a513b3fe20abfe3a61339fecf2e294e2e6c0f8dbc0a3f63d51722712b5b3583350f8cfc9acbfbe1e1778e7ee29a265447709c6911c3feb53304f0cdcb5f1ed5c8205863a71d2276e28c37f6ce7c11d4b8a565ade77202f554abeedb68a02f7644e47d72f0fb6b823ad1fbe65259cfe8a39f299d273b2614e2a229204f4885542f869dff13c384c7634c78652cb733d6775ae06a91a6521f8f2e2021c9c9bbe6e1c65c3f859b526abff6639f35202ec7a7463f820b1b914f923778ea9a51487d263f86ce2aa074f14fc64ca0fc9822d28d60ada27ce738c448dc2881bcb472ff3c41f17216f0575bcbc95510e01a7633c4153dbccb5935980bd7ebc3aaf4e61ce905a34985c8086ce64c2b5252993f975f2527d0d603ac575d55316096411d786d92cc16ecf49f9429d35fdfc9718c0e44bb456763efb8efa41e718ce58cce110e8d1f56f311d23f47475e7bc0cc5c52e1af100d887b37e8d6c58348cbb21efe7d8aba683783ac2d875ec3f23672365e5e19c534756a9febc27912792a32dc438eb78dd0eaad227a176aef62ca8c1fb788b0039dade2c056403293f979fdf66a74eef32b557aaf636a01c9db351153997acc8cbbf18bf45b9119b898bf7dc0499817e372af3a68fb88b937d1585942eee76e260c123089d6abd54681509409ad35cba8e694f7bb88a338733dbbf3815c88e44bc0ad23f004215233e5c3f2650615de388aaddf83db7beb321892dbdfcb8040b839007a613cf4292c0c16b9f536bc77af960c6df9a3fa48a4aaba841cd63bc099f51a90c58e2dde8e97891f2539ed5cc10075f39d06c5d490835e6083886141f631f024f1be879423083e123658f65159126d3dcc739125c6e9e4e217a7bee4af4511a3989cd205c08dd3b7f866e11bb48b00a6d01c272c45615df9aab0448fe3c44372e7347654fb0dbc43d3f61e8c5397f5b5910b7119f885343cab454e236f1e7f369f3d44298d73b1743eb1fa73f526556329b434fdc7e8d02e406d0c3f0585bf95551e3d13c331d6de8d11b34805a1a650bf11463c152d56e3a1546d4355e67aa799734594f24418296c7531b99d169de0eeccd5e7509fba714a45d83654b9d7e593a082fc6c31a7614c383e4089fb5f0ef25e8963bec9c8a4db6ffdb671f120e7a610157febc72d9fc8a776eeffca07b881ecdb4c5a17c4f8e10c2699d7b2ed162938211b2ac9c7ec2ff7da4709d9acc8d2089df561d06f38007d8362bc6bd26b210a15d29548e83f066c60946cd122f984e41cc08de8f2c1f1cd3e5dd02a90a2c101a964d3ee9a26cd52fef67cfba2b6819b2497efb5f78ae7d6b965c3b6b79765387aa35a9e896d57518f20255e046fbeac4bdb8736fee8c7e6ce24223059c9f2020f5f3fb7e97e68321d9dae497ae2843877531de9319411bafa1668e81dadb4401e29e2a7621a5fbe86c4dee942cdfd5a8ce3729aa98f42ead03e89990bfc5fee0e2f7ca6e9bfe3f17676aced43202ee8c1d4929e0108ed99277d745e978e924806164624d10522c84315511cc34712cf04a29dc94007dcd3a10233146b434bff3d56416d01903b2c2768cfd1862ff5c026a985743751eabb0095b4a5f46070ef9d38a098b9d0e195c7595ae4819429ebf540d3049dccb75f4a09117b3125208605877731fc8fc35fd77fa1e5c24cd87ac1066cac116cb9fa7350c498b4f3b09c0180410ba736288356a3b12279b3eb91364476f90dc4e0a85f0f6d0cc78cd180409d02cb4e376b4f8c2d7bbd33f3062c97c5b48a7899d360037806eb861fac33d8b021c0149c954b2184d1a719ccb6342c2c50364039775d4a22f118d0d4044a64716c631b08b95df7f5531523b9c19304ca1f92ae4b080e4e8818c9f4bde5197bd817656e0d55326a05f9583adfdbf929a407f6e87e8bbd72dc29934fe80b0466939948450522bb996be203945bddeccf94d8155de203a66557baf7061f86428593218ac04604fa047ab00bd427d828d9e091310e5eed0a9336f1899e5ea95588084a0bbb7150c96fe994a372999ab9779de13578c3a0bf013947812c0a3d7e0761c34ce3c13dc3a4314e1388a259044101dcb115e6f8d5be53da1e63e29576f5ea444648a8c6e20797257c14043c9d236a80c3c5ef54c34117ad2519b298f40447aee857ca5b3bcd9ef4e2ef0b7ab210df2d7d45cd771ca1b7260edf595de24fa64e6e14a0c2c994218d190c282c7f853a5afab3c80edd3e7bea346c7f3e9667854f8d0bdad4af7220ac86407882f3a22ab21e0833bf23526b6a7b32812ad0cb8227d96dbea9d05eb1c655a7fc515cfdcfcd60b8fa7e2189cd5b216fe2aa4294ac22ac0e3d808a4ac11d289148586abd7a1e033ec9523e017cf39afc41739af09d809fc7e2b4b27b4d71385fb806346d321d227d86b32c98028b877c32d919fe9d0604709291e137286e1c10b752b538752d21a1b3581e3f06a20a1f25693a90475f09cef2725ddf4133873c885ba784b462ac78443fb32512b2ad05778993b1172fef55aca084ed150d96c4956450c6c6a186464ce18bf8bd96eef7ada7da22e51d04d27635cbe16ed758c7e1c39afae79df2eae7c8e46397a62cc2acd33499f96824d9ba63ae0c6d3a6f58eff07b78689869b1be2cabfea5a963e62719a50eef967e68ad7478facb6c62e9021d15dbedf20b44844b7049c0b89bb9d9db094afe03c3e1e0ffce8d937ffa073ac808c7e6401c48ea06f0a176220ed7b2bbe9b2b25e74381d43791d3f01bb3bb445e520b0e0bc9e1985dbf9226169e2357bf732eb68694559f73e0bb707d919aaa86f62929e3a1a58ebec3af78441b052fed019ea6ada7e84742cf4e2dbf641428e48b943e46944d0d4168fc2530f84c73463342dccf6aaae74b2d1f9f0e3007d5bac03f147c8d4fe6bedbe39ae0189b37b4085456fa967abbf1ba070db2943b226dc9ff9a5ee8cfcf753690d1a963212ccabc4cf190b1850fb2e1cf3f1001bf5bb4279187bcc881d5ce1d0e8c8b8265d85afe8a5e6671cc15edb4be67991300bbf8f728bb957cf61cc90b16eead69a40057ea8e757bfb20d213af40fe38fd823c62896dfecb7c3525e63b106a4de7fe684a0ac5fca2be7c09350e80fa85b5b8aab8d1e1bb5e15dbd324c6804e52055052425aef54011aa5e99370386b5815e9e43a7788a759207f4e908fe8096beb7113bd8129b67bfc9ba287eab61e1d33c7bd77016d133936e98131218323139dcafd25d67c1fbf01a2ec84fdce8d6d6abc92829ebe153b4c49fa9bde20805a6ee708a720748d23c0f4fa801b09e082237cf5027d9db117cbeaeffcdd69d29e0ae48f35133a638754d6b79cc8ad77ded42ba1dee790555a92f2afa12ad6e2e442c641d176a88ae27e04502e8cee973407d212cb6cc7db05febaf30228ab721c26a61deac134e8240593d20151fa8257039fe77e192061f6190407a20c9e9e1aa2b9c85af66060c1bd534bb2d9dee27e3b12a385fc916433f26687a452bb6c948906ae2b4e317d565a1ac79d4b13493afca84d4b4c5371faa78e1a39d90fac4642621617486843c14cce698e9dbfbc2c584a65407741c7f34abf964eff052dbaf90bd256f46468c805982b4b64cdc83f0266b435d2c18970f64c3443f2a096e6881146f63a8d802c67fe1ebff905364aa5557e85642dc5f3d53205e7a9cfaffc79caa121613fb1595fa2030ee952f1ac8b359466e7e75d3d70f88948ade04384865195c51c8e045e609c569112533206e2a24d41ef40608260e928c32104ef7f3d80ca0891972116369981e882a3fd6174e6f512cb63d5d6a8f4cb5fcfbcc7a3f4676b2503b8bd4fa00ef89d1e165b3bffddce31f3b06a1dfa29824a9ac7e4b8145cebdb51f7c9596154dedb0107ef4645227fdb4b7d6087c4f2b5276d7d09f0ee8401aab89268e577884fde7c70d2257803cfcd523dbe629d3b19db562a31c69899a3cbe2b68c7d351f16fe8351498ac73694ae1347827642606a28c226bebd80561ae0dd8dddfa882b6299b0895e1d4e1b5bf63ae3378d3ff72e85e05e76ad6ad6300f8703a8efde405bdd7d8901416e1cec2ea48369c3ed95998d18ed6e063eac56be6b2ee6130f777d45e798500f21af8452d1ae1b8ae3eb412be06d8dbf1f36eb7342a38233a0e3f2edf0e39f07c3a9adc4c2e9e701f187750caf925ec2c16126701efbd476e9a5bb1ae25f0195e2d2ac03c9d9827e6821b8668a9721034d9e5469d3c43a26c21cab5c75ddbb6ae308a785d0f7503f5ae3eabbb90ac5464a48703861221513a27099c0f0f691f5b8f9c6fcb509f959af7b0f80605b789df9d6950a9623825513b54577148e9a38f8cf4dbced2afbcb88d2ae61ba5a94293a0af4c5a9556e577038b46c7307d43645a4cb876748baef1aa65e9e9fab1df1112802dec92342ca3aa4acd4a8eaa9e2c48bb1d045f3c99371a19d79e03a8623b659e37b72b66087d693d1434434a7d5a5b6eee107bcee988aaa5cb640ea86124d139c57dd0213a6c88460885945d8c9f6ebe623d779e62f19bb5f39ff7cf3d8f15696c848360086f633ae658aa715f9f45bddf5f6651c64053f2ab5069ccb55f16a510d79f0bae9da359ad81b7659334fce8f0d8bcacc2dfc8ca0a79c684821da2347cedc7a20512d4bf998d2a57d6dbfd816680eada24de3a53840ad1d1360c123251ac45935c425d3ffad128fa1ad19e5bba84e8caa0160bcb56b656007cd5449bc6aeb2c5008c6a68795a9f1b5dc061f67185ae4b6f6845c56749bb16bce578d5e194f55524952377d93fdb5962d0e0811b7610e1822ff47d135e10aaa5b5136614ab35d4a8dbae8c2fe5f74c89c80e6590d9a18259c6bc640c4d92aa53f315a5c870f60416ec1b67e3f086309507015e0403c9db8f4f7244a62f81574e487c9210945bf34ce10484508d5f1cd68c62051a36bc93ce2077c4a21592cd2ab741aa0c5fbdc3aa419cd1f00cd394ae8657b1142d5c26fd199a17a69ff65f6063936b2113bdbdfda3fa13ccb3993a071a5fe3df2dfae707d5e692109381c405cebaacd14f7e854f25037e5e784c389c3f1ff3e4f3831795c60b5acee1a27637d8237de3c5ccffb6b6f31194dde165ca6fbaef0da6ec43e5ae629134caf2460c4febc2f3059833084388d099872e11da637e2944d18d8ec7458398fe105563e637ba862d47f09810a7aac0ad6567df33a1643f7e2958f34d89ac2cdba0c8936631dfc8105e70172e5eecbbb18a644daf926f4f23ee62080d5cc19f8cd26defe38829df6ad86bc4908822b1bf469d1e9b12f0f546b27fb43448a47531e407705260796332e24632bdc2e047e6408b6c814d62c2ac559af3cc4fc7c3052f3c027cc59ff78809f113023e87f5e0ec39a93fe07412c8541a6e0a75897a3a31b7bc78ba76f3e3641851d344505472f83ae04168e91e85dc572a6db453419b34f9560b9a9dcfa02c65a460af9055ebbffcec544d7ebd2444befc5744319408a701844d57ea25d665095ba06ef8050b9564bacbfad6d67990816db40b2c81b370e4e6c7b76b09994324cc355514d56dc0bfa206c94277e26b707e333861879238f11a86f6a0085352547480101558abae7f9ee83ab2120c277791e5ce739840593fe129ce9f51b2d01b5b1adac0c08fa3edaee2683639c98c7f6254193f2cdabb7b2ef39e540226ae6de213d438bd64285bca48da3783725ef63e57c3799a0aed490281b9513d2009dddc68dfb75927b99d83624022f29f7864bfca00767cbae3347a30288ff666d5448282948243c5b63eda8b833aad3c8d552115754bc65579386674d36dc902147fbf2ecc1c07da88ee2af271dd2652f2d674f7b93c47500bf6877b0b20009bc730809343f63065d667793a32c8d79494ce70fb6b86c928b432af0c75114c0d549015d9ecd5e878aaa31a1d467bb59e087ddb04ec7f0faf5910eb9add2b4328ce9dc7c55dec3a34ecbb907d0f6e3bfed8dbea1ad2ae998ea72826fabd9c53a65e62456451e95eab3019c768e6de6b28ef27df97906069945773fb73e4c835c7b94ce35127265274bf8285dceba1bd784c9f256613517e78e8e12f02e77470806d9628ec0f9c8f37835e6f5a0e6cbe055d430d6ee9e207ec46bc083eafc20eb8b5956c32de388b1a5e1c15c5585d061641394e17225f85297ed6df64d4bcff8f784379d91fbcebf34706c675c510f038944713613af70760afe2e49c048c9bb7c04c6eb8ea235d87a650cd04a77d518874f38084779f93b6994faf95615dc0bf0a33f8e2ec9055322f7b048a56fc9d1087df476dd7ef85b70cb821303e3d3007ffe52cfdcd0577859d450254bfd9baeee943904adb1af3e2ab2a53f9e52427bab2785fb4dc2c82566e0717fa9fc9a0dcf82075e12fe5bda925150699ad54020546590dd14a4a25bc8a9f531dc9acefebec27eb0476a80a8c582d004bc0f3fcd5439956a28e86519c3524313b6f69a4a83beeacde796d0252761dce69847121eb47d7281f97d1e62cd17c6c77f57c4b77c124b2717444c769daf7e7837d3d2b5471ffdcb4673b01782c1b820a7e22df4583f3ab715ccfb2bdab70de3e1c7230b32457a6f02b6f9a0adde5e745af54d5ef207e4aec6f36e89a12cd513d55e674cff94fd0319682c60e1eb1a8e3211cb63ff9b4db36f6e51a0d32126662cfa85d47fe86137f25ec6a675d885773cce57f2e36c4432722dccc93f0c63857d706622c53451b40bd41e627960c523688b6773c9ec8c5bff5d11918a947e89f9e64c8948c136b8824387ea626d041c2f9a6d9202f7dab27a0eae6001893691cb80793d2f27008f85fe129c207f04682e5fa26edd16c6c3fa463ac80d0511e4bededb36d2b150743d2c8d9af23f70ba3c5a7b87d42e3fbab44ad73ae62eb74842c75462b93026e2f9f7586e1338956973d32d199c2a3f90d363a151dd164e84a19da12151400bbe9d503cd1b6c4ff7ff06fc89752105e78223d687694b43555125a4d6f9eff3091439f117efb84eb3410314bb4999954239cf84d9b3e65d0168e58ca2d5671930dafd9746fa40db7e2aa2614e9a886c4c864049b8ca34c9743c7fe3facdaa7721e3fd68e2abc789019dc0132822e003d1fb2db2b7cc6c1bc5c610da9c85f162a9e1da6913e3bf81f346370d3482dedee5e2fb2d1e9e2c942ca2f447793fb7b9d8180fc5535ea199d0873851be41023497ab8215acad93a9ce4db1d8871c21b8b304a4296727e38b5a353cf4daabd63840bfc61c22c15edbe0d2a9ef473d34aad350d773a434641363cd6608f4700500f2e2028946533f36e1b6ac06fbd35ee3400f70f6acc04485cdcc54fe76ce2d247bca1bcf8ee99cf397a8185823135ae61960f499a5889be7d6c7fb82001974d94479c9b912a19c5cc2e4e586692af64452a0a3fa31bd5d3145e6a01c3e862de55e2408fb15e35c60486b9762b0a688ab390a5848790d271ae63a156bcc281cb407427e7a3e31696ecb7592bad06e54fe8293d89c57e0f88e81be124a52338547194ea4b77747f452b67a3719b0a09d86a7d8196d0d0b2f54e50a2ac7ebcf5393d1caf82eb8f2d566f2524f31186e1548af1c17113877d767ff9afab2caccb34b62eff4db360a6a8875c4b2e78aa92776dceae56d5b87a297835372a7bcf422ddc3af1d555a06d94c231c5110aa41d0d48749202923fca74b2ad466ca1ecbadb737c436646cdb181523ce1413d3157b33dfe024577284149b96a88de9049cda029741935eb1aaf247eaf0540ba95107f0237c6a8c129d380f6329f824829506f2f455abc6efd5b6db92f86e02d095708b7d108e46976d67064f53ff9e9a804408e7f7717c23b6171c098aef904ab9225bdba1198c4c93aabc05559fa20458c1c1c5e231a8e1446baa162db3c04f314dc3b1d047fa9d19084ce7ce2b27c849f62b011403520250b06ae4a6d64a18e3a0cd7028c813a8f8e4868c64efc5cd9d9cc6814a58a25da099b84ab082ae6dd197fba1669a5f4bb7f016928780d719aaf3786fa788e39cb6edfc6b61e50d45a4e8de9e691d7adee229725bf461856f12a9711f0ece7b1d3e949cd01d5d09aea18e34193c051b2aac5d8d10c60d4d448cb1d01d920e0d86aa31206d9029208115285ce76c8e26ebebc97d4cdc024a4e6b7611a979fb415ea15c99acdf7cae6d1f51dc96cefb2773d0c04c72c91c29e0512067939f7766d7e9ed783fbd891f1a73e48c5b953cdd1243a3b37278b2b9b5dfefcbe3fd5347ab9088580d09b1cf8238502023275c01617cce038e4eb5484b70a568070f31cba5344d762e8fd919082baa1109f382cd0b392314673083127b3a0ead3f3f82aff74dfaf95974ff34291b990ceecf2dfa7e287ce8f68a7680f82fab812e3196c4c00e3992725ce88cb530f29ca47481cda6832bda2721185e6bdff4c79da722506052be4a2439e39d89f5a8af835e0a3bde4c96301f81194020ba5703cea8a4eb48e489d1065d00253cc351d91d90fa8061d0e495cdb06aefa8ad9824ca8556e52ea4e2da44989f87d1b2b44b173aa00fa85b3a61afb89fdb64f7202afeb4671ba4bbbf1a34ef7e8955a776298eb036296ba3d1c20f8f494774cd0dbb5b8649222479f5c164c258e0acf2fb39ed8ff749a59036f78863cf0689a805cb2b2d6af84fa2f8a16e98d43808766fbe84b972257cc62f0bb90b0c2afadd193e07d3f8f685a77c1f2bf39c9a6ea9459cfd2febd43d5e16f42a2353090a3950835406f5677c43a116a0f07c57d3592fa2e6d48017ca7d209976ce6833a95fda30bd370b5bcbde8897e249d6f94a639663929959037c0a49f2ca005313159a4ea078aa41d96e6fc48d472cc7b387436407e5f531608300e6718a10476d909fc3918fc564a0c6a411a9e73f297b3a0322425fe90ed3dc80663de510ce60febb09c4dbc2294853d5e24e65a18d4050ba07f135ed6dc56da2e930860f32eabf5b8f4d1dec8a0f671a3bc2fdc1f2b3ed20e70537ae08f36ec5b79a3188c752a752dc2136dba83e28d4d2c8680ddf95bcfd22c3eaa5e0e6cb1a1183c7fbe097a735b268513e1c5ba20ed00b0c276b102c6b00cf5f49ad3126ed24ff4fcbf6aee3312f0341515b69464fa049bf857ac98120e6769c36961bbb5885d1b22d5fa1fa21c924c9be7a041f0331d987094e4fe01abcbbc4d0b6f24d2c4e70a1058a175877198a43eb790ea978ea6bae804cdac66767a28228af0f99c3ae5543e5997db395e259046b1a797de623b7d11460bd510ed0439c64e6cb3ac1fad7983e5d5bf8d1cde5529d772eb4adf34a600e3765b09cb7f60dc356f385fa135aa7e6ead2062162c37038b0d8830e99aefaf7537ffa77775a727547f7e23385517850bc3f2139e6679463d6ea65373300f9ac01596315424f35e30ac346771791478817bcb61edef5babe3dffc63342497087780422ba6263ac7ad91b4bcc899b93caddf7715cea2ac9dd80b6cff896abab0c4ba9f38e2f3102541e4d74b585f88cf8917eb56dcd3e526bd5ad94d79f7cab1ba0508c83052da551a3aa2341353fd2a028133a81893e16aafb7c2df19b901d82c17068c6c3c57f8515d0b305e476b0fd813a63270c9a56a2c0a7a26fb6d8103ce6648f24827ca41132e09426c5cd6f0e7221ed364cd51e90bcb9674d3b2f6e4380ad8f7b96fd6a2ff8a03f3e8b9bb49deb3cfa06b400989752b94c8bcf779c78ace9b11ddc9f8301b8feeb6c4d58817c2b283ca643f969e5aa8b8ceb2c8a3025c4c335a10eed7bc2ed457a34877f22f2c3bb4786b650da495609f3ba91deafc163369b79e2ebad363c5b20239755cbaeced550b3878c379eb3160327284ec4eb6bd6865d13fdbe892897430e964f4df73fe2302976265808419e2136b216b92ec2b544e28e900577c289dd1d2f3f1d281100700633b354cf0cf900c7a19aa4b85505eb5dae1f53ff69c2afe1c035e26d6e324eb8f545306abcb4d9b9cf301f645da4826428089756ae14be20d16c90a4ef7d032a8991af7e437e2534e99823aeab0cd39e5a69bb041ae73a0775af0d15ca1ec2c5bf91a5da287ad607ca2a99dcc9aeecb0d7762e4e5a68d2b95d1c709a750d7dce5648c96249cb22852a1aea7dde4cfd6e0b3217e520f378e90269e385bdf2ba8b98f4fcdee9cf4f735e704b359369e0fbe2a152f64c79d7dcb05546479aa44058f90b747be0eeaa16b933374c20b7e514b77207f69073431dcc462802c6eb88fdfe703ad1a104416737da10f3c56dbca165509426269c564bdf75d2a2d7b88581e1715c3ca18f3706de9aa47fe659b685be9105cb9a1c34b52270798d8ce96a3cd52cfb1448299025d195fc38c518e168d6d25018ff20627568c8e9dffa04d96e20deba071d91dd448f2e7feb84914e55964d4dd72c366f9f15f6fb5de3e279e2123a0ea4a93b41bbdb0a6e034d852a230579e563100168259a14ef038d72eb0bcd0d443bd0b8376de0bb10e7abf32cb2b588ad6c952f6f1cbf8a115a32090f57a34d246990e5cd6c9164e5c514b8cbfe8b2e9cb848305eacc500109a0f1e2315904592190a4a09f923fea90c201e550229f51cf897dd6eac21163da4396f4adfd4ed9c8b750cf48cca3c9482c0ab14576201c4d2b502e0d4e6a7fbc137cf5eec679616dd488246332cac91e38953647fceb4a0f835db8eca4737c4d0854975b9c1980c06cf5a98db92011f8ced342d9c5b578eff627a62864a163521ab53a1977f2beb95783e719e748c89722ba2c0c48f9fe9a9f8635bf05c8ff127b453e484d940d7e5649da595387140c272b42a321a1d7b9e2ac14057750afa118af3d2a0834f0acd8dafd6fdfd0ede994bdb0114df223293a7fff302362c78bb73ddb7fc233295d8b865328c456393b84efa27742c241adbd59af854c1aeaffbf1b0904f1ec96f20534eab549c7ab469436122b948004c1421c8b6a9e5e48f9d411b9377e052dfca23a0db86f6d84a34f5bac03a2d04eef83bcc8b0fb585588aeb11f3a022328dc2e32f696df363247eb9372c74d7da10e4a030b32ffe91f542f9f2df417fe0dbb6a21b095aecc1c374eb0720bb7a6b6f689eae50762cd83276fccd7831afb4cffe83d4b322573297cdf912c0d7c6ade41222a5fd3ea00d567df2116d136acc09ea56ba20ec4f45fc1ec82164bc3cb170a3fcb78b75d1027be674e7b43763b417fa03320ec43e5923727b08ed68031ee1e72ad483562531fac7f81defe7347b453d6846671e31535a8c63ec7b9e75bb5f68710207589e3c7ba0f2fcac645ecc05937af12d58197f980cbd633c8a723162d1d5e567b7fad855b22d305cc12f1af430b2ce0f7740c3f56e57dddfcbee7b21928c2d903c80438a0a21ea9b79b2f3d61e6ec4e81048ded26a288bc0a438f9a842b28446a891a2cb238a9d7c3add49583e1753ce41ca34b02a194c5ed04f1efe45f79c69eec59107df139784e92febc2eac49e01ecf0bf645c5aad6a6feec2c8e53bc071c6ae771896c03ab0e918760ec6e7a5254f47f6e30b1b33b31b4b61de1a37862a9dd23aab4bce546c088612218a790de49d2deae9c6705fb1ce3947d1b9d11c6b2015e5e8e3907a0ed574734de5653b3c1aa5ad8685f5f5d1f9773049c674c7c88ee5be19c53be83641ca873ae2eee16695d84868ca7df43f148614a164d0c44e9099da229c6a0af1c41c2985c0229f08bf3229c1e2f38373f82359bbec6ccabf293fcff2134c2fffbbe2df2377ca3606842338642274c56492a0334b27eca6a08404034fb4f40b36e575c5d2cf7174bcdf1588decf990c4650c2df45c5372e75c2d1ac0ed088551f5dff22d677f10d72b443ae4e3ae217022c4ac41cdc0fdf99f3279bc56e51ed10f9862cdfe95de2890a4d2cc1f83e8135ef7c0c6125ddca8baeed257ada02c6db170b85cac4c0adc3e91127341f51c8caf8933e3d50d4833c8d41c94c33a9764874d4810e002e2b47c2342abbaa27332a7b43f53002015d558ca18be9f838a5d44475bf2a2ec63ce33f60bee5a9ae70823d9a3952e50d4e601d525c17c30898e93ee9b0c04b77a347331674e817988edb019ba8463260b9ebd1f650107f59188fca430a0bbf904aec5ab7abb121b4a02f7d7b57808209a1f957cb02af6e448bdcbb803cb4c3e0c418992d2adbe2302b305b8ab899e609a3cf796fef4d263fe46d22907432a0d3cdd12589c27fb5688c5c3db1c698834a142afab298cc25ea0b96e5316b5e0936c2d0fca47d9d770c5114ee42e2006611a50b3e2131503c8c6157fc529d95d27225b3eb17c2bc75ae4895767432dfb71f9d7e691e8c86d8a94ea759eacc896e3a7144af001385cc09958686556d96b2239e41287dfecc90de01e1fc61759d6add0373f6e0022122a017d7ebd031fb0590539e86132e13798f62589e7f30ecdcd6b822cef8c4531d00607f6d38eec65d2bec5137a1beb53919bc566e1504824e93de1334a9e4e35847710ffa4bb6d7677f1a0e3d1964a174b965dd1589a5cfd91a470fb004e50db04d3ec3e027cc7071ff75fd484d32b39c754b09a21c7ed662af2c74f9983180e52aa6fee994a99d98884f7244e8a5d569f1eb375674c6123535275db5055bb803116dab071db2cbdbf42d2f75e1d41084c327dc59bb7e6f00d6749f8a6f1d5bbfb826bbcac55b29eecdc9003b5fd27b88b6695e5a1dc660d45544e528a3c5eaf4af5e7d9166a141be4c39d9e0bd69636c50c070ae86fdc2b9b012c7941d7484589b8b932ffc3fe148b787400849dfb4873ba7c4fbbe4b8ebaac8784d1f8a84a5d7152706d1303db7c0d5800074a74159bd924404fb587169b4753b51f844ef00e2097314f73e4cc0ee238178736397d6d5ae1cc3343f605bb04be365bb5a0168f5b106d6f3038c96488f3036a32513dc696c9db8674e5677ce6674fc6c97ce6ee95437ea10db1de70f19fc71f4859bbb73940aedc47345bd5c5cd2ef6f9ec22c7dbbba8052ac0d2eabdaffceee0490280656931eeb6fdc3ca6d4846c1b103de70ca2d72cfbc72a76a2a0d6f22cfea3df8b5c8a7ffff779e708be9f7b4a16308d9928bbb5b57ea1b0bd428ec8075bc1211622c5ec4ebbc41f2b4e48bfa84fc88bf0122ef518a4caea062b97c98a7b0168ea5340d5fbb8d337527e494582591ae68b7db04e7a99123a924b67cf11d0252b576d52a90422c8a421e438e0abdfca23e7613aec481d7e8491590c9854c5ad78c9facb0ef7e8036df83a837c8276d69816e5980dadf223e8fd1b654bd2e7847c6e22bc418486759828659f8a87ec9ec986815f7110cfa7adae9c5878a016850378c70347b610eed897a62bdb20bd88d2d76e32f0728cce036e728c08f5605d0e8b4c4a8af71a88e04e95bf68ac1dcbfd14ae68fb61219f8ae64ca23970f0f49c5c1c54aa260ec7e8be50c546912dab2d4bd0c9e8591957f0857595762f5e53e03182351a30d62e1ed018a76ef39213708b817ec084fc3b71d5a9d20046a68f41ceb096b72b924f9adf3948429cc8d918069415b463ec93ba4f0612e8b690457d64ffac8ad509acc765bdbf72ca0e43d61bb4f5b5d7c36ffcf808343e94564f0fd601526b70451ed619503786c5596b1cd98940b792f33f27281217c9f2b6fd4597ff67a17fa39a3675f21afc13b108ff6112349fc23a9c76fa39fa10fc1bb4240c33a77304221a49b118692a75bb0ac3acc7b7cf0d045a61567963692eabf3fb04a38b9ce5f83350097cce528311b806098c6a73d287e34071282e842b1175ba974aeccc5df132a5f76fa026270675278f5a1a61b3213e31ee9af1f86ba12fd223473479ab0ecbf33ef488cd7751f777ecc8dd31e72be7d2838f334785920e10a7ff286101f3d8a91646cbd5d22c3a10971d2cc838f6311ab5e45d899a71f6d2f710c95a86e506af95a7923108c9cae66d34a3082b7d35e1aa01158c3d4ed263b47d3fa8c94985b33e25325b0ece27f206b73d857c5b991e3802567a85e0fd3226ab785118fe31857e2937a302ea1bf97cffdd4c4e4188e1182f371da909c5d2c3496987ce0bc340cd252b8c0dbdd112b1d5e50d132970aa25c3344114dca89a33cc325cabcfff267fd3cca87c2d3a409d10eafb277e32790fd5c0395f6d8be436f246c5436b0d0f261df4179a888ad73655a16bf813ac6a78ed778e3a54aa79d9a215f514d00dc5892044bb50271f86b1c521badd338783a9216f08a57d946ec2d751821ef4d6b05aee13c1d43537a433b99b77254d823e811f676e499a44cee0f21889906924e73e789ee7a131cbd43a7683abee7663691f70ff49e8c0bac985eebf5952dfc3906da1148ff5ca5472afc1c4319d05a03ea73492b683a6c12ce87a6fc09b0085945a76c37185f06e8f1e7240046676526b846c2910f6d66acc8111de4a8a5af10458926f265eb9bf4bd53b78dbcbf66e307c7c077fe58962acdbc2be417626965c2501784844905cf0b6b767611367397092dd479e18736e92d98ca391790cc3c859c74cf45b49c3ab01500551783c105de9db4f2ddb5e5ea089485c7695238053133ce6ffabb70f69631a4c59ad72ee642f2e2371e7b93f955a4c774ba721c3659876e31315485514ef8d5597fc00aaf14280d0f4407ab3018d66db7276eb8c5ce585e1885c045a53ff912d03a111eead609e779ccb80f7beb953b08ac24055d9538046009360d91b6006d20ffe1b8424e4f4f5a4c6e872468de2a34df43c14cd3c796a965679115b9f2ce8e86a7e011674a3b95d2375e2163cf3af74168c3b595e8209afcc86f8811cb186cb5354372791e96b184cb29606c9456a7bccbb6eb2d7d396c6fd98d1dbe1f9b7a9804a892896de4e9cc4322b14c9083e5a10bdc0be515175fe658403481f8a0cd9656bc0f0fd224b6146f2bd3a8fca918d584c2181bb9690a21bbd9c2042c4281668fab54f7b9ab8f8f0beaa075235e9117cbe558b131b2f9884ba3c2e706e17eaacd33ef6b3dff6e6dd61d5cfe5b2941a5662faaaf285e7c2d15c5cbc22b5d62c9148cee732f534e4e37732710299c6d7b3d21cfb41e7fa03065064231b03aecac7d015aa6a9523ac0b12f1331d429216af78afb534857abfbb03914d35d621c5b691affefda4a48180e3edcbedd2fee0caf73bb52a0639ca33609c67558262f43715b02040a63dae6cec06f5208bc0d277f64c75281264ba05995e7de2a7ac50d4ce3d0d8ac75ccecaed746169349c298bf8c00b9d7ad6abb2aac5b4cd5c4d27b13f01423dab9548f2772fb248596a8a263571b095b6ca8b8920b8195631cb2f27f51f56123e11816cefc3af3b227c724e9a69dccf7965ac33b08fa9cf9592b2a83c1f2ee5d2829bb97a15c189747a6c4e10cac483d08fe26176aab2f9b0f9c8aabf036c8576e58f0c564d8fe8aae42fa34d9ebcc2c0b48f39af594fc982b3c6b478778f526fa264d5ed4c6f28f6cb16828c8bbd51d8b330eb4837f7b3cde60c418cd24a364a59fbb634d6155d46ec80bd34c1992ae86bb2e9fa771ab3a388f4e06eb50b7a8651a5084a405e4be3d4d88ffacd5489949f5439e917f9d2ddaf117ab1d52cb39397abc1498abb642eed2a98403c1fc225d4a7b8423b26e8434859ee314dfbab3e01f7aeb409f8e6f917df2e58c2b2d4ef475f2587d14fbdc984415c5ac21ab387b39f1c8e514848b542844847b97ff039128b0264083500f7aeef62933db9720ead6b3703d95d9d4282a6f639c8711ad351da73d4967c8d4cf729fe579640e8ca320fee303ce8208de12256f8297d4a37e250acd4c2d236f8fc3098bff393c69ad467199f1d601c76356841ac2de9510ae7c6ca44b73ab006773cbe0bc0ef1273311423ca46cf82641701a5770f0534945fc921a16b84e4b223317be462fe1f52f63ce15969eecbf82a7263857904c2153598c0020ff519d6bbcf98e6b2ea187abf9f2a79eb388bfdda3aeff70d41539f525b58725b6fc2a252d80ba4a2f395f1d1df594559915148090a8a01c6bfc16531fa728ddbf1f0de901d208672953800040572372688cb764d36f0ca7f73729f5f402068a7649bba44ac1b7b8600fffe5091edea2f4bc6f6601d3d9eba197586a15cc44da47ceb42185fdbf987d8a480b12f7e6344afb70679de67a0ea6d945c91eb5a9aa492f866958e9358f9efc171a6c0f8f6574e1d624f4fe3645fc290ed0fe1e581a2ce88d8a818e913eb6475f59ccb90a9c621cbeadedd9173518cd3babd94d6e30546af0cde6ff69c579dab5528d7cc0608e9c944736cb63dc8e809bf04ccbfb5043528afff72af49ffbe0123d63764609f5e55e5d05255ec77e9f87e7dd6a80e9ba9ff56399ddb942e0a5a18f44bed5582b7eab7826c2fb5112ad3b9ed00d44e950645135630f8b045c15e9b26178475560533e5e23dea098c020c1ab079c3c1225712d6ff231209dc5c1fd37253a7efec565900ffe6d12c19c53ae0ae5be35b9ce7b8a253de846ffae3672303b0a19df8e881485e57a7c84a6fdaa6f35c44345e332aa9f58f142a2ecec3c2fa7246a39600f3f31c0045c28ea8d3705d0ec6595f02ea3ed659399fc6758bf5f375a03f44b9c8ff547188f097ba71c2127ff9410ae0acc44e71e418c2f0b54166937db912119c50176de4be44118fa60df0316076e56ad1a2cd3565987cb250f5110bbf1b8401a9f0f9a9e2b230be49c382b0cfbf8bda2ced4d7323652d071c4ab592be29db8b1d3ee88537080c3ee3642e5d0bf36b35eab822099540bcd16ba37affb278e959f63a4c17895c193b7cfb1282d146a5282498c3c77221ceb71a7cd6a33ed5551a27c123adcba403e0c53116c2e9f89ae93058e3737a144cced86797d8ab88c5051e0c9aecb9343fb09474d1c2fbda9e9f9a86f71c44f366422c5792b82e7b040d12cce3c1e2e0b09b07c4b9a57dc00255d0915be80f3373c5e3b956cd771bdd84b57c1b90627875c999e2e75f12fa3433891cd54fcfd73514b31bdb9776b64e7fa24f8dcfaaff8ff94ce5b284ad8fcc4a0594aa1835198bb649f4d825b87d46cf182d39e8bbfc44d6b9b3971b901b46eece2eb39971e7bf3d90c84096fbee8be4cd3cacc84a7057d2901f7e1ef8c213c7126cdfe6d9d868c9228ef86400e2625288a48aac800a1a48071bda7aed13e4af341362e17eff44b5aba9d370f4cedf545ad49e0cb73db53926b54810fc56a3269b1e1755fa591ea9525d8453bf9a353601edd05dcebd0413ad7f144fd2197a32fd9785c4e6ca07ac79a16225e06ce8271df428348f1bdf2e8a753552697e3de1a842b00c4ec9f3127f43eb2513814feaa88779af64636af69cd8ffe519abff2e46789731cd2de35685f6e89c5721510497c3b9482e37559b7bcf7ca38fe0ebba118c30a0f75b4c3ae45c3768c4fcc1b198ea9fe1704f6c7d352d4a4970e717c87d2cae49f433f8ed34303d2d157e9ac4b77be85f4778318a2a593dfd20dabc364ce9a4bc41c33418d87895d2313604254cfac2fc851a7f2b8e1a7e1e6ffaa0d7fc6fdb43c21e5fc0b682e79640c3f40bb5e2027e2005e58061047b8eb709936fc614c5acbd0b1c70ef08cb1ea7abaf2ec5630fea4e131d056552ce1ff2eb68be24288fc2804fc887afbdbbb27da0da6230d0de5bbde10ac150f96123bd1f4935fc6a5120accadf9983bf0fa71f3e367a2639242ca6eddba63d2143bb3d56b2c8c1a2b4c101d71209b691f2cabe2a310b7b017fb8ef5700596c24f7d5626d61de6868b056ce7c4ec03ac4d66c2f091950911f26f07d0507598933c115779a1743d0f4867d771690c904af48710f1bb92458c1aef2540e92ec8786daf6bedebdc4471a94a37bf0d68e27c02a578061fa0cc9ee659e92ae4e4458a48f8470b6a724347c7d8b83a58fb636fa862d2c829a3b8554e77422925b837eae06fa952510a05de5bbbe4b617dce5fb8c058f4e19a501e9752e789867808a2419bf1e119a5c96dfd8b84563903aeacf37d8c9239b4df8feb8ad759b85b76c1ffe415e71067333146e9d924e982cfce48810410968d61d426476f704a0499cf7fcec275d0764ee6b7782fbb3ec5028b587762189b8bd68666f852cadb79204e7884ed0db5292468c9fa8f183995c1f67e753b9f04f8f0bdc295213ca51b1e04a9ac22e3f296add3b7f302b2b214b960dead9fd41c8adf614c37bb6961a0057513e721735925e12897ee1bd0eebfaae9ddc9087a384fcdcb9707dee2675f3f815fd3c4be0dc3666730971f0b89d87fb2e154cd09937f1728b15ab4de245b48e170a8a59209b75d838ca55b025de28e530446e675b1948b902ed33d9604f5b94a10ea855bed12c9b429ef4d4d876459b2eaecb925981b050c27a6cca104f3c09d520ac2b3641a1df9a581a7b2a19b2fb2be30a3f87c6f057fd5cc43433b470e6220b2329b9469386df9a143aa36ffe49694a16c00752e14e01bb2c09b597db3d55723fb6439082c2586e524346a652d8eb347fc86a337fab23e5124c8c0387ec31b6d24a2605aff39f4637a261166798b342cfd6a26c0bc86b608cda0dea56217bd9900e4a73cc3c2dda531b83d6157cc3ddb1185c7961cb2fe32e363994c4562975dfdaab2b26ee24dbd82355cae00cea2a2dc51fabcef85936bca126220fc2bcdada8da12b66e8f3d736a32d81542bc7c7270677722a90ade1c982ac6e4c07eb1af087f4796b0a9e170643046e3af53b079b08ed651c68bf1c8008381ad5a5c8e23d3932e5ce65734205f2d4ef80a009e07fc1a7835bb0265c39955f52e45c65e86f2e497fba4126fdf4f1e0dec70be3dbe1fa1d27680507597a9496f04106059ca331471a0f3bb6df7b958de1d01de2deb5482aeefa3cc699ffd15e73a7cf4e151956530ced33933cea3aa2ab0a3dea55c96d596e7b2c6120ff81e6defaa8d98de23d8aae39b0da9bfe56f881f8af3c63bcabfccbe7b4649aec5596694407a4f8bad903081c144157f06fefb904f199c7ec9b11c14d500823526d8288baa86b1b69cf3e5a9c0015e43d0665b9046124de41d4078862dc2f10c1402f0972be6e42e8caa7bd56a2f423b1ed9d50c749363795456d263ec79d3db2de85db9efdada56ffdd04dc6709c7aabfae445e86f8901964bbfd5cdc00da52d609f62286b2a7e6057a90d700f327f35d0076859d63bc51dbb3ad5dd986b9047a40bcc81daef25382f4517c3a9031d33e81d9c7f770e861af764eb2a5924cc1f15c776100d135d9e040b85bd58524d69c3135141caf52eab9e96e9ccf63dff95b7b95996a176586981641f22fad88dce56864cf24accfae87904fd9bc702f1600347dc4d2c8d63b665f52dfffa4ec6b7e7a30eb1d00172622697595047fa410ea874944489004a558df2ca976f3da453236e61dc0e4a6204f983fedeaffbe045516564ccb2e6c051e4e557eb9aa78f01b5f132604cb462cc1115743be0f0a2974d11444adb94ff8a40d2c14cc3e1959694ea68e5c328ea4f5b23071d937ff2356aa3a71a461629014759ca58132efd4ec1b5c409adb754176018894a5e60d2f1d65e394ba056427d745959130b96726fc7faaf4ea2cb64e45525bbade18f1385e00bdd8da940b64f4c56b42531537849f585205b36348a2f4395af4f8caa717ef8f0647acf00bea5c050336e7ce8baaeb8b88ed6463aeacda1ca99515293f1fc03efc8094a531de055b56b049a54aa48554eb0498d1f11fa1846db0b9a270f48c96841010e0ef8c5e4d96870fe77f957cfbdab3f29925f66eb32e243cf9ba161bcde257f241927415687c858134f50db73e8fae79b72493b0c553c6deb0e562c86bb30dd680056d7b36ae263a24a4e83a08f9de8818331c6c3c61c5121b287d28f70eee54aa0e1923e36eb0034ab478ef6feb9dcb28fdca20faedf5ee353a56197c102333e2e9f5430f42bee7f91fde212fdfb16d520e405e7dcfc5adbf10a4b5a553dc0a488c252b8004c6ddb9ca0445cad798942c9401a7ed39fa25f6daddef421ce4c162328b81950eb9bc94c77ce3dbf194c49d657c26b0212600d352c9e57f127c21664af2e1b89aef8bb1ae0781cb7bd8111dc9751b16538f82292dce6ed73de4a1b506b361995c27b8c1da22f804db74ef271f56e7db44463392f053b6b79978a207b30bd37198dd88d87eb3aa80f4874eede63f74b1ff1b6a1663fe820fdc6a31304e11b3938d6bbf6062edfdc0a38a446cb3ac5006679aab8996c6ec75c79fdd2a0338234f574c26d523feceefc55d6073064fe0291baf39a9da7ede2bf62b42f60acfa2422cf0edd66b906cb15666074e451e0657d2c13669886d839763069a5ab4260f7459f773b21f80fc679e6183e7fd73ff8b4e50c063a55d048287af34df78ef537d64b3f77b6ddf3bab1b7d34a8329fe24d985d10510040f51370b6294520bc46824709ea98bc83cade758444a6b1ad7c4f0f074c644a6d39d0174dda075b39b59dbac7a25f5831cdb843567f25fed3a45d161d3ba390f64fe0d5b0f493bd46bb36b6950be71f0bd3cd2e2f5c7eec3de0297c00c6c417a3f6757356f8cf3477cd856f72b9dbe114acfa6c7913e02db9177396ec47e66bbdff96a68df99e8e723ff24579e9f2d9e7dbd0cdd8151a15548fffed3ffcf703f5c5c9b13ffa47628e7423239e19b911e3417a0ebd203151b0220b7fc9a6cae8841d8d1810dca3a9e4532e92c559100f962184b2fa9308ec5c220d5517369debbd3a1800f6df36c578bde10c45fafef8b6e3f6a298649b8be55be8df61dcb417a64265bdd2b80c4bcf8b5d9b3933292d999317450039a573cfc5dd2e5eebde0d2042805153a0828f42bfa1a16de752871c553869eaf28717b135adcdbf6968b9f2f25326e099b1aea03ea22dc3c92323abf3316b142a689f57f9858c570e93518715bb37c6ed48c50bdfa095c5fa33b5c170adb60b9cd09b3e9d017b57dabc76bb6cc84e9bbb164db91feca67b4f246ff23d01e7e5eeee5b592ae7d2341d31f48dbfbda8c2d8a93203cb6431a67403ebd98e19a65f388289c04ee62148f4a4b19b5392ae14cfe2d549aa09067a6a8043fb90f9c0dae08eaf809e9652193cbba4c7bdca745fd126ff5f5d66076de8beec4eb1b2ba5f6a3f238bfa02b2a455bbb256dfbab709ac70250ba7ce0942fb861babe41dca57e429a243f8cce63f94a50dc0a54ee79196c7431dfd2de4b218e4ea41101683877391bb669ddb9e0cdbe0950e27078d884191cad2d815fd6b8f00324086f51173642fed1a5905e6d221eb2bd34982eb459e835fee8ca1d94493b8e2d2a6126cef1472f90a0449e749cb611d0721d6b6f439ce8fe0f9026e02e27602fc4026a32904cafd776f537dc24a750432de226bf66761426164bbc572327363e0d3b0f57c76754ec3966b34768b4b5e84584010ab24b7a78b61fc96389c6e767dddf283d8f6c103aa65e0703b5e975c22217b48bc6278e909aec1f4a2dc58bf07f7149095ebe5b7c7cf39eea97ad43b103e3d28a220d96a4489fa45ba923a79a052be91671cdc5e107b9042f19b62bbe96ec78821bb783bb450a3736a87cdcb798a271a2ea0e1fa9de82db0e78e2f48cde49bd336bd861285a05652bcc939a37bfc1896b4f7570dad19b372dbdfba5f98180ed0e73cb924c3b32e96e28009392ca9d659bb0697d508c451b1a7bfd959aaf046a056498ac0879d8cf8dc94527edfd1559e35de7687985ac2af7e891c01ea7b26bc117f6509f42dbc734586774023a997ddd1c6df6d503d906408e9e33b224cb65fedec458aab6a77b2b616d438a592290d249743b1827910d4f31f4dcf56eb9d44ad6ca5438c94b503c149aeb9fe7587a23d1ca8e767e25dc99220c05a1c7ccf15321fb8da43b698b817fa15743de5ec818c77bdde007089a66b5c71b8ae36a39c7591af8ab85b376bb174db5593ac1a1d9b6bcd813e1c755d2fa72ca575a045142abee354874096cc2b9c890fc69c85dd13cbc6ed76cffcc4ffb9b72f0286a9806717bfd6ba59013867a2fe9d317c9868076bfd6caacacd60560db4d1c0bfd6f1a6371ec0ebb23867808b75e6746e62d588342b2d449c77a10c9dc6b0ee8a76b22784971a850e5a117cd9a6c7a06ba8fe9ff1710230af6b2f6672782a487cbd4734e26d6280d53ddfe1a86734b3e27fbe00ea344f5b559fe539a9e8ea90976df8f6f7cacb4e31f9e07502330a19c9256609488782fb08e2712b53ecb5cec6b4948641e180cd590794853db99e3ad2ed7a5e35e99bca814af713da04b1b418efd028741085d37c1d8f747f12db97c29d49ba9e86dfaf2f1492e4bccfad927e0f8f5ba20909dda2611931c4c7b14dc46ebded1a872fd191c892676d301d6266f8e03ae16d165ba6667eb1c5e5805a6bd2fb9f582711ee9b82520f72fa833ed160a4e65b898641675008eb64eb565e59e10f62cfaf3721eb70895befd21b4094fe816b65b301d7293c8ed038052b135ddc0e8b5bbb56089a292e20f348edfd0988d8e097201503cc838eb1c3d3d53eb271f15bacae2376b868c93a927871007e91b2e1f152780ada79588467882258f442f9389556f37a7e19c29caa1dffcc3a526094afaef3536830cbcaf5435af0747d7ab255ad0257700bb60b3b22adebaae326473db62eacfd18a631c777f500fa5e828d059bc2dbc622be38c98eea4f7e5857372176af279c976db1aea3a323ed5866d3c30ac976ff3d2433d551f26d82e6fef0d67aaf77cfd33fcaf01b5af769130a8073fad315930a34b5f779d5da9fbc07775e490674949cff305d79df28000049c69e12408fe3bcb48d393489649c72140166784895e70059e0c72e5b97de9d8c56ee4cc4e0973628dca53b168056b74b769edf00bdf532e7dc674a7feb6d2ef24738cf966f1ebdeca8ad9057925e78fdbf277e2ca661a89c1466cbfb0e6c106b26f6f915afea24cd256649212595697e0c36efd50abfae1f16e098e8d228e19e0867a81ed4fd61f9caf41ecd65d327eb24b8622ea0aa535f391190cc5a66fcae00d89a99ad399aff7627d62784afdeb4e2e8b68a9bda8da534f4630573fea8adde60c595c13183b93d39d3907ccfde9bbdb17a5d2cd244da91283289ebf65e36466d0784744946996c0cee43a4b8044af7044389a6cc5018248246e12dd469856a23af5476b7c4d15d26cdd1de8908be12961848877d24a4ee46cbbdc3969267efe13c2036abf6124f5cc9250d2da9a2ebe02d2eec9b1784021acbd438f4e54494b99e4060667bdb43ee9605457869d05ee0fff1eb60ddfe6ff621f12d3054d45131e40605d95ea7bf31d8004b09553d489e698f1d50d2b5219e524339ae4c46f51df06022a836ae6aab59ca18e1257efbddf58b4e41bf5bb19f148250e770dcd86b7db697fb9612ed7926e4a7b9b9e8bf80c90bedbcc81e7131d32513b2072d9a467ddb0a6b62aa2684b8df23f5c193e564a092447d5fde6dd1fdd72214d59ed69de35d99189d16c6a713b6136954c8930a68e52ad3aa3671cfea4bc86f8810ded764f7886a005dcf6edd674505175516ad75c159da8eefdf553fdf2830487ac245c69ab7c59b4e2eea844567154d5205c1582f3994431617598c9b5065e38ac706b1fa017472098c58c9857b854277804c0a6c87496edd69556ad16c8bbaf2c5fb5142a97a9e56cb8b6d547c0aa58b8ee5ec3ba342ea59f4e9a0a9e23df1c74f7860ca9719f94c752a70479a1f79f2eade6c1af8da081f7eec47f3d7d57b00861c06e9cb40eff88f070f2aeed417937ea1d991a2c383ef2eb2da9c441a489971946f8e5d5c57900fc87c18ec7a777de7edab99cb15fa91ca025347ee62735223698563a4d2e4691890f6286a433028817a64aa7c0c8779fab65e835684667aa71c2d17f2c7d6643364e0072a033e6da03d3baf498f0e5fd9ee670866ffbc0a8fa82af66fdbcfde1c25aa622ae5762f0da6d10eeab6713d9675ecd16c7ee3b7c8481eb2745ede9ba812ca1ee6912b28c700a516a11bd05e9f03a1c4a50c9d7cc6a258e530b85e0ac1b3324ee8ba9feaa3479592dc7c54a4b6f3c5942a3c3c4104eb2b950cc8907085d21c696834152ae243fa1bff42ce7821df2bd488b06c3db83e163f6b873111b419c91d920b46e51b0af9cf5aee9adfe4992625fd7b362c62749542a8e81a651845934ec9415e17d16eb0a8074f3ed545de3ebba7238141d285425609aa985a1aacc27a6af7cc092e07559e29c9f96aff04c064f05fd010daf3656f2857d3b693b089dcaafcd1514b91eb42f55369c554cc57c07f9a81680adb89a0c4bd6bed67501436011f06379c84d6ad5f9ec52e66d5deb8cae22fd38f8e67715cadc2680ec539c100244cd93e1b39ca49ce39b9f005bbffbca7e5f6adb525d8372a12c96b2a530f6e1781c5f26b2ec071c9293b935ec29838bb1010f9782105e708931ec8abff2a2135aee52c6a347d51068cb56ac8be0fc2cd36c235905b5d90dd67fea60bf155974366cec0a25a316c40598f42373edce0f052aae0c7b05e956b40c5bb9973b91e44284bb9a68aab6b0b2c40ca56d6ed9b9e1bbb0e12641545ce102d40cbdf62ae648250d123554790572425b705312c19eb0195343ecdcf3f03a5c176e1fb07251247396afc4993e15c24923ada5dbd436d5d3ed8627c648caaa856828e454d8c92f67da1bce6066a466ce3bef6d8ebf3543cc97986bfdffd4145fbf8643439bc202795c71203104477446725911f95c253a3a3cb23ba7ec8e256d10b2037f93ba4fe168ab1c237a06bb46cb2d7bf94d29728965c96ddae3d5532e50428b203778e1ee2f769a9253a04d2f8c3bc91dfd3e97f7ff6c9aba387314525f8bb26ef1545ebc074adfd9aaed1c210fb9897f0085812587899997a22531548b50611df610b134900bf9a565a992c4e9db623f0e78b25a93bc3982d951f327ca5ae9c20e24e83d04fc29bc4abb0fe9384e96717d6d0af294994494dc51c19ed936d72d51bc078c8fa25df9fafd9018124efb4f5bef885dc4673d498386c621f1c83fd1af8118206c8fbbc72e66a51d727022f9231e6c12e58b53b08c43817869e9cf9d877a8610d56279e5f7d7fec71540ba6727c98c402a1c79a941d12ff8e123f1069c653d965c572eba35e4275b1f3fbd27ada460a817273a7d802d57916170e7208282b5ac312941796ea89995d6bb099f0ef2e735928be565a0552755d4285dcfaa562fbdf9221bc2719070180b57b3e65ae11a285c17644ca186384daba826eb3ec0cd02427b4e1635bf9e645e7b266aaa30a046b4407f8f63f02b196ec9cc8423f538a2bb4cf90bd5c2e43f690d1d9220bedd3211af29281ecf25cb5893ade39fea28673445ea0f43944268d336dadd9c581091beb39b3225cee69e68594019acb394d4b14ecc1dd7d935914aeefe8c47c6f2654f268e952afcb12dbf8ca54cb585df66375e7748046cafb8a219141ae9e6b653c55a5a5d140a99c3c1c1f7c0a86850345378b905c7b7546bc018994b838dd8d95316269a1ffabb586d3bd8c7c661eb15310663be3c1565dd71b1395fc8acdd3a423160686770069c6c807b55b9d593b7879862a176c8d06d2b1ae32d81f347da253599a6fdeaa80639b5a5851d0642960c7ea1e9ba279b4a341e1aab5668441e2bd8e068570417a9e2f9dc13954112ecb871e5a5d2706af087fcfbda942e97473dad614db8c0706e6a61d622c5bc7de43b833ccbe5b336ec597f4705813e4995951e0714751cfe9337d963d03a230a7fc4b7fe315952128797b72d24e76fdea2f4582d7cf2e451272017d5016a43fee59f0f03d42b88de8a116cdc3d758845989b54e185650e1de536099cb85786b553ec54436f79a2eb0876afe0af6f60ea4d0a8a22db9095fa5e1810c67b3c0dc09cd7c1420d1b3364d772d9081ed9e52a7cf09965b4a9860f6f6404f25f16b71a731d06fcb31479e83991936ad2ade4440c2cdb5001f7542c367812f033aa31092bd3615530c240ba634d14c31556c74fb52bd266dd3ce6f6c787a1cb551e36bfaf0b42a759f365074a1684f677e8b8589bf4fd4034ff91a9736b0c0f64c6f8b80c317b1972287fd9eefef62fd8e476fa4626f0a6c6e040d308d5c43c61fe2297e0305670391cb40cb4fb7005c0ecfe89f6b8192306b3d6f5e36fbb7871fc630b51fe9a6f7c4378a36718417ddcbf4b0a264aec4c22bb5c1f4ed081453cf913b45090b72645bdd08a97e3836a623a37c8f8e822c463a072a4d5ad70003901626fb98d98d6f8bddf35e1352cf308094c8358c12d5c722c9e2ef8266e3676985702938b66470f5fffa065fd67ac395829bfe43397503fff32694855433960c0f784a730735034ce530f34fc4aaa3b7236b726981744c5de5f4ea49034ae170d084abf3b57ed81fe4dda5c59d58a2cec59e02a906f736af8f05793af5d5843362981ce338c41627ce881d9f3780e94f96e98533524a0defebf9124819b07ca99ad9d68cf17b87e5c90ad8eb8aaeb153bc585150b7bd91868f8566809ae42f954633df795312daca6ce63a904c1a73832a63c345f55fa54f5e0ffd4a82c768c3f409d1ede4011bfe3f1fd98986819fefa1dbbe2832681576e31f06f1e8cae251a68cc7efad2f7feaec7b3bb45794d5b909806d74f139e1e1b432fb66f77952927da2b50b5cf377071b0a3ce0dfd636a6240c83c381c9c936f4f8e7658993d438fbd80545366611dea854cb81148dca1644dc6fa81b09821ec131dd0b623d7d0c13a63f05f14d0db0532108cdf5c21cbedd6d3dbfdf5010270f5a40e60a7cd61c8bcf3a5f9fe85ac44649a8b4e959cd723dd96c40498a5894fef32f256481df76e111ebdad0abdd3c46e7a253c7bb71ad6d03f1a6001c394e5aa52fb77e262e76d3811d3aa6b9b01c5ac5ecf62f8986cf807ccb82897e4b2bf589606872ce544ffd962298035a5ef1e87a03c45494a7396d972c8e613889b9e632b9f975b076b4e4cc6cd1ccd5621cefa7df797e5bc5602d7add1936af262cdbfb983133f60fcd8589a4fa30c9026460f098dc74d74c6ad75ca3bc595d520d1d17c7994025adcb6855152c767feb5eea71f9be1a43563f4fe5d992809002c67d76adc6715e7bc7e63c92ca92edcffa02d94f338b97300e0a5d11c9224d9bb12ca33d8d72428a9c0d437fffa7b282333d1d5bac81226b7453365affa828bc3c1b17f090833654b23ffafb14bf90080a9e02ec8c3a5994b4869f810c0300ae70850a97d9fb4a63be448ed2a6331c14dab80a9879bcd2303d2233d51464c9f737ed7288a090e627d8fb9eca7d618f0fd8c209067f3166b8eac28233efe0badfc8d33d496f00c832b9d584540223b17a515753720b5ac7d74d4311c8defd3bcf9dd105c412229bf17a607dc6a89b596331ad422cf9ffaf0eaecf73789fb5a8fa52c26fe6de1f5902651fe088f242fc1685ffc58265241d6cb82f217427617bc135f952bf05a1a876d864ceb8c735a5ed1e6859067752b20568417ed8a35b2e44d226e6c6d3afc80a72deb83a22a913b22451fdfc3fea1255840799f052471dc7456006620027247c3636215c6fc1c1e2855ab6b73dce4b0055e4a9cfdb094e9b0779efd97642eb6f105853d747f6c00b4de66994c64c6d6c568eeb3791782008b8ee5798dccdb46732d26cb1b92161b14342ba7521be0c5ed305b994f1b2d11acf3100658ad15ee28cec662840cd7c475ba8cb174a8e95664ae4dd76b5d68bd52c6837e26a8e35fde64ad24561f7de75800c0541c40b8ed62746603ba7f42e2f77016ab2ebf7d3e2b2089d33056812045fbf30e90abf0d27bbb068ee69b96aa9a2e30b041831dff396986457727728a7897a9e30f001fb6e47d4f9750e55d7176ae1d898716e6c23d48603e05eb0399621c95fc4bc043a9a31402011591a0e215b8a361096923aa0dccebfe3278fbe0421e718275aa9da690704a8853b204a610a7c3c109126cc820ac9e8e6fe1d9146f132855cfc60896a0d451c2fd21088e7d8ef8bf57ccce068372a4518a470af2d20088d5e0efb564a220e21c7b03a22542c88e3f1c288a25be116c21c4cf257c9aa60ee505e7faa522aecd88b0275dc885bb66b7caff0733d48f3d7bfee7a9959cf172264e9646474d3e20ee867a245797dae26776eeef5757fb4821e28a72c7957f81787da57aba5e223225b08e51f847fd0dd846a7a463007512e0bc60bd7175040696eb78b5487a7f18341e5aef4ea0d742254e96512141e1e6f7a860808c145232fd7b63b48396b3a55212cbd401560ac05a659e6b09d03d24bfdd1fd3660853d3770bfcd1de4c93eb37a351377cb31dd49fb3a7845b4504f7bc72ec4fabc9379b431c461a10cd35bdec658058d6a7de13b593843ae9e967d76c62602bf0ddb49914d3eb3df4593e00944b17cd0c63bbadd69cfbe690ec199ae2ca4c142ddb2ba7e84ce76ffa438e43c3a9c0e3ae51941c01a584af83353aef1a9bd28f9fa5903ea08780f8c3718733411d8250925d5d29c44ba6b44c4622ef5241d5a3db54ffb94771921054a1a845d427ed8773403c30f5ffdf32bc7acc6e95c7252113be5042b1f3b1107117596582b02fc4a88973782b806f0ecf78e9cb2ed77df6b2ffc73370532bd6428cffe0e23a778767794c69057754139bc554c2776314de79a7ecde358ce17191cbd98c7f9e3cd903db17e311fc6b2cb3488bba47b036af77ccf9d8d75f6549cc8895d79c9eb818cb40b6e4f0c30fa7d71fd28ab2bab064b94df4e7e4f4c961691c2e5570c1d64d83768b981a13a14395a640bfa53de5f39f683b56059c8b2b5da974339478e4ffcb73e23b36f18dc0b6e1172a654fa0448017e3803f30c53ef3b358ff28e80a3f3dbc097f39de81e0150c5c2ac3378e54c6d5ce6d58b37e2612c5ac05b6277a28a5ead921595ed2807827bf17ab31319a116773c40d0ebd9da04baea8161b6df308acd35ca00770aa1b5c41e0176c9b1edc6e571ec192234109b6a6a9bcb129e76de5b08ed60993865ff397f24b59aa6ddd45478ef2767d5917210ecfc093cf3fcc1f2cc48217b37029f320914dd54e30c57f78a83af8a6f08dd03b4ece128a5df9575a09c2b67eccf96ff1fcaebd3268ba4942a1c879b2a2c9fb0d2713ac71c2d7df5eb0ee9df1eddf0508bd9c66d4c1e3db23a67727379e36fea668fde4615f21073ab20f4602e744984e6bfdc4cc535fc942c70369dbc27ac30d3142dbb1c78ebb0deb4b510df078fba5f185004ecbddc2f1d79e1965e642205fe89b64ceafdff653fdec38757ed93dcb415ffb4291eb6b0b9ba67989d0449f81cac9a796e072631746653417c5c94dfc222036ce35959f60cecaa73e656aac77074ef80176263dcf06d9169b1d47cd62614168d6606c25cde839347e7ba1af0c20958763c13313aa69a77e8c6611c56623d744d0960df17c9feb549410f74599078df53838269338a807a5fe2791f4552122baee298ce13d661b1b2eb525df1cdfd2bc145dc222352c83882b9c776a0704e5db62d8f6173debbaa60c4c60c9f7021db37c2b85ed3efd52e77fd5ee2acf8a135566074e51ddcd1c3bb187fc835a23b14ca41a39026b6795a7102871a66cc83db91fa0e2c2151e54baf72cdd2b048d6a7eabab228948271544af9b8c21add48ef6a3d2a35059f411309738c249de7e80d6ea9022a9fe494173d8e70943430a5498db2552a066fc80faea1e58a3bbd3a8924b03db89aaa7fb1f0528518c7a8a8342336e195dcb2defda54436dec7c74f301e94a9c2b54e3a157bec418ecae5eb5aac095dddd2c0514b4f87b4511fdb5a28604c717b4829eab28eb7232b9eea9bb768aa544f6323bac0e565724c1b0b0302c7bf63d7da9ad9acab20b6e76bfae2141c6ff1651d5a6d3386c4d0ef4cd5d45e655e7a538b826cc5ab05b76cd2a0ad494c386dc3b0fa840579d6ba72ae0cadbfec21c3129ba6a521367a09cdf31b3453b5921c3c5710a5e118178bdaea0224251ac5cd2425cc7a1c6b86cea237b9be51506e166d79d55a898c958736b50d1e3053cb1a3b9347b71757ca8ce68e65fb537e937511da3e42f839745ccfa31cc5195c0922f124eaa1109ebf468f0c35edfd21951e3aab9908fb87eb46b65657ef67d344c0e0b598480df0d09f73c3d1dc882a4cbc562cb29bb407b6898fa929bfcb662a33c060cf6ba7631944f0fe985121f909db1c5e737a0eefb0e4b2771c317c5824412adc0579ac2a051c9dcb43b2facf3854b6267642730267f748ed439e1ff44107fd121679b5380bb02f1d4c224a38880fd64db823590b2c83cb7dfde53b3a5569a1394654405f998f98aad0efabea160dfe186d54d71878691b941e206fca7daa9956f8a50d765a71355caad0f997ec1f92f28c691f7691c04ade37190183f5cbc0a74edb527651577ca7a022faa3baa3232979cb6092c55b36f6f093232f89cf7f83ee31c24db83f7f8b929b4d9212e3f5da16b2ed1b4b89f3e9f5e2efd935698e00e17442eaedf9cc5a53402338edf4fcfbe8d90c3f1efd7f1a66071a0df08b791a90e96b838b246a786ff3ba18af4af11f338c6796d738bea4667019d5706b19682ab4d64581b24f2cda5a60219c43a503fe7bdea91067db80df004fd2212faecc1e0d162b4e13e10c7f7a58806878cb7fb5d507e5f6943aa6984d2eb4c6fe69c312f36eb646e7864f0a92ce4d0b30499183fd54733b20a0bf0b298e3e0ef9226047207c6a670a35203d42d4313ac013f2e64a41f716db59e2f8037435acb1aacaf062b2a29943bf38970768522bce7782a4bafe873a69dc3ae4730a0bf66e5b922f72ab98f689d9e47a712964d90567baec68ae98da0ad7538328e8cf792d45875a8ceaa22861384432c8774cb87edea89d0fb562b5f10e51d04095ae54f39a3a56b921b95362d669d0f2722c409e664374004b65d64aa005d356ac5773d1165ee052b2dc235cd1274f8ee438388cb12b37ebd5dcee27284fdccdfe114ae6ffaf31554ec680d5124e4466e9f03d9a414e43d6ad13ae0985633c7380f7972f8beb10b2d9d199f430a7fca8cb4a6785de6111581e2ee6a749f4ce79f3b0c8b189929c96f419bf1831699205f083727a517e09c2f111d336b9d6683aaa6d769cebc3f1a23a43ac53eaf47e0a52de02eb21bb809abbdec1e4e1649b65e640211c0d8899ad85da607199b7284b23e6a73c2afc5a406c33857c50da71ddb1ec50cf4376c3503ead47a70cdebe0c5e527b786dffb16e9feeb61d275a14a21959dbda059feafdbb15d6ec3ccbe9f92723f77d2038a9eecedee5dcf763ffcfd64ffa4bbd3f1ff1cfc47b4ed30c4a75689f8665aa321e88cab9f1dbec0fd84a2811988b8c8731e976ca581570d58aba24e5dde9a617b222a33a47e63d7836dc9ac2fff5fb475f742eded47426ed1a080a64e088150d71de70886e64736eb72bff592ab4cdc23aca5e29a193c072c21f19c0bdd03128a3773e215c28ad232ea3d98b71f0607cfc9aef5f5bdd37598bcd0f3278fa92a12f978ad5fb2d572bdf9d709b86f521e847d5150386d88df23d60a585c016f397c0d1545a1599d3f58d539f92957e5d446fec8e3a05068af47e8d5129a23766a2f463bfd831f18724dcc7a90d980735135a878034ec004ac655f6b048a2dffd5f99352da31233126f80f6a548172e979c4c62ba6cba31f642d2f7eeac5e12adab7e6da3be23848ebd1281555596336132c9219a9f32b646dd8430710a38dda39017ebdbe1d91a58d9d8b69ac0d905f8c4705f46cddf21ed46325a2e1e554dd282e560aadd0b71cfaffad60ecc128626a87131f2ab58185bd294b9d65de981a60c70eb5e09f789de8b825318d0fd2a08c498579a9b5fee8c4fa69bf163c34f9166608aa48a3ba185e18d6e9f4c9d3c9222454eda4ba67742eb59897dabc9721e3256ba7f1bf0e72b032cfbb3779114c0085dbe79fc0fc510ed3aa819c1331a30974b094432923cfac41716239ebbdf5cc7718c2ca01cae5f02fbdc98a14cd5a8f7770544ceb27242f7143f65f8567e9aa9b0ec1c31ab4dcf5b21243c5076bf538d07e332b2aacfcf5c2ece8a509f30a8bef9004719ed6e83808a1b4cdf60f082f0d09cfe19b83b0e8026e1e4a446928b51ce2c20e54f497d037023b83343b201ada70030725290e8f00b346bcdb26a2a39b559ea9de2921e599cb2604f5f6aebdbec18cd2837af039df803954afb55717a67a0ac9c1421f7a48ffdb6c8adde23b86ca3d59df052049e7953bbaba5c362b75c45a4ed49ef4e751879670d17e45f506e49f178a8602fbc0c0dc29593a2a08cd8c57839b53a9f204510291b8bdfb65cb008ba93c422179cd8cfb4a00686c12d9030b7b3e4d3bc6c2fb178d16fdbbe370837ef8709fbb1eeb4b4436412c162f80effd108bb8214fcc6bf1b87c916a90faa63800548e54db0f00b0f7605e764f957710391dd2c3671e6bda169368a41603f272d35a2f98e7b418f44f8ba770aed7fdf929a9ea22596facfb137d37d2a2986878768c4ba9369c339d8e76f7ddd0b7987b74b8fcadc617290df4041cc10045e35973016")

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...