local Tinkr, Bastion = ... local RestoModule = Bastion.Module:New('RestoDruid') local Player = Bastion.UnitManager:Get('player') local Target = Bastion.UnitManager:Get('target') -- Initialize SpellBook local SpellBook = Bastion.SpellBook:New() -- Spells local Efflorescence = SpellBook:GetSpell(145205) local Lifebloom = SpellBook:GetSpell(33763) local Innervate = SpellBook:GetSpell(29166) local Swiftmend = SpellBook:GetSpell(18562) local WildGrowth = SpellBook:GetSpell(48438) local Rejuvenation = SpellBook:GetSpell(774) local Tranquility = SpellBook:GetSpell(740) local Ironbark = SpellBook:GetSpell(102342) local NaturesSwiftness = SpellBook:GetSpell(132158) local Regrowth = SpellBook:GetSpell(8936) local Flourish = SpellBook:GetSpell(197721) local IncarnationTreeOfLife = SpellBook:GetSpell(33891) local CenarionWard = SpellBook:GetSpell(102351) local ConvokeTheSpirits = SpellBook:GetSpell(391528) local GroveGuardians = SpellBook:GetSpell(341523) local SoulOfTheForest = SpellBook:GetSpell(114108) local NaturesCure = SpellBook:GetSpell(88423) -- Buffs local SoulOfTheForestBuff = SpellBook:GetSpell(114108) local ClearcastingBuff = SpellBook:GetSpell(16870) local ReforestationBuff = SpellBook:GetSpell(392160) -- Custom Units local Lowest = Bastion.UnitManager:CreateCustomUnit('lowest', function(unit) local lowest = nil local lowestHP = math.huge 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 Tank = Bastion.UnitManager:CreateCustomUnit('tank', function(unit) local tank = nil Bastion.UnitManager:EnumFriends(function(unit) if Player:GetDistance(unit) > 40 or not Player:CanSee(unit) or unit:IsDead() then return false end if unit:IsTank() then tank = unit return true end end) return tank or Player end) -- APLs local DefaultAPL = Bastion.APL:New('default') local CooldownAPL = Bastion.APL:New('cooldown') -- Helper Functions local function GetRejuvCount() local count = 0 Bastion.UnitManager:EnumFriends(function(unit) if unit:GetAuras():FindMy(Rejuvenation):IsUp() then count = count + 1 end end) return count end local function ShouldUseFlourish() return GetRejuvCount() >= 3 and WildGrowth:GetTimeSinceLastCast() <= 6 end -- Efflorescence cast tracking local lastEfflorescenceCast = 0 -- Default APL DefaultAPL:AddSpell( Efflorescence:CastableIf(function(self) local currentTime = GetTime() return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and (currentTime - lastEfflorescenceCast) > 10 end):SetTarget(Bastion.UnitManager:Get('none')):OnCast(function(self) local loc = Bastion.UnitManager:FindFriendsCentroid(10, 40) self:Click(loc) lastEfflorescenceCast = GetTime() end) ) DefaultAPL:AddSpell( Lifebloom:CastableIf(function(self) return Tank:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and (not Tank:GetAuras():FindMy(Lifebloom):IsUp() or Tank:GetAuras():FindMy(Lifebloom):GetRemainingTime() <= 4.5) end):SetTarget(Tank) ) DefaultAPL:AddSpell( Rejuvenation:CastableIf(function(self) return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Lowest:GetHP() <= 95 and not Player:GetAuras():FindMy(SoulOfTheForestBuff):IsUp() end):SetTarget(Lowest) ) DefaultAPL:AddSpell( Swiftmend:CastableIf(function(self) return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Lowest:GetHP() <= 60 end):SetTarget(Lowest) ) DefaultAPL:AddSpell( WildGrowth:CastableIf(function(self) return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and (Player:GetAuras():FindMy(SoulOfTheForestBuff):IsUp() or Player:GetPartyHPAround(30, 95) >= 3) and not Player:IsMoving() end):SetTarget(Player) ) DefaultAPL:AddSpell( Regrowth:CastableIf(function(self) return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Lowest:GetHP() < 70 and (Player:GetAuras():FindMy(ClearcastingBuff):IsUp() or NaturesSwiftness:GetTimeSinceLastCast() < 2) and not Player:IsMoving() end):SetTarget(Lowest) ) DefaultAPL:AddSpell( CenarionWard:CastableIf(function(self) return Tank:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Tank:GetHP() <= 95 end):SetTarget(Tank) ) DefaultAPL:AddSpell( NaturesCure:CastableIf(function(self) return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Lowest:GetAuras():HasAnyDispelableAura(NaturesCure) end):SetTarget(Lowest) ) -- Cooldown APL CooldownAPL:AddSpell( Tranquility:CastableIf(function(self) return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetPartyHPAround(40, 70) >= 3 end):SetTarget(Player) ) CooldownAPL:AddSpell( Innervate:CastableIf(function(self) return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetPP() <= 80 end):SetTarget(Player) ) CooldownAPL:AddSpell( Ironbark:CastableIf(function(self) return Tank:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Tank:GetHP() <= 70 end):SetTarget(Tank) ) CooldownAPL:AddSpell( NaturesSwiftness:CastableIf(function(self) return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Lowest:GetHP() < 50 end):SetTarget(Lowest) ) CooldownAPL:AddSpell( Flourish:CastableIf(function(self) return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and ShouldUseFlourish() end):SetTarget(Player) ) CooldownAPL:AddSpell( IncarnationTreeOfLife:CastableIf(function(self) return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetPartyHPAround(40, 80) >= 3 end):SetTarget(Player) ) CooldownAPL:AddSpell( ConvokeTheSpirits:CastableIf(function(self) return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetAuras():FindMy(ReforestationBuff):GetCount() == 3 end):SetTarget(Player) ) CooldownAPL:AddSpell( GroveGuardians:CastableIf(function(self) return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and self:GetCharges() == 3 end):SetTarget(Player) ) -- Module Sync RestoModule:Sync(function() if Player:IsAffectingCombat() then CooldownAPL:Execute() DefaultAPL:Execute() end end) Bastion:Register(RestoModule)