Files
ice-hud/modules/SliceAndDice.lua
rokiyo 286e413198 - Refactored how bars are created and resized.
- Enabled the "expand" bar fill for the PlayerHealth module.
2010-11-02 15:08:42 +00:00

420 lines
12 KiB
Lua

local L = LibStub("AceLocale-3.0"):GetLocale("IceHUD", false)
local SliceAndDice = IceCore_CreateClass(IceUnitBar)
local IceHUD = _G.IceHUD
local NetherbladeItemIdList = {29044, 29045, 29046, 29047, 29048}
-- Parnic - bah, have to abandon the more robust string representation of each slot because of loc issues...
local NetherbladeEquipLocList = {1, 3, 5, 7, 10} --"HeadSlot", "ShoulderSlot", "ChestSlot", "LegsSlot", "HandsSlot"}
local GlyphSpellId = 56810
local baseTime = 9
local gapPerComboPoint = 3
local netherbladeBonus = 3
local glyphBonusSec = 3
local impSndTalentPage = 2
local impSndTalentIdx = 4
local impSndBonusPerRank = 0.25
local maxComboPoints = 5
local sndEndTime = 0
local sndDuration = 0
local CurrMaxSnDDuration = 0
local PotentialSnDDuration = 0
-- Constructor --
function SliceAndDice.prototype:init()
SliceAndDice.super.prototype.init(self, "SliceAndDice", "player")
self.moduleSettings = {}
self.moduleSettings.desiredLerpTime = 0
self.moduleSettings.shouldAnimate = false
self:SetDefaultColor("SliceAndDice", 0.75, 1, 0.2)
self:SetDefaultColor("SliceAndDicePotential", 1, 1, 1)
self.bTreatEmptyAsFull = true
end
-- 'Public' methods -----------------------------------------------------------
-- OVERRIDE
function SliceAndDice.prototype:Enable(core)
SliceAndDice.super.prototype.Enable(self, core)
self:RegisterEvent("PLAYER_TARGET_CHANGED", "TargetChanged")
self:RegisterEvent("UNIT_AURA", "UpdateSliceAndDice")
self:RegisterEvent("UNIT_COMBO_POINTS", "UpdateDurationBar")
if not self.moduleSettings.alwaysFullAlpha then
self:Show(false)
else
self:UpdateSliceAndDice(nil, self.unit)
end
self:SetBottomText1("")
end
function SliceAndDice.prototype:TargetChanged()
self:UpdateDurationBar()
self:UpdateSliceAndDice()
end
function SliceAndDice.prototype:Disable(core)
SliceAndDice.super.prototype.Disable(self, core)
end
-- OVERRIDE
function SliceAndDice.prototype:GetDefaultSettings()
local settings = SliceAndDice.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"]="SnD:"
settings["showAsPercentOfMax"] = true
settings["durationAlpha"] = 0.6
settings["usesDogTagStrings"] = false
settings["lockLowerFontAlpha"] = false
settings["lowerTextString"] = ""
settings["lowerTextVisible"] = false
settings["hideAnimationSettings"] = true
settings["bAllowExpand"] = false
return settings
end
-- OVERRIDE
function SliceAndDice.prototype:GetOptions()
local opts = SliceAndDice.super.prototype.GetOptions(self)
opts["textSettings"].args["upperTextString"]["desc"] = "The text to display under this bar. # will be replaced with the number of Slice and Dice seconds remaining."
opts["showAsPercentOfMax"] =
{
type = 'toggle',
name = L["Show bar as % of maximum"],
desc = L["If this is checked, then the SnD 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 SnD 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 SnD time bar alpha"],
desc = L["What alpha value to use for the bar that displays how long your SnD 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
}
return opts
end
function SliceAndDice.prototype:CreateFrame()
SliceAndDice.super.prototype.CreateFrame(self)
self:CreateDurationBar()
end
function SliceAndDice.prototype:CreateDurationBar()
self.durationFrame = self:BarFactory(self.durationFrame, "BACKGROUND","ARTWORK")
-- Rokiyo: Do we need to call this here?
self.CurrScale = 0
self.durationFrame.bar:SetVertexColor(self:GetColor("SliceAndDicePotential", self.alpha * 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 SliceAndDice.prototype:RotateHorizontal()
SliceAndDice.super.prototype.RotateHorizontal(self)
self:RotateFrame(self.durationFrame)
end
function SliceAndDice.prototype:ResetRotation()
SliceAndDice.super.prototype.ResetRotation(self)
if self.durationFrame.anim then
self.durationFrame.anim:Stop()
end
end
-- 'Protected' methods --------------------------------------------------------
function SliceAndDice.prototype:GetBuffDuration(unitName, buffName)
local i = 1
local buff, rank, texture, count, type, duration, endTime, remaining
if IceHUD.WowVer >= 30000 then
buff, rank, texture, count, type, duration, endTime = UnitBuff(unitName, i)
else
buff, rank, texture, count, duration, remaining = UnitBuff(unitName, i)
end
while buff do
if (texture and string.match(texture, buffName)) then
if endTime and not remaining then
remaining = endTime - GetTime()
end
return duration, remaining
end
i = i + 1;
if IceHUD.WowVer >= 30000 then
buff, rank, texture, count, type, duration, endTime = UnitBuff(unitName, i)
else
buff, rank, texture, count, duration, remaining = UnitBuff(unitName, i)
end
end
return nil, nil
end
function SliceAndDice.prototype:MyOnUpdate()
SliceAndDice.super.prototype.MyOnUpdate(self)
if self.bUpdateSnd then
self:UpdateSliceAndDice(nil, self.unit, true)
end
end
function SliceAndDice.prototype:UpdateSliceAndDice(event, unit, fromUpdate)
if unit and unit ~= self.unit then
return
end
local now = GetTime()
local remaining = nil
if not fromUpdate or IceHUD.WowVer < 30000 then
sndDuration, remaining = self:GetBuffDuration(self.unit, "Ability_Rogue_SliceDice")
if not remaining then
sndEndTime = 0
else
sndEndTime = remaining + now
end
end
if sndEndTime and sndEndTime >= now then
if not fromUpdate then
self.bUpdateSnd = true
end
self:Show(true)
if not remaining then
remaining = sndEndTime - now
end
local denominator = (self.moduleSettings.showAsPercentOfMax and CurrMaxSnDDuration or sndDuration)
self:UpdateBar(denominator ~= 0 and remaining / denominator or 0, "SliceAndDice")
formatString = self.moduleSettings.upperText or ''
else
self:UpdateBar(0, "SliceAndDice")
if ((IceHUD.WowVer >= 30000 and GetComboPoints(self.unit, "target") == 0) or (IceHUD.WowVer < 30000 and GetComboPoints() == 0)) or not UnitExists("target") then
if self.bIsVisible then
self.bUpdateSnd = nil
end
if not self.moduleSettings.alwaysFullAlpha then
self:Show(false)
end
end
end
-- somewhat redundant, but we also need to check potential remaining time
if (remaining ~= nil) or PotentialSnDDuration > 0 then
self:SetBottomText1(self.moduleSettings.upperText .. tostring(floor(remaining or 0)) .. " (" .. PotentialSnDDuration .. ")")
end
end
function SliceAndDice.prototype:UpdateDurationBar(event, unit)
if unit and unit ~= self.unit then
return
end
local points
if IceHUD.WowVer >= 30000 then
points = GetComboPoints(self.unit, "target")
else
points = GetComboPoints("target")
end
local scale
-- first, set the cached upper limit of SnD duration
CurrMaxSnDDuration = self:GetMaxBuffTime(maxComboPoints)
-- 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 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") then
self:Show(true)
end
PotentialSnDDuration = self:GetMaxBuffTime(points)
-- compute the scale from the current number of combo points
scale = IceHUD:Clamp(PotentialSnDDuration / CurrMaxSnDDuration, 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
local min_y, max_y
if (self.moduleSettings.inverse == "INVERSE") then
min_y = 0
max_y = scale
else
min_y = 1-scale
max_y = 1
end
if (self.moduleSettings.side == IceCore.Side.Left) then
self.durationFrame.bar:SetTexCoord(1, 0, min_y, max_y)
else
self.durationFrame.bar:SetTexCoord(0, 1, min_y, max_y)
end
self.durationFrame:SetHeight(self.settings.barHeight * scale)
if scale == 0 then
self.durationFrame.bar:Hide()
else
self.durationFrame.bar:SetVertexColor(self:GetColor("SliceAndDicePotential", self.alpha * self.moduleSettings.durationAlpha))
self.durationFrame.bar:Show()
end
if sndEndTime < GetTime() then
self:SetBottomText1(self.moduleSettings.upperText .. "0 (" .. PotentialSnDDuration .. ")")
end
end
function SliceAndDice.prototype:GetMaxBuffTime(numComboPoints)
local maxduration
if numComboPoints == 0 then
return 0
end
maxduration = baseTime + ((numComboPoints - 1) * gapPerComboPoint)
if self:HasNetherbladeBonus() then
maxduration = maxduration + netherbladeBonus
end
if self:HasGlyphBonus() then
maxduration = maxduration + glyphBonusSec
end
_, _, _, _, rank = GetTalentInfo(impSndTalentPage, impSndTalentIdx)
maxduration = maxduration * (1 + (rank * impSndBonusPerRank))
return maxduration
end
function SliceAndDice.prototype:HasNetherbladeBonus()
local numPieces
local linkStr, itemId
numPieces = 0
-- run through all the possible equip locations of a netherblade piece
for i=1,#NetherbladeEquipLocList do
-- pull the link string for the item in this equip loc
linkStr = GetInventoryItemLink(self.unit, NetherbladeEquipLocList[i])
-- get the item id out of that link string
itemId = self:GetItemIdFromItemLink(linkStr)
-- check if the item id in that slot is part of the netherblade item id list
if self:IsItemIdInList(itemId, NetherbladeItemIdList) then
-- increment the fact that we have this piece of netherblade
numPieces = numPieces + 1
-- check if we've met the set bonus for slice and dice
if numPieces >= 2 then
return true
end
end
end
end
function SliceAndDice.prototype:HasGlyphBonus()
for i=1,GetNumGlyphSockets() do
local enabled, _, _, spell = GetGlyphSocketInfo(i)
if enabled and spell == GlyphSpellId then
return true
end
end
return false
end
function SliceAndDice.prototype:GetItemIdFromItemLink(linkStr)
local itemId
if linkStr then
_, itemId, _, _, _, _, _, _, _ = strsplit(":", linkStr)
end
return itemId or 0
end
function SliceAndDice.prototype:IsItemIdInList(itemId, list)
for i=1,#list do
if string.match(itemId, list[i]) then
return true
end
end
return false
end
function SliceAndDice.prototype:OutCombat()
SliceAndDice.super.prototype.OutCombat(self)
self:UpdateSliceAndDice()
end
local _, unitClass = UnitClass("player")
-- Load us up
if unitClass == "ROGUE" then
IceHUD.SliceAndDice = SliceAndDice:new()
end