--[[
Auto Carry Plugin - Ahri Prodiction Edition
Author: Chancity & Kain
Version: See version variable below.
Copyright 2013
Dependency: Sida's Auto Carry
How to install:
Make sure you already have AutoCarry installed.
Name the script EXACTLY "SidasAutoCarryPlugin - Ahri.lua" without the quotes.
Place the plugin in BoL/Scripts/Common folder.
Features:
Smart Combos (Checks for mana, ability damage, and cool downs), can be disabled
Draw text for smart combo is shown on target
Fully customizable ability options in Mixed Mode (Q, W, E)
Mixed Mode Harass with mana management
Optional use Q return while using Mixed Mode
Draws Skill Ranges based on what skills are ready
Download:
Version History:
Version: 1.14
Added options to adjust Q and E width
Version: 1.13
Added automatic updates
Added ability to change ranges for all skills
Version: 1.12
Added require charm toggle
Added permaShow for ult toggle and require charm
Cleaned up code and logic
Version: 1.11
Removed KS
Version: 1.1
Added ult toggle
Version: 1.09
Fixed a small bug with damage calculations
Added KSing feature
Use Ult has can be toggled on and off with "Z", can be changed
Version: 1.08
Added new draw text messages
Fixed a bug when checking current mana for Smart Combos
Version: 1.07
PROdiction 2.0
Version: 1.06
Added Back: Smart Combos (Checks for mana, ability damage, and cool downs), can be disabled
Added Back: Draw text for smart combo is shown on target
Version: 1.05
Smart Combos (Checks for mana, ability damage, and cool downs), can be disabled
Draw text for smart combo is shown on target
Slider to change format of draw text
Slider to adjust "Q Return"
Version: 1.04
Release
--]]
if myHero.charName ~= "Ahri" then return end
local GetVersionURL, hasUpdated = "http://bit.ly/17GTqzC", true
local PLUGIN_PATH = BOL_PATH.."Scripts\\Common\\SidasAutoCarryPlugin - "..myHero.charName..".lua"
local VERSION_PATH = os.getenv("APPDATA").."\\"..myHero.charName.."Version.ini"
DownloadFile(GetVersionURL, VERSION_PATH, function() end)
function DefaultRanges()
QRange, QSpeed, QDelay, QWidth = 895, 1.67, 240, 50
WRange, WSpeed, WDelay, WWidth = 605, nil, nil, 225
ERange, ESpeed, EDelay, EWidth = 920, 1.55, 240, 80
RRange, RSpeed, RDelay, RWidth = 700, math.huge, 100, 100
setRange = false
end
function Variables()
curVersion = 1.19
UpdateChat = {}
AhriTumbleActive = false
if VIP_USER then
AdvancedCallback:bind('OnGainBuff', function(unit, buff) OnGainBuff(unit, buff) end)
AdvancedCallback:bind('OnLoseBuff', function(unit, buff) OnLoseBuff(unit, buff) end)
end
if AutoCarry.Skills then IsSACReborn = true else IsSACReborn = false end
if IsSACReborn then
AutoCarry.Skills:DisableAll()
end
QReady, WReady, EReady, RReady, DFGReady, IReady = false, false, false, false, false, false
DFGSlot = nil
if IsSACReborn then
SkillQ = AutoCarry.Skills:NewSkill(false, _Q, QRange, "Orb Of Deception", AutoCarry.SPELL_LINEAR, 0, false, false, QSpeed, QDelay, QWidth, false)
SkillW = AutoCarry.Skills:NewSkill(false, _W, WRange, "Fox Fire", AutoCarry.SPELL_TARGETED, 0, false, false, WSpeed, WDelay, WWidth, false)
SkillE = AutoCarry.Skills:NewSkill(false, _E, ERange, "Charm", AutoCarry.SPELL_LINEAR_COL, 0, false, false, ESpeed, EDelay, EWidth, true)
SkillR = AutoCarry.Skills:NewSkill(false, _R, RRange, "Spirit Rush", AutoCarry.SPELL_SELF_AT_MOUSE, 0, false, false, RSpeed, RDelay, RWidth, false)
else
SkillQ = {spellKey = _Q, range = QRange, speed = QSpeed, delay = QDelay, width = QWidth, configName = "orbofdeception", displayName = "Q (Orb of Deception)", enabled = true, skillShot = true, minions = false, reset = false, reqTarget = false }
SkillW = {spellKey = _W, range = WRange, speed = WSpeed, delay = WDelay, width = WWidth, configName = "foxfire", displayName = "W (Fox-Fire)", enabled = true, skillShot = false, minions = false, reset = false, reqTarget = false }
SkillE = {spellKey = _E, range = ERange, speed = ESpeed, delay = EDelay, width = EWidth, configName = "charm", displayName = "E (Charm)", enabled = true, skillShot = true, minions = true, reset = false, reqTarget = false }
SkillR = {spellKey = _R, range = RRange, speed = RSpeed, delay = RDelay, width = RWidth, configName = "spiritrush", displayName = "R (Spirit Rush)", enabled = true, skillShot = false, minions = false, reset = false, reqTarget = false }
end
ignite = nil
useIgnite = true
if myHero:GetSpellData(SUMMONER_1).name:find("SummonerDot") then
ignite = SUMMONER_1
elseif myHero:GetSpellData(SUMMONER_2).name:find("SummonerDot") then
ignite = SUMMONER_2
end
enemyHeros = {}
enemyHerosCount = 0
for i = 1, heroManager.iCount do
local hero = heroManager:GetHero(i)
if hero.team ~= player.team then
local enemyCount = enemyHerosCount + 1
enemyHeros[enemyCount] = {object = hero, q = 0, w = 0, e = 0, r = 0, dfg = 0, ig = 0, myDamage = 0, manaCombo = 0}
enemyHerosCount = enemyCount
end
end
KeyQ = string.byte("Q")
KeyE = string.byte("E")
end
function AhriMenu()
Menu = AutoCarry.PluginMenu
Menu:addSubMenu(""..myHero.charName.." Auto Carry: Auto Carry", "autocarry")
Menu.autocarry:addParam("SmartCombo","Use Smart Combo", SCRIPT_PARAM_ONOFF, true)
Menu.autocarry:addParam("CastR","Use Spirit Rush (Z)", SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("Z"))
Menu.autocarry:permaShow("CastR")
Menu:addSubMenu(""..myHero.charName.." Auto Carry: Mixed Mode", "mixedmode")
Menu.mixedmode:addSubMenu("Q Return", "qreturn")
Menu.mixedmode.qreturn:addParam("MixedQdoubleProc","Use Q Return", SCRIPT_PARAM_ONOFF, false)
Menu.mixedmode.qreturn:addParam("bottomQ","Minimum Range %", SCRIPT_PARAM_SLICE, 75, 65, 85, 0)
Menu.mixedmode.qreturn:addParam("topQ","Maximum Range %", SCRIPT_PARAM_SLICE, 95, 75, 95, 0)
Menu.mixedmode:addParam("MixedUseQ","Use Orb Of Deception", SCRIPT_PARAM_ONOFF, true)
Menu.mixedmode:addParam("MixedUseW","Use Fox Fire", SCRIPT_PARAM_ONOFF, false)
Menu.mixedmode:addParam("MixedUseE","Use Charm", SCRIPT_PARAM_ONOFF, true)
Menu.mixedmode:addParam("MixedMinMana","Mana Manager %", SCRIPT_PARAM_SLICE, 40, 0, 100, 0)
Menu:addSubMenu(""..myHero.charName.." Auto Carry: Skill Settings", "skills")
Menu.skills:addParam("UseAdjustedSkills","Adjusted Skills", SCRIPT_PARAM_ONOFF, false)
Menu.skills:addSubMenu("Q Settings", "Qskill")
Menu.skills.Qskill:addParam("QskillRange","Q Range", SCRIPT_PARAM_SLICE, 895, 800, 1000, 0)
Menu.skills.Qskill:addParam("QskillWidth","Q Width", SCRIPT_PARAM_SLICE, 25, 50, 120, 0)
Menu.skills:addSubMenu("E Settings", "Eskill")
Menu.skills.Eskill:addParam("EskillRange","E Range", SCRIPT_PARAM_SLICE, 920, 800, 1000, 0)
Menu.skills.Eskill:addParam("EskillWidth","E Width", SCRIPT_PARAM_SLICE, 25, 80, 100, 0)
Menu.skills:addSubMenu("W Settings", "Wskill")
Menu.skills.Wskill:addParam("WskillRange","W Range", SCRIPT_PARAM_SLICE, 600, 450, 700, 0)
Menu.skills:addSubMenu("R Settings", "Rskill")
Menu.skills.Rskill:addParam("RskillRange","R Range", SCRIPT_PARAM_SLICE, 700, 450, 900, 0)
Menu:addSubMenu(""..myHero.charName.." Auto Carry: Draw", "draw")
Menu.draw:addParam("DrawKillable","Draw Killable", SCRIPT_PARAM_ONOFF, true)
Menu.draw:addParam("DrawKillableTextSize","Draw Killable Text Size", SCRIPT_PARAM_SLICE, 15, 0, 40, 0)
Menu.draw:addParam("DrawTextTargetColor","Target Color", SCRIPT_PARAM_COLOR, {255,0,238,0})
Menu.draw:addParam("DrawTextUnitColor","Unit Color", SCRIPT_PARAM_COLOR, { 255, 255, 50, 50 })
Menu.draw:addParam("DrawRange","Draw Skill Range", SCRIPT_PARAM_ONOFF, true)
Menu:addSubMenu(""..myHero.charName.." Auto Carry: Extras", "extras")
Menu.extras:addParam("RequireCharm","Require Charm (X)", SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("X"))
Menu.extras:permaShow("RequireCharm")
Menu.extras:addParam("ProMode","Use Auto Q & E Keys", SCRIPT_PARAM_ONOFF, false)
Menu.extras:addParam("Ignite","Use Ignite", SCRIPT_PARAM_ONOFF, true)
end
function PluginOnLoad()
DefaultRanges()
Variables()
AhriMenu()
AutoCarry.SkillsCrosshair.range = ERange
end
function PluginOnTick()
if myHero.dead then return end
if hasUpdated then
if FileExist(VERSION_PATH) then
AutoUpdate()
end
end
CheckSpells()
damageCalculation()
if Menu.skills.UseAdjustedSkills then
AdjustRanges()
elseif setRange then
DefaultRanges()
end
if Target ~= nil and AutoCarry.MainMenu.AutoCarry then
FullCombo()
end
if Target ~= nil and AutoCarry.MainMenu.MixedMode and CheckMana() then
HarassCombo()
end
if Menu.extras.Ignite and ignite and IReady then doIgnite() end
end
function PluginOnDraw()
if myHero.dead then return end
if Menu.draw.DrawRange and EReady then
DrawCircle(myHero.x, myHero.y, myHero.z, ERange, 0xe066a3)
elseif Menu.draw.DrawRange and QReady then
DrawCircle(myHero.x, myHero.y, myHero.z, QRange, 0xe066a3)
elseif Menu.draw.DrawRange and WReady then
DrawCircle(myHero.x, myHero.y, myHero.z, WRange, 0xe066a3)
end
if Menu.draw.DrawKillable then
for i = 1, enemyHerosCount do
local Unit = enemyHeros[i].object
local q = enemyHeros[i].q
local w = enemyHeros[i].w
local e = enemyHeros[i].e
local r = enemyHeros[i].r
local dfg = enemyHeros[i].dfg
local ig = enemyHeros[i].ig
local myDamage = enemyHeros[i].myDamage
local manaCombo = enemyHeros[i].manaCombo
local comboMessage = ""
local a = Menu.draw.DrawTextTargetColor
local b = Menu.draw.DrawTextUnitColor
if ValidTarget(Unit) then
if myDamage >= Unit.health and manaCombo <= myHero.mana then
if e == 1 then
comboMessage = comboMessage.." E"
end
if q == 1 then
comboMessage = comboMessage.." Q"
end
if w == 1 then
comboMessage = comboMessage.." W"
end
if r >= 1 then
comboMessage = comboMessage.." R"..tostring(r)
end
if dfg == 1 then
comboMessage = comboMessage.." DFG"
end
if ig == 1 then
comboMessage = comboMessage.." IG"
end
if Unit == Target then
DrawText3D("Killable"..comboMessage,Unit.x,Unit.y, Unit.z,Menu.draw.DrawKillableTextSize,ARGB(a[1],a[2],a[3],a[4]), true)
else
DrawText3D("Killable"..comboMessage,Unit.x,Unit.y, Unit.z,Menu.draw.DrawKillableTextSize,ARGB(b[1],b[2],b[3],b[4]), true)
end
elseif myDamage < Unit.health and QReady or WReady or EReady then
if Unit == Target then
DrawText3D("Harass"..comboMessage,Unit.x,Unit.y, Unit.z,Menu.draw.DrawKillableTextSize,ARGB(a[1],a[2],a[3],a[4]), true)
else
DrawText3D("Harass"..comboMessage,Unit.x,Unit.y, Unit.z,Menu.draw.DrawKillableTextSize,ARGB(b[1],b[2],b[3],b[4]), true)
end
elseif not myHero.dead then
if Unit == Target then
DrawText3D("Not Killable"..comboMessage,Unit.x,Unit.y, Unit.z,Menu.draw.DrawKillableTextSize,ARGB(a[1],a[2],a[3],a[4]), true)
else
DrawText3D("Not Killable"..comboMessage,Unit.x,Unit.y, Unit.z,Menu.draw.DrawKillableTextSize,ARGB(b[1],b[2],b[3],b[4]), true)
end
end
end
end
end
end
function FullCombo()
if Menu.autocarry.SmartCombo then
for i = 1, enemyHerosCount do
local Unit = enemyHeros[i].object
local q = enemyHeros[i].q
local w = enemyHeros[i].w
local e = enemyHeros[i].e
local r = enemyHeros[i].r
local dfg = enemyHeros[i].dfg
local myDamage = enemyHeros[i].myDamage
if Unit.name == Target.name and myDamage >= Target.health then
if ig == 0 then
useIgnite = false
else
useIgnite = true
end
if e == 1 then CastE() end
if charmCheck() then return end
if dfg == 1 then
if DFGReady then CastSpell(DFGSlot, Target) end
end
if r >= 1 and Menu.autocarry.CastR then CastR() end
if q == 1 then CastQ() end
if w == 1 then CastW() end
elseif myDamage < Target.health then
if AhriTumbleActive and Menu.autocarry.CastR then CastR() end
CastE()
if charmCheck() then return end
CastQ()
CastW()
end
end
else
CastE()
if charmCheck() then return end
CastQ()
CastW()
end
end
function HarassCombo()
if Menu.mixedmode.MixedUseE and EReady and CheckMana() and ValidTarget(Target, ERange) then
CastE()
end
if charmCheck() then return end
if Menu.mixedmode.MixedUseQ and QReady and CheckMana() and ValidTarget(Target, QRange) then
if Menu.mixedmode.MixedQdoubleProc then
if HarassQ() then
CastQ()
end
else
CastQ()
end
end
if Menu.mixedmode.MixedUseW and WReady and CheckMana() and GetDistance(Target) <= WRange then CastSpell(_W) end
end
function CastE()
if EReady and ValidTarget(Target, ERange) then
if IsSACReborn then
SkillE:Cast(Target)
else
AutoCarry.CastSkillshot(SkillE, Target)
end
end
end
function CastQ()
if QReady and ValidTarget(Target, QRange) then
if IsSACReborn then
SkillQ:Cast(Target)
else
AutoCarry.CastSkillshot(SkillQ, Target)
end
end
end
function CastW()
if WReady and GetDistance(Target) <= WRange then CastSpell(_W) end
end
function CastR()
if RReady and ValidTarget(Target, RRange) then
if IsSACReborn then
SkillR:Cast(Target)
else
AutoCarry.CastSkillshot(SkillR, Target)
end
end
end
function doIgnite()
for _, enemy in pairs(GetEnemyHeroes()) do
if ValidTarget(enemy, 600) and useIgnite and enemy.health <= 50 + (20 * player.level) and not IsIgnited(enemy) then
CastSpell(ignite, enemy)
end
end
end
function IsIgnited(target)
if TargetHaveBuff("SummonerDot", target) then
igniteTick = GetTickCount()
return true
elseif igniteTick == nil or GetTickCount()-igniteTick>500 then
return false
end
end
function CheckMana()
if myHero.mana >= myHero.maxMana*(Menu.mixedmode.MixedMinMana/100) then
return true
else
return false
end
end
function HarassQ()
if GetDistance(Target) >= (QRange * Menu.mixedmode.qreturn.bottomQ/100) and GetDistance(Target) <= (QRange * Menu.mixedmode.qreturn.topQ/100) then
return true
else
return false
end
end
function charmCheck()
CheckSpells()
if EReady and Menu.extras.RequireCharm then
return true
else
return false
end
end
function CheckSpells()
Target = AutoCarry.GetAttackTarget()
DFGSlot = GetInventorySlotItem(3128)
QReady = (myHero:CanUseSpell(_Q) == READY)
WReady = (myHero:CanUseSpell(_W) == READY)
EReady = (myHero:CanUseSpell(_E) == READY)
RReady = (myHero:CanUseSpell(_R) == READY)
DFGReady = (DFGSlot ~= nil and myHero:CanUseSpell(DFGSlot) == READY)
IReady = (ignite ~= nil and myHero:CanUseSpell(ignite) == READY)
end
function OnGainBuff(unit, buff)
if unit.isMe then
if buff.name == "AhriTumble" then
AhriTumbleActive = true
end
end
end
function OnLoseBuff(unit, buff)
if unit.isMe then
if buff.name == "AhriTumble" then
AhriTumbleActive = false
end
end
end
function AdjustRanges()
if QRange > Menu.skills.Qskill.QskillRange or QRange < Menu.skills.Qskill.QskillRange then QRange = Menu.skills.Qskill.QskillRange end
if QWidth > Menu.skills.Qskill.QskillWidth or QRange < Menu.skills.Qskill.QskillWidth then QWidth = Menu.skills.Qskill.QskillWidth end
if WRange > Menu.skills.Wskill.WskillRange or WRange < Menu.skills.Wskill.WskillRange then WRange = Menu.skills.Wskill.WskillRange end
if ERange > Menu.skills.Eskill.EskillRange or ERange < Menu.skills.Eskill.EskillRange then ERange = Menu.skills.Eskill.EskillRange end
if EWidth > Menu.skills.Eskill.EskillWidth or EWidth < Menu.skills.Eskill.EskillWidth then EWidth = Menu.skills.Eskill.EskillWidth end
if RRange > Menu.skills.Rskill.RskillRange or RRange < Menu.skills.Rskill.RskillRange then RRange = Menu.skills.Rskill.RskillRange end
setRange = true
end
function damageCalculation()
for i = 1, enemyHerosCount do
local Unit = enemyHeros[i].object
if ValidTarget(Unit) then
dfgdamage, ignitedamage = 0, 0
manaCombo, myDamage, QDamage, EDamage, WDamage, RDamage = 0, 0, getDmg("Q", Unit, myHero), getDmg("E", Unit, myHero), getDmg("W", Unit, myHero), getDmg("R", Unit, myHero)
dfgdamage = (DFGSlot and getDmg("DFG",Unit,myHero) or 0)
ignitedamage = (ignite and getDmg("IGNITE",Unit,myHero) or 0)
if EReady then
if myHero.mana >= myHero:GetSpellData(_E).mana and myHero.mana >= manaCombo then
manaCombo = manaCombo + myHero:GetSpellData(_E).mana
myDamage = myDamage + EDamage
enemyHeros[i].e = 1
else
enemyHeros[i].e = 0
end
else
enemyHeros[i].e = 0
end
if QReady then
if myHero.mana >= myHero:GetSpellData(_Q).mana and myHero.mana >= manaCombo and myDamage < Unit.health then
manaCombo = manaCombo + myHero:GetSpellData(_Q).mana
myDamage = myDamage + QDamage
enemyHeros[i].q = 1
else
enemyHeros[i].q = 0
end
else
enemyHeros[i].q = 0
end
if WReady then
if myHero.mana >= myHero:GetSpellData(_W).mana and myHero.mana >= manaCombo and myDamage < Unit.health then
manaCombo = manaCombo + myHero:GetSpellData(_W).mana
myDamage = myDamage + (WDamage + WDamage)
enemyHeros[i].w = 1
else
enemyHeros[i].w = 0
end
else
enemyHeros[i].w = 0
end
if RReady then
if myHero.mana >= myHero:GetSpellData(_R).mana and myHero.mana >= manaCombo and myDamage < Unit.health then
manaCombo = manaCombo + myHero:GetSpellData(_R).mana
myDamage = myDamage + RDamage
enemyHeros[i].r = 1
if myDamage < Unit.health then
myDamage = myDamage + RDamage
enemyHeros[i].r = 2
end
if myDamage < Unit.health then
myDamage = myDamage + RDamage
enemyHeros[i].r = 3
end
else
enemyHeros[i].r = 0
end
else
enemyHeros[i].r = 0
end
if DFGReady and myDamage < Unit.health then
myDamage = myDamage * 1.2
myDamage = myDamage + dfgdamage
enemyHeros[i].dfg = 1
else
enemyHeros[i].dfg = 0
end
if IReady and myDamage < Unit.health then
myDamage = myDamage + ignitedamage
enemyHeros[i].ig = 1
else
enemyHeros[i].ig = 0
end
enemyHeros[i].manaCombo = manaCombo
enemyHeros[i].myDamage = myDamage
end
end
end
function PluginOnWndMsg(msg, key)
if Target ~= nil and Menu.extras.ProMode then
if msg == KEY_DOWN and key == KeyQ then CastQ() end
if msg == KEY_DOWN and key == KeyE then CastE() end
end
end
function NewIniReader()
local reader = {}
function reader:Read(fName)
self.root = {}
self.reading_section = ""
for line in io.lines(fName) do
if startsWith(line, "[") then
local section = string.sub(line,2,-2)
self.root[section] = {}
self.reading_section = section;
elseif not startsWith(line, ";") then
if self.reading_section then
local var,val = line:usplit("=")
self.root[self.reading_section] = self.root[self.reading_section] or {}
self.root[self.reading_section][var] = val
end
end
end
end
function reader:GetValue(Section, Key)
return self.root[Section][Key]
end
function reader:GetKeys(Section)
return self.root[Section]
end
return reader;
end
function startsWith(text,prefix)
return string.sub(text, 1, string.len(prefix)) == prefix
end
function string:usplit(sep)
return self:match("([^" .. sep .. "]+)[" .. sep .. "]+(.+)")
end
function AutoUpdate()
reader = NewIniReader()
if FileExist(VERSION_PATH) then
reader:Read(VERSION_PATH)
newDownloadURL = reader:GetValue("Version", "Download")
newVersion = reader:GetValue("Version", "Version")
newMessage = reader:GetValue("Version", "Message")
UpdateChat = {
" >> "..myHero.charName.." Auto Carry Plugin: Checking for update... ",
" >> "..myHero.charName.." Auto Carry Plugin: Running Version "..curVersion.."",
" >> "..myHero.charName.." Auto Carry Plugin: New Version Released "..newVersion.."",
" >> "..myHero.charName.." Auto Carry Plugin: Updated to version "..newVersion.." press F9 two times to use updated script. ",
" >> "..myHero.charName.." Auto Carry Plugin: Script is Up-To-Date ",
" >> "..myHero.charName.." Auto Carry Plugin: Update Message ("..newVersion.."): "..newMessage.."",
" >> "..myHero.charName.." Auto Carry Plugin: Failed to check for update, press F9 two times if first run "
}
os.remove(VERSION_PATH)
if tonumber(newVersion) > tonumber(curVersion) then
DownloadFile(newDownloadURL, PLUGIN_PATH, function()
if FileExist(PLUGIN_PATH) then
ChatUpdate("update")
end
end)
else
ChatUpdate("uptodate")
end
else
ChatUpdate("failed")
end
hasUpdated = false
end
function ChatUpdate(stats)
PrintChat(UpdateChat[1])
PrintChat(UpdateChat[2])
if stats == "update" then
PrintChat(UpdateChat[3])
PrintChat(UpdateChat[4])
PrintChat(UpdateChat[6])
elseif stats == "uptodate" then
PrintChat(UpdateChat[5])
PrintChat(UpdateChat[6])
else
PrintChat(UpdateChat[7])
end
end
--UPDATEURL=
--HASH=C6B2398227C148F3D2E108F35189BEEA