From 7a5aff5b161a8aeac744f58b1df0ccd5e55adb99 Mon Sep 17 00:00:00 2001 From: Adam Hellberg Date: Wed, 13 Dec 2023 00:06:41 +0100 Subject: [PATCH] Fix line endings --- Chocobo.lua | 1372 ++++++++++++++++---------------- Chocobo.toc | 68 +- ChocoboCommand.lua | 612 +++++++------- ChocoboCustomSongPanel.lua | 434 +++++----- ChocoboSoundControl.lua | 808 +++++++++---------- ChocoboSoundControlPanel.lua | 1092 ++++++++++++------------- libs/ChocoboLib/ChocoboLib.lua | 200 ++--- libs/ChocoboLib/ChocoboLib.xml | 44 +- locales/load.xml | 64 +- locales/ptBR.lua | 48 +- 10 files changed, 2371 insertions(+), 2371 deletions(-) diff --git a/Chocobo.lua b/Chocobo.lua index f8e470c..421eadf 100644 --- a/Chocobo.lua +++ b/Chocobo.lua @@ -1,686 +1,686 @@ ---[[ - Copyright (c) 2010-2020 by Adam Hellberg - - This file is part of Chocobo. - - Chocobo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Chocobo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Chocobo. If not, see . - - ------ - - Chocobo AddOn - Dedicated to Shishu (Flurdy) on Azuremyst-EU ---]] - -Chocobo = { - Name = "Chocobo", - Version = GetAddOnMetadata("Chocobo", "Version"), - Loaded = false, - Mounted = false, - Running = false, -- True if the OnUpdate handler is running. - MusicDir = "Interface\\AddOns\\Chocobo\\music\\", - Global = {}, - Events = {}, - Songs = { -- Default songs loaded on first run - -- Please note that you can't add custom songs here, - -- this is only used when restoring default settings or on initial setup - "chocobo.ogg", - "chocobo_ffiv.ogg", - "chocobo_ffxii.ogg", - "chocobo_ffxiii.ogg" - }, - - -- Values are overridden later with the return from GetSpellInfo - -- The ones specified here are just placeholders and to help - -- identify IDs during development - Mounts = { - Hawkstriders = { - [35022] = "Black Hawkstrider", - [35020] = "Blue Hawkstrider", - [35018] = "Purple Hawkstrider", - [34795] = "Red Hawkstrider", - [63642] = "Silvermoon Hawkstrider", - [66091] = "Sunreaver Hawkstrider", - [35025] = "Swift Green Hawkstrider", - [33660] = "Swift Pink Hawkstrider", - [35027] = "Swift Purple Hawkstrider", - [65639] = "Swift Red Hawkstrider", - [35028] = "Swift Warstrider", -- (Thanks Khormin for pointing it out) - [46628] = "Swift White Hawkstrider" - }, - Plainstriders = { - [102346] = "Swift Forest Strider", - [102350] = "Swift Lovebird", - [101573] = "Swift Shorestrider", - [102349] = "Swift Springtrider" - }, - RidingCranes = { - [127174] = "Azure Riding Crane", - [127176] = "Golden Riding Crane", - [127177] = "Regal Riding Crane" - }, - RavenLord = { - [41252] = "Raven Lord" -- (If enabled in options) - }, - Flametalon = { - [101542] = "Flametalon of Alysrazor" -- (Fire version of Raven Lord) - }, - DruidForms = { -- When AllMounts is enabled - [783] = "Travel Form", - [33943] = "Flight form", - [40120] = "Swift Flight Form" - } - } -} - -local C = Chocobo - ---@debug@ -if C.Version == "@".."project-version".."@" then C.Version = "Development" end ---@end-debug@ - -local CLib = ChocoboLib -local L = _G["ChocoboLocale"] - -assert(CLib, "Chocobo Lib not loaded") -assert(L, "Chocobo Locales not loaded") - -local nowPlaying -- The current song playing, used when preventing the same song playing twice - -function C:OnEvent(_, event, ...) - if self.Events[event] then self.Events[event](self, ...) end -end - -function C.Events.ADDON_LOADED(self, ...) - -- Currently, this seems a bit bugged when having multiple addons. The "loaded" message will disappear sometimes. - local addonName = (select(1, ...)):lower() - if addonName ~= "chocobo" or self.Loaded then return end - if type(_G["CHOCOBO"]) ~= "table" then _G["CHOCOBO"] = {} end - self.Global = _G["CHOCOBO"] - if type(self.Global["DEBUG"]) ~= "boolean" then - -- Should be fired on first launch, set the saved variable to default value - self:Msg(L["DebugNotSet"]) - self.Global["DEBUG"] = false - end - if type(self.Global["ALLMOUNTS"]) ~= "boolean" then - -- Should be fired on first launch, set the saved variable to default value - self:Msg(L["AllMountsNotSet"]) - self.Global["ALLMOUNTS"] = false - end - if type(self.Global["PLAINSTRIDER"]) ~= "boolean" then - self:Msg(L["PlainstridersNotSet"]) - self.Global["PLAINSTRIDER"] = true - end - if type(self.Global["RIDINGCRANE"]) ~= "boolean" then - self:Msg(L["RidingCranesNotSet"]) - self.Global["RIDINGCRANE"] = true - end - if type(self.Global["RAVENLORD"]) ~= "boolean" then - self:Msg(L["RavenLordNotSet"]) - self.Global["RAVENLORD"] = false - end - if type(self.Global["FLAMETALON"]) ~= "boolean" then - self:Msg(L["FlametalonNotSet"]) - self.Global["FLAMETALON"] = false - end - if not self.Global["MUSIC"] then -- If the song list is empty - -- Populate the table with default songs - self:Msg(L["NoMusic"]) - self.Global["MUSIC"] = {} - for _,v in pairs(self.Songs) do -- Add all of the default songs - self:AddMusic(v) - end - end - if not self.Global["MUSIC_OGG_UPDATE"] then -- Reset music if still using mp3s - self:ResetMusic() - self.Global["MUSIC_OGG_UPDATE"] = true - end - if type(self.Global["PREVENTDUPE"]) ~= "boolean" then - self:Msg(L["PreventDupeNotSet"]) - self.Global["PREVENTDUPE"] = true - end - if not self.Global["MOUNTS"] then - self:Msg(L["NoMounts"]) - self.Global["MOUNTS"] = {} - end - if not self.Global["CUSTOM"] then - self.Global["CUSTOM"] = {} - end - if type(self.Global["ENABLED"]) ~= "boolean" then - -- Should be fired on first launch, set the saved variable to default value - self:Msg(L["EnabledNotSet"]) - self.Global["ENABLED"] = true - end - - self.SoundControl:Init() - self.SoundControl:Check() - - -- [NEW] Check all songs and convert out-of-date ones to new format - -- (Removing the Interface\\AddOns\\Chocobo\\music\\ part) - self:MusicCheck() - - self:Msg((L["AddOnLoaded"]):format(self.Version)) - self:Msg(L["Enjoy"]) - self.Loaded = true -end - -function C.Events.UNIT_AURA(self) - if not self.Global["ENABLED"] then return end -- Return if addon is disabled - self:DebugMsg((L["Event_UNIT_AURA"]):format("player")) - if self.Loaded == false then - -- This should NOT happen - self:ErrorMsg(L["NotLoaded"]) - return - end - if self.Running then return end -- Return if the timer is already running. - self.Running = true - C_Timer.After(1, function() self:CheckMount() end) -end - -function C.Events.PLAYER_LOGOUT(self) - -- Save local copy of globals - -- TODO: Is this redundant? - _G["CHOCOBO"] = self.Global -end - -function C:CheckMount() - local mounted, mountName, _ = self:HasMount() -- Get mounted status and name of mount (if mounted) - if IsMounted() or mounted then -- More efficient way to make it also detect flight form here? - -- Print what mount the player is mounted on - if mountName then self:DebugMsg((L["CurrentMount"]):format(mountName)) end - self:DebugMsg(L["PlayerIsMounted"]) -- Print that the player is mounted - -- TODO: Redundant to have both the above messages? Remove the second? - -- Proceed if player is on one of the activated mounts or if allmounts (override) is true - if mounted or self.Global["ALLMOUNTS"] then - self:DebugMsg(L["PlayerOnHawkstrider"]) - if not self.Mounted then -- Check so that the player is not already mounted - self.SoundControl:Check() -- Enable sound if disabled and the option is enabled - self:DebugMsg(L["PlayingMusic"]) - self.Mounted = true - -- Player mounted but mount is not recognised, check all buffs to find a match - if type(mountName) ~= "string" then - local found = false - local index = 1 - repeat - local name = UnitBuff("player", index, "PLAYER CANCELABLE") - if not name then break end -- No more buffs to check - if self.Global["CUSTOM"][name:lower()] then - self:PlayRandomMusic(name) - found = true - end - index = index + 1 - until found or index > 40 - if not found then self:PlayRandomMusic() end - elseif self.Global["CUSTOM"][mountName:lower()] then - self:PlayRandomMusic(mountName) - else - self:PlayRandomMusic() - end - else -- If the player has already mounted - self:DebugMsg(L["AlreadyMounted"]) - end - else -- Player is not on a hawkstrider - self:DebugMsg(L["NoHawkstrider"]) - end - elseif self.Mounted then -- When the player has dismounted - self.SoundControl:Check() -- Disable sound if enabled and the option is enabled - self:DebugMsg(L["NotMounted"]) - self.Mounted = false - -- Note that StopMusic() will also stop any other custom music playing (such as from EpicMusicPlayer) - StopMusic() - end - self.Running = false -end - -function C:HasMount() - local mountColl = {} - - for _, name in pairs(self.Mounts.Hawkstriders) do - mountColl[#mountColl + 1] = name - end - - if self.Global["PLAINSTRIDER"] then - for _, name in pairs(self.Mounts.Plainstriders) do - mountColl[#mountColl + 1] = name - end - end - - if self.Global["RIDINGCRANE"] then - for _, name in pairs(self.Mounts.RidingCranes) do - mountColl[#mountColl + 1] = name - end - end - - if self.Global["RAVENLORD"] then - for _, name in pairs(self.Mounts.RavenLord) do - mountColl[#mountColl + 1] = name - end - end - - if self.Global["FLAMETALON"] then - for _, name in pairs(self.Mounts.Flametalon) do - mountColl[#mountColl + 1] = name - end - end - - if self.Global["ALLMOUNTS"] then -- Add druid flight forms - for _, name in pairs(self.Mounts.DruidForms) do - mountColl[#mountColl + 1] = name - end - end - - if #self.Global["MOUNTS"] > 0 then - for _, v in pairs(self.Global["MOUNTS"]) do - mountColl[#mountColl + 1] = v -- Can be both a string and a number value - end - end - - for mountName, _ in pairs(self.Global["CUSTOM"]) do - mountColl[#mountColl + 1] = mountName - end - - return CLib:HasBuff(mountColl) -end - -function C:MusicCheck() - local matchString = "^" .. self.MusicDir -- Match the music dir path at the beginning of the string only. - -- The substring has to start AFTER the matched string, adding one to the length. - local length = self.MusicDir:len() + 1 - local updated = 0 -- Keep track of how many songs that had to update - for i,v in ipairs(self.Global["MUSIC"]) do - if v:match(matchString) then - local change = v:sub(length, v:len()) -- A substring that includes only the filename (or subfolders, if any) - self.Global["MUSIC"][i] = change - self:Msg((L["SongUpdated"]):format(i, change)) - updated = updated + 1 - end - end - if updated > 0 then -- Print how many songs that were updated - self:Msg((L["SongsUpdated"]):format(updated)) - else -- All songs up to date, no action needed - self:Msg(L["SongsUpToDate"]) - end -end - --- If isMount is true, treat song as the mount name/ID -function C:PlayMusic(song, isMount) - local songFile - if isMount then - song = song:lower() - local mountSongs = self.Global.CUSTOM[song] - if mountSongs and #mountSongs > 0 then - local id = math.random(1, #mountSongs) - songFile = mountSongs[id] - if #mountSongs > 1 and self.Global["PREVENTDUPE"] and songFile == nowPlaying then - while songFile == nowPlaying do - id = math.random(1, #mountSongs) - songFile = mountSongs[id] - end - end - self:DebugMsg((L["PlayingSong"]):format(id, songFile)) - else - self:ErrorMsg((L["CustomNotDefined"]):format(song)) - return - end - if type(songFile) ~= "string" then - self:ErrorMsg((L["CustomSongNotFound"]):format(song)) - return - end - elseif type(song) == "string" then - songFile = song - else - songFile = self.Global["MUSIC"][song] - if not songFile then - self:ErrorMsg(L["SongNotFound"]) - return false - end - self:DebugMsg((L["PlayingSong"]):format(song, songFile)) - end - nowPlaying = songFile - songFile = self.MusicDir .. songFile - PlayMusic(songFile) -end - -function C:PlayRandomMusic(mount) - if mount then - self:PlayMusic(mount, true) - else - local id = math.random(1, #self.Global["MUSIC"]) - if self.Global["PREVENTDUPE"] and #self.Global["MUSIC"] > 1 then - local name = self.Global["MUSIC"][id] - while name == nowPlaying do - id = math.random(1, #self.Global["MUSIC"]) - name = self.Global["MUSIC"][id] - end - end - self:PlayMusic(id) - end -end - -function C:AddMusic(songName) -- Add a song the the list - songName = CLib:Trim(songName) - if songName == "" or songName == nil then - self:ErrorMsg(L["NoFile"]) - return false - end - for _,v in pairs(self.Global["MUSIC"]) do -- Loop through all the songs currently in the list and... - if v == songName then -- ... make sure it isn't there already - self:ErrorMsg(L["AlreadyExists"]) - return false - end - end - table.insert(self.Global["MUSIC"], songName) -- Insert the song into list - self:Msg((L["AddedSong"]):format(songName)) - return true -end - -function C:RemoveMusic(list, songName) -- Remove a song from the list - if type(list) ~= "table" then - songName = list - list = self.Global.MUSIC - end - if type(songName) == "number" then - if list[songName] then - local name = list[songName] - table.remove(list, songName) - self:Msg((L["RemovedSong"]):format(name)) - return true - end - return false - end - songName = CLib:Trim(songName) - if songName == "" or songName == nil then - self:ErrorMsg(L["NoFile"]) - return false - end - for i,v in ipairs(list) do -- Loop through all the songs in the list until... - if v == songName then -- ... the desired one is found and then... - table.remove(list, i) -- ... remove it from the list. - self:Msg((L["RemovedSong"]):format(songName)) - return true - end - end - self:ErrorMsg(L["SongNotFound"]) - return false -end - -function C:GetCustomMusic(mount) - mount = CLib:Trim(tostring(mount)):lower() - - if type(self.Global.CUSTOM[mount]) ~= "table" then - self.Global.CUSTOM[mount] = {} - end - - return self.Global.CUSTOM[mount] -end - -function C:AddCustomMusic(song, mount) - if song then - song = CLib:Trim(tostring(song)) - end - mount = mount:lower() - if song == "" or type(song) ~= "string" then - song = nil - --self:ErrorMsg((L["AddCustomInvalidSong"]):format(tostring(song))) - --return - end - if type(mount) ~= "string" or mount == "" then - self:ErrorMsg((L["AddCustomInvalidMount"]):format(tostring(mount))) - return - end - if self.Global.CUSTOM[mount] then - if song and CLib:InTable(self.Global.CUSTOM[mount], song) then - self:ErrorMsg((L["AddCustomExists"]):format(song, mount)) - return - end - if not song then return end - table.insert(self.Global.CUSTOM[mount], song) - self:Msg((L["AddCustomSuccess"]):format(song, mount)) - else - self.Global.CUSTOM[mount] = {} - if not song then return end - table.insert(self.Global.CUSTOM[mount], song) - self:Msg((L["AddCustomSuccess"]):format(song, mount)) - end -end - -function C:RemoveCustomMusic(mount, song) - mount = mount:lower() - if type(mount) ~= "string" then - self:ErrorMsg((L["RemoveCustomInvalidMount"]):format(tostring(mount))) - end - local list = self.Global.CUSTOM[mount] - if list then - if song then - self:RemoveMusic(list, song) - else - wipe(list) - self.Global.CUSTOM[mount] = nil - self:Msg((L["RemoveCustomSuccess"]):format(mount)) - end - else - self:ErrorMsg((L["RemoveCustomNotExist"]):format(mount)) - end -end - -function C:PrintMusic() -- Print all the songs currently in list to chat - if #self.Global["MUSIC"] <= 0 then - self:Msg(L["MusicListEmpty"]) - else - for i,v in ipairs(self.Global["MUSIC"]) do - self:Msg(("\124cff00CCFF%i: %s\124r"):format(i, v)) - end - end - - if CLib:Count(self.Global["CUSTOM"]) <= 0 then - return - end - - self:Msg(L["PrintMusicCustomStart"]) - - for k,v in pairs(self.Global["CUSTOM"]) do - self:Msg((L["PrintMusicCustomHeader"]):format(k)) - for _,s in pairs(v) do - self:Msg((L["PrintMusicCustomSong"]):format(s)) - end - end -end - -function C:ResetMusic() -- Resets the values in Chocobo.Global["MUSIC"] to default - self:Msg(L["ResetMusic"]) - wipe(self.Global.MUSIC) - for _,v in pairs(self.Songs) do -- Add all the default songs again - self:AddMusic(v) - end -end - -function C:AddMount(mount) - mount = CLib:Trim(mount) - mount = tonumber(mount) or mount - if mount == "" or mount == nil then - self:ErrorMsg(L["NoMount"]) - return - end - local compare = tostring(mount):lower() - for _,v in pairs(self.Global["MOUNTS"]) do - if tostring(v):lower() == compare then - self:ErrorMsg(L["MountAlreadyExists"]) - return - end - end - table.insert(self.Global["MOUNTS"], mount) - self:Msg((L["AddedMount"]):format(mount)) -end - -function C:RemoveMount(mount) - if mount == "" or mount == nil then - self:ErrorMsg(L["NoMount"]) - return - end - mount = mount:lower() - for i,v in ipairs(self.Global["MOUNTS"]) do - if v:lower() == mount then - table.remove(self.Global["MOUNTS"], i) - self:Msg((L["RemovedMount"]):format(mount)) - return - end - end - self:ErrorMsg(L["MountNotFound"]) -end - -function C:PrintMounts() - if #self.Global["MOUNTS"] <= 0 then - self:Msg(L["MountListEmpty"]) - else - for i,v in ipairs(self.Global["MOUNTS"]) do - self:Msg(("\124cff00CCFF%i: %s\124r"):format(i, v)) - end - end -end - -function C:ResetMounts() - self:Msg(L["ResetMounts"]) - wipe(self.Global.MOUNTS) -end - -function C:FilterMount(filter, silent) - if type(filter) == "nil" then filter = Chocobo.Global["ALLMOUNTS"] end - if filter then - if not silent then self:Msg(L["HawkstriderOnly"]) end - self.Global["ALLMOUNTS"] = false - else - if not silent then self:Msg(L["AllMounts"]) end - self.Global["ALLMOUNTS"] = true - end -end - -function C:ToggleDebug() - self:Debug(not self.Global["DEBUG"], true) -end - -function C:Debug(set, silent) - if set == "enable" or set == "on" or set == true then - if not silent then self:Msg(L["DebuggingEnabled"]) end - self.Global["DEBUG"] = true - elseif set == "disable" or set == "off" or set == false then - if not silent then self:Msg(L["DebuggingDisabled"]) end - self.Global["DEBUG"] = false - elseif not silent then - if self.Global["DEBUG"] then - self:Msg(L["DebugIsEnabled"]) - else - self:Msg(L["DebugIsDisabled"]) - end - end -end - -function C:PlainstriderToggle(silent) - self.Global["PLAINSTRIDER"] = not self.Global["PLAINSTRIDER"] - if silent then return end - if self.Global["PLAINSTRIDER"] then - self:Msg(L["PlainstriderTrue"]) - else - self:Msg(L["PlainstriderFalse"]) - end -end - -function C:RidingCraneToggle(silent) - self.Global["RIDINGCRANE"] = not self.Global["RIDINGCRANE"] - if silent then return end - if self.Global["RIDINGCRANE"] then - self:Msg(L["RidingCranesTrue"]) - else - self:Msg(L["RidingCranesFalse"]) - end -end - -function C:RavenLordToggle(silent) - self.Global["RAVENLORD"] = not self.Global["RAVENLORD"] - if silent then return end - if self.Global["RAVENLORD"] then - self:Msg(L["RavenLordTrue"]) - else - self:Msg(L["RavenLordFalse"]) - end -end - -function C:FlametalonToggle(silent) - self.Global["FLAMETALON"] = not self.Global["FLAMETALON"] - if silent then return end - if self.Global["FLAMETALON"] then - self:Msg(L["FlametalonTrue"]) - else - self:Msg(L["FlametalonFalse"]) - end -end - -function C:Toggle(silent) -- Toggle the AddOn on and off - if self.Global["ENABLED"] then -- If the addon is enabled - self.Global["ENABLED"] = false -- Disable it - StopMusic() - if not silent then self:Msg(L["AddOnDisabled"]) end -- Print status - else -- If the addon is disabled - self.Global["ENABLED"] = true -- Enable it - if not silent then self:Msg(L["AddOnEnabled"]) end -- Print status - end -end - -function C:PreventDupeToggle(silent) - if self.Global["PREVENTDUPE"] then - self.Global["PREVENTDUPE"] = false - if not silent then self:Msg(L["PreventDupeDisabled"]) end - else - self.Global["PREVENTDUPE"] = true - if not silent then self:Msg(L["PreventDupeEnabled"]) end - end -end - -function C:GetGlobal(var) - return self.Global[var] -end - -function C:Msg(msg) -- Send a normal message - DEFAULT_CHAT_FRAME:AddMessage(L["MsgPrefix"] .. msg) -end - -function C:ErrorMsg(msg) -- Send an error message, these are prefixed with the word "ERROR" in red - DEFAULT_CHAT_FRAME:AddMessage(L["ErrorPrefix"] .. msg) -end - --- Send a debug message, these are only sent when debugging is enabled and are prefixed by the word "Debug" in yellow -function C:DebugMsg(msg) - if self.Global["DEBUG"] == true then - DEFAULT_CHAT_FRAME:AddMessage(L["DebugPrefix"] .. msg) - end -end - -function C:GetVersion() - return self.Version -end - --- Create the frame, no need for an XML file! -C.Frame = CreateFrame("Frame") -C.Frame:SetScript("OnEvent", function (frame, event, ...) C:OnEvent(frame, event, ...) end) -for k,_ in pairs(C.Events) do - if k == "UNIT_AURA" then - C.Frame:RegisterUnitEvent(k, "player") - else - C.Frame:RegisterEvent(k) - end -end - -for _, section in pairs(C.Mounts) do - for id, _ in pairs(section) do - section[id] = GetSpellInfo(id) - end -end +--[[ + Copyright (c) 2010-2020 by Adam Hellberg + + This file is part of Chocobo. + + Chocobo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Chocobo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Chocobo. If not, see . + + ------ + + Chocobo AddOn + Dedicated to Shishu (Flurdy) on Azuremyst-EU +--]] + +Chocobo = { + Name = "Chocobo", + Version = GetAddOnMetadata("Chocobo", "Version"), + Loaded = false, + Mounted = false, + Running = false, -- True if the OnUpdate handler is running. + MusicDir = "Interface\\AddOns\\Chocobo\\music\\", + Global = {}, + Events = {}, + Songs = { -- Default songs loaded on first run + -- Please note that you can't add custom songs here, + -- this is only used when restoring default settings or on initial setup + "chocobo.ogg", + "chocobo_ffiv.ogg", + "chocobo_ffxii.ogg", + "chocobo_ffxiii.ogg" + }, + + -- Values are overridden later with the return from GetSpellInfo + -- The ones specified here are just placeholders and to help + -- identify IDs during development + Mounts = { + Hawkstriders = { + [35022] = "Black Hawkstrider", + [35020] = "Blue Hawkstrider", + [35018] = "Purple Hawkstrider", + [34795] = "Red Hawkstrider", + [63642] = "Silvermoon Hawkstrider", + [66091] = "Sunreaver Hawkstrider", + [35025] = "Swift Green Hawkstrider", + [33660] = "Swift Pink Hawkstrider", + [35027] = "Swift Purple Hawkstrider", + [65639] = "Swift Red Hawkstrider", + [35028] = "Swift Warstrider", -- (Thanks Khormin for pointing it out) + [46628] = "Swift White Hawkstrider" + }, + Plainstriders = { + [102346] = "Swift Forest Strider", + [102350] = "Swift Lovebird", + [101573] = "Swift Shorestrider", + [102349] = "Swift Springtrider" + }, + RidingCranes = { + [127174] = "Azure Riding Crane", + [127176] = "Golden Riding Crane", + [127177] = "Regal Riding Crane" + }, + RavenLord = { + [41252] = "Raven Lord" -- (If enabled in options) + }, + Flametalon = { + [101542] = "Flametalon of Alysrazor" -- (Fire version of Raven Lord) + }, + DruidForms = { -- When AllMounts is enabled + [783] = "Travel Form", + [33943] = "Flight form", + [40120] = "Swift Flight Form" + } + } +} + +local C = Chocobo + +--@debug@ +if C.Version == "@".."project-version".."@" then C.Version = "Development" end +--@end-debug@ + +local CLib = ChocoboLib +local L = _G["ChocoboLocale"] + +assert(CLib, "Chocobo Lib not loaded") +assert(L, "Chocobo Locales not loaded") + +local nowPlaying -- The current song playing, used when preventing the same song playing twice + +function C:OnEvent(_, event, ...) + if self.Events[event] then self.Events[event](self, ...) end +end + +function C.Events.ADDON_LOADED(self, ...) + -- Currently, this seems a bit bugged when having multiple addons. The "loaded" message will disappear sometimes. + local addonName = (select(1, ...)):lower() + if addonName ~= "chocobo" or self.Loaded then return end + if type(_G["CHOCOBO"]) ~= "table" then _G["CHOCOBO"] = {} end + self.Global = _G["CHOCOBO"] + if type(self.Global["DEBUG"]) ~= "boolean" then + -- Should be fired on first launch, set the saved variable to default value + self:Msg(L["DebugNotSet"]) + self.Global["DEBUG"] = false + end + if type(self.Global["ALLMOUNTS"]) ~= "boolean" then + -- Should be fired on first launch, set the saved variable to default value + self:Msg(L["AllMountsNotSet"]) + self.Global["ALLMOUNTS"] = false + end + if type(self.Global["PLAINSTRIDER"]) ~= "boolean" then + self:Msg(L["PlainstridersNotSet"]) + self.Global["PLAINSTRIDER"] = true + end + if type(self.Global["RIDINGCRANE"]) ~= "boolean" then + self:Msg(L["RidingCranesNotSet"]) + self.Global["RIDINGCRANE"] = true + end + if type(self.Global["RAVENLORD"]) ~= "boolean" then + self:Msg(L["RavenLordNotSet"]) + self.Global["RAVENLORD"] = false + end + if type(self.Global["FLAMETALON"]) ~= "boolean" then + self:Msg(L["FlametalonNotSet"]) + self.Global["FLAMETALON"] = false + end + if not self.Global["MUSIC"] then -- If the song list is empty + -- Populate the table with default songs + self:Msg(L["NoMusic"]) + self.Global["MUSIC"] = {} + for _,v in pairs(self.Songs) do -- Add all of the default songs + self:AddMusic(v) + end + end + if not self.Global["MUSIC_OGG_UPDATE"] then -- Reset music if still using mp3s + self:ResetMusic() + self.Global["MUSIC_OGG_UPDATE"] = true + end + if type(self.Global["PREVENTDUPE"]) ~= "boolean" then + self:Msg(L["PreventDupeNotSet"]) + self.Global["PREVENTDUPE"] = true + end + if not self.Global["MOUNTS"] then + self:Msg(L["NoMounts"]) + self.Global["MOUNTS"] = {} + end + if not self.Global["CUSTOM"] then + self.Global["CUSTOM"] = {} + end + if type(self.Global["ENABLED"]) ~= "boolean" then + -- Should be fired on first launch, set the saved variable to default value + self:Msg(L["EnabledNotSet"]) + self.Global["ENABLED"] = true + end + + self.SoundControl:Init() + self.SoundControl:Check() + + -- [NEW] Check all songs and convert out-of-date ones to new format + -- (Removing the Interface\\AddOns\\Chocobo\\music\\ part) + self:MusicCheck() + + self:Msg((L["AddOnLoaded"]):format(self.Version)) + self:Msg(L["Enjoy"]) + self.Loaded = true +end + +function C.Events.UNIT_AURA(self) + if not self.Global["ENABLED"] then return end -- Return if addon is disabled + self:DebugMsg((L["Event_UNIT_AURA"]):format("player")) + if self.Loaded == false then + -- This should NOT happen + self:ErrorMsg(L["NotLoaded"]) + return + end + if self.Running then return end -- Return if the timer is already running. + self.Running = true + C_Timer.After(1, function() self:CheckMount() end) +end + +function C.Events.PLAYER_LOGOUT(self) + -- Save local copy of globals + -- TODO: Is this redundant? + _G["CHOCOBO"] = self.Global +end + +function C:CheckMount() + local mounted, mountName, _ = self:HasMount() -- Get mounted status and name of mount (if mounted) + if IsMounted() or mounted then -- More efficient way to make it also detect flight form here? + -- Print what mount the player is mounted on + if mountName then self:DebugMsg((L["CurrentMount"]):format(mountName)) end + self:DebugMsg(L["PlayerIsMounted"]) -- Print that the player is mounted + -- TODO: Redundant to have both the above messages? Remove the second? + -- Proceed if player is on one of the activated mounts or if allmounts (override) is true + if mounted or self.Global["ALLMOUNTS"] then + self:DebugMsg(L["PlayerOnHawkstrider"]) + if not self.Mounted then -- Check so that the player is not already mounted + self.SoundControl:Check() -- Enable sound if disabled and the option is enabled + self:DebugMsg(L["PlayingMusic"]) + self.Mounted = true + -- Player mounted but mount is not recognised, check all buffs to find a match + if type(mountName) ~= "string" then + local found = false + local index = 1 + repeat + local name = UnitBuff("player", index, "PLAYER CANCELABLE") + if not name then break end -- No more buffs to check + if self.Global["CUSTOM"][name:lower()] then + self:PlayRandomMusic(name) + found = true + end + index = index + 1 + until found or index > 40 + if not found then self:PlayRandomMusic() end + elseif self.Global["CUSTOM"][mountName:lower()] then + self:PlayRandomMusic(mountName) + else + self:PlayRandomMusic() + end + else -- If the player has already mounted + self:DebugMsg(L["AlreadyMounted"]) + end + else -- Player is not on a hawkstrider + self:DebugMsg(L["NoHawkstrider"]) + end + elseif self.Mounted then -- When the player has dismounted + self.SoundControl:Check() -- Disable sound if enabled and the option is enabled + self:DebugMsg(L["NotMounted"]) + self.Mounted = false + -- Note that StopMusic() will also stop any other custom music playing (such as from EpicMusicPlayer) + StopMusic() + end + self.Running = false +end + +function C:HasMount() + local mountColl = {} + + for _, name in pairs(self.Mounts.Hawkstriders) do + mountColl[#mountColl + 1] = name + end + + if self.Global["PLAINSTRIDER"] then + for _, name in pairs(self.Mounts.Plainstriders) do + mountColl[#mountColl + 1] = name + end + end + + if self.Global["RIDINGCRANE"] then + for _, name in pairs(self.Mounts.RidingCranes) do + mountColl[#mountColl + 1] = name + end + end + + if self.Global["RAVENLORD"] then + for _, name in pairs(self.Mounts.RavenLord) do + mountColl[#mountColl + 1] = name + end + end + + if self.Global["FLAMETALON"] then + for _, name in pairs(self.Mounts.Flametalon) do + mountColl[#mountColl + 1] = name + end + end + + if self.Global["ALLMOUNTS"] then -- Add druid flight forms + for _, name in pairs(self.Mounts.DruidForms) do + mountColl[#mountColl + 1] = name + end + end + + if #self.Global["MOUNTS"] > 0 then + for _, v in pairs(self.Global["MOUNTS"]) do + mountColl[#mountColl + 1] = v -- Can be both a string and a number value + end + end + + for mountName, _ in pairs(self.Global["CUSTOM"]) do + mountColl[#mountColl + 1] = mountName + end + + return CLib:HasBuff(mountColl) +end + +function C:MusicCheck() + local matchString = "^" .. self.MusicDir -- Match the music dir path at the beginning of the string only. + -- The substring has to start AFTER the matched string, adding one to the length. + local length = self.MusicDir:len() + 1 + local updated = 0 -- Keep track of how many songs that had to update + for i,v in ipairs(self.Global["MUSIC"]) do + if v:match(matchString) then + local change = v:sub(length, v:len()) -- A substring that includes only the filename (or subfolders, if any) + self.Global["MUSIC"][i] = change + self:Msg((L["SongUpdated"]):format(i, change)) + updated = updated + 1 + end + end + if updated > 0 then -- Print how many songs that were updated + self:Msg((L["SongsUpdated"]):format(updated)) + else -- All songs up to date, no action needed + self:Msg(L["SongsUpToDate"]) + end +end + +-- If isMount is true, treat song as the mount name/ID +function C:PlayMusic(song, isMount) + local songFile + if isMount then + song = song:lower() + local mountSongs = self.Global.CUSTOM[song] + if mountSongs and #mountSongs > 0 then + local id = math.random(1, #mountSongs) + songFile = mountSongs[id] + if #mountSongs > 1 and self.Global["PREVENTDUPE"] and songFile == nowPlaying then + while songFile == nowPlaying do + id = math.random(1, #mountSongs) + songFile = mountSongs[id] + end + end + self:DebugMsg((L["PlayingSong"]):format(id, songFile)) + else + self:ErrorMsg((L["CustomNotDefined"]):format(song)) + return + end + if type(songFile) ~= "string" then + self:ErrorMsg((L["CustomSongNotFound"]):format(song)) + return + end + elseif type(song) == "string" then + songFile = song + else + songFile = self.Global["MUSIC"][song] + if not songFile then + self:ErrorMsg(L["SongNotFound"]) + return false + end + self:DebugMsg((L["PlayingSong"]):format(song, songFile)) + end + nowPlaying = songFile + songFile = self.MusicDir .. songFile + PlayMusic(songFile) +end + +function C:PlayRandomMusic(mount) + if mount then + self:PlayMusic(mount, true) + else + local id = math.random(1, #self.Global["MUSIC"]) + if self.Global["PREVENTDUPE"] and #self.Global["MUSIC"] > 1 then + local name = self.Global["MUSIC"][id] + while name == nowPlaying do + id = math.random(1, #self.Global["MUSIC"]) + name = self.Global["MUSIC"][id] + end + end + self:PlayMusic(id) + end +end + +function C:AddMusic(songName) -- Add a song the the list + songName = CLib:Trim(songName) + if songName == "" or songName == nil then + self:ErrorMsg(L["NoFile"]) + return false + end + for _,v in pairs(self.Global["MUSIC"]) do -- Loop through all the songs currently in the list and... + if v == songName then -- ... make sure it isn't there already + self:ErrorMsg(L["AlreadyExists"]) + return false + end + end + table.insert(self.Global["MUSIC"], songName) -- Insert the song into list + self:Msg((L["AddedSong"]):format(songName)) + return true +end + +function C:RemoveMusic(list, songName) -- Remove a song from the list + if type(list) ~= "table" then + songName = list + list = self.Global.MUSIC + end + if type(songName) == "number" then + if list[songName] then + local name = list[songName] + table.remove(list, songName) + self:Msg((L["RemovedSong"]):format(name)) + return true + end + return false + end + songName = CLib:Trim(songName) + if songName == "" or songName == nil then + self:ErrorMsg(L["NoFile"]) + return false + end + for i,v in ipairs(list) do -- Loop through all the songs in the list until... + if v == songName then -- ... the desired one is found and then... + table.remove(list, i) -- ... remove it from the list. + self:Msg((L["RemovedSong"]):format(songName)) + return true + end + end + self:ErrorMsg(L["SongNotFound"]) + return false +end + +function C:GetCustomMusic(mount) + mount = CLib:Trim(tostring(mount)):lower() + + if type(self.Global.CUSTOM[mount]) ~= "table" then + self.Global.CUSTOM[mount] = {} + end + + return self.Global.CUSTOM[mount] +end + +function C:AddCustomMusic(song, mount) + if song then + song = CLib:Trim(tostring(song)) + end + mount = mount:lower() + if song == "" or type(song) ~= "string" then + song = nil + --self:ErrorMsg((L["AddCustomInvalidSong"]):format(tostring(song))) + --return + end + if type(mount) ~= "string" or mount == "" then + self:ErrorMsg((L["AddCustomInvalidMount"]):format(tostring(mount))) + return + end + if self.Global.CUSTOM[mount] then + if song and CLib:InTable(self.Global.CUSTOM[mount], song) then + self:ErrorMsg((L["AddCustomExists"]):format(song, mount)) + return + end + if not song then return end + table.insert(self.Global.CUSTOM[mount], song) + self:Msg((L["AddCustomSuccess"]):format(song, mount)) + else + self.Global.CUSTOM[mount] = {} + if not song then return end + table.insert(self.Global.CUSTOM[mount], song) + self:Msg((L["AddCustomSuccess"]):format(song, mount)) + end +end + +function C:RemoveCustomMusic(mount, song) + mount = mount:lower() + if type(mount) ~= "string" then + self:ErrorMsg((L["RemoveCustomInvalidMount"]):format(tostring(mount))) + end + local list = self.Global.CUSTOM[mount] + if list then + if song then + self:RemoveMusic(list, song) + else + wipe(list) + self.Global.CUSTOM[mount] = nil + self:Msg((L["RemoveCustomSuccess"]):format(mount)) + end + else + self:ErrorMsg((L["RemoveCustomNotExist"]):format(mount)) + end +end + +function C:PrintMusic() -- Print all the songs currently in list to chat + if #self.Global["MUSIC"] <= 0 then + self:Msg(L["MusicListEmpty"]) + else + for i,v in ipairs(self.Global["MUSIC"]) do + self:Msg(("\124cff00CCFF%i: %s\124r"):format(i, v)) + end + end + + if CLib:Count(self.Global["CUSTOM"]) <= 0 then + return + end + + self:Msg(L["PrintMusicCustomStart"]) + + for k,v in pairs(self.Global["CUSTOM"]) do + self:Msg((L["PrintMusicCustomHeader"]):format(k)) + for _,s in pairs(v) do + self:Msg((L["PrintMusicCustomSong"]):format(s)) + end + end +end + +function C:ResetMusic() -- Resets the values in Chocobo.Global["MUSIC"] to default + self:Msg(L["ResetMusic"]) + wipe(self.Global.MUSIC) + for _,v in pairs(self.Songs) do -- Add all the default songs again + self:AddMusic(v) + end +end + +function C:AddMount(mount) + mount = CLib:Trim(mount) + mount = tonumber(mount) or mount + if mount == "" or mount == nil then + self:ErrorMsg(L["NoMount"]) + return + end + local compare = tostring(mount):lower() + for _,v in pairs(self.Global["MOUNTS"]) do + if tostring(v):lower() == compare then + self:ErrorMsg(L["MountAlreadyExists"]) + return + end + end + table.insert(self.Global["MOUNTS"], mount) + self:Msg((L["AddedMount"]):format(mount)) +end + +function C:RemoveMount(mount) + if mount == "" or mount == nil then + self:ErrorMsg(L["NoMount"]) + return + end + mount = mount:lower() + for i,v in ipairs(self.Global["MOUNTS"]) do + if v:lower() == mount then + table.remove(self.Global["MOUNTS"], i) + self:Msg((L["RemovedMount"]):format(mount)) + return + end + end + self:ErrorMsg(L["MountNotFound"]) +end + +function C:PrintMounts() + if #self.Global["MOUNTS"] <= 0 then + self:Msg(L["MountListEmpty"]) + else + for i,v in ipairs(self.Global["MOUNTS"]) do + self:Msg(("\124cff00CCFF%i: %s\124r"):format(i, v)) + end + end +end + +function C:ResetMounts() + self:Msg(L["ResetMounts"]) + wipe(self.Global.MOUNTS) +end + +function C:FilterMount(filter, silent) + if type(filter) == "nil" then filter = Chocobo.Global["ALLMOUNTS"] end + if filter then + if not silent then self:Msg(L["HawkstriderOnly"]) end + self.Global["ALLMOUNTS"] = false + else + if not silent then self:Msg(L["AllMounts"]) end + self.Global["ALLMOUNTS"] = true + end +end + +function C:ToggleDebug() + self:Debug(not self.Global["DEBUG"], true) +end + +function C:Debug(set, silent) + if set == "enable" or set == "on" or set == true then + if not silent then self:Msg(L["DebuggingEnabled"]) end + self.Global["DEBUG"] = true + elseif set == "disable" or set == "off" or set == false then + if not silent then self:Msg(L["DebuggingDisabled"]) end + self.Global["DEBUG"] = false + elseif not silent then + if self.Global["DEBUG"] then + self:Msg(L["DebugIsEnabled"]) + else + self:Msg(L["DebugIsDisabled"]) + end + end +end + +function C:PlainstriderToggle(silent) + self.Global["PLAINSTRIDER"] = not self.Global["PLAINSTRIDER"] + if silent then return end + if self.Global["PLAINSTRIDER"] then + self:Msg(L["PlainstriderTrue"]) + else + self:Msg(L["PlainstriderFalse"]) + end +end + +function C:RidingCraneToggle(silent) + self.Global["RIDINGCRANE"] = not self.Global["RIDINGCRANE"] + if silent then return end + if self.Global["RIDINGCRANE"] then + self:Msg(L["RidingCranesTrue"]) + else + self:Msg(L["RidingCranesFalse"]) + end +end + +function C:RavenLordToggle(silent) + self.Global["RAVENLORD"] = not self.Global["RAVENLORD"] + if silent then return end + if self.Global["RAVENLORD"] then + self:Msg(L["RavenLordTrue"]) + else + self:Msg(L["RavenLordFalse"]) + end +end + +function C:FlametalonToggle(silent) + self.Global["FLAMETALON"] = not self.Global["FLAMETALON"] + if silent then return end + if self.Global["FLAMETALON"] then + self:Msg(L["FlametalonTrue"]) + else + self:Msg(L["FlametalonFalse"]) + end +end + +function C:Toggle(silent) -- Toggle the AddOn on and off + if self.Global["ENABLED"] then -- If the addon is enabled + self.Global["ENABLED"] = false -- Disable it + StopMusic() + if not silent then self:Msg(L["AddOnDisabled"]) end -- Print status + else -- If the addon is disabled + self.Global["ENABLED"] = true -- Enable it + if not silent then self:Msg(L["AddOnEnabled"]) end -- Print status + end +end + +function C:PreventDupeToggle(silent) + if self.Global["PREVENTDUPE"] then + self.Global["PREVENTDUPE"] = false + if not silent then self:Msg(L["PreventDupeDisabled"]) end + else + self.Global["PREVENTDUPE"] = true + if not silent then self:Msg(L["PreventDupeEnabled"]) end + end +end + +function C:GetGlobal(var) + return self.Global[var] +end + +function C:Msg(msg) -- Send a normal message + DEFAULT_CHAT_FRAME:AddMessage(L["MsgPrefix"] .. msg) +end + +function C:ErrorMsg(msg) -- Send an error message, these are prefixed with the word "ERROR" in red + DEFAULT_CHAT_FRAME:AddMessage(L["ErrorPrefix"] .. msg) +end + +-- Send a debug message, these are only sent when debugging is enabled and are prefixed by the word "Debug" in yellow +function C:DebugMsg(msg) + if self.Global["DEBUG"] == true then + DEFAULT_CHAT_FRAME:AddMessage(L["DebugPrefix"] .. msg) + end +end + +function C:GetVersion() + return self.Version +end + +-- Create the frame, no need for an XML file! +C.Frame = CreateFrame("Frame") +C.Frame:SetScript("OnEvent", function (frame, event, ...) C:OnEvent(frame, event, ...) end) +for k,_ in pairs(C.Events) do + if k == "UNIT_AURA" then + C.Frame:RegisterUnitEvent(k, "player") + else + C.Frame:RegisterEvent(k) + end +end + +for _, section in pairs(C.Mounts) do + for id, _ in pairs(section) do + section[id] = GetSpellInfo(id) + end +end diff --git a/Chocobo.toc b/Chocobo.toc index 378f3e6..639f594 100644 --- a/Chocobo.toc +++ b/Chocobo.toc @@ -1,34 +1,34 @@ -## Interface: 100200 -## Interface-Classic: 11500 -## Interface-Wrath: 30403 -## Version: @project-version@ -## Title: Chocobo -## Notes: Plays the Chocobo song when you mount on a hawkstrider! |cffFF0000Version @project-version@|r |cff00CCFFBy F16Gaming|r -## Author: Sharparam -## SavedVariables: CHOCOBO -## X-Project-Slug: chocobo -## X-Curse-Project-ID: 27585 -## X-WoWI-ID: 20953 -## X-Wago-ID: rkGrYgKy - -#@no-lib-strip@ -libs\LibStub\LibStub.lua -libs\CallbackHandler-1.0\CallbackHandler-1.0.xml -#@end-no-lib-strip@ - -#LibDataBroker can't be installed stand-alone -libs\LibDataBroker-1-1\LibDataBroker-1.1.lua - -#Built-in library, do not strip -libs\ChocoboLib\ChocoboLib.xml - -locales\load.xml - -Chocobo.lua -ChocoboCommand.lua -SongsAndMountsPanel.xml -ChocoboOptions.lua -ChocoboCustomSongPanel.lua -ChocoboSoundControl.lua -ChocoboSoundControlPanel.lua -Broker_Chocobo.lua +## Interface: 100200 +## Interface-Classic: 11500 +## Interface-Wrath: 30403 +## Version: @project-version@ +## Title: Chocobo +## Notes: Plays the Chocobo song when you mount on a hawkstrider! |cffFF0000Version @project-version@|r |cff00CCFFBy F16Gaming|r +## Author: Sharparam +## SavedVariables: CHOCOBO +## X-Project-Slug: chocobo +## X-Curse-Project-ID: 27585 +## X-WoWI-ID: 20953 +## X-Wago-ID: rkGrYgKy + +#@no-lib-strip@ +libs\LibStub\LibStub.lua +libs\CallbackHandler-1.0\CallbackHandler-1.0.xml +#@end-no-lib-strip@ + +#LibDataBroker can't be installed stand-alone +libs\LibDataBroker-1-1\LibDataBroker-1.1.lua + +#Built-in library, do not strip +libs\ChocoboLib\ChocoboLib.xml + +locales\load.xml + +Chocobo.lua +ChocoboCommand.lua +SongsAndMountsPanel.xml +ChocoboOptions.lua +ChocoboCustomSongPanel.lua +ChocoboSoundControl.lua +ChocoboSoundControlPanel.lua +Broker_Chocobo.lua diff --git a/ChocoboCommand.lua b/ChocoboCommand.lua index 3c3b109..95c09d7 100644 --- a/ChocoboCommand.lua +++ b/ChocoboCommand.lua @@ -1,306 +1,306 @@ ---[[ - Copyright (c) 2010-2020 by Adam Hellberg - - This file is part of Chocobo. - - Chocobo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Chocobo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Chocobo. If not, see . ---]] - -Chocobo.Command = { - Slash = { - "chocobo" - }, - Commands = {} -} - -local C = Chocobo -local CC = C.Command -local CLib = ChocoboLib -local L = _G["ChocoboLocale"] - -local AddCustomPattern = "\"([%w%p%s]+)\" \"([%w%p%s]+)\"" - --- Argument #1 (command) can be either string or a table. -function CC:Register(command, func) - if type(command) == "string" then - command = {command} - end - for _,v in pairs(command) do - if not self:HasCommand(v) then - if v ~= "__DEFAULT__" then v = v:lower() end - self.Commands[v] = func - end - end -end - -function CC:HasCommand(command) - return self.Commands[command] -end - -function CC:HandleCommand(command, args) - if self:HasCommand(command) then - self.Commands[command](args) - elseif self:HasCommand("__DEFAULT__") then - self.Commands["__DEFAULT__"](args) - else - C:ErrorMsg((L["InvalidCommand"]):format(command)) - end -end - -CC:Register("__DEFAULT__", function() - C:Msg(L["HelpMessage1"]) - C:Msg(L["HelpMessage2"]) - C:Msg(L["HelpMessage3"]) - C:Msg(L["HelpMessage4"]) - C:Msg(L["HelpMessage17"]) - C:Msg(L["HelpMessage18"]) - C:Msg(L["HelpMessage19"]) - C:Msg(L["HelpMessage5"]) - C:Msg(L["HelpMessage6"]) - C:Msg(L["HelpMessage7"]) - C:Msg(L["HelpMessage8"]) - C:Msg(L["HelpMessage9"]) - C:Msg(L["HelpMessage10"]) - C:Msg(L["HelpMessage12"]) - C:Msg(L["HelpMessage13"]) - C:Msg(L["HelpMessage14"]) - C:Msg(L["HelpMessage15"]) - C:Msg(L["HelpMessage16"]) - C:Msg(L["HelpMessage11"]) -end) - -CC:Register({"options", "o", "config", "gui"}, function() - Chocobo.SoundControl.Options:Open() - Chocobo.Options:Open() -end) - -CC:Register({"allmounts", "am", "all"}, function() C:FilterMount(false) end) -CC:Register({"hawkstrider", "hs", "hawk"}, function() C:FilterMount(true) end) -CC:Register({"modetoggle", "mounttoggle", "mt"}, function() C:FilterMount() end) -CC:Register({"toggle", "t"}, function() C:Toggle() end) -CC:Register({"plainstridertoggle", "plainstrider", "plainstriders", "ps"}, function() C:PlainstriderToggle() end) -CC:Register({"ridingcranetoggle", "ridingcrane", "ridingcranes", "rc"}, function() C:RidingCraneToggle() end) -CC:Register({"ravenlordtoggle", "ravenlord", "rl"}, function() C:RavenLordToggle() end) -CC:Register({"flametalontoggle", "flametalon", "flame", "alysrazor", "alys"}, function() C:FlametalonToggle() end) -CC:Register({"preventdupetoggle", "pdtoggle", "pdt"}, function() C:PreventDupeToggle() end) - -CC:Register({"soundcontrol", "sc", "sndctrl", "sound"}, function(args) - local handled = false - if #args > 0 then - local vol = tonumber(args[3]) - if args[1] == "gui" or args[1] == "options" then - Chocobo.SoundControl.Options:Open() - handled = true - elseif args[1] == "toggle" or args[1] == "t" then - C.SoundControl:Toggle() - handled = true - elseif args[1] == "default" or args[1] == "d" then - C.SoundControl:ToggleDefault() - handled = true - elseif args[1] == "music" or args[1] == "m" then - if #args > 1 then - if args[2] == "toggle" or args[2] == "t" then - C.SoundControl:ToggleMusic() - handled = true - elseif args[2]:match("^mount") or args[2] == "m" then - C.SoundControl:ToggleMusicMount() - handled = true - elseif args[2]:match("^not?mount") or args[2] == "nm" then - C.SoundControl:ToggleMusicNoMount() - handled = true - elseif args[2] == "volume" or args[2] == "vol" or args[2] == "v" then - if type(vol) == "number" then - C.SoundControl:SetMusicVolume(vol) - handled = true - elseif args[3] == "toggle" or args[3] == "t" then - C.SoundControl:ToggleMusicVolume() - handled = true - else - C.SoundControl:PrintMusicVolume() - handled = true - end - end - end - elseif args[1] == "sfx" or args[1] == "sound" or args[1] == "s" then - if #args > 1 then - if args[2] == "toggle" or args[2] == "t" then - C.SoundControl:ToggleSFX() - handled = true - elseif args[2]:match("^mount") or args[2] == "m" then - C.SoundControl:ToggleSFXMount() - handled = true - elseif args[2]:match("^not?mount") or args[2] == "nm" then - C.SoundControl:ToggleSFXNoMount() - handled = true - elseif args[2] == "volume" or args[2] == "vol" or args[2] == "v" then - if type(vol) == "number" then - C.SoundControl:SetSFXVolume(vol) - handled = true - elseif args[3] == "toggle" or args[3] == "t" then - C.SoundControl:ToggleSFXVolume() - handled = true - else - C.SoundControl:PrintSFXVolume() - handled = true - end - end - end - elseif args[1] == "ambience" or args[1] == "amb" or args[1] == "a" then - if #args > 1 then - if args[2] == "toggle" or args[2] == "t" then - C.SoundControl:ToggleAmbience() - handled = true - elseif args[2]:match("^mount") or args[2] == "m" then - C.SoundControl:ToggleAmbienceMount() - handled = true - elseif args[2]:match("^not?mount") or args[2] == "nm" then - C.SoundControl:ToggleAmbienceNoMount() - handled = true - elseif args[2] == "volume" or args[2] == "vol" or args[2] == "v" then - if type(vol) == "number" then - C.SoundControl:SetAmbienceVolume(vol) - handled = true - elseif args[3] == "toggle" or args[3] == "t" then - C.SoundControl:ToggleAmbienceVolume() - handled = true - else - C.SoundControl:PrintAmbienceVolume() - handled = true - end - end - end - end - end - if not handled then - C:Msg(L["SCSyntax1"]) - C:Msg(L["SCSyntax2"]) - end -end) - -CC:Register({"list", "l", "ls"}, function() C:PrintMusic() end) -CC:Register({"reset", "r"}, function() C:ResetMusic() end) -CC:Register({"listmounts", "lm"}, function() C:PrintMounts() end) -CC:Register({"resetmounts", "rm"}, function() C:ResetMounts() end) - -CC:Register({"debug", "d"}, function(args) - if not args[1] then - C:Debug() - else - C:Debug(args[1]:lower()) - end -end) - -CC:Register({"add", "a"}, function(args) - if #args > 0 then - local song = args[1] - if #args > 1 then - for i=2,#args do - song = song .. " " .. args[i] - end - end - C:AddMusic(song) - else - C:Msg(L["AddSyntax"]) - end -end) - -CC:Register({"remove", "rem", "delete", "del"}, function(args) - if #args > 0 then - local song = args[1] - if #args > 1 then - for i=2,#args do - song = song .. " " .. args[i] - end - end - C:RemoveMusic(song) - else - C:Msg(L["RemoveSyntax"]) - end -end) - -CC:Register({"addcustom", "addc", "ac"}, function(args) - if #args < 2 then - C:ErrorMsg(L["AddCustomSyntax"]) - return - end - local arg = args[1] - for i=2,#args do - arg = arg .. " " .. args[i] - end - local mount, song = arg:match(AddCustomPattern) - if not mount or not song then - C:ErrorMsg(L["AddCustomSyntax"]) - return - end - C:AddCustomMusic(song, mount) -end) - -CC:Register({"removecustom", "removec", "remc", "rc"}, function(args) - if #args < 1 then - C:ErrorMsg(L["RemoveCustomSyntax"]) - return - end - local arg = args[1] - if #args > 1 then - for i=2,#args do - arg = arg .. " " .. args[i] - end - end - C:RemoveCustomMusic(arg) -end) - -CC:Register({"addmount", "addm"}, function(args) - if #args > 0 then - local mount = args[1] - if #args > 1 then - for i=2,#args do - mount = mount .. " " .. args[i] - end - end - C:AddMount(mount) - else - C:Msg(L["AddMountSyntax"]) - end -end) - -CC:Register({"removemount", "remm", "deletemount", "delmount", "delm"}, function(args) - if #args > 0 then - local mount = args[1] - if #args > 1 then - for i=2,#args do - mount = mount .. " " .. args[i] - end - end - C:RemoveMount(mount) - else - C:Msg(L["RemoveMountSyntax"]) - end -end) - -for i,v in ipairs(CC.Slash) do - _G["SLASH_" .. C.Name:upper() .. i] = "/" .. v -end - -SlashCmdList[C.Name:upper()] = function(msg) - msg = CLib:Trim(msg) - local args = CLib:Split(msg) - local cmd = args[1] - local t = {} - if #args > 1 then - for i=2,#args do - table.insert(t, args[i]) - end - end - CC:HandleCommand(cmd, t) -end +--[[ + Copyright (c) 2010-2020 by Adam Hellberg + + This file is part of Chocobo. + + Chocobo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Chocobo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Chocobo. If not, see . +--]] + +Chocobo.Command = { + Slash = { + "chocobo" + }, + Commands = {} +} + +local C = Chocobo +local CC = C.Command +local CLib = ChocoboLib +local L = _G["ChocoboLocale"] + +local AddCustomPattern = "\"([%w%p%s]+)\" \"([%w%p%s]+)\"" + +-- Argument #1 (command) can be either string or a table. +function CC:Register(command, func) + if type(command) == "string" then + command = {command} + end + for _,v in pairs(command) do + if not self:HasCommand(v) then + if v ~= "__DEFAULT__" then v = v:lower() end + self.Commands[v] = func + end + end +end + +function CC:HasCommand(command) + return self.Commands[command] +end + +function CC:HandleCommand(command, args) + if self:HasCommand(command) then + self.Commands[command](args) + elseif self:HasCommand("__DEFAULT__") then + self.Commands["__DEFAULT__"](args) + else + C:ErrorMsg((L["InvalidCommand"]):format(command)) + end +end + +CC:Register("__DEFAULT__", function() + C:Msg(L["HelpMessage1"]) + C:Msg(L["HelpMessage2"]) + C:Msg(L["HelpMessage3"]) + C:Msg(L["HelpMessage4"]) + C:Msg(L["HelpMessage17"]) + C:Msg(L["HelpMessage18"]) + C:Msg(L["HelpMessage19"]) + C:Msg(L["HelpMessage5"]) + C:Msg(L["HelpMessage6"]) + C:Msg(L["HelpMessage7"]) + C:Msg(L["HelpMessage8"]) + C:Msg(L["HelpMessage9"]) + C:Msg(L["HelpMessage10"]) + C:Msg(L["HelpMessage12"]) + C:Msg(L["HelpMessage13"]) + C:Msg(L["HelpMessage14"]) + C:Msg(L["HelpMessage15"]) + C:Msg(L["HelpMessage16"]) + C:Msg(L["HelpMessage11"]) +end) + +CC:Register({"options", "o", "config", "gui"}, function() + Chocobo.SoundControl.Options:Open() + Chocobo.Options:Open() +end) + +CC:Register({"allmounts", "am", "all"}, function() C:FilterMount(false) end) +CC:Register({"hawkstrider", "hs", "hawk"}, function() C:FilterMount(true) end) +CC:Register({"modetoggle", "mounttoggle", "mt"}, function() C:FilterMount() end) +CC:Register({"toggle", "t"}, function() C:Toggle() end) +CC:Register({"plainstridertoggle", "plainstrider", "plainstriders", "ps"}, function() C:PlainstriderToggle() end) +CC:Register({"ridingcranetoggle", "ridingcrane", "ridingcranes", "rc"}, function() C:RidingCraneToggle() end) +CC:Register({"ravenlordtoggle", "ravenlord", "rl"}, function() C:RavenLordToggle() end) +CC:Register({"flametalontoggle", "flametalon", "flame", "alysrazor", "alys"}, function() C:FlametalonToggle() end) +CC:Register({"preventdupetoggle", "pdtoggle", "pdt"}, function() C:PreventDupeToggle() end) + +CC:Register({"soundcontrol", "sc", "sndctrl", "sound"}, function(args) + local handled = false + if #args > 0 then + local vol = tonumber(args[3]) + if args[1] == "gui" or args[1] == "options" then + Chocobo.SoundControl.Options:Open() + handled = true + elseif args[1] == "toggle" or args[1] == "t" then + C.SoundControl:Toggle() + handled = true + elseif args[1] == "default" or args[1] == "d" then + C.SoundControl:ToggleDefault() + handled = true + elseif args[1] == "music" or args[1] == "m" then + if #args > 1 then + if args[2] == "toggle" or args[2] == "t" then + C.SoundControl:ToggleMusic() + handled = true + elseif args[2]:match("^mount") or args[2] == "m" then + C.SoundControl:ToggleMusicMount() + handled = true + elseif args[2]:match("^not?mount") or args[2] == "nm" then + C.SoundControl:ToggleMusicNoMount() + handled = true + elseif args[2] == "volume" or args[2] == "vol" or args[2] == "v" then + if type(vol) == "number" then + C.SoundControl:SetMusicVolume(vol) + handled = true + elseif args[3] == "toggle" or args[3] == "t" then + C.SoundControl:ToggleMusicVolume() + handled = true + else + C.SoundControl:PrintMusicVolume() + handled = true + end + end + end + elseif args[1] == "sfx" or args[1] == "sound" or args[1] == "s" then + if #args > 1 then + if args[2] == "toggle" or args[2] == "t" then + C.SoundControl:ToggleSFX() + handled = true + elseif args[2]:match("^mount") or args[2] == "m" then + C.SoundControl:ToggleSFXMount() + handled = true + elseif args[2]:match("^not?mount") or args[2] == "nm" then + C.SoundControl:ToggleSFXNoMount() + handled = true + elseif args[2] == "volume" or args[2] == "vol" or args[2] == "v" then + if type(vol) == "number" then + C.SoundControl:SetSFXVolume(vol) + handled = true + elseif args[3] == "toggle" or args[3] == "t" then + C.SoundControl:ToggleSFXVolume() + handled = true + else + C.SoundControl:PrintSFXVolume() + handled = true + end + end + end + elseif args[1] == "ambience" or args[1] == "amb" or args[1] == "a" then + if #args > 1 then + if args[2] == "toggle" or args[2] == "t" then + C.SoundControl:ToggleAmbience() + handled = true + elseif args[2]:match("^mount") or args[2] == "m" then + C.SoundControl:ToggleAmbienceMount() + handled = true + elseif args[2]:match("^not?mount") or args[2] == "nm" then + C.SoundControl:ToggleAmbienceNoMount() + handled = true + elseif args[2] == "volume" or args[2] == "vol" or args[2] == "v" then + if type(vol) == "number" then + C.SoundControl:SetAmbienceVolume(vol) + handled = true + elseif args[3] == "toggle" or args[3] == "t" then + C.SoundControl:ToggleAmbienceVolume() + handled = true + else + C.SoundControl:PrintAmbienceVolume() + handled = true + end + end + end + end + end + if not handled then + C:Msg(L["SCSyntax1"]) + C:Msg(L["SCSyntax2"]) + end +end) + +CC:Register({"list", "l", "ls"}, function() C:PrintMusic() end) +CC:Register({"reset", "r"}, function() C:ResetMusic() end) +CC:Register({"listmounts", "lm"}, function() C:PrintMounts() end) +CC:Register({"resetmounts", "rm"}, function() C:ResetMounts() end) + +CC:Register({"debug", "d"}, function(args) + if not args[1] then + C:Debug() + else + C:Debug(args[1]:lower()) + end +end) + +CC:Register({"add", "a"}, function(args) + if #args > 0 then + local song = args[1] + if #args > 1 then + for i=2,#args do + song = song .. " " .. args[i] + end + end + C:AddMusic(song) + else + C:Msg(L["AddSyntax"]) + end +end) + +CC:Register({"remove", "rem", "delete", "del"}, function(args) + if #args > 0 then + local song = args[1] + if #args > 1 then + for i=2,#args do + song = song .. " " .. args[i] + end + end + C:RemoveMusic(song) + else + C:Msg(L["RemoveSyntax"]) + end +end) + +CC:Register({"addcustom", "addc", "ac"}, function(args) + if #args < 2 then + C:ErrorMsg(L["AddCustomSyntax"]) + return + end + local arg = args[1] + for i=2,#args do + arg = arg .. " " .. args[i] + end + local mount, song = arg:match(AddCustomPattern) + if not mount or not song then + C:ErrorMsg(L["AddCustomSyntax"]) + return + end + C:AddCustomMusic(song, mount) +end) + +CC:Register({"removecustom", "removec", "remc", "rc"}, function(args) + if #args < 1 then + C:ErrorMsg(L["RemoveCustomSyntax"]) + return + end + local arg = args[1] + if #args > 1 then + for i=2,#args do + arg = arg .. " " .. args[i] + end + end + C:RemoveCustomMusic(arg) +end) + +CC:Register({"addmount", "addm"}, function(args) + if #args > 0 then + local mount = args[1] + if #args > 1 then + for i=2,#args do + mount = mount .. " " .. args[i] + end + end + C:AddMount(mount) + else + C:Msg(L["AddMountSyntax"]) + end +end) + +CC:Register({"removemount", "remm", "deletemount", "delmount", "delm"}, function(args) + if #args > 0 then + local mount = args[1] + if #args > 1 then + for i=2,#args do + mount = mount .. " " .. args[i] + end + end + C:RemoveMount(mount) + else + C:Msg(L["RemoveMountSyntax"]) + end +end) + +for i,v in ipairs(CC.Slash) do + _G["SLASH_" .. C.Name:upper() .. i] = "/" .. v +end + +SlashCmdList[C.Name:upper()] = function(msg) + msg = CLib:Trim(msg) + local args = CLib:Split(msg) + local cmd = args[1] + local t = {} + if #args > 1 then + for i=2,#args do + table.insert(t, args[i]) + end + end + CC:HandleCommand(cmd, t) +end diff --git a/ChocoboCustomSongPanel.lua b/ChocoboCustomSongPanel.lua index c6d14fd..e935bc0 100644 --- a/ChocoboCustomSongPanel.lua +++ b/ChocoboCustomSongPanel.lua @@ -1,217 +1,217 @@ ---[[ - Copyright (c) 2010-2020 by Adam Hellberg - - This file is part of Chocobo. - - Chocobo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Chocobo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Chocobo. If not, see . ---]] - -local L = _G["ChocoboLocale"] - -local C = Chocobo - -C.CustomSongPanel = {} - -local CSP = C.CustomSongPanel - -local function createList(parent, header, listGetter, addFunc, removeFunc, resetFunc, itemClickFunc) - local list = CreateFrame("Frame", nil, parent, "ChocoboSongsAndMountsListTemplate") - list.items = {} - list.Header:SetText(header) - list.AddButton:SetText(L["Options_Add"]) - list.AddButton:SetScript("OnClick", function() - local item = list.EditBox:GetText() - addFunc(item) - list:RefreshLayout() - list.EditBox:SetText("") - end) - list.ResetButton:SetText(L["Options_Reset"]) - list.ResetButton:SetScript("OnClick", function() - resetFunc() - list:RefreshLayout() - end) - list.ListScrollFrame.update = function() list:RefreshLayout() end - list:SetScript("OnShow", function(self) - self.items = listGetter() - HybridScrollFrame_CreateButtons(self.ListScrollFrame, "ChocoboSongsAndMountsItemTemplate") - self:RefreshLayout() - end) - function list:RemoveItem(index) - local item = listGetter()[index] - removeFunc(item) - self:RefreshLayout() - end - function list:RefreshLayout() - local items = listGetter() - - if items then - self.EditBox:Enable() - self.AddButton:Enable() - else - self.EditBox:Disable() - self.AddButton:Disable() - items = {} - end - - local buttons = HybridScrollFrame_GetButtons(self.ListScrollFrame) - if not buttons then return end - local offset = HybridScrollFrame_GetOffset(self.ListScrollFrame) - - for buttonIndex = 1, #buttons do - local button = buttons[buttonIndex] - local itemIndex = buttonIndex + offset - - button:UnlockHighlight() - - if itemIndex <= #items then - local item = items[itemIndex] - button:SetID(itemIndex) - button.Text:SetText(item) - button:SetWidth(self.ListScrollFrame.scrollChild:GetWidth()) - if itemClickFunc then - button:SetScript("OnClick", function(btn) - for _, b in pairs(buttons) do b:UnlockHighlight() end - btn:LockHighlight() - itemClickFunc(item) - end) - end - button:Show() - else - button:Hide() - end - end - - local buttonHeight = self.ListScrollFrame.buttonHeight - local totalHeight = #items * buttonHeight - local shownHeight = #buttons * buttonHeight - - HybridScrollFrame_Update(self.ListScrollFrame, totalHeight, shownHeight) - end - function list:ClearHighlights() - local buttons = HybridScrollFrame_GetButtons(self.ListScrollFrame) - if not buttons then return end - for _, btn in pairs(buttons) do - btn:UnlockHighlight() - end - end - - HybridScrollFrame_SetDoNotHideScrollBar(list.ListScrollFrame, true) - - return list -end - -local frame = CreateFrame("Frame") -CSP.Frame = frame -frame:Hide() -frame.name = "Custom Songs" -frame.parent = "Chocobo" -frame.refresh = function() CSP:Update() end - -frame.description = CreateFrame("Frame", nil, frame) -frame.description:SetSize(600, 25) -frame.description:SetPoint("TOP", 0, -10) -frame.description.label = frame.description:CreateFontString(nil, "OVERLAY", nil) -frame.description.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.description.label:SetText("%CUSTOMSONG_DESCRIPTION%") -frame.description.label:SetPoint("TOPLEFT") -frame.description.label:SetPoint("BOTTOMRIGHT") -frame.description.label:SetTextColor(1, 0.8196079, 0) -frame.description.label:SetText(L["CustomSongPanel_Description"]) - -frame.mounts = createList( - frame, - L["SongsAndMounts_Mounts"], - function() - local items = {} - for k, _ in pairs(C.Global.CUSTOM) do - items[#items + 1] = k - end - sort(items) - return items - end, - function(item) - C:AddCustomMusic(nil, item) - frame.songs:Clear() - end, - function(item) - C:RemoveCustomMusic(item) - frame.songs:Clear() - end, - function() end, - function(item) - frame.songs.mount = item - frame.songs:RefreshLayout() - frame.songs.Header:SetText(L["SongsAndMounts_SongsForMount"]:format(item)) - end) -frame.mounts:SetPoint("TOP", frame.description, "BOTTOM") -frame.mounts:SetPoint("LEFT", 5, 0) -frame.mounts:SetPoint("RIGHT", frame, "BOTTOM", -20, 0) -frame.mounts:SetPoint("BOTTOM", 0, 5) -frame.mounts.ResetButton:Disable() - -frame.songs = createList( - frame, - L["SongsAndMounts_Songs"], - function() - local mount = frame.songs.mount - if not mount then return nil end - return C:GetCustomMusic(mount) - end, - function(item) - local mount = frame.songs.mount - if not mount then return end - C:AddCustomMusic(item, mount) - end, - function(item) - local mount = frame.songs.mount - if not mount then return end - C:RemoveCustomMusic(mount, item) - end, - function() - local mount = frame.songs.mount - if not mount then return end - C:RemoveCustomMusic(mount) - frame.mounts:RefreshLayout() - end) -frame.songs:SetPoint("TOP", frame.mounts, "TOP") -frame.songs:SetPoint("LEFT", frame, "BOTTOM") -frame.songs:SetPoint("RIGHT", -25, 0) -frame.songs:SetPoint("BOTTOM", frame.mounts, "BOTTOM") -function frame.songs:Clear() - self.mount = nil - self.Header:SetText(L["SongsAndMounts_Songs"]) - self:RefreshLayout() -end - -function CSP:Update() - frame.mounts:ClearHighlights() - frame.songs.mount = nil - frame.songs.Header:SetText(L["SongsAndMounts_Songs"]) - frame.songs:RefreshLayout() -end - -frame:SetScript("OnShow", function() CSP:Update() end) - -frame.OnCommit = function() end -frame.OnDefault = function() end -frame.OnRefresh = function() CSP:Update() end - -if Settings and SettingsPanel then - local category = Settings.GetCategory(C.Name) - local subcategory = Settings.RegisterCanvasLayoutSubcategory(category, frame, "Custom Songs") - Settings.RegisterAddOnCategory(subcategory) -else - InterfaceOptions_AddCategory(frame, C.Name) -end - +--[[ + Copyright (c) 2010-2020 by Adam Hellberg + + This file is part of Chocobo. + + Chocobo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Chocobo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Chocobo. If not, see . +--]] + +local L = _G["ChocoboLocale"] + +local C = Chocobo + +C.CustomSongPanel = {} + +local CSP = C.CustomSongPanel + +local function createList(parent, header, listGetter, addFunc, removeFunc, resetFunc, itemClickFunc) + local list = CreateFrame("Frame", nil, parent, "ChocoboSongsAndMountsListTemplate") + list.items = {} + list.Header:SetText(header) + list.AddButton:SetText(L["Options_Add"]) + list.AddButton:SetScript("OnClick", function() + local item = list.EditBox:GetText() + addFunc(item) + list:RefreshLayout() + list.EditBox:SetText("") + end) + list.ResetButton:SetText(L["Options_Reset"]) + list.ResetButton:SetScript("OnClick", function() + resetFunc() + list:RefreshLayout() + end) + list.ListScrollFrame.update = function() list:RefreshLayout() end + list:SetScript("OnShow", function(self) + self.items = listGetter() + HybridScrollFrame_CreateButtons(self.ListScrollFrame, "ChocoboSongsAndMountsItemTemplate") + self:RefreshLayout() + end) + function list:RemoveItem(index) + local item = listGetter()[index] + removeFunc(item) + self:RefreshLayout() + end + function list:RefreshLayout() + local items = listGetter() + + if items then + self.EditBox:Enable() + self.AddButton:Enable() + else + self.EditBox:Disable() + self.AddButton:Disable() + items = {} + end + + local buttons = HybridScrollFrame_GetButtons(self.ListScrollFrame) + if not buttons then return end + local offset = HybridScrollFrame_GetOffset(self.ListScrollFrame) + + for buttonIndex = 1, #buttons do + local button = buttons[buttonIndex] + local itemIndex = buttonIndex + offset + + button:UnlockHighlight() + + if itemIndex <= #items then + local item = items[itemIndex] + button:SetID(itemIndex) + button.Text:SetText(item) + button:SetWidth(self.ListScrollFrame.scrollChild:GetWidth()) + if itemClickFunc then + button:SetScript("OnClick", function(btn) + for _, b in pairs(buttons) do b:UnlockHighlight() end + btn:LockHighlight() + itemClickFunc(item) + end) + end + button:Show() + else + button:Hide() + end + end + + local buttonHeight = self.ListScrollFrame.buttonHeight + local totalHeight = #items * buttonHeight + local shownHeight = #buttons * buttonHeight + + HybridScrollFrame_Update(self.ListScrollFrame, totalHeight, shownHeight) + end + function list:ClearHighlights() + local buttons = HybridScrollFrame_GetButtons(self.ListScrollFrame) + if not buttons then return end + for _, btn in pairs(buttons) do + btn:UnlockHighlight() + end + end + + HybridScrollFrame_SetDoNotHideScrollBar(list.ListScrollFrame, true) + + return list +end + +local frame = CreateFrame("Frame") +CSP.Frame = frame +frame:Hide() +frame.name = "Custom Songs" +frame.parent = "Chocobo" +frame.refresh = function() CSP:Update() end + +frame.description = CreateFrame("Frame", nil, frame) +frame.description:SetSize(600, 25) +frame.description:SetPoint("TOP", 0, -10) +frame.description.label = frame.description:CreateFontString(nil, "OVERLAY", nil) +frame.description.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.description.label:SetText("%CUSTOMSONG_DESCRIPTION%") +frame.description.label:SetPoint("TOPLEFT") +frame.description.label:SetPoint("BOTTOMRIGHT") +frame.description.label:SetTextColor(1, 0.8196079, 0) +frame.description.label:SetText(L["CustomSongPanel_Description"]) + +frame.mounts = createList( + frame, + L["SongsAndMounts_Mounts"], + function() + local items = {} + for k, _ in pairs(C.Global.CUSTOM) do + items[#items + 1] = k + end + sort(items) + return items + end, + function(item) + C:AddCustomMusic(nil, item) + frame.songs:Clear() + end, + function(item) + C:RemoveCustomMusic(item) + frame.songs:Clear() + end, + function() end, + function(item) + frame.songs.mount = item + frame.songs:RefreshLayout() + frame.songs.Header:SetText(L["SongsAndMounts_SongsForMount"]:format(item)) + end) +frame.mounts:SetPoint("TOP", frame.description, "BOTTOM") +frame.mounts:SetPoint("LEFT", 5, 0) +frame.mounts:SetPoint("RIGHT", frame, "BOTTOM", -20, 0) +frame.mounts:SetPoint("BOTTOM", 0, 5) +frame.mounts.ResetButton:Disable() + +frame.songs = createList( + frame, + L["SongsAndMounts_Songs"], + function() + local mount = frame.songs.mount + if not mount then return nil end + return C:GetCustomMusic(mount) + end, + function(item) + local mount = frame.songs.mount + if not mount then return end + C:AddCustomMusic(item, mount) + end, + function(item) + local mount = frame.songs.mount + if not mount then return end + C:RemoveCustomMusic(mount, item) + end, + function() + local mount = frame.songs.mount + if not mount then return end + C:RemoveCustomMusic(mount) + frame.mounts:RefreshLayout() + end) +frame.songs:SetPoint("TOP", frame.mounts, "TOP") +frame.songs:SetPoint("LEFT", frame, "BOTTOM") +frame.songs:SetPoint("RIGHT", -25, 0) +frame.songs:SetPoint("BOTTOM", frame.mounts, "BOTTOM") +function frame.songs:Clear() + self.mount = nil + self.Header:SetText(L["SongsAndMounts_Songs"]) + self:RefreshLayout() +end + +function CSP:Update() + frame.mounts:ClearHighlights() + frame.songs.mount = nil + frame.songs.Header:SetText(L["SongsAndMounts_Songs"]) + frame.songs:RefreshLayout() +end + +frame:SetScript("OnShow", function() CSP:Update() end) + +frame.OnCommit = function() end +frame.OnDefault = function() end +frame.OnRefresh = function() CSP:Update() end + +if Settings and SettingsPanel then + local category = Settings.GetCategory(C.Name) + local subcategory = Settings.RegisterCanvasLayoutSubcategory(category, frame, "Custom Songs") + Settings.RegisterAddOnCategory(subcategory) +else + InterfaceOptions_AddCategory(frame, C.Name) +end + diff --git a/ChocoboSoundControl.lua b/ChocoboSoundControl.lua index c4f0008..cce09ab 100644 --- a/ChocoboSoundControl.lua +++ b/ChocoboSoundControl.lua @@ -1,404 +1,404 @@ ---[[ - Copyright (c) 2010-2020 by Adam Hellberg - - This file is part of Chocobo. - - Chocobo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Chocobo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Chocobo. If not, see . ---]] - -local C = Chocobo - -C.SoundControl = { - Version = 1, - Settings = {} -} - -local SC = C.SoundControl - -local L = _G["ChocoboLocale"] - -function SC:Init() - if type(C.Global["SOUNDCONTROL"]) ~= "table" then - C:Msg(L["SoundControlNotSet"]) - self:SetupVars() - end - - self.Settings = C.Global["SOUNDCONTROL"] - - if (self.Settings["VERSION"] or 0) < self.Version then - C:ErrorMsg(L["SCVarsOutOfDate"]) - self:SetupVars(true) -- Reset vars, preserving any user-made settings - end - - self:Check() -end - -function SC:SetupVars(reset) - local e, d, se, sm, sn, sv, smv, me, mm, mn, mv, mmv, ae, am, an, av, amv = - false, - true, - true, - false, - false, - 1.0, - false, - true, - true, - false, - 1.0, - true, - true, - false, - false, - 1.0, - false - if reset then - e = self.Settings["ENABLED"] or false - d = self.Settings["DEFAULT"] or true - local sfx = "SFX" - local vol = "VOLUME" - if type(self.Settings["VERSION"]) == "nil" then - sfx = "SOUND" - vol = "DEFAULT_VOLUME" - end - se = self.Settings[sfx]["ENABLED"] or true - sm = self.Settings[sfx]["MOUNTED"] or false - sn = self.Settings[sfx]["NOTMOUNTED"] or false - sv = self.Settings[sfx][vol] or 1.0 - smv = self.Settings[sfx]["MOD_VOLUME"] or false - me = self.Settings["MUSIC"]["ENABLED"] or true - mm = self.Settings["MUSIC"]["MOUNTED"] or true - mn = self.Settings["MUSIC"]["NOTMOUNTED"] or false - mv = self.Settings["MUSIC"][vol] or 1.0 - mmv = self.Settings["MUSIC"]["MOD_VOLUME"] or true - ae = self.Settings["AMBIENCE"]["ENABLED"] or true - am = self.Settings["AMBIENCE"]["MOUNTED"] or false - an = self.Settings["AMBIENCE"]["NOTMOUNTED"] or false - av = self.Settings["AMBIENCE"][vol] or 1.0 - amv = self.Settings["AMBIENCE"]["MOD_VOLUME"] or false - end - C.Global["SOUNDCONTROL"] = { - ["VERSION"] = self.Version, - ["ENABLED"] = e, -- Enable sound control at all? - ["DEFAULT"] = d, -- Use the old style sound control? - ["SFX"] = { - ["ENABLED"] = se, -- Should AddOn control SFX playback? - ["MOUNTED"] = sm, -- SFX when mounted? - ["NOTMOUNTED"] = sn, -- SFX when not mounted? - ["VOLUME"] = sv, -- Volume to modify to if volume <= 0 - ["MOD_VOLUME"] = smv -- Whether or not to modify volume - }, - ["MUSIC"] = { - ["ENABLED"] = me, -- Should AddOn control music playback? - ["MOUNTED"] = mm, -- Music when mounted? - ["NOTMOUNTED"] = mn, -- Music when not mounted? - ["VOLUME"] = mv, -- Volume to modify to if volume <= 0 - ["MOD_VOLUME"] = mmv -- Whether or not to modify volume - }, - ["AMBIENCE"] = { - ["ENABLED"] = ae, -- Should AddOn control ambience playback? - ["MOUNTED"] = am, -- Ambience when mounted? - ["NOTMOUNTED"] = an, -- Ambience when not mounted? - ["VOLUME"] = av, -- Volume to modify to if volume <= 0 - ["MOD_VOLUME"] = amv -- Whether or not to modify volume - } - } - self.Settings = C.Global["SOUNDCONTROL"] - if reset then C:Msg(L["SoundControlReset"]) end -end - -local function BoolToNum(bool) - if bool then return 1 else return 0 end -end - -function SC:Toggle(silent) - self.Settings["ENABLED"] = not self.Settings["ENABLED"] - if self.Settings["ENABLED"] then - if not silent then C:Msg(L["SCEnabled"]) end - self:Check() - else - if not silent then C:Msg(L["SCDisabled"]) end - self:Restore() - end -end - -function SC:ToggleDefault(silent) - self.Settings["DEFAULT"] = not self.Settings["DEFAULT"] - self:Check() - if silent then return end - if self.Settings["DEFAULT"] then - C:Msg(L["SCDefaultEnabled"]) - else - C:Msg(L["SCDefaultDisabled"]) - end -end - -function SC:ToggleMusic(silent) - self.Settings["MUSIC"]["ENABLED"] = not self.Settings["MUSIC"]["ENABLED"] - self:Check() - if silent then return end - if self.Settings["MUSIC"]["ENABLED"] then - C:Msg(L["SCMusicEnabled"]) - else - C:Msg(L["SCMusicDisabled"]) - end -end - -function SC:ToggleMusicMount(silent) - self.Settings["MUSIC"]["MOUNTED"] = not self.Settings["MUSIC"]["MOUNTED"] - self:Check() - if silent then return end - if self.Settings["MUSIC"]["MOUNTED"] then - C:Msg(L["SCMusicMountEnabled"]) - else - C:Msg(L["SCMusicMountDisabled"]) - end -end - -function SC:ToggleMusicNoMount(silent) - self.Settings["MUSIC"]["NOTMOUNTED"] = not self.Settings["MUSIC"]["NOTMOUNTED"] - self:Check() - if silent then return end - if self.Settings["MUSIC"]["NOTMOUNTED"] then - C:Msg(L["SCMusicNoMountEnabled"]) - else - C:Msg(L["SCMusicNoMountDisabled"]) - end -end - -function SC:ToggleMusicVolume(silent) - self.Settings["MUSIC"]["MOD_VOLUME"] = not self.Settings["MUSIC"]["MOD_VOLUME"] - self:VolumeCheck() - if silent then return end - if self.Settings["MUSIC"]["MOD_VOLUME"] then - C:Msg(L["SCMusicVolumeEnabled"]) - else - C:Msg(L["SCMusicVolumeDisabled"]) - end -end - -function SC:ToggleSFX(silent) - self.Settings["SFX"]["ENABLED"] = not self.Settings["SFX"]["ENABLED"] - self:Check() - if silent then return end - if self.Settings["SFX"]["ENABLED"] then - C:Msg(L["SCSFXEnabled"]) - else - C:Msg(L["SCSFXDisabled"]) - end -end - -function SC:ToggleSFXMount(silent) - self.Settings["SFX"]["MOUNTED"] = not self.Settings["SFX"]["MOUNTED"] - self:Check() - if silent then return end - if self.Settings["SFX"]["MOUNTED"] then - C:Msg(L["SCSFXMountEnabled"]) - else - C:Msg(L["SCSFXMountDisabled"]) - end -end - -function SC:ToggleSFXNoMount(silent) - self.Settings["SFX"]["NOTMOUNTED"] = not self.Settings["SFX"]["NOTMOUNTED"] - self:Check() - if silent then return end - if self.Settings["SFX"]["NOTMOUNTED"] then - C:Msg(L["SCSFXNoMountEnabled"]) - else - C:Msg(L["SCSFXNoMountDisabled"]) - end -end - -function SC:ToggleSFXVolume(silent) - self.Settings["SFX"]["MOD_VOLUME"] = not self.Settings["SFX"]["MOD_VOLUME"] - self:VolumeCheck() - if silent then return end - if self.Settings["SFX"]["MOD_VOLUME"] then - C:Msg(L["SCSFXVolumeEnabled"]) - else - C:Msg(L["SCSFXVolumeDisabled"]) - end -end - -function SC:ToggleAmbience(silent) - self.Settings["AMBIENCE"]["ENABLED"] = not self.Settings["AMBIENCE"]["ENABLED"] - self:Check() - if silent then return end - if self.Settings["AMBIENCE"]["ENABLED"] then - C:Msg(L["SCAmbEnabled"]) - else - C:Msg(L["SCAmbDisabled"]) - end -end - -function SC:ToggleAmbienceMount(silent) - self.Settings["AMBIENCE"]["MOUNTED"] = not self.Settings["AMBIENCE"]["MOUNTED"] - self:Check() - if silent then return end - if self.Settings["AMBIENCE"]["MOUNTED"] then - C:Msg(L["SCAmbMountEnabled"]) - else - C:Msg(L["SCAmbMountDisabled"]) - end -end - -function SC:ToggleAmbienceNoMount(silent) - self.Settings["AMBIENCE"]["NOTMOUNTED"] = not self.Settings["AMBIENCE"]["NOTMOUNTED"] - self:Check() - if silent then return end - if self.Settings["AMBIENCE"]["NOTMOUNTED"] then - C:Msg(L["SCAmbNoMountEnabled"]) - else - C:Msg(L["SCAmbNoMountDisabled"]) - end -end - -function SC:ToggleAmbienceVolume(silent) - self.Settings["AMBIENCE"]["MOD_VOLUME"] = not self.Settings["AMBIENCE"]["MOD_VOLUME"] - self:VolumeCheck() - if silent then return end - if self.Settings["AMBIENCE"]["MOD_VOLUME"] then - C:Msg(L["SCAmbVolumeEnabled"]) - else - C:Msg(L["SCAmbVolumeDisabled"]) - end -end - -function SC:ValidateVolume(volume) - if volume < 0 or volume > 100 then - C:ErrorMsg(L["SCVolumeOutOfRange"]) - return false - end - return true -end - -function SC:SetMusicVolume(volume, silent) - if self.Settings["DEFAULT"] then - if not silent then C:ErrorMsg(L["SCVolumeNotAllowed"]) end - return - end - if self:ValidateVolume(volume) then - local vol = volume / 100 - self.Settings["MUSIC"]["VOLUME"] = vol - self:VolumeCheck() - if not silent then C:Msg((L["SCNewMusicVolume"]):format(volume)) end - end -end - -function SC:SetSFXVolume(volume, silent) - if self.Settings["DEFAULT"] then - if not silent then C:ErrorMsg(L["SCVolumeNotAllowed"]) end - return - end - if self:ValidateVolume(volume) then - local vol = volume / 100 - self.Settings["SFX"]["VOLUME"] = vol - self:VolumeCheck() - if not silent then C:Msg((L["SCNewSFXVolume"]):format(volume)) end - end -end - -function SC:SetAmbienceVolume(volume, silent) - if self.Settings["DEFAULT"] then - if not silent then C:ErrorMsg(L["SCVolumeNotAllowed"]) end - return - end - if self:ValidateVolume(volume) then - local vol = volume / 100 - self.Settings["AMBIENCE"]["VOLUME"] = vol - self:VolumeCheck() - if not silent then C:Msg((L["SCNewAmbVolume"]):format(volume)) end - end -end - -function SC:PrintMusicVolume() - C:Msg((L["SCMusicVolume"]):format(self.Settings["MUSIC"]["VOLUME"] * 100)) -end - -function SC:PrintSFXVolume() - C:Msg((L["SCSFXVolume"]):format(self.Settings["SFX"]["VOLUME"] * 100)) -end - -function SC:PrintAmbienceVolume() - C:Msg((L["SCAmbienceVolume"]):format(self.Settings["AMBIENCE"]["VOLUME"] * 100)) -end - -function SC:Restore() - SetCVar("Sound_EnableAllSound", 1) - SetCVar("Sound_EnableSFX", 1) - SetCVar("Sound_EnableMusic", 1) - SetCVar("Sound_EnableAmbience", 1) -end - -function SC:VolumeCheck() - if not self.Settings["ENABLED"] then return end - if self.Settings["DEFAULT"] then return end - if self.Settings["MUSIC"]["MOD_VOLUME"] then - SetCVar("Sound_MusicVolume", self.Settings["MUSIC"]["VOLUME"]) - end - if self.Settings["SFX"]["MOD_VOLUME"] then - SetCVar("Sound_SFXVolume", self.Settings["SFX"]["VOLUME"]) - end - if self.Settings["AMBIENCE"]["MOD_VOLUME"] then - SetCVar("Sound_AmbienceVolume", self.Settings["AMBIENCE"]["VOLUME"]) - end -end - -function SC:Check() - if not self.Settings["ENABLED"] then return end - if tonumber(GetCVar("Sound_EnableAllSound")) == 0 then - SetCVar("Sound_EnableAllSound", 1) - end - -- Player is currently dismounting or dismounted - if (C.Mounted and C.Running) or (not C.Mounted and not C.Running) then - if self.Settings["DEFAULT"] then - SetCVar("Sound_EnableMusic", 0) - SetCVar("Sound_EnableSFX", 0) - SetCVar("Sound_EnableAmbience", 0) - else - if self.Settings["MUSIC"]["ENABLED"] then - SetCVar("Sound_EnableMusic", BoolToNum(self.Settings["MUSIC"]["NOTMOUNTED"])) - end - if self.Settings["SFX"]["ENABLED"] then - SetCVar("Sound_EnableSFX", BoolToNum(self.Settings["SFX"]["NOTMOUNTED"])) - end - if self.Settings["AMBIENCE"]["ENABLED"] then - SetCVar("Sound_EnableAmbience", BoolToNum(self.Settings["AMBIENCE"]["NOTMOUNTED"])) - end - end - else -- Player is mounting or mounted - if self.Settings["DEFAULT"] then - SetCVar("Sound_EnableSFX", 0) - SetCVar("Sound_EnableAmbience", 0) - SetCVar("Sound_EnableMusic", 1) - if tonumber(GetCVar("Sound_MusicVolume")) <= 0 then - SetCVar("Sound_MusicVolume", 1.0) - end - else - if self.Settings["MUSIC"]["ENABLED"] then - SetCVar("Sound_EnableMusic", BoolToNum(self.Settings["MUSIC"]["MOUNTED"])) - end - if self.Settings["SFX"]["ENABLED"] then - SetCVar("Sound_EnableSFX", BoolToNum(self.Settings["SFX"]["MOUNTED"])) - end - if self.Settings["AMBIENCE"]["ENABLED"] then - SetCVar("Sound_EnableAmbience", BoolToNum(self.Settings["AMBIENCE"]["MOUNTED"])) - end - end - end - if not self.Settings["DEFAULT"] then - self:VolumeCheck() - end -end +--[[ + Copyright (c) 2010-2020 by Adam Hellberg + + This file is part of Chocobo. + + Chocobo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Chocobo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Chocobo. If not, see . +--]] + +local C = Chocobo + +C.SoundControl = { + Version = 1, + Settings = {} +} + +local SC = C.SoundControl + +local L = _G["ChocoboLocale"] + +function SC:Init() + if type(C.Global["SOUNDCONTROL"]) ~= "table" then + C:Msg(L["SoundControlNotSet"]) + self:SetupVars() + end + + self.Settings = C.Global["SOUNDCONTROL"] + + if (self.Settings["VERSION"] or 0) < self.Version then + C:ErrorMsg(L["SCVarsOutOfDate"]) + self:SetupVars(true) -- Reset vars, preserving any user-made settings + end + + self:Check() +end + +function SC:SetupVars(reset) + local e, d, se, sm, sn, sv, smv, me, mm, mn, mv, mmv, ae, am, an, av, amv = + false, + true, + true, + false, + false, + 1.0, + false, + true, + true, + false, + 1.0, + true, + true, + false, + false, + 1.0, + false + if reset then + e = self.Settings["ENABLED"] or false + d = self.Settings["DEFAULT"] or true + local sfx = "SFX" + local vol = "VOLUME" + if type(self.Settings["VERSION"]) == "nil" then + sfx = "SOUND" + vol = "DEFAULT_VOLUME" + end + se = self.Settings[sfx]["ENABLED"] or true + sm = self.Settings[sfx]["MOUNTED"] or false + sn = self.Settings[sfx]["NOTMOUNTED"] or false + sv = self.Settings[sfx][vol] or 1.0 + smv = self.Settings[sfx]["MOD_VOLUME"] or false + me = self.Settings["MUSIC"]["ENABLED"] or true + mm = self.Settings["MUSIC"]["MOUNTED"] or true + mn = self.Settings["MUSIC"]["NOTMOUNTED"] or false + mv = self.Settings["MUSIC"][vol] or 1.0 + mmv = self.Settings["MUSIC"]["MOD_VOLUME"] or true + ae = self.Settings["AMBIENCE"]["ENABLED"] or true + am = self.Settings["AMBIENCE"]["MOUNTED"] or false + an = self.Settings["AMBIENCE"]["NOTMOUNTED"] or false + av = self.Settings["AMBIENCE"][vol] or 1.0 + amv = self.Settings["AMBIENCE"]["MOD_VOLUME"] or false + end + C.Global["SOUNDCONTROL"] = { + ["VERSION"] = self.Version, + ["ENABLED"] = e, -- Enable sound control at all? + ["DEFAULT"] = d, -- Use the old style sound control? + ["SFX"] = { + ["ENABLED"] = se, -- Should AddOn control SFX playback? + ["MOUNTED"] = sm, -- SFX when mounted? + ["NOTMOUNTED"] = sn, -- SFX when not mounted? + ["VOLUME"] = sv, -- Volume to modify to if volume <= 0 + ["MOD_VOLUME"] = smv -- Whether or not to modify volume + }, + ["MUSIC"] = { + ["ENABLED"] = me, -- Should AddOn control music playback? + ["MOUNTED"] = mm, -- Music when mounted? + ["NOTMOUNTED"] = mn, -- Music when not mounted? + ["VOLUME"] = mv, -- Volume to modify to if volume <= 0 + ["MOD_VOLUME"] = mmv -- Whether or not to modify volume + }, + ["AMBIENCE"] = { + ["ENABLED"] = ae, -- Should AddOn control ambience playback? + ["MOUNTED"] = am, -- Ambience when mounted? + ["NOTMOUNTED"] = an, -- Ambience when not mounted? + ["VOLUME"] = av, -- Volume to modify to if volume <= 0 + ["MOD_VOLUME"] = amv -- Whether or not to modify volume + } + } + self.Settings = C.Global["SOUNDCONTROL"] + if reset then C:Msg(L["SoundControlReset"]) end +end + +local function BoolToNum(bool) + if bool then return 1 else return 0 end +end + +function SC:Toggle(silent) + self.Settings["ENABLED"] = not self.Settings["ENABLED"] + if self.Settings["ENABLED"] then + if not silent then C:Msg(L["SCEnabled"]) end + self:Check() + else + if not silent then C:Msg(L["SCDisabled"]) end + self:Restore() + end +end + +function SC:ToggleDefault(silent) + self.Settings["DEFAULT"] = not self.Settings["DEFAULT"] + self:Check() + if silent then return end + if self.Settings["DEFAULT"] then + C:Msg(L["SCDefaultEnabled"]) + else + C:Msg(L["SCDefaultDisabled"]) + end +end + +function SC:ToggleMusic(silent) + self.Settings["MUSIC"]["ENABLED"] = not self.Settings["MUSIC"]["ENABLED"] + self:Check() + if silent then return end + if self.Settings["MUSIC"]["ENABLED"] then + C:Msg(L["SCMusicEnabled"]) + else + C:Msg(L["SCMusicDisabled"]) + end +end + +function SC:ToggleMusicMount(silent) + self.Settings["MUSIC"]["MOUNTED"] = not self.Settings["MUSIC"]["MOUNTED"] + self:Check() + if silent then return end + if self.Settings["MUSIC"]["MOUNTED"] then + C:Msg(L["SCMusicMountEnabled"]) + else + C:Msg(L["SCMusicMountDisabled"]) + end +end + +function SC:ToggleMusicNoMount(silent) + self.Settings["MUSIC"]["NOTMOUNTED"] = not self.Settings["MUSIC"]["NOTMOUNTED"] + self:Check() + if silent then return end + if self.Settings["MUSIC"]["NOTMOUNTED"] then + C:Msg(L["SCMusicNoMountEnabled"]) + else + C:Msg(L["SCMusicNoMountDisabled"]) + end +end + +function SC:ToggleMusicVolume(silent) + self.Settings["MUSIC"]["MOD_VOLUME"] = not self.Settings["MUSIC"]["MOD_VOLUME"] + self:VolumeCheck() + if silent then return end + if self.Settings["MUSIC"]["MOD_VOLUME"] then + C:Msg(L["SCMusicVolumeEnabled"]) + else + C:Msg(L["SCMusicVolumeDisabled"]) + end +end + +function SC:ToggleSFX(silent) + self.Settings["SFX"]["ENABLED"] = not self.Settings["SFX"]["ENABLED"] + self:Check() + if silent then return end + if self.Settings["SFX"]["ENABLED"] then + C:Msg(L["SCSFXEnabled"]) + else + C:Msg(L["SCSFXDisabled"]) + end +end + +function SC:ToggleSFXMount(silent) + self.Settings["SFX"]["MOUNTED"] = not self.Settings["SFX"]["MOUNTED"] + self:Check() + if silent then return end + if self.Settings["SFX"]["MOUNTED"] then + C:Msg(L["SCSFXMountEnabled"]) + else + C:Msg(L["SCSFXMountDisabled"]) + end +end + +function SC:ToggleSFXNoMount(silent) + self.Settings["SFX"]["NOTMOUNTED"] = not self.Settings["SFX"]["NOTMOUNTED"] + self:Check() + if silent then return end + if self.Settings["SFX"]["NOTMOUNTED"] then + C:Msg(L["SCSFXNoMountEnabled"]) + else + C:Msg(L["SCSFXNoMountDisabled"]) + end +end + +function SC:ToggleSFXVolume(silent) + self.Settings["SFX"]["MOD_VOLUME"] = not self.Settings["SFX"]["MOD_VOLUME"] + self:VolumeCheck() + if silent then return end + if self.Settings["SFX"]["MOD_VOLUME"] then + C:Msg(L["SCSFXVolumeEnabled"]) + else + C:Msg(L["SCSFXVolumeDisabled"]) + end +end + +function SC:ToggleAmbience(silent) + self.Settings["AMBIENCE"]["ENABLED"] = not self.Settings["AMBIENCE"]["ENABLED"] + self:Check() + if silent then return end + if self.Settings["AMBIENCE"]["ENABLED"] then + C:Msg(L["SCAmbEnabled"]) + else + C:Msg(L["SCAmbDisabled"]) + end +end + +function SC:ToggleAmbienceMount(silent) + self.Settings["AMBIENCE"]["MOUNTED"] = not self.Settings["AMBIENCE"]["MOUNTED"] + self:Check() + if silent then return end + if self.Settings["AMBIENCE"]["MOUNTED"] then + C:Msg(L["SCAmbMountEnabled"]) + else + C:Msg(L["SCAmbMountDisabled"]) + end +end + +function SC:ToggleAmbienceNoMount(silent) + self.Settings["AMBIENCE"]["NOTMOUNTED"] = not self.Settings["AMBIENCE"]["NOTMOUNTED"] + self:Check() + if silent then return end + if self.Settings["AMBIENCE"]["NOTMOUNTED"] then + C:Msg(L["SCAmbNoMountEnabled"]) + else + C:Msg(L["SCAmbNoMountDisabled"]) + end +end + +function SC:ToggleAmbienceVolume(silent) + self.Settings["AMBIENCE"]["MOD_VOLUME"] = not self.Settings["AMBIENCE"]["MOD_VOLUME"] + self:VolumeCheck() + if silent then return end + if self.Settings["AMBIENCE"]["MOD_VOLUME"] then + C:Msg(L["SCAmbVolumeEnabled"]) + else + C:Msg(L["SCAmbVolumeDisabled"]) + end +end + +function SC:ValidateVolume(volume) + if volume < 0 or volume > 100 then + C:ErrorMsg(L["SCVolumeOutOfRange"]) + return false + end + return true +end + +function SC:SetMusicVolume(volume, silent) + if self.Settings["DEFAULT"] then + if not silent then C:ErrorMsg(L["SCVolumeNotAllowed"]) end + return + end + if self:ValidateVolume(volume) then + local vol = volume / 100 + self.Settings["MUSIC"]["VOLUME"] = vol + self:VolumeCheck() + if not silent then C:Msg((L["SCNewMusicVolume"]):format(volume)) end + end +end + +function SC:SetSFXVolume(volume, silent) + if self.Settings["DEFAULT"] then + if not silent then C:ErrorMsg(L["SCVolumeNotAllowed"]) end + return + end + if self:ValidateVolume(volume) then + local vol = volume / 100 + self.Settings["SFX"]["VOLUME"] = vol + self:VolumeCheck() + if not silent then C:Msg((L["SCNewSFXVolume"]):format(volume)) end + end +end + +function SC:SetAmbienceVolume(volume, silent) + if self.Settings["DEFAULT"] then + if not silent then C:ErrorMsg(L["SCVolumeNotAllowed"]) end + return + end + if self:ValidateVolume(volume) then + local vol = volume / 100 + self.Settings["AMBIENCE"]["VOLUME"] = vol + self:VolumeCheck() + if not silent then C:Msg((L["SCNewAmbVolume"]):format(volume)) end + end +end + +function SC:PrintMusicVolume() + C:Msg((L["SCMusicVolume"]):format(self.Settings["MUSIC"]["VOLUME"] * 100)) +end + +function SC:PrintSFXVolume() + C:Msg((L["SCSFXVolume"]):format(self.Settings["SFX"]["VOLUME"] * 100)) +end + +function SC:PrintAmbienceVolume() + C:Msg((L["SCAmbienceVolume"]):format(self.Settings["AMBIENCE"]["VOLUME"] * 100)) +end + +function SC:Restore() + SetCVar("Sound_EnableAllSound", 1) + SetCVar("Sound_EnableSFX", 1) + SetCVar("Sound_EnableMusic", 1) + SetCVar("Sound_EnableAmbience", 1) +end + +function SC:VolumeCheck() + if not self.Settings["ENABLED"] then return end + if self.Settings["DEFAULT"] then return end + if self.Settings["MUSIC"]["MOD_VOLUME"] then + SetCVar("Sound_MusicVolume", self.Settings["MUSIC"]["VOLUME"]) + end + if self.Settings["SFX"]["MOD_VOLUME"] then + SetCVar("Sound_SFXVolume", self.Settings["SFX"]["VOLUME"]) + end + if self.Settings["AMBIENCE"]["MOD_VOLUME"] then + SetCVar("Sound_AmbienceVolume", self.Settings["AMBIENCE"]["VOLUME"]) + end +end + +function SC:Check() + if not self.Settings["ENABLED"] then return end + if tonumber(GetCVar("Sound_EnableAllSound")) == 0 then + SetCVar("Sound_EnableAllSound", 1) + end + -- Player is currently dismounting or dismounted + if (C.Mounted and C.Running) or (not C.Mounted and not C.Running) then + if self.Settings["DEFAULT"] then + SetCVar("Sound_EnableMusic", 0) + SetCVar("Sound_EnableSFX", 0) + SetCVar("Sound_EnableAmbience", 0) + else + if self.Settings["MUSIC"]["ENABLED"] then + SetCVar("Sound_EnableMusic", BoolToNum(self.Settings["MUSIC"]["NOTMOUNTED"])) + end + if self.Settings["SFX"]["ENABLED"] then + SetCVar("Sound_EnableSFX", BoolToNum(self.Settings["SFX"]["NOTMOUNTED"])) + end + if self.Settings["AMBIENCE"]["ENABLED"] then + SetCVar("Sound_EnableAmbience", BoolToNum(self.Settings["AMBIENCE"]["NOTMOUNTED"])) + end + end + else -- Player is mounting or mounted + if self.Settings["DEFAULT"] then + SetCVar("Sound_EnableSFX", 0) + SetCVar("Sound_EnableAmbience", 0) + SetCVar("Sound_EnableMusic", 1) + if tonumber(GetCVar("Sound_MusicVolume")) <= 0 then + SetCVar("Sound_MusicVolume", 1.0) + end + else + if self.Settings["MUSIC"]["ENABLED"] then + SetCVar("Sound_EnableMusic", BoolToNum(self.Settings["MUSIC"]["MOUNTED"])) + end + if self.Settings["SFX"]["ENABLED"] then + SetCVar("Sound_EnableSFX", BoolToNum(self.Settings["SFX"]["MOUNTED"])) + end + if self.Settings["AMBIENCE"]["ENABLED"] then + SetCVar("Sound_EnableAmbience", BoolToNum(self.Settings["AMBIENCE"]["MOUNTED"])) + end + end + end + if not self.Settings["DEFAULT"] then + self:VolumeCheck() + end +end diff --git a/ChocoboSoundControlPanel.lua b/ChocoboSoundControlPanel.lua index f11a6da..83eefe8 100644 --- a/ChocoboSoundControlPanel.lua +++ b/ChocoboSoundControlPanel.lua @@ -1,546 +1,546 @@ ---[[ - Copyright (c) 2010-2020 by Adam Hellberg - - This file is part of Chocobo. - - Chocobo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Chocobo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Chocobo. If not, see . ---]] - -local L = _G["ChocoboLocale"] - -Chocobo.SoundControl.Options = {} - -local checkButtonTemplate = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE and "OptionsBaseCheckButtonTemplate" or "OptionsCheckButtonTemplate" - -local function checkbox(name, parent) - local f = CreateFrame("CheckButton", name, parent, checkButtonTemplate) - f:SetSize(40, 40) - f.label = _G[f:GetName() .. "Text"] - - return f -end - -local function slider(name, parent) - local f = CreateFrame("Slider", name, parent, "OptionsSliderTemplate") - f.label = _G[f:GetName() .. "Text"] - f.high = _G[f:GetName() .. "High"] - f.low = _G[f:GetName() .. "Low"] - f.current = f:CreateFontString(name .. "Current", "OVERLAY") - f.current:SetFont([[Fonts\FRIZQT__.TTF]], 10, "OUTLINE") - f.current:SetPoint("TOP", 0, -16) - - return f -end - -local CSCO = Chocobo.SoundControl.Options - -local frame = CreateFrame("Frame") -CSCO.Frame = frame -frame:Hide() -frame.name = "Sound Control" -frame.parent = "Chocobo" -frame.refresh = function() CSCO:Update() end - -frame.logo = frame:CreateTexture(nil, "ARTWORK") -frame.logo:SetTexture([[Interface\AddOns\Chocobo\images\chocobo_small.tga]]) -frame.logo:SetBlendMode("BLEND") -frame.logo:SetSize(128, 128) -frame.logo:SetPoint("BOTTOMRIGHT", -220, 5) -frame.caption = CreateFrame("Frame", nil, frame) -frame.caption:SetSize(600, 25) -frame.caption:SetPoint("TOP", 0, -5) -frame.caption.label = frame.caption:CreateFontString(nil, "OVERLAY") -frame.caption.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.caption.label:SetPoint("TOPLEFT") -frame.caption.label:SetPoint("BOTTOMRIGHT") -frame.caption.label:SetTextColor(1, 0.8196079, 0) -frame.caption.label:SetText(L["SoundControl_Caption"]) -frame.description = CreateFrame("Frame", nil, frame) -frame.description:SetSize(600, 25) -frame.description:SetPoint("TOP", 0, -30) -frame.description.label = frame.description:CreateFontString(nil, "OVERLAY") -frame.description.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.description.label:SetPoint("TOPLEFT") -frame.description.label:SetPoint("BOTTOMRIGHT") -frame.description.label:SetTextColor(1, 1, 1) -frame.description.label:SetText(L["SoundControl_Description"]) - -frame.toggle = checkbox("ChocoboSoundControlOptionsToggle", frame) -frame.toggle:SetPoint("TOPLEFT", 10, -85) -frame.toggle.label:SetText(L["SoundControl_Toggle"]) -frame.toggle.label:SetTextColor(1, 1, 1) -frame.toggle:SetScript("OnClick", function() - Chocobo.SoundControl:Toggle(true) - CSCO:Update() -end) -frame.toggleDefault = checkbox("ChocoboSoundControlOptionsToggleDefault", frame) -frame.toggleDefault:SetPoint("TOPLEFT", 10, -125) -frame.toggleDefault.label:SetText(L["SoundControl_ToggleDefault"]) -frame.toggleDefault:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleDefault(true) - CSCO:Update() -end) - -frame.defaultHelp = CreateFrame("Frame", nil, frame) -frame.defaultHelp:SetSize(400, 50) -frame.defaultHelp:SetPoint("TOPRIGHT", -10, -90) -frame.defaultHelp.label = frame.defaultHelp:CreateFontString(nil, "OVERLAY") -frame.defaultHelp.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.defaultHelp.label:SetPoint("TOPLEFT") -frame.defaultHelp.label:SetPoint("BOTTOMRIGHT") -frame.defaultHelp.label:SetTextColor(1, 1, 1) -frame.defaultHelp.label:SetText(L["SoundControl_DefaultHelp"]) - -frame.defaultNote = CreateFrame("Frame", nil, frame) -frame.defaultNote:SetSize(400, 40) -frame.defaultNote:SetPoint("TOPRIGHT", -10, -130) -frame.defaultNote.label = frame.defaultNote:CreateFontString(nil, "OVERLAY") -frame.defaultNote.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.defaultNote.label:SetPoint("TOPLEFT") -frame.defaultNote.label:SetPoint("BOTTOMRIGHT") -frame.defaultNote.label:SetText(L["SoundControl_DefaultNote"]) - -local panelTabButtonTemplate = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE and "PanelTabButtonTemplate" or "CharacterFrameTabButtonTemplate" -local bd = { - bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", - edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", - tile = true, - edgeSize = 16, - tileSize = 32, - insets = { - left = 2.5, - right = 2.5, - top = 2.5, - bottom = 2.5 - } -} -frame.panelContainer = CreateFrame( - "Frame", - "ChocoboSoundControlOptionsPanelContainer", - frame, - BackdropTemplateMixin and "BackdropTemplate") -frame.panelContainer:SetSize(500, 240) -frame.panelContainer:SetPoint("TOP", 0, -200) -frame.panelContainer:SetBackdrop(bd) -frame.panelContainer.tab1 = CreateFrame( - "Button", - "ChocoboSoundControlOptionsPanelContainerTab1", - frame.panelContainer, - panelTabButtonTemplate) -frame.panelContainer.tab1:SetPoint("LEFT", frame.panelContainer, "BOTTOMLEFT", 5, -12) -frame.panelContainer.tab1:SetText(L["SoundControl_Music"]) -frame.panelContainer.tab1:SetScript("OnClick", function() - PanelTemplates_SetTab(frame.panelContainer, 1) - frame.panelContainer.page1:Show() - frame.panelContainer.page2:Hide() - frame.panelContainer.page3:Hide() -end) -frame.panelContainer.tab2 = CreateFrame( - "Button", - "ChocoboSoundControlOptionsPanelContainerTab2", - frame.panelContainer, - panelTabButtonTemplate) -frame.panelContainer.tab2:SetPoint("LEFT", frame.panelContainer.tab1, "RIGHT", -10, 0) -frame.panelContainer.tab2:SetText(L["SoundControl_SFX"]) -frame.panelContainer.tab2:SetScript("OnClick", function() - PanelTemplates_SetTab(frame.panelContainer, 2) - frame.panelContainer.page1:Hide() - frame.panelContainer.page2:Show() - frame.panelContainer.page3:Hide() -end) -frame.panelContainer.tab3 = CreateFrame( - "Button", - "ChocoboSoundControlOptionsPanelContainerTab3", - frame.panelContainer, - panelTabButtonTemplate) -frame.panelContainer.tab3:SetPoint("LEFT", frame.panelContainer.tab2, "RIGHT", -10, 0) -frame.panelContainer.tab3:SetText(L["SoundControl_Ambience"]) -frame.panelContainer.tab3:SetScript("OnClick", function() - PanelTemplates_SetTab(frame.panelContainer, 3) - frame.panelContainer.page1:Hide() - frame.panelContainer.page2:Hide() - frame.panelContainer.page3:Show() -end) - -frame.panelContainer.page1 = CreateFrame("Frame", "ChocoboSoundControlOptionsPanelContainerPage1", frame.panelContainer) -frame.panelContainer.page1:SetPoint("TOPLEFT") -frame.panelContainer.page1:SetPoint("BOTTOMRIGHT") -frame.panelContainer.page1:Show() -frame.panelContainer.page1.panel = CreateFrame("Frame", nil, frame.panelContainer.page1) -frame.panelContainer.page1.panel:SetSize(360, 20) -frame.panelContainer.page1.panel:SetPoint("TOP", 0, -10) -frame.panelContainer.page1.panel.desc = frame.panelContainer.page1.panel:CreateFontString(nil, "OVERLAY") -frame.panelContainer.page1.panel.desc:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.panelContainer.page1.panel.desc:SetPoint("TOPLEFT") -frame.panelContainer.page1.panel.desc:SetPoint("BOTTOMRIGHT") -frame.panelContainer.page1.panel.desc:SetText(L["SoundControl_MusicDesc"]) -frame.panelContainer.page1.enable = checkbox("ChocoboSoundControlOptionsPage1Enable", frame.panelContainer.page1) -frame.panelContainer.page1.enable:SetPoint("TOPLEFT", 10, -25) -frame.panelContainer.page1.enable.label:SetText(L["SoundControl_MusicEnable"]) -frame.panelContainer.page1.enable:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleMusic(true) - CSCO:Update() -end) -frame.panelContainer.page1.enableMount = checkbox( - "ChocoboSoundControlOptionsPage1EnableMount", - frame.panelContainer.page1) -frame.panelContainer.page1.enableMount:SetPoint("TOPLEFT", 10, -65) -frame.panelContainer.page1.enableMount.label:SetText(L["SoundControl_MusicMount"]) -frame.panelContainer.page1.enableMount:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleMusicMount(true) - CSCO:Update() -end) -frame.panelContainer.page1.enableNoMount = checkbox( - "ChocoboSoundControlOptionsPage1EnableNoMount", - frame.panelContainer.page1) -frame.panelContainer.page1.enableNoMount:SetPoint("TOPLEFT", 10, -105) -frame.panelContainer.page1.enableNoMount.label:SetText(L["SoundControl_MusicNoMount"]) -frame.panelContainer.page1.enableNoMount:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleMusicNoMount(true) - CSCO:Update() -end) -frame.panelContainer.page1.enableVolume = checkbox( - "ChocoboSoundControlOptionsPage1EnableVolume", - frame.panelContainer.page1) -frame.panelContainer.page1.enableVolume:SetPoint("TOPLEFT", 10, -145) -frame.panelContainer.page1.enableVolume.label:SetText(L["SoundControl_MusicVolume"]) -frame.panelContainer.page1.enableVolume:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleMusicVolume(true) - CSCO:Update() -end) -frame.panelContainer.page1.volumeSlider = slider( - "ChocoboSoundControlOptionsPage1VolumeSlider", - frame.panelContainer.page1) -frame.panelContainer.page1.volumeSlider:SetSize(450, 16) -frame.panelContainer.page1.volumeSlider:SetPoint("TOP", 0, -195) -frame.panelContainer.page1.volumeSlider:SetMinMaxValues(0, 100) -frame.panelContainer.page1.volumeSlider:SetValueStep(1) -frame.panelContainer.page1.volumeSlider.label:SetText(L["SoundControl_MusicSetVolume"]) -frame.panelContainer.page1.volumeSlider.high:SetText("100") -frame.panelContainer.page1.volumeSlider.low:SetText("0") -frame.panelContainer.page1.volumeSlider:SetScript("OnValueChanged", function(self) - Chocobo.SoundControl:SetMusicVolume(self:GetValue(), true) - CSCO:Update() -end) -frame.panelContainer.page1.volumeSlider:SetScript("OnMouseWheel", function(self, delta) - CSCO:VolumeScroll(self, delta, 1) -end) - -frame.panelContainer.page2 = CreateFrame("Frame", "ChocoboSoundControlOptionsPanelContainerPage2", frame.panelContainer) -frame.panelContainer.page2:SetPoint("TOPLEFT") -frame.panelContainer.page2:SetPoint("BOTTOMRIGHT") -frame.panelContainer.page2:Hide() -frame.panelContainer.page2.panel = CreateFrame("Frame", nil, frame.panelContainer.page2) -frame.panelContainer.page2.panel:SetSize(360, 20) -frame.panelContainer.page2.panel:SetPoint("TOP", 0, -10) -frame.panelContainer.page2.panel.desc = frame.panelContainer.page2.panel:CreateFontString(nil, "OVERLAY") -frame.panelContainer.page2.panel.desc:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.panelContainer.page2.panel.desc:SetPoint("TOPLEFT") -frame.panelContainer.page2.panel.desc:SetPoint("BOTTOMRIGHT") -frame.panelContainer.page2.panel.desc:SetText(L["SoundControl_SFXDesc"]) -frame.panelContainer.page2.enable = checkbox("ChocoboSoundControlOptionsPage2Enable", frame.panelContainer.page2) -frame.panelContainer.page2.enable:SetPoint("TOPLEFT", 10, -25) -frame.panelContainer.page2.enable.label:SetText(L["SoundControl_SFXEnable"]) -frame.panelContainer.page2.enable:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleSFX(true) - CSCO:Update() -end) -frame.panelContainer.page2.enableMount = checkbox( - "ChocoboSoundControlOptionsPage2EnableMount", - frame.panelContainer.page2) -frame.panelContainer.page2.enableMount:SetPoint("TOPLEFT", 10, -65) -frame.panelContainer.page2.enableMount.label:SetText(L["SoundControl_SFXMount"]) -frame.panelContainer.page2.enableMount:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleSFXMount(true) - CSCO:Update() -end) -frame.panelContainer.page2.enableNoMount = checkbox( - "ChocoboSoundControlOptionsPage2EnableNoMount", - frame.panelContainer.page2) -frame.panelContainer.page2.enableNoMount:SetPoint("TOPLEFT", 10, -105) -frame.panelContainer.page2.enableNoMount.label:SetText(L["SoundControl_SFXNoMount"]) -frame.panelContainer.page2.enableNoMount:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleSFXNoMount(true) - CSCO:Update() -end) -frame.panelContainer.page2.enableVolume = checkbox( - "ChocoboSoundControlOptionsPage2EnableVolume", - frame.panelContainer.page2) -frame.panelContainer.page2.enableVolume:SetPoint("TOPLEFT", 10, -145) -frame.panelContainer.page2.enableVolume.label:SetText(L["SoundControl_SFXVolume"]) -frame.panelContainer.page2.enableVolume:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleSFXVolume(true) - CSCO:Update() -end) -frame.panelContainer.page2.volumeSlider = slider( - "ChocoboSoundControlOptionsPage2VolumeSlider", - frame.panelContainer.page2) -frame.panelContainer.page2.volumeSlider:SetSize(450, 16) -frame.panelContainer.page2.volumeSlider:SetPoint("TOP", 0, -195) -frame.panelContainer.page2.volumeSlider:SetMinMaxValues(0, 100) -frame.panelContainer.page2.volumeSlider:SetValueStep(1) -frame.panelContainer.page2.volumeSlider.label:SetText(L["SoundControl_SFXSetVolume"]) -frame.panelContainer.page2.volumeSlider.high:SetText("100") -frame.panelContainer.page2.volumeSlider.low:SetText("0") -frame.panelContainer.page2.volumeSlider:SetScript("OnValueChanged", function(self) - Chocobo.SoundControl:SetSFXVolume(self:GetValue(), true) - CSCO:Update() -end) -frame.panelContainer.page2.volumeSlider:SetScript("OnMouseWheel", function(self, delta) - CSCO:VolumeScroll(self, delta, 1) -end) - -frame.panelContainer.page3 = CreateFrame("Frame", "ChocoboSoundControlOptionsPanelContainerPage3", frame.panelContainer) -frame.panelContainer.page3:SetPoint("TOPLEFT") -frame.panelContainer.page3:SetPoint("BOTTOMRIGHT") -frame.panelContainer.page3:Hide() -frame.panelContainer.page3.panel = CreateFrame("Frame", nil, frame.panelContainer.page3) -frame.panelContainer.page3.panel:SetSize(360, 20) -frame.panelContainer.page3.panel:SetPoint("TOP", 0, -10) -frame.panelContainer.page3.panel.desc = frame.panelContainer.page3.panel:CreateFontString(nil, "OVERLAY") -frame.panelContainer.page3.panel.desc:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") -frame.panelContainer.page3.panel.desc:SetPoint("TOPLEFT") -frame.panelContainer.page3.panel.desc:SetPoint("BOTTOMRIGHT") -frame.panelContainer.page3.panel.desc:SetText(L["SoundControl_AmbienceDesc"]) -frame.panelContainer.page3.enable = checkbox("ChocoboSoundControlOptionsPage3Enable", frame.panelContainer.page3) -frame.panelContainer.page3.enable:SetPoint("TOPLEFT", 10, -25) -frame.panelContainer.page3.enable.label:SetText(L["SoundControl_AmbienceEnable"]) -frame.panelContainer.page3.enable:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleAmbience(true) - CSCO:Update() -end) -frame.panelContainer.page3.enableMount = checkbox( - "ChocoboSoundControlOptionsPage3EnableMount", - frame.panelContainer.page3) -frame.panelContainer.page3.enableMount:SetPoint("TOPLEFT", 10, -65) -frame.panelContainer.page3.enableMount.label:SetText(L["SoundControl_AmbienceMount"]) -frame.panelContainer.page3.enableMount:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleAmbienceMount(true) - CSCO:Update() -end) -frame.panelContainer.page3.enableNoMount = checkbox( - "ChocoboSoundControlOptionsPage3EnableNoMount", - frame.panelContainer.page3) -frame.panelContainer.page3.enableNoMount:SetPoint("TOPLEFT", 10, -105) -frame.panelContainer.page3.enableNoMount.label:SetText(L["SoundControl_AmbienceNoMount"]) -frame.panelContainer.page3.enableNoMount:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleAmbienceNoMount(true) - CSCO:Update() -end) -frame.panelContainer.page3.enableVolume = checkbox( - "ChocoboSoundControlOptionsPage3EnableVolume", - frame.panelContainer.page3) -frame.panelContainer.page3.enableVolume:SetPoint("TOPLEFT", 10, -145) -frame.panelContainer.page3.enableVolume.label:SetText(L["SoundControl_AmbienceVolume"]) -frame.panelContainer.page3.enableVolume:SetScript("OnClick", function() - Chocobo.SoundControl:ToggleAmbienceVolume(true) - CSCO:Update() -end) -frame.panelContainer.page3.volumeSlider = slider( - "ChocoboSoundControlOptionsPage3VolumeSlider", - frame.panelContainer.page3) -frame.panelContainer.page3.volumeSlider:SetSize(450, 16) -frame.panelContainer.page3.volumeSlider:SetPoint("TOP", 0, -195) -frame.panelContainer.page3.volumeSlider:SetMinMaxValues(0, 100) -frame.panelContainer.page3.volumeSlider:SetValueStep(1) -frame.panelContainer.page3.volumeSlider.label:SetText(L["SoundControl_AmbienceSetVolume"]) -frame.panelContainer.page3.volumeSlider.high:SetText("100") -frame.panelContainer.page3.volumeSlider.low:SetText("0") -frame.panelContainer.page3.volumeSlider:SetScript("OnValueChanged", function(self) - Chocobo.SoundControl:SetAmbienceVolume(self:GetValue(), true) - CSCO:Update() -end) -frame.panelContainer.page3.volumeSlider:SetScript("OnMouseWheel", function(self, delta) - CSCO:VolumeScroll(self, delta, 1) -end) - -function CSCO:Open() - if Settings and SettingsPanel then - Settings.OpenToCategory(Chocobo.Name) - else - InterfaceOptionsFrame_OpenToCategory(frame) - InterfaceOptionsFrame_OpenToCategory(frame) - end -end - -function CSCO:Update() - local settings = Chocobo.SoundControl.Settings - frame.toggle:SetChecked(settings["ENABLED"]) - frame.toggleDefault:SetChecked(settings["DEFAULT"]) - frame.panelContainer.page1.enable:SetChecked(settings["MUSIC"]["ENABLED"]) - frame.panelContainer.page1.enableMount:SetChecked(settings["MUSIC"]["MOUNTED"]) - frame.panelContainer.page1.enableNoMount:SetChecked(settings["MUSIC"]["NOTMOUNTED"]) - frame.panelContainer.page1.enableVolume:SetChecked(settings["MUSIC"]["MOD_VOLUME"]) - frame.panelContainer.page1.volumeSlider:SetValue(settings["MUSIC"]["VOLUME"] * 100) - frame.panelContainer.page1.volumeSlider.current:SetText(tostring(settings["MUSIC"]["VOLUME"] * 100)) - frame.panelContainer.page2.enable:SetChecked(settings["SFX"]["ENABLED"]) - frame.panelContainer.page2.enableMount:SetChecked(settings["SFX"]["MOUNTED"]) - frame.panelContainer.page2.enableNoMount:SetChecked(settings["SFX"]["NOTMOUNTED"]) - frame.panelContainer.page2.enableVolume:SetChecked(settings["SFX"]["MOD_VOLUME"]) - frame.panelContainer.page2.volumeSlider:SetValue(settings["SFX"]["VOLUME"] * 100) - frame.panelContainer.page2.volumeSlider.current:SetText(tostring(settings["SFX"]["VOLUME"] * 100)) - frame.panelContainer.page3.enable:SetChecked(settings["AMBIENCE"]["ENABLED"]) - frame.panelContainer.page3.enableMount:SetChecked(settings["AMBIENCE"]["MOUNTED"]) - frame.panelContainer.page3.enableNoMount:SetChecked(settings["AMBIENCE"]["NOTMOUNTED"]) - frame.panelContainer.page3.enableVolume:SetChecked(settings["AMBIENCE"]["MOD_VOLUME"]) - frame.panelContainer.page3.volumeSlider:SetValue(settings["AMBIENCE"]["VOLUME"] * 100) - frame.panelContainer.page3.volumeSlider.current:SetText(tostring(settings["AMBIENCE"]["VOLUME"] * 100)) - - local enabled = settings["ENABLED"] - local default = settings["DEFAULT"] - - if settings["MUSIC"]["MOD_VOLUME"] and enabled and not default then - frame.panelContainer.page1.volumeSlider:Enable() - frame.panelContainer.page1.volumeSlider.label:SetTextColor(1, 1, 1) - frame.panelContainer.page1.volumeSlider.high:SetTextColor(1, 1, 1) - frame.panelContainer.page1.volumeSlider.low:SetTextColor(1, 1, 1) - frame.panelContainer.page1.volumeSlider.current:SetTextColor(1, 1, 1) - else - frame.panelContainer.page1.volumeSlider:Disable() - frame.panelContainer.page1.volumeSlider.label:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page1.volumeSlider.high:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page1.volumeSlider.low:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page1.volumeSlider.current:SetTextColor(0.5, 0.5, 0.5) - end - - if settings["SFX"]["MOD_VOLUME"] and enabled and not default then - frame.panelContainer.page2.volumeSlider:Enable() - frame.panelContainer.page2.volumeSlider.label:SetTextColor(1, 1, 1) - frame.panelContainer.page2.volumeSlider.high:SetTextColor(1, 1, 1) - frame.panelContainer.page2.volumeSlider.low:SetTextColor(1, 1, 1) - frame.panelContainer.page2.volumeSlider.current:SetTextColor(1, 1, 1) - else - frame.panelContainer.page2.volumeSlider:Disable() - frame.panelContainer.page2.volumeSlider.label:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page2.volumeSlider.high:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page2.volumeSlider.low:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page2.volumeSlider.current:SetTextColor(0.5, 0.5, 0.5) - end - - if settings["AMBIENCE"]["MOD_VOLUME"] and enabled and not default then - frame.panelContainer.page3.volumeSlider:Enable() - frame.panelContainer.page3.volumeSlider.label:SetTextColor(1, 1, 1) - frame.panelContainer.page3.volumeSlider.high:SetTextColor(1, 1, 1) - frame.panelContainer.page3.volumeSlider.low:SetTextColor(1, 1, 1) - frame.panelContainer.page3.volumeSlider.current:SetTextColor(1, 1, 1) - else - frame.panelContainer.page3.volumeSlider:Disable() - frame.panelContainer.page3.volumeSlider.label:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page3.volumeSlider.high:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page3.volumeSlider.low:SetTextColor(0.5, 0.5, 0.5) - frame.panelContainer.page3.volumeSlider.current:SetTextColor(0.5, 0.5, 0.5) - end - - if not enabled or default then - self:CheckboxesEnabled(false) - else - self:CheckboxesEnabled(true) - end - - if enabled then - frame.toggleDefault:Enable() - frame.toggleDefault.label:SetTextColor(1, 1, 1) - else - frame.toggleDefault:Disable() - frame.toggleDefault.label:SetTextColor(0.5, 0.5, 0.5) - end -end - -function CSCO:CheckboxesEnabled(enabled) - local function setEnabled(f, e) - if e then - f:Enable() - else - f:Disable() - end - end - local dr, dg, db = 0.5, 0.5, 0.5 - local r, g, b = 0.5, 0.5, 0.5 - if enabled then - dr, dg, db = 1, 0.82, 0 - r, g, b = 1, 1, 1 - end - if enabled then - setEnabled(frame.panelContainer.tab1, true) - setEnabled(frame.panelContainer.tab2, true) - setEnabled(frame.panelContainer.tab3, true) - end - self:SetToCurrentTab() - frame.panelContainer.page1.panel.desc:SetTextColor(dr, dg, db) - frame.panelContainer.page2.panel.desc:SetTextColor(dr, dg, db) - frame.panelContainer.page3.panel.desc:SetTextColor(dr, dg, db) - setEnabled(frame.panelContainer.page1.enable, enabled) - setEnabled(frame.panelContainer.page1.enableMount, enabled) - setEnabled(frame.panelContainer.page1.enableNoMount, enabled) - setEnabled(frame.panelContainer.page1.enableVolume, enabled) - setEnabled(frame.panelContainer.page2.enable, enabled) - setEnabled(frame.panelContainer.page2.enableMount, enabled) - setEnabled(frame.panelContainer.page2.enableNoMount, enabled) - setEnabled(frame.panelContainer.page2.enableVolume, enabled) - setEnabled(frame.panelContainer.page3.enable, enabled) - setEnabled(frame.panelContainer.page3.enableMount, enabled) - setEnabled(frame.panelContainer.page3.enableNoMount, enabled) - setEnabled(frame.panelContainer.page3.enableVolume, enabled) - if not enabled then - setEnabled(frame.panelContainer.tab1, false) - setEnabled(frame.panelContainer.tab2, false) - setEnabled(frame.panelContainer.tab3, false) - end - frame.panelContainer.page1.enable.label:SetTextColor(r, g, b) - frame.panelContainer.page1.enableMount.label:SetTextColor(r, g, b) - frame.panelContainer.page1.enableNoMount.label:SetTextColor(r, g, b) - frame.panelContainer.page1.enableVolume.label:SetTextColor(r, g, b) - frame.panelContainer.page2.enable.label:SetTextColor(r, g, b) - frame.panelContainer.page2.enableMount.label:SetTextColor(r, g, b) - frame.panelContainer.page2.enableNoMount.label:SetTextColor(r, g, b) - frame.panelContainer.page2.enableVolume.label:SetTextColor(r, g, b) - frame.panelContainer.page3.enable.label:SetTextColor(r, g, b) - frame.panelContainer.page3.enableMount.label:SetTextColor(r, g, b) - frame.panelContainer.page3.enableNoMount.label:SetTextColor(r, g, b) - frame.panelContainer.page3.enableVolume.label:SetTextColor(r, g, b) -end - -function CSCO:SetToCurrentTab() - PanelTemplates_SetTab(frame.panelContainer, PanelTemplates_GetSelectedTab(frame.panelContainer)) -end - -function CSCO:VolumeScroll(s, delta, num) - local new = s:GetValue() + delta - if new < 0 or new > 100 then return end - if num == 1 then - Chocobo.SoundControl:SetMusicVolume(new, true) - elseif num == 2 then - Chocobo.SoundControl:SetSFXVolume(new, true) - elseif num == 3 then - Chocobo.SoundControl:SetAmbienceVolume(new, true) - end - self:Update() -end - -frame:SetScript("OnShow", function() CSCO:Update() end) - -frame.OnCommit = function() end -frame.OnDefault = function() end -frame.OnRefresh = function() CSCO:Update() end - -PanelTemplates_SetNumTabs(frame.panelContainer, 3) -PanelTemplates_SetTab(frame.panelContainer, 1) - -if Settings and SettingsPanel then - local category = Settings.GetCategory(Chocobo.Name) - local subcategory = Settings.RegisterCanvasLayoutSubcategory(category, frame, "Sound Control") - Settings.RegisterAddOnCategory(subcategory) -else - InterfaceOptions_AddCategory(frame, Chocobo.Name) -end +--[[ + Copyright (c) 2010-2020 by Adam Hellberg + + This file is part of Chocobo. + + Chocobo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Chocobo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Chocobo. If not, see . +--]] + +local L = _G["ChocoboLocale"] + +Chocobo.SoundControl.Options = {} + +local checkButtonTemplate = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE and "OptionsBaseCheckButtonTemplate" or "OptionsCheckButtonTemplate" + +local function checkbox(name, parent) + local f = CreateFrame("CheckButton", name, parent, checkButtonTemplate) + f:SetSize(40, 40) + f.label = _G[f:GetName() .. "Text"] + + return f +end + +local function slider(name, parent) + local f = CreateFrame("Slider", name, parent, "OptionsSliderTemplate") + f.label = _G[f:GetName() .. "Text"] + f.high = _G[f:GetName() .. "High"] + f.low = _G[f:GetName() .. "Low"] + f.current = f:CreateFontString(name .. "Current", "OVERLAY") + f.current:SetFont([[Fonts\FRIZQT__.TTF]], 10, "OUTLINE") + f.current:SetPoint("TOP", 0, -16) + + return f +end + +local CSCO = Chocobo.SoundControl.Options + +local frame = CreateFrame("Frame") +CSCO.Frame = frame +frame:Hide() +frame.name = "Sound Control" +frame.parent = "Chocobo" +frame.refresh = function() CSCO:Update() end + +frame.logo = frame:CreateTexture(nil, "ARTWORK") +frame.logo:SetTexture([[Interface\AddOns\Chocobo\images\chocobo_small.tga]]) +frame.logo:SetBlendMode("BLEND") +frame.logo:SetSize(128, 128) +frame.logo:SetPoint("BOTTOMRIGHT", -220, 5) +frame.caption = CreateFrame("Frame", nil, frame) +frame.caption:SetSize(600, 25) +frame.caption:SetPoint("TOP", 0, -5) +frame.caption.label = frame.caption:CreateFontString(nil, "OVERLAY") +frame.caption.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.caption.label:SetPoint("TOPLEFT") +frame.caption.label:SetPoint("BOTTOMRIGHT") +frame.caption.label:SetTextColor(1, 0.8196079, 0) +frame.caption.label:SetText(L["SoundControl_Caption"]) +frame.description = CreateFrame("Frame", nil, frame) +frame.description:SetSize(600, 25) +frame.description:SetPoint("TOP", 0, -30) +frame.description.label = frame.description:CreateFontString(nil, "OVERLAY") +frame.description.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.description.label:SetPoint("TOPLEFT") +frame.description.label:SetPoint("BOTTOMRIGHT") +frame.description.label:SetTextColor(1, 1, 1) +frame.description.label:SetText(L["SoundControl_Description"]) + +frame.toggle = checkbox("ChocoboSoundControlOptionsToggle", frame) +frame.toggle:SetPoint("TOPLEFT", 10, -85) +frame.toggle.label:SetText(L["SoundControl_Toggle"]) +frame.toggle.label:SetTextColor(1, 1, 1) +frame.toggle:SetScript("OnClick", function() + Chocobo.SoundControl:Toggle(true) + CSCO:Update() +end) +frame.toggleDefault = checkbox("ChocoboSoundControlOptionsToggleDefault", frame) +frame.toggleDefault:SetPoint("TOPLEFT", 10, -125) +frame.toggleDefault.label:SetText(L["SoundControl_ToggleDefault"]) +frame.toggleDefault:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleDefault(true) + CSCO:Update() +end) + +frame.defaultHelp = CreateFrame("Frame", nil, frame) +frame.defaultHelp:SetSize(400, 50) +frame.defaultHelp:SetPoint("TOPRIGHT", -10, -90) +frame.defaultHelp.label = frame.defaultHelp:CreateFontString(nil, "OVERLAY") +frame.defaultHelp.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.defaultHelp.label:SetPoint("TOPLEFT") +frame.defaultHelp.label:SetPoint("BOTTOMRIGHT") +frame.defaultHelp.label:SetTextColor(1, 1, 1) +frame.defaultHelp.label:SetText(L["SoundControl_DefaultHelp"]) + +frame.defaultNote = CreateFrame("Frame", nil, frame) +frame.defaultNote:SetSize(400, 40) +frame.defaultNote:SetPoint("TOPRIGHT", -10, -130) +frame.defaultNote.label = frame.defaultNote:CreateFontString(nil, "OVERLAY") +frame.defaultNote.label:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.defaultNote.label:SetPoint("TOPLEFT") +frame.defaultNote.label:SetPoint("BOTTOMRIGHT") +frame.defaultNote.label:SetText(L["SoundControl_DefaultNote"]) + +local panelTabButtonTemplate = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE and "PanelTabButtonTemplate" or "CharacterFrameTabButtonTemplate" +local bd = { + bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", + edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", + tile = true, + edgeSize = 16, + tileSize = 32, + insets = { + left = 2.5, + right = 2.5, + top = 2.5, + bottom = 2.5 + } +} +frame.panelContainer = CreateFrame( + "Frame", + "ChocoboSoundControlOptionsPanelContainer", + frame, + BackdropTemplateMixin and "BackdropTemplate") +frame.panelContainer:SetSize(500, 240) +frame.panelContainer:SetPoint("TOP", 0, -200) +frame.panelContainer:SetBackdrop(bd) +frame.panelContainer.tab1 = CreateFrame( + "Button", + "ChocoboSoundControlOptionsPanelContainerTab1", + frame.panelContainer, + panelTabButtonTemplate) +frame.panelContainer.tab1:SetPoint("LEFT", frame.panelContainer, "BOTTOMLEFT", 5, -12) +frame.panelContainer.tab1:SetText(L["SoundControl_Music"]) +frame.panelContainer.tab1:SetScript("OnClick", function() + PanelTemplates_SetTab(frame.panelContainer, 1) + frame.panelContainer.page1:Show() + frame.panelContainer.page2:Hide() + frame.panelContainer.page3:Hide() +end) +frame.panelContainer.tab2 = CreateFrame( + "Button", + "ChocoboSoundControlOptionsPanelContainerTab2", + frame.panelContainer, + panelTabButtonTemplate) +frame.panelContainer.tab2:SetPoint("LEFT", frame.panelContainer.tab1, "RIGHT", -10, 0) +frame.panelContainer.tab2:SetText(L["SoundControl_SFX"]) +frame.panelContainer.tab2:SetScript("OnClick", function() + PanelTemplates_SetTab(frame.panelContainer, 2) + frame.panelContainer.page1:Hide() + frame.panelContainer.page2:Show() + frame.panelContainer.page3:Hide() +end) +frame.panelContainer.tab3 = CreateFrame( + "Button", + "ChocoboSoundControlOptionsPanelContainerTab3", + frame.panelContainer, + panelTabButtonTemplate) +frame.panelContainer.tab3:SetPoint("LEFT", frame.panelContainer.tab2, "RIGHT", -10, 0) +frame.panelContainer.tab3:SetText(L["SoundControl_Ambience"]) +frame.panelContainer.tab3:SetScript("OnClick", function() + PanelTemplates_SetTab(frame.panelContainer, 3) + frame.panelContainer.page1:Hide() + frame.panelContainer.page2:Hide() + frame.panelContainer.page3:Show() +end) + +frame.panelContainer.page1 = CreateFrame("Frame", "ChocoboSoundControlOptionsPanelContainerPage1", frame.panelContainer) +frame.panelContainer.page1:SetPoint("TOPLEFT") +frame.panelContainer.page1:SetPoint("BOTTOMRIGHT") +frame.panelContainer.page1:Show() +frame.panelContainer.page1.panel = CreateFrame("Frame", nil, frame.panelContainer.page1) +frame.panelContainer.page1.panel:SetSize(360, 20) +frame.panelContainer.page1.panel:SetPoint("TOP", 0, -10) +frame.panelContainer.page1.panel.desc = frame.panelContainer.page1.panel:CreateFontString(nil, "OVERLAY") +frame.panelContainer.page1.panel.desc:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.panelContainer.page1.panel.desc:SetPoint("TOPLEFT") +frame.panelContainer.page1.panel.desc:SetPoint("BOTTOMRIGHT") +frame.panelContainer.page1.panel.desc:SetText(L["SoundControl_MusicDesc"]) +frame.panelContainer.page1.enable = checkbox("ChocoboSoundControlOptionsPage1Enable", frame.panelContainer.page1) +frame.panelContainer.page1.enable:SetPoint("TOPLEFT", 10, -25) +frame.panelContainer.page1.enable.label:SetText(L["SoundControl_MusicEnable"]) +frame.panelContainer.page1.enable:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleMusic(true) + CSCO:Update() +end) +frame.panelContainer.page1.enableMount = checkbox( + "ChocoboSoundControlOptionsPage1EnableMount", + frame.panelContainer.page1) +frame.panelContainer.page1.enableMount:SetPoint("TOPLEFT", 10, -65) +frame.panelContainer.page1.enableMount.label:SetText(L["SoundControl_MusicMount"]) +frame.panelContainer.page1.enableMount:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleMusicMount(true) + CSCO:Update() +end) +frame.panelContainer.page1.enableNoMount = checkbox( + "ChocoboSoundControlOptionsPage1EnableNoMount", + frame.panelContainer.page1) +frame.panelContainer.page1.enableNoMount:SetPoint("TOPLEFT", 10, -105) +frame.panelContainer.page1.enableNoMount.label:SetText(L["SoundControl_MusicNoMount"]) +frame.panelContainer.page1.enableNoMount:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleMusicNoMount(true) + CSCO:Update() +end) +frame.panelContainer.page1.enableVolume = checkbox( + "ChocoboSoundControlOptionsPage1EnableVolume", + frame.panelContainer.page1) +frame.panelContainer.page1.enableVolume:SetPoint("TOPLEFT", 10, -145) +frame.panelContainer.page1.enableVolume.label:SetText(L["SoundControl_MusicVolume"]) +frame.panelContainer.page1.enableVolume:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleMusicVolume(true) + CSCO:Update() +end) +frame.panelContainer.page1.volumeSlider = slider( + "ChocoboSoundControlOptionsPage1VolumeSlider", + frame.panelContainer.page1) +frame.panelContainer.page1.volumeSlider:SetSize(450, 16) +frame.panelContainer.page1.volumeSlider:SetPoint("TOP", 0, -195) +frame.panelContainer.page1.volumeSlider:SetMinMaxValues(0, 100) +frame.panelContainer.page1.volumeSlider:SetValueStep(1) +frame.panelContainer.page1.volumeSlider.label:SetText(L["SoundControl_MusicSetVolume"]) +frame.panelContainer.page1.volumeSlider.high:SetText("100") +frame.panelContainer.page1.volumeSlider.low:SetText("0") +frame.panelContainer.page1.volumeSlider:SetScript("OnValueChanged", function(self) + Chocobo.SoundControl:SetMusicVolume(self:GetValue(), true) + CSCO:Update() +end) +frame.panelContainer.page1.volumeSlider:SetScript("OnMouseWheel", function(self, delta) + CSCO:VolumeScroll(self, delta, 1) +end) + +frame.panelContainer.page2 = CreateFrame("Frame", "ChocoboSoundControlOptionsPanelContainerPage2", frame.panelContainer) +frame.panelContainer.page2:SetPoint("TOPLEFT") +frame.panelContainer.page2:SetPoint("BOTTOMRIGHT") +frame.panelContainer.page2:Hide() +frame.panelContainer.page2.panel = CreateFrame("Frame", nil, frame.panelContainer.page2) +frame.panelContainer.page2.panel:SetSize(360, 20) +frame.panelContainer.page2.panel:SetPoint("TOP", 0, -10) +frame.panelContainer.page2.panel.desc = frame.panelContainer.page2.panel:CreateFontString(nil, "OVERLAY") +frame.panelContainer.page2.panel.desc:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.panelContainer.page2.panel.desc:SetPoint("TOPLEFT") +frame.panelContainer.page2.panel.desc:SetPoint("BOTTOMRIGHT") +frame.panelContainer.page2.panel.desc:SetText(L["SoundControl_SFXDesc"]) +frame.panelContainer.page2.enable = checkbox("ChocoboSoundControlOptionsPage2Enable", frame.panelContainer.page2) +frame.panelContainer.page2.enable:SetPoint("TOPLEFT", 10, -25) +frame.panelContainer.page2.enable.label:SetText(L["SoundControl_SFXEnable"]) +frame.panelContainer.page2.enable:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleSFX(true) + CSCO:Update() +end) +frame.panelContainer.page2.enableMount = checkbox( + "ChocoboSoundControlOptionsPage2EnableMount", + frame.panelContainer.page2) +frame.panelContainer.page2.enableMount:SetPoint("TOPLEFT", 10, -65) +frame.panelContainer.page2.enableMount.label:SetText(L["SoundControl_SFXMount"]) +frame.panelContainer.page2.enableMount:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleSFXMount(true) + CSCO:Update() +end) +frame.panelContainer.page2.enableNoMount = checkbox( + "ChocoboSoundControlOptionsPage2EnableNoMount", + frame.panelContainer.page2) +frame.panelContainer.page2.enableNoMount:SetPoint("TOPLEFT", 10, -105) +frame.panelContainer.page2.enableNoMount.label:SetText(L["SoundControl_SFXNoMount"]) +frame.panelContainer.page2.enableNoMount:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleSFXNoMount(true) + CSCO:Update() +end) +frame.panelContainer.page2.enableVolume = checkbox( + "ChocoboSoundControlOptionsPage2EnableVolume", + frame.panelContainer.page2) +frame.panelContainer.page2.enableVolume:SetPoint("TOPLEFT", 10, -145) +frame.panelContainer.page2.enableVolume.label:SetText(L["SoundControl_SFXVolume"]) +frame.panelContainer.page2.enableVolume:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleSFXVolume(true) + CSCO:Update() +end) +frame.panelContainer.page2.volumeSlider = slider( + "ChocoboSoundControlOptionsPage2VolumeSlider", + frame.panelContainer.page2) +frame.panelContainer.page2.volumeSlider:SetSize(450, 16) +frame.panelContainer.page2.volumeSlider:SetPoint("TOP", 0, -195) +frame.panelContainer.page2.volumeSlider:SetMinMaxValues(0, 100) +frame.panelContainer.page2.volumeSlider:SetValueStep(1) +frame.panelContainer.page2.volumeSlider.label:SetText(L["SoundControl_SFXSetVolume"]) +frame.panelContainer.page2.volumeSlider.high:SetText("100") +frame.panelContainer.page2.volumeSlider.low:SetText("0") +frame.panelContainer.page2.volumeSlider:SetScript("OnValueChanged", function(self) + Chocobo.SoundControl:SetSFXVolume(self:GetValue(), true) + CSCO:Update() +end) +frame.panelContainer.page2.volumeSlider:SetScript("OnMouseWheel", function(self, delta) + CSCO:VolumeScroll(self, delta, 1) +end) + +frame.panelContainer.page3 = CreateFrame("Frame", "ChocoboSoundControlOptionsPanelContainerPage3", frame.panelContainer) +frame.panelContainer.page3:SetPoint("TOPLEFT") +frame.panelContainer.page3:SetPoint("BOTTOMRIGHT") +frame.panelContainer.page3:Hide() +frame.panelContainer.page3.panel = CreateFrame("Frame", nil, frame.panelContainer.page3) +frame.panelContainer.page3.panel:SetSize(360, 20) +frame.panelContainer.page3.panel:SetPoint("TOP", 0, -10) +frame.panelContainer.page3.panel.desc = frame.panelContainer.page3.panel:CreateFontString(nil, "OVERLAY") +frame.panelContainer.page3.panel.desc:SetFont([[Fonts\FRIZQT__.TTF]], 12, "OUTLINE") +frame.panelContainer.page3.panel.desc:SetPoint("TOPLEFT") +frame.panelContainer.page3.panel.desc:SetPoint("BOTTOMRIGHT") +frame.panelContainer.page3.panel.desc:SetText(L["SoundControl_AmbienceDesc"]) +frame.panelContainer.page3.enable = checkbox("ChocoboSoundControlOptionsPage3Enable", frame.panelContainer.page3) +frame.panelContainer.page3.enable:SetPoint("TOPLEFT", 10, -25) +frame.panelContainer.page3.enable.label:SetText(L["SoundControl_AmbienceEnable"]) +frame.panelContainer.page3.enable:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleAmbience(true) + CSCO:Update() +end) +frame.panelContainer.page3.enableMount = checkbox( + "ChocoboSoundControlOptionsPage3EnableMount", + frame.panelContainer.page3) +frame.panelContainer.page3.enableMount:SetPoint("TOPLEFT", 10, -65) +frame.panelContainer.page3.enableMount.label:SetText(L["SoundControl_AmbienceMount"]) +frame.panelContainer.page3.enableMount:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleAmbienceMount(true) + CSCO:Update() +end) +frame.panelContainer.page3.enableNoMount = checkbox( + "ChocoboSoundControlOptionsPage3EnableNoMount", + frame.panelContainer.page3) +frame.panelContainer.page3.enableNoMount:SetPoint("TOPLEFT", 10, -105) +frame.panelContainer.page3.enableNoMount.label:SetText(L["SoundControl_AmbienceNoMount"]) +frame.panelContainer.page3.enableNoMount:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleAmbienceNoMount(true) + CSCO:Update() +end) +frame.panelContainer.page3.enableVolume = checkbox( + "ChocoboSoundControlOptionsPage3EnableVolume", + frame.panelContainer.page3) +frame.panelContainer.page3.enableVolume:SetPoint("TOPLEFT", 10, -145) +frame.panelContainer.page3.enableVolume.label:SetText(L["SoundControl_AmbienceVolume"]) +frame.panelContainer.page3.enableVolume:SetScript("OnClick", function() + Chocobo.SoundControl:ToggleAmbienceVolume(true) + CSCO:Update() +end) +frame.panelContainer.page3.volumeSlider = slider( + "ChocoboSoundControlOptionsPage3VolumeSlider", + frame.panelContainer.page3) +frame.panelContainer.page3.volumeSlider:SetSize(450, 16) +frame.panelContainer.page3.volumeSlider:SetPoint("TOP", 0, -195) +frame.panelContainer.page3.volumeSlider:SetMinMaxValues(0, 100) +frame.panelContainer.page3.volumeSlider:SetValueStep(1) +frame.panelContainer.page3.volumeSlider.label:SetText(L["SoundControl_AmbienceSetVolume"]) +frame.panelContainer.page3.volumeSlider.high:SetText("100") +frame.panelContainer.page3.volumeSlider.low:SetText("0") +frame.panelContainer.page3.volumeSlider:SetScript("OnValueChanged", function(self) + Chocobo.SoundControl:SetAmbienceVolume(self:GetValue(), true) + CSCO:Update() +end) +frame.panelContainer.page3.volumeSlider:SetScript("OnMouseWheel", function(self, delta) + CSCO:VolumeScroll(self, delta, 1) +end) + +function CSCO:Open() + if Settings and SettingsPanel then + Settings.OpenToCategory(Chocobo.Name) + else + InterfaceOptionsFrame_OpenToCategory(frame) + InterfaceOptionsFrame_OpenToCategory(frame) + end +end + +function CSCO:Update() + local settings = Chocobo.SoundControl.Settings + frame.toggle:SetChecked(settings["ENABLED"]) + frame.toggleDefault:SetChecked(settings["DEFAULT"]) + frame.panelContainer.page1.enable:SetChecked(settings["MUSIC"]["ENABLED"]) + frame.panelContainer.page1.enableMount:SetChecked(settings["MUSIC"]["MOUNTED"]) + frame.panelContainer.page1.enableNoMount:SetChecked(settings["MUSIC"]["NOTMOUNTED"]) + frame.panelContainer.page1.enableVolume:SetChecked(settings["MUSIC"]["MOD_VOLUME"]) + frame.panelContainer.page1.volumeSlider:SetValue(settings["MUSIC"]["VOLUME"] * 100) + frame.panelContainer.page1.volumeSlider.current:SetText(tostring(settings["MUSIC"]["VOLUME"] * 100)) + frame.panelContainer.page2.enable:SetChecked(settings["SFX"]["ENABLED"]) + frame.panelContainer.page2.enableMount:SetChecked(settings["SFX"]["MOUNTED"]) + frame.panelContainer.page2.enableNoMount:SetChecked(settings["SFX"]["NOTMOUNTED"]) + frame.panelContainer.page2.enableVolume:SetChecked(settings["SFX"]["MOD_VOLUME"]) + frame.panelContainer.page2.volumeSlider:SetValue(settings["SFX"]["VOLUME"] * 100) + frame.panelContainer.page2.volumeSlider.current:SetText(tostring(settings["SFX"]["VOLUME"] * 100)) + frame.panelContainer.page3.enable:SetChecked(settings["AMBIENCE"]["ENABLED"]) + frame.panelContainer.page3.enableMount:SetChecked(settings["AMBIENCE"]["MOUNTED"]) + frame.panelContainer.page3.enableNoMount:SetChecked(settings["AMBIENCE"]["NOTMOUNTED"]) + frame.panelContainer.page3.enableVolume:SetChecked(settings["AMBIENCE"]["MOD_VOLUME"]) + frame.panelContainer.page3.volumeSlider:SetValue(settings["AMBIENCE"]["VOLUME"] * 100) + frame.panelContainer.page3.volumeSlider.current:SetText(tostring(settings["AMBIENCE"]["VOLUME"] * 100)) + + local enabled = settings["ENABLED"] + local default = settings["DEFAULT"] + + if settings["MUSIC"]["MOD_VOLUME"] and enabled and not default then + frame.panelContainer.page1.volumeSlider:Enable() + frame.panelContainer.page1.volumeSlider.label:SetTextColor(1, 1, 1) + frame.panelContainer.page1.volumeSlider.high:SetTextColor(1, 1, 1) + frame.panelContainer.page1.volumeSlider.low:SetTextColor(1, 1, 1) + frame.panelContainer.page1.volumeSlider.current:SetTextColor(1, 1, 1) + else + frame.panelContainer.page1.volumeSlider:Disable() + frame.panelContainer.page1.volumeSlider.label:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page1.volumeSlider.high:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page1.volumeSlider.low:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page1.volumeSlider.current:SetTextColor(0.5, 0.5, 0.5) + end + + if settings["SFX"]["MOD_VOLUME"] and enabled and not default then + frame.panelContainer.page2.volumeSlider:Enable() + frame.panelContainer.page2.volumeSlider.label:SetTextColor(1, 1, 1) + frame.panelContainer.page2.volumeSlider.high:SetTextColor(1, 1, 1) + frame.panelContainer.page2.volumeSlider.low:SetTextColor(1, 1, 1) + frame.panelContainer.page2.volumeSlider.current:SetTextColor(1, 1, 1) + else + frame.panelContainer.page2.volumeSlider:Disable() + frame.panelContainer.page2.volumeSlider.label:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page2.volumeSlider.high:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page2.volumeSlider.low:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page2.volumeSlider.current:SetTextColor(0.5, 0.5, 0.5) + end + + if settings["AMBIENCE"]["MOD_VOLUME"] and enabled and not default then + frame.panelContainer.page3.volumeSlider:Enable() + frame.panelContainer.page3.volumeSlider.label:SetTextColor(1, 1, 1) + frame.panelContainer.page3.volumeSlider.high:SetTextColor(1, 1, 1) + frame.panelContainer.page3.volumeSlider.low:SetTextColor(1, 1, 1) + frame.panelContainer.page3.volumeSlider.current:SetTextColor(1, 1, 1) + else + frame.panelContainer.page3.volumeSlider:Disable() + frame.panelContainer.page3.volumeSlider.label:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page3.volumeSlider.high:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page3.volumeSlider.low:SetTextColor(0.5, 0.5, 0.5) + frame.panelContainer.page3.volumeSlider.current:SetTextColor(0.5, 0.5, 0.5) + end + + if not enabled or default then + self:CheckboxesEnabled(false) + else + self:CheckboxesEnabled(true) + end + + if enabled then + frame.toggleDefault:Enable() + frame.toggleDefault.label:SetTextColor(1, 1, 1) + else + frame.toggleDefault:Disable() + frame.toggleDefault.label:SetTextColor(0.5, 0.5, 0.5) + end +end + +function CSCO:CheckboxesEnabled(enabled) + local function setEnabled(f, e) + if e then + f:Enable() + else + f:Disable() + end + end + local dr, dg, db = 0.5, 0.5, 0.5 + local r, g, b = 0.5, 0.5, 0.5 + if enabled then + dr, dg, db = 1, 0.82, 0 + r, g, b = 1, 1, 1 + end + if enabled then + setEnabled(frame.panelContainer.tab1, true) + setEnabled(frame.panelContainer.tab2, true) + setEnabled(frame.panelContainer.tab3, true) + end + self:SetToCurrentTab() + frame.panelContainer.page1.panel.desc:SetTextColor(dr, dg, db) + frame.panelContainer.page2.panel.desc:SetTextColor(dr, dg, db) + frame.panelContainer.page3.panel.desc:SetTextColor(dr, dg, db) + setEnabled(frame.panelContainer.page1.enable, enabled) + setEnabled(frame.panelContainer.page1.enableMount, enabled) + setEnabled(frame.panelContainer.page1.enableNoMount, enabled) + setEnabled(frame.panelContainer.page1.enableVolume, enabled) + setEnabled(frame.panelContainer.page2.enable, enabled) + setEnabled(frame.panelContainer.page2.enableMount, enabled) + setEnabled(frame.panelContainer.page2.enableNoMount, enabled) + setEnabled(frame.panelContainer.page2.enableVolume, enabled) + setEnabled(frame.panelContainer.page3.enable, enabled) + setEnabled(frame.panelContainer.page3.enableMount, enabled) + setEnabled(frame.panelContainer.page3.enableNoMount, enabled) + setEnabled(frame.panelContainer.page3.enableVolume, enabled) + if not enabled then + setEnabled(frame.panelContainer.tab1, false) + setEnabled(frame.panelContainer.tab2, false) + setEnabled(frame.panelContainer.tab3, false) + end + frame.panelContainer.page1.enable.label:SetTextColor(r, g, b) + frame.panelContainer.page1.enableMount.label:SetTextColor(r, g, b) + frame.panelContainer.page1.enableNoMount.label:SetTextColor(r, g, b) + frame.panelContainer.page1.enableVolume.label:SetTextColor(r, g, b) + frame.panelContainer.page2.enable.label:SetTextColor(r, g, b) + frame.panelContainer.page2.enableMount.label:SetTextColor(r, g, b) + frame.panelContainer.page2.enableNoMount.label:SetTextColor(r, g, b) + frame.panelContainer.page2.enableVolume.label:SetTextColor(r, g, b) + frame.panelContainer.page3.enable.label:SetTextColor(r, g, b) + frame.panelContainer.page3.enableMount.label:SetTextColor(r, g, b) + frame.panelContainer.page3.enableNoMount.label:SetTextColor(r, g, b) + frame.panelContainer.page3.enableVolume.label:SetTextColor(r, g, b) +end + +function CSCO:SetToCurrentTab() + PanelTemplates_SetTab(frame.panelContainer, PanelTemplates_GetSelectedTab(frame.panelContainer)) +end + +function CSCO:VolumeScroll(s, delta, num) + local new = s:GetValue() + delta + if new < 0 or new > 100 then return end + if num == 1 then + Chocobo.SoundControl:SetMusicVolume(new, true) + elseif num == 2 then + Chocobo.SoundControl:SetSFXVolume(new, true) + elseif num == 3 then + Chocobo.SoundControl:SetAmbienceVolume(new, true) + end + self:Update() +end + +frame:SetScript("OnShow", function() CSCO:Update() end) + +frame.OnCommit = function() end +frame.OnDefault = function() end +frame.OnRefresh = function() CSCO:Update() end + +PanelTemplates_SetNumTabs(frame.panelContainer, 3) +PanelTemplates_SetTab(frame.panelContainer, 1) + +if Settings and SettingsPanel then + local category = Settings.GetCategory(Chocobo.Name) + local subcategory = Settings.RegisterCanvasLayoutSubcategory(category, frame, "Sound Control") + Settings.RegisterAddOnCategory(subcategory) +else + InterfaceOptions_AddCategory(frame, Chocobo.Name) +end diff --git a/libs/ChocoboLib/ChocoboLib.lua b/libs/ChocoboLib/ChocoboLib.lua index bcbf423..bea6663 100644 --- a/libs/ChocoboLib/ChocoboLib.lua +++ b/libs/ChocoboLib/ChocoboLib.lua @@ -1,100 +1,100 @@ ---[[ - Copyright (c) 2010-2020 by Adam Hellberg - - This file is part of Chocobo. - - Chocobo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Chocobo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Chocobo. If not, see . - - ------ - - Chocobo Lib (Chocobo Library) - - Collection of functions useful for buff/mount related actions. - As well as some general functions useful for anything. ---]] - -ChocoboLib = {} - ---[[General Functions]]-- --- String functions -function ChocoboLib:Trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function ChocoboLib:Split(s) - local r = {} - for token in string.gmatch(s, "[^%s]+") do - table.insert(r, token) - end - return r -end - --- Table functions -function ChocoboLib:InTable(tbl, val) - for _,v in pairs(tbl) do - if v == val then return true end - end - return false -end - -function ChocoboLib:Count(tbl) - local c = 0 - for _, _ in pairs(tbl) do - c = c + 1 - end - return c -end - ---[[ChocoboLib Specific Functions]]-- --- Buff/Aura functions - -local function GetBuffs() - local buffs = {} - for i=1,40 do -- Loop through all 40 possible buff indexes - local name, _, _, _, _, _, _, _, _, id = UnitBuff("player", i, "PLAYER CANCELABLE") -- Get buff on index i - -- Insert it into the buffs table, break if buff is nil (that means no other buffs exist on the player) - if name and id then buffs[name] = id else break end - end - return buffs -end - --- ChocoboLib:HasBuff ---- Argument #1: [table] containing numeric buff IDs or names to check ---- Overload #1.1: [number] ID of buff to check ---- Overload #1.2: [string] name of buff to check ---- RETURNS: false if the buff wasn't found, true, id of buff and name of buff if buff was found -function ChocoboLib:HasBuff(idColl) -- idColl is either a number or a table with IDs or buff names - -- TODO: Implement ability to pass IDs as varargs (1, 2, 3, 4, 5, ...) - if type(idColl) == "number" then - return self:HasBuff({idColl}) - elseif type(idColl) == "string" then - return self:HasBuff({idColl}) - elseif type(idColl) ~= "table" then - error("Argument #1 must be of type 'table', 'number' or 'string'.") -- Localize error? - return false -- Just in case the error() did not cause it to exit, for whatever reason. - end - - local buffs = GetBuffs() - - for _, value in pairs(idColl) do - local vType = type(value) - for name, id in pairs(buffs) do - if (vType == "number" and id == value) or (vType == "string" and name:lower() == value:lower()) then - return true, name or "", id - end - end - end - - return false -- Else return false (Player does not have the buff) -end +--[[ + Copyright (c) 2010-2020 by Adam Hellberg + + This file is part of Chocobo. + + Chocobo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Chocobo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Chocobo. If not, see . + + ------ + + Chocobo Lib (Chocobo Library) + + Collection of functions useful for buff/mount related actions. + As well as some general functions useful for anything. +--]] + +ChocoboLib = {} + +--[[General Functions]]-- +-- String functions +function ChocoboLib:Trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function ChocoboLib:Split(s) + local r = {} + for token in string.gmatch(s, "[^%s]+") do + table.insert(r, token) + end + return r +end + +-- Table functions +function ChocoboLib:InTable(tbl, val) + for _,v in pairs(tbl) do + if v == val then return true end + end + return false +end + +function ChocoboLib:Count(tbl) + local c = 0 + for _, _ in pairs(tbl) do + c = c + 1 + end + return c +end + +--[[ChocoboLib Specific Functions]]-- +-- Buff/Aura functions + +local function GetBuffs() + local buffs = {} + for i=1,40 do -- Loop through all 40 possible buff indexes + local name, _, _, _, _, _, _, _, _, id = UnitBuff("player", i, "PLAYER CANCELABLE") -- Get buff on index i + -- Insert it into the buffs table, break if buff is nil (that means no other buffs exist on the player) + if name and id then buffs[name] = id else break end + end + return buffs +end + +-- ChocoboLib:HasBuff +--- Argument #1: [table] containing numeric buff IDs or names to check +--- Overload #1.1: [number] ID of buff to check +--- Overload #1.2: [string] name of buff to check +--- RETURNS: false if the buff wasn't found, true, id of buff and name of buff if buff was found +function ChocoboLib:HasBuff(idColl) -- idColl is either a number or a table with IDs or buff names + -- TODO: Implement ability to pass IDs as varargs (1, 2, 3, 4, 5, ...) + if type(idColl) == "number" then + return self:HasBuff({idColl}) + elseif type(idColl) == "string" then + return self:HasBuff({idColl}) + elseif type(idColl) ~= "table" then + error("Argument #1 must be of type 'table', 'number' or 'string'.") -- Localize error? + return false -- Just in case the error() did not cause it to exit, for whatever reason. + end + + local buffs = GetBuffs() + + for _, value in pairs(idColl) do + local vType = type(value) + for name, id in pairs(buffs) do + if (vType == "number" and id == value) or (vType == "string" and name:lower() == value:lower()) then + return true, name or "", id + end + end + end + + return false -- Else return false (Player does not have the buff) +end diff --git a/libs/ChocoboLib/ChocoboLib.xml b/libs/ChocoboLib/ChocoboLib.xml index 2ca9398..63b37e6 100644 --- a/libs/ChocoboLib/ChocoboLib.xml +++ b/libs/ChocoboLib/ChocoboLib.xml @@ -1,22 +1,22 @@ - - -