local version = "2.531" local TESTVERSION = false local AUTOUPDATE = true local UPDATE_HOST = "raw.github.com" local UPDATE_PATH = "/Hellsing/BoL/master/common/VPrediction.lua".."?rand="..math.random(1,10000) local UPDATE_FILE_PATH = LIB_PATH.."vPrediction.lua" local UPDATE_URL = "https://"..UPDATE_HOST..UPDATE_PATH local function AutoupdaterMsg(msg) print("VPrediction: "..msg..".") end if AUTOUPDATE then local ServerData = GetWebResult(UPDATE_HOST, "/Hellsing/BoL/master/version/VPrediction.version") if ServerData then ServerVersion = type(tonumber(ServerData)) == "number" and tonumber(ServerData) or nil if ServerVersion then if tonumber(version) < ServerVersion then AutoupdaterMsg("New version available"..ServerVersion) AutoupdaterMsg("Updating, please don't press F9") DelayAction(function() DownloadFile(UPDATE_URL, UPDATE_FILE_PATH, function () AutoupdaterMsg("Successfully updated. ("..version.." => "..ServerVersion.."), press F9 twice to load the updated version.") end) end, 3) else AutoupdaterMsg("You have got the latest version ("..ServerVersion..")") end end else AutoupdaterMsg("Error downloading version info") end end --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- local _FAST, _MEDIUM, _SLOW = 1, 2, 3 class 'VPrediction' --{ function VPrediction:__init() self.version = tonumber(version) self.showdevmode = false self.hitboxes = {['Braum'] = 80, ['RecItemsCLASSIC'] = 65, ['TeemoMushroom'] = 50.0, ['TestCubeRender'] = 65, ['Xerath'] = 65, ['Kassadin'] = 65, ['Rengar'] = 65, ['Thresh'] = 55.0, ['RecItemsTUTORIAL'] = 65, ['Ziggs'] = 55.0, ['ZyraPassive'] = 20.0, ['ZyraThornPlant'] = 20.0, ['KogMaw'] = 65, ['HeimerTBlue'] = 35.0, ['EliseSpider'] = 65, ['Skarner'] = 80.0, ['ChaosNexus'] = 65, ['Katarina'] = 65, ['Riven'] = 65, ['SightWard'] = 1, ['HeimerTYellow'] = 35.0, ['Ashe'] = 65, ['VisionWard'] = 1, ['TT_NGolem2'] = 80.0, ['ThreshLantern'] = 65, ['RecItemsCLASSICMap10'] = 65, ['RecItemsODIN'] = 65, ['TT_Spiderboss'] = 200.0, ['RecItemsARAM'] = 65, ['OrderNexus'] = 65, ['Soraka'] = 65, ['Jinx'] = 65, ['TestCubeRenderwCollision'] = 65, ['Red_Minion_Wizard'] = 48.0, ['JarvanIV'] = 65, ['Blue_Minion_Wizard'] = 48.0, ['TT_ChaosTurret2'] = 88.4, ['TT_ChaosTurret3'] = 88.4, ['TT_ChaosTurret1'] = 88.4, ['ChaosTurretGiant'] = 88.4, ['Dragon'] = 100.0, ['LuluSnowman'] = 50.0, ['Worm'] = 100.0, ['ChaosTurretWorm'] = 88.4, ['TT_ChaosInhibitor'] = 65, ['ChaosTurretNormal'] = 88.4, ['AncientGolem'] = 100.0, ['ZyraGraspingPlant'] = 20.0, ['HA_AP_OrderTurret3'] = 88.4, ['HA_AP_OrderTurret2'] = 88.4, ['Tryndamere'] = 65, ['OrderTurretNormal2'] = 88.4, ['Singed'] = 65, ['OrderInhibitor'] = 65, ['Diana'] = 65, ['HA_FB_HealthRelic'] = 65, ['TT_OrderInhibitor'] = 65, ['GreatWraith'] = 80.0, ['Yasuo'] = 65, ['OrderTurretDragon'] = 88.4, ['OrderTurretNormal'] = 88.4, ['LizardElder'] = 65.0, ['HA_AP_ChaosTurret'] = 88.4, ['Ahri'] = 65, ['Lulu'] = 65, ['ChaosInhibitor'] = 65, ['HA_AP_ChaosTurret3'] = 88.4, ['HA_AP_ChaosTurret2'] = 88.4, ['ChaosTurretWorm2'] = 88.4, ['TT_OrderTurret1'] = 88.4, ['TT_OrderTurret2'] = 88.4, ['TT_OrderTurret3'] = 88.4, ['LuluFaerie'] = 65, ['HA_AP_OrderTurret'] = 88.4, ['OrderTurretAngel'] = 88.4, ['YellowTrinketUpgrade'] = 1, ['MasterYi'] = 65, ['Lissandra'] = 65, ['ARAMOrderTurretNexus'] = 88.4, ['Draven'] = 65, ['FiddleSticks'] = 65, ['SmallGolem'] = 80.0, ['ARAMOrderTurretFront'] = 88.4, ['ChaosTurretTutorial'] = 88.4, ['NasusUlt'] = 80.0, ['Maokai'] = 80.0, ['Wraith'] = 50.0, ['Wolf'] = 50.0, ['Sivir'] = 65, ['Corki'] = 65, ['Janna'] = 65, ['Nasus'] = 80.0, ['Golem'] = 80.0, ['ARAMChaosTurretFront'] = 88.4, ['ARAMOrderTurretInhib'] = 88.4, ['LeeSin'] = 65, ['HA_AP_ChaosTurretTutorial'] = 88.4, ['GiantWolf'] = 65.0, ['HA_AP_OrderTurretTutorial'] = 88.4, ['YoungLizard'] = 50.0, ['Jax'] = 65, ['LesserWraith'] = 50.0, ['Blitzcrank'] = 80.0, ['brush_D_SR'] = 65, ['brush_E_SR'] = 65, ['brush_F_SR'] = 65, ['brush_C_SR'] = 65, ['brush_A_SR'] = 65, ['brush_B_SR'] = 65, ['ARAMChaosTurretInhib'] = 88.4, ['Shen'] = 65, ['Nocturne'] = 65, ['Sona'] = 65, ['ARAMChaosTurretNexus'] = 88.4, ['YellowTrinket'] = 1, ['OrderTurretTutorial'] = 88.4, ['Caitlyn'] = 65, ['Trundle'] = 65, ['Malphite'] = 80.0, ['Mordekaiser'] = 80.0, ['ZyraSeed'] = 65, ['Vi'] = 50, ['Tutorial_Red_Minion_Wizard'] = 48.0, ['Renekton'] = 80.0, ['Anivia'] = 65, ['Fizz'] = 65, ['Heimerdinger'] = 55.0, ['Evelynn'] = 65, ['Rumble'] = 80.0, ['Leblanc'] = 65, ['Darius'] = 80.0, ['OlafAxe'] = 50.0, ['Viktor'] = 65, ['XinZhao'] = 65, ['Orianna'] = 65, ['Vladimir'] = 65, ['Nidalee'] = 65, ['Tutorial_Red_Minion_Basic'] = 48.0, ['ZedShadow'] = 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, ['Blue_Minion_Basic'] = 48.0, ['Brand'] = 65, ['Teemo'] = 55.0, ['Amumu'] = 55.0, ['Annie'] = 55.0, ['Odin_Blue_Minion_caster'] = 48.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, ['Tutorial_Blue_Minion_Wizard'] = 48.0, ['DrMundo'] = 80.0, ['Volibear'] = 80.0, ['Irelia'] = 65, ['Odin_Red_Minion_Caster'] = 48.0, ['Lucian'] = 65, ['Yorick'] = 80.0, ['RammusPB'] = 65, ['Red_Minion_Basic'] = 48.0, ['Udyr'] = 65, ['MonkeyKing'] = 65, ['Tutorial_Blue_Minion_Basic'] = 48.0, ['Kennen'] = 55.0, ['Nunu'] = 65, ['Ryze'] = 65, ['Zed'] = 65, ['Nautilus'] = 80.0, ['Gangplank'] = 65, ['shopevo'] = 65, ['Lux'] = 65, ['Sejuani'] = 80.0, ['Ezreal'] = 65, ['OdinNeutralGuardian'] = 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, ['YorickRavenousGhoul'] = 1.0, ['YorickSpectralGhoul'] = 1.0, ['JinxMine'] = 65, ['YorickDecayedGhoul'] = 1.0, ['XerathArcaneBarrageLauncher'] = 65, ['Odin_SOG_Order_Crystal'] = 65, ['TestCube'] = 65, ['ShyvanaDragon'] = 80.0, ['FizzBait'] = 65, ['ShopKeeper'] = 65, ['Blue_Minion_MechMelee'] = 65.0, ['OdinQuestBuff'] = 65, ['TT_Buffplat_L'] = 65, ['TT_Buffplat_R'] = 65, ['KogMawDead'] = 65, ['TempMovableChar'] = 48.0, ['Lizard'] = 50.0, ['GolemOdin'] = 80.0, ['OdinOpeningBarrier'] = 65, ['TT_ChaosTurret4'] = 88.4, ['TT_Flytrap_A'] = 65, ['TT_Chains_Order_Periph'] = 65, ['TT_NWolf'] = 65.0, ['ShopMale'] = 65, ['OdinShieldRelic'] = 65, ['TT_Chains_Xaos_Base'] = 65, ['LuluSquill'] = 50.0, ['TT_Shopkeeper'] = 65, ['redDragon'] = 100.0, ['MonkeyKingClone'] = 65, ['Odin_skeleton'] = 65, ['OdinChaosTurretShrine'] = 88.4, ['Cassiopeia_Death'] = 65, ['OdinCenterRelic'] = 48.0, ['Ezreal_cyber_1'] = 65, ['Ezreal_cyber_3'] = 65, ['Ezreal_cyber_2'] = 65, ['OdinRedSuperminion'] = 55.0, ['TT_Speedshrine_Gears'] = 65, ['JarvanIVWall'] = 65, ['DestroyedNexus'] = 65, ['ARAMOrderNexus'] = 65, ['Red_Minion_MechCannon'] = 65.0, ['OdinBlueSuperminion'] = 55.0, ['SyndraOrbs'] = 65, ['LuluKitty'] = 50.0, ['SwainNoBird'] = 65, ['LuluLadybug'] = 50.0, ['CaitlynTrap'] = 65, ['TT_Shroom_A'] = 65, ['ARAMChaosTurretShrine'] = 88.4, ['Odin_Windmill_Propellers'] = 65, ['DestroyedInhibitor'] = 65, ['TT_NWolf2'] = 50.0, ['OdinMinionGraveyardPortal'] = 1.0, ['SwainBeam'] = 65, ['Summoner_Rider_Order'] = 65.0, ['TT_Relic'] = 65, ['odin_lifts_crystal'] = 65, ['OdinOrderTurretShrine'] = 88.4, ['SpellBook1'] = 65, ['Blue_Minion_MechCannon'] = 65.0, ['TT_ChaosInhibitor_D'] = 65, ['Odin_SoG_Chaos'] = 65, ['TrundleWall'] = 65, ['HA_AP_HealthRelic'] = 65, ['OrderTurretShrine'] = 88.4, ['OriannaBall'] = 48.0, ['ChaosTurretShrine'] = 88.4, ['LuluCupcake'] = 50.0, ['HA_AP_ChaosTurretShrine'] = 88.4, ['TT_Chains_Bot_Lane'] = 65, ['TT_NWraith2'] = 50.0, ['TT_Tree_A'] = 65, ['SummonerBeacon'] = 65, ['Odin_Drill'] = 65, ['TT_NGolem'] = 80.0, ['Shop'] = 65, ['AramSpeedShrine'] = 65, ['DestroyedTower'] = 65, ['OriannaNoBall'] = 65, ['Odin_Minecart'] = 65, ['Summoner_Rider_Chaos'] = 65.0, ['OdinSpeedShrine'] = 65, ['TT_Brazier'] = 65, ['TT_SpeedShrine'] = 65, ['odin_lifts_buckets'] = 65, ['OdinRockSaw'] = 65, ['OdinMinionSpawnPortal'] = 1.0, ['SyndraSphere'] = 48.0, ['TT_Nexus_Gears'] = 65, ['Red_Minion_MechMelee'] = 65.0, ['SwainRaven'] = 65, ['crystal_platform'] = 65, ['MaokaiSproutling'] = 48.0, ['Urf'] = 65, ['TestCubeRender10Vision'] = 65, ['MalzaharVoidling'] = 10.0, ['GhostWard'] = 1, ['MonkeyKingFlying'] = 65, ['LuluPig'] = 50.0, ['AniviaIceBlock'] = 65, ['TT_OrderInhibitor_D'] = 65, ['yonkey'] = 65, ['Odin_SoG_Order'] = 65, ['RammusDBC'] = 65, ['FizzShark'] = 65, ['LuluDragon'] = 50.0, ['OdinTestCubeRender'] = 65, ['OdinCrane'] = 65, ['TT_Tree1'] = 65, ['ARAMOrderTurretShrine'] = 88.4, ['TT_Chains_Order_Base'] = 65, ['Odin_Windmill_Gears'] = 65, ['ARAMChaosNexus'] = 65, ['TT_NWraith'] = 50.0, ['TT_OrderTurret4'] = 88.4, ['Odin_SOG_Chaos_Crystal'] = 65, ['TT_SpiderLayer_Web'] = 65, ['OdinQuestIndicator'] = 1.0, ['JarvanIVStandard'] = 65, ['TT_DummyPusher'] = 65, ['OdinClaw'] = 65, ['EliseSpiderling'] = 1.0, ['QuinnValor'] = 65, ['UdyrTigerUlt'] = 65, ['UdyrTurtleUlt'] = 65, ['UdyrUlt'] = 65, ['UdyrPhoenixUlt'] = 65, ['ShacoBox'] = 10, ['HA_AP_Poro'] = 65, ['AnnieTibbers'] = 80.0, ['UdyrPhoenix'] = 65, ['UdyrTurtle'] = 65, ['UdyrTiger'] = 65, ['HA_AP_OrderShrineTurret'] = 88.4, ['HA_AP_OrderTurretRubble'] = 65, ['HA_AP_Chains_Long'] = 65, ['HA_AP_OrderCloth'] = 65, ['HA_AP_PeriphBridge'] = 65, ['HA_AP_BridgeLaneStatue'] = 65, ['HA_AP_ChaosTurretRubble'] = 88.4, ['HA_AP_BannerMidBridge'] = 65, ['HA_AP_PoroSpawner'] = 50.0, ['HA_AP_Cutaway'] = 65, ['HA_AP_Chains'] = 65, ['HA_AP_ShpSouth'] = 65, ['HA_AP_HeroTower'] = 65, ['HA_AP_ShpNorth'] = 65, ['ChaosInhibitor_D'] = 65, ['ZacRebirthBloblet'] = 65, ['OrderInhibitor_D'] = 65, ['Nidalee_Spear'] = 65, ['Nidalee_Cougar'] = 65, ['TT_Buffplat_Chain'] = 65, ['WriggleLantern'] = 1, ['TwistedLizardElder'] = 65.0, ['RabidWolf'] = 65.0, ['HeimerTGreen'] = 50.0, ['HeimerTRed'] = 50.0, ['ViktorFF'] = 65, ['TwistedGolem'] = 80.0, ['TwistedSmallWolf'] = 50.0, ['TwistedGiantWolf'] = 65.0, ['TwistedTinyWraith'] = 50.0, ['TwistedBlueWraith'] = 50.0, ['TwistedYoungLizard'] = 50.0, ['Red_Minion_Melee'] = 48.0, ['Blue_Minion_Melee'] = 48.0, ['Blue_Minion_Healer'] = 48.0, ['Ghast'] = 60.0, ['blueDragon'] = 100.0, ['Red_Minion_MechRange'] = 65.0, ['Test_CubeSphere'] = 65,} self.projectilespeeds = {["Velkoz"]= 2000,["TeemoMushroom"] = math.huge,["TestCubeRender"] = math.huge ,["Xerath"] = 2000.0000 ,["Kassadin"] = math.huge ,["Rengar"] = math.huge ,["Thresh"] = 1000.0000 ,["Ziggs"] = 1500.0000 ,["ZyraPassive"] = 1500.0000 ,["ZyraThornPlant"] = 1500.0000 ,["KogMaw"] = 1800.0000 ,["HeimerTBlue"] = 1599.3999 ,["EliseSpider"] = 500.0000 ,["Skarner"] = 500.0000 ,["ChaosNexus"] = 500.0000 ,["Katarina"] = 467.0000 ,["Riven"] = 347.79999 ,["SightWard"] = 347.79999 ,["HeimerTYellow"] = 1599.3999 ,["Ashe"] = 2000.0000 ,["VisionWard"] = 2000.0000 ,["TT_NGolem2"] = math.huge ,["ThreshLantern"] = math.huge ,["TT_Spiderboss"] = math.huge ,["OrderNexus"] = math.huge ,["Soraka"] = 1000.0000 ,["Jinx"] = 2750.0000 ,["TestCubeRenderwCollision"] = 2750.0000 ,["Red_Minion_Wizard"] = 650.0000 ,["JarvanIV"] = 20.0000 ,["Blue_Minion_Wizard"] = 650.0000 ,["TT_ChaosTurret2"] = 1200.0000 ,["TT_ChaosTurret3"] = 1200.0000 ,["TT_ChaosTurret1"] = 1200.0000 ,["ChaosTurretGiant"] = 1200.0000 ,["Dragon"] = 1200.0000 ,["LuluSnowman"] = 1200.0000 ,["Worm"] = 1200.0000 ,["ChaosTurretWorm"] = 1200.0000 ,["TT_ChaosInhibitor"] = 1200.0000 ,["ChaosTurretNormal"] = 1200.0000 ,["AncientGolem"] = 500.0000 ,["ZyraGraspingPlant"] = 500.0000 ,["HA_AP_OrderTurret3"] = 1200.0000 ,["HA_AP_OrderTurret2"] = 1200.0000 ,["Tryndamere"] = 347.79999 ,["OrderTurretNormal2"] = 1200.0000 ,["Singed"] = 700.0000 ,["OrderInhibitor"] = 700.0000 ,["Diana"] = 347.79999 ,["HA_FB_HealthRelic"] = 347.79999 ,["TT_OrderInhibitor"] = 347.79999 ,["GreatWraith"] = 750.0000 ,["Yasuo"] = 347.79999 ,["OrderTurretDragon"] = 1200.0000 ,["OrderTurretNormal"] = 1200.0000 ,["LizardElder"] = 500.0000 ,["HA_AP_ChaosTurret"] = 1200.0000 ,["Ahri"] = 1750.0000 ,["Lulu"] = 1450.0000 ,["ChaosInhibitor"] = 1450.0000 ,["HA_AP_ChaosTurret3"] = 1200.0000 ,["HA_AP_ChaosTurret2"] = 1200.0000 ,["ChaosTurretWorm2"] = 1200.0000 ,["TT_OrderTurret1"] = 1200.0000 ,["TT_OrderTurret2"] = 1200.0000 ,["TT_OrderTurret3"] = 1200.0000 ,["LuluFaerie"] = 1200.0000 ,["HA_AP_OrderTurret"] = 1200.0000 ,["OrderTurretAngel"] = 1200.0000 ,["YellowTrinketUpgrade"] = 1200.0000 ,["MasterYi"] = math.huge ,["Lissandra"] = 2000.0000 ,["ARAMOrderTurretNexus"] = 1200.0000 ,["Draven"] = 1700.0000 ,["FiddleSticks"] = 1750.0000 ,["SmallGolem"] = math.huge ,["ARAMOrderTurretFront"] = 1200.0000 ,["ChaosTurretTutorial"] = 1200.0000 ,["NasusUlt"] = 1200.0000 ,["Maokai"] = math.huge ,["Wraith"] = 750.0000 ,["Wolf"] = math.huge ,["Sivir"] = 1750.0000 ,["Corki"] = 2000.0000 ,["Janna"] = 1200.0000 ,["Nasus"] = math.huge ,["Golem"] = math.huge ,["ARAMChaosTurretFront"] = 1200.0000 ,["ARAMOrderTurretInhib"] = 1200.0000 ,["LeeSin"] = math.huge ,["HA_AP_ChaosTurretTutorial"] = 1200.0000 ,["GiantWolf"] = math.huge ,["HA_AP_OrderTurretTutorial"] = 1200.0000 ,["YoungLizard"] = 750.0000 ,["Jax"] = 400.0000 ,["LesserWraith"] = math.huge ,["Blitzcrank"] = math.huge ,["ARAMChaosTurretInhib"] = 1200.0000 ,["Shen"] = 400.0000 ,["Nocturne"] = math.huge ,["Sona"] = 1500.0000 ,["ARAMChaosTurretNexus"] = 1200.0000 ,["YellowTrinket"] = 1200.0000 ,["OrderTurretTutorial"] = 1200.0000 ,["Caitlyn"] = 2500.0000 ,["Trundle"] = 347.79999 ,["Malphite"] = 1000.0000 ,["Mordekaiser"] = math.huge ,["ZyraSeed"] = math.huge ,["Vi"] = 1000.0000 ,["Tutorial_Red_Minion_Wizard"] = 650.0000 ,["Renekton"] = math.huge ,["Anivia"] = 1400.0000 ,["Fizz"] = math.huge ,["Heimerdinger"] = 1500.0000 ,["Evelynn"] = 467.0000 ,["Rumble"] = 347.79999 ,["Leblanc"] = 1700.0000 ,["Darius"] = math.huge ,["OlafAxe"] = math.huge ,["Viktor"] = 2300.0000 ,["XinZhao"] = 20.0000 ,["Orianna"] = 1450.0000 ,["Vladimir"] = 1400.0000 ,["Nidalee"] = 1750.0000 ,["Tutorial_Red_Minion_Basic"] = math.huge ,["ZedShadow"] = 467.0000 ,["Syndra"] = 1800.0000 ,["Zac"] = 1000.0000 ,["Olaf"] = 347.79999 ,["Veigar"] = 1100.0000 ,["Twitch"] = 2500.0000 ,["Alistar"] = math.huge ,["Akali"] = 467.0000 ,["Urgot"] = 1300.0000 ,["Leona"] = 347.79999 ,["Talon"] = math.huge ,["Karma"] = 1500.0000 ,["Jayce"] = 347.79999 ,["Galio"] = 1000.0000 ,["Shaco"] = math.huge ,["Taric"] = math.huge ,["TwistedFate"] = 1500.0000 ,["Varus"] = 2000.0000 ,["Garen"] = 347.79999 ,["Swain"] = 1600.0000 ,["Vayne"] = 2000.0000 ,["Fiora"] = 467.0000 ,["Quinn"] = 2000.0000 ,["Kayle"] = math.huge ,["Blue_Minion_Basic"] = math.huge ,["Brand"] = 2000.0000 ,["Teemo"] = 1300.0000 ,["Amumu"] = 500.0000 ,["Annie"] = 1200.0000 ,["Odin_Blue_Minion_caster"] = 1200.0000 ,["Elise"] = 1600.0000 ,["Nami"] = 1500.0000 ,["Poppy"] = 500.0000 ,["AniviaEgg"] = 500.0000 ,["Tristana"] = 2250.0000 ,["Graves"] = 3000.0000 ,["Morgana"] = 1600.0000 ,["Gragas"] = math.huge ,["MissFortune"] = 2000.0000 ,["Warwick"] = math.huge ,["Cassiopeia"] = 1200.0000 ,["Tutorial_Blue_Minion_Wizard"] = 650.0000 ,["DrMundo"] = math.huge ,["Volibear"] = 467.0000 ,["Irelia"] = 467.0000 ,["Odin_Red_Minion_Caster"] = 650.0000 ,["Lucian"] = 2800.0000 ,["Yorick"] = math.huge ,["RammusPB"] = math.huge ,["Red_Minion_Basic"] = math.huge ,["Udyr"] = 467.0000 ,["MonkeyKing"] = 20.0000 ,["Tutorial_Blue_Minion_Basic"] = math.huge ,["Kennen"] = 1600.0000 ,["Nunu"] = 500.0000 ,["Ryze"] = 2400.0000 ,["Zed"] = 467.0000 ,["Nautilus"] = 1000.0000 ,["Gangplank"] = 1000.0000 ,["Lux"] = 1600.0000 ,["Sejuani"] = 500.0000 ,["Ezreal"] = 2000.0000 ,["OdinNeutralGuardian"] = 1800.0000 ,["Khazix"] = 500.0000 ,["Sion"] = math.huge ,["Aatrox"] = 347.79999 ,["Hecarim"] = 500.0000 ,["Pantheon"] = 20.0000 ,["Shyvana"] = 467.0000 ,["Zyra"] = 1700.0000 ,["Karthus"] = 1200.0000 ,["Rammus"] = math.huge ,["Zilean"] = 1200.0000 ,["Chogath"] = 500.0000 ,["Malzahar"] = 2000.0000 ,["YorickRavenousGhoul"] = 347.79999 ,["YorickSpectralGhoul"] = 347.79999 ,["JinxMine"] = 347.79999 ,["YorickDecayedGhoul"] = 347.79999 ,["XerathArcaneBarrageLauncher"] = 347.79999 ,["Odin_SOG_Order_Crystal"] = 347.79999 ,["TestCube"] = 347.79999 ,["ShyvanaDragon"] = math.huge ,["FizzBait"] = math.huge ,["Blue_Minion_MechMelee"] = math.huge ,["OdinQuestBuff"] = math.huge ,["TT_Buffplat_L"] = math.huge ,["TT_Buffplat_R"] = math.huge ,["KogMawDead"] = math.huge ,["TempMovableChar"] = math.huge ,["Lizard"] = 500.0000 ,["GolemOdin"] = math.huge ,["OdinOpeningBarrier"] = math.huge ,["TT_ChaosTurret4"] = 500.0000 ,["TT_Flytrap_A"] = 500.0000 ,["TT_NWolf"] = math.huge ,["OdinShieldRelic"] = math.huge ,["LuluSquill"] = math.huge ,["redDragon"] = math.huge ,["MonkeyKingClone"] = math.huge ,["Odin_skeleton"] = math.huge ,["OdinChaosTurretShrine"] = 500.0000 ,["Cassiopeia_Death"] = 500.0000 ,["OdinCenterRelic"] = 500.0000 ,["OdinRedSuperminion"] = math.huge ,["JarvanIVWall"] = math.huge ,["ARAMOrderNexus"] = math.huge ,["Red_Minion_MechCannon"] = 1200.0000 ,["OdinBlueSuperminion"] = math.huge ,["SyndraOrbs"] = math.huge ,["LuluKitty"] = math.huge ,["SwainNoBird"] = math.huge ,["LuluLadybug"] = math.huge ,["CaitlynTrap"] = math.huge ,["TT_Shroom_A"] = math.huge ,["ARAMChaosTurretShrine"] = 500.0000 ,["Odin_Windmill_Propellers"] = 500.0000 ,["TT_NWolf2"] = math.huge ,["OdinMinionGraveyardPortal"] = math.huge ,["SwainBeam"] = math.huge ,["Summoner_Rider_Order"] = math.huge ,["TT_Relic"] = math.huge ,["odin_lifts_crystal"] = math.huge ,["OdinOrderTurretShrine"] = 500.0000 ,["SpellBook1"] = 500.0000 ,["Blue_Minion_MechCannon"] = 1200.0000 ,["TT_ChaosInhibitor_D"] = 1200.0000 ,["Odin_SoG_Chaos"] = 1200.0000 ,["TrundleWall"] = 1200.0000 ,["HA_AP_HealthRelic"] = 1200.0000 ,["OrderTurretShrine"] = 500.0000 ,["OriannaBall"] = 500.0000 ,["ChaosTurretShrine"] = 500.0000 ,["LuluCupcake"] = 500.0000 ,["HA_AP_ChaosTurretShrine"] = 500.0000 ,["TT_NWraith2"] = 750.0000 ,["TT_Tree_A"] = 750.0000 ,["SummonerBeacon"] = 750.0000 ,["Odin_Drill"] = 750.0000 ,["TT_NGolem"] = math.huge ,["AramSpeedShrine"] = math.huge ,["OriannaNoBall"] = math.huge ,["Odin_Minecart"] = math.huge ,["Summoner_Rider_Chaos"] = math.huge ,["OdinSpeedShrine"] = math.huge ,["TT_SpeedShrine"] = math.huge ,["odin_lifts_buckets"] = math.huge ,["OdinRockSaw"] = math.huge ,["OdinMinionSpawnPortal"] = math.huge ,["SyndraSphere"] = math.huge ,["Red_Minion_MechMelee"] = math.huge ,["SwainRaven"] = math.huge ,["crystal_platform"] = math.huge ,["MaokaiSproutling"] = math.huge ,["Urf"] = math.huge ,["TestCubeRender10Vision"] = math.huge ,["MalzaharVoidling"] = 500.0000 ,["GhostWard"] = 500.0000 ,["MonkeyKingFlying"] = 500.0000 ,["LuluPig"] = 500.0000 ,["AniviaIceBlock"] = 500.0000 ,["TT_OrderInhibitor_D"] = 500.0000 ,["Odin_SoG_Order"] = 500.0000 ,["RammusDBC"] = 500.0000 ,["FizzShark"] = 500.0000 ,["LuluDragon"] = 500.0000 ,["OdinTestCubeRender"] = 500.0000 ,["TT_Tree1"] = 500.0000 ,["ARAMOrderTurretShrine"] = 500.0000 ,["Odin_Windmill_Gears"] = 500.0000 ,["ARAMChaosNexus"] = 500.0000 ,["TT_NWraith"] = 750.0000 ,["TT_OrderTurret4"] = 500.0000 ,["Odin_SOG_Chaos_Crystal"] = 500.0000 ,["OdinQuestIndicator"] = 500.0000 ,["JarvanIVStandard"] = 500.0000 ,["TT_DummyPusher"] = 500.0000 ,["OdinClaw"] = 500.0000 ,["EliseSpiderling"] = 2000.0000 ,["QuinnValor"] = math.huge ,["UdyrTigerUlt"] = math.huge ,["UdyrTurtleUlt"] = math.huge ,["UdyrUlt"] = math.huge ,["UdyrPhoenixUlt"] = math.huge ,["ShacoBox"] = 1500.0000 ,["HA_AP_Poro"] = 1500.0000 ,["AnnieTibbers"] = math.huge ,["UdyrPhoenix"] = math.huge ,["UdyrTurtle"] = math.huge ,["UdyrTiger"] = math.huge ,["HA_AP_OrderShrineTurret"] = 500.0000 ,["HA_AP_Chains_Long"] = 500.0000 ,["HA_AP_BridgeLaneStatue"] = 500.0000 ,["HA_AP_ChaosTurretRubble"] = 500.0000 ,["HA_AP_PoroSpawner"] = 500.0000 ,["HA_AP_Cutaway"] = 500.0000 ,["HA_AP_Chains"] = 500.0000 ,["ChaosInhibitor_D"] = 500.0000 ,["ZacRebirthBloblet"] = 500.0000 ,["OrderInhibitor_D"] = 500.0000 ,["Nidalee_Spear"] = 500.0000 ,["Nidalee_Cougar"] = 500.0000 ,["TT_Buffplat_Chain"] = 500.0000 ,["WriggleLantern"] = 500.0000 ,["TwistedLizardElder"] = 500.0000 ,["RabidWolf"] = math.huge ,["HeimerTGreen"] = 1599.3999 ,["HeimerTRed"] = 1599.3999 ,["ViktorFF"] = 1599.3999 ,["TwistedGolem"] = math.huge ,["TwistedSmallWolf"] = math.huge ,["TwistedGiantWolf"] = math.huge ,["TwistedTinyWraith"] = 750.0000 ,["TwistedBlueWraith"] = 750.0000 ,["TwistedYoungLizard"] = 750.0000 ,["Red_Minion_Melee"] = math.huge ,["Blue_Minion_Melee"] = math.huge ,["Blue_Minion_Healer"] = 1000.0000 ,["Ghast"] = 750.0000 ,["blueDragon"] = 800.0000 ,["Red_Minion_MechRange"] = 3000.0000,} self.ActiveAttacks = {} self.MinionsAttacks = {} if not _G.VPredictionMenu then _G.VPredictionMenu = scriptConfig("VPrediction", "VPrediction") _G.VPredictionMenu:addParam("Mode", "Cast Mode", SCRIPT_PARAM_LIST, 1, {"Fast", "Medium", "Slow" }) --[[Collision]] _G.VPredictionMenu:addSubMenu("Collision", "Collision") _G.VPredictionMenu.Collision:addParam("Buffer", "Collision buffer", SCRIPT_PARAM_SLICE, 20, 0, 100) _G.VPredictionMenu.Collision:addParam("Minions", "Normal minions", SCRIPT_PARAM_ONOFF, true) _G.VPredictionMenu.Collision:addParam("Mobs", "Jungle minions", SCRIPT_PARAM_ONOFF, true) _G.VPredictionMenu.Collision:addParam("Others", "Others", SCRIPT_PARAM_ONOFF, true) _G.VPredictionMenu.Collision:addParam("CHealth", "Check if minions are about to die (BETA)", SCRIPT_PARAM_ONOFF, false) _G.VPredictionMenu.Collision:addParam("info", "-", SCRIPT_PARAM_INFO, "^ Can cause fps drops") _G.VPredictionMenu.Collision:addParam("UnitPos", "Check collision at the unit pos", SCRIPT_PARAM_ONOFF, true) _G.VPredictionMenu.Collision:addParam("CastPos", "Check collision at the cast pos", SCRIPT_PARAM_ONOFF, true) _G.VPredictionMenu.Collision:addParam("PredictPos", "Check collision at the predicted pos", SCRIPT_PARAM_ONOFF, false) if self.showdevmode then _G.VPredictionMenu:addSubMenu("Developers", "Developers") _G.VPredictionMenu.Developers:addParam("Debug", "Enable debug", SCRIPT_PARAM_ONOFF, false) _G.VPredictionMenu.Developers:addParam("SC", "Show collision", SCRIPT_PARAM_ONOFF, false) end _G.VPredictionMenu:addParam("Version", "Version", SCRIPT_PARAM_INFO, tostring(self.version)) end --[[Use waypoints from the last 10 seconds]] self.WaypointsTime = 10 self.EnemyMinions = minionManager(MINION_ENEMY, 2000, myHero, MINION_SORT_HEALTH_ASC) self.JungleMinions = minionManager(MINION_JUNGLE, 2000, myHero, MINION_SORT_HEALTH_ASC) self.OtherMinions = minionManager(MINION_OTHER, 2000, myHero, MINION_SORT_HEALTH_ASC) self.TargetsVisible = {} self.TargetsWaypoints = {} self.TargetsImmobile = {} self.TargetsDashing = {} self.TargetsSlowed = {} self.DontShoot = {} self.DontShoot2 = {} self.DontShootUntilNewWaypoints = {} if VIP_USER then WayPointManager.AddCallback(function(NetworkID) self:OnNewWayPoints(NetworkID) end) AdvancedCallback:bind("OnGainVision", function(unit) self:OnGainVision(unit) end) AdvancedCallback:bind("OnGainBuff", function(unit, buff) self:OnGainBuff(unit, buff) end) AdvancedCallback:bind("OnDash", function(unit, dash) self:OnDash(unit, dash) end) end AddProcessSpellCallback(function(unit, spell) self:OnProcessSpell(unit, spell) end) AddTickCallback(function() self:OnTick() end) AddDrawCallback(function() self:OnDraw() end) AddProcessSpellCallback(function(unit, spell) self:CollisionProcessSpell(unit, spell) end) self.BlackList = { {name = "aatroxq", duration = 0.75}, --[[4 Dashes, OnDash fails]] } --[[Spells that will cause OnDash to fire, dont shoot and wait to OnDash]] self.dashAboutToHappend = { {name = "ahritumble", duration = 0.25},--ahri's r {name = "akalishadowdance", duration = 0.25},--akali r {name = "headbutt", duration = 0.25},--alistar w {name = "caitlynentrapment", duration = 0.25},--caitlyn e {name = "carpetbomb", duration = 0.25},--corki w {name = "dianateleport", duration = 0.25},--diana r {name = "fizzpiercingstrike", duration = 0.25},--fizz q {name = "fizzjump", duration = 0.25},--fizz e {name = "gragasbodyslam", duration = 0.25},--gragas e {name = "gravesmove", duration = 0.25},--graves e {name = "ireliagatotsu", duration = 0.25},--irelia q {name = "jarvanivdragonstrike", duration = 0.25},--jarvan q {name = "jaxleapstrike", duration = 0.25},--jax q {name = "khazixe", duration = 0.25},--khazix e and e evolved {name = "leblancslide", duration = 0.25},--leblanc w {name = "leblancslidem", duration = 0.25},--leblanc w (r) {name = "blindmonkqtwo", duration = 0.25},--lee sin q {name = "blindmonkwone", duration = 0.25},--lee sin w {name = "luciane", duration = 0.25},--lucian e {name = "maokaiunstablegrowth", duration = 0.25},--maokai w {name = "nocturneparanoia2", duration = 0.25},--nocturne r {name = "pantheon_leapbash", duration = 0.25},--pantheon e? {name = "renektonsliceanddice", duration = 0.25},--renekton e {name = "riventricleave", duration = 0.25},--riven q {name = "rivenfeint", duration = 0.25},--riven e {name = "sejuaniarcticassault", duration = 0.25},--sejuani q {name = "shenshadowdash", duration = 0.25},--shen e {name = "shyvanatransformcast", duration = 0.25},--shyvana r {name = "rocketjump", duration = 0.25},--tristana w {name = "slashcast", duration = 0.25},--tryndamere e {name = "vaynetumble", duration = 0.25},--vayne q {name = "viq", duration = 0.25},--vi q {name = "monkeykingnimbus", duration = 0.25},--wukong q {name = "xenzhaosweep", duration = 0.25},--xin xhao q {name = "yasuodashwrapper", duration = 0.25},--yasuo e } --[[Spells that don't allow movement (durations approx)]] self.spells = { {name = "katarinar", duration = 1}, --Katarinas R {name = "drain", duration = 1}, --Fiddle W {name = "crowstorm", duration = 1}, --Fiddle R {name = "consume", duration = 0.5}, --Nunu Q {name = "absolutezero", duration = 1}, --Nunu R {name = "rocketgrab", duration = 0.5}, --Blitzcrank Q {name = "staticfield", duration = 0.5}, --Blitzcrank R {name = "cassiopeiapetrifyinggaze", duration = 0.5}, --Cassio's R {name = "ezrealtrueshotbarrage", duration = 1}, --Ezreal's R {name = "galioidolofdurand", duration = 1}, --Ezreal's R --{name = "gragasdrunkenrage", duration = 1}, --Gragas W, Rito changed it so that it allows full movement while casting {name = "luxmalicecannon", duration = 1}, --Lux R {name = "reapthewhirlwind", duration = 1}, --Jannas R {name = "jinxw", duration = 0.6}, --jinxW {name = "jinxr", duration = 0.6}, --jinxR {name = "missfortunebullettime", duration = 1}, --MissFortuneR {name = "shenstandunited", duration = 1}, --ShenR {name = "threshe", duration = 0.4}, --ThreshE {name = "threshrpenta", duration = 0.75}, --ThreshR {name = "infiniteduress", duration = 1}, --Warwick R {name = "meditate", duration = 1} --yi W } self.blinks = { {name = "ezrealarcaneshift", range = 475, delay = 0.25, delay2=0.8},--Ezreals E {name = "deceive", range = 400, delay = 0.25, delay2=0.8}, --Shacos Q {name = "riftwalk", range = 700, delay = 0.25, delay2=0.8},--KassadinR {name = "gate", range = 5500, delay = 1.5, delay2=1.5},--Twisted fate R {name = "katarinae", range = math.huge, delay = 0.25, delay2=0.8},--Katarinas E {name = "elisespideredescent", range = math.huge, delay = 0.25, delay2=0.8},--Elise E {name = "elisespidere", range = math.huge, delay = 0.25, delay2=0.8},--Elise insta E } return self end --R_WAYPOINT new definition, known as broken --[[ if VIP_USER then load(Base64Decode("G0x1YVIAAQQEBAgAGZMNChoKAAAAAAAAAAAAAQMMAAAABgBAAAdAQAAHgEAAS8AAAKUAAABKgACCpUAAAEqAgIKlgAAASoAAgwpAgIEfAIAABwAAAAQDAAAAX0cABAcAAABQYWNrZXQABAsAAABkZWZpbml0aW9uAAQLAAAAUl9XQVlQT0lOVAAEBQAAAGluaXQABAcAAABkZWNvZGUABAcAAABlbmNvZGUAAwAAAAIAAAAJAAAAAAAIEAAAAAsAAQBLAAADgUAAAMFAAAABQQAAQUEAAIFBAADBQQAAZEAAAwpAAIAKQECBCkDAgUsAAAAKQACCHwAAAR8AgAAFAAAABA8AAABhZGRpdGlvbmFsSW5mbwADAAAAAAAAAAAEDwAAAHNlcXVlbmNlTnVtYmVyAAQKAAAAbmV0d29ya0lkAAQKAAAAd2F5UG9pbnRzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAlAAAAAQAKPgAAAApAQIBLwAAAiwAAAEqAAIGMAEEAnYAAAUqAgIGLAAAASoCAgocAQACNgEEBzMBBAN2AAAGNwAABCoAAgIwAQQCdgAABSoAAhIxAQgCdgAABGIBCARfAAICHAEAAjcBCAZtAAAAXQACAhwBAAI0AQwEKgACAh0BDAMcAQAABgQMAoUAGgApAAYCMAUEAnYEAAcfBwAAYwAEDF8AEgIcBQADOwUMDCsABgMxBRADdgQABSsABiMxBQgDdgQAB0MHEA0rAAYnHAUAAzQHFAwrAAYDGQUUAx4HFAwACAABHgsQA3YGAAUrAgYIXAACAoAD5f18AAAEfAIAAFwAAAAQEAAAAcG9zAAMAAAAAAADwPwQPAAAAYWRkaXRpb25hbEluZm8ABAoAAABuZXR3b3JrSWQABAgAAABEZWNvZGVGAAQKAAAAd2F5UG9pbnRzAAMAAAAAAAAYQAQIAAAARGVjb2RlMgAEFAAAAGFkZGl0aW9uYWxOZXR3b3JrSWQABAgAAABEZWNvZGUxAAMAAAAAAAAAAAMAAAAAAAAsQAMAAAAAAAAoQAQFAAAAc2l6ZQADAAAAAAAA8L8DAAAAAAAAIkAEDwAAAHNlcXVlbmNlTnVtYmVyAAQIAAAARGVjb2RlNAAEDgAAAHdheXBvaW50Q291bnQAAwAAAAAAAABAAwAAAAAAABBABAcAAABQYWNrZXQABBAAAABkZWNvZGVXYXlQb2ludHMAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAnAAAAOQAAAAEACUUAAABGQEAAhoBAAIfAQAGHAEEBXYAAAQhAAIBGAEAATEDBAMeAQQDHwMEBXUCAAUYAQABMAMIAx4BBAMdAwgHVAIABzoDCAV1AgAFGwEIAh4BBAIdAQgFdAAEBF8AAgIYBQACMAUMDAAKAAp1BgAFigAAA40D+f0YAQABMAMMAwUADAF1AgAFGAEAATIDDAMeAQQDHwMMBXUCAAUYAQABMQMEAx4BBAMcAxAHHQMQBx4DEAV1AgAFGAEAATEDBAMeAQQDHAMQBx0DEAcfAxAFdQIABRgBAAExAwQDHgEEAxwDEAccAxQHHgMQBXUCAAUYAQABMQMEAx4BBAMcAxAHHAMUBx8DEAV1AgAFGAEAAXwAAAR8AgAAVAAAABAIAAABwAAQLAAAAQ0xvTFBhY2tldAAEBwAAAFBhY2tldAAECAAAAGhlYWRlcnMABAsAAABSX1dBWVBPSU5UAAQIAAAARW5jb2RlRgAEBwAAAHZhbHVlcwAECgAAAG5ldHdvcmtJZAAECAAAAEVuY29kZTIABA8AAABhZGRpdGlvbmFsSW5mbwADAAAAAAAAGEAEBwAAAGlwYWlycwAECAAAAEVuY29kZTEAAwAAAAAAAAhABAgAAABFbmNvZGU0AAQPAAAAc2VxdWVuY2VOdW1iZXIABAoAAAB3YXlQb2ludHMAAwAAAAAAAPA/BAIAAAB4AAQCAAAAeQADAAAAAAAAAEAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAA="))() end ]] function VPrediction:GetTime() return os.clock() end --[[Track when we lose or gain vision over an enemy]] function VPrediction:OnGainVision(unit) if unit.type == myHero.type then self.TargetsVisible[unit.networkID] = self:GetTime() end end --[[Track when we lose or gain vision over an enemy]] function VPrediction:OnLoseVision(unit) if unit.type == myHero.type then self.TargetsVisible[unit.networkID] = math.huge end end function VPrediction:OnGainBuff(unit, buff) if unit.type == myHero.type and (buff.type == BUFF_STUN or buff.type == BUFF_ROOT or buff.type == BUFF_KNOCKUP or buff.type == BUFF_SUPPRESS) then self.TargetsImmobile[unit.networkID] = self:GetTime() + buff.duration elseif unit.type == myHero.type and (buff.type == BUFF_SLOW or buff.type == BUFF_CHARM or buff.type == BUFF_FEAR or buff.type == BUFF_TAUNT) then self.TargetsSlowed[unit.networkID] = self:GetTime() + buff.duration end if unit.type == myHero.type and (buff.type == BUFF_KNOCKBACK) then self.DontShoot[unit.networkID] = self:GetTime() + 1 end end function VPrediction:OnDash(unit, dash) if unit.type == myHero.type then dash.endPos = dash.target and dash.target or dash.endPos dash.startT = self:GetTime() - GetLatency()/2000 dash.endT = dash.startT + dash.duration self.TargetsDashing[unit.networkID] = dash self.DontShootUntilNewWaypoints[unit.networkID] = true end end function VPrediction:OnProcessSpell(unit, spell) if unit and unit.type == myHero.type then for i, s in ipairs(self.spells) do if spell.name:lower() == s.name then self.TargetsImmobile[unit.networkID] = self:GetTime() + s.duration return end end for i, s in ipairs(self.blinks) do local LandingPos = GetDistance(unit, Vector(spell.endPos)) < s.range and Vector(spell.endPos) or Vector(unit) + s.range * (Vector(spell.endPos) - Vector(unit)):normalized() if spell.name:lower() == s.name and not IsWall(D3DXVECTOR3(spell.endPos.x, spell.endPos.y, spell.endPos.z)) then self.TargetsDashing[unit.networkID] = {isblink = true, duration = s.delay, endT = self:GetTime() + s.delay, endT2 = self:GetTime() + s.delay2, startPos = Vector(unit), endPos = LandingPos} return end end for i, s in ipairs(self.BlackList) do if spell.name:lower() == s.name then self.DontShoot[unit.networkID] = self:GetTime() + s.duration return end end for i, s in ipairs(self.dashAboutToHappend) do if spell.name:lower() == s.name then self.DontShoot2[unit.networkID] = self:GetTime() + s.duration return end end end end function VPrediction:OnNewWayPoints(NetworkID) local object = objManager:GetObjectByNetworkId(NetworkID) if object and object.valid and object.networkID and object.type == myHero.type then self.DontShootUntilNewWaypoints[NetworkID] = false if self.TargetsWaypoints[NetworkID] == nil then self.TargetsWaypoints[NetworkID] = {} end local WaypointsToAdd = WayPointManager:GetWayPoints(object) if WaypointsToAdd and #WaypointsToAdd >= 1 then --[[Save only the last waypoint (where the player clicked)]] table.insert(self.TargetsWaypoints[NetworkID], {unitpos = Vector(object) , waypoint = WaypointsToAdd[#WaypointsToAdd], time = self:GetTime(), n = #WaypointsToAdd}) end elseif object and object.valid and object.type ~= myHero.type then local i = 1 while i <= #self.ActiveAttacks do if (self.ActiveAttacks[i].Attacker and self.ActiveAttacks[i].Attacker.valid and self.ActiveAttacks[i].Attacker.networkID == NetworkID and (self.ActiveAttacks[i].starttime + self.ActiveAttacks[i].windUpTime - GetLatency()/2000) > self:GetTime()) then local wpts = WayPointManager:GetWayPoints(object) if #wpts > 1 then table.remove(self.ActiveAttacks, i) else i = i + 1 end else i = i + 1 end end end end function VPrediction:IsImmobile(unit, delay, radius, speed, from, spelltype) if self.TargetsImmobile[unit.networkID] then local ExtraDelay = speed == math.huge and 0 or (GetDistance(from, unit) / speed) if (self.TargetsImmobile[unit.networkID] > (self:GetTime() + delay + ExtraDelay) and spelltype == "circular") then return true, Vector(unit), Vector(unit) + (radius/3) * (Vector(from) - Vector(unit)):normalized() elseif (self.TargetsImmobile[unit.networkID] + (radius / unit.ms)) > (self:GetTime() + delay + ExtraDelay) then return true, Vector(unit), Vector(unit) end end return false, Vector(unit), Vector(unit) end function VPrediction:isSlowed(unit, delay, speed, from) if self.TargetsSlowed[unit.networkID] then if self.TargetsSlowed[unit.networkID] > (self:GetTime() + delay + GetDistance(unit, from) / speed) then return true end end return false end function VPrediction:IsDashing(unit, delay, radius, speed, from) local TargetDashing = false local CanHit = false local Position if self.TargetsDashing[unit.networkID] then local dash = self.TargetsDashing[unit.networkID] if dash.endT >= self:GetTime() then TargetDashing = true if dash.isblink then if (dash.endT - self:GetTime()) <= (delay + GetDistance(from, dash.endPos)/speed) then Position = Vector(dash.endPos.x, 0, dash.endPos.z) CanHit = (unit.ms * (delay + GetDistance(from, dash.endPos)/speed - (dash.endT2 - self:GetTime()))) < radius end if ((dash.endT - self:GetTime()) >= (delay + GetDistance(from, dash.startPos)/speed)) and not CanHit then Position = Vector(dash.startPos.x, 0, dash.startPos.z) CanHit = true end else local t1, p1, t2, p2, dist = VectorMovementCollision(dash.startPos, dash.endPos, dash.speed, from, speed, (self:GetTime() - dash.startT) + delay) t1, t2 = (t1 and 0 <= t1 and t1 <= (dash.endT - self:GetTime() - delay)) and t1 or nil, (t2 and 0 <= t2 and t2 <= (dash.endT - self:GetTime() - delay)) and t2 or nil local t = t1 and t2 and math.min(t1,t2) or t1 or t2 if t then Position = t==t1 and Vector(p1.x, 0, p1.y) or Vector(p2.x, 0, p2.y) CanHit = true else Position = Vector(dash.endPos.x, 0, dash.endPos.z) CanHit = (unit.ms * (delay + GetDistance(from, Position)/speed - (dash.endT - self:GetTime()))) < radius end end end end return TargetDashing, CanHit, Position end function VPrediction:GetWaypoints(NetworkID, from, to) local Result = {} to = to and to or self:GetTime() if self.TargetsWaypoints[NetworkID] then for i, waypoint in ipairs(self.TargetsWaypoints[NetworkID]) do if from <= waypoint.time and to >= waypoint.time then table.insert(Result, waypoint) end end end return Result, #Result end function VPrediction:CountWaypoints(NetworkID, from, to) local R, N = self:GetWaypoints(NetworkID, from, to) return N end function VPrediction:GetWaypointsLength(Waypoints) local result = 0 for i = 1, #Waypoints -1 do result = result + GetDistance(Waypoints[i], Waypoints[i + 1]) end return result end function VPrediction:CutWaypoints(Waypoints, distance) local result = {} local remaining = distance if distance > 0 then for i = 1, #Waypoints -1 do local A, B = Waypoints[i], Waypoints[i + 1] local dist = GetDistance(A, B) if dist >= remaining then result[1] = Vector(A) + remaining * (Vector(B) - Vector(A)):normalized() for j = i + 1, #Waypoints do result[j - i + 1] = Waypoints[j] end remaining = 0 break else remaining = remaining - dist end end else local A, B = Waypoints[1], Waypoints[2] result = Waypoints result[1] = Vector(A) - distance * (Vector(B) - Vector(A)):normalized() end return result end function VPrediction:GetCurrentWayPoints(object) local result = {} if not VIP_USER then if object.hasMovePath then table.insert(result, Vector(object.x, object.z)) for i = object.pathIndex, object.pathCount do path = object:GetPath(i) table.insert(result, Vector(path.x, path.z)) end else table.insert(result, object and Vector(object.x, object.z) or Vector(object.x, object.z)) end return result else local wayPoints, lineSegment, distanceSqr, fPoint = WayPointManager:GetRawWayPoints(object), 0, math.huge, nil if not wayPoints and not object then return { { x = object.x, y = object.z } } elseif not wayPoints and object then return { { x = object.x, y = object.z } } end for i = 1, #wayPoints - 1 do local p1, tmp1, tmp2 = VectorPointProjectionOnLineSegment(wayPoints[i], wayPoints[i + 1], Vector(object)) local distanceSegmentSqr = GetDistanceSqr(p1, object) if distanceSegmentSqr <= distanceSqr then fPoint = p1 lineSegment = i distanceSqr = distanceSegmentSqr else break --not necessary, but makes it faster end end local result = { fPoint or { x = object.x, y = object.z } } for i = lineSegment + 1, #wayPoints do result[#result + 1] = wayPoints[i] end if #result == 2 and GetDistanceSqr(result[1], result[2]) < 400 then result[2] = nil end return result end end --[[Calculate the hero position based on the last waypoints]] function VPrediction:CalculateTargetPosition(unit, delay, radius, speed, from, spelltype) local Waypoints = {} local Position, CastPosition = Vector(unit), Vector(unit) local t Waypoints = self:GetCurrentWayPoints(unit) local Waypointslength = self:GetWaypointsLength(Waypoints) if #Waypoints == 1 then Position, CastPosition = Vector(Waypoints[1].x, 0, Waypoints[1].y), Vector(Waypoints[1].x, 0, Waypoints[1].y) return Position, CastPosition elseif (Waypointslength - delay * unit.ms + radius) >= 0 then local tA = 0 Waypoints = self:CutWaypoints(Waypoints, delay * unit.ms - radius) if speed ~= math.huge then for i = 1, #Waypoints - 1 do local A, B = Waypoints[i], Waypoints[i+1] if i == #Waypoints - 1 then B = Vector(B) + radius * Vector(B - A):normalized() end local t1, p1, t2, p2, D = VectorMovementCollision(A, B, unit.ms, Vector(from.x, from.z), speed) local tB = tA + D / unit.ms t1, t2 = (t1 and tA <= t1 and t1 <= (tB - tA)) and t1 or nil, (t2 and tA <= t2 and t2 <= (tB - tA)) and t2 or nil t = t1 and t2 and math.min(t1, t2) or t1 or t2 if t then CastPosition = t==t1 and Vector(p1.x, 0, p1.y) or Vector(p2.x, 0, p2.y) break end tA = tB end else t = 0 CastPosition = Vector(Waypoints[1].x, 0, Waypoints[1].y) end if t then if (self:GetWaypointsLength(Waypoints) - t * unit.ms - radius) >= 0 then Waypoints = self:CutWaypoints(Waypoints, radius + t * unit.ms) Position = Vector(Waypoints[1].x, 0, Waypoints[1].y) else Position = CastPosition end elseif unit.type ~= myHero.type then CastPosition = Vector(Waypoints[#Waypoints].x, 0, Waypoints[#Waypoints].y) Position = CastPosition end elseif unit.type ~= myHero.type then CastPosition = Vector(Waypoints[#Waypoints].x, 0, Waypoints[#Waypoints].y) Position = CastPosition end if t and self:isSlowed(unit, 0, math.huge, from) and not self:isSlowed(unit, t, math.huge, from) and Position then CastPosition = Position end return Position, CastPosition end function VPrediction:MaxAngle(unit, currentwaypoint, from) local WPtable, n = self:GetWaypoints(unit.networkID, from) local Max = 0 local CV = (Vector(currentwaypoint.x, 0, currentwaypoint.y) - Vector(unit)) for i, waypoint in ipairs(WPtable) do local angle = Vector(0, 0, 0):angleBetween(CV, Vector(waypoint.waypoint.x, 0, waypoint.waypoint.y) - Vector(waypoint.unitpos.x, 0, waypoint.unitpos.y)) if angle > Max then Max = angle end end return Max end function VPrediction:WayPointAnalysis(unit, delay, radius, range, speed, from, spelltype) local Position, CastPosition, HitChance local SavedWayPoints = self.TargetsWaypoints[unit.networkID] and self.TargetsWaypoints[unit.networkID] or {} local CurrentWayPoints = self:GetCurrentWayPoints(unit) local VisibleSince = self.TargetsVisible[unit.networkID] and self.TargetsVisible[unit.networkID] or self:GetTime() HitChance = 1 Position, CastPosition = self:CalculateTargetPosition(unit, delay, radius, speed, from, spelltype) if self:CountWaypoints(unit.networkID, self:GetTime() - 0.1) >= 1 or self:CountWaypoints(unit.networkID, self:GetTime() - 1) == 1 then HitChance = 2 end local N = (_G.VPredictionMenu.Mode == _SLOW) and 3 or 2 local t1 = (_G.VPredictionMenu.Mode == _SLOW) and 1 or 0.5 if self:CountWaypoints(unit.networkID, self:GetTime() - 0.75) >= N then local angle = self:MaxAngle(unit, CurrentWayPoints[#CurrentWayPoints], self:GetTime() - t1) if angle > 90 then HitChance = 1 elseif angle < 30 and self:CountWaypoints(unit.networkID, self:GetTime() - 0.1) >= 1 then HitChance = 2 end end N = (_G.VPredictionMenu.Mode == _SLOW) and 2 or 1 if self:CountWaypoints(unit.networkID, self:GetTime() - N) == 0 then HitChance = 2 end if _G.VPredictionMenu.Mode == _FAST then HitChance = 2 end if #CurrentWayPoints <= 1 and self:GetTime() - VisibleSince > 1 then HitChance = 2 end if self:isSlowed(unit, delay, speed, from) then HitChance = 2 end if Position and CastPosition and ((radius / unit.ms >= delay + GetDistance(from, CastPosition)/speed) or (radius / unit.ms >= delay + GetDistance(from, Position)/speed)) then HitChance = 3 end --[[Angle too wide]] if Vector(from):angleBetween(Vector(unit), Vector(CastPosition)) > 60 then HitChance = 1 end if not Position or not CastPosition then HitChance = 0 CastPosition = Vector(CurrentWayPoints[#CurrentWayPoints].x, 0, CurrentWayPoints[#CurrentWayPoints].y) Position = CastPosition end if GetDistance(myHero, unit) < 250 then HitChance = 2 Position, CastPosition = self:CalculateTargetPosition(unit, delay*0.5, radius, speed*2, from, spelltype) Position = CastPosition end if #SavedWayPoints == 0 and (self:GetTime() - VisibleSince) > 3 then HitChance = 2 end if self.DontShootUntilNewWaypoints[unit.networkID] then HitChance = 0 CastPosition = Vector(unit.x, 0, unit.z) Position = CastPosition end return CastPosition, HitChance, Position end function VPrediction:GetBestCastPosition(unit, delay, radius, range, speed, from, collision, spelltype) assert(unit, "VPrediction: Target can't be nil") range = range and range - 4 or math.huge radius = radius == 0 and 1 or (radius + self:GetHitBox(unit)) - 4 speed = speed and speed or math.huge from = from and from or Vector(myHero) if from.networkID and from.networkID == myHero.networkID then from = Vector(myHero) end local IsFromMyHero = GetDistanceSqr(from, myHero) < 50*50 and true or false delay = delay + (0.07 + GetLatency() / 2000) local Position, CastPosition, HitChance = Vector(unit), Vector(unit), 0 local TargetDashing, CanHitDashing, DashPosition = self:IsDashing(unit, delay, radius, speed, from) local TargetImmobile, ImmobilePos, ImmobileCastPosition = self:IsImmobile(unit, delay, radius, speed, from, spelltype) local VisibleSince = self.TargetsVisible[unit.networkID] and self.TargetsVisible[unit.networkID] or self:GetTime() if unit.type ~= myHero.type then Position, CastPosition = self:CalculateTargetPosition(unit, delay, radius, speed, from, spelltype) HitChance = 2 else if self.DontShoot[unit.networkID] and self.DontShoot[unit.networkID] > self:GetTime() then Position, CastPosition = Vector(unit.x, unit.y, unit.z), Vector(unit.x, unit.y, unit.z) HitChance = 0 elseif TargetDashing then if CanHitDashing then HitChance = 5 else HitChance = 0 end Position, CastPosition = DashPosition, DashPosition elseif self.DontShoot2[unit.networkID] and self.DontShoot2[unit.networkID] > self:GetTime() then Position, CastPosition = Vector(unit.x, unit.y, unit.z), Vector(unit.x, unit.y, unit.z) HitChance = 7 elseif TargetImmobile then Position, CastPosition = ImmobilePos, ImmobileCastPosition HitChance = 4 elseif not self.DontUseWayPoints then CastPosition, HitChance, Position = self:WayPointAnalysis(unit, delay, radius, range, speed, from, spelltype) end end --[[Out of range]] if IsFromMyHero then if (spelltype == "line" and GetDistanceSqr(from, Position) >= range * range) then HitChance = 0 end if (spelltype == "circular" and (GetDistanceSqr(from, Position) >= (range + radius)^2)) then HitChance = 0 end if self.ShotAtMaxRange and HitChance ~= 0 and spelltype == "circular" and (GetDistanceSqr(from, CastPosition) > range ^ 2) then if GetDistanceSqr(from, Position) <= (range + radius / 1.4) ^ 2 then if GetDistanceSqr(from, Position) <= range * range then CastPosition = Position else CastPosition = Vector(from) + range * (Vector(Position) - Vector(from)):normalized() end end elseif (GetDistanceSqr(from, CastPosition) > range ^ 2) then HitChance = 0 end end radius = radius - self:GetHitBox(unit) + 4 if collision and HitChance > 0 then self.EnemyMinions.range = range + 500 * (delay + range/speed) self.JungleMinions.range = self.EnemyMinions.range self.OtherMinions.range = self.EnemyMinions.range self.EnemyMinions:update() self.JungleMinions:update() self.OtherMinions:update() if collision and _G.VPredictionMenu.Collision.UnitPos and self:CheckMinionCollision(unit, unit, delay, radius, range, speed, from) then HitChance = -1 elseif _G.VPredictionMenu.Collision.PredictPos and self:CheckMinionCollision(unit, Position, delay, radius, range, speed, from) then HitChance = -1 elseif _G.VPredictionMenu.Collision.CastPos and self:CheckMinionCollision(unit, CastPosition, delay, radius, range, speed, from) then HitChance = -1 end end return CastPosition, HitChance, Position end -------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- --Collision -------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- function VPrediction:GetPredictedHealth(unit, time, delay) local IncDamage = 0 local i = 1 local MaxDamage = 0 local count = 0 delay = delay and delay or 0.07 while i <= #self.ActiveAttacks do if self.ActiveAttacks[i].Attacker and not self.ActiveAttacks[i].Attacker.dead and self.ActiveAttacks[i].Target and self.ActiveAttacks[i].Target.networkID == unit.networkID then local hittime = self.ActiveAttacks[i].starttime + self.ActiveAttacks[i].windUpTime + (GetDistance(self.ActiveAttacks[i].pos, unit)) / self.ActiveAttacks[i].projectilespeed + delay if self:GetTime() < hittime - delay and hittime < self:GetTime() + time then IncDamage = IncDamage + self.ActiveAttacks[i].damage count = count + 1 if self.ActiveAttacks[i].damage > MaxDamage then MaxDamage = self.ActiveAttacks[i].damage end end end i = i + 1 end return unit.health - IncDamage, MaxDamage, count end function VPrediction:GetPredictedHealth2(unit, t) local damage = 0 local i = 1 while i <= #self.ActiveAttacks do local n = 0 if (self:GetTime() - 0.1) <= self.ActiveAttacks[i].starttime + self.ActiveAttacks[i].animationTime and self.ActiveAttacks[i].Target and self.ActiveAttacks[i].Target.valid and self.ActiveAttacks[i].Target.networkID == unit.networkID and self.ActiveAttacks[i].Attacker and self.ActiveAttacks[i].Attacker.valid and not self.ActiveAttacks[i].Attacker.dead then local FromT = self.ActiveAttacks[i].starttime local ToT = t + self:GetTime() while FromT < ToT do if FromT >= self:GetTime() and (FromT + (self.ActiveAttacks[i].windUpTime + GetDistance(unit, self.ActiveAttacks[i].pos) / self.ActiveAttacks[i].projectilespeed)) < ToT then n = n + 1 end FromT = FromT + self.ActiveAttacks[i].animationTime end end damage = damage + n * self.ActiveAttacks[i].damage i = i + 1 end return unit.health - damage end function VPrediction:CollisionProcessSpell(unit, spell) if unit and unit.valid and spell.target and unit.type ~= myHero.type and spell.target.type == 'obj_AI_Minion' and unit.team == myHero.team and spell and spell.name and (spell.name:lower():find("attack") or (spell.name == "frostarrow")) and spell.windUpTime and spell.target then if GetDistanceSqr(unit) < 4000000 then local time = self:GetTime() + spell.windUpTime + GetDistance(spell.target, unit) / self:GetProjectileSpeed(unit) - GetLatency()/2000 local i = 1 while i <= #self.ActiveAttacks do if (self.ActiveAttacks[i].Attacker and self.ActiveAttacks[i].Attacker.valid and self.ActiveAttacks[i].Attacker.networkID == unit.networkID) or ((self.ActiveAttacks[i].hittime + 3) < self:GetTime()) then table.remove(self.ActiveAttacks, i) else i = i + 1 end end table.insert(self.ActiveAttacks, {Attacker = unit, pos = Vector(unit), Target = spell.target, animationTime = spell.animationTime, damage = self:CalcDamageOfAttack(unit, spell.target, spell, 0), hittime=time, starttime = self:GetTime() - GetLatency()/2000, windUpTime = spell.windUpTime, projectilespeed = self:GetProjectileSpeed(unit)}) end end end function VPrediction:CheckCol(unit, minion, Position, delay, radius, range, speed, from, draw) if unit.networkID == minion.networkID then return false end --[[Check first if the minion is going to be dead when skillshots reaches his position]] if minion.type ~= myHero.type and _G.VPredictionMenu.Collision.CHealth and self:GetPredictedHealth(minion, delay + GetDistance(from, minion) / speed - GetLatency()/1000) < 0 then return false end local waypoints = self:GetCurrentWayPoints(minion) local MPos, CastPosition = #waypoints == 1 and Vector(minion) or self:CalculateTargetPosition(minion, delay, radius, speed, from, "line") if GetDistanceSqr(from, MPos) <= (range)^2 and GetDistanceSqr(from, minion) <= (range + 100)^2 then local buffer = (#waypoints > 1) and _G.VPredictionMenu.Collision.Buffer or 8 if minion.type == myHero.type then buffer = buffer + self:GetHitBox(minion) end if draw then DrawCircle3D(minion.x, myHero.y, minion.z, self:GetHitBox(minion) + buffer, 1, ARGB(255, 255, 255, 255)) DrawCircle3D(MPos.x, myHero.y, MPos.z, self:GetHitBox(minion) + buffer, 1, ARGB(255, 255, 255, 255)) self:DLine(MPos, minion, Color) end if #waypoints > 1 then local proj1, pointLine, isOnSegment = VectorPointProjectionOnLineSegment(from, Position, Vector(MPos)) if isOnSegment and (GetDistanceSqr(MPos, proj1) <= (self:GetHitBox(minion) + radius + buffer) ^ 2) then return true end end local proj2, pointLine, isOnSegment = VectorPointProjectionOnLineSegment(from, Position, Vector(minion)) if isOnSegment and (GetDistanceSqr(minion, proj2) <= (self:GetHitBox(minion) + radius + buffer) ^ 2) then return true end end return false end function VPrediction:CheckMinionCollision(unit, Position, delay, radius, range, speed, from, draw, updatemanagers) Position = Vector(Position) from = from and Vector(from) or myHero if updatemanagers then self.EnemyMinions.range = range + 500 * (delay + range / speed) self.JungleMinions.range = self.EnemyMinions.range self.OtherMinions.range = self.EnemyMinions.range self.EnemyMinions:update() self.JungleMinions:update() self.OtherMinions:update() end local result = false if _G.VPredictionMenu.Collision.Minions then for i, minion in ipairs(self.EnemyMinions.objects) do if self:CheckCol(unit, minion, Position, delay, radius, range, speed, from, draw) then if not draw then return true else result = true end end end end if _G.VPredictionMenu.Collision.Mobs then for i, minion in ipairs(self.JungleMinions.objects) do if self:CheckCol(unit, minion, Position, delay, radius, range, speed, from, draw) then if not draw then return true else result = true end end end end if _G.VPredictionMenu.Collision.Others then for i, minion in ipairs(self.OtherMinions.objects) do if minion.team ~= myHero.team and self:CheckCol(unit, minion, Position, delay, radius, range, speed, from, draw) then if not draw then return true else result = true end end end end if self.ChampionCollision then for i, enemy in ipairs(GetEnemyHeroes()) do if self:CheckCol(unit, enemy, Position, delay, radius, range, speed, from, draw) then if not draw then return true else result = true end end end end if draw then local Direction = Vector(Position - from):perpendicular():normalized() local Color = result and ARGB(255, 255, 0, 0) or ARGB(255, 0, 255, 0) local P1r = Vector(from) + radius * Vector(Direction) local P1l = Vector(from) - radius * Vector(Direction) local P2r = Vector(from) + radius * Direction - Vector(Direction):perpendicular() * GetDistance(from, Position) local P2l = Vector(from) - radius * Direction - Vector(Direction):perpendicular() * GetDistance(from, Position) self:DLine(P1r, P1l, Color) self:DLine(P1r, P2r, Color) self:DLine(P1l, P2l, Color) self:DLine(P2r, P2l, Color) if not result and IsKeyDown(string.byte("T")) then CastSpell(_Q, Position.x, Position.z) end end return false end function VPrediction:GetCircularCastPosition(unit, delay, radius, range, speed, from, collision) return self:GetBestCastPosition(unit, delay, radius, range, speed, from, collision, "circular") end function VPrediction:GetLineCastPosition(unit, delay, radius, range, speed, from, collision) return self:GetBestCastPosition(unit, delay, radius, range, speed, from, collision, "line") end function VPrediction:GetPredictedPos(unit, delay, speed, from, collision) return self:GetBestCastPosition(unit, delay, 1, math.huge, speed, from, collision, "circular") end --TODO: Recode this stuff and make it more readable :D function VPrediction:GetCircularAOECastPosition(unit, delay, radius, range, speed, from, collision) local CastPosition, HitChance, Position = self:GetBestCastPosition(unit, delay, radius, range, speed, from, collision, "circular") local points = {} local mainCastPosition, mainHitChance, mainPosition = CastPosition, HitChance, Position table.insert(points, Position) for i, target in ipairs(GetEnemyHeroes()) do if target.networkID ~= unit.networkID and ValidTarget(target, range * 1.5) then CastPosition, HitChance, Position = self:GetBestCastPosition(target, delay, radius, range, speed, from, collision, "circular") if GetDistance(from, Position) < (range + radius) and (Hitchance ~= -1 or not collision) then table.insert(points, Position) end end end while #points > 1 do local Mec = MEC(points) local Circle = Mec:Compute() if Circle.radius <= radius + self:GetHitBox(unit) - 8 then return Circle.center, mainHitChance, #points end local maxdist = -1 local maxdistindex = 0 for i=2, #points do local d = GetDistanceSqr(points[i], points[1]) if d > maxdist or maxdist == -1 then maxdistindex = i maxdist = d end end table.remove(points, maxdistindex) end return mainCastPosition, mainHitChance, #points, mainPosition end function VPrediction:GetLineAOECastPosition(unit, delay, radius, range, speed, from) local CastPosition, HitChance, Position = self:GetBestCastPosition(unit, delay, radius, range, speed, from, false, "line") local points = {} local Positions = {} local mainCastPosition, mainHitChance = CastPosition, HitChance table.insert(Positions, {unit = unit, HitChance = HitChance, Position = Position, CastPosition = CastPosition}) table.insert(points, Position) range = range and range - 4 or 20000 radius = radius == 0 and 1 or (radius + self:GetHitBox(unit)) - 4 from = from and Vector(from) or Vector(myHero) local function CircleCircleIntersection(C1, C2, R1, R2) local D = GetDistance(C1, C2) local A = (R1 * R1 - R2 * R2 + D * D ) / (2 * D) local H = math.sqrt(R1 * R1 - A * A); local Direction = (Vector(C2) - Vector(C1)):normalized() local PA = Vector(C1) + A * Direction local S1 = PA + H * Direction:perpendicular() local S2 = PA - H * Direction:perpendicular() return S1, S2 end local function GetPosiblePoints(from, pos, width, range) local middlepoint = (from + pos)/2 local P1, P2 = CircleCircleIntersection(from, middlepoint, width, GetDistance(middlepoint, from)) local V1 = (P1 - from) local V2 = (P2 - from) return from + range * (pos - V1 - from):normalized(), from + range * (pos - V2 - from):normalized() end local function CountHits(P1, P2, width, points) local hits = 0 local hitt = {} width = width + 2 for i, point in ipairs(points) do local pointSegment, pointLine, isOnSegment = VectorPointProjectionOnLineSegment(P1, P2, point) if isOnSegment and GetDistanceSqr(pointSegment, point) <= width * width then hits = hits + 1 table.insert(hitt, point) elseif i == 1 then return -1 end end return hits, hitt end for i, target in ipairs(GetEnemyHeroes()) do if target.networkID ~= unit.networkID and ValidTarget(target, range * 1.5) then CastPosition, HitChance, Position = self:GetBestCastPosition(target, delay, radius, range, speed, from, false, "line") if GetDistance(from, Position) < (range + radius) then table.insert(points, Position) table.insert(Positions, {unit = target, HitChance = HitChance, Position = Position, CastPosition = CastPosition}) end end end local MaxHit = 1 local MaxHitPos if #points > 1 then for i, candidate in ipairs(points) do local C1, C2 = GetPosiblePoints(from, points[i], radius - 20, range) local hits, MPoints1 = CountHits(from, C1, radius, points) local hits2, MPoints2 = CountHits(from, C2, radius, points) if hits >= MaxHit then MaxHitPos = C1 MaxHit = hits MaxHitPoints = MPoints1 end if hits2 >= MaxHit then MaxHitPos = C2 MaxHit = hits2 MaxHitPoints = MPoints2 end end end if MaxHit > 1 then --center the line local maxdist = -1 local p1 local p2 for i, hitp in ipairs(MaxHitPoints) do for o, hitp2 in ipairs(MaxHitPoints) do local StartP, EndP = Vector(from), (Vector(hitp) + Vector(hitp2)) / 2 local pointSegment, pointLine, isOnSegment = VectorPointProjectionOnLineSegment(StartP, EndP, hitp) local pointSegment2, pointLine2, isOnSegment2 = VectorPointProjectionOnLineSegment(StartP, EndP, hitp2) local dist = GetDistanceSqr(hitp, pointLine) + GetDistanceSqr(hitp2, pointLine2) if dist >= maxdist then maxdist = dist p1 = hitp p2 = hitp2 end end end if self.ReturnHitTable then for i = #Positions, 1, -1 do local pointSegment, pointLine, isOnSegment = VectorPointProjectionOnLineSegment(Vector(from), (p1 + p2) / 2, Positions[i].Position) if (not isOnSegment) or (GetDistanceSqr(pointLine, Positions[i].Position) > (radius + 5)^2) then table.remove(Positions, i) end end end return (p1 + p2) / 2, mainHitChance, MaxHit, Positions else return mainCastPosition, mainHitChance, 1, Positions end end function VPrediction:GetConeAOECastPosition(unit, delay, angle, range, speed, from) range = range and range - 4 or 20000 radius = 1 from = from and Vector(from) or Vector(myHero) angle = (angle < math.pi * 2) and angle or (angle * math.pi / 180) local CastPosition, HitChance, Position = self:GetBestCastPosition(unit, delay, radius, range, speed, from, false, "line") local points = {} local mainCastPosition, mainHitChance = CastPosition, HitChance table.insert(points, Vector(Position) - Vector(from)) local function CountVectorsBetween(V1, V2, points) local result = 0 local hitpoints = {} for i, test in ipairs(points) do local NVector = Vector(V1):crossP(test) local NVector2 = Vector(test):crossP(V2) if NVector.y >= 0 and NVector2.y >= 0 then result = result + 1 table.insert(hitpoints, test) elseif i == 1 then return -1 --doesnt hit the main target end end return result, hitpoints end local function CheckHit(position, angle, points) local direction = Vector(position):normalized() local v1 = Vector(position):rotated(0, -angle / 2, 0) local v2 = Vector(position):rotated(0, angle / 2, 0) return CountVectorsBetween(v1, v2, points) end for i, target in ipairs(GetEnemyHeroes()) do if target.networkID ~= unit.networkID and ValidTarget(target, range * 1.5) then CastPosition, HitChance, Position = self:GetBestCastPosition(target, delay, radius, range, speed, from, false, "line") if GetDistanceSqr(from, Position) < range * range then table.insert(points, Vector(Position) - Vector(from)) end end end local MaxHitPos local MaxHit = 1 local MaxHitPoints = {} if #points > 1 then for i, point in ipairs(points) do local pos1 = Vector(point):rotated(0, angle / 2, 0) local pos2 = Vector(point):rotated(0, - angle / 2, 0) local hits, points1 = CheckHit(pos1, angle, points) local hits2, points2 = CheckHit(pos2, angle, points) if hits >= MaxHit then MaxHitPos = C1 MaxHit = hits MaxHitPoints = points1 end if hits2 >= MaxHit then MaxHitPos = C2 MaxHit = hits2 MaxHitPoints = points2 end end end if MaxHit > 1 then --Center the cone local maxangle = -1 local p1 local p2 for i, hitp in ipairs(MaxHitPoints) do for o, hitp2 in ipairs(MaxHitPoints) do local cangle = Vector():angleBetween(hitp2, hitp) if cangle > maxangle then maxangle = cangle p1 = hitp p2 = hitp2 end end end return Vector(from) + range * (((p1 + p2) / 2)):normalized(), mainHitChance, MaxHit else return mainCastPosition, mainHitChance, 1 end end function VPrediction:OnTick() --[[Delete the old saved Waypoints]] if self.lastick == nil or self:GetTime() - self.lastick > 0.2 then self.lastick = self:GetTime() for NID, TargetWaypoints in pairs(self.TargetsWaypoints) do local i = 1 while i <= #self.TargetsWaypoints[NID] do if self.TargetsWaypoints[NID][i]["time"] + self.WaypointsTime < self:GetTime() then table.remove(self.TargetsWaypoints[NID], i) else i = i + 1 end end end for i, unit in ipairs(GetEnemyHeroes()) do for j = 1, unit.buffCount do local buff = unit:getBuff(j) if buff.valid and buff.name == "Stun" then if self.TargetsImmobile[unit.networkID] and self.TargetsImmobile[unit.networkID] < self:GetTime() then self.TargetsImmobile[unit.networkID] = self:GetTime() + (buff.endT-buff.startT) end end end end end end --[[Drawing functions for debug: ]] function VPrediction:DrawSavedWaypoints(object, time) local Waypoints = self:GetWaypoints(object.networkID, self:GetTime() - time) for i, waypoint in ipairs(Waypoints) do DrawCircle3D(waypoint.waypoint.x, myHero.y, waypoint.waypoint.y, 100, 2, ARGB(255, 255, 255, 255)) DrawText3D(tostring(i), waypoint.waypoint.x, myHero.y, waypoint.waypoint.y, 13, ARGB(255, 255, 255, 255), true) DrawCircle3D(waypoint.unitpos.x, myHero.y, waypoint.unitpos.y, 100, 2, ARGB(255, 255, 0, 0)) end end function VPrediction:DrawHitBox(object) DrawCircle3D(object.x, object.y, object.z, self:GetHitBox(object), 1, ARGB(255, 255, 255, 255)) if object then DrawCircle3D(object.x, object.y, object.z, self:GetHitBox(object), 1, ARGB(255, 0, 255, 0)) end end function VPrediction:DLine(From, To, Color) DrawLine3D(From.x, From.y, From.z, To.x, To.y, To.z, 1, Color) end function VPrediction:OnDraw() if self.showdevmode and _G.VPredictionMenu.Developers.Debug then LastGetTarget = LastGetTarget or myHero local target = GetTarget() or LastGetTarget LastGetTarget = target for i, enemy in ipairs(GetEnemyHeroes()) do self:DrawHitBox(enemy) end if _G.VPredictionMenu.Developers.SC then self.EnemyMinions:update() self.JungleMinions:update() self.OtherMinions:update() self:CheckMinionCollision(Vector(myHero) + 1050 * (Vector(mousePos) - Vector(myHero)):normalized(), 0.25, 70, 1050, 1800, myHero, true) end if target then self:DrawHitBox(target) local CastPosition, HitChance, Position = self:GetCircularCastPosition(target, 0.6, 70, 900, math.huge) if HitChance >= -1 then DrawText3D(tostring(HitChance), CastPosition.x, myHero.y, CastPosition.z, 40, ARGB(255, 255, 255, 255), true) DrawCircle3D(Position.x, myHero.y, Position.z, 70 + self:GetHitBox(target), 1, ARGB(255, 0, 255, 0)) DrawCircle3D(CastPosition.x, myHero.y, CastPosition.z, 70 + self:GetHitBox(target), 1, ARGB(255, 255, 0, 0)) end local waypoint = self:GetCurrentWayPoints(target) for i = 1, #waypoint-1 do self:DLine(Vector(waypoint[i].x, myHero.y, waypoint[i].y), Vector(waypoint[i+1].x, myHero.y, waypoint[i+1].y), ARGB(255,255,255,255)) end end end end function VPrediction:GetHitBox(object) if self.nohitboxmode and object.type and object.type == myHero.type then return 0 end return (self.hitboxes[object.charName] ~= nil and self.hitboxes[object.charName] ~= 0) and self.hitboxes[object.charName] or 65 end function VPrediction:GetProjectileSpeed(unit) return self.projectilespeeds[unit.charName] and self.projectilespeeds[unit.charName] or math.huge end function VPrediction:CalcDamageOfAttack(source, target, spell, additionalDamage) -- read initial armor and damage values local armorPenPercent = source.armorPenPercent local armorPen = source.armorPen local totalDamage = source.totalDamage + (additionalDamage or 0) local damageMultiplier = spell.name:find("CritAttack") and 2 or 1 -- minions give wrong values for armorPen and armorPenPercent if source.type == "obj_AI_Minion" then armorPenPercent = 1 elseif source.type == "obj_AI_Turret" then armorPenPercent = 0.7 end -- turrets ignore armor penetration and critical attacks if target.type == "obj_AI_Turret" then armorPenPercent = 1 armorPen = 0 damageMultiplier = 1 end -- calculate initial damage multiplier for negative and positive armor local targetArmor = (target.armor * armorPenPercent) - armorPen if targetArmor < 0 then -- minions can't go below 0 armor. --damageMultiplier = (2 - 100 / (100 - targetArmor)) * damageMultiplier damageMultiplier = 1 * damageMultiplier else damageMultiplier = 100 / (100 + targetArmor) * damageMultiplier end -- use ability power or ad based damage on turrets if source.type == myHero.type and target.type == "obj_AI_Turret" then totalDamage = math.max(source.totalDamage, source.damage + 0.4 * source.ap) end -- minions deal less damage to enemy heros if source.type == "obj_AI_Minion" and target.type == myHero.type and source.team ~= TEAM_NEUTRAL then damageMultiplier = 0.60 * damageMultiplier end -- heros deal less damage to turrets if source.type == myHero.type and target.type == "obj_AI_Turret" then damageMultiplier = 0.95 * damageMultiplier end -- minions deal less damage to turrets if source.type == "obj_AI_Minion" and target.type == "obj_AI_Turret" then damageMultiplier = 0.475 * damageMultiplier end -- siege minions and superminions take less damage from turrets if source.type == "obj_AI_Turret" and (target.charName == "Red_Minion_MechCannon" or target.charName == "Blue_Minion_MechCannon") then damageMultiplier = 0.8 * damageMultiplier end -- caster minions and basic minions take more damage from turrets if source.type == "obj_AI_Turret" and (target.charName == "Red_Minion_Wizard" or target.charName == "Blue_Minion_Wizard" or target.charName == "Red_Minion_Basic" or target.charName == "Blue_Minion_Basic") then damageMultiplier = (1 / 0.875) * damageMultiplier end -- turrets deal more damage to all units by default if source.type == "obj_AI_Turret" then damageMultiplier = 1.05 * damageMultiplier end -- calculate damage dealt return damageMultiplier * totalDamage end --}