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

1646 lines
56 KiB

if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then
local L = BigWigsAPI:GetLocale("BigWigs")
print(L.classicWarning1)
print(L.classicWarning2)
BasicMessageDialog.Text:SetText(L.classicWarning1)
BasicMessageDialog:Show()
return
end
local L = BigWigsAPI:GetLocale("BigWigs")
local mod, public = {}, {}
local bwFrame = CreateFrame("Frame")
local ldb = LibStub("LibDataBroker-1.1")
local ldbi = LibStub("LibDBIcon-1.0")
local strfind = string.find
-----------------------------------------------------------------------
-- Generate our version variables
--
local BIGWIGS_VERSION = 227
local BIGWIGS_RELEASE_STRING, BIGWIGS_VERSION_STRING = "", ""
local versionQueryString, versionResponseString = "Q^%d^%s^%d^%s", "V^%d^%s^%d^%s"
local customGuildName = false
local BIGWIGS_GUILD_VERSION = 0
local guildWarnMessage = ""
do
-- START: MAGIC PACKAGER VOODOO VERSION STUFF
local _, tbl = ...
local REPO = "REPO"
local ALPHA = "ALPHA"
local RELEASE = "RELEASE"
local releaseType = RELEASE
local myGitHash = "5438284" -- The ZIP packager will replace this with the Git hash.
local releaseString = ""
--[=[@alpha@
-- The following code will only be present in alpha ZIPs.
releaseType = ALPHA
--@end-alpha@]=]
-- If we find "@" then we're running from Git directly.
if strfind(myGitHash, "@", nil, true) then
myGitHash = "repo"
releaseType = REPO
end
if releaseType == REPO then
releaseString = L.sourceCheckout:format(BIGWIGS_VERSION)
elseif releaseType == RELEASE then
releaseString = L.officialRelease:format(BIGWIGS_VERSION, myGitHash)
elseif releaseType == ALPHA then
releaseString = L.alphaRelease:format(BIGWIGS_VERSION, myGitHash)
end
-- Format is "V:version^hash^guildVersion^guildName"
local isVersionNumber = type(tbl.guildVersion) == "number"
local isGuildString = type(tbl.guildName) == "string"
local isGuildWarnString = type(tbl.guildWarn) == "string"
if isVersionNumber and isGuildString and isGuildWarnString and tbl.guildVersion > 0 and tbl.guildName:gsub(" ", "") ~= "" then
customGuildName = tbl.guildName
BIGWIGS_GUILD_VERSION = tbl.guildVersion
guildWarnMessage = tbl.guildWarn
releaseString = L.guildRelease:format(BIGWIGS_GUILD_VERSION, BIGWIGS_VERSION)
versionQueryString = versionQueryString:format(BIGWIGS_VERSION, myGitHash, tbl.guildVersion, tbl.guildName)
versionResponseString = versionResponseString:format(BIGWIGS_VERSION, myGitHash, tbl.guildVersion, tbl.guildName)
BIGWIGS_VERSION_STRING = ("%d/%d-%s"):format(BIGWIGS_GUILD_VERSION, BIGWIGS_VERSION, myGitHash)
else
versionQueryString = versionQueryString:format(BIGWIGS_VERSION, myGitHash, 0, "")
versionResponseString = versionResponseString:format(BIGWIGS_VERSION, myGitHash, 0, "")
BIGWIGS_VERSION_STRING = ("%d-%s"):format(BIGWIGS_VERSION, myGitHash)
end
BIGWIGS_RELEASE_STRING = releaseString
-- END: MAGIC PACKAGER VOODOO VERSION STUFF
end
-----------------------------------------------------------------------
-- Locals
--
local tooltipFunctions = {}
local next, tonumber, type, strsplit = next, tonumber, type, strsplit
local SendAddonMessage, Ambiguate, CTimerAfter, CTimerNewTicker = C_ChatInfo.SendAddonMessage, Ambiguate, C_Timer.After, C_Timer.NewTicker
local GetInstanceInfo, GetBestMapForUnit, GetMapInfo = GetInstanceInfo, C_Map.GetBestMapForUnit, C_Map.GetMapInfo
local UnitName, UnitGUID = UnitName, UnitGUID
local debugstack, print = debugstack, print
-- Try to grab unhooked copies of critical funcs (hooked by some crappy addons)
public.GetBestMapForUnit = GetBestMapForUnit
public.GetMapInfo = GetMapInfo
public.GetInstanceInfo = GetInstanceInfo
public.SendAddonMessage = SendAddonMessage
public.SendChatMessage = SendChatMessage
public.CTimerAfter = CTimerAfter
public.CTimerNewTicker = CTimerNewTicker
public.UnitName = UnitName
public.UnitGUID = UnitGUID
public.SetRaidTarget = SetRaidTarget
public.UnitHealth = UnitHealth
public.UnitHealthMax = UnitHealthMax
public.UnitDetailedThreatSituation = UnitDetailedThreatSituation
-- Version
local usersHash = {}
local usersVersion = {}
local usersGuildVersion = {}
local usersGuildName = {}
local usersDBM = {}
local highestFoundVersion = BIGWIGS_VERSION
local highestFoundGuildVersion = BIGWIGS_GUILD_VERSION
-- Loading
local isMouseDown = false
local loadOnCoreEnabled = {} -- BigWigs modulepacks that should load when a hostile zone is entered or the core is manually enabled, this would be the default plugins Bars, Messages etc
local loadOnZone = {} -- BigWigs modulepack that should load on a specific zone
local loadOnSlash = {} -- BigWigs modulepacks that can load from a chat command
local menus = {} -- contains the menus for BigWigs, once the core is loaded they will get injected
local enableZones = {} -- contains the zones in which BigWigs will enable
local disabledZones -- contains the zones in which BigWigs will enable, but the user has disabled the addon
local worldBosses = {} -- contains the list of world bosses per zone that should enable the core
local fakeZones = { -- Fake zones used as GUI menus
[-101]=true, -- Outland
[-424]=true, -- Pandaria
[-572]=true, -- Draenor
[-619]=true, -- Broken Isles
[-947]=true, -- Azeroth
[-1647]=true, -- Shadowlands
}
do
local c = "BigWigs_Classic"
local bc = "BigWigs_BurningCrusade"
local wotlk = "BigWigs_WrathOfTheLichKing"
local cata = "BigWigs_Cataclysm"
local mop = "BigWigs_MistsOfPandaria"
local wod = "BigWigs_WarlordsOfDraenor"
local l = "BigWigs_Legion"
local bfa = "BigWigs_BattleForAzeroth"
local s = "BigWigs_Shadowlands"
local lw_c = "LittleWigs_Classic"
local lw_bc = "LittleWigs_BurningCrusade"
local lw_wotlk = "LittleWigs_WrathOfTheLichKing"
local lw_cata = "LittleWigs_Cataclysm"
local lw_mop = "LittleWigs_MistsOfPandaria"
local lw_wod = "LittleWigs_WarlordsOfDraenor"
local lw_l = "LittleWigs_Legion"
local lw_bfa = "LittleWigs_BattleForAzeroth"
local lw_s = "LittleWigs_Shadowlands"
public.zoneTbl = {
--[[ BigWigs: Classic ]]--
[409] = c, -- Molten Core
[469] = c, -- Blackwing Lair
[509] = c, -- Ruins of Ahn'Qiraj
[531] = c, -- Ahn'Qiraj Temple
--[[ BigWigs: The Burning Crusade ]]--
[-101] = bc, -- Outland (Fake Menu)
[565] = bc, -- Gruul's Lair
[532] = bc, -- Karazhan
[548] = bc, -- Coilfang: Serpentshrine Cavern
[550] = bc, -- Tempest Keep
[544] = bc, -- Magtheridon's Lair
[534] = bc, -- The Battle for Mount Hyjal
[564] = bc, -- Black Temple
[580] = bc, -- The Sunwell
--[[ BigWigs: Wrath of the Lich King ]]--
[533] = wotlk, -- Naxxramas
[616] = wotlk, -- The Eye of Eternity
[603] = wotlk, -- Ulduar
[624] = wotlk, -- Vault of Archavon
[649] = wotlk, -- Trial of the Crusader
[724] = wotlk, -- The Ruby Sanctum
[631] = wotlk, -- Icecrown Citadel
[615] = wotlk, -- The Obsidian Sanctum
[249] = wotlk, -- Onyxia's Lair
--[[ BigWigs: Cataclysm ]]--
[671] = cata, -- The Bastion of Twilight
[669] = cata, -- Blackwing Descent
[754] = cata, -- Throne of the Four Winds
[757] = cata, -- Baradin Hold
[720] = cata, -- Firelands
[967] = cata, -- Dragon Soul
--[[ BigWigs: Mists of Pandaria ]]--
[-424] = mop, -- Pandaria (Fake Menu)
[1009] = mop, -- Heart of Fear
[996] = mop, -- Terrace of Endless Spring
[1008] = mop, -- Mogu'shan Vaults
[1098] = mop, -- Throne of Thunder
[1136] = mop, -- Siege of Orgrimmar
--[[ BigWigs: Warlords of Draenor ]]--
[-572] = wod, -- Draenor (Fake Menu)
[1228] = wod, -- Highmaul
[1205] = wod, -- Blackrock Foundry
[1448] = wod, -- Hellfire Citadel
--[[ BigWigs: Legion ]]--
[-619] = l, -- Broken Isles (Fake Menu)
[1520] = l, -- The Emerald Nightmare
[1648] = l, -- Trial of Valor
[1530] = l, -- The Nighthold
[1676] = l, -- Tomb of Sargeras
[1712] = l, -- Antorus, the Burning Throne
[1779] = l, -- Invasion Points
--[[ BigWigs: Battle for Azeroth ]]--
[-947] = bfa, -- Azeroth (Fake Menu)
[1861] = bfa, -- Uldir
[2070] = bfa, -- Battle Of Dazar'alor
[2096] = bfa, -- Crucible of Storms
[2164] = bfa, -- The Eternal Palace
[2217] = bfa, -- Ny'alotha, the Waking City
--[[ BigWigs: Shadowlands ]]--
[-1647] = s, -- Shadowlands (Fake Menu)
[2296] = s, -- Castle Nathria
[2450] = s, -- Sanctum of Domination
--[[ LittleWigs: Classic ]]--
[33] = lw_c, -- Shadowfang Keep
[36] = lw_c, -- Deadmines
--[[ LittleWigs: The Burning Crusade ]]--
[540] = lw_bc, -- Hellfire Citadel: The Shattered Halls
[542] = lw_bc, -- Hellfire Citadel: The Blood Furnace
[543] = lw_bc, -- Hellfire Citadel: Ramparts
[546] = lw_bc, -- Coilfang: The Underbog
[545] = lw_bc, -- Coilfang: The Steamvault
[547] = lw_bc, -- Coilfang: The Slave Pens
[553] = lw_bc, -- Tempest Keep: The Botanica
[554] = lw_bc, -- Tempest Keep: The Mechanar
[552] = lw_bc, -- Tempest Keep: The Arcatraz
[556] = lw_bc, -- Auchindoun: Sethekk Halls
[555] = lw_bc, -- Auchindoun: Shadow Labyrinth
[557] = lw_bc, -- Auchindoun: Mana-Tombs
[558] = lw_bc, -- Auchindoun: Auchenai Crypts
[269] = lw_bc, -- Opening of the Dark Portal
[560] = lw_bc, -- The Escape from Durnholde
[585] = lw_bc, -- Magister's Terrace
--[[ LittleWigs: Wrath of the Lich King ]]--
[576] = lw_wotlk, -- The Nexus
[578] = lw_wotlk, -- The Oculus
[608] = lw_wotlk, -- Violet Hold
[595] = lw_wotlk, -- The Culling of Stratholme
[619] = lw_wotlk, -- Ahn'kahet: The Old Kingdom
[604] = lw_wotlk, -- Gundrak
[574] = lw_wotlk, -- Utgarde Keep
[575] = lw_wotlk, -- Utgarde Pinnacle
[602] = lw_wotlk, -- Halls of Lightning
[601] = lw_wotlk, -- Azjol-Nerub
[658] = lw_wotlk, -- Pit of Saron
[599] = lw_wotlk, -- Halls of Stone
[600] = lw_wotlk, -- Drak'Tharon Keep
[650] = lw_wotlk, -- Trial of the Champion
[668] = lw_wotlk, -- Halls of Reflection
[632] = lw_wotlk, -- The Forge of Souls
--[[ LittleWigs: Cataclysm ]]--
[568] = lw_cata, -- Zul'Aman
[859] = lw_cata, -- Zul'Gurub
[643] = lw_cata, -- Throne of the Tides
[644] = lw_cata, -- Halls of Origination
[645] = lw_cata, -- Blackrock Caverns
[755] = lw_cata, -- Lost City of the Tol'vir
[725] = lw_cata, -- The Stonecore
[938] = lw_cata, -- End Time
[939] = lw_cata, -- Well of Eternity
[657] = lw_cata, -- The Vortex Pinnacle
[670] = lw_cata, -- Grim Batol
--[[ LittleWigs: Mists of Pandaria ]]--
[959] = lw_mop, -- Shado-Pan Monastery
[960] = lw_mop, -- Temple of the Jade Serpent
[961] = lw_mop, -- Stormstout Brewery
[962] = lw_mop, -- Gate of the Setting Sun
[994] = lw_mop, -- Mogu'shan Palace
[1001] = lw_mop, -- Scarlet Halls
[1011] = lw_mop, -- Siege of Niuzao Temple
[1112] = lw_mop, -- Pursuing the Black Harvest
[1004] = lw_mop, -- Scarlet Monastery
--[[ LittleWigs: Warlords of Draenor ]]--
[1209] = lw_wod, -- Skyreach
[1176] = lw_wod, -- Shadowmoon Burial Grounds
[1208] = lw_wod, -- Grimrail Depot
[1279] = lw_wod, -- The Everbloom
[1195] = lw_wod, -- Iron Docks
[1182] = lw_wod, -- Auchindoun
[1175] = lw_wod, -- Bloodmaul Slag Mines
[1358] = lw_wod, -- Upper Blackrock Spire
--[[ LittleWigs: Legion ]]--
[1544] = lw_l, -- Assault on Violet Hold
[1677] = lw_l, -- Cathedral of Eternal Night
[1571] = lw_l, -- Court of Stars
[1651] = lw_l, -- Return to Karazhan
[1501] = lw_l, -- Black Rook Hold
[1516] = lw_l, -- The Arcway
[1466] = lw_l, -- Darkheart Thicket
[1458] = lw_l, -- Neltharion's Lair
[1456] = lw_l, -- Eye of Azshara
[1492] = lw_l, -- Maw of Souls
[1477] = lw_l, -- Halls of Valor
[1493] = lw_l, -- Vault of the Wardens
[1753] = lw_l, -- Seat of the Triumvirate
--[[ LittleWigs: Battle for Azeroth ]]--
[1763] = lw_bfa, -- Atal'Dazar
[1754] = lw_bfa, -- Freehold
[1762] = lw_bfa, -- King's Rest
[1864] = lw_bfa, -- Shrine of the Storm
[1822] = lw_bfa, -- Siege of Boralus
[1877] = lw_bfa, -- Temple of Sethraliss
[1594] = lw_bfa, -- The Undermine
[1771] = lw_bfa, -- Tol Dagor
[1841] = lw_bfa, -- Underrot
[1862] = lw_bfa, -- Waycrest Manor
[2097] = lw_bfa, -- Operation: Mechagon
[2212] = lw_bfa, -- Horrific Vision of Orgrimmar
[2213] = lw_bfa, -- Horrific Vision of Stormwind
--[[ LittleWigs: Shadowlands ]]--
[2284] = lw_s, -- Sanguine Depths
[2285] = lw_s, -- Spires of Ascension
[2286] = lw_s, -- The Necrotic Wake
[2287] = lw_s, -- Halls of Atonement
[2289] = lw_s, -- Plaguefall
[2290] = lw_s, -- Mists of Tirna Scithe
[2291] = lw_s, -- De Other Side
[2293] = lw_s, -- Theater of Pain
[2441] = lw_s, -- Tazavesh, the Veiled Market
}
public.zoneTblWorld = {
[-104] = -101, [-100] = -101, -- Outland
[-376] = -424, [-379] = -424, [-504] = -424, [-507] = -424, [-554] = -424, -- Pandaria
[-542] = -572, [-543] = -572, [-534] = -572, -- Draenor
[-630] = -619, [-634] = -619, [-641] = -619, [-650] = -619, [-680] = -619, -- Broken Isles
[-942] = -947, -- Azeroth/BfA
[-1536] = -1647, [-1565] = -1647, [-1525] = -1647, [-1533] = -1647, -- Shadowlands
}
end
-----------------------------------------------------------------------
-- Utility
--
local EnableAddOn, GetAddOnEnableState, GetAddOnInfo, IsAddOnLoaded, LoadAddOn = EnableAddOn, GetAddOnEnableState, GetAddOnInfo, IsAddOnLoaded, LoadAddOn
local GetAddOnMetadata, IsInGroup, IsInRaid, UnitAffectingCombat, UnitGroupRolesAssigned = GetAddOnMetadata, IsInGroup, IsInRaid, UnitAffectingCombat, UnitGroupRolesAssigned
local GetSpecialization, GetSpecializationRole, IsPartyLFG, UnitIsDeadOrGhost, UnitSetRole = GetSpecialization, GetSpecializationRole, IsPartyLFG, UnitIsDeadOrGhost, UnitSetRole
local reqFuncAddons = {
BigWigs_Core = true,
BigWigs_Options = true,
BigWigs_Plugins = true,
}
local function IsAddOnEnabled(addon)
local character = UnitName("player")
return GetAddOnEnableState(character, addon) > 0
end
local function sysprint(msg)
print("|cFF33FF99BigWigs|r: "..msg)
end
local function load(obj, index)
if obj then return true end
if loadOnSlash[index] then
if not IsAddOnLoaded(index) then -- Check if we need remove our slash handler stub.
for _, slash in next, loadOnSlash[index] do
hash_SlashCmdList[slash] = nil
end
end
loadOnSlash[index] = nil
end
if reqFuncAddons[index] then
reqFuncAddons[index] = nil
if index == "BigWigs_Core" then
reqFuncAddons.BigWigs_Plugins = nil
end
end
EnableAddOn(index) -- Make sure it wasn't left disabled for whatever reason
local loaded, reason = LoadAddOn(index)
if not loaded then
sysprint(ADDON_LOAD_FAILED:format(GetAddOnInfo(index), _G["ADDON_"..reason]))
end
return loaded
end
local function loadAddons(tbl)
if not tbl[1] then return end
for i = 1, #tbl do
local index = tbl[i]
if not IsAddOnLoaded(index) and load(nil, index) then
local name = GetAddOnInfo(index)
public:SendMessage("BigWigs_ModulePackLoaded", name)
end
end
for i = #tbl, 1, -1 do
tbl[i] = nil
end
end
local function loadZone(zone)
if loadOnZone[zone] then
loadAddons(loadOnZone[zone])
end
end
local function loadAndEnableCore()
local loaded = load(BigWigs, "BigWigs_Core")
if not BigWigs then return end
loadAddons(loadOnCoreEnabled)
BigWigs:Enable()
return loaded
end
local function loadCoreAndOpenOptions()
loadAndEnableCore()
load(BigWigsOptions, "BigWigs_Options")
if BigWigsOptions then
BigWigsOptions:Open()
end
end
local function Popup(msg)
BasicMessageDialog.Text:SetText(msg)
BasicMessageDialog:Show()
end
-----------------------------------------------------------------------
-- LDB Plugin
--
local dataBroker = ldb:NewDataObject("BigWigs",
{type = "launcher", label = "BigWigs", icon = "Interface\\AddOns\\BigWigs\\Media\\Icons\\core-disabled"}
)
function dataBroker.OnClick(self, button)
-- If you are a dev and need the BigWigs options loaded to do something, please come talk to us on Discord about your use case
if button == "RightButton" then
--if isMouseDown then
loadCoreAndOpenOptions()
--else
-- local trace = debugstack(2)
-- public.mstack = trace
-- sysprint("|cFFff0000WARNING!|r")
-- sysprint("One of your addons was prevented from force loading the BigWigs options.")
-- sysprint("Contact us on the BigWigs Discord about this, it should not be happening.")
--end
end
end
function dataBroker.OnTooltipShow(tt)
tt:AddLine("BigWigs")
if BigWigs and BigWigs:IsEnabled() then
local added = false
for name, module in BigWigs:IterateBossModules() do
if module:IsEnabled() then
if not added then
tt:AddLine(L.activeBossModules, 1, 1, 1)
added = true
end
tt:AddLine(module.displayName)
end
end
end
for i = 1, #tooltipFunctions do
tooltipFunctions[i](tt)
end
tt:AddLine(L.tooltipHint, 0.2, 1, 0.2, 1)
end
-----------------------------------------------------------------------
-- Version listing functions
--
tooltipFunctions[#tooltipFunctions+1] = function(tt)
local add, i = false, 0
for _, version in next, usersVersion do
i = i + 1
if version < highestFoundVersion then
add = true
break
end
end
if not add and i ~= GetNumGroupMembers() then
add = true
end
if add then
tt:AddLine(L.oldVersionsInGroup, 1, 0, 0, 1)
end
end
-----------------------------------------------------------------------
-- Loader initialization
--
do
local loadOnInstanceAddons = {} -- Will contain all names of addons with an X-BigWigs-LoadOn-InstanceId directive
local loadOnWorldBoss = {} -- Addons that should load when targetting a specific mob
local extraMenus = {} -- Addons that contain extra zone menus to appear in the GUI
local noMenus = {} -- Addons that contain zones that shouldn't create a menu
local blockedMenus = {} -- Zones that shouldn't create a menu
for i = 1, GetNumAddOns() do
local name = GetAddOnInfo(i)
if reqFuncAddons[name] then
EnableAddOn(i) -- Make sure it wasn't left disabled for whatever reason
end
if IsAddOnEnabled(i) then
local meta = GetAddOnMetadata(i, "X-BigWigs-LoadOn-CoreEnabled")
if meta then
if name == "BigWigs_Plugins" then -- Always first
table.insert(loadOnCoreEnabled, 1, i)
else
loadOnCoreEnabled[#loadOnCoreEnabled + 1] = i
end
end
meta = GetAddOnMetadata(i, "X-BigWigs-LoadOn-InstanceId")
if meta then
loadOnInstanceAddons[#loadOnInstanceAddons + 1] = i
end
meta = GetAddOnMetadata(i, "X-BigWigs-ExtraMenu")
if meta then
extraMenus[#extraMenus + 1] = i
end
meta = GetAddOnMetadata(i, "X-BigWigs-NoMenu")
if meta then
noMenus[#noMenus + 1] = i
end
meta = GetAddOnMetadata(i, "X-BigWigs-LoadOn-WorldBoss")
if meta then
loadOnWorldBoss[#loadOnWorldBoss + 1] = i
end
meta = GetAddOnMetadata(i, "X-BigWigs-LoadOn-Slash")
if meta then
loadOnSlash[i] = {}
local tbl = {strsplit(",", meta)}
for j=1, #tbl do
local slash = tbl[j]:trim():upper()
_G["SLASH_"..slash..1] = slash
SlashCmdList[slash] = function(text)
if strfind(name, "BigWigs", nil, true) then
-- Attempting to be smart. Only load core & config if it's a BW plugin.
loadAndEnableCore()
load(BigWigsOptions, "BigWigs_Options")
end
if load(nil, i) then -- Load the addon/plugin
-- Call the slash command again, which should have been set by the addon.
-- Authors, do NOT delay setting it in OnInitialize/OnEnable/etc.
ChatFrame_ImportAllListsToHash()
local func = hash_SlashCmdList[slash]
if func then
func(text)
else
-- Addon didn't register the slash command for whatever reason, print the default invalid slash message.
local info = ChatTypeInfo["SYSTEM"]
DEFAULT_CHAT_FRAME:AddMessage(HELP_TEXT_SIMPLE, info.r, info.g, info.b, info.id)
end
end
end
loadOnSlash[i][j] = slash
end
end
else
local meta = GetAddOnMetadata(i, "X-BigWigs-LoadOn-InstanceId")
if meta then -- Disabled content
for j = 1, select("#", strsplit(",", meta)) do
local rawId = select(j, strsplit(",", meta))
local id = tonumber(rawId:trim())
if id and id > 0 then
if public.zoneTbl[id] then
if not disabledZones then disabledZones = {} end
disabledZones[id] = name
end
end
end
end
end
if next(loadOnSlash) then
ChatFrame_ImportAllListsToHash() -- Add our slashes to the hash.
end
end
local function iterateInstanceIds(addon, ...)
for i = 1, select("#", ...) do
local rawId = select(i, ...)
local id = tonumber(rawId:trim())
if id then
local instanceName = GetRealZoneText(id)
-- register the instance id for enabling.
if instanceName and instanceName ~= "" then -- Protect live client from beta client ids
enableZones[id] = true
if not loadOnZone[id] then loadOnZone[id] = {} end
loadOnZone[id][#loadOnZone[id] + 1] = addon
if not menus[id] and not blockedMenus[id] then menus[id] = true end
end
else
local name = GetAddOnInfo(addon)
sysprint(("The instance ID %q from the addon %q was not parsable."):format(tostring(rawId), name))
end
end
end
local currentZone = nil
local function iterateWorldBosses(addon, ...)
for i = 1, select("#", ...) do
local rawZoneOrBoss = select(i, ...)
local zoneOrBoss = tonumber(rawZoneOrBoss:trim())
if zoneOrBoss then
if not currentZone then
currentZone = zoneOrBoss
-- register the zone for enabling.
enableZones[currentZone] = "world"
if not loadOnZone[currentZone] then loadOnZone[currentZone] = {} end
loadOnZone[currentZone][#loadOnZone[currentZone] + 1] = addon
else
worldBosses[zoneOrBoss] = currentZone
currentZone = nil
end
else
local name = GetAddOnInfo(addon)
sysprint(("The zone ID %q from the addon %q was not parsable."):format(tostring(rawZoneOrBoss), name))
end
end
end
local function addExtraMenus(addon, ...)
for i = 1, select("#", ...) do
local rawMenu = select(i, ...)
local id = tonumber(rawMenu:trim())
if id then
local name
if id < 0 then
local tbl = GetMapInfo(-id)
if tbl then
name = tbl.name
else
name = tostring(id)
end
else
name = GetRealZoneText(id)
end
if name and name ~= "" then -- Protect live client from beta client ids
if not loadOnZone[id] then loadOnZone[id] = {} end
loadOnZone[id][#loadOnZone[id] + 1] = addon
if not menus[id] then menus[id] = true end
end
else
local name = GetAddOnInfo(addon)
sysprint(("The extra menu ID %q from the addon %q was not parsable."):format(tostring(rawMenu), name))
end
end
end
local function blockMenus(addon, ...)
for i = 1, select("#", ...) do
local rawMenu = select(i, ...)
local id = tonumber(rawMenu:trim())
if id then
local name
if id < 0 then
local tbl = GetMapInfo(-id)
if tbl then
name = tbl.name
else
name = tostring(id)
end
else
name = GetRealZoneText(id)
end
if name and name ~= "" and not blockedMenus[id] then -- Protect live client from beta client ids
blockedMenus[id] = true
end
else
local name = GetAddOnInfo(addon)
sysprint(("The block menu ID %q from the addon %q was not parsable."):format(tostring(rawMenu), name))
end
end
end
for i = 1, #extraMenus do
local index = extraMenus[i]
local data = GetAddOnMetadata(index, "X-BigWigs-ExtraMenu")
if data then
addExtraMenus(index, strsplit(",", data))
end
end
for i = 1, #noMenus do
local index = noMenus[i]
local data = GetAddOnMetadata(index, "X-BigWigs-NoMenu")
if data then
blockMenus(index, strsplit(",", data))
end
end
for i = 1, #loadOnInstanceAddons do
local index = loadOnInstanceAddons[i]
local instancesIds = GetAddOnMetadata(index, "X-BigWigs-LoadOn-InstanceId")
if instancesIds then
iterateInstanceIds(index, strsplit(",", instancesIds))
end
end
for i = 1, #loadOnWorldBoss do
local index = loadOnWorldBoss[i]
local zones = GetAddOnMetadata(index, "X-BigWigs-LoadOn-WorldBoss")
if zones then
iterateWorldBosses(index, strsplit(",", zones))
end
end
end
function mod:ADDON_LOADED(addon)
if addon ~= "BigWigs" then
-- If you are a dev and need the BigWigs options loaded to do something, please come talk to us on Discord about your use case
--if reqFuncAddons[addon] then
-- local trace = debugstack(2)
-- public.lstack = trace
-- sysprint("|cFFff0000WARNING!|r")
-- sysprint("One of your addons is force loading the BigWigs options.")
-- sysprint("Contact us on the BigWigs Discord about this, it should not be happening.")
-- reqFuncAddons = {}
--end
return
end
--bwFrame:RegisterEvent("GLOBAL_MOUSE_DOWN")
--bwFrame:RegisterEvent("GLOBAL_MOUSE_UP")
bwFrame:RegisterEvent("ZONE_CHANGED")
bwFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
bwFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
bwFrame:RegisterEvent("LFG_PROPOSAL_SHOW")
-- Role Updating
bwFrame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
RolePollPopup:UnregisterEvent("ROLE_POLL_BEGIN")
bwFrame:RegisterEvent("CHAT_MSG_ADDON")
C_ChatInfo.RegisterAddonMessagePrefix("BigWigs")
C_ChatInfo.RegisterAddonMessagePrefix("D4") -- DBM
-- LibDBIcon setup
if type(BigWigsIconDB) ~= "table" then
BigWigsIconDB = {}
end
ldbi:Register("BigWigs", dataBroker, BigWigsIconDB)
if BigWigs3DB then
-- Somewhat ugly, but saves loading AceDB with the loader instead of with the core
if BigWigs3DB.profileKeys and BigWigs3DB.profiles then
local name = UnitName("player")
local realm = GetRealmName()
if name and realm and BigWigs3DB.profileKeys[name.." - "..realm] then
local key = BigWigs3DB.profiles[BigWigs3DB.profileKeys[name.." - "..realm]]
if key then
self.isFakingDBM = key.fakeDBMVersion
self.isShowingZoneMessages = key.showZoneMessages
end
if BigWigs3DB.namespaces and BigWigs3DB.namespaces.BigWigs_Plugins_Sounds and BigWigs3DB.namespaces.BigWigs_Plugins_Sounds.profiles and BigWigs3DB.namespaces.BigWigs_Plugins_Sounds.profiles[BigWigs3DB.profileKeys[name.." - "..realm]] then
self.isSoundOn = BigWigs3DB.namespaces.BigWigs_Plugins_Sounds.profiles[BigWigs3DB.profileKeys[name.." - "..realm]].sound
end
end
end
-- Cleanup function.
-- TODO: look into having a way for our boss modules not to create a table when no options are changed.
if BigWigs3DB.namespaces then
for k,v in next, BigWigs3DB.namespaces do
if strfind(k, "BigWigs_Bosses_", nil, true) and not next(v) then
BigWigs3DB.namespaces[k] = nil
end
end
end
BigWigs3DB.wipe80 = nil -- XXX temp boss DB wipe for 8.0.1 // removed in 9.0.2
BigWigs3DB.discord = nil -- XXX 9.0.2
end
self:BigWigs_CoreOptionToggled(nil, "fakeDBMVersion", self.isFakingDBM)
local num = tonumber(C_CVar.GetCVar("Sound_NumChannels")) or 0
if num < 64 then
C_CVar.SetCVar("Sound_NumChannels", "64") -- Blizzard keeps screwing with addon sound priority so we force this minimum
end
num = tonumber(C_CVar.GetCVar("Sound_MaxCacheSizeInBytes")) or 0
if num < 67108864 then
C_CVar.SetCVar("Sound_MaxCacheSizeInBytes", "67108864") -- Set the cache to the "Small (64MB)" setting as a minimum
end
--bwFrame:UnregisterEvent("ADDON_LOADED")
--self.ADDON_LOADED = nil
bwFrame.UnregisterEvent(UIParent, "TALKINGHEAD_REQUESTED") -- Prevent the event order re-shuffling mid-instance
end
function mod:GLOBAL_MOUSE_DOWN(button)
if button == "RightButton" then
isMouseDown = true
end
end
function mod:GLOBAL_MOUSE_UP(button)
if button == "RightButton" then
isMouseDown = false
end
end
-- We can't do our addon loading in ADDON_LOADED as the target addons may be registering that
-- which would break that event for those addons. Use this event instead.
function mod:UPDATE_FLOATING_CHAT_WINDOWS()
bwFrame:UnregisterEvent("UPDATE_FLOATING_CHAT_WINDOWS")
self.UPDATE_FLOATING_CHAT_WINDOWS = nil
self:GROUP_ROSTER_UPDATE()
self:PLAYER_ENTERING_WORLD()
self:ZONE_CHANGED()
end
-- Various temporary printing stuff
do
local old = {
BigWigs_Ulduar = "BigWigs_WrathOfTheLichKing",
BigWigs_Yogg_Brain = "BigWigs_WrathOfTheLichKing",
BigWigs_TheEye = "BigWigs_BurningCrusade",
BigWigs_Sunwell = "BigWigs_BurningCrusade",
BigWigs_SSC = "BigWigs_BurningCrusade",
BigWigs_Outland = "BigWigs_BurningCrusade",
BigWigs_Northrend = "BigWigs_WrathOfTheLichKing",
BigWigs_Naxxramas = "BigWigs_WrathOfTheLichKing",
BigWigs_MC = "BigWigs_Classic",
BigWigs_Karazhan = "BigWigs_BurningCrusade",
BigWigs_Hyjal = "BigWigs_BurningCrusade",
BigWigs_Coliseum = "BigWigs_WrathOfTheLichKing",
BigWigs_Citadel = "BigWigs_WrathOfTheLichKing",
BigWigs_LK_Valkyr_Marker = "BigWigs_WrathOfTheLichKing",
BigWigs_BWL = "BigWigs_Classic",
BigWigs_BlackTemple = "BigWigs_BurningCrusade",
BigWigs_AQ20 = "BigWigs_Classic",
BigWigs_AQ40 = "BigWigs_Classic",
BigWigs_Baradin = "BigWigs_Cataclysm",
BigWigs_Bastion = "BigWigs_Cataclysm",
BigWigs_Blackwing = "BigWigs_Cataclysm",
BigWigs_DragonSoul = "BigWigs_Cataclysm",
BigWigs_Firelands = "BigWigs_Cataclysm",
BigWigs_Throne = "BigWigs_Cataclysm",
bigwigs_zonozzicons = "BigWigs_Cataclysm",
BigWigs_EndlessSpring = "BigWigs_MistsOfPandaria",
BigWigs_HeartOfFear = "BigWigs_MistsOfPandaria",
BigWigs_Mogushan = "BigWigs_MistsOfPandaria",
BigWigs_Pandaria = "BigWigs_MistsOfPandaria",
BigWigs_SiegeOfOrgrimmar = "BigWigs_MistsOfPandaria",
BigWigs_ThroneOfThunder = "BigWigs_MistsOfPandaria",
BigWigs_Draenor = "BigWigs_WarlordsOfDraenor",
BigWigs_Highmaul = "BigWigs_WarlordsOfDraenor",
BigWigs_BlackrockFoundry = "BigWigs_WarlordsOfDraenor",
BigWigs_HellfireCitadel = "BigWigs_WarlordsOfDraenor",
LittleWigs_ShadoPanMonastery = "LittleWigs",
LittleWigs_ScarletHalls = "LittleWigs",
LittleWigs_ScarletMonastery = "LittleWigs",
LittleWigs_MogushanPalace = "LittleWigs",
LittleWigs_TempleOfTheJadeSerpent = "LittleWigs",
LittleWigs_TBC = "LittleWigs",
LittleWigs_Auchindoun = "LittleWigs",
LittleWigs_Coilfang = "LittleWigs",
LittleWigs_CoT = "LittleWigs",
LittleWigs_HellfireCitadel = "LittleWigs",
LittleWigs_MagistersTerrace = "LittleWigs",
LittleWigs_TempestKeep = "LittleWigs",
LittleWigs_LK = "LittleWigs",
LittleWigs_Coldarra = "LittleWigs",
LittleWigs_Dalaran = "LittleWigs",
LittleWigs_Dragonblight = "LittleWigs",
LittleWigs_Frozen_Halls = "LittleWigs",
LittleWigs_Howling_Fjord = "LittleWigs",
LittleWigs_Icecrown = "LittleWigs",
LittleWigs_Stratholme = "LittleWigs",
LittleWigs_Storm_Peaks = "LittleWigs",
["LittleWigs_Zul'Drak"] = "LittleWigs",
BigWigs_TayakIcons = "BigWigs",
BigWigs_PizzaBar = "BigWigs",
BigWigs_ShaIcons = "BigWigs",
BigWigs_LeiShi_Marker = "BigWigs",
BigWigs_NoPluginWarnings = "BigWigs",
LFG_ProposalTime = "BigWigs",
CourtOfStarsGossipHelper = "LittleWigs",
BigWigs_DispelResist = "Abandoned",
BigWigs_Voice_HeroesOfTheStorm = "BigWigs_Countdown_HeroesOfTheStorm",
BigWigs_Voice_Overwatch = "BigWigs_Countdown_Overwatch",
BigWigs_AutoReply = "BigWigs",
BigWigs_AutoReply2 = "BigWigs",
BigWigs_Antorus = "BigWigs_Legion",
BigWigs_ArgusInvasionPoints = "BigWigs_Legion",
BigWigs_BrokenIsles = "BigWigs_Legion",
BigWigs_Nighthold = "BigWigs_Legion",
BigWigs_Nightmare = "BigWigs_Legion",
BigWigs_TombOfSargeras = "BigWigs_Legion",
BigWigs_TrialOfValor = "BigWigs_Legion",
BigWigs_SiegeOfZuldazar = "BigWigs",
FS_Core = "Abandoned", -- abandoned addon breaking the load order
BigWigs_Azeroth = "BigWigs_BattleForAzeroth",
BigWigs_BattleOfDazaralor = "BigWigs_BattleForAzeroth",
BigWigs_CrucibleOfStorms = "BigWigs_BattleForAzeroth",
BigWigs_EternalPalace = "BigWigs_BattleForAzeroth",
BigWigs_Nyalotha = "BigWigs_BattleForAzeroth",
BigWigs_Uldir = "BigWigs_BattleForAzeroth",
}
local delayedMessages = {}
local warning = "The addon '|cffffff00%s|r' is forcing %s to load prematurely, notify the BigWigs authors!"
local dontForceLoadList = {
BigWigs_Core = true,
BigWigs_Plugins = true,
BigWigs_Options = true,
BigWigs_Shadowlands = true,
BigWigs_CastleNathria = true,
BigWigs_SanctumOfDomination = true,
BigWigs_Classic = true,
BigWigs_BurningCrusade = true,
BigWigs_WrathOfTheLichKing = true,
BigWigs_Cataclysm = true,
BigWigs_MistsOfPandaria = true,
BigWigs_WarlordsOfDraenor = true,
BigWigs_Legion = true,
BigWigs_BattleForAzeroth = true,
LittleWigs = true,
LittleWigs_Classic = true,
LittleWigs_BurningCrusade = true,
LittleWigs_WrathOfTheLichKing = true,
LittleWigs_Cataclysm = true,
LittleWigs_MistsOfPandaria = true,
LittleWigs_WarlordsOfDraenor = true,
LittleWigs_Legion = true,
LittleWigs_BattleForAzeroth = true,
}
-- Try to teach people not to force load our modules.
for i = 1, GetNumAddOns() do
local name = GetAddOnInfo(i)
if IsAddOnEnabled(i) and not IsAddOnLoadOnDemand(i) then
for j = 1, select("#", GetAddOnOptionalDependencies(i)) do
local meta = select(j, GetAddOnOptionalDependencies(i))
local addonName = tostring(meta)
if dontForceLoadList[addonName] then
delayedMessages[#delayedMessages+1] = warning:format(name, addonName)
end
end
for j = 1, select("#", GetAddOnDependencies(i)) do
local meta = select(j, GetAddOnDependencies(i))
local addonName = tostring(meta)
if dontForceLoadList[addonName] then
delayedMessages[#delayedMessages+1] = warning:format(name, addonName)
end
end
end
if old[name] then
delayedMessages[#delayedMessages+1] = L.removeAddon:format(name, old[name])
Popup(L.removeAddon:format(name, old[name]))
end
end
local L = GetLocale()
local locales = {
--ruRU = "Russian (ruRU)",
itIT = "Italian (itIT)",
--koKR = "Korean (koKR)",
esES = "Spanish (esES)",
--esMX = "Spanish (esMX)",
--deDE = "German (deDE)",
--ptBR = "Portuguese (ptBR)",
--frFR = "French (frFR)",
}
if locales[L] then
delayedMessages[#delayedMessages+1] = ("BigWigs is missing translations for %s. Can you help? Visit git.io/vpBye or ask us on Discord for more info."):format(locales[L])
end
if #delayedMessages > 0 then
function mod:LOADING_SCREEN_DISABLED()
bwFrame:UnregisterEvent("LOADING_SCREEN_DISABLED")
CTimerAfter(0, function() -- Timers aren't fully functional until 1 frame after loading is done
CTimerAfter(15, function()
for i = 1, #delayedMessages do
sysprint(delayedMessages[i])
end
delayedMessages = nil
end)
end)
self.LOADING_SCREEN_DISABLED = nil
end
bwFrame:RegisterEvent("LOADING_SCREEN_DISABLED")
end
end
-----------------------------------------------------------------------
-- Callback handler
--
do
local callbackMap = {}
function public:RegisterMessage(msg, func)
if self == BigWigsLoader then
error(".RegisterMessage(addon, message, function) attempted to register a function to BigWigsLoader, you might be using : instead of . to register the callback.")
end
if type(msg) ~= "string" then
error(":RegisterMessage(message, function) attempted to register invalid message, must be a string!")
end
local funcType = type(func)
if funcType == "string" then
if not self[func] then error((":RegisterMessage(message, function) attempted to register the function '%s' but it doesn't exist!"):format(func)) end
elseif funcType == "nil" then
if not self[msg] then error((":RegisterMessage(message, function) attempted to register the function '%s' but it doesn't exist!"):format(msg)) end
elseif funcType ~= "function" then
error(":RegisterMessage(message, function) attempted to register an invalid function!")
end
if not callbackMap[msg] then callbackMap[msg] = {} end
callbackMap[msg][self] = func or msg
end
function public:UnregisterMessage(msg)
if self == BigWigsLoader then
error(".UnregisterMessage(addon, message, function) attempted to unregister a function from BigWigsLoader, you might be using : instead of . to register the callback.")
end
if type(msg) ~= "string" then error(":UnregisterMessage(message) attempted to unregister an invalid message, must be a string!") end
if not callbackMap[msg] then return end
callbackMap[msg][self] = nil
if not next(callbackMap[msg]) then
callbackMap[msg] = nil
end
end
local pcall, geterrorhandler = pcall, geterrorhandler
function public:SendMessage(msg, ...)
if callbackMap[msg] then
for k,v in next, callbackMap[msg] do
if type(v) == "function" then
local success, errorMsg = pcall(v, msg, ...)
if not success then
geterrorhandler()(("BigWigs: One of your addons caused an error on the %q callback:\n%s"):format(msg, errorMsg))
end
else
local success, errorMsg = pcall(k[v], k, msg, ...)
if not success then
geterrorhandler()(("BigWigs: One of your addons caused an error on the %q callback:\n%s"):format(msg, errorMsg))
end
end
end
end
end
local function UnregisterAllMessages(_, module)
for k,v in next, callbackMap do
for j in next, v do
if j == module then
public.UnregisterMessage(module, k)
end
end
end
end
public.RegisterMessage(mod, "BigWigs_OnBossDisable", UnregisterAllMessages)
public.RegisterMessage(mod, "BigWigs_OnBossWipe", UnregisterAllMessages)
public.RegisterMessage(mod, "BigWigs_OnPluginDisable", UnregisterAllMessages)
end
-----------------------------------------------------------------------
-- DBM version collection & faking
--
do
local DBMdotRevision = "20210701004539" -- The changing version of the local client, changes with every new zip using the project-date-integer packager replacement.
local DBMdotDisplayVersion = "9.1.1" -- "N.N.N" for a release and "N.N.N alpha" for the alpha duration.
local DBMdotReleaseRevision = "20210630000000" -- Hardcoded time, manually changed every release, they use it to track the highest release version, a new DBM release is the only time it will change.
local timer, prevUpgradedUser = nil, nil
local function sendMsg()
if IsInGroup() then
SendAddonMessage("D4", "V\t"..DBMdotRevision.."\t"..DBMdotReleaseRevision.."\t"..DBMdotDisplayVersion.."\t"..GetLocale().."\t".."true", IsInGroup(2) and "INSTANCE_CHAT" or "RAID") -- LE_PARTY_CATEGORY_INSTANCE = 2
end
timer, prevUpgradedUser = nil, nil
end
function mod:DBM_VersionCheck(prefix, sender, revision, releaseRevision, displayVersion)
if prefix == "H" and (BigWigs and BigWigs.db and BigWigs.db.profile.fakeDBMVersion or self.isFakingDBM) then
if timer then timer:Cancel() end
timer = CTimerNewTicker(3.3, sendMsg, 1)
elseif prefix == "V" then
usersDBM[sender] = displayVersion
--if BigWigs and BigWigs.db.profile.fakeDBMVersion or self.isFakingDBM then
-- -- If there are people with newer versions than us, suddenly we've upgraded!
-- local rev, dotRev = tonumber(revision), tonumber(DBMdotRevision)
-- if rev and displayVersion and rev ~= 99999 and rev > dotRev and not strfind(displayVersion, "alpha", nil, true) then -- Failsafes
-- if not prevUpgradedUser then
-- prevUpgradedUser = sender
-- elseif prevUpgradedUser ~= sender then
-- DBMdotRevision = revision -- Update our local rev with the highest possible rev found.
-- DBMdotReleaseRevision = releaseRevision -- Update our release rev with the highest found, this should be the same for alpha users and latest release users.
-- DBMdotDisplayVersion = displayVersion -- Update to the latest display version.
-- -- Re-send the addon message.
-- if timer then timer:Cancel() end
-- timer = CTimerNewTicker(1, sendMsg, 1)
-- end
-- end
--end
end
end
function mod:BigWigs_CoreOptionToggled(_, key, value)
if key == "fakeDBMVersion" and value and IsInGroup() then
self:DBM_VersionCheck("H") -- Send addon message if feature is being turned on inside a raid/group.
end
end
public.RegisterMessage(mod, "BigWigs_CoreOptionToggled")
end
-----------------------------------------------------------------------
-- Events
--
bwFrame:SetScript("OnEvent", function(_, event, ...)
mod[event](mod, ...)
end)
bwFrame:RegisterEvent("ADDON_LOADED")
bwFrame:RegisterEvent("UPDATE_FLOATING_CHAT_WINDOWS")
do
-- Role Updating
local prev = 0
function mod:PLAYER_REGEN_ENABLED()
bwFrame:UnregisterEvent("PLAYER_REGEN_ENABLED")
self:ACTIVE_TALENT_GROUP_CHANGED() -- Force role check
end
function mod:ACTIVE_TALENT_GROUP_CHANGED()
if IsInGroup() then
if IsPartyLFG() then return end
local tree = GetSpecialization()
if not tree then return end -- No spec selected
local role = GetSpecializationRole(tree)
if role and UnitGroupRolesAssigned("player") ~= role then
if InCombatLockdown() or UnitAffectingCombat("player") then
bwFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
return
end
-- ACTIVE_TALENT_GROUP_CHANGED fires twice when changing spec, leaving the talent tree, and entering the new tree. We throttle this to prevent a double role chat message.
-- It should only fire once when joining a group (triggered from GROUP_ROSTER_UPDATE)
-- This will fail when logging in/reloading in a group because GetSpecializationRole is nil since WoW v7 when GROUP_ROSTER_UPDATE fires
-- However, your role seems to be saved internally and preserved, so is this really an issue?
local t = GetTime()
if (t-prev) > 2 then
prev = t
UnitSetRole("player", role)
end
end
end
end
end
-- Merged LFG_ProposalTime addon by Freebaser
do
local prev
function mod:LFG_PROPOSAL_SHOW()
if not prev then
local timerBar = CreateFrame("StatusBar", nil, LFGDungeonReadyPopup)
timerBar:SetPoint("TOP", LFGDungeonReadyPopup, "BOTTOM", 0, -5)
local tex = timerBar:CreateTexture()
tex:SetTexture(137012) -- Interface\\TargetingFrame\\UI-StatusBar
timerBar:SetStatusBarTexture(tex)
timerBar:SetSize(190, 9)
timerBar:SetStatusBarColor(1, 0.1, 0)
timerBar:SetMinMaxValues(0, 40)
timerBar:Show()
local bg = timerBar:CreateTexture(nil, "BACKGROUND")
bg:SetAllPoints(timerBar)
bg:SetColorTexture(0, 0, 0, 0.7)
local spark = timerBar:CreateTexture(nil, "OVERLAY")
spark:SetTexture(130877) -- Interface\\CastingBar\\UI-CastingBar-Spark
spark:SetSize(32, 32)
spark:SetBlendMode("ADD")
spark:SetPoint("LEFT", tex, "RIGHT", -15, 0)
local border = timerBar:CreateTexture(nil, "OVERLAY")
border:SetTexture(130874) -- Interface\\CastingBar\\UI-CastingBar-Border
border:SetSize(256, 64)
border:SetPoint("TOP", timerBar, 0, 28)
timerBar.text = timerBar:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
timerBar.text:SetPoint("CENTER", timerBar, "CENTER")
self.LFG_PROPOSAL_SHOW = function()
prev = GetTime() + 40
-- Play in Master for those that have SFX off or very low.
-- Using false as third arg to avoid the "only one of each sound at a time" throttle.
-- Only play via the "Master" channel if we have sounds turned on
if (BigWigs and BigWigs:GetPlugin("Sounds") and BigWigs:GetPlugin("Sounds").db.profile.sound) or self.isSoundOn ~= false then
local _, id = PlaySound(8960, "Master", false) -- SOUNDKIT.READY_CHECK
if id then
StopSound(id-1) -- Should work most of the time to stop the blizz sound
end
end
end
self:LFG_PROPOSAL_SHOW()
timerBar:SetScript("OnUpdate", function(f)
local timeLeft = prev - GetTime()
if timeLeft > 0 then
f:SetValue(timeLeft)
f.text:SetFormattedText("BigWigs: %.1f", timeLeft)
end
end)
-- USE THIS CALLBACK TO SKIN THIS WINDOW! NO NEED FOR UGLY HAX! E.g.
-- local name, addon = ...
-- if BigWigsLoader then
-- BigWigsLoader.RegisterMessage(addon, "BigWigs_FrameCreated", function(event, frame, name) print(name.." frame created.") end)
-- end
public:SendMessage("BigWigs_FrameCreated", timerBar, "QueueTimer")
end
end
end
function mod:CHAT_MSG_ADDON(prefix, msg, channel, sender)
if channel ~= "RAID" and channel ~= "PARTY" and channel ~= "INSTANCE_CHAT" then
return
elseif prefix == "BigWigs" then
local bwPrefix, bwMsg, extra, guildVersion, guildName = strsplit("^", msg)
sender = Ambiguate(sender, "none")
if bwPrefix == "V" or bwPrefix == "Q" then
self:VersionCheck(bwPrefix, bwMsg, extra, guildVersion, guildName, sender)
elseif bwPrefix == "B" then
public:SendMessage("BigWigs_BossComm", bwMsg, extra, sender)
elseif bwPrefix == "P" then
if bwMsg == "Pull" then
local _, _, _, instanceId = UnitPosition("player")
local _, _, _, tarInstanceId = UnitPosition(sender)
if instanceId == tarInstanceId then
loadAndEnableCore() -- Force enable the core when receiving a pull timer.
end
elseif bwMsg == "Break" then
loadAndEnableCore() -- Force enable the core when receiving a break timer.
end
public:SendMessage("BigWigs_PluginComm", bwMsg, extra, sender)
end
elseif prefix == "D4" then
local dbmPrefix, arg1, arg2, arg3, arg4 = strsplit("\t", msg)
sender = Ambiguate(sender, "none")
if dbmPrefix == "V" or dbmPrefix == "H" then
self:DBM_VersionCheck(dbmPrefix, sender, arg1, arg2, arg3)
elseif dbmPrefix == "U" or dbmPrefix == "PT" or dbmPrefix == "M" or dbmPrefix == "BT" then
if dbmPrefix == "PT" then
local _, _, _, instanceId = UnitPosition("player")
local _, _, _, tarInstanceId = UnitPosition(sender)
if instanceId == tarInstanceId then
loadAndEnableCore() -- Force enable the core when receiving a pull timer.
end
elseif dbmPrefix == "BT" then
loadAndEnableCore() -- Force enable the core when receiving a break timer.
end
public:SendMessage("DBM_AddonMessage", sender, dbmPrefix, arg1, arg2, arg3, arg4)
end
end
end
local ResetVersionWarning
do
local timer = nil
local function sendMsg()
if IsInGroup() then
SendAddonMessage("BigWigs", versionResponseString, IsInGroup(2) and "INSTANCE_CHAT" or "RAID") -- LE_PARTY_CATEGORY_INSTANCE = 2
end
timer = nil
end
local hasWarned = 0
local hasGuildWarned = false
local verTimer = nil
local verGuildTimer = nil
function ResetVersionWarning()
hasWarned = 0
hasGuildWarned = false
if verTimer then verTimer:Cancel() end -- We may have left the group whilst a warning is about to show
if verGuildTimer then verGuildTimer:Cancel() end
verTimer = nil
verGuildTimer = nil
end
local function printOutOfDate(tbl)
if hasWarned == 3 then return end
local warnedOutOfDate, warnedReallyOutOfDate, warnedExtremelyOutOfDate = 0, 0, 0
for k,v in next, tbl do
if v > BIGWIGS_VERSION then
warnedOutOfDate = warnedOutOfDate + 1
if (v - 1) > BIGWIGS_VERSION then -- 2+ releases
warnedReallyOutOfDate = warnedReallyOutOfDate + 1
if (v - 2) > BIGWIGS_VERSION then -- 3+ releases
warnedExtremelyOutOfDate = warnedExtremelyOutOfDate + 1
end
end
end
end
if warnedExtremelyOutOfDate > 1 then
if verTimer then verTimer:Cancel() end
verTimer = CTimerNewTicker(3, function()
hasWarned = 3
verTimer = nil
local diff = highestFoundVersion - BIGWIGS_VERSION
if not customGuildName then
local msg = L.warnSeveralReleases:format(diff)
sysprint(msg)
Popup(msg)
RaidNotice_AddMessage(RaidWarningFrame, msg, {r=1,g=1,b=1}, 40)
else
sysprint(L.warnOldBase:format(BIGWIGS_GUILD_VERSION, BIGWIGS_VERSION, diff))
end
end, 1)
elseif warnedReallyOutOfDate > 1 and hasWarned < 2 and not customGuildName then
if verTimer then verTimer:Cancel() end
verTimer = CTimerNewTicker(3, function()
hasWarned = 2
verTimer = nil
sysprint(L.warnTwoReleases)
RaidNotice_AddMessage(RaidWarningFrame, L.warnTwoReleases, {r=1,g=1,b=1}, 20)
end, 1)
elseif warnedOutOfDate > 1 and hasWarned < 1 and not customGuildName then
if verTimer then verTimer:Cancel() end
verTimer = CTimerNewTicker(3, function()
hasWarned = 1
verTimer = nil
sysprint(L.getNewRelease)
end, 1)
end
end
local function printGuildOutOfDate(tbl)
if hasGuildWarned then return end
local warnedOutOfDate = 0
for k,v in next, tbl do
if v > BIGWIGS_GUILD_VERSION and usersGuildName[k] == customGuildName then
warnedOutOfDate = warnedOutOfDate + 1
end
end
if warnedOutOfDate > 1 and not hasGuildWarned then
if verGuildTimer then verGuildTimer:Cancel() end
verGuildTimer = CTimerNewTicker(3, function()
hasGuildWarned = true
verGuildTimer = nil
sysprint(guildWarnMessage)
Popup(guildWarnMessage)
end, 1)
end
end
function mod:VersionCheck(prefix, verString, hash, guildVerString, guildName, sender)
if prefix == "Q" then
if timer then timer:Cancel() end
timer = CTimerNewTicker(3, sendMsg, 1)
end
if prefix == "V" or prefix == "Q" then -- V = version response, Q = version query
local version = tonumber(verString)
if version and version > 0 then -- Allow addons to query BigWigs versions by using a version of 0, but don't add them to the user list.
usersVersion[sender] = version
usersHash[sender] = hash
if version > highestFoundVersion then highestFoundVersion = version end
local guildVersion = tonumber(guildVerString)
if guildVersion and guildVersion > 0 then
usersGuildVersion[sender] = guildVersion
usersGuildName[sender] = guildName
if customGuildName and customGuildName == guildName then
if guildVersion > highestFoundGuildVersion then
highestFoundGuildVersion = guildVersion
end
if guildVersion > BIGWIGS_GUILD_VERSION then
printGuildOutOfDate(usersGuildVersion)
end
end
end
if version > BIGWIGS_VERSION then
printOutOfDate(usersVersion)
end
end
end
end
end
do
local warnedThisZone = {}
function mod:PLAYER_ENTERING_WORLD() -- Raid bosses
-- Zone checking
local _, _, _, _, _, _, _, id = GetInstanceInfo()
-- Module loading
if enableZones[id] then
if loadAndEnableCore() then
loadZone(id)
end
elseif BigWigs3DB and BigWigs3DB.breakTime then -- Break timer restoration
loadAndEnableCore()
else
if disabledZones and disabledZones[id] then -- We have content for the zone but it is disabled in the addons menu
local msg = L.disabledAddOn:format(disabledZones[id])
sysprint(msg)
Popup(msg)
-- Only print once
warnedThisZone[id] = true
disabledZones[id] = nil
end
end
-- Lacking zone modules
if (BigWigs and BigWigs.db.profile.showZoneMessages == false) or self.isShowingZoneMessages == false then return end
local zoneAddon = public.zoneTbl[id]
if zoneAddon and zoneAddon ~= "BigWigs_Shadowlands" then
if strfind(zoneAddon, "LittleWigs_", nil, true) then zoneAddon = "LittleWigs" end -- Collapse into one addon
if id > 0 and not fakeZones[id] and not warnedThisZone[id] and not IsAddOnEnabled(zoneAddon) then
warnedThisZone[id] = true
local msg = L.missingAddOn:format(zoneAddon)
sysprint(msg)
RaidNotice_AddMessage(RaidWarningFrame, msg, {r=1,g=1,b=1}, 15)
end
end
end
end
do
function mod:UNIT_TARGET(unit)
local unitTarget = unit.."target"
local guid = UnitGUID(unitTarget)
if guid then
local _, _, _, _, _, mobId = strsplit("-", guid)
mobId = tonumber(mobId)
local id = mobId and worldBosses[mobId]
if id and loadAndEnableCore() then
loadZone(id)
BigWigs:Enable(unitTarget)
end
end
end
function mod:ZONE_CHANGED() -- For world bosses, not useful for raids as it fires after loading has ended
local id = 0
local mapId = GetBestMapForUnit("player")
if mapId then
id = -mapId -- Use map id for world bosses
end
-- Module loading
if enableZones[id] == "world" then
bwFrame:RegisterEvent("UNIT_TARGET")
else
bwFrame:UnregisterEvent("UNIT_TARGET")
end
end
end
do
local grouped = nil
function mod:GROUP_ROSTER_UPDATE()
local groupType = (IsInGroup(2) and 3) or (IsInRaid() and 2) or (IsInGroup() and 1) -- LE_PARTY_CATEGORY_INSTANCE = 2
if (not grouped and groupType) or (grouped and groupType and grouped ~= groupType) then
grouped = groupType
SendAddonMessage("BigWigs", versionQueryString, groupType == 3 and "INSTANCE_CHAT" or "RAID")
SendAddonMessage("D4", "H\t", groupType == 3 and "INSTANCE_CHAT" or "RAID") -- Also request DBM versions
self:ACTIVE_TALENT_GROUP_CHANGED() -- Force role check
elseif grouped and not groupType then
grouped = nil
ResetVersionWarning()
usersVersion = {}
usersHash = {}
end
end
end
function mod:BigWigs_BossModuleRegistered(_, _, module)
if module.worldBoss then
local id = -(module.mapId)
enableZones[id] = "world"
worldBosses[module.worldBoss] = id
else
enableZones[module.instanceId] = true
end
local id = module.otherMenu or module.instanceId or -(module.mapId)
if type(menus[id]) ~= "table" then menus[id] = {} end
menus[id][#menus[id]+1] = module
end
public.RegisterMessage(mod, "BigWigs_BossModuleRegistered")
function mod:BigWigs_CoreEnabled()
dataBroker.icon = "Interface\\AddOns\\BigWigs\\Media\\Icons\\core-enabled"
-- Send a version query on enable, should fix issues with joining a group then zoning into an instance,
-- which kills your ability to receive addon comms during the loading process.
if IsInGroup() then
SendAddonMessage("BigWigs", versionQueryString, IsInGroup(2) and "INSTANCE_CHAT" or "RAID")
SendAddonMessage("D4", "H\t", IsInGroup(2) and "INSTANCE_CHAT" or "RAID") -- Also request DBM versions
end
-- Core is loaded, nil these to force checking BigWigs.db.profile.option
self.isFakingDBM = nil
self.isShowingZoneMessages = nil
self.isSoundOn = nil
end
public.RegisterMessage(mod, "BigWigs_CoreEnabled")
function mod:BigWigs_CoreDisabled()
dataBroker.icon = "Interface\\AddOns\\BigWigs\\Media\\Icons\\core-disabled"
end
public.RegisterMessage(mod, "BigWigs_CoreDisabled")
-----------------------------------------------------------------------
-- API
--
function public:RegisterTooltipInfo(func)
for i = 1, #tooltipFunctions do
if tooltipFunctions[i] == func then
error(("The function %q has already been registered."):format(func))
end
end
tooltipFunctions[#tooltipFunctions+1] = func
end
function public:GetReleaseString()
return BIGWIGS_RELEASE_STRING
end
function public:GetVersionString()
return BIGWIGS_VERSION_STRING
end
function public:GetZoneMenus()
return menus
end
function public:LoadZone(zone)
loadZone(zone)
end
-----------------------------------------------------------------------
-- Slash commands
--
SLASH_BigWigs1 = "/bw"
SLASH_BigWigs2 = "/bigwigs"
SlashCmdList.BigWigs = function()
-- If you are a dev and need the BigWigs options loaded to do something, please come talk to us on Discord about your use case
--local trace = debugstack(2)
--if strfind(trace, "[string \"*:OnEnterPressed\"]:1: in function <[string \"*:OnEnterPressed\"]:1>", nil, true) then
loadCoreAndOpenOptions()
--else
-- public.stack = trace
-- sysprint("|cFFff0000WARNING!|r")
-- sysprint("One of your addons was prevented from force loading the BigWigs options.")
-- sysprint("Contact us on the BigWigs Discord about this, it should not be happening.")
-- return
--end
end
SLASH_BigWigsVersion1 = "/bwv"
SlashCmdList.BigWigsVersion = function()
if not IsInGroup() then
sysprint(BIGWIGS_RELEASE_STRING)
return
end
local function coloredNameVersion(name, version, hash, guildVersion)
if not version then
version = ""
elseif guildVersion then
version = ("|cFFCCCCCC(%d/%d%s)|r"):format(guildVersion, version, hash and "-"..hash or "") -- %d because BigWigs versions are always stored as a number
else
version = ("|cFFCCCCCC(%s%s)|r"):format(version, hash and "-"..hash or "") -- %s because DBM users are stored as a string
end
local _, class = UnitClass(name)
local tbl = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class] or GRAY_FONT_COLOR
name = name:gsub("%-.+", "*") -- Replace server names with *
return ("|cFF%02x%02x%02x%s|r%s"):format(tbl.r*255, tbl.g*255, tbl.b*255, name, version)
end
local list = {}
local unit
if not IsInRaid() then
list[1] = UnitName("player")
unit = "party%d"
else
unit = "raid%d"
end
for i = 1, GetNumGroupMembers() do
local n, s = UnitName((unit):format(i))
if n and s and s ~= "" then n = n.."-"..s end
if n then list[#list+1] = n end
end
local good = {} -- highest release users
local ugly = {} -- old version users
local bad = {} -- no boss mod
local dbm = {} -- DBM users
for i = 1, #list do
local player = list[i]
local usesBossMod = nil
if usersVersion[player] then
usesBossMod = true
if customGuildName == usersGuildName[player] then
if usersGuildVersion[player] < highestFoundGuildVersion then
ugly[#ugly + 1] = coloredNameVersion(player, usersVersion[player], usersHash[player], usersGuildVersion[player])
else
good[#good + 1] = coloredNameVersion(player, usersVersion[player], usersHash[player], usersGuildVersion[player])
end
else
if usersVersion[player] < highestFoundVersion then
ugly[#ugly + 1] = coloredNameVersion(player, usersVersion[player], usersHash[player])
else
good[#good + 1] = coloredNameVersion(player, usersVersion[player], usersHash[player])
end
end
end
if usersDBM[player] then
dbm[#dbm+1] = coloredNameVersion(player, usersDBM[player])
usesBossMod = true
end
if not usesBossMod then
bad[#bad+1] = coloredNameVersion(player, UnitIsConnected(player) == false and L.offline)
end
end
if #good > 0 then print(L.upToDate, unpack(good)) end
if #ugly > 0 then print(L.outOfDate, unpack(ugly)) end
if #dbm > 0 then print(L.dbmUsers, unpack(dbm)) end
if #bad > 0 then print(L.noBossMod, unpack(bad)) end
end
-------------------------------------------------------------------------------
-- Global
--
BigWigsLoader = setmetatable({}, { __index = public, __newindex = function() end, __metatable = false })