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