|
|
|
local Tinkr, Bastion = ...
|
|
|
|
|
|
|
|
local RestoShamanModule = Bastion.Module:New('RestoShaman')
|
|
|
|
local Player = Bastion.UnitManager:Get('player')
|
|
|
|
local Target = Bastion.UnitManager:Get('target')
|
|
|
|
local SpellBook = Bastion.SpellBook:New()
|
|
|
|
|
|
|
|
-- Spells
|
|
|
|
local WaterShield = SpellBook:GetSpell(52127)
|
|
|
|
local EarthShield = SpellBook:GetSpell(974)
|
|
|
|
local Riptide = SpellBook:GetSpell(61295)
|
|
|
|
local HealingSurge = SpellBook:GetSpell(8004)
|
|
|
|
local HealingWave = SpellBook:GetSpell(77472)
|
|
|
|
local ChainHeal = SpellBook:GetSpell(1064)
|
|
|
|
local HealingRain = SpellBook:GetSpell(73920)
|
|
|
|
local Downpour = SpellBook:GetSpell(207778)
|
|
|
|
local HealingStreamTotem = SpellBook:GetSpell(5394)
|
|
|
|
local CloudburstTotem = SpellBook:GetSpell(157153)
|
|
|
|
local SpiritLinkTotem = SpellBook:GetSpell(98008)
|
|
|
|
local AncestralGuidance = SpellBook:GetSpell(108281)
|
|
|
|
local Ascendance = SpellBook:GetSpell(114052)
|
|
|
|
local Wellspring = SpellBook:GetSpell(197995)
|
|
|
|
local UnleashLife = SpellBook:GetSpell(73685)
|
|
|
|
local PrimordialWave = SpellBook:GetSpell(375982)
|
|
|
|
local LavaBurst = SpellBook:GetSpell(51505)
|
|
|
|
local FlameShock = SpellBook:GetSpell(188389)
|
|
|
|
local WindShear = SpellBook:GetSpell(57994)
|
|
|
|
local LightningBolt = SpellBook:GetSpell(403)
|
|
|
|
|
|
|
|
-- Buffs
|
|
|
|
local TidalWaves = SpellBook:GetSpell(53390)
|
|
|
|
local WaterShieldBuff = SpellBook:GetSpell(52127)
|
|
|
|
local EarthShieldBuff = SpellBook:GetSpell(383648)
|
|
|
|
local UnleashLifeBuff = SpellBook:GetSpell(73685)
|
|
|
|
|
|
|
|
-- Custom Units
|
|
|
|
local Lowest = Bastion.UnitManager:CreateCustomUnit('lowest', function()
|
|
|
|
local lowest = nil
|
|
|
|
local lowestHP = 100
|
|
|
|
|
|
|
|
Bastion.UnitManager:EnumFriends(function(unit)
|
|
|
|
if unit:IsDead() or Player:GetDistance(unit) > 40 or not Player:CanSee(unit) then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
local hp = unit:GetHP()
|
|
|
|
if hp < lowestHP then
|
|
|
|
lowest = unit
|
|
|
|
lowestHP = hp
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
return lowest or Player
|
|
|
|
end)
|
|
|
|
|
|
|
|
local BestTarget = Bastion.UnitManager:CreateCustomUnit('besttarget', function()
|
|
|
|
local bestTarget = nil
|
|
|
|
local highestHP = 0
|
|
|
|
|
|
|
|
Bastion.UnitManager:EnumEnemies(function(unit)
|
|
|
|
if unit:IsAffectingCombat() and Player:IsWithinCombatDistance(unit, 40) and Player:CanSee(unit) and Player:IsFacing(unit) then
|
|
|
|
local hp = unit:GetHP()
|
|
|
|
if hp > highestHP then
|
|
|
|
bestTarget = unit
|
|
|
|
highestHP = hp
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
return bestTarget or Target
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- APLs
|
|
|
|
local DefaultAPL = Bastion.APL:New('default')
|
|
|
|
local CooldownAPL = Bastion.APL:New('cooldown')
|
|
|
|
local DefensiveAPL = Bastion.APL:New('defensive')
|
|
|
|
local DpsAPL = Bastion.APL:New('dps')
|
|
|
|
local InterruptAPL = Bastion.APL:New('interrupt')
|
|
|
|
|
|
|
|
-- Helper Functions
|
|
|
|
local function GetPlayerManaPercent()
|
|
|
|
return (UnitPower("player", Enum.PowerType.Mana) / UnitPowerMax("player", Enum.PowerType.Mana)) * 100
|
|
|
|
end
|
|
|
|
|
|
|
|
local function NeedsUrgentHealing()
|
|
|
|
return Lowest:GetHP() < 70 or Player:GetPartyHPAround(30, 80) >= 3
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Modify the EarthShield spell in the DefaultAPL
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
EarthShield:CastableIf(function(self)
|
|
|
|
local playerShield = Player:GetAuras():FindMy(EarthShieldBuff)
|
|
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
|
|
|
|
(not playerShield:IsUp() or playerShield:GetRemainingTime() < 30)
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Default APL
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
Riptide:CastableIf(function(self)
|
|
|
|
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Lowest:GetHP() < 95 and not Lowest:GetAuras():FindMy(TidalWaves):IsUp()
|
|
|
|
end):SetTarget(Lowest)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
UnleashLife:CastableIf(function(self)
|
|
|
|
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Lowest:GetHP() < 80
|
|
|
|
end):SetTarget(Lowest)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
HealingSurge:CastableIf(function(self)
|
|
|
|
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Lowest:GetHP() < 70 and Player:GetAuras():FindMy(TidalWaves):IsUp()
|
|
|
|
end):SetTarget(Lowest)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
HealingWave:CastableIf(function(self)
|
|
|
|
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Lowest:GetHP() < 85
|
|
|
|
end):SetTarget(Lowest)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
ChainHeal:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Player:GetPartyHPAround(40, 85) >= 3
|
|
|
|
end):SetTarget(Lowest)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Cooldown APL
|
|
|
|
CooldownAPL:AddSpell(
|
|
|
|
CloudburstTotem:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Player:GetPartyHPAround(40, 80) >= 3
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
CooldownAPL:AddSpell(
|
|
|
|
HealingStreamTotem:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and not CloudburstTotem:IsKnownAndUsable() and Player:GetPartyHPAround(40, 90) >= 2
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
CooldownAPL:AddSpell(
|
|
|
|
SpiritLinkTotem:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Player:GetPartyHPAround(30, 70) >= 3
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
CooldownAPL:AddSpell(
|
|
|
|
AncestralGuidance:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Player:GetPartyHPAround(40, 75) >= 3
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
CooldownAPL:AddSpell(
|
|
|
|
Ascendance:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and Player:GetPartyHPAround(40, 60) >= 3
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- DPS APL
|
|
|
|
DpsAPL:AddSpell(
|
|
|
|
FlameShock:CastableIf(function(self)
|
|
|
|
return BestTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and not BestTarget:GetAuras():FindMy(FlameShock):IsUp()
|
|
|
|
end):SetTarget(BestTarget)
|
|
|
|
)
|
|
|
|
|
|
|
|
DpsAPL:AddSpell(
|
|
|
|
LavaBurst:CastableIf(function(self)
|
|
|
|
return BestTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and BestTarget:GetAuras():FindMy(FlameShock):IsUp()
|
|
|
|
end):SetTarget(BestTarget)
|
|
|
|
)
|
|
|
|
|
|
|
|
DpsAPL:AddSpell(
|
|
|
|
LightningBolt:CastableIf(function(self)
|
|
|
|
return BestTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
end):SetTarget(BestTarget)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Interrupt APL
|
|
|
|
InterruptAPL:AddSpell(
|
|
|
|
WindShear:CastableIf(function(self)
|
|
|
|
return BestTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
|
|
and BestTarget:IsCasting() and BestTarget:IsInterruptible()
|
|
|
|
and BestTarget:GetChannelOrCastPercentComplete() >= 50
|
|
|
|
end):SetTarget(BestTarget)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Modify the out of combat Earth Shield logic in the Module Sync function
|
|
|
|
RestoShamanModule:Sync(function()
|
|
|
|
if Player:IsMounted() then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Out of combat healing and buffs
|
|
|
|
if not Player:IsAffectingCombat() then
|
|
|
|
if not Player:GetAuras():FindMy(WaterShieldBuff):IsUp() then
|
|
|
|
WaterShield:Cast(Player)
|
|
|
|
elseif not Player:GetAuras():FindMy(EarthShieldBuff):IsUp() then
|
|
|
|
EarthShield:Cast(Player)
|
|
|
|
elseif Lowest:GetHP() < 90 then
|
|
|
|
DefaultAPL:Execute()
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- In combat
|
|
|
|
InterruptAPL:Execute()
|
|
|
|
|
|
|
|
if NeedsUrgentHealing() then
|
|
|
|
CooldownAPL:Execute()
|
|
|
|
DefaultAPL:Execute()
|
|
|
|
else
|
|
|
|
if GetPlayerManaPercent() > 80 and BestTarget:Exists() then
|
|
|
|
DpsAPL:Execute()
|
|
|
|
end
|
|
|
|
|
|
|
|
if Riptide:GetCharges() >= 2 then
|
|
|
|
Bastion.UnitManager:EnumFriends(function(unit)
|
|
|
|
if unit:GetHP() < 95 and not unit:GetAuras():FindMy(TidalWaves):IsUp() then
|
|
|
|
Riptide:Cast(unit)
|
|
|
|
return true -- Stop enumerating after casting
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
if HealingWave:IsKnownAndUsable() and Lowest:GetHP() < 90 then
|
|
|
|
HealingWave:Cast(Lowest)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- AoE Healing
|
|
|
|
if Player:GetPartyHPAround(30, 85) >= 4 then
|
|
|
|
if HealingRain:IsKnownAndUsable() then
|
|
|
|
local loc = Bastion.UnitManager:FindFriendsCentroid(10, 40)
|
|
|
|
if loc then
|
|
|
|
HealingRain:Cast(Player):OnCast(function(self)
|
|
|
|
self:Click(loc)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
elseif Downpour:IsKnownAndUsable() then
|
|
|
|
local loc = Bastion.UnitManager:FindFriendsCentroid(10, 40)
|
|
|
|
if loc then
|
|
|
|
Downpour:Cast(Player):OnCast(function(self)
|
|
|
|
self:Click(loc)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
elseif Wellspring:IsKnownAndUsable() then
|
|
|
|
Wellspring:Cast(Player)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
Bastion:Register(RestoShamanModule)
|