You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

682 lines
20 KiB

-------------------------------------------------------------------------------
-- Module Declaration
--
local oldPlugin = BigWigs:NewPlugin("Super Emphasize") -- XXX temp 9.0.2
oldPlugin.defaultDB = {
Countdown = {},
}
local plugin = BigWigs:NewPlugin("Countdown")
if not plugin then return end
local voiceMap = {
enUS = {"English: Default (%s)", "Male", "Female"},
deDE = {"Deutsch: Standard (%s)", "Männlich", "Weiblich"},
esES = {"Español (es): Predeterminado (%s)", "Masculino", "Femenino"},
esMX = {"Español (mx): Predeterminado (%s)", "Masculino", "Femenino"},
frFR = {"Français : Défaut (%s)", "Homme", "Femme"},
itIT = {"Italiano: Predefinito (%s)", "Maschio", "Femmina"},
koKR = {"한국어 : 기본 (%s)", "남성", "여성"},
ptBR = {"Português: Padrão (%s)", "Masculino", "Feminino"},
ruRU = {"Русский: По умолчанию (%s)", "Мужской", "Женский"},
zhCN = {"简体中文:默认(%s)", "男性", "女性"},
zhTW = {"繁體中文:預設值(%s)", "男性", "女性"},
}
local defaultVoice = "English: Amy"
do
local locale = GetLocale()
if locale ~= "enUS" and voiceMap[locale] then
defaultVoice = ("%s: Default (Female)"):format(locale)
end
end
plugin.defaultDB = {
textEnabled = true,
fontName = plugin:GetDefaultFont(),
outline = "THICKOUTLINE",
fontSize = 48,
monochrome = false,
fontColor = { r = 1, g = 0, b = 0 },
voice = defaultVoice,
countdownTime = 5,
position = {"TOP", "TOP", 0, -300},
bossCountdowns = {},
}
-------------------------------------------------------------------------------
-- Locals
--
local media = LibStub("LibSharedMedia-3.0")
local FONT = media.MediaType and media.MediaType.FONT or "font"
local BigWigsAPI = BigWigsAPI
local L = BigWigsAPI:GetLocale("BigWigs: Plugins")
plugin.displayName = L.countdown
local PlaySoundFile = PlaySoundFile
local countdownAnchor = nil
local countdownFrame = nil
local countdownText = nil
local inConfigMode = false
-------------------------------------------------------------------------------
-- Countdown Registration
--
BigWigsAPI:RegisterCountdown(L.none, { false, false, false, false, false })
BigWigsAPI:RegisterCountdown("English: Amy", {
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\1.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\2.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\3.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\4.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\5.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\6.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\7.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\8.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\9.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Amy\\10.ogg",
})
BigWigsAPI:RegisterCountdown("English: David", {
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\1.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\2.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\3.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\4.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\5.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\6.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\7.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\8.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\9.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\David\\10.ogg",
})
BigWigsAPI:RegisterCountdown("English: Jim", {
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\1.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\2.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\3.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\4.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\5.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\6.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\7.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\8.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\9.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Jim\\10.ogg",
})
for locale, info in next, voiceMap do
local name, male, female = unpack(info)
BigWigsAPI:RegisterCountdown(("%s: Default (Male)"):format(locale), name:format(male), {
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\male\\1.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\male\\2.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\male\\3.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\male\\4.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\male\\5.ogg",
})
local id = ("%s: Default (Female)"):format(locale)
if locale == "esMX" then
-- never extracted the esMX female announcer and it's gone now, so just use esES
locale = "esES"
end
BigWigsAPI:RegisterCountdown(id, name:format(female), {
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\female\\1.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\female\\2.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\female\\3.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\female\\4.ogg",
"Interface\\AddOns\\BigWigs\\Media\\Sounds\\Heroes\\"..locale.."\\female\\5.ogg",
})
end
--------------------------------------------------------------------------------
-- Anchors & Frames
--
local function showAnchors()
inConfigMode = true
countdownAnchor:Show()
countdownFrame:Show()
countdownText:SetText("5")
end
local function hideAnchors()
inConfigMode = false
countdownAnchor:Hide()
countdownFrame:Hide()
end
do
local function OnDragStart(self)
self:StartMoving()
end
local function OnDragStop(self)
self:StopMovingOrSizing()
local point, _, relPoint, x, y = self:GetPoint()
plugin.db.profile.position = {point, relPoint, x, y}
plugin:UpdateGUI() -- Update X/Y if GUI is open.
end
local function RefixPosition(self)
self:ClearAllPoints()
local point, relPoint = plugin.db.profile.position[1], plugin.db.profile.position[2]
local x, y = plugin.db.profile.position[3], plugin.db.profile.position[4]
self:SetPoint(point, UIParent, relPoint, x, y)
end
countdownAnchor = CreateFrame("Frame", nil, UIParent)
countdownAnchor:EnableMouse(true)
countdownAnchor:SetClampedToScreen(true)
countdownAnchor:SetMovable(true)
countdownAnchor:RegisterForDrag("LeftButton")
countdownAnchor:SetWidth(80)
countdownAnchor:SetHeight(80)
countdownAnchor:SetFrameStrata("HIGH")
countdownAnchor:SetFixedFrameStrata(true)
countdownAnchor:SetFrameLevel(20)
countdownAnchor:SetFixedFrameLevel(true)
countdownAnchor:SetScript("OnDragStart", OnDragStart)
countdownAnchor:SetScript("OnDragStop", OnDragStop)
countdownAnchor.RefixPosition = RefixPosition
local point, relPoint = plugin.defaultDB.position[1], plugin.defaultDB.position[2]
local x, y = plugin.defaultDB.position[3], plugin.defaultDB.position[4]
countdownAnchor:SetPoint(point, UIParent, relPoint, x, y)
countdownAnchor:Hide()
local bg = countdownAnchor:CreateTexture()
bg:SetAllPoints(countdownAnchor)
bg:SetColorTexture(0, 0, 0, 0.3)
local header = countdownAnchor:CreateFontString()
header:SetFont(plugin:GetDefaultFont(12))
header:SetShadowOffset(1, -1)
header:SetTextColor(1,0.82,0,1)
header:SetText(L.textCountdown)
header:SetPoint("BOTTOM", countdownAnchor, "TOP", 0, 5)
header:SetJustifyV("MIDDLE")
header:SetJustifyH("CENTER")
end
-------------------------------------------------------------------------------
-- Options
--
local function voiceSorting()
local list = BigWigsAPI:GetCountdownList()
local sorted = {}
for k in next, list do
if k ~= L.none then
sorted[#sorted + 1] = k
end
end
sort(sorted, function(a, b) return list[a] < list[b] end)
tinsert(sorted, 1, L.none)
return sorted
end
local function UpdateFont()
local flags = nil
if plugin.db.profile.monochrome and plugin.db.profile.outline ~= "NONE" then
flags = "MONOCHROME," .. plugin.db.profile.outline
elseif plugin.db.profile.monochrome then
flags = "MONOCHROME"
elseif plugin.db.profile.outline ~= "NONE" then
flags = plugin.db.profile.outline
end
countdownText:SetFont(media:Fetch(FONT, plugin.db.profile.fontName), plugin.db.profile.fontSize, flags)
countdownText:SetTextColor(plugin.db.profile.fontColor.r, plugin.db.profile.fontColor.g, plugin.db.profile.fontColor.b)
end
do
local checkTextDisabled = function() return not plugin.db.profile.textEnabled end
plugin.pluginOptions = {
name = "|TInterface\\AddOns\\BigWigs\\Media\\Icons\\Menus\\Countdown:20|t ".. L.countdown,
type = "group",
childGroups = "tab",
get = function(info) return plugin.db.profile[info[#info]] end,
set = function(info, value)
plugin.db.profile[info[#info]] = value
UpdateFont()
end,
order = 5,
args = {
general = {
type = "group",
name = L.general,
order = 1,
args = {
heading = {
type = "description",
name = L.countdownDesc.. "\n\n",
order = 1,
width = "full",
fontSize = "medium",
},
countdownTime = {
name = L.countdownAt,
desc = L.countdownAt_desc,
type = "range", min = 3, max = 10, step = 1,
order = 2,
width = 2,
},
countdownTest = {
name = L.countdownTest,
type = "execute",
handler = plugin,
func = "TestCountdown",
order = 3,
},
audioSpacer = {
type = "description",
name = "\n\n",
order = 4,
width = "full",
fontSize = "medium",
},
audioHeader = {
type = "header",
name = L.countdownAudioHeader,
order = 5,
},
voice = {
name = L.countdownVoice,
type = "select",
values = BigWigsAPI.GetCountdownList,
sorting = voiceSorting,
order = 6,
width = "full",
},
textSpacer = {
type = "description",
name = "\n\n",
order = 7,
width = "full",
fontSize = "medium",
},
textHeader = {
type = "header",
name = L.countdownTextHeader,
order = 8,
},
textEnabled = {
type = "toggle",
name = L.textCountdown,
desc = L.textCountdownDesc,
order = 9,
width = "full",
},
fontName = {
type = "select",
name = L.font,
order = 10,
values = media:List(FONT),
itemControl = "DDI-Font",
get = function()
for i, v in next, media:List(FONT) do
if v == plugin.db.profile.fontName then return i end
end
end,
set = function(_, value)
local list = media:List(FONT)
plugin.db.profile.fontName = list[value]
UpdateFont()
end,
width = 2,
disabled = checkTextDisabled,
},
outline = {
type = "select",
name = L.outline,
order = 11,
values = {
NONE = L.none,
OUTLINE = L.thin,
THICKOUTLINE = L.thick,
},
disabled = checkTextDisabled,
},
fontColor = {
type = "color",
name = L.countdownColor,
get = function(info)
return plugin.db.profile.fontColor.r, plugin.db.profile.fontColor.g, plugin.db.profile.fontColor.b
end,
set = function(info, r, g, b)
plugin.db.profile.fontColor.r, plugin.db.profile.fontColor.g, plugin.db.profile.fontColor.b = r, g, b
UpdateFont()
end,
order = 12,
disabled = checkTextDisabled,
},
fontSize = {
type = "range",
name = L.fontSize,
desc = L.fontSizeDesc,
order = 13,
softMax = 100, max = 200, min = 20, step = 1,
disabled = checkTextDisabled,
},
monochrome = {
type = "toggle",
name = L.monochrome,
desc = L.monochromeDesc,
order = 14,
disabled = checkTextDisabled,
},
resetHeader = {
type = "header",
name = "",
order = 15,
},
reset = {
type = "execute",
name = L.reset,
desc = L.resetCountdownDesc,
func = function()
local restoreCountdowns = plugin.db.profile.bossCountdowns
plugin.db:ResetProfile()
plugin.db.profile.bossCountdowns = restoreCountdowns
end,
order = 16,
},
resetAll = {
type = "execute",
name = L.resetAll,
desc = L.resetAllCountdownDesc,
func = function() plugin.db:ResetProfile() end,
order = 17,
},
},
},
exactPositioning = {
type = "group",
name = L.positionExact,
order = 2,
disabled = checkTextDisabled,
args = {
posx = {
type = "range",
name = L.positionX,
desc = L.positionDesc,
min = -2048,
max = 2048,
step = 1,
order = 1,
width = "full",
get = function()
return plugin.db.profile.position[3]
end,
set = function(_, value)
plugin.db.profile.position[3] = value
countdownAnchor:RefixPosition()
end,
},
posy = {
type = "range",
name = L.positionY,
desc = L.positionDesc,
min = -2048,
max = 2048,
step = 1,
order = 2,
width = "full",
get = function()
return plugin.db.profile.position[4]
end,
set = function(_, value)
plugin.db.profile.position[4] = value
countdownAnchor:RefixPosition()
end,
},
},
},
},
}
end
local function createOptions()
local sModule = BigWigs:GetPlugin("Sounds", true)
if sModule then
-- ability options
sModule.soundOptions.args.separator1 = {
name = "",
type = "description",
order = 3,
}
sModule.soundOptions.args.countdown = {
name = "Countdown",
type = "select",
values = BigWigsAPI.GetCountdownList,
sorting = voiceSorting,
get = function(info)
local name, key = unpack(info.arg)
return plugin.db.profile.bossCountdowns[name] and plugin.db.profile.bossCountdowns[name][key] or plugin.db.profile.voice
end,
set = function(info, value)
local name, key = unpack(info.arg)
if value ~= plugin.db.profile.voice then
if not plugin.db.profile.bossCountdowns[name] then plugin.db.profile.bossCountdowns[name] = {} end
plugin.db.profile.bossCountdowns[name][key] = value
else -- clean up
if plugin.db.profile.bossCountdowns[name] then
plugin.db.profile.bossCountdowns[name][key] = nil
end
if not next(plugin.db.profile.bossCountdowns[name]) then
plugin.db.profile.bossCountdowns[name] = nil
end
end
end,
order = 4,
width = "full",
}
end
end
-------------------------------------------------------------------------------
-- Initialization
--
do
local LOCALE = GetLocale()
local KEY = "%s: Default (Female)"
local function check(voice)
local lang = voice and voice:match("^(.+): Heroes of the Storm$")
if not lang then return end
if lang == "Español" then
-- Try to pick the correct Spanish locale
if LOCALE == "esMX" or LOCALE == "esES" then
return KEY:format(LOCALE)
end
return KEY:format(GetCurrentRegion() == 1 and "esMX" or "esES") -- NA or EU
end
for locale, info in next, voiceMap do
if info[1]:sub(1, #lang) == lang then
return KEY:format(locale)
end
end
end
local function upgradeDB(sv)
if not sv or not sv.profiles then return end
for profile, db in next, sv.profiles do
local voice = check(db.voice)
if voice then
db.voice = voice
end
if db.bossCountdowns then
for moduleName, abilities in next, db.bossCountdowns do
for k, v in next, abilities do
local voice = check(v)
if voice then
abilities[k] = voice
end
end
end
end
end
end
function plugin:OnRegister()
-- XXX temp 9.0.5
upgradeDB(self.db)
upgradeDB(BigWigs3DB.namespaces["BigWigs_Plugins_Pull"])
end
end
do
local function updateProfile()
local db = plugin.db.profile
for k, v in next, db do
local defaultType = type(plugin.defaultDB[k])
if defaultType == "nil" then
db[k] = nil
elseif type(v) ~= defaultType then
db[k] = plugin.defaultDB[k]
end
end
if db.outline ~= "NONE" and db.outline ~= "OUTLINE" and db.outline ~= "THICKOUTLINE" then
db.outline = plugin.defaultDB.outline
end
if db.fontSize < 20 or db.fontSize > 200 then
db.fontSize = plugin.defaultDB.fontSize
end
if type(db.fontColor.r) ~= "number" or db.fontColor.r < 0 or db.fontColor.r > 1
or type(db.fontColor.g) ~= "number" or db.fontColor.g < 0 or db.fontColor.g > 1
or type(db.fontColor.b) ~= "number" or db.fontColor.b < 0 or db.fontColor.b > 1 then
db.fontColor = plugin.defaultDB.fontColor
end
if db.countdownTime < 3 or db.countdownTime > 10 then
db.countdownTime = plugin.defaultDB.countdownTime
end
UpdateFont()
countdownAnchor:RefixPosition()
-- Reset invalid voice selections
if not BigWigsAPI:HasCountdown(db.voice) then
db.voice = defaultVoice
end
for boss, tbl in next, db.bossCountdowns do
for ability, chosenVoice in next, tbl do
if not BigWigsAPI:HasCountdown(chosenVoice) then
db.bossCountdowns[boss][ability] = nil
end
end
end
-- XXX temp 9.0.2
oldPlugin.db:ResetProfile(nil, true) -- no callbacks
end
function plugin:OnPluginEnable()
self:RegisterMessage("BigWigs_StartCountdown")
self:RegisterMessage("BigWigs_StopCountdown")
self:RegisterMessage("BigWigs_OnBossDisable")
self:RegisterMessage("BigWigs_OnBossWipe", "BigWigs_OnBossDisable")
self:RegisterMessage("BigWigs_ProfileUpdate", updateProfile)
self:RegisterMessage("BigWigs_StartConfigureMode", showAnchors)
self:RegisterMessage("BigWigs_StopConfigureMode", hideAnchors)
updateProfile()
createOptions()
end
end
-------------------------------------------------------------------------------
-- Event Handlers
--
local latestCountdown = nil
do
countdownFrame = CreateFrame("Frame", nil, UIParent)
countdownFrame:SetFrameStrata("FULLSCREEN_DIALOG")
countdownFrame:SetFixedFrameStrata(true)
countdownFrame:SetFrameLevel(20) -- Behind GUI (level 100)
countdownFrame:SetFixedFrameLevel(true)
countdownFrame:SetPoint("CENTER", countdownAnchor, "CENTER")
countdownFrame:SetWidth(80)
countdownFrame:SetHeight(80)
countdownFrame:Hide()
countdownText = countdownFrame:CreateFontString()
countdownText:SetPoint("CENTER", countdownFrame, "CENTER")
local updater = countdownFrame:CreateAnimationGroup()
updater:SetScript("OnFinished", function()
if inConfigMode then
countdownText:SetText("5")
else
countdownFrame:Hide()
end
end)
local anim = updater:CreateAnimation("Alpha")
anim:SetFromAlpha(1)
anim:SetToAlpha(0)
anim:SetDuration(1)
anim:SetStartDelay(1.1)
function plugin:SetText(text, timer)
latestCountdown = timer
countdownText:SetText(text)
updater:Stop()
countdownFrame:Show()
updater:Play()
end
end
do
local timers = {}
function plugin:BigWigs_StartCountdown(_, module, key, text, time, customVoice, customStart, audioOnly)
if module and time > 1.3 then
self:BigWigs_StopCountdown(nil, module, text)
if not timers[module] then
timers[module] = {}
end
local count = customStart or self.db.profile.countdownTime
while count >= time do
count = count - 1
end
local cancelTimer = {false}
timers[module][text] = cancelTimer
local voice = customVoice or plugin.db.profile.bossCountdowns[module.name] and plugin.db.profile.bossCountdowns[module.name][key] or plugin.db.profile.voice
local function printTime()
if not cancelTimer[1] then
if not audioOnly and plugin.db.profile.textEnabled then
plugin:SetText(count, cancelTimer)
end
local sound = BigWigsAPI:GetCountdownSound(voice, count)
if sound then
PlaySoundFile(sound, "Master")
end
count = count - 1
end
end
local startOffset = count + 0.3
for i = 1.3, startOffset do
self:SimpleTimer(printTime, time-i)
end
end
end
function plugin:BigWigs_StopCountdown(_, module, text)
local moduleTimers = timers[module]
if moduleTimers and moduleTimers[text] then
moduleTimers[text][1] = true
if latestCountdown == moduleTimers[text] then
self:SetText("") -- Only clear the text if the cancelled countdown was the last to display something
end
end
end
function plugin:BigWigs_OnBossDisable(_, module)
if timers[module] then
for _, timer in next, timers[module] do
timer[1] = true
if latestCountdown == timer then
self:SetText("") -- Only clear the text if the cancelled countdown was the last to display something
end
end
timers[module] = nil
end
end
end
function plugin:TestCountdown()
self:SendMessage("BigWigs_StartCountdown", self, nil, "test countdown", self.db.profile.countdownTime + 0.5)
end