/tags
-- --------------------- |
-- NeedToKnow |
-- by Nephthys of Hyjal |
-- updated by |
-- kitjan |
-- Bilt of Lightninghoof |
-- lieandswell@yahoo.com |
-- --------------------- |
-- ------------- |
-- ADDON GLOBALS |
-- ------------- |
NeedToKnow = {}; |
-- NEEDTOKNOW = {} is defined in the localization file, which must be loaded before this file |
NEEDTOKNOW.VERSION = "2.8.3"; |
NEEDTOKNOW.MAXGROUPS = 4; |
NEEDTOKNOW.MAXBARS = 6; |
NEEDTOKNOW.UPDATE_INTERVAL = 0.05; |
NEEDTOKNOW.CURRENTSPEC = 1; |
-- 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 = { |
SPELL_AURA_APPLIED = true, |
SPELL_AURA_REMOVED = true, |
SPELL_AURA_APPLIED_DOSE = true, |
SPELL_AURA_REMOVED_DOSE = true, |
SPELL_AURA_REFRESH = true, |
SPELL_AURA_BROKEN = true, |
SPELL_AURA_BROKEN_SPELL = true |
} |
NEEDTOKNOW.BAR_DEFAULTS = { |
Enabled = true, |
AuraName = "", |
Unit = "player", |
BuffOrDebuff = "HELPFUL", |
OnlyMine = true, |
BarColor = { r=0.6, g=0.6, b=0.6, a=1.0 }, |
TimeFormat = "Fmt_SingleUnit", |
vct_enabled = false, |
vct_color = { r=0.6, g=0.6, b=0.0, a=0.3 }, |
vct_spell = "", |
vct_extra = 0, |
bDetectExtends = false, |
}; |
NEEDTOKNOW.GROUP_DEFAULTS = { |
Enabled = false, |
NumberBars = 3, |
Scale = 1.0, |
Width = 270, |
Bars = {}, |
Position = { "TOPLEFT", "TOPLEFT", 100, -100 }, |
FixedDuration = nil, |
}; |
NEEDTOKNOW.DEFAULTS = { |
Version = NEEDTOKNOW.VERSION, |
Locked = false, |
BarTexture = "BantoBar", |
BkgdColor = { 0, 0, 0, 0.8 }, |
BarSpacing = 3, |
BarPadding = 3, |
Spec = {}, |
}; |
NEEDTOKNOW.SPEC_DEFAULTS = { |
Groups = {}, |
}; |
for barID = 1, NEEDTOKNOW.MAXBARS do |
NEEDTOKNOW.GROUP_DEFAULTS["Bars"][barID] = NEEDTOKNOW.BAR_DEFAULTS; |
end; |
for groupID = 1, NEEDTOKNOW.MAXGROUPS do |
NEEDTOKNOW.SPEC_DEFAULTS["Groups"][groupID] = NEEDTOKNOW.GROUP_DEFAULTS; |
end; |
for specID = 1, 2 do |
NEEDTOKNOW.DEFAULTS["Spec"][specID] = NEEDTOKNOW.SPEC_DEFAULTS; |
end; |
function NeedToKnow.Test(stuff) |
if ( stuff ) then |
DEFAULT_CHAT_FRAME:AddMessage("NeedToKnow test: "..stuff); |
else |
DEFAULT_CHAT_FRAME:AddMessage("NeedToKnow test: "..self:GetName()); |
end |
end |
-- ------------------- |
-- SharedMedia Support |
-- ------------------- |
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 |
-- --------------- |
-- EXECUTIVE FRAME |
-- --------------- |
function NeedToKnow.ExecutiveFrame_OnEvent(self, event, ...) |
if ( event == "ADDON_LOADED" and select(1,...) == "NeedToKnow") then |
if ( not NeedToKnow_Settings ) then |
NeedToKnow_Settings = CopyTable(NEEDTOKNOW.DEFAULTS); |
NeedToKnow_Settings["Spec"][1]["Groups"][1]["Enabled"] = true; |
NeedToKnow_Settings["Spec"][2]["Groups"][1]["Enabled"] = true; |
else |
NeedToKnow.SafeUpgrade(); |
NeedToKnow.Update(); |
NeedToKnow.UIPanel_Update(); |
end |
if ( not NeedToKnow_Visible ) then |
NeedToKnow_Visible = true; |
end |
NeedToKnow.last_cast = {}; -- [spell][guidTarget] = { time, dur } |
NeedToKnow.nSent = 0; |
NeedToKnow.totem_drops = {}; -- array 1-4 of precise times the totems appeared |
SlashCmdList["NEEDTOKNOW"] = NeedToKnow.SlashCommand; |
SLASH_NEEDTOKNOW1 = "/needtoknow"; |
SLASH_NEEDTOKNOW2 = "/ntk"; |
else |
local fnName = "ExecutiveFrame_"..event; |
local fn = NeedToKnow[fnName]; |
if ( fn ) then |
fn(...); |
end |
end |
end |
function NeedToKnow.ExecutiveFrame_UNIT_SPELLCAST_SUCCEEDED(unit, spell, rank) |
if unit == "player" then |
local r = NeedToKnow.last_cast[spell]; |
if ( r and r.state == 1 ) then |
r.state = 2; |
-- A little extra safety just in case we get two SUCCEEDED entries |
-- before we get the combat log events for them (though I don't |
-- think this is possible.) |
NeedToKnow.last_success = spell; |
-- We need the actual target, which we can only get from the combat log. |
-- Thankfully, the combat log event always comes after this one, so we |
-- don't need to register for the combat log for long at all. |
NeedToKnow_ExecutiveFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED"); |
if ( NeedToKnow.nSent > 1 ) then |
NeedToKnow.nSent = NeedToKnow.nSent - 1; |
else |
NeedToKnow.nSent = 0; |
NeedToKnow_ExecutiveFrame:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED"); |
end |
end |
end |
end |
function NeedToKnow.ExecutiveFrame_COMBAT_LOG_EVENT_UNFILTERED(time, event, guidCaster, ...) |
-- the time that's passed in appears to be time of day, not game time like everything else. |
time = GetTime(); |
-- TODO: Is checking r.state sufficient or must event be checked instead? |
if ( guidCaster == NeedToKnow.guidPlayer ) then |
local guidTarget, _, _, _, spell = select(3, ...); |
local r = NeedToKnow.last_cast[spell]; |
if ( r and r.state == 2) then |
r.state = 0; |
-- record this spellcast |
if ( not r[guidTarget] ) then |
r[guidTarget] = { time = time, dur = 0 }; |
else |
r[guidTarget].time = time; |
r[guidTarget].dur = 0; |
end |
-- Use this event to expire some targets. This should limit us to |
-- two combats' worth of targets (since GC doesn't happen in combat) |
for kG, vG in pairs(r) do |
if ( type(vG) == "table" and ( vG.time + 300 < time ) ) then |
r[kG] = nil; |
end |
end |
end |
if ( spell == NeedToKnow.last_success ) then |
-- We saw our spell, we can disconnect from the spam hose |
NeedToKnow_ExecutiveFrame:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED"); |
end |
end |
end |
function NeedToKnow.ExecutiveFrame_PLAYER_LOGIN() |
-- save group positions if upgrading from version that used layout-local.txt |
if ( not NeedToKnow_Settings.OldVersion or |
NeedToKnow_Settings.OldVersion < "2.1" ) then |
for groupID = 1, NEEDTOKNOW.MAXGROUPS do |
NeedToKnow.SavePosition(_G["NeedToKnow_Group"..groupID], groupID); |
end |
elseif (NeedToKnow_Settings["Version"] < "2.4") then |
NeedToKnow.UIPanel_Update(); |
end |
NeedToKnow.guidPlayer = UnitGUID("player"); |
NEEDTOKNOW.CURRENTSPEC = GetActiveTalentGroup(); |
NeedToKnow.Update(); |
NeedToKnow.UIPanel_Update(); |
end |
function NeedToKnow.ExecutiveFrame_PLAYER_TALENT_UPDATE() |
NEEDTOKNOW.CURRENTSPEC = GetActiveTalentGroup(); |
NeedToKnow.Update(); |
NeedToKnow.UIPanel_Update(); |
end |
function NeedToKnow.SafeUpgrade() |
-- If there had been an error during the previous upgrade, NeedToKnow_Settings |
-- may be in an inconsistent, halfway state. |
local bCorruptUpgrade = false; |
if ( NeedToKnow_Settings["Spec"] ) then |
for idxSpec = 1,2 do |
local specSettings = NeedToKnow_Settings.Spec[idxSpec]; |
if ( not specSettings or not specSettings.Groups ) then |
bCorruptUpgrade = true; |
else |
for idxGroup = 1,NEEDTOKNOW.MAXGROUPS do |
local groupSettings = specSettings.Groups[idxGroup]; |
if not groupSettings then |
bCorruptUpgrade = true; |
end |
end |
end |
end |
if ( not bCorruptUpgrade and NeedToKnow_Settings["Version"] < "2.4" ) then |
NeedToKnow_Settings.OldVersion = NeedToKnow_Settings["Version"]; |
NeedToKnow_Settings["Version"] = NEEDTOKNOW.VERSION; |
end |
end |
if ( bCorruptUpgrade or NeedToKnow_Settings["Version"] < "2.0" ) then -- total settings clear if v1.x |
print("Old NeedToKnow settings not compatible with current version... starting from scratch"); |
NeedToKnow_Settings = CopyTable(NEEDTOKNOW.DEFAULTS); |
NeedToKnow_Settings["Spec"][1]["Groups"][1]["Enabled"] = true; |
NeedToKnow_Settings["Spec"][2]["Groups"][1]["Enabled"] = true; |
-- if before dual spec support, copy old settings to both specs |
elseif (NeedToKnow_Settings["Version"] < "2.4") then |
local tempSettings = CopyTable(NeedToKnow_Settings); |
NeedToKnow.Reset(); |
NeedToKnow_Settings["Locked"] = tempSettings["Locked"]; |
NeedToKnow_Settings["BarTexture"] = tempSettings["BarTexture"]; |
NeedToKnow_Settings["BkgdColor"] = tempSettings["BkgdColor"]; |
NeedToKnow_Settings["BarSpacing"] = tempSettings["BarSpacing"]; |
NeedToKnow_Settings["BarPadding"] = tempSettings["BarPadding"]; |
NeedToKnow_Settings["Version"] = tempSettings["Version"]; |
for i = 1, NEEDTOKNOW.MAXGROUPS do |
NeedToKnow_Settings["Spec"][1]["Groups"][i] = tempSettings["Groups"][i]; |
NeedToKnow_Settings["Spec"][2]["Groups"][i] = tempSettings["Groups"][i]; |
end |
end |
NeedToKnow_Settings.OldVersion = NeedToKnow_Settings["Version"]; |
NeedToKnow_Settings["Version"] = NEEDTOKNOW.VERSION; |
-- Add any new settings |
for iS,vS in ipairs(NeedToKnow_Settings["Spec"]) do |
for kD, vD in pairs(NEEDTOKNOW.SPEC_DEFAULTS) do |
if nil == vS[kD] then |
vS[kD] = NeedToKnow.deepcopy(vD); |
end |
end |
for iG,vG in ipairs(vS["Groups"]) do |
for kD, vD in pairs(NEEDTOKNOW.GROUP_DEFAULTS) do |
if nil == vG[kD] then |
vG[kD] = NeedToKnow.deepcopy(vD); |
end |
end |
for iB, vB in ipairs(vG["Bars"]) do |
for kD, vD in pairs(NEEDTOKNOW.BAR_DEFAULTS) do |
if nil == vB[kD] then |
vB[kD] = NeedToKnow.deepcopy(vD); |
end |
end |
end |
end |
end |
end |
-- 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 |
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() |
for groupID = 1, NEEDTOKNOW.MAXGROUPS do |
NeedToKnow.Group_Update(groupID); |
end |
end |
function NeedToKnow.Show(bShow) |
NeedToKnow_Visible = bShow; |
for groupID = 1, NEEDTOKNOW.MAXGROUPS do |
local groupName = "NeedToKnow_Group"..groupID; |
local group = _G[groupName]; |
local groupSettings = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]; |
if (NeedToKnow_Visible and groupSettings.Enabled) then |
group:Show(); |
else |
group:Hide(); |
end |
end |
end |
do |
local executiveFrame = CreateFrame("Frame", "NeedToKnow_ExecutiveFrame"); |
executiveFrame:SetScript("OnEvent", NeedToKnow.ExecutiveFrame_OnEvent); |
executiveFrame:RegisterEvent("ADDON_LOADED"); |
executiveFrame:RegisterEvent("PLAYER_LOGIN"); |
executiveFrame:RegisterEvent("PLAYER_TALENT_UPDATE"); |
end |
-- ------ |
-- GROUPS |
-- ------ |
function NeedToKnow.Group_Update(groupID) |
local groupName = "NeedToKnow_Group"..groupID; |
local group = _G[groupName]; |
local groupSettings = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]; |
for barID = 1, groupSettings.NumberBars do |
local barName = groupName.."Bar"..barID; |
local bar = _G[barName] or CreateFrame("StatusBar", barName, group, "NeedToKnow_BarTemplate"); |
bar:SetID(barID); |
if ( barID > 1 ) then |
bar:SetPoint("TOP", _G[groupName.."Bar"..(barID-1)], "BOTTOM", 0, -NeedToKnow_Settings.BarSpacing); |
else |
bar:SetPoint("TOPLEFT", group, "TOPLEFT"); |
end |
NeedToKnow.Bar_Update(groupID, barID); |
if ( not groupSettings.Enabled ) then |
NeedToKnow.ClearScripts(bar); |
end |
end |
for barID = groupSettings.NumberBars+1, NEEDTOKNOW.MAXBARS do |
local bar = _G[groupName.."Bar"..barID]; |
if ( bar ) then |
bar:Hide(); |
NeedToKnow.ClearScripts(bar); |
end |
end |
local resizeButton = _G[groupName.."ResizeButton"]; |
resizeButton:SetPoint("BOTTOMRIGHT", groupName.."Bar"..groupSettings.NumberBars, "BOTTOMRIGHT", 8, -8); |
if ( NeedToKnow_Settings["Locked"] ) then |
resizeButton:Hide(); |
else |
resizeButton:Show(); |
end |
-- Early enough in the loading process (before PLAYER_LOGIN), we might not |
-- know the position yet |
if groupSettings.Position then |
group:ClearAllPoints(); |
local point, relativePoint, xOfs, yOfs = unpack(groupSettings.Position); |
group:SetPoint(point, UIParent, relativePoint, xOfs, yOfs); |
group:SetScale(groupSettings.Scale); |
end |
if ( NeedToKnow_Visible and groupSettings.Enabled ) then |
group:Show(); |
else |
group:Hide(); |
end |
end |
-- ---- |
-- BARS |
-- ---- |
-- 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) |
local barName = "NeedToKnow_Group"..groupID.."Bar"..barID; |
local bar = _G[barName]; |
local background = _G[barName.."Background"]; |
bar.spark = _G[barName.."Spark"]; |
bar.text = _G[barName.."Text"]; |
bar.time = _G[barName.."Time"]; |
local groupSettings = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]; |
local barSettings = groupSettings["Bars"][barID]; |
bar.settings = barSettings; |
bar.auraName = barSettings.AuraName; |
bar.unit = barSettings.Unit; |
if ( barSettings.Unit == "mhand" or barSettings.Unit == "ohand" ) then |
bar.unit = "player"; |
end |
bar.nextUpdate = GetTime() + NEEDTOKNOW.UPDATE_INTERVAL; |
bar.fixedDuration = groupSettings.FixedDuration; |
bar:SetMinMaxValues(0,1); |
bar:SetValue(1); |
bar:SetStatusBarTexture(NeedToKnow.LSM:Fetch("statusbar", NeedToKnow_Settings["BarTexture"])); |
bar:SetStatusBarColor(barSettings.BarColor.r, barSettings.BarColor.g, barSettings.BarColor.b, barSettings.BarColor.a); |
bar:SetWidth(groupSettings.Width); |
bar.text:SetWidth(groupSettings.Width-60); |
background:SetWidth(groupSettings.Width + 2*NeedToKnow_Settings["BarPadding"]); |
background:SetHeight(bar:GetHeight() + 2*NeedToKnow_Settings["BarPadding"]); |
background:SetVertexColor(unpack(NeedToKnow_Settings["BkgdColor"])); |
-- Set up the Visual Cast Time overlay. It isn't a part of the template |
-- because most bars won't use it and thus don't need to pay the cost of |
-- a hidden frame |
if ( barSettings.vct_enabled ) then |
if ( nil == bar.vct ) then |
bar.vct = bar:CreateTexture(barName.."VisualCast", "ARTWORK"); |
bar.vct:SetPoint("TOPLEFT", bar, "TOPLEFT"); |
end |
local argb = barSettings.vct_color; |
bar.vct:SetTexture(argb.r, argb.g, argb.b, argb.a ); |
bar.vct:SetBlendMode("ADD"); |
bar.vct:SetHeight(bar:GetHeight()); |
elseif (nil ~= bar.vct) then |
bar.vct:Hide(); |
end |
if ( NeedToKnow_Settings["Locked"] ) then |
-- Set up the bar to be functional |
bar:EnableMouse(0); |
if ( barSettings.Enabled ) then |
NeedToKnow.SetScripts(bar); |
-- Events were cleared while unlocked, so need to check the bar again n ow |
NeedToKnow.Bar_AuraCheck(bar); |
else |
NeedToKnow.ClearScripts(bar); |
bar:Hide(); |
end |
else |
NeedToKnow.ClearScripts(bar); |
-- Set up the bar to be configured |
bar:EnableMouse(1); |
bar:Show(); |
bar.spark:Hide(); |
bar.time:Hide(); |
if ( bar.vct ) then |
bar.vct:SetWidth( bar:GetWidth() / 16); |
bar.vct:Show(); |
end |
local txt = bar.auraName; |
if ( barSettings.bDetectExtends == true ) then |
txt = txt .. " + 3s"; |
end |
bar.text:SetText(txt); |
if ( barSettings.Enabled ) then |
bar:SetAlpha(1); |
else |
bar:SetAlpha(0.4); |
end |
end |
end |
function NeedToKnow.SetScripts(bar) |
bar:SetScript("OnEvent", NeedToKnow.Bar_OnEvent); |
bar:SetScript("OnUpdate", NeedToKnow.Bar_OnUpdate); |
if ( "TOTEM" == bar.settings.BuffOrDebuff ) then |
bar:RegisterEvent("PLAYER_TOTEM_UPDATE"); |
elseif ( "mhand" == bar.settings.Unit or "ohand" == bar.settings.Unit ) then |
bar:RegisterEvent("UNIT_INVENTORY_CHANGED"); |
elseif ( bar.unit == "targettarget" ) then |
-- WORKAROUND: PLAYER_TARGET_CHANGED happens immediately, UNIT_TARGET every couple seconds |
bar:RegisterEvent("PLAYER_TARGET_CHANGED"); |
bar:RegisterEvent("UNIT_TARGET"); |
-- WORKAROUND: Don't get UNIT_AURA for targettarget |
bar:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED"); |
else |
bar:RegisterEvent("UNIT_AURA"); |
if ( bar.unit == "focus" ) then |
bar:RegisterEvent("PLAYER_FOCUS_CHANGED"); |
elseif ( bar.unit == "target" ) then |
bar:RegisterEvent("PLAYER_TARGET_CHANGED"); |
end |
end |
if bar.settings.bDetectExtends then |
bar:RegisterEvent("UNIT_SPELLCAST_SENT"); |
end |
end |
function NeedToKnow.ClearScripts(bar) |
bar:SetScript("OnEvent", nil); |
bar:SetScript("OnUpdate", nil); |
bar:UnregisterEvent("PLAYER_TARGET_CHANGED"); |
bar:UnregisterEvent("PLAYER_FOCUS_CHANGED"); |
bar:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED"); |
bar:UnregisterEvent("PLAYER_TOTEM_UPDATE"); |
bar:UnregisterEvent("UNIT_AURA"); |
bar:UnregisterEvent("UNIT_INVENTORY_CHANGED"); |
bar:UnregisterEvent("UNIT_TARGET"); |
bar:UnregisterEvent("UNIT_SPELLCAST_SENT"); |
end |
function NeedToKnow.Bar_OnEvent(self, event, ...) |
if ( event == "COMBAT_LOG_EVENT_UNFILTERED") then |
local combatEvent = select(2, ...); |
if ( NEEDTOKNOW.AURAEVENTS[combatEvent] ) then |
local guidTarget = select(6, ...) |
if ( guidTarget == UnitGUID(self.unit) ) then |
local idSpell, nameSpell = select(9, ...) |
if (self.auraName:find(idSpell) or |
self.auraName:find(nameSpell)) |
then |
NeedToKnow.Bar_AuraCheck(self); |
end |
end |
elseif ( combatEvent == "UNIT_DIED" ) and ( select(6, ...) == UnitGUID(self.unit) ) then |
NeedToKnow.Bar_AuraCheck(self); |
end |
elseif ( event == "PLAYER_TOTEM_UPDATE" ) then |
NeedToKnow.Bar_AuraCheck(self); |
elseif ( event == "UNIT_AURA" ) and ( select(1, ...) == self.unit ) then |
NeedToKnow.Bar_AuraCheck(self); |
elseif ( event == "UNIT_INVENTORY_CHANGED" and select(1, ...) == self.unit ) then |
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_SPELLCAST_SENT" ) then |
local unit, spell = select(1, ...); |
if unit == "player" and self.buffName == spell then |
local r = NeedToKnow.last_cast[spell]; |
if ( r and r.state == 0 ) then |
r.state = 1; |
NeedToKnow.nSent = NeedToKnow.nSent + 1; |
NeedToKnow_ExecutiveFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED"); |
end |
end |
end |
end |
-- AuraCheck calls on this to compute the "text" of the bar |
-- It is separated out like this in part to be hooked by other addons |
function NeedToKnow.ComputeBarText(buffName, count, extended) |
local text; |
if ( count > 1 ) then |
text = buffName.." ["..count.."]"; |
else |
text = buffName; |
end |
if ( extended and extended > 1 ) then |
text = text .. string.format(" + %.0fs", extended); |
end |
return text; |
end |
-- Called by NeedToKnow.UpdateVCT, which is called from AuraCheck and possibly |
-- by Bar_Update depending on vct_refresh. In addition to refactoring out some |
-- code from the long AuraCheck, this also provides a convenient hook for other addons |
function NeedToKnow.ComputeVCTDuration(bar) |
local vct_duration = 0; |
local spellToTime = bar.settings.vct_spell |
if ( nil == spellToTime or "" == spellToTime ) then |
spellToTime = bar.buffName; |
end |
local _, _, _, _, _, _, castTime = GetSpellInfo(spellToTime); |
if ( castTime ) then |
vct_duration = castTime / 1000; |
bar.vct_refresh = true; |
else |
bar.vct_refresh = false; |
end |
if ( bar.settings.vct_extra ) then |
vct_duration = vct_duration + bar.settings.vct_extra; |
end |
return vct_duration; |
end |
function NeedToKnow.UpdateVCT(bar) |
local vct_duration = NeedToKnow.ComputeVCTDuration(bar); |
if ( bar.duration ) then |
vct_width = (vct_duration * bar:GetWidth()) / bar.duration; |
if (vct_width > bar:GetWidth()) then |
vct_width = bar:GetWidth(); |
end |
else |
vct_width = 0; |
end |
if ( vct_width > 1 ) then |
bar.vct:SetWidth(vct_width); |
bar.vct:Show(); |
else |
bar.vct:Hide(); |
end |
end |
function NeedToKnow.ConfigureVisibleBar(bar, count, extended) |
local text = NeedToKnow.ComputeBarText(bar.buffName, count, extended); |
bar.text:SetText(text); |
-- Is this an aura with a finite duration? |
local vct_width = 0; |
if ( bar.duration > 0 ) then |
bar:SetMinMaxValues(0, bar.duration); |
local timeLeft = bar.expirationTime - GetTime(); |
bar:SetValue(timeLeft); |
-- Hide the spark if it's "off the bar" |
if ( timeLeft > bar.duration ) then |
bar.spark:Hide(); |
else |
bar.spark:SetPoint("CENTER", bar, "LEFT", bar:GetWidth()*timeLeft/bar.duration, 0); |
bar.spark:Show(); |
end |
-- Determine the size of the visual cast bar |
if ( bar.settings.vct_enabled ) then |
NeedToKnow.UpdateVCT(bar); |
end |
bar.time:Show(); |
else |
-- Hide the time text and spark for auras with "infinite" duration |
bar:SetMinMaxValues(0, 1); |
bar:SetValue(1); |
bar.time:Hide(); |
bar.spark:Hide(); |
if ( bar.vct ) then |
bar.vct:Hide(); |
end |
end |
end |
function NeedToKnow.GetUtilityTooltips() |
if ( not NeedToKnow_Tooltip1 ) then |
for idxTip = 1,2 do |
local ttname = "NeedToKnow_Tooltip"..idxTip; |
local tt = CreateFrame("GameTooltip", ttname) |
tt:SetOwner(UIParent, "ANCHOR_NONE") |
tt.left = {} |
tt.right = tt:CreateFontString() |
tt.right:SetFontObject(GameFontNormal) |
for i = 1, 30 do |
tt.left[i] = tt:CreateFontString() |
tt.left[i]:SetFontObject(GameFontNormal) |
tt:AddFontStrings(tt.left[i], tt.right) |
end |
end |
end |
local tt1,tt2 = NeedToKnow_Tooltip1, NeedToKnow_Tooltip2; |
tt1:ClearLines(); |
tt2:ClearLines(); |
return tt1,tt2; |
end |
function NeedToKnow.DetermineTempEnchantFromTooltip(i_invID) |
local tt1,tt2 = NeedToKnow.GetUtilityTooltips(); |
tt1:SetInventoryItem("player", i_invID); |
local n,h = tt1:GetItem(); |
tt2:SetHyperlink(h); |
-- Look for green lines present in tt1 that are missing from tt2 |
local nLines1, nLines2 = tt1:NumLines(), tt2:NumLines(); |
local i1, i2 = 1,1; |
while ( i1 <= nLines1 ) do |
local txt1 = tt1.left[i1]; |
if ( txt1:GetTextColor() ~= 0 ) then |
i1 = i1 + 1; |
elseif ( i2 <= nLines2 ) then |
local txt2 = tt2.left[i2]; |
if ( txt2:GetTextColor() ~= 0 ) then |
i2 = i2 + 1; |
elseif (txt1:GetText() == txt2:GetText()) then |
i1 = i1 + 1; |
i2 = i2 + 1; |
else |
break; |
end |
else |
break; |
end |
end |
if ( i1 <= nLines1 ) then |
local line = tt1.left[i1]:GetText(); |
local iter = line:gmatch("[^%s]+"); |
local name, rank = iter(), iter(); |
return name, rank; |
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 |
local settings = bar.settings; |
-- Determine if the bar should be showing anything |
if ( UnitExists(bar.unit) ) then |
local isWeapon; |
if ( "mhand" == settings.Unit or |
"ohand" == settings.Unit ) |
then |
isWeapon = true; |
end |
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); |
end |
if ( hasOffHandEnchant and "ohand" == settings.Unit ) then |
offHandEnchantName, offHandEnchantRank = NeedToKnow.DetermineTempEnchantFromTooltip(17); |
end |
end |
local startIndex=1; |
local numBuffs; |
_ , numBuffs = string.gsub(bar.auraName, "," , ",") |
for idxBuff=0, numBuffs do |
local endIndex = bar.auraName:find(",",startIndex,true) or (string.len(bar.auraName)+1) |
local barSpell = strtrim(string.sub(bar.auraName, startIndex, endIndex-1)) |
local filter = settings.BuffOrDebuff |
local _, nDigits = barSpell:find("^[0-9]+") |
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 = 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; |
count = 1; |
caster = "player"; |
break; |
end |
end |
elseif isWeapon then |
-- todo: use substring instead? |
if ( "mhand" == settings.Unit and mainHandEnchantName == 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 == barSpell ) then |
buffName = mainHandEnchantName |
count = offHandCharges; |
if ( count < 1 ) then count = 1 end |
duration = 1800 |
expirationTime = GetTime() + offHandExpiration/1000 |
caster = "player" |
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, buffIconPath; |
buffName, buffRank, buffIconPath, count, _, duration, expirationTime, caster, _, _, spellID = UnitAura(bar.unit, j, filter); |
if (not buffName) then |
break; |
end |
if (spellID == barID) then |
break; |
else |
buffName, count, duration, expirationTime, caster = nil; |
end |
j=j+1; |
end |
else |
buffName, _ , _, count, _, duration, expirationTime, caster = UnitAura(bar.unit, barSpell, nil, filter); |
end |
end |
if ( duration ) then |
break; |
else |
startIndex=endIndex+1; |
end |
end |
end |
-- There is an aura this bar is watching! Set it up |
duration = tonumber(duration); |
if ( duration ) then |
-- Handle duration increases |
local extended; |
if (settings.bDetectExtends) then |
local curStart = expirationTime - duration; |
local guidTarget = UnitGUID(bar.unit); |
if ( not NeedToKnow.last_cast[buffName] ) then |
NeedToKnow.last_cast[buffName] = { state=0 }; |
end |
local r = NeedToKnow.last_cast[buffName]; |
if ( not r[guidTarget] ) then |
r[guidTarget] = { time=curStart, dur=duration }; |
elseif ( r[guidTarget].dur == 0 ) then |
r[guidTarget].dur = duration |
else |
local rStart = r[guidTarget]; |
extended = expirationTime - rStart.time - rStart.dur; |
if ( extended > 1 ) then |
duration = rStart.dur; |
end |
end |
end |
bar.duration = tonumber(bar.fixedDuration) or duration; |
bar.expirationTime = expirationTime; |
bar.buffName = buffName; |
NeedToKnow.ConfigureVisibleBar(bar, count, extended); |
bar:Show(); |
else |
bar:Hide(); |
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; |
nMinutes = floor(i_fSeconds / 60); |
nSeconds = floor(i_fSeconds - nMinutes*60); |
return string.format("%02d:%02d", nMinutes, nSeconds); |
else |
string.format(SecondsToTimeAbbrev(i_fSeconds)); |
end |
end |
function NeedToKnow.Fmt_Float(i_fSeconds) |
return string.format("%0.1f", i_fSeconds); |
end |
function NeedToKnow.Bar_OnUpdate(self, elapsed) |
local now = GetTime(); |
if ( now > self.nextUpdate ) then |
self.nextUpdate = now + NEEDTOKNOW.UPDATE_INTERVAL; |
-- WORKAROUND: Although the existence of the enchant is correct at UNIT_INVENTORY_CHANGED |
-- the expiry time is not yet correct. So we update the expiration every update :( |
local origUnit = self.settings.Unit; |
if ( origUnit == "mhand" ) then |
-- The expiry time doesn't update right away, so we have to poll it |
local mhEnchant, mhExpire = GetWeaponEnchantInfo() |
self.expirationTime = GetTime() + mhExpire/1000; |
elseif ( origUnit == "ohand" ) then |
local _, _, _, ohEnchant, ohExpire = GetWeaponEnchantInfo() |
self.expirationTime = GetTime() + ohExpire/1000; |
end |
if ( self.duration > 0 ) then |
local timeLeft = self.expirationTime - GetTime(); |
timeLeft = max(0, timeLeft); |
self:SetValue(timeLeft); |
local fn = NeedToKnow[self.settings.TimeFormat]; |
local oldText = self.time:GetText(); |
local newText; |
if ( fn ) then |
newText = fn(timeLeft); |
else |
newText = string.format(SecondsToTimeAbbrev(timeLeft)); |
end |
if ( newText ~= oldText ) then |
self.time:SetText(newText); |
end |
if ( timeLeft <= self.duration ) then |
self.spark:SetPoint("CENTER", self, "LEFT", self:GetWidth()*timeLeft/self.duration, 0); |
self.spark:Show(); |
end |
if ( self.vct_refresh ) then |
NeedToKnow.UpdateVCT(self); |
end |
end |
end |
end |
## Interface: 30300 |
## Title: NeedToKnow - Updated! |
## Author: Kitjan |
## Version: 2.8.3 |
## Notes: Buff/debuff timer bars, original code by Nephthys of Hyjal-US Added support for multiple buffs per bar. |
## OptionalDeps: LibStub,LibSharedMedia-3.0 |
## DefaultState: Enabled |
## LoadOnDemand: 0 |
## SavedVariablesPerCharacter: NeedToKnow_Settings |
libs\LibStub\LibStub.lua |
libs\CallbackHandler-1.0\CallbackHandler-1.0.lua |
libs\LibSharedMedia-3.0\lib.xml |
NeedToKnow.xml |
NeedToKnow_Options.xml |
 |
-- If you want to be super helpful, you can translate this stuff into whatever non-enUS language you happen to know. Email them to me and I'll credit you. ZOMG 15 minutes of fame. Neph <lieandswell@yahoo.com> |
NEEDTOKNOW = {}; |
-- Untranslated defaults |
NEEDTOKNOW.BARMENU_TOTEM = "Totem"; |
NEEDTOKNOW.CMD_HIDE = "hide"; |
NEEDTOKNOW.CMD_SHOW = "show"; |
NEEDTOKNOW.BARMENU_TIMEFORMAT = "Time Format"; |
NEEDTOKNOW.FMT_SINGLEUNIT = "Single unit (2 m)"; |
NEEDTOKNOW.FMT_TWOUNITS = "Minutes and seconds (01:10)"; |
NEEDTOKNOW.FMT_FLOAT = "Fractional Seconds (70.1)"; |
NEEDTOKNOW.BARMENU_VISUALCASTTIME = "Visual Cast Time"; |
NEEDTOKNOW.BARMENU_VCT_ENABLE = "Enable for this bar"; |
NEEDTOKNOW.BARMENU_VCT_COLOR = "Overlay color"; |
NEEDTOKNOW.BARMENU_VCT_SPELL = "Choose cast time by spell"; |
NEEDTOKNOW.BARMENU_VCT_EXTRA = "Set additional time"; |
NEEDTOKNOW.BARMENU_MAIN_HAND = "Main Hand"; |
NEEDTOKNOW.BARMENU_OFF_HAND = "Off Hand"; |
NEEDTOKNOW.CHOOSE_VCT_SPELL_DIALOG = "Enter the name of a spell (in your spellbook) whose cast time will determine the base length of the visual cast time. If left blank, the aura name will be used as the spell name. To force this to be 0, type 0."; |
NEEDTOKNOW.CHOOSE_VCT_EXTRA_DIALOG = "Enter an amount of seconds that will be added to the cast time of the spell. Ex: 1.5"; |
if ( GetLocale() == "deDE" ) then |
-- Thanks, sp00n & Fxfighter EU-Echsenkessel! |
NEEDTOKNOW.BAR_TOOLTIP1 = "NeedToKnow"; |
NEEDTOKNOW.BAR_TOOLTIP2 = "Rechtsklick auf einen Balken für Einstellungen. Mehr Optionen sind im Blizzard Interface vorhanden. Zum Festsetzen und Aktivieren /needtoknow oder /ntk eingeben."; |
NEEDTOKNOW.RESIZE_TOOLTIP = "Klicken und ziehen, um die GröÃe zu ändern"; |
NEEDTOKNOW.BARMENU_ENABLE = "Leiste aktivieren"; |
NEEDTOKNOW.BARMENU_CHOOSENAME = "Buff/Debuff auswählen"; |
NEEDTOKNOW.CHOOSENAME_DIALOG = "Name des Buffs/Debuffs für diesen Balken angeben" |
NEEDTOKNOW.BARMENU_CHOOSEUNIT = "Betroffene Einheit"; |
NEEDTOKNOW.BARMENU_PLAYER = "Spieler"; |
NEEDTOKNOW.BARMENU_TARGET = "Ziel"; |
NEEDTOKNOW.BARMENU_FOCUS = "Fokus"; |
NEEDTOKNOW.BARMENU_PET = "Begleiter (Pet)"; |
NEEDTOKNOW.BARMENU_VEHICLE = "Vehicle"; |
NEEDTOKNOW.BARMENU_TARGETTARGET = "Ziel des Ziels"; |
NEEDTOKNOW.BARMENU_BUFFORDEBUFF = "Buff oder Debuff?"; |
NEEDTOKNOW.BARMENU_BUFF = "Buff"; |
NEEDTOKNOW.BARMENU_DEBUFF = "Debuff"; |
NEEDTOKNOW.BARMENU_ONLYMINE = "Nur Anzeigen wenn es selbst gezaubert wurde"; |
NEEDTOKNOW.BARMENU_BARCOLOR = "Farbe des Balken"; |
NEEDTOKNOW.BARMENU_CLEARSETTINGS = "Einstellungen löschen"; |
NEEDTOKNOW.UIPANEL_SUBTEXT1 = "Diese Einstellungen ändern die Anzahl und die Gruppierung der Balken."; |
NEEDTOKNOW.UIPANEL_SUBTEXT2 = "Die Darstellung funktioniert auch bei festgesetzen Balken. Wenn sie freigesetzt sind, können die Gruppierungen verschoben und deren GröÃe verändert werden. Ein Rechtsklick auf einen Balken zeigt weitere Einstellungsmöglichkeiten an. '/needtoknow' oder '/ntk' kann ebenfalls zum Festsetzen und Freistellen verwendet werden."; |
NEEDTOKNOW.UIPANEL_BARGROUP = "Gruppe "; |
NEEDTOKNOW.UIPANEL_NUMBERBARS = "Anzahl der Balken"; |
NEEDTOKNOW.UIPANEL_FIXEDDURATION = "Max bar duration"; |
NEEDTOKNOW.UIPANEL_BARTEXTURE = "Balkentextur"; |
NEEDTOKNOW.UIPANEL_BACKGROUNDCOLOR = "Background color"; |
NEEDTOKNOW.UIPANEL_BARSPACING = "Bar spacing"; |
NEEDTOKNOW.UIPANEL_BARPADDING = "Bar padding"; |
NEEDTOKNOW.UIPANEL_LOCK = "AddOn sperren"; |
NEEDTOKNOW.UIPANEL_UNLOCK = "AddOn entsperren"; |
NEEDTOKNOW.UIPANEL_TOOLTIP_ENABLEGROUP = "Diese Gruppierung aktivieren und anzeigen"; |
NEEDTOKNOW.UIPANEL_TOOLTIP_FIXEDDURATION = "Set the maximum length of bars for this group (in seconds). Leave empty to set dynamically per bar."; |
NEEDTOKNOW.UIPANEL_TOOLTIP_BARTEXTURE = "Die Textur für die Balken auswählen"; |
NEEDTOKNOW.CMD_RESET = "reset"; |
elseif ( GetLocale() == "koKR" ) then |
-- Thanks, metalchoir! |
NEEDTOKNOW.BAR_TOOLTIP1 = "NeedToKnow"; |
NEEDTOKNOW.BAR_TOOLTIP2 = "ì°í´ë¦: ë©ë´ ë¶ë¬ì¤ê¸°\nì¸ë¶ìµì ì 기본 ì¸í°íì´ì¤ ì¤ì ìì ê°ë¥\n/ntk ëª ë ¹ì´ë¡ ì ê·¼ íì ì ëì¨ ì¬ì©ê°ë¥"; |
NEEDTOKNOW.RESIZE_TOOLTIP = "ëëê·¸: í¬ê¸° ë³ê²½"; |
NEEDTOKNOW.BARMENU_ENABLE = "ë° ì¬ì©"; |
NEEDTOKNOW.BARMENU_CHOOSENAME = "ì ë ¥: 주문 ì´ë¦"; |
NEEDTOKNOW.CHOOSENAME_DIALOG = "ë°ì íìí ë²í ëë ëë²íì ì´ë¦ì ì ë ¥íì¸ì" |
NEEDTOKNOW.BARMENU_CHOOSEUNIT = "ì ë ì í"; |
NEEDTOKNOW.BARMENU_PLAYER = "본ì¸"; |
NEEDTOKNOW.BARMENU_TARGET = "ëì"; |
NEEDTOKNOW.BARMENU_FOCUS = "주ìëì"; |
NEEDTOKNOW.BARMENU_PET = "í«"; |
NEEDTOKNOW.BARMENU_VEHICLE = "íê²"; |
NEEDTOKNOW.BARMENU_TARGETTARGET = "ëìì ëì"; |
NEEDTOKNOW.BARMENU_BUFFORDEBUFF = "ì í: ë²í/ëë²í"; |
NEEDTOKNOW.BARMENU_SPELLID = "ì¬ì© 주문 ID"; |
NEEDTOKNOW.BARMENU_BUFF = "ë²í"; |
NEEDTOKNOW.BARMENU_DEBUFF = "ëë²í"; |
NEEDTOKNOW.BARMENU_ONLYMINE = "ìì ì´ ìì í ê²ë§ ë³´ì¬ì¤"; |
NEEDTOKNOW.BARMENU_BARCOLOR = "ë° ìì"; |
NEEDTOKNOW.BARMENU_CLEARSETTINGS = "ì¤ì ì´ê¸°í"; |
NEEDTOKNOW.UIPANEL_SUBTEXT1 = "ìëì ìµì ìì íì´ë¨¸ì 그룹과 ê° ê·¸ë£¹ë³ ë° ê°¯ì를 ì¤ì íì¤ ì ììµëë¤."; |
NEEDTOKNOW.UIPANEL_SUBTEXT2 = "ë°ë ì ê·¼ íì ìëí©ëë¤. íë ¸ì ë ë°ì ì´ëê³¼ í¬ê¸° ì¡°ì , ê·¸ë¦¬ê³ ê°ê°ì ë°ì ì°í´ë¦ì í¨ì¼ë¡ì¨ ì¤ì ì íì¤ ì ììµëë¤. '/needtoknow' ëë '/ntk' ëª ë ¹ì´ë¥¼ íµí´ìë ì ê¸/í ì íì´ ê°ë¥í©ëë¤."; |
NEEDTOKNOW.UIPANEL_BARGROUP = "그룹 "; |
NEEDTOKNOW.UIPANEL_NUMBERBARS = "ë° ê°¯ì"; |
NEEDTOKNOW.UIPANEL_FIXEDDURATION = "Max bar duration"; |
NEEDTOKNOW.UIPANEL_BARTEXTURE = "ë° í ì¤ì²"; |
NEEDTOKNOW.UIPANEL_BARSPACING = "ë° ê°ê²©"; |
NEEDTOKNOW.UIPANEL_BARPADDING = "ë°°ê²½ í¬ê¸°"; |
NEEDTOKNOW.UIPANEL_BACKGROUNDCOLOR = "ë°°ê²½ ìì"; |
NEEDTOKNOW.UIPANEL_LOCK = "ì ê¸"; |
NEEDTOKNOW.UIPANEL_UNLOCK = "í림"; |
NEEDTOKNOW.UIPANEL_TOOLTIP_ENABLEGROUP = "ì´ ê·¸ë£¹ì ë°ë¥¼ íì/ì¬ì©í©ëë¤."; |
NEEDTOKNOW.UIPANEL_TOOLTIP_FIXEDDURATION = "Set the maximum length of bars for this group (in seconds). Leave empty to set dynamically per bar."; |
NEEDTOKNOW.UIPANEL_TOOLTIP_BARTEXTURE = "ë° í ì¤ì²ë¥¼ ì ííì¸ì"; |
NEEDTOKNOW.CMD_RESET = "ì´ê¸°í"; |
elseif ( GetLocale() == "ruRU" ) then |
-- Thanks, Vlakarados! |
NEEDTOKNOW.BAR_TOOLTIP1 = "NeedToKnow"; |
NEEDTOKNOW.BAR_TOOLTIP2 = "Ðлик пÑавой кнопкой мÑÑи по полоÑе Ð´Ð»Ñ Ð½Ð°ÑÑÑойки. ÐолÑÑе наÑÑÑоек в ÐнÑеÑÑÐµÐ¹Ñ / ÐодиÑикаÑии / NeedToKnow менÑ. ÐвеÑÑи /needtoknow или /ntk Ð´Ð»Ñ Ð±Ð»Ð¾ÐºÐ¸Ñовки и вклÑÑениÑ."; |
NEEDTOKNOW.RESIZE_TOOLTIP = "ÐликнÑÑÑ Ð¸ ÑаÑиÑÑ Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÑазмеÑа"; |
NEEDTOKNOW.BARMENU_ENABLE = "ÐклÑÑиÑÑ Ð¿Ð¾Ð»Ð¾ÑÑ"; |
NEEDTOKNOW.BARMENU_CHOOSENAME = "ÐÑбÑаÑÑ Ð±Ð°ÑÑ/дебаÑÑ Ð´Ð»Ñ ÑлежениÑ"; |
NEEDTOKNOW.CHOOSENAME_DIALOG = "ÐведиÑе название баÑÑа/дебаÑÑа Ð´Ð»Ñ ÑлежениÑ" |
NEEDTOKNOW.BARMENU_CHOOSEUNIT = "Ð®Ð½Ð¸Ñ ÑлежениÑ"; |
NEEDTOKNOW.BARMENU_PLAYER = "ÐгÑок"; |
NEEDTOKNOW.BARMENU_TARGET = "ЦелÑ"; |
NEEDTOKNOW.BARMENU_FOCUS = "ФокÑÑ"; |
NEEDTOKNOW.BARMENU_PET = "ÐиÑомеÑ"; |
NEEDTOKNOW.BARMENU_VEHICLE = "СÑедÑÑво пеÑедвижениÑ"; |
NEEDTOKNOW.BARMENU_TARGETTARGET = "Ð¦ÐµÐ»Ñ Ñели"; |
NEEDTOKNOW.BARMENU_BUFFORDEBUFF = "ÐаÑÑ Ð¸Ð»Ð¸ дебаÑÑ?"; |
NEEDTOKNOW.BARMENU_SPELLID = "ÐÑполÑзÑйÑе ÑдоÑÑовеÑение лиÑноÑÑи пÑоизноÑÐµÐ½Ð¸Ñ Ð¿Ð¾ бÑквам"; |
NEEDTOKNOW.BARMENU_BUFF = "ÐаÑÑ"; |
NEEDTOKNOW.BARMENU_DEBUFF = "ÐебаÑÑ"; |
NEEDTOKNOW.BARMENU_ONLYMINE = "ÐоказÑваÑÑ ÑолÑко наложеннÑе мной"; |
NEEDTOKNOW.BARMENU_BARCOLOR = "Ð¦Ð²ÐµÑ Ð¿Ð¾Ð»Ð¾ÑÑ"; |
NEEDTOKNOW.BARMENU_CLEARSETTINGS = "ÐÑиÑÑиÑÑ Ð½Ð°ÑÑÑойки"; |
NEEDTOKNOW.UIPANEL_SUBTEXT1 = "ÐÑи наÑÑÑойки позволÑÑÑ Ð½Ð°ÑÑÑоиÑÑ Ð±Ð°ÑÑ/дебаÑÑ Ð¿Ð¾Ð»Ð¾ÑÑ ÑлежениÑ."; |
NEEDTOKNOW.UIPANEL_SUBTEXT2 = "ÐолоÑÑ ÑабоÑаÑÑ ÑолÑко когда заблокиÑÐ¾Ð²Ð°Ð½Ñ Ð³ÑÑппÑ. Ðожно менÑÑÑ ÑÐ°Ð·Ð¼ÐµÑ Ð¸ пеÑемеÑаÑÑ Ð³ÑÑÐ¿Ð¿Ñ Ð¿Ð¾Ð»Ð¾Ñ Ð¸ кликнÑÑÑ Ð¿Ñавой кнопкой мÑÑи Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸Ð½Ð´Ð¸Ð²Ð¸Ð´ÑалÑнÑÑ Ð½Ð°ÑÑÑоек. ÐвеÑÑи '/needtoknow' или '/ntk' to блокиÑовки/ÑазблокиÑовки."; |
NEEDTOKNOW.UIPANEL_BARGROUP = "ÐÑÑппа "; |
NEEDTOKNOW.UIPANEL_NUMBERBARS = "ÐолиÑеÑÑво полоÑ"; |
NEEDTOKNOW.UIPANEL_FIXEDDURATION = "ÐакÑималÑное вÑÐµÐ¼Ñ Ð½Ð° полоÑе"; |
NEEDTOKNOW.UIPANEL_BARTEXTURE = "ТекÑÑÑÑа полоÑ"; |
NEEDTOKNOW.UIPANEL_BARSPACING = "ÐÑомежÑÑок полоÑ"; |
NEEDTOKNOW.UIPANEL_BARPADDING = "УплоÑнение полоÑ"; |
NEEDTOKNOW.UIPANEL_BACKGROUNDCOLOR = "Ð¦Ð²ÐµÑ Ñона"; |
NEEDTOKNOW.UIPANEL_LOCK = "ÐаблокиÑоваÑÑ"; |
NEEDTOKNOW.UIPANEL_UNLOCK = "РазблокиÑоваÑÑ"; |
NEEDTOKNOW.UIPANEL_TOOLTIP_ENABLEGROUP = "ÐоказаÑÑ Ð¸ вклÑÑиÑÑ ÑÑÑ Ð³ÑÑÐ¿Ð¿Ñ Ð¿Ð¾Ð»Ð¾Ñ"; |
NEEDTOKNOW.UIPANEL_TOOLTIP_FIXEDDURATION = "УказаÑÑ Ð¼Ð°ÐºÑималÑное вÑÐµÐ¼Ñ Ð¿Ñобега полоÑÑ Ð² ÑекÑÐ½Ð´Ð°Ñ . ÐÑÑавиÑÑ Ð¿ÑÑÑÑм Ð´Ð»Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑкого вÑемени Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ полоÑÑ (полное вÑÐµÐ¼Ñ = длиÑелÑноÑÑÑ Ð±Ð°ÑÑа/дебаÑÑа)."; |
NEEDTOKNOW.UIPANEL_TOOLTIP_BARTEXTURE = "ÐÑбÑаÑÑ ÑекÑÑÑÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð»Ð¾Ñ."; |
NEEDTOKNOW.CMD_RESET = "ÑбÑоÑ"; |
else |
NEEDTOKNOW.BAR_TOOLTIP1 = "NeedToKnow"; |
NEEDTOKNOW.BAR_TOOLTIP2 = "Right click bars to configure. More options in the Blizzard interface options menu. Type /needtoknow to lock and enable."; |
NEEDTOKNOW.RESIZE_TOOLTIP = "Click and drag to change size"; |
NEEDTOKNOW.BARMENU_ENABLE = "Enable bar"; |
NEEDTOKNOW.BARMENU_CHOOSENAME = "Choose buff/debuff to time"; |
NEEDTOKNOW.CHOOSENAME_DIALOG = "Enter the name of the buff or debuff to time with this bar" |
NEEDTOKNOW.BARMENU_CHOOSEUNIT = "Unit to monitor"; |
NEEDTOKNOW.BARMENU_PLAYER = "Player"; |
NEEDTOKNOW.BARMENU_TARGET = "Target"; |
NEEDTOKNOW.BARMENU_FOCUS = "Focus"; |
NEEDTOKNOW.BARMENU_PET = "Pet"; |
NEEDTOKNOW.BARMENU_VEHICLE = "Vehicle"; |
NEEDTOKNOW.BARMENU_TARGETTARGET = "Target of Target"; |
NEEDTOKNOW.BARMENU_BUFFORDEBUFF = "Buff or debuff?"; |
NEEDTOKNOW.BARMENU_SPELLID = "Use SpellID"; |
NEEDTOKNOW.BARMENU_BUFF = "Buff"; |
NEEDTOKNOW.BARMENU_DEBUFF = "Debuff"; |
NEEDTOKNOW.BARMENU_ONLYMINE = "Only show if cast by self"; |
NEEDTOKNOW.BARMENU_BARCOLOR = "Bar color"; |
NEEDTOKNOW.BARMENU_CLEARSETTINGS = "Clear settings"; |
NEEDTOKNOW.UIPANEL_SUBTEXT1 = "These options allow you to customize the buff/debuff timer bars."; |
NEEDTOKNOW.UIPANEL_SUBTEXT2 = "Bars work when locked. When unlocked, you can move/size bar groups and right click individual bars for more settings. You can also type '/needtoknow' or '/ntk' to lock/unlock."; |
NEEDTOKNOW.UIPANEL_BARGROUP = "Group "; |
NEEDTOKNOW.UIPANEL_NUMBERBARS = "Number of bars"; |
NEEDTOKNOW.UIPANEL_FIXEDDURATION = "Max bar duration"; |
NEEDTOKNOW.UIPANEL_BARTEXTURE = "Bar texture"; |
NEEDTOKNOW.UIPANEL_BARSPACING = "Bar spacing"; |
NEEDTOKNOW.UIPANEL_BARPADDING = "Bar padding"; |
NEEDTOKNOW.UIPANEL_BACKGROUNDCOLOR = "Background color"; |
NEEDTOKNOW.UIPANEL_LOCK = "Lock"; |
NEEDTOKNOW.UIPANEL_UNLOCK = "Unlock"; |
NEEDTOKNOW.UIPANEL_TOOLTIP_ENABLEGROUP = "Show and enable this group of bars"; |
NEEDTOKNOW.UIPANEL_TOOLTIP_FIXEDDURATION = "Set the maximum length of bars for this group (in seconds). Leave empty to set dynamically per bar."; |
NEEDTOKNOW.UIPANEL_TOOLTIP_BARTEXTURE = "Choose the texture graphic for timer bars"; |
NEEDTOKNOW.CMD_RESET = "reset"; |
end |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Frame name="NeedToKnow_GroupOptionsTemplate" virtual="true"> |
<Size> |
<AbsDimension x="128" y="26"/> |
</Size> |
<Frames> |
<CheckButton name="$parentEnableButton" inherits="InterfaceOptionsCheckButtonTemplate"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" /> |
</Anchors> |
<HitRectInsets> |
<AbsInset left="0" right="-70" top="0" bottom="0"/> |
</HitRectInsets> |
<Scripts> |
<OnLoad> |
local text = getglobal(self:GetName().."Text"); |
text:SetText(NEEDTOKNOW.UIPANEL_BARGROUP..self:GetParent():GetID()); |
</OnLoad> |
<OnClick> |
NeedToKnow.GroupEnableButton_OnClick(self); |
</OnClick> |
<OnEnter> |
GameTooltip:SetOwner(this, "ANCHOR_TOPLEFT"); |
GameTooltip:SetText(NEEDTOKNOW.UIPANEL_TOOLTIP_ENABLEGROUP, nil, nil, nil, nil, 1); |
</OnEnter> |
<OnLeave> |
GameTooltip:Hide(); |
</OnLeave> |
</Scripts> |
</CheckButton> |
<Frame name="$parentNumberbarsWidget"> |
<Size> |
<AbsDimension x="64" y="32"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER" relativeTo="$parent" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="125" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="BACKGROUND"> |
<FontString name="$parentText" inherits="GameFontHighlight" justifyH="CENTER" text="X"> |
<Anchors> |
<Anchor point="CENTER" relativeTo="$parent" relativePoint="CENTER" /> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Frames> |
<Button name="$parentLeftButton"> |
<Size> |
<AbsDimension x="20" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="CENTER"> |
<Offset> |
<AbsDimension x="-8" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
NeedToKnow.NumberbarsButton_OnClick(self, -1); |
</OnClick> |
</Scripts> |
<NormalTexture file="Interface\Buttons\UI-SpellbookIcon-PrevPage-Up"/> |
<PushedTexture file="Interface\Buttons\UI-SpellbookIcon-PrevPage-Down"/> |
<DisabledTexture file="Interface\Buttons\UI-SpellbookIcon-PrevPage-Disabled"/> |
<HighlightTexture file="Interface\Buttons\UI-Common-MouseHilight" alphaMode="ADD"/> |
</Button> |
<Button name="$parentRightButton"> |
<Size> |
<AbsDimension x="20" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parent" relativePoint="CENTER"> |
<Offset> |
<AbsDimension x="8" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
NeedToKnow.NumberbarsButton_OnClick(self, 1); |
</OnClick> |
</Scripts> |
<NormalTexture file="Interface\Buttons\UI-SpellbookIcon-NextPage-Up"/> |
<PushedTexture file="Interface\Buttons\UI-SpellbookIcon-NextPage-Down"/> |
<DisabledTexture file="Interface\Buttons\UI-SpellbookIcon-NextPage-Disabled"/> |
<HighlightTexture file="Interface\Buttons\UI-Common-MouseHilight" alphaMode="ADD"/> |
</Button> |
</Frames> |
</Frame> |
<EditBox name="$parentFixedDurationBox" numeric="true" letters="3" autoFocus="false"> |
<Size> |
<AbsDimension x="30" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER" relativeTo="$parentNumberbarsWidget" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="40" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="BACKGROUND"> |
<Texture name="$parentLeft" file="Interface\Common\Common-Input-Border"> |
<Size> |
<AbsDimension x="8" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="-5" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<TexCoords left="0" right="0.0625" top="0" bottom="0.625"/> |
</Texture> |
<Texture name="$parentRight" file="Interface\Common\Common-Input-Border"> |
<Size> |
<AbsDimension x="8" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<TexCoords left="0.9375" right="1.0" top="0" bottom="0.625"/> |
</Texture> |
<Texture name="$parentMiddle" file="Interface\Common\Common-Input-Border"> |
<Size> |
<AbsDimension x="10" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentLeft" relativePoint="RIGHT"/> |
<Anchor point="RIGHT" relativeTo="$parentRight" relativePoint="LEFT"/> |
</Anchors> |
<TexCoords left="0.0625" right="0.9375" top="0" bottom="0.625"/> |
</Texture> |
</Layer> |
</Layers> |
<Scripts> |
<OnEnter> |
GameTooltip:SetOwner(this, "ANCHOR_TOPLEFT"); |
GameTooltip:SetText(NEEDTOKNOW.UIPANEL_TOOLTIP_FIXEDDURATION, nil, nil, nil, nil, 1); |
</OnEnter> |
<OnLeave> |
GameTooltip:Hide(); |
</OnLeave> |
<OnTabPressed> |
if ( IsShiftKeyDown() ) then |
local prevGroup = max(1, self:GetParent():GetID() - 1); |
_G[self:GetParent():GetParent():GetName().."Group"..prevGroup.."FixedDurationBox"]:SetFocus(); |
else |
local nextGroup = min(NEEDTOKNOW.MAXGROUPS, self:GetParent():GetID() + 1); |
_G[self:GetParent():GetParent():GetName().."Group"..nextGroup.."FixedDurationBox"]:SetFocus(); |
end |
</OnTabPressed> |
<OnEnterPressed> |
EditBox_ClearFocus(self); |
</OnEnterPressed> |
<OnEscapePressed> |
EditBox_ClearFocus(self); |
</OnEscapePressed> |
<OnTextChanged> |
NeedToKnow.FixedDurationEditBox_OnTextChanged(self); |
</OnTextChanged> |
<OnEditFocusLost> |
EditBox_ClearHighlight(self); |
</OnEditFocusLost> |
<OnEditFocusGained> |
EditBox_HighlightText(self); |
</OnEditFocusGained> |
</Scripts> |
<FontString inherits="ChatFontNormal"/> |
</EditBox> |
</Frames> |
</Frame> |
<Button name="NeedToKnow_ColorButtonTemplate" virtual="true"> |
<Size> |
<AbsDimension x="16" y="16"/> |
</Size> |
<Layers> |
<Layer level="BACKGROUND"> |
<Texture name="$parentSwatch"> |
<Size> |
<AbsDimension x="14" y="14"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="1.0"/> |
</Texture> |
</Layer> |
<Layer level="ARTWORK"> |
<FontString name="$parentLabel" inherits="GameFontHighlight" justifyH="LEFT" justifyV="TOP"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parent" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="8" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<NormalTexture name="$parentNormalTexture" file="Interface\ChatFrame\ChatFrameColorSwatch"/> |
</Button> |
<Frame name="InterfaceOptionsNeedToKnowPanel" hidden="true" parent="InterfaceOptionsFramePanelContainer"> |
<Layers> |
<Layer level="ARTWORK"> |
<FontString name="$parentTitle" text="NeedToKnow" inherits="GameFontNormalLarge" justifyH="LEFT" justifyV="TOP"> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="16" y="-16"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentVersion" inherits="GameFontNormalLarge" justifyH="LEFT" justifyV="TOP"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentTitle" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="4" y="-0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentSubText1" inherits="GameFontHighlightSmall" nonspacewrap="true" maxLines="3" justifyH="LEFT" justifyV="TOP"> |
<Size> |
<AbsDimension y="24" x="0"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentTitle" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-8"/> |
</Offset> |
</Anchor> |
<Anchor point="RIGHT"> |
<Offset> |
<AbsDimension x="-24" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentSubText2" inherits="GameFontHighlightSmall" nonspacewrap="false" justifyH="LEFT" justifyV="BOTTOM"> |
<Size> |
<AbsDimension x="0" y="48"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="128" y="16"/> |
</Offset> |
</Anchor> |
<Anchor point="RIGHT"> |
<Offset> |
<AbsDimension x="-24" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentNumberbarsLabel" inherits="GameFontNormalSmall"> |
<Anchors> |
<Anchor point="BOTTOM" relativeTo="$parentSubText1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="133" y="-28"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentFixedDurationLabel" inherits="GameFontNormalSmall"> |
<Anchors> |
<Anchor point="BOTTOM" relativeTo="$parentSubText1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="203" y="-28"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnLoad> |
this.name = "NeedToKnow"; |
this.default = NeedToKnow.Reset; |
this.cancel = NeedToKnow.Cancel; |
InterfaceOptions_AddCategory(self); |
NeedToKnow.UIPanel_OnLoad(self); |
</OnLoad> |
<OnShow> |
NeedToKnow_OldSettings = CopyTable(NeedToKnow_Settings); |
NeedToKnow.UIPanel_Update(); |
</OnShow> |
</Scripts> |
<Frames> |
<Frame name="$parentGroup1" inherits="NeedToKnow_GroupOptionsTemplate" id="1"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentSubText1" relativePoint="BOTTOMLEFT"> |
<Offset x="8" y="-40"/> |
</Anchor> |
</Anchors> |
</Frame> |
<Frame name="$parentGroup2" inherits="NeedToKnow_GroupOptionsTemplate" id="2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentGroup1" relativePoint="BOTTOMLEFT"> |
<Offset x="0" y="-8"/> |
</Anchor> |
</Anchors> |
</Frame> |
<Frame name="$parentGroup3" inherits="NeedToKnow_GroupOptionsTemplate" id="3"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentGroup2" relativePoint="BOTTOMLEFT"> |
<Offset x="0" y="-8"/> |
</Anchor> |
</Anchors> |
</Frame> |
<Frame name="$parentGroup4" inherits="NeedToKnow_GroupOptionsTemplate" id="4"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentGroup3" relativePoint="BOTTOMLEFT"> |
<Offset x="0" y="-8"/> |
</Anchor> |
</Anchors> |
</Frame> |
<Slider name="$parentBarSpacingSlider" inherits="OptionsSliderTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentSubText1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="16" y="-208"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLoad> |
getglobal(self:GetName().."Text"):SetText(NEEDTOKNOW.UIPANEL_BARSPACING); |
</OnLoad> |
<OnValueChanged> |
NeedToKnow_Settings["BarSpacing"] = value; |
NeedToKnow.Update(); |
</OnValueChanged> |
</Scripts> |
</Slider> |
<Slider name="$parentBarPaddingSlider" inherits="OptionsSliderTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentBarSpacingSlider" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-32"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLoad> |
getglobal(self:GetName().."Text"):SetText(NEEDTOKNOW.UIPANEL_BARPADDING); |
</OnLoad> |
<OnValueChanged> |
NeedToKnow_Settings["BarPadding"] = value; |
NeedToKnow.Update(); |
</OnValueChanged> |
</Scripts> |
</Slider> |
<Slider name="$parentBarTextureSlider" inherits="OptionsSliderTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentBarSpacingSlider" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="166" y="0" /> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="BACKGROUND"> |
<FontString name="$parentLabel" inherits="GameFontHighlight"> |
<Anchors> |
<Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="40" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnLoad> |
</OnLoad> |
<OnValueChanged> |
NeedToKnow.UpdateBarTextureSlider(self, value); |
</OnValueChanged> |
</Scripts> |
</Slider> |
<Button name="$parentBackgroundColorButton" inherits="NeedToKnow_ColorButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentBarTextureSlider" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="30" y="-24"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLoad> |
self:RegisterForClicks("LeftButtonUp"); |
</OnLoad> |
<OnClick> |
NeedToKnow.ChooseColor("BkgdColor"); |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentLockUnlockButton" inherits="UIPanelButtonTemplate"> |
<Size> |
<AbsDimension x="96" y="22"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="16" y="16"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
PlaySound("gsTitleOptionOK"); |
NeedToKnow.LockToggle(); |
NeedToKnow.LockUnlockButton_Update(); |
</OnClick> |
</Scripts> |
<NormalFont inherits="GameFontNormalSmall"/> |
<HighlightFont inherits="GameFontHighlightSmall"/> |
</Button> |
</Frames> |
</Frame> |
</Ui> |
-- -------------------------------------- |
-- TellMeWhen |
-- by Nephthys <Drunken Monkeys> of Hyjal |
-- -------------------------------------- |
NEEDTOKNOW.MAXBARSPACING = 24; |
NEEDTOKNOW.MAXBARPADDING = 12; |
local LSM = LibStub("LibSharedMedia-3.0", true); |
local textureList = LSM:List("statusbar"); |
function NeedToKnow.SlashCommand(cmd) |
if ( cmd == NEEDTOKNOW.CMD_RESET ) then |
NeedToKnow.Reset(); |
elseif ( cmd == NEEDTOKNOW.CMD_SHOW ) then |
NeedToKnow.Show(true); |
elseif ( cmd == NEEDTOKNOW.CMD_HIDE ) then |
NeedToKnow.Show(false); |
else |
NeedToKnow.LockToggle(); |
end |
end |
-- ----------------------- |
-- INTERFACE OPTIONS PANEL |
-- ----------------------- |
function NeedToKnow.UIPanel_OnLoad(self) |
local panelName = self:GetName(); |
local versionText = getglobal(panelName.."Version"); |
local subText1 = getglobal(panelName.."SubText1"); |
local subText2 = getglobal(panelName.."SubText2"); |
local numberbarsLabel = getglobal(panelName.."NumberbarsLabel"); |
local fixedDurationLabel = getglobal(panelName.."FixedDurationLabel"); |
local barTextureLabel = getglobal(panelName.."BarTextureSliderLabel"); |
local backgroundColorLabel = getglobal(panelName.."BackgroundColorButtonLabel"); |
versionText:SetText(NEEDTOKNOW.VERSION); |
subText1:SetText(NEEDTOKNOW.UIPANEL_SUBTEXT1); |
subText2:SetText(NEEDTOKNOW.UIPANEL_SUBTEXT2); |
numberbarsLabel:SetText(NEEDTOKNOW.UIPANEL_NUMBERBARS); |
numberbarsLabel:SetWidth(50); |
fixedDurationLabel:SetText(NEEDTOKNOW.UIPANEL_FIXEDDURATION); |
fixedDurationLabel:SetWidth(50); |
barTextureLabel:SetText(NEEDTOKNOW.UIPANEL_BARTEXTURE); |
backgroundColorLabel:SetText(NEEDTOKNOW.UIPANEL_BACKGROUNDCOLOR); |
end |
function NeedToKnow.UIPanel_Update() |
local settings = NeedToKnow_Settings; |
local panelName = "InterfaceOptionsNeedToKnowPanel"; |
for groupID = 1, NEEDTOKNOW.MAXGROUPS do |
NeedToKnow.GroupEnableButton_Update(groupID); |
NeedToKnow.NumberbarsWidget_Update(groupID); |
_G[panelName.."Group"..groupID.."FixedDurationBox"]:SetText(settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["FixedDuration"] or ""); |
end |
_G[panelName.."BackgroundColorButtonNormalTexture"]:SetVertexColor(unpack(NeedToKnow_Settings["BkgdColor"])); |
local barSpacingSlider = _G[panelName.."BarSpacingSlider"]; |
barSpacingSlider:SetMinMaxValues(0, NEEDTOKNOW.MAXBARSPACING); |
barSpacingSlider:SetValue(settings.BarSpacing); |
local barTextureSlider = _G[panelName.."BarTextureSlider"]; |
barTextureSlider:SetMinMaxValues(1, #(textureList)); |
barTextureSlider:SetValueStep(1); |
getglobal(panelName.."BarTextureSliderLow"):SetText(''); |
getglobal(panelName.."BarTextureSliderHigh"):SetText(''); |
getglobal(panelName.."BarTextureSliderLabel"):SetText(settings["BarTexture"]); |
getglobal(panelName.."BarTextureSliderText"):SetText('Bar Texture'); |
for i=1, #(textureList) do |
if textureList[i] == settings.BarTexture then |
barTextureSlider:SetValue(i); |
end |
end |
local barPaddingSlider = _G[panelName.."BarPaddingSlider"]; |
barPaddingSlider:SetMinMaxValues(0, NEEDTOKNOW.MAXBARPADDING); |
barPaddingSlider:SetValue(settings.BarPadding); |
NeedToKnow.LockUnlockButton_Update(); |
end |
function NeedToKnow.GroupEnableButton_Update(groupID) |
local button = _G["InterfaceOptionsNeedToKnowPanelGroup"..groupID.."EnableButton"]; |
button:SetChecked(NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Enabled"]); |
end |
function NeedToKnow.GroupEnableButton_OnClick(self) |
local groupID = self:GetParent():GetID(); |
if ( self:GetChecked() ) then |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Enabled"] = true; |
else |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Enabled"] = false; |
end |
NeedToKnow.Update(); |
end |
function NeedToKnow.NumberbarsWidget_Update(groupID) |
local widgetName = "InterfaceOptionsNeedToKnowPanelGroup"..groupID.."NumberbarsWidget"; |
local text = getglobal(widgetName.."Text"); |
local leftButton = getglobal(widgetName.."LeftButton"); |
local rightButton = getglobal(widgetName.."RightButton"); |
local numberBars = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["NumberBars"]; |
text:SetText(numberBars); |
leftButton:Enable(); |
rightButton:Enable(); |
if ( numberBars == 1 ) then |
leftButton:Disable(); |
elseif ( numberBars == NEEDTOKNOW.MAXBARS ) then |
rightButton:Disable(); |
end |
end |
function NeedToKnow.NumberbarsButton_OnClick(self, increment) |
local groupID = self:GetParent():GetParent():GetID(); |
local oldNumber = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["NumberBars"]; |
if ( oldNumber == 1 ) and ( increment < 0 ) then |
return; |
elseif ( oldNumber == NEEDTOKNOW.MAXBARS ) and ( increment > 0 ) then |
return; |
end |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["NumberBars"] = oldNumber + increment; |
NeedToKnow.Group_Update(groupID); |
NeedToKnow.NumberbarsWidget_Update(groupID); |
end |
function NeedToKnow.FixedDurationEditBox_OnTextChanged(self) |
local enteredText = self:GetText(); |
if enteredText == "" then |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][self:GetParent():GetID()]["FixedDuration"] = nil; |
else |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][self:GetParent():GetID()]["FixedDuration"] = enteredText; |
end |
NeedToKnow.Update(); |
end |
function NeedToKnow.UpdateBarTextureSlider(info, value) |
getglobal(info:GetName().."Label"):SetText(textureList[value]); |
NeedToKnow_Settings["BarTexture"] = textureList[value]; |
NeedToKnow.Update(); |
end |
function NeedToKnow.ChooseColor(variable) |
info = UIDropDownMenu_CreateInfo(); |
info.r, info.g, info.b, info.opacity = unpack(NeedToKnow_Settings[variable]); |
info.opacity = 1 - info.opacity; |
info.hasOpacity = true; |
info.opacityFunc = NeedToKnow.SetOpacity; |
info.swatchFunc = NeedToKnow.SetColor; |
info.cancelFunc = NeedToKnow.CancelColor; |
info.extraInfo = variable; |
-- Not sure if I should leave this state around or not. It seems like the |
-- correct strata to have it at anyway, so I'm going to leave it there for now |
ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG"); |
OpenColorPicker(info); |
end |
function NeedToKnow.SetColor() |
local variable = ColorPickerFrame.extraInfo; |
local r,g,b = ColorPickerFrame:GetColorRGB(); |
NeedToKnow_Settings[variable][1] = r; |
NeedToKnow_Settings[variable][2] = g; |
NeedToKnow_Settings[variable][3] = b; |
NeedToKnow.Update(); |
NeedToKnow.UIPanel_Update(); |
end |
function NeedToKnow.SetOpacity() |
local variable = ColorPickerFrame.extraInfo; |
NeedToKnow_Settings[variable][4] = 1 - OpacitySliderFrame:GetValue(); |
NeedToKnow.Update(); |
NeedToKnow.UIPanel_Update(); |
end |
function NeedToKnow.CancelColor(previousValues) |
if ( previousValues ) then |
local variable = ColorPickerFrame.extraInfo; |
NeedToKnow_Settings[variable] = {previousValues.r, previousValues.g, previousValues.b, previousValues.opacity}; |
NeedToKnow.Update(); |
NeedToKnow.UIPanel_Update(); |
end |
end |
function NeedToKnow.LockUnlockButton_Update() |
local text = getglobal("InterfaceOptionsNeedToKnowPanelLockUnlockButtonText"); |
if ( NeedToKnow_Settings["Locked"] ) then |
text:SetText(NEEDTOKNOW.UIPANEL_UNLOCK); |
else |
text:SetText(NEEDTOKNOW.UIPANEL_LOCK); |
end |
end |
function NeedToKnow.LockToggle() |
if ( NeedToKnow_Settings["Locked"] ) then |
NeedToKnow_Settings["Locked"] = false; |
else |
NeedToKnow_Settings["Locked"] = true; |
end |
NeedToKnow.Show(true); |
PlaySound("UChatScrollButton"); |
NeedToKnow.last_cast = {}; |
NeedToKnow.Update(); |
end |
function NeedToKnow.Reset() |
NeedToKnow_Settings = CopyTable(NEEDTOKNOW.DEFAULTS); |
NeedToKnow_Settings["Spec"][1]["Groups"][1]["Enabled"] = true; |
NeedToKnow_Settings["Spec"][2]["Groups"][1]["Enabled"] = true; |
for groupID = 1, NEEDTOKNOW.MAXGROUPS do |
local group = getglobal("NeedToKnow_Group"..groupID); |
group:ClearAllPoints(); |
group:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", 100, -100 - 100*groupID); |
end |
NeedToKnow.Update(); |
NeedToKnow.UIPanel_Update(); |
end |
function NeedToKnow.Cancel() |
NeedToKnow_Settings = CopyTable(NeedToKnow_OldSettings); |
NeedToKnow.Update(); |
end |
-- -------- |
-- BAR GUI |
-- -------- |
NeedToKnow.CurrentBar = { groupID = 1, barID = 1 }; -- a dirty hack, i know. |
StaticPopupDialogs["NEEDTOKNOW.CHOOSENAME_DIALOG"] = { |
text = NEEDTOKNOW.CHOOSENAME_DIALOG, |
button1 = ACCEPT, |
button2 = CANCEL, |
hasEditBox = 1, |
maxLetters = 255, |
OnAccept = function(iconNumber) |
local text = getglobal(this:GetParent():GetName().."EditBox"):GetText(); |
local variable = this:GetParent().variable; |
if ( nil ~= variable ) then |
NeedToKnow.BarMenu_ChooseName(text, variable); |
end |
end, |
EditBoxOnEnterPressed = function(iconNumber) |
local text = getglobal(this:GetParent():GetName().."EditBox"):GetText(); |
local variable = this:GetParent().variable; |
if ( nil ~= variable ) then |
NeedToKnow.BarMenu_ChooseName(text, variable); |
end |
this:GetParent():Hide(); |
end, |
EditBoxOnEscapePressed = function() |
this:GetParent():Hide(); |
end, |
OnHide = function() |
if ( ChatFrameEditBox:IsVisible() ) then |
ChatFrameEditBox:SetFocus(); |
end |
getglobal(this:GetName().."EditBox"):SetText(""); |
end, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
}; |
NeedToKnow.BarMenu_MoreOptions = { |
{ VariableName = "Enabled", MenuText = NEEDTOKNOW.BARMENU_ENABLE }, |
{ VariableName = "AuraName", MenuText = NEEDTOKNOW.BARMENU_CHOOSENAME, Type = "Dialog", DialogText = "CHOOSENAME_DIALOG" }, |
{ VariableName = "BuffOrDebuff", MenuText = NEEDTOKNOW.BARMENU_BUFFORDEBUFF, Type = "Submenu" }, |
{ VariableName = "Unit", MenuText = NEEDTOKNOW.BARMENU_CHOOSEUNIT, Type = "Submenu" }, |
{ VariableName = "TimeFormat", MenuText = NEEDTOKNOW.BARMENU_TIMEFORMAT, Type = "Submenu" }, |
{ VariableName = "VisualCastTime", MenuText = NEEDTOKNOW.BARMENU_VISUALCASTTIME, Type = "Submenu" }, |
{ VariableName = "bDetectExtends", MenuText = "Track duration increases" }, -- FIXME: Localization |
{ VariableName = "OnlyMine", MenuText = NEEDTOKNOW.BARMENU_ONLYMINE }, |
{ VariableName = "BarColor", MenuText = NEEDTOKNOW.BARMENU_BARCOLOR, Type = "Color" }, |
} |
NeedToKnow.BarMenu_SubMenus = { |
-- the keys on this table need to match the settings variable names |
BuffOrDebuff = { |
{ Setting = "HELPFUL", MenuText = NEEDTOKNOW.BARMENU_BUFF }, |
{ Setting = "HARMFUL", MenuText = NEEDTOKNOW.BARMENU_DEBUFF }, |
{ Setting = "TOTEM", MenuText = NEEDTOKNOW.BARMENU_TOTEM }, |
}, |
TimeFormat = { |
{ Setting = "Fmt_SingleUnit", MenuText = NEEDTOKNOW.FMT_SINGLEUNIT }, |
{ Setting = "Fmt_TwoUnits", MenuText = NEEDTOKNOW.FMT_TWOUNITS }, |
{ Setting = "Fmt_Float", MenuText = NEEDTOKNOW.FMT_FLOAT }, |
}, |
Unit = { |
{ Setting = "player", MenuText = NEEDTOKNOW.BARMENU_PLAYER }, |
{ Setting = "target", MenuText = NEEDTOKNOW.BARMENU_TARGET }, |
{ Setting = "targettarget", MenuText = NEEDTOKNOW.BARMENU_TARGETTARGET }, |
{ Setting = "focus", MenuText = NEEDTOKNOW.BARMENU_FOCUS }, |
{ Setting = "pet", MenuText = NEEDTOKNOW.BARMENU_PET }, |
{ Setting = "vehicle", MenuText = NEEDTOKNOW.BARMENU_VEHICLE }, |
{ Setting = "mhand", MenuText = NEEDTOKNOW.BARMENU_MAIN_HAND }, |
{ Setting = "ohand", MenuText = NEEDTOKNOW.BARMENU_OFF_HAND }, |
}, |
VisualCastTime = { |
{ VariableName = "vct_enabled", MenuText = NEEDTOKNOW.BARMENU_VCT_ENABLE }, |
{ VariableName = "vct_color", MenuText = NEEDTOKNOW.BARMENU_VCT_COLOR, Type = "Color" }, |
{ VariableName = "vct_spell", MenuText = NEEDTOKNOW.BARMENU_VCT_SPELL, Type = "Dialog", DialogText = "CHOOSE_VCT_SPELL_DIALOG" }, |
{ VariableName = "vct_extra", MenuText = NEEDTOKNOW.BARMENU_VCT_EXTRA, Type = "Dialog", DialogText = "CHOOSE_VCT_SPELL_DIALOG", Numeric=true }, |
}, |
}; |
function NeedToKnow.Bar_OnEnter(self) |
local tooltip = getglobal("GameTooltip"); |
GameTooltip_SetDefaultAnchor(tooltip, self); |
tooltip:AddLine(NEEDTOKNOW.BAR_TOOLTIP1, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b, 1); |
tooltip:AddLine(NEEDTOKNOW.BAR_TOOLTIP2, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1); |
tooltip:Show(); |
end |
function NeedToKnow.Bar_OnMouseUp(self, button) |
if ( button == "RightButton" ) then |
PlaySound("UChatScrollButton"); |
NeedToKnow.CurrentBar["barID"] = self:GetID(); |
NeedToKnow.CurrentBar["groupID"] = self:GetParent():GetID(); |
ToggleDropDownMenu(1, nil, getglobal(self:GetName().."DropDown"), "cursor", 0, 0); |
end |
end |
function NeedToKnow.BarMenu_AddButton(barSettings, i_desc, i_parent) |
info = UIDropDownMenu_CreateInfo(); |
local type = i_desc["Type"]; |
info.text = i_desc["MenuText"]; |
info.value = i_desc["VariableName"]; |
if ( nil == info.value and nil ~= i_desc["Setting"]) then |
info.value = i_parent; |
type = "SetVar"; |
end; |
local varSettings = barSettings[info.value]; |
if ( not varSettings and (type == "Check" or type == "Color") ) then |
print (string.format("NTK: Could not find %s in", info.value), barSettings); |
return |
end |
info.hasArrow = false; |
info.checked = false; |
--info.notCheckable = true; -- Doesn't prevent checking, just formats the line differently |
info.keepShownOnClick = true; |
if ( nil == type or type == "Check" ) then |
info.func = NeedToKnow.BarMenu_ToggleSetting; |
info.checked = (nil ~= varSettings and varSettings); |
info.notCheckable = false; |
elseif ( type == "SetVar" ) then |
info.func = NeedToKnow.BarMenu_ChooseSetting; |
info.value = i_desc["Setting"]; |
info.checked = (varSettings == info.value); |
info.notCheckable = false; |
info.keepShownOnClick = false; |
elseif ( type == "Submenu" ) then |
info.hasArrow = true; |
elseif ( type == "Dialog" ) then |
info.func = NeedToKnow.BarMenu_ShowNameDialog; |
info.keepShownOnClick = false; |
info.value = {variable = i_desc.VariableName, text = i_desc.DialogText, numeric = i_desc.Numeric }; |
elseif ( type == "Color" ) then |
info.hasColorSwatch = 1; |
info.hasOpacity = true; |
info.r = varSettings.r; |
info.g = varSettings.g; |
info.b = varSettings.b; |
info.opacity = 1 - varSettings.a; |
info.swatchFunc = NeedToKnow.BarMenu_SetColor; |
info.opacityFunc = NeedToKnow.BarMenu_SetOpacity; |
info.cancelFunc = NeedToKnow.BarMenu_CancelColor; |
info.func = UIDropDownMenuButton_OpenColorPicker; |
info.keepShownOnClick = false; |
end |
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL); |
if ( type == "Color" ) then |
-- Sadly, extraInfo isn't a field propogated to the button |
-- Code to get the button copied from UIDropDownMenu_AddButton |
local level = UIDROPDOWNMENU_MENU_LEVEL; |
local listFrame = _G["DropDownList"..level]; |
local index = listFrame and (listFrame.numButtons) or 1; |
local listFrameName = listFrame:GetName(); |
local button = getglobal(listFrameName.."Button"..index); |
button.extraInfo = info.value; |
end |
end |
function NeedToKnow.BarMenu_Initialize() |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
local barSettings = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID]; |
if ( UIDROPDOWNMENU_MENU_LEVEL == 2 ) then |
if ( UIDROPDOWNMENU_MENU_VALUE == "VisualCastTime" ) then |
-- Create a summary title for the visual cast time submenu |
local title = ""; |
if ( barSettings.vct_spell and "" ~= barSettings.vct_spell ) then |
title = title .. barSettings.vct_spell; |
end |
local fExtra = tonumber(barSettings.vct_extra); |
if ( fExtra and fExtra > 0 ) then |
if ("" ~= title) then |
title = title .. " + "; |
end |
title = title .. string.format("%0.1fs", fExtra); |
end |
if ( "" ~= title ) then |
local info = UIDropDownMenu_CreateInfo(); |
info.text = title; |
info.isTitle = true; |
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL); |
end |
end |
local subMenus = NeedToKnow.BarMenu_SubMenus; |
for index, value in ipairs(subMenus[UIDROPDOWNMENU_MENU_VALUE]) do |
NeedToKnow.BarMenu_AddButton(barSettings, value, UIDROPDOWNMENU_MENU_VALUE); |
end |
return; |
end |
-- show name |
if ( barSettings.AuraName ) and ( barSettings.AuraName ~= "" ) then |
local info = UIDropDownMenu_CreateInfo(); |
info.text = barSettings.AuraName; |
info.isTitle = true; |
UIDropDownMenu_AddButton(info); |
end |
local moreOptions = NeedToKnow.BarMenu_MoreOptions; |
for index, value in ipairs(moreOptions) do |
NeedToKnow.BarMenu_AddButton(barSettings, moreOptions[index]); |
end |
info = UIDropDownMenu_CreateInfo(); |
info.disabled = true; |
UIDropDownMenu_AddButton(info); |
-- clear settings |
info = UIDropDownMenu_CreateInfo(); |
info.text = NEEDTOKNOW.BARMENU_CLEARSETTINGS; |
info.func = NeedToKnow.BarMenu_ClearSettings; |
UIDropDownMenu_AddButton(info); |
if ( false == barSettings.OnlyMine ) then |
NeedToKnow.BarMenu_UncheckAndDisable(groupID, barID, "bDetectExtends"); |
end |
end |
function NeedToKnow.BarMenu_ToggleSetting(self, a1, a2, checked) |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][this.value] = this.checked; |
if ( this.value == "OnlyMine" ) then |
if ( false == this.checked ) then |
NeedToKnow.BarMenu_UncheckAndDisable(groupID, barID, "bDetectExtends"); |
else |
NeedToKnow.BarMenu_EnableItem(groupID, barID, "bDetectExtends"); |
end |
end |
NeedToKnow.Bar_Update(groupID, barID); |
end |
function NeedToKnow.BarMenu_UncheckAndDisable(groupID, barID, i_valueName) |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][i_valueName] = false; |
local listFrame = _G["DropDownList"..1]; |
local listFrameName = listFrame:GetName(); |
local n = listFrame.numButtons; |
for index=1,n do |
local button = getglobal(listFrameName.."Button"..index); |
local txt = button.value; |
if ( txt == i_valueName ) then |
getglobal(listFrameName.."Button"..index.."Check"):Hide(); |
button.checked = false; |
button:Disable(); |
break; |
end; |
end |
end |
function NeedToKnow.BarMenu_EnableItem(groupID, barID, i_valueName) |
local listFrame = _G["DropDownList"..1]; |
local listFrameName = listFrame:GetName(); |
local n = listFrame.numButtons; |
for index=1,n do |
local button = getglobal(listFrameName.."Button"..index); |
local txt = button.value; |
if ( txt == i_valueName ) then |
button:Enable(); |
break; |
end; |
end |
end |
function NeedToKnow.BarMenu_ChooseSetting(self, a1, a2, checked) |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][UIDROPDOWNMENU_MENU_VALUE] = this.value; |
NeedToKnow.Bar_Update(groupID, barID); |
end |
-- TODO: There has to be a better way to do this, this has pretty bad user feel |
function NeedToKnow.EditBox_Numeric_OnTextChanged(self, isUserInput) |
if ( isUserInput ) then |
local txt = self:GetText(); |
local culled = txt:gsub("[^0-9.]",""); -- Remove non-digits |
local iPeriod = culled:find("[.]"); |
if ( nil ~= iPeriod ) then |
local before = culled:sub(1, iPeriod); |
local after = string.gsub( culled:sub(iPeriod+1), "[.]", "" ); |
culled = before .. after; |
end |
if ( txt ~= culled ) then |
self:SetText(culled); |
end |
end |
if ( NeedToKnow.EditBox_Original_OnTextChanged ) then |
NeedToKnow.EditBox_Original_OnTextChanged(self, isUserInput); |
end |
end |
function NeedToKnow.BarMenu_ShowNameDialog(self, a1, a2, checked) |
StaticPopupDialogs["NEEDTOKNOW.CHOOSENAME_DIALOG"].text = NEEDTOKNOW[this.value.text]; |
local dialog = StaticPopup_Show("NEEDTOKNOW.CHOOSENAME_DIALOG"); |
dialog.variable = this.value.variable; |
local edit = getglobal(dialog:GetName().."EditBox"); |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
local curval = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][dialog.variable]; |
local numeric = this.value.numeric or false; |
-- TODO: There has to be a better way to do this, this has pretty bad user feel |
if ( nil == NeedToKnow.EditBox_Original_OnTextChanged ) then |
NeedToKnow.EditBox_Original_OnTextChanged = edit:GetScript("OnTextChanged"); |
end |
if ( numeric ) then |
edit:SetScript("OnTextChanged", NeedToKnow.EditBox_Numeric_OnTextChanged); |
else |
edit:SetScript("OnTextChanged", NeedToKnow.EditBox_Original_OnTextChanged); |
end |
edit:SetFocus(); |
edit:SetText(curval); |
end |
function NeedToKnow.BarMenu_ChooseName(text, variable) |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][variable] = text; |
NeedToKnow.Bar_Update(groupID, barID); |
end |
function MemberDump(v, bIndex) |
print("members") |
for index, value in pairs(v) do |
print(" ", index, value); |
end |
local mt = getmetatable(v) |
if ( mt ) then |
print("metatable") |
for index, value in pairs(mt) do |
print(" ", index, value); |
end |
if ( mt.__index and bIndex) then |
print("__index") |
for index, value in pairs(mt.__index) do |
print(" ", index, value); |
end |
end |
end |
end |
function NeedToKnow.BarMenu_SetColor() |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
local varSettings = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][ColorPickerFrame.extraInfo]; |
varSettings.r,varSettings.g,varSettings.b = ColorPickerFrame:GetColorRGB(); |
NeedToKnow.Bar_Update(groupID, barID); |
end |
function NeedToKnow.BarMenu_SetOpacity() |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
local varSettings = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][ColorPickerFrame.extraInfo]; |
varSettings.a = 1 - OpacitySliderFrame:GetValue(); |
NeedToKnow.Bar_Update(groupID, barID); |
end |
function NeedToKnow.BarMenu_CancelColor(previousValues) |
if ( previousValues.r ) then |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
local varSettings = NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID][ColorPickerFrame.extraInfo]; |
varSettings.r = previousValues.r; |
varSettings.g = previousValues.g; |
varSettings.b = previousValues.b; |
varSettings.a = 1 - previousValues.opacity; |
NeedToKnow.Bar_Update(groupID, barID); |
end |
end |
function NeedToKnow.BarMenu_ClearSettings() |
local groupID = NeedToKnow.CurrentBar["groupID"]; |
local barID = NeedToKnow.CurrentBar["barID"]; |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Bars"][barID] = CopyTable(NEEDTOKNOW.BAR_DEFAULTS); |
NeedToKnow.Bar_Update(groupID, barID); |
CloseDropDownMenus(); |
end |
-- ------------- |
-- RESIZE BUTTON |
-- ------------- |
function NeedToKnow.Resizebutton_OnEnter(self) |
local tooltip = getglobal("GameTooltip"); |
GameTooltip_SetDefaultAnchor(tooltip, self); |
tooltip:AddLine(NEEDTOKNOW.RESIZE_TOOLTIP, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1); |
tooltip:Show(); |
end |
function NeedToKnow.StartSizing(self, button) |
local group = self:GetParent(); |
local groupID = self:GetParent():GetID(); |
group.oldScale = group:GetScale(); |
group.oldX = group:GetLeft(); |
group.oldY = group:GetTop(); |
-- group:ClearAllPoints(); |
-- group:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", group.oldX, group.oldY); |
self.oldCursorX, self.oldCursorY = GetCursorPosition(UIParent); |
self.oldWidth = getglobal(group:GetName().."Bar1"):GetWidth(); |
self:SetScript("OnUpdate", NeedToKnow.Sizing_OnUpdate); |
end |
function NeedToKnow.Sizing_OnUpdate(self) |
local uiScale = UIParent:GetScale(); |
local cursorX, cursorY = GetCursorPosition(UIParent); |
local group = self:GetParent(); |
local groupID = self:GetParent():GetID(); |
-- calculate & set new scale |
local newYScale = group.oldScale * (cursorY/uiScale - group.oldY*group.oldScale) / (self.oldCursorY/uiScale - group.oldY*group.oldScale) ; |
local newScale = max(0.6, newYScale); |
group:SetScale(newScale); |
-- set new frame coords to keep same on-screen position |
local newX = group.oldX * group.oldScale / newScale; |
local newY = group.oldY * group.oldScale / newScale; |
group:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", newX, newY); |
-- calculate & set new bar width |
local newWidth = max(50, ((cursorX - self.oldCursorX)/uiScale + self.oldWidth * group.oldScale)/newScale); |
NeedToKnow.SetWidth(groupID, newWidth); |
end |
function NeedToKnow.SetWidth(groupID, width) |
for barID = 1, NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["NumberBars"] do |
local bar = getglobal("NeedToKnow_Group"..groupID.."Bar"..barID); |
local background = getglobal(bar:GetName().."Background"); |
local text = getglobal(bar:GetName().."Text"); |
bar:SetWidth(width); |
text:SetWidth(width-60); |
background:SetWidth(width + 2*NeedToKnow_Settings["BarPadding"]); |
end |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Width"] = width; -- move this to StopSizing? |
end |
function NeedToKnow.StopSizing(self, button) |
self:SetScript("OnUpdate", nil) |
local groupID = self:GetParent():GetID(); |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Scale"] = self:GetParent():GetScale(); |
NeedToKnow.SavePosition(self:GetParent(), groupID); |
end |
function NeedToKnow.SavePosition(group, groupID) |
groupID = groupID or group:GetID(); |
local point, _, relativePoint, xOfs, yOfs = group:GetPoint(); |
NeedToKnow_Settings["Spec"][NEEDTOKNOW.CURRENTSPEC]["Groups"][groupID]["Position"] = {point, relativePoint, xOfs, yOfs}; |
end |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Script file="LibSharedMedia-3.0.lua" /> |
</Ui> |
--[[ |
Name: LibSharedMedia-3.0 |
Revision: $Revision: 53 $ |
Author: Elkano (elkano@gmx.de) |
Inspired By: SurfaceLib by Haste/Otravi (troeks@gmail.com) |
Website: http://www.wowace.com/projects/libsharedmedia-3-0/ |
Description: Shared handling of media data (fonts, sounds, textures, ...) between addons. |
Dependencies: LibStub, CallbackHandler-1.0 |
License: LGPL v2.1 |
]] |
local MAJOR, MINOR = "LibSharedMedia-3.0", 90000 + tonumber(("$Revision: 53 $"):match("(%d+)")) |
local lib = LibStub:NewLibrary(MAJOR, MINOR) |
if not lib then return end |
local _G = getfenv(0) |
local pairs = _G.pairs |
local type = _G.type |
local band = _G.bit.band |
local table_insert = _G.table.insert |
local table_sort = _G.table.sort |
local locale = GetLocale() |
local locale_is_western |
local LOCALE_MASK = 0 |
lib.LOCALE_BIT_koKR = 1 |
lib.LOCALE_BIT_ruRU = 2 |
lib.LOCALE_BIT_zhCN = 4 |
lib.LOCALE_BIT_zhTW = 8 |
lib.LOCALE_BIT_western = 128 |
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0") |
lib.callbacks = lib.callbacks or CallbackHandler:New(lib) |
lib.DefaultMedia = lib.DefaultMedia or {} |
lib.MediaList = lib.MediaList or {} |
lib.MediaTable = lib.MediaTable or {} |
lib.MediaType = lib.MediaType or {} |
lib.OverrideMedia = lib.OverrideMedia or {} |
local defaultMedia = lib.DefaultMedia |
local mediaList = lib.MediaList |
local mediaTable = lib.MediaTable |
local overrideMedia = lib.OverrideMedia |
-- create mediatype constants |
lib.MediaType.BACKGROUND = "background" -- background textures |
lib.MediaType.BORDER = "border" -- border textures |
lib.MediaType.FONT = "font" -- fonts |
lib.MediaType.STATUSBAR = "statusbar" -- statusbar textures |
lib.MediaType.SOUND = "sound" -- sound files |
-- populate lib with default Blizzard data |
-- BACKGROUND |
if not lib.MediaTable.background then lib.MediaTable.background = {} end |
lib.MediaTable.background["Blizzard Dialog Background"] = [[Interface\DialogFrame\UI-DialogBox-Background]] |
lib.MediaTable.background["Blizzard Low Health"] = [[Interface\FullScreenTextures\LowHealth]] |
lib.MediaTable.background["Blizzard Out of Control"] = [[Interface\FullScreenTextures\OutOfControl]] |
lib.MediaTable.background["Blizzard Parchment"] = [[Interface\AchievementFrame\UI-Achievement-Parchment-Horizontal]] |
lib.MediaTable.background["Blizzard Parchment 2"] = [[Interface\AchievementFrame\UI-Achievement-Parchment]] |
lib.MediaTable.background["Blizzard Tabard Background"] = [[Interface\TabardFrame\TabardFrameBackground]] |
lib.MediaTable.background["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Background]] |
lib.MediaTable.background["Solid"] = [[Interface\Buttons\WHITE8X8]] |
-- BORDER |
if not lib.MediaTable.border then lib.MediaTable.border = {} end |
lib.MediaTable.border["None"] = [[Interface\None]] |
lib.MediaTable.border["Blizzard Dialog"] = [[Interface\DialogFrame\UI-DialogBox-Border]] |
lib.MediaTable.border["Blizzard Dialog Gold"] = [[Interface\DialogFrame\UI-DialogBox-Gold-Border]] |
lib.MediaTable.border["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Border]] |
-- FONT |
if not lib.MediaTable.font then lib.MediaTable.font = {} end |
local SML_MT_font = lib.MediaTable.font |
if locale == "koKR" then |
LOCALE_MASK = lib.LOCALE_BIT_koKR |
-- |
SML_MT_font["êµµì ê¸ê¼´"] = [[Fonts\2002B.TTF]] |
SML_MT_font["기본 ê¸ê¼´"] = [[Fonts\2002.TTF]] |
SML_MT_font["ë°ë¯¸ì§ ê¸ê¼´"] = [[Fonts\K_Damage.TTF]] |
SML_MT_font["íì¤í¸ ê¸ê¼´"] = [[Fonts\K_Pagetext.TTF]] |
-- |
lib.DefaultMedia["font"] = "기본 ê¸ê¼´" -- someone from koKR please adjust if needed |
-- |
elseif locale == "zhCN" then |
LOCALE_MASK = lib.LOCALE_BIT_zhCN |
-- |
SML_MT_font["伤害æ°å"] = [[Fonts\ZYKai_C.ttf]] |
SML_MT_font["é»è®¤"] = [[Fonts\ZYKai_T.ttf]] |
SML_MT_font["è天"] = [[Fonts\ZYHei.ttf]] |
-- |
lib.DefaultMedia["font"] = "é»è®¤" -- someone from zhCN please adjust if needed |
-- |
elseif locale == "zhTW" then |
LOCALE_MASK = lib.LOCALE_BIT_zhTW |
-- |
SML_MT_font["æ示è¨æ¯"] = [[Fonts\bHEI00M.ttf]] |
SML_MT_font["è天"] = [[Fonts\bHEI01B.ttf]] |
SML_MT_font["å·å®³æ¸å"] = [[Fonts\bKAI00M.ttf]] |
SML_MT_font["é è¨"] = [[Fonts\bLEI00D.ttf]] |
-- |
lib.DefaultMedia["font"] = "é è¨" -- someone from zhTW please adjust if needed |
elseif locale == "ruRU" then |
LOCALE_MASK = lib.LOCALE_BIT_ruRU |
-- |
SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]] |
SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]] |
SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]] |
SML_MT_font["Nimrod MT"] = [[Fonts\NIM_____.ttf]] |
SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]] |
-- |
lib.DefaultMedia.font = "Friz Quadrata TT" |
-- |
else |
LOCALE_MASK = lib.LOCALE_BIT_western |
locale_is_western = true |
-- |
SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]] |
SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]] |
SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]] |
SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]] |
-- |
lib.DefaultMedia.font = "Friz Quadrata TT" |
-- |
end |
-- STATUSBAR |
if not lib.MediaTable.statusbar then lib.MediaTable.statusbar = {} end |
lib.MediaTable.statusbar["Blizzard"] = [[Interface\TargetingFrame\UI-StatusBar]] |
lib.DefaultMedia.statusbar = "Blizzard" |
-- SOUND |
if not lib.MediaTable.sound then lib.MediaTable.sound = {} end |
lib.MediaTable.sound["None"] = [[Interface\Quiet.mp3]] -- Relies on the fact that PlaySound[File] doesn't error on non-existing input. |
lib.DefaultMedia.sound = "None" |
local function rebuildMediaList(mediatype) |
local mtable = mediaTable[mediatype] |
if not mtable then return end |
if not mediaList[mediatype] then mediaList[mediatype] = {} end |
local mlist = mediaList[mediatype] |
-- list can only get larger, so simply overwrite it |
local i = 0 |
for k in pairs(mtable) do |
i = i + 1 |
mlist[i] = k |
end |
table_sort(mlist) |
end |
function lib:Register(mediatype, key, data, langmask) |
if type(mediatype) ~= "string" then |
error(MAJOR..":Register(mediatype, key, data, langmask) - mediatype must be string, got "..type(mediatype)) |
end |
if type(key) ~= "string" then |
error(MAJOR..":Register(mediatype, key, data, langmask) - key must be string, got "..type(key)) |
end |
if mediatype == lib.MediaType.FONT and ((langmask and band(langmask, LOCALE_MASK) == 0) or not (langmask or locale_is_western)) then return false end |
mediatype = mediatype:lower() |
if not mediaTable[mediatype] then mediaTable[mediatype] = {} end |
local mtable = mediaTable[mediatype] |
if mtable[key] then return false end |
mtable[key] = data |
rebuildMediaList(mediatype) |
self.callbacks:Fire("LibSharedMedia_Registered", mediatype, key) |
return true |
end |
function lib:Fetch(mediatype, key, noDefault) |
local mtt = mediaTable[mediatype] |
local overridekey = overrideMedia[mediatype] |
local result = mtt and ((overridekey and mtt[overridekey] or mtt[key]) or (not noDefault and defaultMedia[mediatype] and mtt[defaultMedia[mediatype]])) or nil |
return result |
end |
function lib:IsValid(mediatype, key) |
return mediaTable[mediatype] and (not key or mediaTable[mediatype][key]) and true or false |
end |
function lib:HashTable(mediatype) |
return mediaTable[mediatype] |
end |
function lib:List(mediatype) |
if not mediaTable[mediatype] then |
return nil |
end |
if not mediaList[mediatype] then |
rebuildMediaList(mediatype) |
end |
return mediaList[mediatype] |
end |
function lib:GetGlobal(mediatype) |
return overrideMedia[mediatype] |
end |
function lib:SetGlobal(mediatype, key) |
if not mediaTable[mediatype] then |
return false |
end |
overrideMedia[mediatype] = (key and mediaTable[mediatype][key]) and key or nil |
self.callbacks:Fire("LibSharedMedia_SetGlobal", mediatype, overrideMedia[mediatype]) |
return true |
end |
function lib:GetDefault(mediatype) |
return defaultMedia[mediatype] |
end |
function lib:SetDefault(mediatype, key) |
if mediaTable[mediatype] and mediaTable[mediatype][key] and not defaultMedia[mediatype] then |
defaultMedia[mediatype] = key |
return true |
else |
return false |
end |
end |
------------------------------------------------------------------------ |
r56 | elkano | 2008-10-30 10:28:00 +0000 (Thu, 30 Oct 2008) | 1 line |
Changed paths: |
A /tags/2 (from /trunk:55) |
tagging r55 for release/embedding |
------------------------------------------------------------------------ |
r55 | arrowmaster | 2008-10-28 11:11:06 +0000 (Tue, 28 Oct 2008) | 1 line |
Changed paths: |
A /trunk/lib.xml |
revert commit 54 by FUCKING DUMBASS Jncl, NEVER TOUCH THIS PROJECT AGAIN FUCKING DUMBASS |
------------------------------------------------------------------------ |
r54 | jncl | 2008-10-28 11:02:15 +0000 (Tue, 28 Oct 2008) | 2 lines |
Changed paths: |
D /trunk/lib.xml |
LibSharedMedia-3.0: Removed lib.xml from root level |
- Current packaged version 50 has an incorrect TOC, but the one in the SVN is correct, so forcing a new package |
------------------------------------------------------------------------ |
r53 | elkano | 2008-10-23 13:45:10 +0000 (Thu, 23 Oct 2008) | 1 line |
Changed paths: |
M /trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
added a type check for mediatype and key to :Register |
------------------------------------------------------------------------ |
r52 | arrowmaster | 2008-10-14 21:30:05 +0000 (Tue, 14 Oct 2008) | 1 line |
Changed paths: |
M /tags/1 |
M /tags/1/CallbackHandler-1.0/CallbackHandler-1.0.lua |
M /tags/1/LibSharedMedia-3.0.toc |
M /tags/1/LibStub/LibStub.lua |
M /tags/1/tests |
M /tags/1/tests/LibSharedMedia-3.0 tests.lua |
M /tags/1/tests/wow_api.lua |
M /trunk |
M /trunk/.pkgmeta |
M /trunk/CallbackHandler-1.0/CallbackHandler-1.0.lua |
M /trunk/LibSharedMedia-3.0.toc |
M /trunk/LibStub/LibStub.lua |
A /trunk/lib.xml |
M /trunk/tests |
M /trunk/tests/LibSharedMedia-3.0 tests.lua |
M /trunk/tests/wow_api.lua |
Add lib.xml back to base directory since removing it broke some externals, and fix various svn properties |
------------------------------------------------------------------------ |
r51 | durcyn | 2008-10-14 20:59:32 +0000 (Tue, 14 Oct 2008) | 1 line |
Changed paths: |
M /trunk/LibSharedMedia-3.0.toc |
LibSharedMedia-3.0: if we're going to nuke the root lib.xml, maybe the toc should refer to the child lib.xml, no? |
------------------------------------------------------------------------ |
r49 | elkano | 2008-10-14 11:43:31 +0000 (Tue, 14 Oct 2008) | 1 line |
Changed paths: |
M /trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
LibSharedMedia-3.0: added some additional default media |
------------------------------------------------------------------------ |
r48 | elkano | 2008-10-14 11:25:18 +0000 (Tue, 14 Oct 2008) | 5 lines |
Changed paths: |
M /trunk/.pkgmeta |
M /trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
M /trunk/LibSharedMedia-3.0.toc |
D /trunk/lib.xml |
A /trunk/tests |
A /trunk/tests/LibSharedMedia-3.0 tests.lua |
A /trunk/tests/wow_api.lua |
LibSharedMedia-3.0 |
- removed base folder lib.xml by now they should all have changed to the subfolder |
- added some test code as separate file |
- cleaned up ruRU code |
- fixed TOC for WoW 3.x |
------------------------------------------------------------------------ |
r47 | nevcairiel | 2008-10-12 11:40:04 +0000 (Sun, 12 Oct 2008) | 1 line |
Changed paths: |
M /trunk/LibSharedMedia-3.0.toc |
Patch 3.0 prep: Remove LoD from Libraries that have no load manager (LoD+OptDep Bug) |
------------------------------------------------------------------------ |
r46 | nevcairiel | 2008-10-09 21:53:54 +0000 (Thu, 09 Oct 2008) | 1 line |
Changed paths: |
M /trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
WoWAce Post-Processing: Virtually inflate Library Revision numbers for proper upgrade path |
------------------------------------------------------------------------ |
r45 | ackis | 2008-10-04 06:04:47 +0000 (Sat, 04 Oct 2008) | 1 line |
Changed paths: |
M /trunk/.pkgmeta |
Fake commit to see if this will be packaged |
------------------------------------------------------------------------ |
r44 | root | 2008-09-29 21:29:16 +0000 (Mon, 29 Sep 2008) | 1 line |
Changed paths: |
A /trunk/.pkgmeta |
Facilitate WowAce-on-CurseForge transition |
------------------------------------------------------------------------ |
r42 | root | 2008-09-29 20:58:19 +0000 (Mon, 29 Sep 2008) | 1 line |
Changed paths: |
D /tmp/trunk/LibSharedMedia-3.0 |
A /trunk (from /tmp/trunk/LibSharedMedia-3.0:41) |
Importing old repo data under /trunk |
------------------------------------------------------------------------ |
r41 | StingerSoft | 2008-09-20 09:45:25 +0000 (Sat, 20 Sep 2008) | 2 lines |
Changed paths: |
M /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
LibSharedMedia-3.0 |
- added ruRU local |
------------------------------------------------------------------------ |
r34 | helium | 2008-03-31 10:09:02 +0000 (Mon, 31 Mar 2008) | 2 lines |
Changed paths: |
M /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.toc |
LibSharedMedia-3.0 |
- TOC 20400 |
------------------------------------------------------------------------ |
r33 | arrowmaster | 2008-03-27 12:26:53 +0000 (Thu, 27 Mar 2008) | 1 line |
Changed paths: |
A /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0 |
A /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
A /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0/lib.xml |
D /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
M /tmp/trunk/LibSharedMedia-3.0/lib.xml |
LibSharedMedia-3.0: move library to a sub directory so libs don't get included when using externals, leaving an extra lib.xml for backwards compat |
------------------------------------------------------------------------ |
r31 | nevcairiel | 2008-03-25 00:53:46 +0000 (Tue, 25 Mar 2008) | 1 line |
Changed paths: |
M /tmp/trunk/LibSharedMedia-3.0/CallbackHandler-1.0/CallbackHandler-1.0.lua |
LibSharedMedia-3.0: - update callbackhandler |
------------------------------------------------------------------------ |
r29 | elkano | 2008-03-04 11:13:28 +0000 (Tue, 04 Mar 2008) | 1 line |
Changed paths: |
M /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.toc |
LibSharedMedia-3.0: fixed slashes in toc |
------------------------------------------------------------------------ |
r28 | elkano | 2008-03-04 10:35:57 +0000 (Tue, 04 Mar 2008) | 1 line |
Changed paths: |
M /tmp/trunk/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
LibSharedMedia-3.0: adding the magic keyword |
------------------------------------------------------------------------ |
r27 | elkano | 2008-03-04 10:34:07 +0000 (Tue, 04 Mar 2008) | 1 line |
Changed paths: |
A /tmp/trunk/LibSharedMedia-3.0 (from /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0:26) |
LibSharedMedia-3.0: moving to trunk |
------------------------------------------------------------------------ |
r26 | elkano | 2008-02-26 07:52:48 +0000 (Tue, 26 Feb 2008) | 1 line |
Changed paths: |
M /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
LibSharedMedia-3.0: rearranged some code so upgrades will always overwrite default data (allowing updates to it) |
------------------------------------------------------------------------ |
r24 | elkano | 2008-02-21 11:55:51 +0000 (Thu, 21 Feb 2008) | 1 line |
Changed paths: |
M /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
LibSharedMedia-3.0: now rebuilds media list after sth new was registered |
------------------------------------------------------------------------ |
r23 | elkano | 2008-02-18 08:42:23 +0000 (Mon, 18 Feb 2008) | 3 lines |
Changed paths: |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/CallbackHandler-1.0 |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/CallbackHandler-1.0/CallbackHandler-1.0.lua |
D /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/CallbackHandler-1.0.lua |
M /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.toc |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibStub |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibStub/LibStub.lua |
D /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibStub.lua |
LibSharedMedia-3.0 |
- changing name shown to "Lib: SharedMedia-3.0" |
- move LS and CBH to subdirectories |
------------------------------------------------------------------------ |
r22 | nevcairiel | 2008-02-18 08:36:16 +0000 (Mon, 18 Feb 2008) | 2 lines |
Changed paths: |
D /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0 |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.lua (from /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.lua:20) |
M /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.toc |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/lib.xml (from /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/lib.xml:20) |
LibSharedMedia-3.0 |
- or maybe not |
------------------------------------------------------------------------ |
r21 | nevcairiel | 2008-02-18 08:14:05 +0000 (Mon, 18 Feb 2008) | 2 lines |
Changed paths: |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0 |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0/LibSharedMedia-3.0.lua (from /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.lua:20) |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0/lib.xml (from /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/lib.xml:20) |
D /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
M /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.toc |
D /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/lib.xml |
LibSharedMedia-3.0 |
- update layout to the library standard, so embeds dont get the libraries with it |
------------------------------------------------------------------------ |
r19 | elkano | 2008-02-05 14:40:25 +0000 (Tue, 05 Feb 2008) | 1 line |
Changed paths: |
M /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0 |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/CallbackHandler-1.0.lua |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.toc |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibStub.lua |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/lib.xml |
LibSharedMedia-3.0: add LibStub, CallBackHandler, toc and xml files |
------------------------------------------------------------------------ |
r17 | elkano | 2008-02-05 14:08:16 +0000 (Tue, 05 Feb 2008) | 3 lines |
Changed paths: |
A /tmp/branches/LibSharedMedia-3.0/Elkano |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0 |
A /tmp/branches/LibSharedMedia-3.0/Elkano/LibSharedMedia-3.0/LibSharedMedia-3.0.lua |
LibSharedMedia-3.0 |
- pushing version |
- updating my code |
------------------------------------------------------------------------ |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
--[[ $Id: CallbackHandler-1.0.lua 60548 2008-02-07 11:04:06Z nevcairiel $ ]] |
local MAJOR, MINOR = "CallbackHandler-1.0", 3 |
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) |
if not CallbackHandler then return end -- No upgrade needed |
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} |
local type = type |
local pcall = pcall |
local pairs = pairs |
local assert = assert |
local concat = table.concat |
local loadstring = loadstring |
local next = next |
local select = select |
local type = type |
local xpcall = xpcall |
local function errorhandler(err) |
return geterrorhandler()(err) |
end |
local function CreateDispatcher(argCount) |
local code = [[ |
local next, xpcall, eh = ... |
local method, ARGS |
local function call() method(ARGS) end |
local function dispatch(handlers, ...) |
local index |
index, method = next(handlers) |
if not method then return end |
local OLD_ARGS = ARGS |
ARGS = ... |
repeat |
xpcall(call, eh) |
index, method = next(handlers, index) |
until not method |
ARGS = OLD_ARGS |
end |
return dispatch |
]] |
local ARGS, OLD_ARGS = {}, {} |
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end |
code = code:gsub("OLD_ARGS", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(ARGS, ", ")) |
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler) |
end |
local Dispatchers = setmetatable({}, {__index=function(self, argCount) |
local dispatcher = CreateDispatcher(argCount) |
rawset(self, argCount, dispatcher) |
return dispatcher |
end}) |
-------------------------------------------------------------------------- |
-- CallbackHandler:New |
-- |
-- target - target object to embed public APIs in |
-- RegisterName - name of the callback registration API, default "RegisterCallback" |
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" |
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. |
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused) |
-- TODO: Remove this after beta has gone out |
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused") |
RegisterName = RegisterName or "RegisterCallback" |
UnregisterName = UnregisterName or "UnregisterCallback" |
if UnregisterAllName==nil then -- false is used to indicate "don't want this method" |
UnregisterAllName = "UnregisterAllCallbacks" |
end |
-- we declare all objects and exported APIs inside this closure to quickly gain access |
-- to e.g. function names, the "target" parameter, etc |
-- Create the registry object |
local events = setmetatable({}, meta) |
local registry = { recurse=0, events=events } |
-- registry:Fire() - fires the given event/message into the registry |
function registry:Fire(eventname, ...) |
if not rawget(events, eventname) or not next(events[eventname]) then return end |
local oldrecurse = registry.recurse |
registry.recurse = oldrecurse + 1 |
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...) |
registry.recurse = oldrecurse |
if registry.insertQueue and oldrecurse==0 then |
-- Something in one of our callbacks wanted to register more callbacks; they got queued |
for eventname,callbacks in pairs(registry.insertQueue) do |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
for self,func in pairs(callbacks) do |
events[eventname][self] = func |
-- fire OnUsed callback? |
if first and registry.OnUsed then |
registry.OnUsed(registry, target, eventname) |
first = nil |
end |
end |
end |
registry.insertQueue = nil |
end |
end |
-- Registration of a callback, handles: |
-- self["method"], leads to self["method"](self, ...) |
-- self with function ref, leads to functionref(...) |
-- "addonId" (instead of self) with function ref, leads to functionref(...) |
-- all with an optional arg, which, if present, gets passed as first argument (after self if present) |
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) |
if type(eventname) ~= "string" then |
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) |
end |
method = method or eventname |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
if type(method) ~= "string" and type(method) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) |
end |
local regfunc |
if type(method) == "string" then |
-- self["method"] calling style |
if type(self) ~= "table" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) |
elseif self==target then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) |
elseif type(self[method]) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) self[method](self,arg,...) end |
else |
regfunc = function(...) self[method](self,...) end |
end |
else |
-- function ref with self=object or self="addonId" |
if type(self)~="table" and type(self)~="string" then |
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) method(arg,...) end |
else |
regfunc = method |
end |
end |
if events[eventname][self] or registry.recurse<1 then |
-- if registry.recurse<1 then |
-- we're overwriting an existing entry, or not currently recursing. just set it. |
events[eventname][self] = regfunc |
-- fire OnUsed callback? |
if registry.OnUsed and first then |
registry.OnUsed(registry, target, eventname) |
end |
else |
-- we're currently processing a callback in this registry, so delay the registration of this new entry! |
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency |
registry.insertQueue = registry.insertQueue or setmetatable({},meta) |
registry.insertQueue[eventname][self] = regfunc |
end |
end |
-- Unregister a callback |
target[UnregisterName] = function(self, eventname) |
if not self or self==target then |
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) |
end |
if type(eventname) ~= "string" then |
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) |
end |
if rawget(events, eventname) and events[eventname][self] then |
events[eventname][self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(events[eventname]) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then |
registry.insertQueue[eventname][self] = nil |
end |
end |
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds |
if UnregisterAllName then |
target[UnregisterAllName] = function(...) |
if select("#",...)<1 then |
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) |
end |
if select("#",...)==1 and ...==target then |
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) |
end |
for i=1,select("#",...) do |
local self = select(i,...) |
if registry.insertQueue then |
for eventname, callbacks in pairs(registry.insertQueue) do |
if callbacks[self] then |
callbacks[self] = nil |
end |
end |
end |
for eventname, callbacks in pairs(events) do |
if callbacks[self] then |
callbacks[self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(callbacks) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
end |
end |
end |
end |
return registry |
end |
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it |
-- try to upgrade old implicit embeds since the system is selfcontained and |
-- relies on closures to work. |
-------------------- |
NeedToKnow |
by Kitjan |
-------------------- |
NeedToKnow allows you to monitor specific buffs and debuffs of your choosing as timer bars that always appear in a consistent place on your screen in a consistent color. It's especially useful for monitoring frequently used short-duration buffs and debuffs. For example, a rogue could configure NeedToKnow to show timer bars for Slice and Dice, Rupture, and their own stack of Deadly Poison VII. A death knight could use it to track their own diseases on a mob. NeedToKnow also works with procs and on-use trinkets. The number, size, position, and appearance of timer bars are all customizable. |
------------ |
Instructions |
------------ |
General options are available in the Blizzard interface options menu. You can type "/needtoknow" or "/ntk" to lock/unlock the addon. To configure individual bars, right click them while unlocked. Bars work while locked. |
When entering your settings, be careful with your spelling and capitalization. Also remember that buffs and debuffs sometimes have different names than the items and abilities that apply them. The Death Knight ability Icy Touch, for example, applies a DoT called Frost Fever. |
---------- |
Change log |
---------- |
2.8.0 |
- Added the ability to track increases in spell duration, especially useful for dps druids |
- Marked as being a 3.3 addon |
- Fixed: Took advantage of a new 3.3 API to get the spell id of active buffs and debuffs. Bars that check spellid should be much more reliable and, for example, be able to tell the difference between the two different Death's Verdict procs |
- Fixed: Totem timing is much more accurate |
- Fixed: Visual cast times now updates based on changes in haste and other casting-time-affecting abilities |
2.7.1 |
- Fixed: Accidentally removed the background color picker |
2.7.0 |
- Added options for how the time text is formatted. The current style is the default, with mm:ss and ss.t as other options |
- Added "visual cast time" overlay which can be used to tell when there's less than some critical amount of time left on an aura |
- Hid the spark when the aura lasts longer than the bar (either an infinite duration, or using the Max duration feature.) |
- Hid the time text when the aura has an infinite duration |
2.6.0 |
- Added support for a new "Buff or Debuff" type: Totem. Type in the name of the totem to watch for (can be a partial string.) |
- Fixed a parse error in the DE localization |
- Slightly improved performance of "target of target" |
- Added two new /ntk options: show and hide. They can be used to temporarily show and hide the ntk groups. |
2.5.2 |
-Changed event parsing to try to be more robust (see autobot's errors) |
2.5.1 |
-Trying a different strategy for identifying "only cast by me" spells |
-When editing the watched auras, the edit field starts with the current value |
-Configuring by SpellID is automatically detected and does not need a menu item checked |
2.5 |
-Fixed ToT issue |
-Added support for SpellID |
2.4.3 |
-Added SharedMedia support, uses LibSharedMedia-3.0 |
-Greatly improved performance |
2.4.2 |
-Fixed a bug with the multiple buffs per line |
-Fixed a small bug with resize button showing |
-Optimized performance slightly |
2.4.1 |
-Fixed character restriction on buff names, no accepts up to 255 characters. |
-Added Russian localization |
2.4 |
-Brought up to 3.2 API standards |
-Added multiple buffs/debuffs per bar |
-Dual-Specialization support |
Version 2.2 |
- Added option to show bars with a fixed maximum duration |
- Fixed an issue with targetoftarget |
- Added koKR localization. Thanks, metalchoir! |
- Added deDE localization. Thanks, sp00n & Fxfighter! |
Version 2.1 |
- Updated for WoW 3.1 |
- Can now track spells cast by player's pet or vehicle |
- Can now track buffs/debuffs on player's vehicle |
- Added options for background color, bar spacing, bar padding, bar opacity |
- Fixed a problem with buff charges not showing as consumed |
Version 2.0.1 |
- Updated for WoW 3.0 |
- Can now track (de)buffs applied by others |
- Added option to only show buffs/debuffs if applied by self |
Version 2.0 |
- Added support for monitoring debuffs |
- Added support for variable numbers of bars |
- Added support for separate groups of bars |
- Added support for monitoring buffs/debuffs on target, focus, pet, or target of target |
- Bars are now click-through while locked |
- Reminder icons have been been greatly expanded in functionality and split off into their own addon: TellMeWhen |
- Cleaner bar graphics |
- Users of older versions will need to re-enter settings |
Version 1.2 |
- Updated for WoW 2.4 API changes |
Version 1.1.1 |
- Icons should now work properly with item cooldowns. |
- Reset button should now work properly when you first use the AddOn. |
Version 1.1 |
- Icons will now show when reactive abilities (Riposte, Execute, etc.) are available. |
- Added options for bar color and texture. |
- Added graphical user interface. Most slash commands gone. |
- Added localization support. Translations would be much appreciated. |
- Users of older version will need to re-enter settings. |
Version 1.0 |
- Hello world! |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Script file="NeedToKnow_Localization.lua"/> |
<Script file="NeedToKnow.lua"/> |
<Script file="NeedToKnow_Options.lua"/> |
<Frame name="NeedToKnow_GroupTemplate" virtual="true"> |
<Size> |
<AbsDimension x="1" y="1"/> |
</Size> |
<Layers> |
<Layer level="BACKGROUND"> |
<Texture setAllPoints="true"> |
<Color r="0" g="0" b="0" a="0"/> |
</Texture> |
</Layer> |
</Layers> |
<Frames> |
<Button name="$parentResizeButton" frameStrata="HIGH"> |
<Size> |
<AbsDimension x="20" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"/> |
</Anchors> |
<Layers> |
<Layer level="BACKGROUND"> |
<Texture name="$parentTexture" file="Interface\AddOns\NeedToKnow\Textures\Resize"> |
<Size> |
<AbsDimension x="10" y="10"/> |
</Size> |
</Texture> |
</Layer> |
</Layers> |
<Scripts> |
<OnLoad> |
getglobal(self:GetName().."Texture"):SetVertexColor(0.6, 0.6, 0.6); |
</OnLoad> |
<OnMouseDown> |
NeedToKnow.StartSizing(self, button); |
</OnMouseDown> |
<OnMouseUp> |
NeedToKnow.StopSizing(self, button); |
</OnMouseUp> |
<OnEnter> |
NeedToKnow.Resizebutton_OnEnter(self); |
getglobal(self:GetName().."Texture"):SetVertexColor(1, 1, 1); |
</OnEnter> |
<OnLeave> |
GameTooltip:Hide(); |
getglobal(self:GetName().."Texture"):SetVertexColor(0.6, 0.6, 0.6); |
</OnLeave> |
</Scripts> |
</Button> |
</Frames> |
</Frame> |
<StatusBar name="NeedToKnow_BarTemplate" drawLayer="BORDER" toplevel="true" enableMouse="true" virtual="true"> |
<Size> |
<AbsDimension x="271" y="18"/> |
</Size> |
<BarTexture file="Interface\PaperDollInfoFrame\UI-Character-Skills-Bar"/> |
<BarColor r="1.0" g="0.7" b="0.0" a="1.0"/> |
<Layers> |
<Layer level="BACKGROUND"> |
<Texture name="$parentBackground" setAllPoints="true"> |
<Color r="1" g="1" b="1" a="1"/> |
<Size> |
<AbsDimension x="277" y="24"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Texture> |
</Layer> |
<Layer level="ARTWORK"> |
<FontString name="$parentText" inherits="GameFontHighlight" justifyH="LEFT"> |
<Size> |
<AbsDimension x="180" y="16"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT"> |
<Offset> |
<AbsDimension x="10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentTime" inherits="GameFontHighlight" justifyH="RIGHT"> |
<Size> |
<AbsDimension x="40" y="16"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
<Layer level="OVERLAY"> |
<Texture name="$parentSpark" file="Interface\CastingBar\UI-CastingBar-Spark" alphaMode="ADD"> |
<Size> |
<AbsDimension x="32" y="60"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER" relativeTo="$parent" relativePoint="RIGHT"/> |
</Anchors> |
</Texture> |
</Layer> |
</Layers> |
<Scripts> |
<OnLoad> |
self:RegisterForDrag("LeftButton"); |
</OnLoad> |
<OnEnter> |
NeedToKnow.Bar_OnEnter(self, motion); |
</OnEnter> |
<OnLeave> |
GameTooltip:Hide(); |
</OnLeave> |
<OnMouseUp> |
NeedToKnow.Bar_OnMouseUp(self, button); |
</OnMouseUp> |
<OnDragStart> |
self:GetParent():StartMoving(); |
</OnDragStart> |
<OnDragStop> |
self:GetParent():StopMovingOrSizing(); |
NeedToKnow.SavePosition(self:GetParent(), self:GetParent():GetID()); |
</OnDragStop> |
</Scripts> |
<Frames> |
<Frame name="$parentDropDown" inherits="UIDropDownMenuTemplate" hidden="true"> |
<Anchors> |
<Anchor point="TOP"/> |
</Anchors> |
<Scripts> |
<OnLoad> |
UIDropDownMenu_Initialize(this, NeedToKnow.BarMenu_Initialize, "MENU"); |
</OnLoad> |
<OnShow> |
UIDropDownMenu_Initialize(this, NeedToKnow.BarMenu_Initialize, "MENU"); |
</OnShow> |
</Scripts> |
</Frame> |
</Frames> |
</StatusBar> |
<Frame name="NeedToKnow_Group1" inherits="NeedToKnow_GroupTemplate" toplevel="true" movable="true" parent="UIParent" id="1"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="100" y="-200"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Frame> |
<Frame name="NeedToKnow_Group2" inherits="NeedToKnow_GroupTemplate" toplevel="true" movable="true" parent="UIParent" id="2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="100" y="-300"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Frame> |
<Frame name="NeedToKnow_Group3" inherits="NeedToKnow_GroupTemplate" toplevel="true" movable="true" parent="UIParent" id="3"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="100" y="-400"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Frame> |
<Frame name="NeedToKnow_Group4" inherits="NeedToKnow_GroupTemplate" toplevel="true" movable="true" parent="UIParent" id="4"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="100" y="-500"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Frame> |
</Ui> |