You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
8.3 KiB
248 lines
8.3 KiB
--- ============================ HEADER ============================
|
|
--- ======= LOCALIZE =======
|
|
-- Addon
|
|
local addonName, HR = ...;
|
|
-- HeroLib
|
|
local HL = HeroLib;
|
|
local Cache, Utils = HeroCache, HL.Utils;
|
|
local Unit = HL.Unit;
|
|
local Player = Unit.Player;
|
|
local Target = Unit.Target;
|
|
local Spell = HL.Spell;
|
|
local Item = HL.Item;
|
|
-- Lua
|
|
local pairs = pairs;
|
|
local gsub = string.gsub;
|
|
-- API
|
|
local UnitInParty = UnitInParty
|
|
local UnitInRaid = UnitInRaid
|
|
-- File Locals
|
|
HR.Commons = {};
|
|
local Commons = {};
|
|
HR.Commons.Everyone = Commons;
|
|
local Settings = HR.GUISettings.General;
|
|
local AbilitySettings = HR.GUISettings.Abilities;
|
|
|
|
--- ============================ CONTENT ============================
|
|
-- Num/Bool helper functions
|
|
function Commons.num(val)
|
|
if val then return 1 else return 0 end
|
|
end
|
|
|
|
function Commons.bool(val)
|
|
return val ~= 0
|
|
end
|
|
|
|
-- Is the current target valid?
|
|
function Commons.TargetIsValid()
|
|
return Target:Exists() and Player:CanAttack(Target) and not Target:IsDeadOrGhost();
|
|
end
|
|
|
|
-- Is the current unit valid during cycle?
|
|
function Commons.UnitIsCycleValid(Unit, BestUnitTTD, TimeToDieOffset)
|
|
return not Unit:IsFacingBlacklisted() and not Unit:IsUserCycleBlacklisted() and (not BestUnitTTD or Unit:FilteredTimeToDie(">", BestUnitTTD, TimeToDieOffset));
|
|
end
|
|
|
|
-- Is it worth to DoT the unit?
|
|
function Commons.CanDoTUnit(Unit, HealthThreshold)
|
|
return Unit:Health() >= HealthThreshold or Unit:IsDummy();
|
|
end
|
|
|
|
-- Interrupt
|
|
function Commons.Interrupt(Range, Spell, Setting, StunSpells)
|
|
if Settings.InterruptEnabled and Target:IsInterruptible() and Target:IsInRange(Range) then
|
|
if Spell:IsCastable(true) then
|
|
if HR.Cast(Spell, Setting) then return "Cast " .. Spell:Name() .. " (Interrupt)"; end
|
|
elseif Settings.InterruptWithStun and Target:CanBeStunned() then
|
|
if StunSpells then
|
|
for i = 1, #StunSpells do
|
|
if StunSpells[i][1]:IsCastable() and StunSpells[i][3]() then
|
|
if HR.Cast(StunSpells[i][1]) then return StunSpells[i][2]; end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Is in Solo Mode?
|
|
function Commons.IsSoloMode()
|
|
return Settings.SoloMode and not Player:IsInRaidArea() and not Player:IsInDungeonArea();
|
|
end
|
|
|
|
-- Cycle Unit Helper
|
|
function Commons.CastCycle(Object, Enemies, Condition, OutofRange, OffGCD, DisplayStyle)
|
|
if Condition(Target) then
|
|
return HR.Cast(Object, OffGCD, DisplayStyle, OutofRange)
|
|
end
|
|
if HR.AoEON() then
|
|
local TargetGUID = Target:GUID()
|
|
for _, CycleUnit in pairs(Enemies) do
|
|
if CycleUnit:GUID() ~= TargetGUID and not CycleUnit:IsFacingBlacklisted() and not CycleUnit:IsUserCycleBlacklisted() and Condition(CycleUnit) then
|
|
HR.CastLeftNameplate(CycleUnit, Object)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Target If Helper
|
|
function Commons.CastTargetIf(Object, Enemies, TargetIfMode, TargetIfCondition, Condition, OutofRange, OffGCD, DisplayStyle)
|
|
local TargetCondition = (not Condition or (Condition and Condition(Target)))
|
|
if not HR.AoEON() and TargetCondition then
|
|
return HR.Cast(Object, OffGCD, DisplayStyle, OutofRange)
|
|
end
|
|
if HR.AoEON() then
|
|
local BestUnit, BestConditionValue = nil, nil
|
|
for _, CycleUnit in pairs(Enemies) do
|
|
if not CycleUnit:IsFacingBlacklisted() and not CycleUnit:IsUserCycleBlacklisted() and (CycleUnit:AffectingCombat() or CycleUnit:IsDummy())
|
|
and (not BestConditionValue or Utils.CompareThis(TargetIfMode, TargetIfCondition(CycleUnit), BestConditionValue)) then
|
|
BestUnit, BestConditionValue = CycleUnit, TargetIfCondition(CycleUnit)
|
|
end
|
|
end
|
|
if BestUnit then
|
|
if TargetCondition and (BestUnit:GUID() == Target:GUID() or BestConditionValue == TargetIfCondition(Target)) then
|
|
return HR.Cast(Object, OffGCD, DisplayStyle, OutofRange)
|
|
elseif ((Condition and Condition(BestUnit)) or not Condition) then
|
|
HR.CastLeftNameplate(BestUnit, Object)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Commons.GroupBuffMissing(spell)
|
|
local range = 40
|
|
local buffIDs = { 381732, 381741, 381746, 381748, 381749, 381750, 381751, 381752, 381753, 381754, 381756, 381757, 381758 }
|
|
if spell:Name() == "Battle Shout" then range = 100 end
|
|
local Group
|
|
if UnitInRaid("player") then
|
|
Group = Unit.Raid
|
|
elseif UnitInParty("player") then
|
|
Group = Unit.Party
|
|
else
|
|
return false
|
|
end
|
|
for _, Char in pairs(Group) do
|
|
if spell:Name() == "Blessing of the Bronze" then
|
|
if Char:Exists() and Char:IsInRange(range) then
|
|
for _, v in pairs(buffIDs) do
|
|
if Char:BuffUp(HL.Spell(v), true) then return false end
|
|
end
|
|
return true
|
|
end
|
|
else
|
|
if Char:Exists() and Char:IsInRange(range) and Char:BuffDown(spell, true) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function Commons.GetCurrentEmpowerData(stage)
|
|
local CurrentStage = 0
|
|
local StagesData = {}
|
|
_, _, _, StartTimeMS, EndTimeMS, _, _, _, _, StageTotal = UnitChannelInfo("player")
|
|
|
|
if StageTotal and StageTotal > 0 then
|
|
local LastFinish = 0
|
|
for i = 1, StageTotal do
|
|
StagesData[i] = {
|
|
Start = LastFinish,
|
|
Finish = LastFinish + GetUnitEmpowerStageDuration("player", i - 1) / 1000
|
|
}
|
|
HR.Print(" Start"..i..": "..StagesData[i].Start)
|
|
HR.Print("Finish"..i..": "..StagesData[i].Finish)
|
|
LastFinish = StagesData[i].Finish
|
|
if StartTimeMS / 1000 + LastFinish <= GetTime() then
|
|
CurrentStage = i
|
|
end
|
|
end
|
|
end
|
|
|
|
if stage then
|
|
return CurrentStage
|
|
else
|
|
return StagesData
|
|
end
|
|
end
|
|
|
|
-- Check if player's selected potion type is ready
|
|
function Commons.PotionSelected()
|
|
local Classes = { "Warrior", "Paladin", "Hunter", "Rogue", "Priest", "DeathKnight", "Shaman", "Mage", "Warlock", "Monk", "Druid", "DemonHunter", "Evoker" }
|
|
local ClassNum = Cache.Persistent.Player.Class[3]
|
|
local Class = Classes[ClassNum]
|
|
|
|
local Specs = {
|
|
-- DeathKnight
|
|
[250] = "Blood", [251] = "Frost", [252] = "Unholy",
|
|
-- DemonHunter
|
|
[577] = "Havoc", [581] = "Vengeance",
|
|
-- Druid
|
|
[102] = "Balance", [103] = "Feral", [104] = "Guardian", [105] = "Restoration",
|
|
-- Evoker
|
|
[1467] = "Devastation", [1468] = "Preservation", [1473] = "Augmentation",
|
|
-- Hunter
|
|
[253] = "BeastMastery", [254] = "Marksmanship", [255] = "Survival",
|
|
-- Mage
|
|
[62] = "Arcane", [63] = "Fire", [64] = "Frost",
|
|
-- Monk
|
|
[268] = "Brewmaster", [269] = "Windwalker", [270] = "Mistweaver",
|
|
-- Paladin
|
|
[65] = "Holy", [66] = "Protection", [70] = "Retribution",
|
|
--Priest
|
|
[256] = "Discipline", [257] = "Holy", [258] = "Shadow",
|
|
-- Rogue
|
|
[259] = "Assassination", [260] = "Outlaw", [261] = "Subtlety",
|
|
-- Shaman
|
|
[262] = "Elemental", [263] = "Enhancement", [264] = "Restoration",
|
|
-- Warlock
|
|
[265] = "Affliction", [266] = "Demonology", [267] = "Destruction",
|
|
-- Warrior
|
|
[71] = "Arms", [72] = "Fury", [73] = "Protection",
|
|
}
|
|
local SpecNum = Cache.Persistent.Player.Spec[1]
|
|
local Spec = Specs[SpecNum]
|
|
|
|
local PotionType = HR.GUISettings.APL[Class][Spec].PotionType.Selected
|
|
local PowerPotionIDs = {
|
|
-- Fleeting Ultimate Power
|
|
191914, 191913, 191912,
|
|
-- Fleeting Power
|
|
191907, 191906, 191905,
|
|
-- Ultimate Power
|
|
191383, 191382, 191381,
|
|
-- Power
|
|
191389, 191388, 191387
|
|
}
|
|
local FrozenFocusIDs = { 191365, 191364, 191363 }
|
|
local ChilledClarityIDs = { 191368, 191367, 191366 }
|
|
local ShockingDisclosureIDs = { 191401, 191400, 191399 }
|
|
if PotionType == "Power" then
|
|
for _, PotionID in ipairs(PowerPotionIDs) do
|
|
if Item(PotionID):IsUsable() then
|
|
return Item(PotionID)
|
|
end
|
|
end
|
|
elseif PotionType == "Frozen Focus" then
|
|
for _, PotionID in ipairs(FrozenFocusIDs) do
|
|
if Item(PotionID):IsUsable() then
|
|
return Item(PotionID)
|
|
end
|
|
end
|
|
elseif PotionType == "Chilled Clarity" then
|
|
for _, PotionID in ipairs(ChilledClarityIDs) do
|
|
if Item(PotionID):IsUsable() then
|
|
return Item(PotionID)
|
|
end
|
|
end
|
|
elseif PotionType == "Shocking Disclosure" then
|
|
for _, PotionID in ipairs(ShockingDisclosureIDs) do
|
|
if Item(PotionID):IsUsable() then
|
|
return Item(PotionID)
|
|
end
|
|
end
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|