mirror of
https://github.com/parnic/ice-hud.git
synced 2025-06-16 06:40:13 -05:00
511 lines
14 KiB
Lua
511 lines
14 KiB
Lua
local L = LibStub("AceLocale-3.0"):GetLocale("IceHUD", false)
|
|
local RollTheBones = IceCore_CreateClass(IceUnitBar)
|
|
|
|
local IceHUD = _G.IceHUD
|
|
|
|
local baseTime = 12
|
|
local gapPerComboPoint = 6
|
|
local maxComboPoints = 5
|
|
local rtbEndTime = 0
|
|
local rtbDuration = 0
|
|
local rtbCount = 0
|
|
local sixComboPointsTalentID = 19240
|
|
local behaviorDependsOnComboPoints = IceHUD.WowVer < 90000
|
|
|
|
local CurrMaxRtBDuration = 0
|
|
local PotentialRtBDuration = 0
|
|
|
|
local RtBBuffs = {199603, 193358, 193357, 193359, 199600, 193356}
|
|
local RtBSet = {}
|
|
for _, v in ipairs(RtBBuffs) do
|
|
RtBSet[v] = true
|
|
end
|
|
|
|
local SPELL_POWER_COMBO_POINTS = SPELL_POWER_COMBO_POINTS
|
|
if Enum and Enum.PowerType then
|
|
SPELL_POWER_COMBO_POINTS = Enum.PowerType.ComboPoints
|
|
end
|
|
|
|
local GetSpellInfo = GetSpellInfo
|
|
if not GetSpellInfo and C_Spell and C_Spell.GetSpellInfo then
|
|
GetSpellInfo = function(spellID)
|
|
if not spellID then
|
|
return nil
|
|
end
|
|
|
|
local spellInfo = C_Spell.GetSpellInfo(spellID)
|
|
if spellInfo then
|
|
return spellInfo.name, nil, spellInfo.iconID, spellInfo.castTime, spellInfo.minRange, spellInfo.maxRange, spellInfo.spellID, spellInfo.originalIconID
|
|
end
|
|
end
|
|
end
|
|
|
|
local GetSpellName = GetSpellInfo
|
|
if C_Spell and C_Spell.GetSpellName then
|
|
GetSpellName = C_Spell.GetSpellName
|
|
end
|
|
|
|
local UnitBuff = UnitBuff
|
|
if not UnitBuff and C_UnitAuras and AuraUtil then
|
|
UnitBuff = function(unitToken, index, filter)
|
|
local auraData = C_UnitAuras.GetBuffDataByIndex(unitToken, index, filter)
|
|
if not auraData then
|
|
return nil
|
|
end
|
|
|
|
return AuraUtil.UnpackAuraData(auraData)
|
|
end
|
|
end
|
|
|
|
-- Constructor --
|
|
function RollTheBones.prototype:init()
|
|
RollTheBones.super.prototype.init(self, "RollTheBones", "player")
|
|
|
|
self.moduleSettings = {}
|
|
self.moduleSettings.desiredLerpTime = 0
|
|
self.moduleSettings.shouldAnimate = false
|
|
|
|
self:SetDefaultColor("RollTheBones", 1, 0.6, 0.2)
|
|
if behaviorDependsOnComboPoints then
|
|
self:SetDefaultColor("RollTheBones2", 0.75, 1, 0.2)
|
|
self:SetDefaultColor("RollTheBones3", 0.4, 1, 0.2)
|
|
self:SetDefaultColor("RollTheBones4", 0.4, 1, 0.2)
|
|
self:SetDefaultColor("RollTheBones5", 0.1, 1, 0.7)
|
|
self:SetDefaultColor("RollTheBones6", 0.1, 1, 0.7)
|
|
self:SetDefaultColor("RollTheBonesPotential", 1, 1, 1)
|
|
end
|
|
|
|
self.bTreatEmptyAsFull = true
|
|
end
|
|
|
|
-- 'Public' methods -----------------------------------------------------------
|
|
|
|
-- OVERRIDE
|
|
function RollTheBones.prototype:Enable(core)
|
|
RollTheBones.super.prototype.Enable(self, core)
|
|
|
|
self:RegisterEvent("UNIT_AURA", "UpdateRollTheBones")
|
|
|
|
if behaviorDependsOnComboPoints then
|
|
self:RegisterEvent(IceHUD.UnitPowerEvent, "ComboPointsChanged")
|
|
end
|
|
|
|
if not self.moduleSettings.alwaysFullAlpha then
|
|
self:Show(false)
|
|
else
|
|
self:UpdateRollTheBones()
|
|
end
|
|
|
|
self:SetBottomText1("")
|
|
end
|
|
|
|
function RollTheBones.prototype:Disable(core)
|
|
RollTheBones.super.prototype.Disable(self, core)
|
|
end
|
|
|
|
function RollTheBones.prototype:ComboPointsChanged(...)
|
|
if select('#', ...) >= 3 and select(1, ...) == IceHUD.UnitPowerEvent and select(3, ...) ~= "COMBO_POINTS" then
|
|
return
|
|
end
|
|
|
|
self:TargetChanged()
|
|
self:UpdateDurationBar()
|
|
end
|
|
|
|
-- OVERRIDE
|
|
function RollTheBones.prototype:GetDefaultSettings()
|
|
local settings = RollTheBones.super.prototype.GetDefaultSettings(self)
|
|
|
|
settings["enabled"] = false
|
|
settings["shouldAnimate"] = false
|
|
settings["desiredLerpTime"] = nil
|
|
settings["lowThreshold"] = 0
|
|
settings["side"] = IceCore.Side.Right
|
|
settings["offset"] = 6
|
|
settings["upperText"]="RtB:"
|
|
settings["showAsPercentOfMax"] = true
|
|
settings["durationAlpha"] = 0.6
|
|
settings["usesDogTagStrings"] = false
|
|
settings["lockLowerFontAlpha"] = false
|
|
settings["lowerTextString"] = ""
|
|
settings["lowerTextVisible"] = false
|
|
settings["hideAnimationSettings"] = true
|
|
settings["bAllowExpand"] = true
|
|
settings["bShowWithNoTarget"] = true
|
|
settings["bUseMultipleBuffColors"] = true
|
|
|
|
return settings
|
|
end
|
|
|
|
-- OVERRIDE
|
|
function RollTheBones.prototype:GetOptions()
|
|
local opts = RollTheBones.super.prototype.GetOptions(self)
|
|
|
|
opts["textSettings"].args["upperTextString"]["desc"] = "The text to display under this bar. # will be replaced with the number of Roll the Bones seconds remaining."
|
|
opts["textSettings"].args["upperTextString"].hidden = false
|
|
|
|
if behaviorDependsOnComboPoints then
|
|
opts["showAsPercentOfMax"] =
|
|
{
|
|
type = 'toggle',
|
|
name = L["Show bar as % of maximum"],
|
|
desc = L["If this is checked, then the RtB buff time shows as a percent of the maximum attainable (taking set bonuses and talents into account). Otherwise, the bar always goes from full to empty when applying RtB no matter the duration."],
|
|
get = function()
|
|
return self.moduleSettings.showAsPercentOfMax
|
|
end,
|
|
set = function(info, v)
|
|
self.moduleSettings.showAsPercentOfMax = v
|
|
end,
|
|
disabled = function()
|
|
return not self.moduleSettings.enabled
|
|
end
|
|
}
|
|
|
|
opts["durationAlpha"] =
|
|
{
|
|
type = "range",
|
|
name = L["Potential RtB time bar alpha"],
|
|
desc = L["What alpha value to use for the bar that displays how long your RtB will last if you activate it. (This gets multiplied by the bar's current alpha to stay in line with the bar on top of it)"],
|
|
min = 0,
|
|
max = 100,
|
|
step = 5,
|
|
get = function()
|
|
return self.moduleSettings.durationAlpha * 100
|
|
end,
|
|
set = function(info, v)
|
|
self.moduleSettings.durationAlpha = v / 100.0
|
|
self:Redraw()
|
|
end,
|
|
disabled = function()
|
|
return not self.moduleSettings.enabled
|
|
end
|
|
}
|
|
|
|
opts["bUseMultipleBuffColors"] =
|
|
{
|
|
type = 'toggle',
|
|
name = L["Use multiple buff colors"],
|
|
desc = L["If this is checked, then the bar uses different colors depending on how many RtB buffs you have"],
|
|
get = function()
|
|
return self.moduleSettings.bUseMultipleBuffColors
|
|
end,
|
|
set = function(info, v)
|
|
self.moduleSettings.bUseMultipleBuffColors = v
|
|
self:Redraw()
|
|
end,
|
|
disabled = function()
|
|
return not self.moduleSettings.enabled
|
|
end,
|
|
}
|
|
end
|
|
|
|
opts["bShowWithNoTarget"] =
|
|
{
|
|
type = 'toggle',
|
|
name = L["Show with no target"],
|
|
desc = L["Whether or not to display when you have no target selected but have combo points available"],
|
|
get = function()
|
|
return self.moduleSettings.bShowWithNoTarget
|
|
end,
|
|
set = function(info, v)
|
|
self.moduleSettings.bShowWithNoTarget = v
|
|
self:ComboPointsChanged()
|
|
end,
|
|
disabled = function()
|
|
return not self.moduleSettings.enabled
|
|
end,
|
|
}
|
|
|
|
return opts
|
|
end
|
|
|
|
function RollTheBones.prototype:CreateFrame()
|
|
RollTheBones.super.prototype.CreateFrame(self)
|
|
|
|
self:CreateDurationBar()
|
|
end
|
|
|
|
function RollTheBones.prototype:CreateDurationBar()
|
|
if not behaviorDependsOnComboPoints then
|
|
return
|
|
end
|
|
|
|
self.durationFrame = self:BarFactory(self.durationFrame, "BACKGROUND","ARTWORK", "Duration")
|
|
|
|
-- Rokiyo: Do we need to call this here?
|
|
self.CurrScale = 0
|
|
|
|
self.durationFrame.bar:SetVertexColor(self:GetColor("RollTheBonesPotential", self.moduleSettings.durationAlpha))
|
|
self.durationFrame.bar:SetHeight(0)
|
|
|
|
self:UpdateBar(1, "undef")
|
|
|
|
-- force update the bar...if we're in here, then either the UI was just loaded or the player is jacking with the options.
|
|
-- either way, make sure the duration bar matches accordingly
|
|
self:UpdateDurationBar()
|
|
end
|
|
|
|
function RollTheBones.prototype:RotateHorizontal()
|
|
RollTheBones.super.prototype.RotateHorizontal(self)
|
|
|
|
if self.durationFrame then
|
|
self:RotateFrame(self.durationFrame)
|
|
end
|
|
end
|
|
|
|
function RollTheBones.prototype:ResetRotation()
|
|
RollTheBones.super.prototype.ResetRotation(self)
|
|
|
|
if self.durationFrame and self.durationFrame.anim then
|
|
self.durationFrame.anim:Stop()
|
|
end
|
|
end
|
|
|
|
-- 'Protected' methods --------------------------------------------------------
|
|
|
|
function RollTheBones.prototype:GetBuffDuration(unitName, ids)
|
|
local i = 1
|
|
local buff, _, type, duration, endTime, spellId
|
|
if IceHUD.SpellFunctionsReturnRank then
|
|
buff, _, _, _, type, duration, endTime, _, _, _, spellId = UnitBuff(unitName, i)
|
|
else
|
|
buff, _, _, type, duration, endTime, _, _, _, spellId = UnitBuff(unitName, i)
|
|
end
|
|
|
|
local realDuration, remaining, count
|
|
local now = GetTime()
|
|
|
|
count = 0
|
|
while buff do
|
|
if (spellId and ids[spellId]) then
|
|
if endTime then
|
|
realDuration = duration
|
|
remaining = endTime - now
|
|
count = count + 1
|
|
end
|
|
end
|
|
|
|
i = i + 1;
|
|
|
|
if IceHUD.SpellFunctionsReturnRank then
|
|
buff, _, _, _, type, duration, endTime, _, _, _, spellId = UnitBuff(unitName, i)
|
|
else
|
|
buff, _, _, type, duration, endTime, _, _, _, spellId = UnitBuff(unitName, i)
|
|
end
|
|
|
|
end
|
|
|
|
if count > 0 then
|
|
return realDuration, remaining, count
|
|
else
|
|
return nil, nil, 0
|
|
end
|
|
end
|
|
|
|
function RollTheBones.prototype:MyOnUpdate()
|
|
RollTheBones.super.prototype.MyOnUpdate(self)
|
|
if self.bUpdateRtb then
|
|
self:UpdateRollTheBones("internal", self.unit)
|
|
end
|
|
if self.target or self.moduleSettings.bShowWithNoTarget then
|
|
self:UpdateDurationBar()
|
|
end
|
|
end
|
|
|
|
local function RTBGetComboPoints(unit)
|
|
return UnitPower(unit, SPELL_POWER_COMBO_POINTS)
|
|
end
|
|
|
|
-- use this to figure out if Roll the Bones is available or not. neither IsSpellKnown nor IsPlayerSpell are correct for it
|
|
-- when SnD is known, but this is.
|
|
local function HasSpell(id)
|
|
local spell = GetSpellName(id)
|
|
return spell == GetSpellName(spell)
|
|
end
|
|
|
|
local function ShouldHide()
|
|
return not HasSpell(193316)
|
|
end
|
|
|
|
function RollTheBones.prototype:UpdateRollTheBones(event, unit)
|
|
if unit and unit ~= self.unit then
|
|
return
|
|
end
|
|
|
|
local now = GetTime()
|
|
local remaining = nil
|
|
local fromUpdate = event == "internal"
|
|
|
|
if not fromUpdate then
|
|
rtbDuration, remaining, rtbCount = self:GetBuffDuration(self.unit, RtBSet)
|
|
|
|
if not remaining then
|
|
rtbEndTime = 0
|
|
else
|
|
rtbEndTime = remaining + now
|
|
end
|
|
end
|
|
|
|
if rtbEndTime and rtbEndTime >= now then
|
|
if not fromUpdate then
|
|
self.bUpdateRtb = true
|
|
end
|
|
|
|
self:Show(true)
|
|
if not remaining then
|
|
remaining = rtbEndTime - now
|
|
end
|
|
local denominator = ((self.moduleSettings.showAsPercentOfMax and behaviorDependsOnComboPoints) and CurrMaxRtBDuration or rtbDuration)
|
|
self:UpdateBar(denominator ~= 0 and remaining / denominator or 0, self:GetColorName(rtbCount))
|
|
else
|
|
self:UpdateBar(0, "RollTheBones")
|
|
|
|
if RTBGetComboPoints(self.unit) == 0 or (not UnitExists("target") and not self.moduleSettings.bShowWithNoTarget) or ShouldHide() then
|
|
if self.bIsVisible then
|
|
self.bUpdateRtb = nil
|
|
end
|
|
|
|
if not self.moduleSettings.alwaysFullAlpha or ShouldHide() then
|
|
self:Show(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- somewhat redundant, but we also need to check potential remaining time
|
|
if (remaining ~= nil) or PotentialRtBDuration > 0 then
|
|
local potText = behaviorDependsOnComboPoints and " (" .. PotentialRtBDuration .. ")" or ""
|
|
self:SetBottomText1(self.moduleSettings.upperText .. tostring(floor(remaining or 0)) .. (self.moduleSettings.durationAlpha ~= 0 and potText or ""))
|
|
end
|
|
end
|
|
|
|
function RollTheBones.prototype:GetColorName(count)
|
|
if behaviorDependsOnComboPoints and self.moduleSettings.bUseMultipleBuffColors and count >= 2 then
|
|
return "RollTheBones"..count
|
|
else
|
|
return "RollTheBones"
|
|
end
|
|
end
|
|
|
|
function RollTheBones.prototype:TargetChanged()
|
|
if self.moduleSettings.bShowWithNoTarget and RTBGetComboPoints(self.unit) > 0 then
|
|
self.target = true
|
|
else
|
|
self.target = UnitExists("target")
|
|
end
|
|
self:Update(self.unit)
|
|
|
|
self:UpdateDurationBar()
|
|
self:UpdateRollTheBones()
|
|
end
|
|
|
|
function RollTheBones.prototype:UpdateDurationBar(event, unit)
|
|
if not self.durationFrame then
|
|
return
|
|
end
|
|
|
|
if unit and unit ~= self.unit then
|
|
return
|
|
end
|
|
|
|
local points = RTBGetComboPoints(self.unit)
|
|
if UnitPowerMax then
|
|
CurrMaxRtBDuration = self:GetMaxBuffTime(UnitPowerMax(self.unit, SPELL_POWER_COMBO_POINTS))
|
|
else
|
|
-- check for Deeper Stratagem
|
|
local _, _, _, DeeperStratagem = GetTalentInfoByID(sixComboPointsTalentID, GetActiveSpecGroup())
|
|
|
|
if DeeperStratagem then
|
|
-- first, set the cached upper limit of RtB duration
|
|
CurrMaxRtBDuration = self:GetMaxBuffTime(maxComboPoints + 1)
|
|
else
|
|
CurrMaxRtBDuration = self:GetMaxBuffTime(maxComboPoints)
|
|
end
|
|
end
|
|
|
|
if event then
|
|
self:UpdateRollTheBones()
|
|
end
|
|
|
|
-- player doesn't want to show the percent of max or the alpha is zeroed out, so don't bother with the duration bar
|
|
if not self.moduleSettings.showAsPercentOfMax or self.moduleSettings.durationAlpha == 0 or (points == 0 and not self:IsVisible())
|
|
or ShouldHide() then
|
|
self.durationFrame:Hide()
|
|
return
|
|
end
|
|
self.durationFrame:Show()
|
|
|
|
-- if we have combo points and a target selected, go ahead and show the bar so the duration bar can be seen
|
|
if points > 0 and (UnitExists("target") or self.moduleSettings.bShowWithNoTarget) then
|
|
self:Show(true)
|
|
end
|
|
|
|
if self.moduleSettings.durationAlpha > 0 then
|
|
PotentialRtBDuration = self:GetMaxBuffTime(points)
|
|
|
|
-- compute the scale from the current number of combo points
|
|
local scale = IceHUD:Clamp(PotentialRtBDuration / CurrMaxRtBDuration, 0, 1)
|
|
|
|
-- sadly, animation uses bar-local variables so we can't use the animation for 2 bar textures on the same bar element
|
|
if (self.moduleSettings.reverse) then
|
|
scale = 1 - scale
|
|
end
|
|
|
|
self.durationFrame.bar:SetVertexColor(self:GetColor("RollTheBonesPotential", self.moduleSettings.durationAlpha))
|
|
self:SetBarCoord(self.durationFrame, scale)
|
|
end
|
|
|
|
if rtbEndTime < GetTime() then
|
|
local potText = " (" .. PotentialRtBDuration .. ")"
|
|
self:SetBottomText1(self.moduleSettings.upperText .. "0" .. (self.moduleSettings.durationAlpha > 0 and potText or ""))
|
|
end
|
|
end
|
|
|
|
function RollTheBones.prototype:GetMaxBuffTime(numComboPoints)
|
|
local maxduration
|
|
|
|
if numComboPoints == 0 then
|
|
return 0
|
|
end
|
|
|
|
maxduration = baseTime + ((numComboPoints - 1) * gapPerComboPoint)
|
|
|
|
return maxduration
|
|
end
|
|
|
|
function RollTheBones.prototype:GetItemIdFromItemLink(linkStr)
|
|
local itemId
|
|
local _
|
|
|
|
if linkStr then
|
|
_, itemId, itemId2, _, _, _, _, _, _ = strsplit(":", linkStr)
|
|
end
|
|
|
|
if not tonumber(itemId) then
|
|
itemId = itemId2
|
|
end
|
|
|
|
return itemId or 0
|
|
end
|
|
|
|
function RollTheBones.prototype:IsItemIdInList(itemId, list)
|
|
for i=1,#list do
|
|
if string.match(itemId, list[i]) then
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function RollTheBones.prototype:OutCombat()
|
|
RollTheBones.super.prototype.OutCombat(self)
|
|
|
|
self:UpdateRollTheBones()
|
|
end
|
|
|
|
local _, unitClass = UnitClass("player")
|
|
-- Load us up
|
|
if unitClass == "ROGUE" and IceHUD.WowVer >= 70000 then
|
|
IceHUD.RollTheBones = RollTheBones:new()
|
|
end
|