WoWInterface SVN NeedToKnow-Updated

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /branches
    from Rev 86 to Rev 93
    Reverse comparison

Rev 86 → Rev 93

Kitjan/NeedToKnow/NeedToKnow.lua
1,11 → 1,32
-- ----------------------
-- ----------------------
-- NeedToKnow
-- by Kitjan, lieandswell
-- ----------------------
 
 
if not trace then trace = print end
 
--function maybe_trace(...)
--local so_far = ""
--local p = _G
--for idx = 1,40,1 do
--local v = select(idx,...)
--if not v then
--break
--end
--p = p[v]
--if not p then
--if so_far == "" then
--trace("global variable",v,"does not exist")
--else
--trace(so_far,"does not have member",v)
--end
--return;
--end
--so_far = so_far .. "." .. v
--end
--trace(so_far,"=",p)
--end
--
-- -------------
-- ADDON GLOBALS
-- -------------
15,13 → 36,14
 
-- NEEDTOKNOW = {} is defined in the localization file, which must be loaded before this file
 
NEEDTOKNOW.VERSION = "3.2.0"
NEEDTOKNOW.VERSION = "3.3.00"
NEEDTOKNOW.UPDATE_INTERVAL = 0.05
NEEDTOKNOW.MAXBARS = 20
 
-- Get the localized name of spell 75, which is "Auto Shot" in US English
NEEDTOKNOW.AUTO_SHOT = GetSpellInfo(75)
 
 
-- COMBAT_LOG_EVENT_UNFILTERED events where select(6,...) is the caster, 9 is the spellid, and 10 is the spell name
-- (used for Target-of-target monitoring)
NEEDTOKNOW.AURAEVENTS = {
62,6 → 84,7
blink_boss = false,
blink_label = "",
buffcd_duration = 0,
buffcd_reset_spells = "",
usable_duration = 0,
append_cd = true,
append_usable = false,
76,7 → 99,7
FixedDuration = nil,
}
NEEDTOKNOW.DEFAULTS = {
Version = NEEDTOKNOW.VERSION,
Version = NEEDTOKNOW.VERSION,
OldVersion = NEEDTOKNOW.VERSION,
Profiles = {},
Chars = {},
95,27 → 118,28
BarPadding = 3,
}
 
 
-- -------------------
-- SharedMedia Support
-- -------------------
 
NeedToKnow.LSM = LibStub("LibSharedMedia-3.0", true)
NeedToKnow.LSM = LibStub("LibSharedMedia-3.0", true)
 
if not NeedToKnow.LSM:Fetch("statusbar", "Aluminum", true) then NeedToKnow.LSM:Register("statusbar", "Aluminum", [[Interface\Addons\NeedToKnow\Textures\Aluminum.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Armory", true) then NeedToKnow.LSM:Register("statusbar", "Armory", [[Interface\Addons\NeedToKnow\Textures\Armory.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "BantoBar", true) then NeedToKnow.LSM:Register("statusbar", "BantoBar", [[Interface\Addons\NeedToKnow\Textures\BantoBar.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "DarkBottom", true) then NeedToKnow.LSM:Register("statusbar", "DarkBottom", [[Interface\Addons\NeedToKnow\Textures\Darkbottom.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Default", true) then NeedToKnow.LSM:Register("statusbar", "Default", [[Interface\Addons\NeedToKnow\Textures\Default.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Flat", true) then NeedToKnow.LSM:Register("statusbar", "Flat", [[Interface\Addons\NeedToKnow\Textures\Flat.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Glaze", true) then NeedToKnow.LSM:Register("statusbar", "Glaze", [[Interface\Addons\NeedToKnow\Textures\Glaze.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Gloss", true) then NeedToKnow.LSM:Register("statusbar", "Gloss", [[Interface\Addons\NeedToKnow\Textures\Gloss.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Graphite", true) then NeedToKnow.LSM:Register("statusbar", "Graphite", [[Interface\Addons\NeedToKnow\Textures\Graphite.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Minimalist", true) then NeedToKnow.LSM:Register("statusbar", "Minimalist", [[Interface\Addons\NeedToKnow\Textures\Minimalist.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Otravi", true) then NeedToKnow.LSM:Register("statusbar", "Otravi", [[Interface\Addons\NeedToKnow\Textures\Otravi.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Smooth", true) then NeedToKnow.LSM:Register("statusbar", "Smooth", [[Interface\Addons\NeedToKnow\Textures\Smooth.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Smooth v2", true) then NeedToKnow.LSM:Register("statusbar", "Smooth v2", [[Interface\Addons\NeedToKnow\Textures\Smoothv2.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Striped", true) then NeedToKnow.LSM:Register("statusbar", "Striped", [[Interface\Addons\NeedToKnow\Textures\Striped.tga]]) end
 
if not NeedToKnow.LSM:Fetch("statusbar", "Aluminum", true) then NeedToKnow.LSM:Register("statusbar", "Aluminum", [[Interface\Addons\NeedToKnow\Textures\Aluminum.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Armory", true) then NeedToKnow.LSM:Register("statusbar", "Armory", [[Interface\Addons\NeedToKnow\Textures\Armory.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "BantoBar", true) then NeedToKnow.LSM:Register("statusbar", "BantoBar", [[Interface\Addons\NeedToKnow\Textures\BantoBar.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "DarkBottom", true) then NeedToKnow.LSM:Register("statusbar", "DarkBottom", [[Interface\Addons\NeedToKnow\Textures\Darkbottom.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Default", true) then NeedToKnow.LSM:Register("statusbar", "Default", [[Interface\Addons\NeedToKnow\Textures\Default.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Flat", true) then NeedToKnow.LSM:Register("statusbar", "Flat", [[Interface\Addons\NeedToKnow\Textures\Flat.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Glaze", true) then NeedToKnow.LSM:Register("statusbar", "Glaze", [[Interface\Addons\NeedToKnow\Textures\Glaze.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Gloss", true) then NeedToKnow.LSM:Register("statusbar", "Gloss", [[Interface\Addons\NeedToKnow\Textures\Gloss.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Graphite", true) then NeedToKnow.LSM:Register("statusbar", "Graphite", [[Interface\Addons\NeedToKnow\Textures\Graphite.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Minimalist", true) then NeedToKnow.LSM:Register("statusbar", "Minimalist", [[Interface\Addons\NeedToKnow\Textures\Minimalist.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Otravi", true) then NeedToKnow.LSM:Register("statusbar", "Otravi", [[Interface\Addons\NeedToKnow\Textures\Otravi.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Smooth", true) then NeedToKnow.LSM:Register("statusbar", "Smooth", [[Interface\Addons\NeedToKnow\Textures\Smooth.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Smooth v2", true) then NeedToKnow.LSM:Register("statusbar", "Smooth v2", [[Interface\Addons\NeedToKnow\Textures\Smoothv2.tga]]) end
if not NeedToKnow.LSM:Fetch("statusbar", "Striped", true) then NeedToKnow.LSM:Register("statusbar", "Striped", [[Interface\Addons\NeedToKnow\Textures\Striped.tga]]) end
 
-- ---------------
-- EXECUTIVE FRAME
-- ---------------
128,7 → 152,6
end
end
 
 
function NeedToKnow.ExecutiveFrame_UNIT_SPELLCAST_SUCCEEDED(unit, spell, rank)
if unit == "player" then
local r = NeedToKnow.last_cast[spell]
155,7 → 178,6
end
end
 
 
function NeedToKnow.ExecutiveFrame_COMBAT_LOG_EVENT_UNFILTERED(tod, event, guidCaster, ...)
-- the time that's passed in appears to be time of day, not game time like everything else.
local time = GetTime()
199,6 → 221,7
NeedToKnow.last_cast = {} -- [spell][guidTarget] = { time, dur }
NeedToKnow.nSent = 0
NeedToKnow.totem_drops = {} -- array 1-4 of precise times the totems appeared
NeedToKnow.weapon_enchants = { mhand = {}, ohand = {} }
 
SlashCmdList["NEEDTOKNOW"] = NeedToKnow.SlashCommand
SLASH_NEEDTOKNOW1 = "/needtoknow"
206,6 → 229,7
end
end
 
 
function NeedToKnow.ExecutiveFrame_PLAYER_LOGIN()
NeedToKnowLoader.SafeUpgrade()
NeedToKnow.ExecutiveFrame_PLAYER_TALENT_UPDATE()
224,20 → 248,25
NeedToKnow.ExecutiveFrame_ADDON_LOADED = nil
NeedToKnow.ExecutiveFrame_PLAYER_LOGIN = nil
NeedToKnowLoader = nil
 
NeedToKnow.UpdateWeaponEnchants()
end
 
 
function NeedToKnow.ExecutiveFrame_PLAYER_TALENT_UPDATE()
local spec = GetActiveTalentGroup()
if NeedToKnow.CharSettings then
local spec = GetActiveTalentGroup()
 
local profile = NeedToKnow.CharSettings.Specs[spec]
if not profile then
profile = NeedToKnow.CreateProfile(CopyTable(NEEDTOKNOW.PROFILE_DEFAULTS), spec)
local profile = NeedToKnow.CharSettings.Specs[spec]
if not profile then
profile = NeedToKnow.CreateProfile(CopyTable(NEEDTOKNOW.PROFILE_DEFAULTS), spec)
end
 
NeedToKnow.ChangeProfile(profile);
end
 
NeedToKnow.ChangeProfile(profile);
end
 
 
function NeedToKnow.RemoveDefaultValues(t, def, k)
if not k then k = "" end
if not def then
269,6 → 298,11
end
 
function NeedToKnow.CompressProfile(profileSettings)
for k,p in pairs(NeedToKnow_Globals.Profiles) do
if p == profileSettings then
trace("Compressing",k)
end
end
-- Remove unused bars/groups
for iG,vG in ipairs(profileSettings["Groups"]) do
if iG > profileSettings.nGroups then
285,32 → 319,37
end
 
 
-- DEBUG: remove k, it's just for debugging
function NeedToKnow.AddDefaultsToTable(t, def, k)
if type(t) ~= "table" then return end
if not def then
return
end
if not k then k = "" end
local n = table.maxn(t)
if n > 0 then
if type(t) ~= "table" then return end
if not def then
return
end
if not k then k = "" end
local n = table.maxn(t)
if n > 0 then
for i=1,n do
local rhs = def[i]
if not rhs then rhs = def[1] end
if not t[i] then
t[i] = NeedToKnow.deepcopy(rhs)
else
NeedToKnow.AddDefaultsToTable(t[i], rhs, k .. " " .. i)
end
local rhs = def[i]
if not rhs then rhs = def[1] end
if not t[i] then
t[i] = NeedToKnow.DeepCopy(rhs)
else
NeedToKnow.AddDefaultsToTable(t[i], rhs, k .. " " .. i)
end
end
else
else
for kD,vD in pairs(def) do
if not t[kD] then
t[kD] = NeedToKnow.deepcopy(vD)
else
NeedToKnow.AddDefaultsToTable(t[kD], vD, k .. " " .. kD)
end
if not t[kD] then
if type(vD) == "table" then
t[kD] = NeedToKnow.DeepCopy(vD)
else
t[kD] = vD
end
else
NeedToKnow.AddDefaultsToTable(t[kD], vD, k .. " " .. kD)
end
end
end
end
end
 
function NeedToKnow.UncompressProfile(profileSettings)
337,7 → 376,13
end
end
 
NeedToKnow.AddDefaultsToTable(profileSettings, NEEDTOKNOW.PROFILE_DEFAULTS)
for k,p in pairs(NeedToKnow_Globals.Profiles) do
if p == profileSettings then
trace("Uncompressing",k)
end
end
 
NeedToKnow.AddDefaultsToTable(profileSettings, NEEDTOKNOW.PROFILE_DEFAULTS)
if ( not profileSettings["BarFont"] or profileSettings["BarFont"] == "DEFAULT" ) then
profileSettings["BarFont"] = GameFontHighlight:GetFont()
end
361,7 → 406,6
 
-- fill in any missing defaults
NeedToKnow.UncompressProfile(NeedToKnow.ProfileSettings)
 
-- Hide any groups not in use
local iGroup = NeedToKnow.ProfileSettings.nGroups + 1
while true do
539,6 → 583,7
end
 
for iS,vS in pairs(NeedToKnow_Globals.Profiles) do
-- DEBUG: This is just to debug the uncompress/compress code by forcing it to happen
NeedToKnow.UncompressProfile(vS)
if vS.bUncompressed then
NeedToKnow.CompressProfile(vS)
556,27 → 601,41
 
 
 
-- Copies anything (int, table, whatever). Unlike CopyTable, deepcopy can
-- recreate a recursive reference structure (CopyTable will stack overflow.)
-- Copied from http://lua-users.org/wiki/CopyTable
function NeedToKnow.deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
function NeedToKnow.DeepCopy(object)
if type(object) ~= "table" then
return object
else
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
for k,v in pairs(object) do
new_table[k] = NeedToKnow.DeepCopy(v)
end
return setmetatable(new_table, getmetatable(object))
return new_table
end
return _copy(object)
end
 
 
---- Copies anything (int, table, whatever). Unlike DeepCopy (and CopyTable), CopyRefGraph can
---- recreate a recursive reference structure (CopyTable will stack overflow.)
---- Copied from http://lua-users.org/wiki/CopyTable
--function NeedToKnow.CopyRefGraph(object)
--local lookup_table = {}
--local function _copy(object)
--if type(object) ~= "table" then
--return object
--elseif lookup_table[object] then
--return lookup_table[object]
--end
--local new_table = {}
--lookup_table[object] = new_table
--for index, value in pairs(object) do
--new_table[_copy(index)] = _copy(value)
--end
--return setmetatable(new_table, getmetatable(object))
--end
--return _copy(object)
--end
 
 
function NeedToKnow.Update()
if UnitExists("player") and NeedToKnow.ProfileSettings then
for groupID = 1, NeedToKnow.ProfileSettings.nGroups do
585,6 → 644,7
end
end
 
 
function NeedToKnow.Show(bShow)
NeedToKnow_Visible = bShow
for groupID = 1, NeedToKnow.ProfileSettings.nGroups do
636,6 → 696,7
NeedToKnow.ClearScripts(bar)
end
end
 
local resizeButton = _G[groupName.."ResizeButton"]
resizeButton:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 8, -8)
 
650,7 → 711,7
break
end
end
 
 
if ( NeedToKnow.CharSettings["Locked"] ) then
resizeButton:Hide()
else
679,6 → 740,36
-- BARS
-- ----
 
-- Attempt to figure out if a name is an item or a spell, and if a spell
-- try to choose a spell with that name that has a cooldown
-- This may fail for valid names if the client doesn't have the data for
-- that spell yet (just logged in or changed talent specs), in which case
-- we mark that spell to try again later
function NeedToKnow.SetupSpellCooldown(bar, idx, barSpell)
local isSpellID = barSpell:match("%d+") == barSpell
if ( barSpell == "Auto Shot" or
barSpell == NEEDTOKNOW.AUTO_SHOT or
barSpell == "75" )
then
bar.settings.bAutoShot = true
bar.cd_functions[idx] = NeedToKnow.GetAutoShotCooldown
elseif not isSpellID then
local item_id = NeedToKnow.GetItemIDString(barSpell)
if item_id then
bar.spells[idx] = item_id
bar.cd_functions[idx] = NeedToKnow.GetItemCooldown
else
local betterSpell = barSpell
betterSpell = NeedToKnow.TryToFindSpellWithCD(barSpell)
if nil ~= betterSpell then
bar.spells[idx] = betterSpell
elseif not GetSpellCooldown(barSpell) then
bar.cd_functions[idx] = NeedToKnow.GetUnresolvedCooldown
end
end
end
end
 
-- Called when the configuration of the bar has changed, when the addon
-- is loaded or when ntk is locked and unlocked
function NeedToKnow.Bar_Update(groupID, barID)
698,6 → 789,7
bar:SetPoint("RIGHT", group, "RIGHT", 0, 0)
trace("Creating bar for", groupID, barID)
end
 
local background = _G[barName.."Background"]
bar.spark = _G[barName.."Spark"]
bar.text = _G[barName.."Text"]
711,6 → 803,7
groupSettings.Bars[barID] = CopyTable(NEEDTOKNOW.BAR_DEFAULTS)
end
bar.auraName = barSettings.AuraName
 
if ( barSettings.BuffOrDebuff == "BUFFCD" or
barSettings.BuffOrDebuff == "TOTEM" or
barSettings.BuffOrDebuff == "USABLE" or
719,42 → 812,6
barSettings.Unit = "player"
end
 
-- Split the spell names
bar.spells = {}
bar.functions = {}
for barSpell in bar.auraName:gmatch("([^,]+)") do
barSpell = strtrim(barSpell)
table.insert(bar.spells, barSpell)
table.insert(bar.functions, NeedToKnow.GetSpellCooldown)
end
 
-- split the user name overrides
bar.spell_names = {}
for un in barSettings.show_text_user:gmatch("([^,]+)") do
un = strtrim(un)
table.insert(bar.spell_names, un)
end
 
-- Look for certain special "spell" names
barSettings.bAutoShot = nil
if ( barSettings.BuffOrDebuff == "CASTCD" ) then
for idx, barSpell in ipairs(bar.spells) do
if ( barSpell == "Auto Shot" or
barSpell == NEEDTOKNOW.AUTO_SHOT or
barSpell == "75" )
then
barSettings.bAutoShot = true
bar.functions[idx] = NeedToKnow.GetAutoShotCooldown
elseif (barSpell:match("%d+") ~= barSpell) then
local item_id = NeedToKnow.GetItemIDString(barSpell)
if item_id then
bar.spells[idx] = item_id
bar.functions[idx] = NeedToKnow.GetItemCooldown
end
end
end
end
 
bar.settings = barSettings
bar.unit = barSettings.Unit
bar.nextUpdate = GetTime() + NEEDTOKNOW.UPDATE_INTERVAL
812,18 → 869,72
end
 
if ( NeedToKnow.CharSettings["Locked"] ) then
-- Set up the bar to be functional
bar:EnableMouse(0)
local enabled = barSettings.Enabled
if ( enabled and barSettings.BuffOrDebuff == "BUFFCD" ) then
local dur = tonumber(barSettings.buffcd_duration)
if (not dur or dur < 1) then
print("Internal cooldown bar watching",barSettings.AuraName,"did not set a cooldown duration. Disabling the bar")
enabled = false
local enabled = groupSettings.Enabled and barSettings.Enabled
if enabled then
-- Set up the bar to be functional
-- click through
bar:EnableMouse(0)
 
-- Split the spell names
bar.spells = {}
bar.cd_functions = {}
for barSpell in bar.auraName:gmatch("([^,]+)") do
barSpell = strtrim(barSpell)
table.insert(bar.spells, barSpell)
end
end
 
-- split the user name overrides
bar.spell_names = {}
for un in barSettings.show_text_user:gmatch("([^,]+)") do
un = strtrim(un)
table.insert(bar.spell_names, un)
end
 
-- split the "reset" spells (for internal cooldowns which reset when the player gains an aura)
if barSettings.buffcd_reset_spells and barSettings.buffcd_reset_spells ~= "" then
bar.reset_spells = {}
bar.reset_start = {}
for resetSpell in barSettings.buffcd_reset_spells:gmatch("([^,]+)") do
resetSpell = strtrim(resetSpell)
table.insert(bar.reset_spells, resetSpell)
table.insert(bar.reset_start, 0)
end
else
bar.reset_spells = nil
bar.reset_start = nil
end
 
barSettings.bAutoShot = nil
 
-- Determine which helper functions to use
if "BUFFCD" == barSettings.BuffOrDebuff then
bar.fnCheck = NeedToKnow.AuraCheck_BUFFCD
elseif "TOTEM" == barSettings.BuffOrDebuff then
bar.fnCheck = NeedToKnow.AuraCheck_TOTEM
elseif "USABLE" == barSettings.BuffOrDebuff then
bar.fnCheck = NeedToKnow.AuraCheck_USABLE
elseif "CASTCD" == barSettings.BuffOrDebuff then
bar.fnCheck = NeedToKnow.AuraCheck_CASTCD
for idx, barSpell in ipairs(bar.spells) do
table.insert(bar.cd_functions, NeedToKnow.GetSpellCooldown)
NeedToKnow.SetupSpellCooldown(bar, idx, barSpell)
end
elseif "mhand" == barSettings.Unit or "ohand" == barSettings.Unit then
bar.fnCheck = NeedToKnow.AuraCheck_Weapon
elseif barSettings.show_all_stacks then
bar.fnCheck = NeedToKnow.AuraCheck_AllStacks
else
bar.fnCheck = NeedToKnow.AuraCheck_Single
end
 
if ( enabled ) then
if ( barSettings.BuffOrDebuff == "BUFFCD" ) then
local dur = tonumber(barSettings.buffcd_duration)
if (not dur or dur < 1) then
print("Internal cooldown bar watching",barSettings.AuraName,"did not set a cooldown duration. Disabling the bar")
enabled = false
end
end
 
NeedToKnow.SetScripts(bar)
-- Events were cleared while unlocked, so need to check the bar again now
NeedToKnow.Bar_AuraCheck(bar)
916,6 → 1027,8
bar:RegisterEvent("PLAYER_FOCUS_CHANGED")
elseif ( bar.unit == "target" ) then
bar:RegisterEvent("PLAYER_TARGET_CHANGED")
elseif ( bar.unit == "pet" ) then
bar:RegisterEvent("UNIT_PET")
end
end
 
978,11 → 1091,14
elseif ( event == "UNIT_AURA" ) and ( select(1, ...) == self.unit ) then
NeedToKnow.Bar_AuraCheck(self)
elseif ( event == "UNIT_INVENTORY_CHANGED" and select(1, ...) == "player" ) then
NeedToKnow.UpdateWeaponEnchants()
NeedToKnow.Bar_AuraCheck(self)
elseif ( event == "PLAYER_TARGET_CHANGED" ) or ( event == "PLAYER_FOCUS_CHANGED" ) then
NeedToKnow.Bar_AuraCheck(self)
elseif ( event == "UNIT_TARGET" and select(1, ...) == "target" ) then
NeedToKnow.Bar_AuraCheck(self)
elseif ( event == "UNIT_PET" and select(1, ...) == "player" ) then
NeedToKnow.Bar_AuraCheck(self)
elseif ( event == "UNIT_SPELLCAST_SENT" ) then
local unit, spell = select(1, ...)
if ( self.settings.bDetectExtends ) then
1172,7 → 1288,9
-- Force an update to get all the bars to the current position (sharing code)
-- This will call UpdateVCT again, but that seems ok
bar.nextUpdate = -NEEDTOKNOW.UPDATE_INTERVAL
NeedToKnow.Bar_OnUpdate(bar, 0)
if bar.expirationTime > GetTime() then
NeedToKnow.Bar_OnUpdate(bar, 0)
end
 
bar.time:Show()
else
1220,19 → 1338,18
local tt = CreateFrame("GameTooltip", ttname)
tt:SetOwner(UIParent, "ANCHOR_NONE")
tt.left = {}
tt.right = {}
-- Most of the tooltip lines share the same text widget,
-- But we need to query the third one for cooldown info
tt.right1 = tt:CreateFontString()
tt.right1:SetFontObject(GameFontNormal)
tt.right3 = tt:CreateFontString()
tt.right3:SetFontObject(GameFontNormal)
for i = 1, 30 do
tt.left[i] = tt:CreateFontString()
tt.left[i]:SetFontObject(GameFontNormal)
if i ~= 3 then
tt:AddFontStrings(tt.left[i], tt.right1)
if i < 5 then
tt.right[i] = tt:CreateFontString()
tt.right[i]:SetFontObject(GameFontNormal)
tt:AddFontStrings(tt.left[i], tt.right[i])
else
tt:AddFontStrings(tt.left[i], tt.right3)
tt:AddFontStrings(tt.left[i], tt.right[4])
end
end
end
1299,13 → 1416,20
 
-- Get the number and unit of the cooldown from the tooltip
local tt1 = NeedToKnow.GetUtilityTooltips()
tt1:SetHyperlink( GetSpellLink(spell) )
local cd = tt1.right3:GetText()
local n_cd, unit_cd
if cd then
cd = cd:lower()
n_cd, unit_cd = cd:match("(%d+) (.+) ")
end
local lnk = GetSpellLink(spell)
local cd, n_cd, unit_cd
if lnk and lnk ~= "" then
tt1:SetHyperlink( lnk )
 
for iTT=3,2,-1 do
cd = tt1.right[iTT]:GetText()
if cd then
cd = cd:lower()
n_cd, unit_cd = cd:match("(%d+) (.+) ")
end
if n_cd then break end
end
end
 
-- unit_ref will be "|4sec:sec;" in english, so do a find rather than a ==
if not n_cd then
1323,6 → 1447,31
end
 
 
-- Search the player's spellbook for a spell that matches
-- todo: cache this result?
function NeedToKnow.TryToFindSpellWithCD(barSpell)
if NeedToKnow.DetermineShortCooldownFromTooltip(barSpell) > 0 then return barSpell end
 
for iBook = 1, GetNumSpellTabs() do
local sBook,_,iFirst,nSpells = GetSpellTabInfo(iBook)
for iSpell=iFirst+1, iFirst+nSpells do
local sName = GetSpellInfo(iSpell, sBook)
if sName == barSpell then
local sLink = GetSpellLink(iSpell, sBook)
local sID = sLink:match("spell:(%d+)")
local start = GetSpellCooldown(sID)
if start then
local ttcd = NeedToKnow.DetermineShortCooldownFromTooltip(sID)
if ttcd and ttcd>0 then
return sID
end
end
end
end
end
end
 
 
function NeedToKnow.GetItemIDString(id_or_name)
local _, link = GetItemInfo(id_or_name)
if link then
1334,6 → 1483,7
end
 
 
-- Helper for NeedToKnow.AuraCheck_CASTCD which gets the autoshot cooldown
function NeedToKnow.GetAutoShotCooldown(bar)
local tNow = GetTime()
if ( bar.tAutoShotStart and bar.tAutoShotStart + bar.tAutoShotCD > tNow ) then
1345,6 → 1495,17
end
 
 
-- Helper for NeedToKnow.AuraCheck_CASTCD for names we haven't figured out yet
function NeedToKnow.GetUnresolvedCooldown(bar, barSpell, idxName)
NeedToKnow.SetupSpellCooldown(bar, idxName, barSpell)
local fn = bar.cd_functions[idxName]
if NeedToKnow.GetUnresolvedCooldown ~= fn then
-- Have to re-evaluate barSpell since SetupSpellCooldown may have changed bar.spells
return fn(bar, bar.spells[idxName], idxName)
end
end
 
 
-- Wrapper around GetSpellCooldown with extra sauce
-- Expected to return start, cd_len, enable, buffName, iconpath
function NeedToKnow.GetSpellCooldown(bar, barSpell)
1386,7 → 1547,7
 
-- Wrapper around GetItemCooldown
-- Expected to return start, cd_len, enable, buffName, iconpath
function NeedToKnow.GetItemCooldown(bar, item_id)
function NeedToKnow.GetItemCooldown(bar, item_id, idx)
local start, cd_len, enable = GetItemCooldown(item_id)
if start then
local name, _, _, _, _, _, _, _, icon = GetItemInfo(item_id)
1395,224 → 1556,359
end
 
 
-- Scrapes the current tooltips for the player's weapons to tease out
-- the name of the current weapon imbue (and not just the name of the
-- weapon, like you get from the Blizzard API.) This info gets cached
-- on the bar so we don't have to compute it every Bar_AuraCheck
function NeedToKnow.UpdateWeaponEnchants()
local mdata = NeedToKnow.weapon_enchants.mhand
local odata = NeedToKnow.weapon_enchants.ohand
 
mdata.present, mdata.expiration, mdata.charges,
odata.present, odata.expiration, odata.charges
= GetWeaponEnchantInfo()
 
if ( mdata.present ) then
local oldname = mdata.name
mdata.name = NeedToKnow.DetermineTempEnchantFromTooltip(16)
if not mdata.name then
mdata.name = "Unknown"
print("Warning: NTK couldn't figure out what enchant is on the main hand weapon")
end
mdata.expiration = GetTime() + mdata.expiration/1000
if oldname ~= mdata.name then
_,_,mdata.icon = GetSpellInfo(mdata.name)
end
else
mdata.name=nil
end
 
if ( odata.present ) then
local oldname = odata.name
odata.name = NeedToKnow.DetermineTempEnchantFromTooltip(17)
if not odata.name then
odata.name = "Unknown"
print("Warning: NTK couldn't figure out what enchant is on the off-hand weapon")
end
odata.expiration = GetTime() + odata.expiration/1000
if oldname ~= odata.name then
_,_,odata.icon = GetSpellInfo(odata.name)
end
else
odata.name = nil
end
end
 
 
-- Bar_AuraCheck helper for Totem bars, this returns data if
-- a totem matching barSpell is currently out.
function NeedToKnow.AuraCheck_TOTEM(bar, idxName, barSpell, isSpellID)
local spellName, spellRank, spellIconPath
if ( isSpellID ) then
spellName, spellRank, spellIconPath = GetSpellInfo(barSpell)
end
for iSlot=1, 4 do
local haveTotem, totemName, startTime, totemDuration, totemIcon = GetTotemInfo(iSlot)
local sComp = barSpell
if isSpellID then sComp = spellName end
if ( totemName and totemName:find(sComp) ) then
-- WORKAROUND: The startTime reported here is both cast to an int and off by
-- a latency meaning it can be significantly low. So we cache the GetTime
-- that the totem actually appeared, so long as GetTime is reasonably close to
-- startTime (since the totems may have been out for awhile before this runs.)
if ( not NeedToKnow.totem_drops[iSlot] or
NeedToKnow.totem_drops[iSlot] < startTime )
then
local precise = GetTime()
if ( precise - startTime > 1 ) then
precise = startTime + 1
end
NeedToKnow.totem_drops[iSlot] = precise
end
 
return totemDuration, -- duration
totemName, -- name
1, -- count
NeedToKnow.totem_drops[iSlot] + totemDuration, -- expiration time
totemIcon, -- icon path
"player" -- caster
end
end
end
 
 
-- Bar_AuraCheck helper that checks the bar.weapon_enchants
-- (computed by UpdateWeaponEnchants) for the given spell.
-- FIXME: this is the only bar type that does not work with spell ids.
function NeedToKnow.AuraCheck_Weapon(bar, idxName, barSpell, isSpellID)
local data = NeedToKnow.weapon_enchants[bar.settings.Unit]
if ( data.present and data.name and data.name:find(barSpell) ) then
return 1800, -- duration TODO: Get real duration?
data.name, -- name
data.charges, -- count
data.expiration, -- expiration time
data.icon, -- icon path
"player" -- caster
end
end
 
 
-- Bar_AuraCheck helper that checks for spell/item use cooldowns
-- Relies on NeedToKnow.GetAutoShotCooldown, NeedToKnow.GetSpellCooldown
-- and NeedToKnow.GetItemCooldown. Bar_Update will have already pre-processed
-- this list so that bar.cd_functions[idxName] can do something with barSpell
function NeedToKnow.AuraCheck_CASTCD(bar, idxName, barSpell, isSpellID)
local func = bar.cd_functions[idxName]
local start, cd_len, should_cooldown, buffName, iconPath = func(bar, barSpell, idxName)
 
-- filter out the GCD, we only care about actual spell CDs
if start and cd_len <= 1.5 and func ~= NeedToKnow.GetAutoShotCooldown then
if bar.expirationTime then
start = bar.expirationTime - bar.duration
cd_len = bar.duration
else
start = nil
end
end
 
if start and cd_len then
local tNow = GetTime()
local tEnd = start + cd_len
if ( tEnd > tNow + 0.1 ) then
return cd_len, -- duration
buffName, -- name
1, -- count
tEnd, -- expiration time
iconPath, -- icon path
"player" -- caster
end
end
end
 
 
-- Bar_AuraCheck helper for watching "Is Usable", which means that the action
-- bar button for the spell lights up. This is mostly useful for Victory Rush
function NeedToKnow.AuraCheck_USABLE(bar, idxName, barSpell, isSpellID)
local key
local settings = bar.settings
if ( isSpellID ) then key = tonumber(barSpell) else key = barSpell end
if ( not key ) then key = "" end
local spellName, _, iconPath = GetSpellInfo(key)
if ( spellName ) then
local isUsable, notEnoughMana = IsUsableSpell(spellName)
if (isUsable or notEnoughMana) then
local duration = settings.usable_duration
local expirationTime
local tNow = GetTime()
if ( not bar.expirationTime or
(bar.expirationTime > 0 and bar.expirationTime < tNow - 0.01) )
then
duration = settings.usable_duration
expirationTime = tNow + duration
else
duration = bar.duration
expirationTime = bar.expirationTime
end
 
return duration, -- duration
spellName, -- name
1, -- count
expirationTime, -- expiration time
iconPath, -- icon path
"player" -- caster
end
end
end
 
 
-- Bar_AuraCheck helper for watching "internal cooldowns", which is like a spell
-- cooldown for spells cast automatically (procs). The "reset on buff" logic
-- is still handled by
function NeedToKnow.AuraCheck_BUFFCD(bar, idxName, barSpell, isSpellID)
local duration, buffName, _, expiration, iconPath, caster = NeedToKnow.AuraCheck_Single(bar, idxName, barSpell, isSpellID)
local tNow = GetTime()
if ( duration ) then
if expiration == 0 then
-- TODO: This really doesn't work very well as a substitute for telling when the aura was appliedS
if not bar.expirationTime then
local nDur = tonumber(bar.settings.buffcd_duration)
return nDur, buffName, 1, nDur+tNow, iconPath, caster
else
return bar.duration, -- duration
bar.buffName, -- name
1, -- count
bar.expirationTime, -- expiration time
bar.iconPath, -- icon path
"player" -- caster
end
end
local tStart = expiration - duration
duration = tonumber(bar.settings.buffcd_duration)
expiration = tStart + duration
if ( expiration > tNow ) then
return duration, -- duration
buffName, -- name
-- Seeing the charges on the CD bar violated least surprise for me
1, -- count
expiration, -- expiration time
iconPath, -- icon path
caster -- caster
end
elseif ( bar.expirationTime and bar.expirationTime > tNow + 0.1 ) then
return bar.duration, -- duration
bar.buffName, -- name
1, -- count
bar.expirationTime, -- expiration time
bar.iconPath, -- icon path
"player" -- caster
end
end
 
 
-- Bar_AuraCheck helper that looks for the first instance of a buff
-- Uses the UnitAura filters exclusively if it can
function NeedToKnow.AuraCheck_Single(bar, idxName, barSpell, isSpellID)
local settings = bar.settings
local filter = settings.BuffOrDebuff
if settings.OnlyMine then
filter = filter .. "|PLAYER"
end
 
if isSpellID then
-- WORKAROUND: The second parameter to UnitAura can't be a spellid, so I have
-- to walk them all
local barID = tonumber(barSpell)
local j = 1
while true do
local buffName, _, iconPath, count, _, duration, expirationTime, caster, _, _, spellID
= UnitAura(bar.unit, j, filter)
if (not buffName) then
break
end
 
if (spellID == barID) then
return duration, -- duration
buffName, -- name
count, -- count
expirationTime, -- expiration time
iconPath, -- icon path
caster -- caster
end
j=j+1
end
else
local buffName, _ , iconPath, count, _, duration, expirationTime, caster
= UnitAura(bar.unit, barSpell, nil, filter)
 
return duration, -- duration
buffName, -- name
count, -- count
expirationTime, -- expiration time
iconPath, -- icon path
caster -- caster
end
end
 
 
-- Bar_AuraCheck helper that updates bar.all_stacks (but returns nil)
-- by scanning all the auras on the unit
function NeedToKnow.AuraCheck_AllStacks(bar, idxName, barSpell, isSpellID)
local j = 1
local matchID
if isSpellID then matchID = tonumber(barSpell) end
local all_stacks = bar.all_stacks
 
while true do
local buffName, _, iconPath, count, _, duration, expirationTime, caster, _, _, spellID
= UnitAura(bar.unit, j, filter)
if (not buffName) then
break
end
 
if (isSpellID and spellID == matchID) or (not isSpellID and barSpell == buffName) then
if (not count or count < 1) then count = 1 end
if ( 0 == all_stacks.total or all_stacks.min.expirationTime > expirationTime ) then
all_stacks.min.idxName = idxName
all_stacks.min.buffName = buffName
all_stacks.min.caster = caster
all_stacks.min.duration = duration
all_stacks.min.expirationTime = expirationTime
all_stacks.min.iconPath = iconPath
end
if ( 0 == all_stacks.total or all_stacks.max.expirationTime < expirationTime ) then
all_stacks.max.duration = duration
all_stacks.max.expirationTime = expirationTime
end
all_stacks.total = all_stacks.total + count
end
 
j = j+1
end
end
 
 
-- Called whenever the state of auras on the bar's unit may have changed
function NeedToKnow.Bar_AuraCheck(bar)
local buffName, count, duration, expirationTime, caster, iconPath
local idxName = 0
local all_stacks
local settings = bar.settings
local bUnitExists, isWeapon
if ( settings.BuffOrDebuff == "CASTCD" or
settings.BuffOrDebuff == "BUFFCD" or
settings.BuffOrDebuff == "USABLE" or
settings.BuffOrDebuff == "TOTEM" )
then
if "mhand" == settings.Unit or
"ohand" == settings.Unit then
isWeapon = true
bUnitExists = true
elseif "player" == settings.Unit then
bUnitExists = true
else
if ( "mhand" == settings.Unit or
"ohand" == settings.Unit )
then
isWeapon = true
bUnitExists = true
else
bUnitExists = UnitExists(bar.unit)
end
bUnitExists = UnitExists(settings.Unit)
end
 
-- Determine if the bar should be showing anything
if ( bUnitExists ) then
 
local mainHandEnchantName, mainHandEnchantRank, offHandEnchantName, offHandEnchantRank
local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges
if ( isWeapon ) then
hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo()
if ( hasMainHandEnchant and "mhand" == settings.Unit ) then
mainHandEnchantName, mainHandEnchantRank = NeedToKnow.DetermineTempEnchantFromTooltip(16)
local all_stacks
local idxName, duration, buffName, count, expirationTime, iconPath, caster
if ( bUnitExists ) then
if ( settings.show_all_stacks ) then
if ( not bar.all_stacks ) then
bar.all_stacks =
{
min =
{
buffName = "",
duration = 0,
expirationTime = 0,
iconPath = "",
caster = ""
},
max =
{
duration = 0,
expirationTime = 0,
},
total = 0
}
else
bar.all_stacks.total = 0
end
if ( hasOffHandEnchant and "ohand" == settings.Unit ) then
offHandEnchantName, offHandEnchantRank = NeedToKnow.DetermineTempEnchantFromTooltip(17)
end
all_stacks = bar.all_stacks
end
 
-- Call the helper function for each of the spells in the list
for idx, barSpell in ipairs(bar.spells) do
idxName = idx
local filter = settings.BuffOrDebuff
local _, nDigits = barSpell:find("^%d+")
local isSpellID = ( nDigits == barSpell:len() )
 
if ( settings.BuffOrDebuff == "TOTEM" ) then
local spellName, spellRank, spellIconPath
if ( isSpellID ) then
spellName, spellRank, spellIconPath = GetSpellInfo(barSpell)
end
for iSlot=1, 4 do
local haveTotem, totemName, startTime, totemDuration, totemIcon = GetTotemInfo(iSlot)
local sComp = barSpell
if isSpellID then sComp = spellName end
if ( totemName and totemName:find(sComp) ) then
-- WORKAROUND: The startTime reported here is both cast to an int and off by
-- a latency meaning it can be significantly low. So we cache the GetTime
-- that the totem actually appeared, so long as GetTime is reasonably close to
-- startTime (since the totems may have been out for awhile before this runs.)
if ( not NeedToKnow.totem_drops[iSlot] or
NeedToKnow.totem_drops[iSlot] < startTime )
then
local precise = GetTime()
if ( precise - startTime > 1 ) then
precise = startTime + 1
end
NeedToKnow.totem_drops[iSlot] = precise
end
buffName = totemName
duration = totemDuration
expirationTime = NeedToKnow.totem_drops[iSlot] + duration
iconPath = totemIcon
count = 1
caster = "player"
break
end
end
elseif isWeapon then
if ( "mhand" == settings.Unit and mainHandEnchantName and mainHandEnchantName:find(barSpell) ) then
buffName = mainHandEnchantName
count = mainHandCharges
if ( count < 1 ) then count = 1 end
duration = 1800
expirationTime = GetTime() + mainHandExpiration/1000
caster = "player"
elseif ( "ohand" == settings.Unit and offHandEnchantName and offHandEnchantName:find(barSpell) ) then
buffName = offHandEnchantName
count = offHandCharges
if ( not count or count < 1 ) then count = 1 end
duration = 1800
expirationTime = GetTime() + offHandExpiration/1000
caster = "player"
end
elseif settings.BuffOrDebuff == "CASTCD" then
local start, cd_len, should_cooldown
local func = bar.functions[idxName]
start, cd_len, should_cooldown, buffName, iconPath = func(bar, barSpell)
 
-- filter out the GCD, we only care about actual spell CDs
if start and cd_len <= 1.5 and func ~= NeedToKnow.GetAutoShotCooldown then
if bar.expirationTime then
start = bar.expirationTime - bar.duration
cd_len = bar.duration
else
start = nil
end
end
 
if start and cd_len then
local tNow = GetTime()
local tEnd = start + cd_len
if ( tEnd > tNow + 0.1 ) then
count = 1
duration = cd_len
expirationTime = tEnd
cast = "player"
end
end
elseif settings.BuffOrDebuff == "USABLE" then
local key
if ( isSpellID ) then key = tonumber(barSpell) else key = barSpell end
if ( not key ) then key = "" end
local spellName
spellName, _, iconPath = GetSpellInfo(key)
if ( spellName ) then
local isUsable, notEnoughMana = IsUsableSpell(spellName)
if (isUsable or notEnoughMana) then
duration = settings.usable_duration
buffName = spellName
count = 1
local tNow = GetTime()
if ( not bar.expirationTime or
(bar.expirationTime > 0 and bar.expirationTime < tNow - 0.01) )
then
duration = settings.usable_duration
expirationTime = tNow + duration
else
duration = bar.duration
expirationTime = bar.expirationTime
end
end
end
else
if settings.OnlyMine then
filter = filter .. "|PLAYER"
end
 
if isSpellID then
-- WORKAROUND: The second parameter to UnitAura can't be a spellid, so I have
-- to walk them all
local barID = tonumber(barSpell)
local j = 1
while true do
local buffRank, spellID
buffName, buffRank, iconPath, count, _, duration, expirationTime, caster, _, _, spellID = UnitAura(bar.unit, j, filter)
if (not buffName) then
break
end
 
if (spellID == barID) then
break
else
duration = nil
end
j=j+1
end
else
buffName, _ , iconPath, count, _, duration, expirationTime, caster = UnitAura(bar.unit, barSpell, nil, filter)
end
end
duration, buffName, count, expirationTime, iconPath, caster
= bar.fnCheck(bar, idx, barSpell, isSpellID);
 
if ( duration ) then
if duration then
if not count or count < 1 then
count = 1
end
 
if ( settings.show_all_stacks ) then
if ( not all_stacks ) then
all_stacks =
{
min =
{
buffName = "",
duration = 0,
expirationTime = 0,
iconPath = "",
caster = ""
},
max =
{
duration = 0,
expirationTime = 0,
},
total = 0
}
end
 
all_stacks.total = all_stacks.total + count
if ( 0 == all_stacks.min.expirationTime or all_stacks.min.expirationTime > expirationTime ) then
all_stacks.min.idxName = idxName
all_stacks.min.buffName = buffName
all_stacks.min.caster = caster
all_stacks.min.duration = duration
all_stacks.min.expirationTime = expirationTime
all_stacks.min.iconPath = iconPath
end
if ( 0 == all_stacks.max.expirationTime or all_stacks.max.expirationTime < expirationTime ) then
all_stacks.max.duration = duration
all_stacks.max.expirationTime = expirationTime
end
else
break
end
idxName = idx
break
end
end
end
 
if ( all_stacks ) then
if ( all_stacks and all_stacks.total > 0 ) then
idxName = all_stacks.min.idxName
buffName = all_stacks.min.buffName
caster = all_stacks.min.caster
1622,27 → 1918,44
count = all_stacks.total
end
 
-- There is an aura this bar is watching! Set it up
duration = tonumber(duration)
if ( settings.BuffOrDebuff == "BUFFCD" ) then
-- Cancel the work done above if a reset spell is encountered
-- (reset_spells will only be set for BUFFCD)
if ( bar.reset_spells ) then
local maxStart = 0
local tNow = GetTime()
count = 1 -- Seeing the charges on the CD bar violated least surprise for me
if ( duration ) then
local tStart = expirationTime - duration
duration = tonumber(settings.buffcd_duration)
expirationTime = tStart + duration
if ( expirationTime <= tNow ) then
duration = nil
-- Keep track of when the reset auras were last applied to the player
for idx, resetSpell in ipairs(bar.reset_spells) do
local _, nDigits = resetSpell:find("^%d+")
local isSpellID = ( nDigits == resetSpell:len() )
 
-- Note this relies on BUFFCD setting the target to player, and that the onlyMine will work either way
local resetDuration, _, _, resetExpiration
= NeedToKnow.AuraCheck_Single(bar, idx, resetSpell, isSpellID)
local tStart
if resetDuration then
if 0 == resetDuration then
tStart = bar.reset_start[idx]
if 0 == tStart then
tStart = tNow
end
else
tStart = resetExpiration-resetDuration
end
bar.reset_start[idx] = tStart
 
if tStart > maxStart then maxStart = tStart end
else
bar.reset_start[idx] = 0
end
elseif ( bar.expirationTime and bar.expirationTime > tNow + 0.1 ) then
duration = bar.duration
expirationTime = bar.expirationTime
buffName = bar.buffName
iconPath = bar.iconPath
end
if duration and maxStart > expirationTime-duration then
duration = nil
end
end
 
-- There is an aura this bar is watching! Set it up
if ( duration ) then
duration = tonumber(duration)
-- Handle duration increases
local extended
if (settings.bDetectExtends) then
1724,10 → 2037,12
end
end
 
 
function NeedToKnow.Fmt_SingleUnit(i_fSeconds)
return string.format(SecondsToTimeAbbrev(i_fSeconds))
end
 
 
function NeedToKnow.Fmt_TwoUnits(i_fSeconds)
if ( i_fSeconds < 6040 ) then
local nMinutes, nSeconds
1779,7 → 2094,7
end
end
 
if ( self.duration > 0 ) then
if ( self.duration and self.duration > 0 ) then
local duration = self.fixedDuration or self.duration
local bar1_timeLeft = self.expirationTime - GetTime()
if ( bar1_timeLeft < 0 ) then
Kitjan/NeedToKnow/NeedToKnow.toc
1,7 → 1,7
## Interface: 30300
## Title: NeedToKnow
## Author: Kitjan, lieandswell
## Version: 3.1.7
## Version: 3.3.0
## Notes: Timer bars for buffs, debuffs, cooldowns, etc.
## X-Compatible-With: 40000
## X-Credits: Bilt, Fxfighter EU-Echsenkessel, metalchoir, sp00n, Vlakarados, wowui.cn
Kitjan/NeedToKnow/NeedToKnow_Localization.lua
45,10 → 45,10
NEEDTOKNOW.UIPANEL_TOOLTIP_BARTEXTURE = "Choose the texture graphic for timer bars";
NEEDTOKNOW.CMD_RESET = "reset";
 
NEEDTOKNOW.UIPANEL_CONFIGMODE = "Config mode";
NEEDTOKNOW.UIPANEL_CONFIGMODE_TOOLTIP = "Unlock timer bars and make them configurable";
NEEDTOKNOW.UIPANEL_PLAYMODE = "Play mode";
NEEDTOKNOW.UIPANEL_PLAYMODE_TOOLTIP = "Lock and enable timer bars, making them click-through";
NEEDTOKNOW.UIPANEL_CONFIGMODE = "Config mode";
NEEDTOKNOW.UIPANEL_CONFIGMODE_TOOLTIP = "Unlock timer bars and make them configurable";
NEEDTOKNOW.UIPANEL_PLAYMODE = "Play mode";
NEEDTOKNOW.UIPANEL_PLAYMODE_TOOLTIP = "Lock and enable timer bars, making them click-through";
 
NEEDTOKNOW.UIPANEL_APPEARANCE = "Appearance";
NEEDTOKNOW.UIPANEL_BACKGROUNDCOLOR = "Background color";
81,6 → 81,7
NEEDTOKNOW.CHOOSE_VCT_EXTRA_DIALOG = "Enter an amount of seconds that will be added to the cast time of the spell. Ex: 1.5";
NEEDTOKNOW.CHOOSE_BLINK_TITLE_DIALOG = "Enter the text to display on the bar when it is blinking.";
NEEDTOKNOW.BUFFCD_DURATION_DIALOG = "Enter the cooldown duration triggered by the buffs watched by this bar.";
NEEDTOKNOW.BUFFCD_RESET_DIALOG = "Enter the buff (or buffs) to watch for which reset the cooldown to 0.";
NEEDTOKNOW.USABLE_DURATION_DIALOG = "Enter the cooldown duration triggered by the abilities watched by this bar.";
 
 
Kitjan/NeedToKnow/NeedToKnow_Options.lua
392,6 → 392,7
Opt_BUFFCD =
{
{ VariableName = "buffcd_duration", MenuText = "Cooldown duration...", Type = "Dialog", DialogText = "BUFFCD_DURATION_DIALOG", Numeric=true },
{ VariableName = "buffcd_reset_spells", MenuText = "Reset on buff...", Type = "Dialog", DialogText = "BUFFCD_RESET_DIALOG" },
{ VariableName = "append_cd", MenuText = "Append \"CD\"" }, -- FIXME: Localization
},
Opt_USABLE =