diff --git a/API.lua b/API.lua index fce110c4e..c9385340d 100644 --- a/API.lua +++ b/API.lua @@ -152,7 +152,7 @@ do end function API.SetSpellRename(spellId, text) if type(spellId) ~= "number" then error("Invalid spell ID for spell rename.") end - if type(text) ~= "string" or #text < 3 then error("Invalid spell text for spell rename.") end + if text and type(text) ~= "string" then error("Invalid spell text for spell rename.") end tbl[spellId] = text end end diff --git a/Core/BossPrototype.lua b/Core/BossPrototype.lua index 074be5bc1..dfd13f641 100644 --- a/Core/BossPrototype.lua +++ b/Core/BossPrototype.lua @@ -306,10 +306,18 @@ function boss:GetAllowWin() return self.allowWin and true or false end +--- Register private auras. +-- @param opts the options table function boss:SetPrivateAuraSounds(opts) for i = 1, #opts do - if type(opts[i]) ~= "table" then - opts[i] = { opts[i] } + local o = opts[i] + if type(o) ~= "table" then + opts[i] = { o } + elseif o.extra then -- XXX compat + for j, v in ipairs(o.extra) do + o[j + 1] = v + end + o.extra = nil end end self.privateAuraSoundOptions = opts @@ -581,7 +589,11 @@ boss.NewLocale = boss.GetLocale do local SetSpellRename = BigWigsAPI.SetSpellRename function boss:SetSpellRename(spellId, text) - SetSpellRename(spellId, text) + rawset(spells, spellId, text) + -- External API is ment for SPELL_CAST_START/SPELL_CAST_SUCCESS? so need a way to translate locale and ej keys to the cast id + if type(spellId) == "number" and spellId > 0 then + SetSpellRename(spellId, text) + end end end @@ -733,7 +745,7 @@ do args.sourceGUID, args.sourceName, args.sourceFlags, args.sourceRaidFlags = sourceGUID, sourceName, sourceFlags, sourceRaidFlags args.destGUID, args.destName, args.destFlags, args.destRaidFlags = destGUID, destName, destFlags, destRaidFlags args.spellId, args.spellName, args.spellSchool = spellId, spellName, spellSchool - args.time, args.extraSpellId, args.extraSpellName, args.amount = time, extraSpellId, amount, amount + args.time, args.extraSpellId, args.extraSpellName, args.amount = time, extraSpellId, rawget(spells, extraSpellId) or amount, nil self[func](self, args) end end @@ -746,7 +758,7 @@ do -- DEVS! Please ask if you need args attached to the table that we've missed out! args.sourceGUID, args.sourceName, args.sourceFlags, args.sourceRaidFlags = sourceGUID, sourceName, sourceFlags, sourceRaidFlags args.destGUID, args.destName, args.destFlags, args.destRaidFlags = destGUID, destName, destFlags, destRaidFlags - args.spellId, args.spellName, args.spellSchool = spellId, spellName, spellSchool + args.spellId, args.spellName, args.spellSchool = spellId, rawget(spells, spellId) or spellName, spellSchool args.time, args.extraSpellId, args.extraSpellName, args.amount = time, extraSpellId, amount, amount self[func](self, args) end @@ -1293,37 +1305,20 @@ do self.privateAuraSounds = {} local soundModule = plugins.Sounds if soundModule then - for _, option in next, self.privateAuraSoundOptions do - local spellId = option[1] - local default = soundModule:GetDefaultSound("privateaura") - - local key = ("pa_%d"):format(spellId) + local default = soundModule:GetDefaultSound("privateaura") + for _, opt in next, self.privateAuraSoundOptions do + local key = ("pa_%d"):format(opt[1]) local sound = soundModule:GetSoundFile(nil, nil, self.db.profile[key] or default) if sound then - local privateAuraSoundId = C_UnitAuras.AddPrivateAuraAppliedSound({ - spellID = spellId, - unitToken = "player", - soundFileName = sound, - outputChannel = "master", - }) - if type(privateAuraSoundId) == "number" then - self.privateAuraSounds[#self.privateAuraSounds + 1] = privateAuraSoundId - else - self:Error("Failed to register Private Aura %q with return: %s", spellId, tostring(privateAuraSoundId)) - end - if option.extra then - for _, id in next, option.extra do - local extrasSoundId = C_UnitAuras.AddPrivateAuraAppliedSound({ - spellID = id, - unitToken = "player", - soundFileName = sound, - outputChannel = "master", - }) - if type(extrasSoundId) == "number" then - self.privateAuraSounds[#self.privateAuraSounds + 1] = extrasSoundId - else - self:Error("Failed to register Private Aura %q with return: %s", id, tostring(extrasSoundId)) - end + for i = 1, #opt do + local privateAuraSoundId = C_UnitAuras.AddPrivateAuraAppliedSound({ + spellID = opt[i], + unitToken = "player", + soundFileName = sound, + outputChannel = "master", + }) + if privateAuraSoundId then + self.privateAuraSounds[#self.privateAuraSounds + 1] = privateAuraSoundId end end end @@ -1331,6 +1326,22 @@ do end end + -- rename updates + local renameModule = plugins.Rename + if renameModule then + -- update cleu spells + for spellId, key in next, self.renameSpells do + self:SetSpellRename(spellId, renameModule:GetName(self, key)) + end + -- update locale string overrides + if self.renameStringDefaults then + local ML = self:GetLocale() + for key, value in next, self.renameStringDefaults do + ML[key] = renameModule:GetName(self, key) or value + end + end + end + if not noEngage or noEngage ~= "NoEngage" then updateData(self) @@ -1606,8 +1617,16 @@ end --- Get a localized spell name from an id. Positive ids for spells (C_Spell.GetSpellName) and negative ids for journal-based section entries (C_EncounterJournal.GetSectionInfo). -- @number spellIdOrSectionId The spell id or the journal-based section id (as a negative number) +-- @bool[opt] noAltName Set to force an API lookup for the name -- @return spell name -function boss:SpellName(spellIdOrSectionId) +function boss:SpellName(spellIdOrSectionId, noAltName) + if noAltName then + if spellIdOrSectionId < 0 then + local info = C_EncounterJournal_GetSectionInfo(-spellIdOrSectionId) + return info and info.title + end + return GetSpellName(spellIdOrSectionId) + end return spells[spellIdOrSectionId] end @@ -3369,7 +3388,14 @@ do if englishSayMessages and englishText then SendChatMessage(format(on, englishText, myName), "SAY") else - SendChatMessage(format(L.on, msg and (type(msg) == "number" and spells[msg] or msg) or spells[key], myName), "SAY") + -- never use renames for chat messages + local text = msg + if not text then + text = self:SpellName(key, true) + elseif type(text) == "number" then + text = self:SpellName(text, true) + end + SendChatMessage(format(L.on, text, myName), "SAY") end end self:Debug(":Say", key, msg, directPrint, englishText) @@ -3388,7 +3414,14 @@ do if englishSayMessages and englishText then SendChatMessage(format(on, englishText, myName), "YELL") else - SendChatMessage(format(L.on, msg and (type(msg) == "number" and spells[msg] or msg) or spells[key], myName), "YELL") + -- never use renames for chat messages + local text = msg + if not text then + text = self:SpellName(key, true) + elseif type(text) == "number" then + text = self:SpellName(text, true) + end + SendChatMessage(format(L.on, text, myName), "YELL") end end self:Debug(":Yell", key, msg, directPrint, englishText) diff --git a/Core/BossPrototype_Classic.lua b/Core/BossPrototype_Classic.lua index 76f212ba6..1da1e9fbe 100644 --- a/Core/BossPrototype_Classic.lua +++ b/Core/BossPrototype_Classic.lua @@ -378,6 +378,8 @@ function boss:GetAllowWin() return self.allowWin and true or false end +--- Register private auras. +-- @param opts the options table function boss:SetPrivateAuraSounds(opts) for i = 1, #opts do if type(opts[i]) ~= "table" then @@ -1362,48 +1364,6 @@ do self:Debug(":Engage", "noEngage:", noEngage, self:GetEncounterID(), self.moduleName) - if self.privateAuraSoundOptions and not self.privateAuraSounds then - self.privateAuraSounds = {} - local soundModule = plugins.Sounds - if soundModule then - for _, option in next, self.privateAuraSoundOptions do - local spellId = option[1] - local default = soundModule:GetDefaultSound("privateaura") - - local key = ("pa_%d"):format(spellId) - local sound = soundModule:GetSoundFile(nil, nil, self.db.profile[key] or default) - if sound then - local privateAuraSoundId = C_UnitAuras.AddPrivateAuraAppliedSound({ - spellID = spellId, - unitToken = "player", - soundFileName = sound, - outputChannel = "master", - }) - if type(privateAuraSoundId) == "number" then - self.privateAuraSounds[#self.privateAuraSounds + 1] = privateAuraSoundId - else - self:Error("Failed to register Private Aura %q with return: %s", spellId, tostring(privateAuraSoundId)) - end - if option.extra then - for _, id in next, option.extra do - local extrasSoundId = C_UnitAuras.AddPrivateAuraAppliedSound({ - spellID = id, - unitToken = "player", - soundFileName = sound, - outputChannel = "master", - }) - if type(extrasSoundId) == "number" then - self.privateAuraSounds[#self.privateAuraSounds + 1] = extrasSoundId - else - self:Error("Failed to register Private Aura %q with return: %s", id, tostring(extrasSoundId)) - end - end - end - end - end - end - end - if not noEngage or noEngage ~= "NoEngage" then updateData(self) diff --git a/Core/Constants.lua b/Core/Constants.lua index a623ea901..35c4d35bb 100644 --- a/Core/Constants.lua +++ b/Core/Constants.lua @@ -196,7 +196,13 @@ function BigWigs:GetBossOptionDetails(module, option) optionType = type(option) end - local alternativeName = module.altNames and module.altNames[option] + local alternativeName + local renameModule = self:GetPlugin("Rename", true) + if renameModule then + alternativeName = renameModule:GetName(module, option) + else + alternativeName = module.altNames and module.altNames[option] + end local moduleLocale = module:GetLocale(true) if optionType == "string" then diff --git a/Core/Core.lua b/Core/Core.lua index 16fb10443..680a10ded 100644 --- a/Core/Core.lua +++ b/Core/Core.lua @@ -619,6 +619,46 @@ do end setupOptions(self) self.SetupOptions = nil + + local renameModule = plugins.Rename + if renameModule then + self.renameSpells = {} -- spellId -> option key + if self.altNames then + local ML = self:GetLocale() + for key, value in next, self.altNames do + if type(value) == "table" then + self.altNames[key] = value[1] -- reduce back to a simple lookup table + for i = 2, #value do + local v = value[i] + if type(v) == "number" then -- set rename for additional spell ids + self.renameSpells[v] = key + self:SetSpellRename(v, renameModule:GetName(self, key)) + elseif type(v) == "string" then -- locale string key + if not self.renameStrings then + self.renameStrings = {} -- option key -> locale string keys + self.renameStringDefaults = {} -- locale string key -> default value + end + if not self.renameStrings[key] then + self.renameStrings[key] = {} + end + table.insert(self.renameStrings[key], v) + self.renameStringDefaults[v] = ML[v] + end + end + end + end + end + -- set current renames + for _, key in next, self.toggleOptions do + if type(key) == "table" then + key = key[1] + end + if type(key) == "number" then + self.renameSpells[key] = key + self:SetSpellRename(key, renameModule:GetName(self, key)) + end + end + end end function core:RegisterBossModule(module) diff --git a/Options/Options.lua b/Options/Options.lua index a416a0fcb..00c3406e1 100644 --- a/Options/Options.lua +++ b/Options/Options.lua @@ -584,6 +584,42 @@ local advancedTabs = { }, } +local builtinOptions = { + berserk = true, + altpower = true, + infobox = true, + proximity = true, + stages = true, + warmup = true, + adds = true, + health = true, +} + +local function setRenameValue(widget, _, value) + local module = widget:GetUserData("module") + local key = widget:GetUserData("key") + local default = widget:GetUserData("default") + + local renameModule = BigWigs:GetPlugin("Rename") + if value == default then + value = nil + end + renameModule:SetName(module, key, value) + -- refresh + local dropdown = widget:GetUserData("dropdown") + local scrollFrame = widget:GetUserData("scrollFrame") + local bossOption = widget:GetUserData("option") + visibleSpellDescriptionWidgets = {} + scrollFrame:ReleaseChildren() + scrollFrame:AddChildren(getAdvancedToggleOption(scrollFrame, dropdown, module, bossOption)) + scrollFrame:PerformLayout() +end + +local function resetRenameValue(widget, _, value) + local editbox = widget:GetUserData("editbox") + editbox:Fire("OnEnterPressed", "") +end + function getAdvancedToggleOption(scrollFrame, dropdown, module, bossOption) local dbKey, name, desc, icon, alternativeName = BigWigs:GetBossOptionDetails(module, bossOption) local widgets = {} @@ -609,7 +645,7 @@ function getAdvancedToggleOption(scrollFrame, dropdown, module, bossOption) widgets[#widgets + 1] = idLabel local check = AceGUI:Create("CheckBox") - check:SetLabel(alternativeName and L.alternativeName:format(name, alternativeName) or name) + check:SetLabel(alternativeName and alternativeName ~= name and L.alternativeName:format(name, alternativeName) or name) check:SetTriState(true) check:SetFullWidth(true) check:SetDescription(desc) @@ -626,6 +662,94 @@ function getAdvancedToggleOption(scrollFrame, dropdown, module, bossOption) end widgets[#widgets + 1] = check + local renameModule = BigWigs:GetPlugin("Rename", true) + if not builtinOptions[dbKey] and renameModule then -- can't rename builtins + local customDesc = AceGUI:Create("Label") + customDesc:SetText("Set a custom name for the ability. This text will be used instead of the spell name in all messages and bars.") + customDesc:SetColor(1, 0.82, 0) + customDesc:SetFullWidth(true) + widgets[#widgets + 1] = customDesc + + local default = renameModule:GetDefaultName(module, dbKey) + local customName = AceGUI:Create("EditBox") + customName:SetText(renameModule:GetName(module, dbKey)) + customName:SetUserData("key", dbKey) + customName:SetUserData("default", default) + customName:SetUserData("scrollFrame", scrollFrame) + customName:SetUserData("dropdown", dropdown) + customName:SetUserData("module", module) + customName:SetUserData("option", bossOption) + customName:SetCallback("OnEnterPressed", setRenameValue) + customName:SetRelativeWidth(0.6) + widgets[#widgets + 1] = customName + + local customReset = AceGUI:Create("Button") + customReset:SetText("Reset") + customReset:SetDisabled(not alternativeName or alternativeName == default) + customReset:SetUserData("editbox", customName) + customReset:SetCallback("OnClick", resetRenameValue) + customReset:SetRelativeWidth(0.2) + widgets[#widgets + 1] = customReset + + local customDefault = AceGUI:Create("Button") + customDefault:SetText("Spell Name") + customDefault:SetDisabled(not alternativeName or alternativeName == name or default == module:SpellName(dbKey, true)) + customDefault:SetUserData("editbox", customName) + customDefault:SetUserData("spell", name) + customDefault:SetUserData("desc", "This ability has a custom name by default, click this button to use the spell name instead.") + customDefault:SetCallback("OnEnter", slaveOptionMouseOver) + customDefault:SetCallback("OnLeave", bwTooltip_Hide) + customDefault:SetCallback("OnClick", function(widget, event, value) + local editbox = widget:GetUserData("editbox") + editbox:Fire("OnEnterPressed", widget:GetUserData("spell")) + end) + customDefault:SetRelativeWidth(0.2) + widgets[#widgets + 1] = customDefault + + if module.renameStrings and module.renameStrings[dbKey] then + local spacer = AceGUI:Create("Label") + spacer:SetFullWidth(true) + widgets[#widgets + 1] = spacer + + for _, stringKey in next, module.renameStrings[dbKey] do + local default = module.renameStringDefaults[stringKey] + local text = renameModule:GetName(module, stringKey) or default + -- XXX just title case the key for now + local label = stringKey:gsub("_", " "):gsub("(%a)(%w*)", function(a, b) return a:upper()..b:lower() end) + -- suffix -> localized category + -- local titles = { + -- me = "On Me", + -- cast = "Cast Message", + -- castbar = "Cast Bar", + -- singular = "Singular Form (Target Message/Bar)", + -- } + -- local suffix = stringKey:match("_(.-)$") + -- local label = titles[suffix] + + local customStringName = AceGUI:Create("EditBox") + customStringName:SetLabel(label) + customStringName:SetText(text) + customStringName:SetUserData("key", stringKey) + customStringName:SetUserData("default", default) + customStringName:SetUserData("scrollFrame", scrollFrame) + customStringName:SetUserData("dropdown", dropdown) + customStringName:SetUserData("module", module) + customStringName:SetUserData("option", bossOption) + customStringName:SetCallback("OnEnterPressed", setRenameValue) + customStringName:SetRelativeWidth(0.6) + widgets[#widgets + 1] = customStringName + + local customStringReset = AceGUI:Create("Button") + customStringReset:SetText("Reset") + customStringReset:SetDisabled(text == default) + customStringReset:SetUserData("editbox", customStringName) + customStringReset:SetCallback("OnClick", resetRenameValue) + customStringReset:SetRelativeWidth(0.4) + widgets[#widgets + 1] = customStringReset + end + end + end + -- Create role-specific secondary checkbox for i, key in next, BigWigs:GetRoleOptions() do local flag = C[key] @@ -732,6 +856,16 @@ local function getDefaultToggleOption(scrollFrame, dropdown, module, bossOption) return dropdown end + if alternativeName == name then alternativeName = nil end -- altname set to spell name + if module.renameStrings and module.renameStrings[dbKey] then + local count = #module.renameStrings[dbKey] + if alternativeName then + alternativeName = ("%s, +%d"):format(alternativeName, count) + else + alternativeName = ("+%d"):format(count) + end + end + local check = AceGUI:Create("CheckBox") check:SetLabel(alternativeName and L.alternativeName:format(name, alternativeName) or name) check:SetTriState(true) @@ -780,7 +914,7 @@ local function getDefaultToggleOption(scrollFrame, dropdown, module, bossOption) local flagIcons = {} local showFlags = { "TANK_HEALER", "TANK", "HEALER", "DISPEL", - "EMPHASIZE", "ME_ONLY", "ME_ONLY_EMPHASIZE", "COUNTDOWN", "CASTBAR_COUNTDOWN", "FLASH", "ICON", "SAY", "SAY_COUNTDOWN", + "EMPHASIZE", "ME_ONLY", "ME_ONLY_EMPHASIZE", "CASTBAR", "COUNTDOWN", "CASTBAR_COUNTDOWN", "FLASH", "ICON", "SAY", "SAY_COUNTDOWN", "PROXIMITY", "INFOBOX", "ALTPOWER", "NAMEPLATE", "PRIVATE", } for i = 1, #showFlags do @@ -953,6 +1087,7 @@ local function populatePrivateAuraOptions(widget) local privateAuraSoundOptions = widget:GetUserData("privateAuraSoundOptions") local soundList = LibStub("LibSharedMedia-3.0"):List("sound") + local defaultSound = soundModule:GetDefaultSound("privateaura") -- preserve module order for _, module in ipairs(widget:GetUserData("moduleList")) do local options = privateAuraSoundOptions[module] @@ -965,9 +1100,8 @@ local function populatePrivateAuraOptions(widget) scrollFrame:AddChild(header) for _, option in ipairs(options) do local spellId = option[1] - local default = soundModule:GetDefaultSound("privateaura") local key = ("pa_%d"):format(spellId) - local id = option.option or spellId + local id = option.tooltip or option.option or spellId -- XXX compat local name = loader.GetSpellName(id) local texture = loader.GetSpellTexture(id) @@ -976,18 +1110,17 @@ local function populatePrivateAuraOptions(widget) icon:SetImage(texture, 0.07, 0.93, 0.07, 0.93) icon:SetImageSize(40, 40) icon:SetRelativeWidth(0.1) - icon:SetUserData("bossOption", id) + icon:SetUserData("spellId", id) icon:SetUserData("updateTooltip", true) icon:SetCallback("OnEnter", function(widget) bwTooltip:SetOwner(widget.frame, "ANCHOR_RIGHT") - bwTooltip:SetSpellByID(widget:GetUserData("bossOption")) + bwTooltip:SetSpellByID(widget:GetUserData("spellId")) bwTooltip:Show() end) icon:SetCallback("OnLeave", bwTooltip_Hide) local dropdown = AceGUI:Create("SharedDropdown") if option.mythic then - -- dropdown:SetLabel(name .. _G.CreateTextureMarkup(521749, 256, 64, 24, 24, 0.5, 0.625, 0.5, 1)) -- 521749 = Interface\EncounterJournal\UI-EJ-Icons dropdown:SetLabel(name .. "|TInterface\\AddOns\\BigWigs\\Media\\Icons\\Menus\\Mythic:20|t") else dropdown:SetLabel(name) @@ -995,7 +1128,7 @@ local function populatePrivateAuraOptions(widget) dropdown:SetList(soundList, nil, "DDI-Sound") dropdown:SetRelativeWidth(0.88) dropdown:SetUserData("key", key) - dropdown:SetUserData("default", default) + dropdown:SetUserData("default", defaultSound) dropdown:SetUserData("module", module) dropdown:SetCallback("OnValueChanged", function(widget, _, value) local key = widget:GetUserData("key") @@ -1007,7 +1140,7 @@ local function populatePrivateAuraOptions(widget) end module.db.profile[key] = value end) - local value = module.db.profile[key] or default + local value = module.db.profile[key] or defaultSound for i, v in next, soundList do if v == value then dropdown:SetValue(i) @@ -1032,7 +1165,7 @@ local function populatePrivateAuraOptions(widget) reset:SetCallback("OnClick", function(widget) for module, options in next, widget:GetUserData("privateAuraSoundOptions") do for _, option in next, options do - local key = "pa_" .. option[1] + local key = ("pa_%d"):format(option[1]) module.db.profile[key] = nil end end diff --git a/Plugins/Rename.lua b/Plugins/Rename.lua new file mode 100644 index 000000000..e8e66a14a --- /dev/null +++ b/Plugins/Rename.lua @@ -0,0 +1,60 @@ +------------------------------------------------------------------------------- +-- Module Declaration +-- + +local plugin, CL = BigWigs:NewPlugin("Rename", { + "GetDefaultName", + "GetName", + "SetName", +}) +if not plugin then return end + +-------------------------------------------------------------------------------- +-- Options +-- + +plugin.defaultDB = {} + +-------------------------------------------------------------------------------- +-- API +-- + +function plugin:GetDefaultName(module, key) + if type(module) == "string" then module = BigWigs:GetBossModule(module, true) end + if not module or not key then + BigWigs:Error(("Rename: Missing module or key (%q, %q)"):format(tostringall(module, key))) + return + end + local altName = module.altNames and module.altNames[key] + if altName == CL.mythic then altName = nil end -- XXX using altnames as labels/descriptors z.z + return altName or module:SpellName(key, true) +end + +function plugin:GetName(module, key) + if type(module) == "string" then module = BigWigs:GetBossModule(module, true) end + if not module or not key then + BigWigs:Error(("Rename: Missing module or key (%q, %q)"):format(tostringall(module, key))) + return + end + local altName = module.altNames and module.altNames[key] + if altName == CL.mythic then altName = nil end + local moduleDb = plugin.db.profile[module.name] + return moduleDb and moduleDb[key] or altName +end + +function plugin:SetName(module, key, value) + if type(module) == "string" then module = BigWigs:GetBossModule(module, true) end + if not module or not key then + BigWigs:Error(("Rename: Missing module or key (%q, %q)"):format(tostringall(module, key))) + return + end + if value == "" then + value = nil + end + local moduleName = module.name + if value and not plugin.db.profile[moduleName] then + plugin.db.profile[moduleName] = {} + end + plugin.db.profile[moduleName][key] = value + module:SetSpellRename(key, value) +end diff --git a/Plugins/modules.xml b/Plugins/modules.xml index 5ead5bb90..696ff97c2 100644 --- a/Plugins/modules.xml +++ b/Plugins/modules.xml @@ -22,4 +22,6 @@