parent
716138b5d3
commit
4c86679130
@ -0,0 +1,379 @@ |
|||||||
|
local Tinkr, Bastion = ... |
||||||
|
|
||||||
|
local HolyPaladinModule = Bastion.Module:New('HolyPaladin') |
||||||
|
local Player = Bastion.UnitManager:Get('player') |
||||||
|
local Target = Bastion.UnitManager:Get('target') |
||||||
|
local MELEE_RANGE = 5 -- Adjust this value based on your class's melee range |
||||||
|
|
||||||
|
-- Initialize SpellBook |
||||||
|
local SpellBook = Bastion.SpellBook:New() |
||||||
|
|
||||||
|
-- Power type constant |
||||||
|
local HOLY_POWER = Enum.PowerType.HolyPower |
||||||
|
|
||||||
|
-- Healing threshold variable |
||||||
|
local healingThreshold = 90 |
||||||
|
|
||||||
|
-- Spells |
||||||
|
local AutoAttack = SpellBook:GetSpell(6603) |
||||||
|
local BeaconOfVirtue = SpellBook:GetSpell(200025) |
||||||
|
local BlessingOfSummer = SpellBook:GetSpell(388007) |
||||||
|
local SacredWeapon = SpellBook:GetSpell(383395) |
||||||
|
local Consecration = SpellBook:GetSpell(26573) |
||||||
|
local Judgment = SpellBook:GetSpell(275773) |
||||||
|
local HolyPrism = SpellBook:GetSpell(114165) |
||||||
|
local WordOfGlory = SpellBook:GetSpell(85673) |
||||||
|
local ShieldOfTheRighteous = SpellBook:GetSpell(53600) |
||||||
|
local HolyShock = SpellBook:GetSpell(20473) |
||||||
|
local HolyLight = SpellBook:GetSpell(82326) |
||||||
|
local CrusaderStrike = SpellBook:GetSpell(35395) |
||||||
|
local HammerOfWrath = SpellBook:GetSpell(24275) |
||||||
|
local FlashOfLight = SpellBook:GetSpell(19750) |
||||||
|
local LightOfDawn = SpellBook:GetSpell(85222) |
||||||
|
local DivineShield = SpellBook:GetSpell(642) |
||||||
|
local LayOnHands = SpellBook:GetSpell(633) |
||||||
|
local BlessingOfProtection = SpellBook:GetSpell(1022) |
||||||
|
local BlessingOfSacrifice = SpellBook:GetSpell(6940) |
||||||
|
local AvengingWrath = SpellBook:GetSpell(31884) |
||||||
|
|
||||||
|
-- Buffs |
||||||
|
local DivineFavorBuff = SpellBook:GetSpell(388039) |
||||||
|
local InfusionOfLightBuff = SpellBook:GetSpell(54149) |
||||||
|
local ConsecrationBuff = SpellBook:GetSpell(188370) |
||||||
|
|
||||||
|
-- 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) |
||||||
|
|
||||||
|
local BestTarget = Bastion.UnitManager:CreateCustomUnit('besttarget', function() |
||||||
|
local bestMeleeTarget = nil |
||||||
|
local bestRangedTarget = nil |
||||||
|
local highestMeleeHealth = 0 |
||||||
|
local highestRangedHealth = 0 |
||||||
|
|
||||||
|
Bastion.UnitManager:EnumEnemies(function(unit) |
||||||
|
if unit:IsAffectingCombat() and unit:GetDistance(Player) <= 40 and Player:CanSee(unit) then |
||||||
|
local health = unit:GetHealth() |
||||||
|
if unit:GetDistance(Player) <= MELEE_RANGE then |
||||||
|
-- Melee target |
||||||
|
if health > highestMeleeHealth then |
||||||
|
highestMeleeHealth = health |
||||||
|
bestMeleeTarget = unit |
||||||
|
end |
||||||
|
else |
||||||
|
-- Ranged target |
||||||
|
if health > highestRangedHealth then |
||||||
|
highestRangedHealth = health |
||||||
|
bestRangedTarget = unit |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end) |
||||||
|
|
||||||
|
-- Return the best melee target if it exists, otherwise return the best ranged target |
||||||
|
return bestMeleeTarget or bestRangedTarget or Target |
||||||
|
end) |
||||||
|
|
||||||
|
local ExecuteTarget = Bastion.UnitManager:CreateCustomUnit('executetarget', function() |
||||||
|
local target = nil |
||||||
|
Bastion.UnitManager:EnumEnemies(function(unit) |
||||||
|
if unit:IsAffectingCombat() and unit:GetDistance(Player) <= 30 and Player:CanSee(unit) |
||||||
|
and unit:GetHP() < 20 then |
||||||
|
target = unit |
||||||
|
return true |
||||||
|
end |
||||||
|
end) |
||||||
|
return target or Bastion.UnitManager:Get('none') |
||||||
|
end) |
||||||
|
|
||||||
|
-- Custom Functions |
||||||
|
|
||||||
|
local function IsInMeleeRange(unit) |
||||||
|
return Player:GetDistance(unit) <= MELEE_RANGE |
||||||
|
end |
||||||
|
|
||||||
|
-- Create APLs |
||||||
|
local DefaultAPL = Bastion.APL:New('default') |
||||||
|
local HealingAPL = Bastion.APL:New('healing') |
||||||
|
local DamageAPL = Bastion.APL:New('damage') |
||||||
|
local CooldownAPL = Bastion.APL:New('cooldown') |
||||||
|
local DefensiveAPL = Bastion.APL:New('defensive') |
||||||
|
local ExecuteAPL = Bastion.APL:New('execute') |
||||||
|
local DamagePriorityAPL = Bastion.APL:New('damagepriority') |
||||||
|
|
||||||
|
-- Utility function to check if healing is needed |
||||||
|
local function HealingNeeded() |
||||||
|
return Lowest:GetHP() < healingThreshold |
||||||
|
end |
||||||
|
|
||||||
|
-- Utility function to check if emergency healing is needed |
||||||
|
local function EmergencyHealingNeeded() |
||||||
|
return Lowest:GetHP() < 50 |
||||||
|
end |
||||||
|
|
||||||
|
-- Utility function to check if Beacon of Virtue should be cast |
||||||
|
local function ShouldCastBeaconOfVirtue() |
||||||
|
local lowHealthCount = 0 |
||||||
|
local totalPartyMembers = 0 |
||||||
|
Bastion.UnitManager:EnumFriends(function(unit) |
||||||
|
if unit:GetDistance(Player) <= 40 and Player:CanSee(unit) then |
||||||
|
totalPartyMembers = totalPartyMembers + 1 |
||||||
|
if unit:GetHP() < 80 then |
||||||
|
lowHealthCount = lowHealthCount + 1 |
||||||
|
end |
||||||
|
end |
||||||
|
end) |
||||||
|
return lowHealthCount >= math.min(3, math.ceil(totalPartyMembers * 0.6)) |
||||||
|
end |
||||||
|
|
||||||
|
-- Utility function to check if anyone in the party needs healing |
||||||
|
local function AnyoneNeedsHealing() |
||||||
|
local needsHealing = false |
||||||
|
Bastion.UnitManager:EnumFriends(function(unit) |
||||||
|
if unit:GetHP() < healingThreshold then |
||||||
|
needsHealing = true |
||||||
|
return true |
||||||
|
end |
||||||
|
end) |
||||||
|
return needsHealing |
||||||
|
end |
||||||
|
|
||||||
|
-- Variables for auto-attack tracking |
||||||
|
local lastAutoAttackTime = 0 |
||||||
|
|
||||||
|
-- Event handler for auto-attack tracking |
||||||
|
Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function() |
||||||
|
local _, subEvent, _, sourceGUID, _, _, _, _, _, _, _, spellID = CombatLogGetCurrentEventInfo() |
||||||
|
if sourceGUID == Player:GetGUID() and (subEvent == "SWING_DAMAGE" or subEvent == "SWING_MISSED") then |
||||||
|
lastAutoAttackTime = GetTime() |
||||||
|
end |
||||||
|
end) |
||||||
|
|
||||||
|
-- Function to check if auto-attacking |
||||||
|
local function IsAutoAttacking() |
||||||
|
return GetTime() - lastAutoAttackTime < 2 |
||||||
|
end |
||||||
|
|
||||||
|
-- Function to check if we're in an aggressive damage phase |
||||||
|
local function AggressiveDamagePhase() |
||||||
|
return Player:GetAuras():FindMy(AvengingWrath):IsUp() or |
||||||
|
Player:GetPower(HOLY_POWER) >= 4 or |
||||||
|
(Player:GetPartyHPAround(40, 90) == 0 and Player:GetHP() > 80) |
||||||
|
end |
||||||
|
|
||||||
|
-- Healing APL |
||||||
|
HealingAPL:AddSpell( |
||||||
|
BeaconOfVirtue:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and |
||||||
|
ShouldCastBeaconOfVirtue() and |
||||||
|
Player:GetPower(HOLY_POWER) >= 3 and |
||||||
|
not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(Lowest):OnCast(function() |
||||||
|
WordOfGlory:ForceCast(Lowest) |
||||||
|
end) |
||||||
|
) |
||||||
|
|
||||||
|
HealingAPL:AddSpell( |
||||||
|
HolyPrism:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and HealingNeeded() |
||||||
|
end):SetTarget(Lowest) |
||||||
|
) |
||||||
|
|
||||||
|
HealingAPL:AddSpell( |
||||||
|
WordOfGlory:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Player:GetPower(HOLY_POWER) >= 3 and HealingNeeded() |
||||||
|
end):SetTarget(Lowest) |
||||||
|
) |
||||||
|
|
||||||
|
HealingAPL:AddSpell( |
||||||
|
HolyShock:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and HealingNeeded() |
||||||
|
end):SetTarget(Lowest) |
||||||
|
) |
||||||
|
|
||||||
|
HealingAPL:AddSpell( |
||||||
|
LightOfDawn:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Player:GetPower(HOLY_POWER) >= 3 and Player:GetPartyHPAround(15, healingThreshold) >= 3 |
||||||
|
end):SetTarget(Player) |
||||||
|
) |
||||||
|
|
||||||
|
HealingAPL:AddSpell( |
||||||
|
FlashOfLight:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and (Player:GetAuras():FindMy(InfusionOfLightBuff):IsUp() or EmergencyHealingNeeded()) |
||||||
|
end):SetTarget(Lowest) |
||||||
|
) |
||||||
|
|
||||||
|
HealingAPL:AddSpell( |
||||||
|
HolyLight:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Player:GetAuras():FindMy(DivineFavorBuff):IsUp() and HealingNeeded() |
||||||
|
end):SetTarget(Lowest) |
||||||
|
) |
||||||
|
|
||||||
|
-- Damage APL |
||||||
|
DamageAPL:AddSpell( |
||||||
|
AutoAttack:CastableIf(function(self) |
||||||
|
return BestTarget:Exists() and not IsAutoAttacking() and Player:CanSee(BestTarget) and Player:IsWithinCombatDistance(BestTarget, 5) |
||||||
|
end):SetTarget(BestTarget):OnCast(function() |
||||||
|
lastAutoAttackTime = GetTime() |
||||||
|
end) |
||||||
|
) |
||||||
|
|
||||||
|
DamageAPL:AddSpell( |
||||||
|
Judgment:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and Player:IsWithinCombatDistance(BestTarget, 30) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(BestTarget) |
||||||
|
) |
||||||
|
|
||||||
|
DamageAPL:AddSpell( |
||||||
|
HolyPrism:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and Player:IsWithinCombatDistance(BestTarget, 30) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(BestTarget) |
||||||
|
) |
||||||
|
|
||||||
|
DamageAPL:AddSpell( |
||||||
|
CrusaderStrike:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and IsInMeleeRange(BestTarget) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(BestTarget) |
||||||
|
) |
||||||
|
|
||||||
|
-- Execute APL |
||||||
|
ExecuteAPL:AddSpell( |
||||||
|
HammerOfWrath:CastableIf(function(self) |
||||||
|
return ExecuteTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(ExecuteTarget) |
||||||
|
) |
||||||
|
|
||||||
|
-- Cooldown APL |
||||||
|
CooldownAPL:AddSpell( |
||||||
|
AvengingWrath:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Player:GetPartyHPAround(40, 75) >= 3 |
||||||
|
end):SetTarget(Player) |
||||||
|
) |
||||||
|
|
||||||
|
CooldownAPL:AddSpell( |
||||||
|
BlessingOfSummer:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and Player:IsWithinCombatDistance(BestTarget, 30) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(Player) |
||||||
|
) |
||||||
|
|
||||||
|
CooldownAPL:AddSpell( |
||||||
|
SacredWeapon:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and Player:IsWithinCombatDistance(BestTarget, 30) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(Player) |
||||||
|
) |
||||||
|
|
||||||
|
CooldownAPL:AddSpell( |
||||||
|
Consecration:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and |
||||||
|
not Player:GetAuras():FindMy(ConsecrationBuff):IsUp() and |
||||||
|
BestTarget:Exists() and |
||||||
|
Player:IsWithinCombatDistance(BestTarget, 10) and |
||||||
|
not Player:IsMoving() and |
||||||
|
not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(Player) |
||||||
|
) |
||||||
|
|
||||||
|
-- Defensive APL |
||||||
|
DefensiveAPL:AddSpell( |
||||||
|
DivineShield:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Player:GetHP() < 20 |
||||||
|
end):SetTarget(Player) |
||||||
|
) |
||||||
|
|
||||||
|
DefensiveAPL:AddSpell( |
||||||
|
LayOnHands:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Lowest:GetHP() < 10 |
||||||
|
end):SetTarget(Lowest) |
||||||
|
) |
||||||
|
|
||||||
|
DefensiveAPL:AddSpell( |
||||||
|
BlessingOfProtection:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Lowest:GetHP() < 30 and not Lowest:IsTank() |
||||||
|
end):SetTarget(Lowest) |
||||||
|
) |
||||||
|
|
||||||
|
DefensiveAPL:AddSpell( |
||||||
|
BlessingOfSacrifice:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and Tank:GetHP() < 50 and Player:GetHP() > 50 |
||||||
|
end):SetTarget(Tank) |
||||||
|
) |
||||||
|
|
||||||
|
-- Damage Priority APL |
||||||
|
DamagePriorityAPL:AddSpell( |
||||||
|
Judgment:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and Player:IsWithinCombatDistance(BestTarget, 30) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(BestTarget) |
||||||
|
) |
||||||
|
|
||||||
|
DamagePriorityAPL:AddSpell( |
||||||
|
HolyShock:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and Player:IsWithinCombatDistance(BestTarget, 40) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(BestTarget) |
||||||
|
) |
||||||
|
|
||||||
|
DamagePriorityAPL:AddSpell( |
||||||
|
CrusaderStrike:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and IsInMeleeRange(BestTarget) and not Player:IsCastingOrChanneling() |
||||||
|
end):SetTarget(BestTarget) |
||||||
|
) |
||||||
|
|
||||||
|
DamagePriorityAPL:AddSpell( |
||||||
|
ShieldOfTheRighteous:CastableIf(function(self) |
||||||
|
return self:IsKnownAndUsable() and BestTarget:Exists() and IsInMeleeRange(BestTarget) and not Player:IsCastingOrChanneling() and Player:GetPower(HOLY_POWER) >= 3 and not HealingNeeded() |
||||||
|
end):SetTarget(BestTarget) |
||||||
|
) |
||||||
|
|
||||||
|
-- Default APL |
||||||
|
DefaultAPL:AddAPL(DefensiveAPL, function() return true end) |
||||||
|
DefaultAPL:AddAPL(CooldownAPL, function() return true end) |
||||||
|
DefaultAPL:AddAPL(HealingAPL, function() return HealingNeeded() end) |
||||||
|
DefaultAPL:AddAPL(ExecuteAPL, function() return true end) |
||||||
|
DefaultAPL:AddAPL(DamagePriorityAPL, function() return not HealingNeeded() and AggressiveDamagePhase() end) |
||||||
|
DefaultAPL:AddAPL(DamageAPL, function() return not HealingNeeded() end) |
||||||
|
|
||||||
|
HolyPaladinModule:Sync(function() |
||||||
|
if Player:IsAffectingCombat() then |
||||||
|
healingThreshold = AggressiveDamagePhase() and 85 or 90 |
||||||
|
DefaultAPL:Execute() |
||||||
|
else |
||||||
|
healingThreshold = 100 |
||||||
|
if AnyoneNeedsHealing() then |
||||||
|
HealingAPL:Execute() |
||||||
|
end |
||||||
|
end |
||||||
|
end) |
||||||
|
|
||||||
|
Bastion:Register(HolyPaladinModule) |
Loading…
Reference in new issue