Kain2030

Auto Carry Plugin - Lucian Edition - v1.1f

Aug 29th, 2013
7,359
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 39.96 KB | None | 0 0
  1. --[[
  2.  
  3.         Auto Carry Plugin - Lucian Edition
  4.         Author: Kain
  5.         Version: 1.1f
  6.         Copyright 2013
  7.  
  8.         Dependency: Sida's Auto Carry: Revamped
  9.  
  10.         How to install:
  11.             Make sure you already have AutoCarry installed.
  12.             Name the script EXACTLY "SidasAutoCarryPlugin - Lucian.lua" without the quotes.
  13.             Place the plugin in BoL/Scripts/Common folder.
  14.        
  15.         Version History:
  16.             Version: 1.1f: http://pastebin.com/Z3ipPQDE
  17.                 Fixed hero multishot bugs.
  18.             Version: 1.1e: http://pastebin.com/Z3ipPQDE
  19.                 Added Multi-shot.
  20.                 Added Smart Farm with Q.
  21.                 Added Mana Manager checks.
  22.                 Split menu into two menus.
  23.                 Fixed non-vip smart farming bug.
  24.             Version: 1.08c: http://pastebin.com/D5NwQUae
  25.                 Fixed Combo weaving.
  26.                 Added spell initiation if AA unavailable.
  27.                 Fixed auto attack before Q.
  28.                 Fixed Killsteal.
  29.                 Added Smart Cast angles to Q. Won't fire if probability of missing is too high.
  30.                 Added minimum range to shoot Ultimate to avoid complete misses.
  31.                 Fixed stand still and shoot range.
  32.                 Fixed a bug with R.
  33.                 Using SAC with "Enabled Jungle Clearing" enabled doesn't use R now.
  34.             Version: 1.07e: http://pastebin.com/kgFKdwuS
  35.                 Sword of the Divine supported.
  36.                 Improved dynamic draw ranges.
  37.                 Harass fixed. Fires Q.
  38.                 Hack fixed killsteal until BoL finally gets updated properly.
  39.                 Killsteal fix resolved firing spells without key pressed.
  40.             Version: 1.07c: http://pastebin.com/tK2WNXsy
  41.                 Relentless Pursuit Out of Enemy slows.
  42.                 Tweaked prediction variables.
  43.                 Killsteal enabled.
  44.             Version: 1.06c: http://pastebin.com/sdvmmNyR
  45.                 Spell weaving.
  46.                 Draw range logic improvement.
  47.                 Menu updates.
  48.             Version: 1.05d Beta: http://pastebin.com/rE5X8puE
  49.                 Improvements to mechanics of Culling Lockon. (Still more to do here.)
  50.                 Fix issue with Ultimate ending early.
  51.                 Miscellaneous bug fixes.
  52.             Version: 1.04 Beta Pre-Release: http://pastebin.com/ayEX5Bfq
  53.                 Culling Lockon added. Considered experimental, but seems to be working pretty well.
  54.             Version: 1.02 Beta Pre-Release: http://pastebin.com/tXxr95g9
  55.             Version: 1.0 Alpha: http://pastebin.com/xWbRz89K
  56. --]]
  57.  
  58. if myHero.charName ~= "Lucian" then return end
  59.  
  60. -- VIP_USER = false -- For testing only.
  61.  
  62. function PluginOnLoad()
  63.     Vars()
  64.     Menu()
  65.  
  66.     AutoCarry.SkillsCrosshair.range = QMaxRange
  67. end
  68.  
  69. function Vars()
  70.     tick = nil
  71.     Target = nil
  72.  
  73.     version = "1.1e"
  74.  
  75.     -- Confirm ranges on release.
  76.     QRange = 550
  77.     QMaxRange = 1100
  78.     WRange = 1000
  79.     ERange = 425
  80.     RRange = 1400
  81.  
  82.     QSpeed = 19.346
  83.     WSpeed = 1.47 -- Old: 1.009
  84.     ESpeed = 3.867
  85.     RSpeed = 2.9 -- Old: 1.3
  86.  
  87.     QWidth = 250
  88.     WWidth = 250
  89.     EWidth = 250
  90.     RWidth = 250
  91.  
  92.     QDelay = 405
  93.     WDelay = 288 -- Old: 256
  94.     EDelay = 1070
  95.     RDelay = 200
  96.  
  97.     RRefresh = 0.1
  98.     RDuration = 3.2 -- Old: 3.0 2.871 - 3.167
  99.  
  100.     ParticleRProjectileName = "Lucian_R_mis.troy"
  101.     ParticleRProjectileNameOld = "bowMaster_volley_mis.troy"
  102.     ParticleR = "Lucian_R_tar.troy"
  103.     ParticleRFiring = "Lucian_R_self.troy"
  104.  
  105.     -- Start New
  106.     BuffPassive = "lucianpassivebuff" -- Old: "Lightslinger"
  107.     BuffW = "lucianwcastingbuff"
  108.     BuffR = "LucianR"
  109.  
  110.     -- End New
  111. --[[
  112.     Raw data dump:
  113.  
  114.     spellName = LucianBasicAttack
  115.     projectileName = ???
  116.     castDelay = 4001.50 (827.00-7176.00)
  117.     projectileSpeed = 6321.08 (724.19-11917.96)
  118.     range = 2594.85 (541.70-4648.01)
  119.  
  120.     spellName = LucianW
  121.     projectileName = Lucian_W_mis.troy
  122.     castDelay = 288.67 (265.00-297.00)
  123.     projectileSpeed = 1484.95 (1391.22-1640.62)
  124.     range = 661.85 (304.68-1000.83)
  125.  
  126.     spellName = LucianE
  127.     projectileName = Lucian_W_mis.troy
  128.     castDelay = 8189.75 (0.00-32245.00)
  129.     projectileSpeed = 25590.51 (703.58-79656.61)
  130.     range = 3772.70 (372.90-8054.26)
  131.  
  132.     spellName = LucianR
  133.     projectileName = Lucian_R_mis.troy
  134.     castDelay = 210.50 (187.00-234.00)
  135.     projectileSpeed = 2850.25 (2342.64-3357.86)
  136.     range = 405.05 (261.91-548.18)
  137.  
  138.     Raw data dump #2:
  139.  
  140.     spellName = LucianW
  141.     projectileName = Lucian_W_mis.troy
  142.     castDelay = 313.81 (265.00-453.00)
  143.     projectileSpeed = 1459.60 (558.14-1797.76)
  144.     range = 648.24 (17.30-1007.14)
  145.  
  146.     spellName = LucianE
  147.     projectileName = Lucian_W_mis.troy
  148.     castDelay = 2147.83 (0.00-10530.00)
  149.     projectileSpeed = 4680.15 (632.65-14746.30)
  150.     range = 3349.24 (809.79-8272.67)
  151.  
  152.     spellName = LucianR
  153.     projectileName = Lucian_R_mis.troy
  154.     castDelay = 199.80 (172.00-218.00)
  155.     projectileSpeed = 3023.31 (2816.79-3321.66)
  156.     range = 757.80 (205.94-1063.38)
  157.  
  158. --]]
  159.  
  160.     SkillQ = {spellKey = _Q, range = QRange, speed = QSpeed, delay = QDelay, width = QWidth, configName = "piercinglight", displayName = "Q (Piercing Light)", enabled = true, skillShot = true, minions = false, reset = false, reqTarget = true }
  161.     SkillW = {spellKey = _W, range = WRange, speed = WSpeed, delay = WDelay, width = WWidth, configName = "ardentblaze", displayName = "W (Ardent Blaze)", enabled = true, skillShot = true, minions = false, reset = false, reqTarget = false }
  162.     SkillE = {spellKey = _E, range = ERange, speed = ESpeed, delay = EDelay, width = EWidth, configName = "relentlesspursuit", displayName = "E (Relentless Pursuit)", enabled = true, skillShot = true, minions = false, reset = false, reqTarget = false }
  163.     SkillR = {spellKey = _R, range = RRange, speed = RSpeed, delay = RDelay, width = RWidth, configName = "theculling", displayName = "R (The Culling)", enabled = true, skillShot = true, minions = false, reset = false, reqTarget = true }
  164.  
  165.     KeyQ = string.byte("Q")
  166.     KeyW = string.byte("W")
  167.     KeyE = string.byte("E")
  168.     KeyR = string.byte("R")
  169.  
  170.     KeyTest = string.byte("U")
  171.  
  172.     DFGSlot, HXGSlot, BWCSlot, STDSlot, SheenSlot, TrinitySlot, LichBaneSlot = nil, nil, nil, nil, nil, nil, nil
  173.     QReady, WReady, EReady, RReady, DFGReady, HXGReady, BWCReady, STDReady, IReady = false, false, false, false, false, false, false, false
  174.  
  175.     ultCastTick = 0
  176.     ultCastTarget = nil
  177.     ultVectorX = nil
  178.     ultVectorZ = nil
  179.  
  180.     isSlowed = false
  181.  
  182.     healthLastTick = 0
  183.     healthLastHealth = 0
  184.  
  185.     isUltFiring = false
  186.     lastUltMessage = 0
  187.  
  188.     comboActive = false
  189.     nextAttack = 0
  190.     lastSpell = 0
  191.  
  192.     -- Angles
  193.     angle_towards = 180
  194.     angle_away = 0
  195.     angle_parallel_towards = 90
  196.     angle_parallel_away = 270
  197.     angle_unknown = -1
  198.  
  199.     -- Collision
  200.     TYPE_ALL = 1
  201.     TYPE_HERO = 2
  202.     TYPE_MINION = 3
  203.  
  204.     lastText = 0
  205.  
  206.     debugMode = false
  207.     debugModeDisableNonR = false
  208. end
  209.  
  210. function Menu()
  211.     AutoCarry.PluginMenu:addParam("sep", "----- Lucian by Kain: v"..version.." -----", SCRIPT_PARAM_INFO, "")
  212.     AutoCarry.PluginMenu:addParam("sep", "----- [ Combo ] -----", SCRIPT_PARAM_INFO, "")
  213.     AutoCarry.PluginMenu:addParam("Combo", "Combo - Default Spacebar", SCRIPT_PARAM_INFO, "")
  214.     AutoCarry.PluginMenu:addParam("FullCombo", "Insta Blast Combo (No AA)", SCRIPT_PARAM_ONKEYDOWN, false, string.byte("Z"))
  215.     AutoCarry.PluginMenu:addParam("ComboQ", "Use Piercing Light", SCRIPT_PARAM_ONOFF, true)
  216.     AutoCarry.PluginMenu:addParam("ComboW", "Use Ardent Blaze", SCRIPT_PARAM_ONOFF, true)
  217.     AutoCarry.PluginMenu:addParam("ComboE", "Use Relentless Pursuit", SCRIPT_PARAM_ONOFF, true)
  218.     AutoCarry.PluginMenu:addParam("ComboR", "Use The Culling", SCRIPT_PARAM_ONOFF, true)
  219.     AutoCarry.PluginMenu:addParam("SmartE", "Smart Relentless Pursuit", SCRIPT_PARAM_ONOFF, true)
  220.     AutoCarry.PluginMenu:addParam("UltLockOn", "Use Ultimate Lock On (Beta)", SCRIPT_PARAM_ONOFF, true)
  221.     AutoCarry.PluginMenu:addParam("sep", "----- [ Misc ] -----", SCRIPT_PARAM_INFO, "")
  222.     AutoCarry.PluginMenu:addParam("PursuitSlow", "Pursuit Out of Slows", SCRIPT_PARAM_ONOFF, true)
  223.     AutoCarry.PluginMenu:addParam("AutoHarass", "Auto Harass", SCRIPT_PARAM_ONOFF, false)
  224.     AutoCarry.PluginMenu:addParam("sep", "----- [ Killsteal ] -----", SCRIPT_PARAM_INFO, "")
  225.     AutoCarry.PluginMenu:addParam("Killsteal", "Killsteal", SCRIPT_PARAM_ONOFF, true)
  226. --  AutoCarry.PluginMenu:addParam("KillstealUlt", "Killsteal with Ult", SCRIPT_PARAM_ONOFF, false)
  227.  
  228.     LucianExtraConfig = scriptConfig("Sida's Auto Carry: Lucian Extra", "Lucian")
  229.     LucianExtraConfig:addParam("sep", "----- [ Advanced ] -----", SCRIPT_PARAM_INFO, "")
  230.     LucianExtraConfig:addParam("EMinMouseDiff", "Pursuit Min. Mouse Diff.", SCRIPT_PARAM_SLICE, 600, 100, 1000, 0)
  231.     LucianExtraConfig:addParam("ProMode", "Use Auto QWER Keys", SCRIPT_PARAM_ONOFF, true)
  232.     LucianExtraConfig:addParam("MaxSpellAngle", "Max Spell Angle", SCRIPT_PARAM_SLICE, 35, 5, 90, 0)
  233.     LucianExtraConfig:addParam("UltClose", "Don't Ult Closer Than", SCRIPT_PARAM_SLICE, 150, 50, 800, 0)
  234.     LucianExtraConfig:addParam("ManaManager", "Mana Manager %", SCRIPT_PARAM_SLICE, 40, 0, 100, 2)
  235.     LucianExtraConfig:addParam("HealthPercentage", "Health Drop %", SCRIPT_PARAM_SLICE, 30, 0, 100, 0)
  236.     LucianExtraConfig:addParam("HealthTime", "Health Tracking Time", SCRIPT_PARAM_SLICE, 2, 2, 5, 0)
  237.     LucianExtraConfig:addParam("sep", "----- [ Performance ] -----", SCRIPT_PARAM_INFO, "")
  238. --  LucianExtraConfig:addParam("PerformanceRatio", "<-- Performance vs FPS -->", SCRIPT_PARAM_SLICE, 5, 1, 10, 0)
  239.     LucianExtraConfig:addParam("UseGoodAngles", "Use Good Shot Angles", SCRIPT_PARAM_ONOFF, true)
  240.     LucianExtraConfig:addParam("UseMultishot", "Use Multishot", SCRIPT_PARAM_ONOFF, true)
  241.     LucianExtraConfig:addParam("SmartFarmWithQ", "Smart Farm With Q", SCRIPT_PARAM_ONOFF, true)
  242.     LucianExtraConfig:addParam("sep", "----- [ Draw ] -----", SCRIPT_PARAM_INFO, "")
  243.     LucianExtraConfig:addParam("DisableDraw", "Disable Draw", SCRIPT_PARAM_ONOFF, false)
  244.     LucianExtraConfig:addParam("DrawFurthest", "Draw Furthest Spell Available", SCRIPT_PARAM_ONOFF, true)
  245.     LucianExtraConfig:addParam("DrawQ", "Draw Piercing Light", SCRIPT_PARAM_ONOFF, true)
  246.     LucianExtraConfig:addParam("DrawW", "Draw Ardent Blaze", SCRIPT_PARAM_ONOFF, true)
  247.     LucianExtraConfig:addParam("DrawE", "Draw Relentless Pursuit", SCRIPT_PARAM_ONOFF, true)
  248.     LucianExtraConfig:addParam("DrawR", "Draw The Culling", SCRIPT_PARAM_ONOFF, true)
  249. end
  250.  
  251. function PluginOnTick()
  252.     tick = GetTickCount()
  253.     Target = AutoCarry.GetAttackTarget(true)
  254.  
  255.     SpellCheck()
  256.  
  257.     -- tick % 5 == 0) and
  258.     if IsTickReady(25) and IsFiringUlt() then
  259.         CheckRPosition()
  260.     else
  261.         if AutoCarry.MainMenu.AutoCarry then
  262.             comboActive = true
  263.             Combo()
  264.         else
  265.             comboActive = false
  266.         end
  267.  
  268.         if AutoCarry.PluginMenu.FullCombo then
  269.             FullCombo()
  270.         end
  271.  
  272.         if AutoCarry.MainMenu.MixedMode or AutoCarry.PluginMenu.AutoHarass then
  273.             Harass()
  274.         end
  275.  
  276.         if AutoCarry.PluginMenu.Killsteal then
  277.             KillSteal()
  278.         end
  279.  
  280.         if (AutoCarry.MainMenu.LaneClear or AutoCarry.MainMenu.MixedMode) and LucianExtraConfig.SmartFarmWithQ and IsTickReady(70) and not IsMyManaLow()  then
  281.             SmartQFarm()
  282.         end
  283.     end
  284. end
  285.  
  286. function PluginOnCreateObj(obj)
  287.     -- Nothing to do here.
  288.     if obj.name == ParticleRFiring then
  289.         if debugMode then PrintChat("Ult Particle Started") end
  290.         isUltFiring = true
  291.         if debugMode then PrintChat("start: "..(tick / 1000)) end
  292.     end
  293. end
  294.  
  295. function PluginOnDeleteObj(obj)
  296.     if obj.name == ParticleRFiring then
  297.         if debugMode then PrintChat("Ult Particle Stopped") end
  298.         isUltFiring = false
  299.         UltFireStop()
  300.         if debugMode then PrintChat("stop: "..(tick / 1000)) end
  301.     end
  302. end
  303.  
  304. function OnAttacked()
  305.     -- AA > Q > AA
  306.     ComboWeave(true)
  307. end
  308.  
  309. --[[
  310. function CustomAttackEnemy(enemy)
  311.         if enemy.dead or not enemy.valid then return end
  312.         -- myHero:Attack(enemy)
  313.         -- AutoCarry.shotFired = true
  314. end
  315. --]]
  316.  
  317. function OnGainBuff(unit, buff)
  318.     if buff and buff.type ~= nil and unit.name == myHero.name and unit.team == myHero.team and (buff.type == 5 or buff.type == 10 or buff.type == 11) then
  319.         -- BUFF_STUN = 5 BUFF_SLOW = 10 BUFF_ROOT = 11
  320.         if AutoCarry.PluginMenu.PursuitSlow then
  321.             isSlowed = true
  322.             CastE()
  323.         end
  324.     end
  325. end
  326.  
  327. function SpellCheck()
  328.     DFGSlot, HXGSlot, BWCSlot, BRKSlot, STDSlot, SheenSlot, TrinitySlot, LichBaneSlot = GetInventorySlotItem(3128),
  329.     GetInventorySlotItem(3146), GetInventorySlotItem(3144), GetInventorySlotItem(3153), GetInventorySlotItem(3131),
  330.     GetInventorySlotItem(3057), GetInventorySlotItem(3078), GetInventorySlotItem(3100)
  331.  
  332.     QReady = (myHero:CanUseSpell(SkillQ.spellKey) == READY)
  333.     WReady = (myHero:CanUseSpell(SkillW.spellKey) == READY)
  334.     EReady = (myHero:CanUseSpell(SkillE.spellKey) == READY)
  335.     RReady = (myHero:CanUseSpell(SkillR.spellKey) == READY)
  336.  
  337.     DFGReady = (DFGSlot ~= nil and myHero:CanUseSpell(DFGSlot) == READY)
  338.     HXGReady = (HXGSlot ~= nil and myHero:CanUseSpell(HXGSlot) == READY)
  339.     BWCReady = (BWCSlot ~= nil and myHero:CanUseSpell(BWCSlot) == READY)
  340.     BRKReady = (BRKSlot ~= nil and myHero:CanUseSpell(BRKSlot) == READY)
  341.     STDReady = (STDSlot ~= nil and myHero:CanUseSpell(BRKSlot) == READY)
  342.  
  343.     IReady = (ignite ~= nil and myHero:CanUseSpell(ignite) == READY)
  344. end
  345.  
  346. -- Handle SBTW Skill Shots
  347.  
  348. function Combo()
  349.     if not Target then return end
  350.     ComboWeave()
  351. end
  352.  
  353. function ComboWeave(attacked)
  354.     if (AutoCarry.MainMenu.MixedMode or AutoCarry.PluginMenu.AutoHarass) and IsTickReady(60) then CastQ() end
  355.  
  356.     if AutoCarry.MainMenu.AutoCarry then
  357.         CastSlots()
  358.  
  359.         if not attacked and tick > (lastSpell + 3000) then
  360.             if not AutoCarry.PluginMenu.ComboW or (AutoCarry.PluginMenu.ComboW and not CastW()) then
  361.                 if AutoCarry.PluginMenu.ComboQ then CastQ() end
  362.             end
  363.         elseif comboActive then -- and tick > nextAttack then
  364.             nextAttack = AutoCarry.GetNextAttackTime()
  365.  
  366.             if AutoCarry.PluginMenu.ComboW then
  367.                 if CastW() then return end
  368.             end
  369.  
  370.             if AutoCarry.PluginMenu.ComboE then
  371.                 if CastE() then return end
  372.             end
  373.  
  374.             if AutoCarry.PluginMenu.ComboQ then
  375.                 if CastQ() then return end
  376.             end
  377.  
  378.             if AutoCarry.PluginMenu.ComboR and IsTickReady(50) then
  379.                 if CastR() then return end
  380.             end
  381.  
  382.             comboActive = false
  383.         end
  384.     end
  385. end
  386.  
  387. function FullCombo()
  388.     CastSlots()
  389.     CastW()
  390.     CastE()
  391.     CastQ()
  392.     CastR()
  393. end
  394.  
  395. function CastSlots()
  396.     if Target ~= nil then
  397.         if GetDistance(Target) <= QRange then
  398.             if DFGReady then CastSpell(DFGSlot, Target) end
  399.             if HXGReady then CastSpell(HXGSlot, Target) end
  400.             if BWCReady then CastSpell(BWCSlot, Target) end
  401.             if BRKReady then CastSpell(BRKSlot, Target) end
  402.             if STDReady then CastSpell(STDSlot, Target) end
  403.         end
  404.     end
  405. end
  406.  
  407. function Harass()
  408.     if IsTickReady(20) then CastQ() end
  409. end
  410.  
  411. function IsTickReady(tickFrequency)
  412.     -- Improves FPS
  413.     -- Disabled for now.
  414. --  local frequency = tickFrequency
  415. --  if LucianExtraConfig.PerformanceRatio > 0 then
  416. --      frequency = (LucianExtraConfig.PerformanceRatio + 1) * tickFrequency
  417. --  elseif LucianExtraConfig.PerformanceRatio < 0 then
  418. --      frequency = tickFrequency / (abs(LucianExtraConfig.PerformanceRatio) + 1)
  419. --  end
  420.    
  421.     -- if tick ~= nil and math.fmod(tick, (tickFrequency * LucianExtraConfig.PerformanceRatio)) == 0 then
  422.     if tick ~= nil and math.fmod(tick, tickFrequency) == 0 then
  423.         return true
  424.     else
  425.         return false
  426.     end
  427. end
  428.  
  429. function UpdateLastSpellTime()
  430.     lastSpell = tick
  431. end
  432.  
  433. function CastQ(enemy)
  434.     -- Q (Piercing Light)
  435.     if not enemy then enemy = Target end
  436.  
  437.     if enemy and not enemy.dead and QReady and ValidTarget(enemy, QMaxRange) then
  438.         local distance = GetDistance(enemy)
  439.         local range = QRange
  440.         if distance > QRange and LucianExtraConfig.UseMultishot then
  441.             range = QMaxRange
  442.         end
  443.  
  444.         local tpQ = VIP_USER and TargetPredictionVIP(range, SkillQ.speed*1000, 0, SkillQ.width) or TargetPrediction(range, SkillQ.speed, 0, SkillQ.width)
  445.  
  446.         local hitCount, hitEnemy = 0, nil
  447.         local angleDiff = nil
  448.         local predPos = nil
  449.  
  450.         if enemy.type == myHero.type then
  451.             if LucianExtraConfig.UseGoodAngles or LucianExtraConfig.UseMultishot then
  452.                 if tpQ then
  453.                     predPos = tpQ:GetPrediction(enemy)
  454.                 end
  455.             end
  456.  
  457.             -- Check angle of prediction.
  458.             if LucianExtraConfig.UseGoodAngles then
  459.                 local goodAngle = false
  460.                 if predPos then
  461.                     angleDiff = GetAngle(enemy, predPos)
  462.                     if angleDiff then
  463.                         goodAngle = IsGoodAngle(angleDiff, LucianExtraConfig.MaxSpellAngle)
  464.                     end
  465.                 end
  466.                
  467.                 if not angleDiff or not goodAngle then return false end
  468.             end
  469.        
  470.  
  471.             -- Find multishot possibilities.
  472.             if distance > QRange and LucianExtraConfig.UseMultishot then
  473.                 hitCount, hitEnemy = FindQMultishot(enemy, predPos, false)
  474.  
  475.                 if hitEnemy and hitCount > 0 then
  476.                     -- We have a winner.
  477.                 end
  478.             end
  479.         end
  480.  
  481.         -- if not angleDiff or (IsGoodAngle(angleDiff, LucianExtraConfig.MaxSpellAngle)) then
  482.         if hitCount > 0 and hitEnemy then
  483.             if debugMode then PrintChat("Q Mode: Multishot") end
  484.            
  485.             if lastText == 0 or (tick > lastText + 2000) then
  486.                 lastText = tick
  487.                 PrintFloatText(myHero, 20, "Multishot!")
  488.             end
  489.  
  490.             CastSpell(SkillQ.spellKey, hitEnemy)
  491.             UpdateLastSpellTime()
  492.             return true
  493.         else
  494.             if debugMode then PrintChat("Q Mode: normal") end
  495.             CastSpell(SkillQ.spellKey, enemy)
  496.             UpdateLastSpellTime()
  497.             return true
  498.         end
  499.     end
  500.  
  501.     return false
  502. end
  503.  
  504. function SmartQFarm()
  505.     if not QReady then return false end
  506.  
  507.     local minions = {}
  508.     for _, minion in pairs(AutoCarry.EnemyMinions().objects) do
  509.         if ValidTarget(minion) and GetDistance(minion) <= QRange then
  510.             if minion.health < getDmg("Q", minion, myHero) then
  511.                 table.insert(minions, minion)
  512.             end
  513.         end
  514.     end
  515.  
  516.     local hitCount, hitEnemy
  517.     for _, minion in pairs(minions) do
  518.         hitCount, hitEnemy = FindQMultishot(minion, minion, true)
  519.         if hitCount >= 2 then
  520.             local count = 0
  521.             for _, enemy in pairs(hitEnemy) do
  522.                 if enemy.health < getDmg("Q", enemy, myHero) then
  523.                     count = count + 1
  524.                 end
  525.             end
  526.  
  527.             if count >= 2 then
  528.                 CastQ(minion)
  529.                 break
  530.             end
  531.         end
  532.     end
  533. end
  534.  
  535. function FindQMultishot(enemy, predPos, multiple)
  536.     local hitCount = 0
  537.     local hitEnemy = nil
  538.  
  539.     if multiple then
  540.         hitEnemy = {}
  541.     end
  542.  
  543.     if not QReady or not enemy or enemy.dead or not predPos then return hitCount, hitEnemy end
  544.  
  545.     local m, minions = GetMinionCollision(SkillQ, QMaxRange, myHero, predPos)
  546.  
  547.     local h, heroes = false, nil
  548.  
  549.     if VIP_USER then
  550.         h, heroes = GetHeroCollision(SkillQ, QMaxRange, myHero, predPos)
  551.     end
  552.  
  553.     if not m and not h then return hitCount, hitEnemy end
  554.  
  555.     if m then
  556.         for index, minion in pairs(minions) do
  557.             hitCount = hitCount + 1
  558.             if GetDistance(minion) < SkillQ.range and (multiple or GetDistance(minion) > 150) then
  559.                 if multiple then
  560.                     table.insert(hitEnemy, minion)
  561.                 else
  562.                     hitEnemy = minion
  563.                 end
  564.             end
  565.         end
  566.     end
  567.  
  568.     if h then
  569.         for index, hero in pairs(heroes) do
  570.             hitCount = hitCount + 1
  571.             if GetDistance(hero) < SkillQ.range then
  572.                 if multiple then
  573.                     table.insert(hitEnemy, hero)
  574.                 else
  575.                     hitEnemy = hero
  576.                 end
  577.             end
  578.         end
  579.     end
  580.  
  581.     return hitCount, hitEnemy
  582. end
  583.  
  584. function GetHeroCollision(skill, altRange, source, destination)
  585.     if not altRange then altRange = skill.range end
  586.  
  587.     if VIP_USER then
  588.         local col = Collision(altRange, skill.speed*1000, skill.delay/1000, skill.width)
  589.  
  590.         if col then
  591.             local ret, heroes = col:GetHeroCollision(source, destination, 2) -- 2 = HERO_ENEMY
  592.             return ret, heroes
  593.         else
  594.             return false, nil
  595.         end
  596.     else
  597.         return false, nil
  598.     end
  599. end
  600.  
  601. function GetMinionCollision(skill, altRange, source, destination)
  602.     if not altRange then altRange = skill.range end
  603.  
  604.     if VIP_USER then
  605.         local col = Collision(altRange, skill.speed*1000, skill.delay/1000, skill.width)
  606.  
  607.         if col then
  608.             local ret, minions = col:GetMinionCollision(source, destination)
  609.             return ret, minions
  610.         else
  611.             return false, nil
  612.         end
  613.     else
  614.         local minion = GetNonVIPMinionCollision(destination, skill.width)
  615.         if minion then
  616.             return true, minion
  617.         else
  618.             return false, nil
  619.         end
  620.     end
  621. end
  622.  
  623. function GetNonVIPMinionCollision(predic, width)
  624.     local minions = {}
  625.     for _, minion in pairs(AutoCarry.EnemyMinions().objects) do
  626.         if minion ~= nil and minion.valid and string.find(minion.name,"Minion_") == 1 and minion.team ~= player.team and minion.dead == false then
  627.             if predic ~= nil and predic.x ~= nil and predic.z ~= nil then
  628.                 ex = player.x
  629.                 ez = player.z
  630.                 tx = predic.x
  631.                 tz = predic.z
  632.  
  633.                 if ex ~= nil and ez ~= nil and tx ~= nil and tz ~= nil then
  634.                     dx = ex - tx
  635.                     dz = ez - tz
  636.                     if dx ~= 0 then
  637.                         m = dz/dx
  638.                         c = ez - m*ex
  639.                     end
  640.                     mx = minion.x
  641.                     mz = minion.z
  642.                     distanc = (math.abs(mz - m*mx - c))/(math.sqrt(m*m+1))
  643.                     if distanc < width and math.sqrt((tx - ex)*(tx - ex) + (tz - ez)*(tz - ez)) > math.sqrt((tx - mx)*(tx - mx) + (tz - mz)*(tz - mz)) then
  644.                         table.insert(minions, minion)
  645.                     end
  646.                 end
  647.             end
  648.         end
  649.     end
  650.  
  651.     return minions
  652. end
  653.  
  654. function CastW(enemy)
  655.     -- W (Ardent Blaze)
  656.     if not enemy then enemy = Target end
  657.  
  658.     if enemy and not enemy.dead and WReady and ValidTarget(enemy, WRange) then
  659.         if debugMode then PrintChat("Cast W") end
  660.         AutoCarry.CastSkillshot(SkillW, enemy)
  661.         UpdateLastSpellTime()
  662.         return true
  663.     end
  664.  
  665.     return false
  666. end
  667.  
  668. --[[
  669. function CastEOld()
  670.     -- E (Relentless Pursuit)
  671.     if debugMode then
  672.         -- PrintChat("Mouse Distance: "..GetDistance(mousePos))
  673.     end
  674.  
  675.     if EReady then
  676.         -- if ( math.abs(mousePos.x - myHero.x) > PursuitMinMouseDiff or math.abs(mousePos.z - myHero.z) > PursuitMinMouseDiff) then
  677.         if ((GetDistance(mousePos) > PursuitMinMouseDiff) and isEnemyInRange(SkillE.range + SkillR.range)) then
  678.             if debugMode then PrintChat("Cast E") end
  679.             CastSpell(SkillE.spellKey, mousePos.x, mousePos.z)
  680.         end
  681.     end
  682. end
  683. --]]
  684.  
  685. function CastE()
  686.     if EReady then
  687.         if AutoCarry.PluginMenu.SmartE then
  688.             if ((GetDistance(mousePos) > LucianExtraConfig.EMinMouseDiff or isSlowed) and isEnemyInRange(SkillE.range + SkillR.range)) then
  689.                 local dashSqr = math.sqrt((mousePos.x - myHero.x)^2+(mousePos.z - myHero.z)^2)
  690.                 local dashX = myHero.x + ERange*((mousePos.x - myHero.x)/dashSqr)
  691.                 local dashZ = myHero.z + ERange*((mousePos.z - myHero.z)/dashSqr)
  692.                 CastSpell(SkillE.spellKey, dashX, dashZ)
  693.                 UpdateLastSpellTime()
  694.                 isSlowed = false
  695.                 return true
  696.             end
  697.         else
  698.             CastSpell(SkillE.spellKey, mousePos.x, mousePos.z)
  699.             UpdateLastSpellTime()
  700.             isSlowed = false
  701.             return true
  702.         end
  703.     end
  704.  
  705.     return false
  706. end
  707.  
  708. function CastR(enemy)
  709.     if not enemy then enemy = Target end
  710.  
  711.     -- R (The Culling)
  712.     if enemy and not enemy.dead and RReady and ValidTarget(enemy, RRange) and enemy.type == myHero.type then
  713.         if GetDistance(enemy) < LucianExtraConfig.UltClose then return false end
  714.  
  715.         if not IsFiringUlt() then
  716.             if debugMode then PrintChat("Cast R") end
  717.             if not isUltFiring then
  718.                 AutoCarry.CastSkillshot(SkillR, enemy)
  719.                 UpdateLastSpellTime()
  720.                 if AutoCarry.PluginMenu.UltLockOn and tick > (lastUltMessage + 2000) then
  721.                     lastUltMessage = tick
  722.                     PrintFloatText(myHero, 10, "Ultimate Locked On!")
  723.                 end
  724.             end
  725.  
  726.             ultCastTarget = enemy
  727.             ultCastTick = tick
  728.  
  729.             -- Vector from target -> myHero
  730.             if ultVectorX == nil and ultVectorZ == nil then
  731.                 if debugMode and false then PrintChat("update x,z") end
  732.                 ultVectorX,y,ultVectorZ = (Vector(myHero) - Vector(ultCastTarget)):normalized():unpack()
  733.             end
  734.         end
  735.  
  736.         CheckRPosition()
  737.     end
  738. end
  739.  
  740. function CheckRPosition()
  741.     if (ultCastTick > 0) then
  742.         if debugMode and IsFiringUlt() then burp = "true" else burp = "false" end
  743.         if debugMode and false then PrintChat("Tick: "..tick..", ultCastTick: "..ultCastTick..", RDuration: "..(ultCastTick + (RDuration * 1000))..", IsFiringUlt: "..burp) end
  744.     end
  745.  
  746.     if AutoCarry.PluginMenu.UltLockOn and IsFiringUlt() then
  747.         MoveMyHeroToRPosition()
  748.     end
  749. end
  750.  
  751. function MoveMyHeroToRPosition()
  752.     -- Please don't steal this function!
  753.     local tpR = VIP_USER and TargetPredictionVIP(SkillR.range, SkillR.speed*1000, RRefresh, SkillR.width) or TargetPrediction(SkillR.range, SkillR.speed, RRefresh*1000, SkillR.width)
  754.  
  755.     local target = nil
  756.     if ultCastTarget ~= nil then
  757.         target = ultCastTarget
  758.     else
  759.         target = Target
  760.     end
  761.  
  762.     local predR = tpR:GetPrediction(target)
  763.  
  764.     if not predR then return end
  765.  
  766.     local RRangeBuffered = RRange * .98 -- Allow a bit of slippage for targets running away.
  767.     local posX = predR.x + (ultVectorX * RRangeBuffered)
  768.     local posZ = predR.z + (ultVectorZ * RRangeBuffered)
  769.  
  770.     -- Thank you, Pythagoras
  771.     -- local distanceBetweenPoints = math.sqrt((predR.x - posX)^2 + (predR.z - posZ)^2)
  772.     -- local distanceBetweenPoints = GetDistance(Point(posX, posZ), predR)
  773.     -- local posXRanged = (posX + (posX - predR.x)) / distanceBetweenPoints * RRangeBuffered
  774.     -- local posZRanged = (posZ + (posZ - predR.z)) / distanceBetweenPoints * RRangeBuffered
  775.  
  776.     local predRPath = LineSegment(Point(predR.x, predR.z), Point(posX, posZ))
  777.  
  778.     local closePoint = nil
  779.     if predRPath ~= nil then
  780.         closePoint = Point(myHero.x, myHero.z):closestPoint(predRPath)
  781.     else
  782.         if debugMode then PrintChat("predRPath is nil") end
  783.     end
  784.  
  785.     if debugMode and closePoint ~= nil then
  786.         --  PrintChat("moveto: "..posX..", "..posZ.."... targetat: "..ultCastTarget.x..", "..ultCastTarget.z..", ultVectorX: "..ultVectorX..", ultVectorZ: "..ultVectorZ..", RDuration: "..RDuration)
  787.         --  PrintChat("posXRanged: "..posXRanged..", posZRanged: "..posZRanged..", closePoint: "..closePoint.x..", "..closePoint.y)
  788.         PrintChat("moveto: "..closePoint.x..", "..closePoint.y.."; targetat: "..predR.x..", "..predR.z..", ultVectorX: "..ultVectorX..", ultVectorZ: "..ultVectorZ)
  789.     end
  790.  
  791.     if debugMode then
  792.         PrintChat("distance: method 1: "..GetDistance(closePoint, predR)..", method 2: "..GetDistance(Point(posX, posZ), predR))
  793.     end
  794.  
  795.     if predRPath ~= nil and closePoint ~= nil and not IsWall(D3DXVECTOR3(closePoint.x, myHero.y, closePoint.y)) and GetDistance(closePoint, predR) > ERange then
  796.         -- Closest Point Method
  797.         if debugMode then PrintChat("Move: Method 1") end
  798.         myHero:MoveTo(closePoint.x, closePoint.y)
  799.     elseif predR ~= nil and posX ~= nil and posZ ~= nil and not IsWall(D3DXVECTOR3(posX, myHero.y, posZ))
  800.         -- and GetDistance(Point(posX, posZ), predR) > 500
  801.         and GetDistance(Point(posX, posZ), predR) < RRange and GetDistance(Point(posX, posZ), predR) > 100 then
  802.         -- Full Vector Method
  803.         if debugMode then PrintChat("Move: Method 2") end
  804.         if (tick > (lastUltMessage + 2000)) then
  805.             -- lastUltMessage = tick
  806.             -- PrintFloatText(myHero, 10, "Ultimate Manual Mode!")
  807.         end
  808.         myHero:MoveTo(posX, posZ)
  809. --  elseif not IsWall(D3DXVECTOR3(posXRanged, myHero.y, posZRanged)) then
  810. --      -- Last Ditch Method
  811. --      if debugMode then PrintChat("Move: Method 3") end
  812. --      myHero:MoveTo(posXRanged, posZRanged)
  813.     else
  814.         -- Fallback to User Aiming
  815.         if debugMode then PrintChat("Move: Wall") end
  816.         myHero:MoveTo(mousePos.x, mousePos.z)
  817.     end
  818.     -- myHero:MoveTo(posXRanged, posZRanged)
  819. end
  820.  
  821. function getDistanceBetweenPoints(pointA, pointB)
  822.     -- Thank you, Pythagoras
  823.     local distanceBetweenPoints = math.sqrt((predR.x - posX)^2 + (predR.z - posZ)^2)
  824. end
  825.  
  826. function IsFiringUlt()
  827.     local tickCount = tick
  828.  
  829.     -- if (ultCastTick > 0) and (tickCount >= ultCastTick) and (tickCount <= (ultCastTick + (RDuration * 1000))) and not RReady and ultCastTarget ~= nil and not ultCastTarget.dead then
  830.     if (ultCastTick > 0) and (tickCount >= ultCastTick) and isUltFiring and ultCastTarget ~= nil and not ultCastTarget.dead then
  831.         AutoCarry.CanMove = false
  832.         return true
  833.     else
  834.         -- UltFireStop()
  835.         return false
  836.     end
  837. end
  838.  
  839. function UltFireStop()
  840.     ultCastTick = 0
  841.     ultVectorX = nil
  842.     ultVectorZ = nil
  843.     AutoCarry.CanMove = true
  844. end
  845.  
  846. function isEnemyInRange(range)
  847.     for _, enemy in pairs(AutoCarry.EnemyTable) do
  848.         if ValidTarget(enemy, range) and not enemy.dead then
  849.             return true
  850.         end
  851.     end
  852.  
  853.     return false
  854. end
  855.  
  856. --[[
  857. function TakingRapidDamage()
  858.     if (tick - healthLastTick) > (LucianExtraConfig.HealthTime * 1000) then
  859.         -- Check amount of health lost
  860.         -- PrintChat((myHero.health - healthLastHealth)..", "..(myHero.maxHealth * (LucianExtraConfig.HealthPercentage / 100))..", "..((tick - healthLastTick) / 1000))
  861.         if healthLastTick ~= 0 and (myHero.health - healthLastHealth) > (myHero.maxHealth * (LucianExtraConfig.HealthPercentage / 100)) then
  862.             -- PrintChat("true")
  863.             return true
  864.         else
  865.             -- Reset counters
  866.             healthLastTick = tick
  867.             healthLastHealth = myHero.health
  868.         end
  869.     end
  870.  
  871.     return false
  872. end
  873. --]]
  874.  
  875. function KillSteal()
  876.     -- Will try to perform a killsteam using any spell.
  877.     if not AutoCarry.PluginMenu.Killsteal then return end
  878.  
  879.     -- Killsteal disabled until Bol update for Lucian
  880.  
  881.     for _, enemy in pairs(AutoCarry.EnemyTable) do
  882.         if enemy and not enemy.dead then
  883.             -- getDmg broken in BoL for Lucian right now.
  884.             local qDmg = GetDamage(enemy, _Q) -- getDmg("Q", enemy, myHero)
  885.             local wDmg = GetDamage(enemy, _W) -- getDmg("W", enemy, myHero)
  886.             -- local rDmg = 50 -- getDmg("R", enemy, myHero)
  887.  
  888.             if QReady and ValidTarget(enemy, QRange) and enemy.health < qDmg then
  889.                 if debugMode then PrintChat("Cast Q KS") end
  890.                 CastQ(enemy)
  891.             elseif WReady and ValidTarget(enemy, WRange) and enemy.health < wDmg then
  892.                 if debugMode then PrintChat("Cast W KS") end
  893.                 CastW(enemy)
  894.             elseif QReady and WReady and ValidTarget(enemy, QRange) and ValidTarget(enemy, WRange) and enemy.health < (qDmg + wDmg) then
  895.                 if debugMode then PrintChat("Cast Q + W KS") end
  896.                 CastW(enemy)
  897.                 if not enemy.dead then
  898.                     CastQ(enemy)
  899.                 end
  900.             -- Ultimate is not a viable killsteal since the number of individual shots to hit can not be pre-determined.
  901.             -- elseif AutoCarry.PluginMenu.KillstealUlt and RReady and ValidTarget(enemy, RRange) and (enemy.health + 20) < rDmg then
  902.             --  if debugMode then PrintChat("Cast R KS") end
  903.             --  CastR(enemy)
  904.             end
  905.  
  906.         end
  907.     end
  908. end
  909.  
  910. function GetDamage(enemy, spell)
  911.     if spell == _Q then
  912.         return myHero:CalcDamage(enemy, ((40*(myHero:GetSpellData(_Q).level-1) + 80) + (((.15 * (myHero:GetSpellData(_Q).level-1)) + .60) * myHero.addDamage)))
  913.     elseif spell == _W then
  914.         return myHero:CalcMagicDamage(enemy, ((40*(myHero:GetSpellData(_Q).level-1) + 60) + (.90 * myHero.ap) + (.60 * myHero.addDamage)))
  915.     end
  916. end
  917.  
  918. function PluginOnWndMsg(msg,key)
  919.     Target = AutoCarry.GetAttackTarget()
  920.     if Target ~= nil and LucianExtraConfig.ProMode then
  921.         -- if msg == KEY_DOWN and key == KeyQ then CastQ() end
  922.         if msg == KEY_DOWN and key == KeyW then CastW() end
  923.         if msg == KEY_DOWN and key == KeyE then CastE() end
  924.         if msg == KEY_DOWN and key == KeyR then CastR() end
  925.         if msg == KEY_DOWN and key == KeyTest and debugMode then
  926.             if ultVectorX == nil and ultVectorZ == nil then
  927.                 ultCastTarget = Target
  928.                 ultVectorX,y,ultVectorZ = (Vector(myHero) - Vector(ultCastTarget)):normalized():unpack()
  929.             end
  930.             MoveMyHeroToRPosition()
  931.         end
  932.        
  933.         if msg == KEY_UP and key == KeyTest and debugMode then
  934.             ultVectorX = nil
  935.             ultVectorZ = nil
  936.         end
  937.     end
  938. end
  939.  
  940. -- Draw
  941. function PluginOnDraw()
  942.     -- if Target ~= nil and not Target.dead and QReady and ValidTarget(Target, QMaxRange) then
  943.     if Target ~= nil and not Target.dead and (AutoCarry.MainMenu.AutoCarry or AutoCarry.MainMenu.MixedMode) then
  944.         DrawArrowsToPos(myHero, Target)
  945.     end
  946.  
  947.     if not LucianExtraConfig.DisableDraw and not myHero.dead then
  948.         local farSpell = FindFurthestReadySpell()
  949.         -- if debugMode and farSpell then PrintChat("far: "..farSpell.configName) end
  950.  
  951.         -- Not needed as SAC has the same range draw.
  952.         -- DrawCircle(myHero.x, myHero.y, myHero.z, getTrueRange(), 0x808080) -- Gray
  953.  
  954.         if LucianExtraConfig.DrawQ and QReady and ((LucianExtraConfig.DrawFurthest and farSpell and farSpell == SkillQ) or not LucianExtraConfig.DrawFurthest) then
  955.             DrawCircle(myHero.x, myHero.y, myHero.z, QRange, 0x0099CC) -- Blue
  956.         end
  957.  
  958.         if LucianExtraConfig.DrawW and WReady and ((LucianExtraConfig.DrawFurthest and farSpell and farSpell == SkillW) or not LucianExtraConfig.DrawFurthest) then
  959.             DrawCircle(myHero.x, myHero.y, myHero.z, WRange, 0xFFFF00) -- Yellow
  960.         end
  961.        
  962.         if LucianExtraConfig.DrawE and EReady and ((LucianExtraConfig.DrawFurthest and farSpell and farSpell == SkillE) or not LucianExtraConfig.DrawFurthest) then
  963.             DrawCircle(myHero.x, myHero.y, myHero.z, ERange, 0x00FF00) -- Green
  964.         end
  965.  
  966.         if LucianExtraConfig.DrawR and RReady and ((LucianExtraConfig.DrawFurthest and farSpell and farSpell == SkillR) or not LucianExtraConfig.DrawFurthest) then
  967.             DrawCircle(myHero.x, myHero.y, myHero.z, RRange, 0xFF0000) -- Red
  968.         end
  969.  
  970.         Target = AutoCarry.GetAttackTarget()
  971.         if Target ~= nil then
  972.             for j=0, 10 do
  973.                 DrawCircle(Target.x, Target.y, Target.z, 40 + j*1.5, 0x00FF00) -- Green
  974.             end
  975.         end
  976.     end
  977. end
  978.  
  979. function FindFurthestReadySpell()
  980.     local farSpell = nil
  981.  
  982.     if LucianExtraConfig.DrawQ and QReady then farSpell = SkillQ end
  983.     if LucianExtraConfig.DrawW and WReady and (not farSpell or WRange > farSpell.range) then farSpell = SkillW end
  984.     if LucianExtraConfig.DrawE and EReady and (not farSpell or ERange > farSpell.range) then farSpell = SkillE end
  985.     if LucianExtraConfig.DrawR and RReady and (not farSpell or RRange > farSpell.range) then farSpell = SkillR end
  986.  
  987.     return farSpell
  988. end
  989.  
  990. function getTrueRange()
  991.     return myHero.range + GetDistance(myHero.minBBox)
  992. end
  993.  
  994. function DrawArrowsToPos(pos1, pos2)
  995.     if pos1 and pos2 then
  996.         startVector = D3DXVECTOR3(pos1.x, pos1.y, pos1.z)
  997.         endVector = D3DXVECTOR3(pos2.x, pos2.y, pos2.z)
  998.         -- directionVector = (endVector-startVector):normalized()
  999.         DrawArrows(startVector, endVector, 60, 0xE97FA5, 100)
  1000.     end
  1001. end
  1002.  
  1003. --[[
  1004. function test1(skill, enemy)
  1005.     local tp = VIP_USER and TargetPredictionVIP(8000, skill.speed*1000, 0, SkillR.width) or TargetPrediction(skill.range, skill.speed, 0, skill.width)
  1006.     -- local tp = TargetPredictionVIP(8000, math.huge, skill.delay, SkillR.width)
  1007.     --local tp = TargetPredictionVIP(8000, math.huge, 0.535, 75)
  1008.     GetEnemyPrediction(enemy, tp)
  1009. end
  1010. --]]
  1011.  
  1012. function GetEnemyPrediction(enemy, tp)
  1013.     -- local tpQ = VIP_USER and TargetPredictionVIP(SkillQ.range, SkillQ.speed*1000, SkillQ.delay, SkillR.width) or TargetPrediction(SkillQ.range, SkillQ.speed, SkillQ.delay*1000, SkillQ.width)
  1014.  
  1015.     if not enemy or enemy.dead or not tp or not QReady then return nil end
  1016.  
  1017.     -- local predPos, p2, p3 = tp:GetPrediction(enemy)
  1018.     local predPos = tp:GetPrediction(enemy)
  1019.    
  1020.     if not predPos then return nil end
  1021.  
  1022.     GetAngle(enemy, predPos)
  1023. end
  1024.  
  1025. -- Angle Functions
  1026. function IsGoodAngle(angleDiff, variance)
  1027.     local direction = Directionality(angleDiff, variance)
  1028.    
  1029.     if direction == angle_towards or direction == angle_away then
  1030.         return true
  1031.     else
  1032.         return false
  1033.     end
  1034. end
  1035.  
  1036. function GetAngle(enemy, predPos)
  1037.     -- ultVectorX,y,ultVectorZ = (Vector(myHero) - Vector(ultCastTarget)):normalized():unpack()
  1038.  
  1039.         -- v1 = Vector(predPos.x - myHero.x, predPos.z - myHero.z):normalized()
  1040.     -- v2 = Vector((Vector(predPos) - Vector(enemy)):normalized())
  1041.         -- v2 = Vector(predPos.x - enemy.x, predPos.z - enemy.z):normalized()
  1042.     -- v2 = Vector(coneTargetsTable[j].x-player.x , coneTargetsTable[j].z-player.z)
  1043.  
  1044.     v1 = (Vector(predPos) - Vector(myHero)):normalized()
  1045.  
  1046.     if predPos.x == enemy.x and predPos.z == enemy.z then
  1047.         -- Enemy is standing still.
  1048.         return false
  1049.     end
  1050.    
  1051.  
  1052.     v2 = (Vector(predPos) - Vector(enemy)):normalized()
  1053. -- PrintChat("a"..predPos.x.."!"..enemy.x.."!"..v2.x.."!"..v2.z)
  1054. --  if not v2 or v2 == -1 then
  1055. --      return false
  1056. --  end
  1057.     -- shootTheta = sign(v1.z)*90-math.deg(math.atan2(v1.z, v1.x))
  1058.     -- enemyTheta = sign(v2.z)*90-math.deg(math.atan2(v2.z, v2.x))
  1059.     -- angle = enemyTheta-shootTheta
  1060.  
  1061.     shootTheta = math.deg(math.atan2(v1.z, v1.x))
  1062.     enemyTheta = math.deg(math.atan2(v2.z, v2.x))
  1063.  
  1064.     if shootTheta < 0 then
  1065.         shootTheta = shootTheta + 360  
  1066.     end
  1067.  
  1068.     if enemyTheta < 0 then
  1069.         enemyTheta = enemyTheta + 360
  1070.     end
  1071.  
  1072.     angleDiff = math.abs(enemyTheta - shootTheta)
  1073.  
  1074.     local angleView = ""
  1075.     local angleVariance = 30
  1076.  
  1077.     angleView = Directionality(angleDiff, LucianExtraConfig.MaxSpellAngle)
  1078.    
  1079.     if angleView ~= nil then
  1080.         -- PrintChat("v1: "..shootTheta..", v2: "..enemyTheta..", angle: "..angle..", angleView: "..angleView..", predx: "..predPos.x..", predz: "..predPos.z..", hittime: "..p2..", posx: "..p3.x..", posz: "..p3.z)
  1081.         -- PrintChat("v1: "..shootTheta..", v2: "..enemyTheta..", angleDiff: "..angleDiff..", angleView: "..angleView..", predx: "..predPos.x..", predz: "..predPos.z)
  1082.     end
  1083.  
  1084.     return angleDiff
  1085. end
  1086.  
  1087. function Directionality(angleDiff, variance)
  1088.     if betweenRounded(angleDiff, variance, angle_away) then
  1089.         return angle_away
  1090.     elseif betweenRounded(angleDiff, variance, angle_towards) then
  1091.         return angle_towards
  1092.     elseif betweenRounded(angleDiff, variance, angle_parallel_towards) then
  1093.         return angle_parallel_towards
  1094.     elseif betweenRounded(angleDiff, variance, angle_parallel_away) then
  1095.         return angle_parallel_away
  1096.     else
  1097.         return angle_unknown
  1098.     end
  1099. end
  1100.  
  1101. function betweenRounded(angleDiff, variance, angle) -- diff = known angle between two people, variance is allowed slippage, angle = goal you want if true
  1102.     low = angle - variance
  1103.     high = angle + variance
  1104.  
  1105.     if low <= 0 then
  1106.         return (low + 360 <= angleDiff or angleDiff <= high)
  1107.     else
  1108.         return (low <= angleDiff and angleDiff <= high)
  1109.     end
  1110. end
  1111.  
  1112. function sign(x)
  1113.     if x > 0 then return 1
  1114.     elseif x < 0 then return -1
  1115.     end
  1116. end
  1117.  
  1118. function IsMyManaLow()
  1119.     if myHero.mana < (myHero.maxMana * ( LucianExtraConfig.ManaManager / 100)) then
  1120.         return true
  1121.     else
  1122.         return false
  1123.     end
  1124. end
  1125.  
  1126. --[[
  1127. class 'ColorARGB' -- {
  1128.  
  1129.     function ColorARGB:__init(red, green, blue, alpha)
  1130.         self.R = red or 255
  1131.         self.G = green or 255
  1132.         self.B = blue or 255
  1133.         self.A = alpha or 255
  1134.     end
  1135.  
  1136.     function ColorARGB.FromArgb(red, green, blue, alpha)
  1137.         return Color(red,green,blue, alpha)
  1138.     end
  1139.  
  1140.     function ColorARGB:ToARGB()
  1141.         return ARGB(self.A, self.R, self.G, self.B)
  1142.     end
  1143.  
  1144.     ColorARGB.Red = ColorARGB(255, 0, 0, 255)
  1145.     ColorARGB.Yellow = ColorARGB(255, 255, 0, 255)
  1146.     ColorARGB.Green = ColorARGB(0, 255, 0, 255)
  1147.     ColorARGB.Aqua = ColorARGB(0, 255, 255, 255)
  1148.     ColorARGB.Blue = ColorARGB(0, 0, 255, 255)
  1149.     ColorARGB.Fuchsia = ColorARGB(255, 0, 255, 255)
  1150.     ColorARGB.Black = ColorARGB(0, 0, 0, 255)
  1151.     ColorARGB.White = ColorARGB(255, 255, 255, 255)
  1152. -- }
  1153.  
  1154. --Notification class
  1155. class 'Message' -- {
  1156.  
  1157.     Message.instance = ""
  1158.  
  1159.     function Message:__init()
  1160.         self.notifys = {}
  1161.  
  1162.         AddDrawCallback(function(obj) self:OnDraw() end)
  1163.     end
  1164.  
  1165.     function Message.Instance()
  1166.         if Message.instance == "" then Message.instance = Message() end return Message.instance
  1167.     end
  1168.  
  1169.     function Message.AddMessage(text, color, target)
  1170.         return Message.Instance():PAddMessage(text, color, target)
  1171.     end
  1172.  
  1173.     function Message:PAddMessage(text, color, target)
  1174.         local x = 0
  1175.         local y = 200
  1176.         local tempName = "Screen"
  1177.         local tempcolor = color or ColorARGB.Red
  1178.  
  1179.         if target then  
  1180.             tempName = target.networkID
  1181.         end
  1182.  
  1183.         self.notifys[tempName] = { text = text, color = tempcolor, duration = GetGameTimer() + 2, object = target}
  1184.     end
  1185.  
  1186.     function Message:OnDraw()
  1187.         for i, notify in pairs(self.notifys) do
  1188.             if notify.duration < GetGameTimer() then notify = nil
  1189.             else
  1190.                 notify.color.A = math.floor((255/2)*(notify.duration - GetGameTimer()))
  1191.  
  1192.                 if i == "Screen" then  
  1193.                     local x = 0
  1194.                     local y = 200
  1195.                     local gameSettings = GetGameSettings()
  1196.                     if gameSettings and gameSettings.General then
  1197.                         if gameSettings.General.Width then x = gameSettings.General.Width/2 end
  1198.                         if gameSettings.General.Height then y = gameSettings.General.Height/4 - 100 end
  1199.                     end  
  1200.                     --PrintChat(tostring(notify.color))
  1201.                     local p = GetTextArea(notify.text, 40).x
  1202.                     self:DrawTextWithBorder(notify.text, 40, x - p/2, y, notify.color:ToARGB(), ARGB(notify.color.A, 0, 0, 0))
  1203.                 else    
  1204.                     local pos = WorldToScreen(D3DXVECTOR3(notify.object.x, notify.object.y, notify.object.z))
  1205.                     local x = pos.x
  1206.                     local y = pos.y - 25
  1207.                     local p = GetTextArea(notify.text, 40).x
  1208.  
  1209.                     self:DrawTextWithBorder(notify.text, 30, x- p/2, y, notify.color:ToARGB(), ARGB(notify.color.A, 0, 0, 0))
  1210.                 end
  1211.             end
  1212.         end
  1213.     end
  1214.  
  1215.     function Message:DrawTextWithBorder(textToDraw, textSize, x, y, textColor, backgroundColor)
  1216.         DrawText(textToDraw, textSize, x + 1, y, backgroundColor)
  1217.         DrawText(textToDraw, textSize, x - 1, y, backgroundColor)
  1218.         DrawText(textToDraw, textSize, x, y - 1, backgroundColor)
  1219.         DrawText(textToDraw, textSize, x, y + 1, backgroundColor)
  1220.         DrawText(textToDraw, textSize, x , y, textColor)
  1221.     end
  1222. -- }
  1223. --]]
Advertisement
Add Comment
Please, Sign In to add comment