diff --git a/.luacheckrc b/.luacheckrc index 5b49191..7a72e8b 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -37,11 +37,13 @@ globals = { "C_GossipInfo", "C_Map", "C_PvP", + "C_Seasons", "C_Timer", "C_UIWidgetManager", "C_VignetteInfo", "CompleteQuest", "CreateFrame", + "Enum", "GetBattlefieldInstanceRunTime", "GetCurrencyInfo", "GetItemCount", diff --git a/DBM-PvP/Ashenvale.lua b/DBM-PvP/Ashenvale.lua new file mode 100644 index 0000000..24b6238 --- /dev/null +++ b/DBM-PvP/Ashenvale.lua @@ -0,0 +1,89 @@ +if WOW_PROJECT_ID ~= WOW_PROJECT_CLASSIC or not C_Seasons or C_Seasons.GetActiveSeason() < 2 then + return +end +local MAP_ASHENVALE = 1440 +local mod = DBM:NewMod("m" .. MAP_ASHENVALE, "DBM-PvP") + +mod:SetRevision("@file-date-integer@") +-- TODO: we could teach this thing to handle outdoor zones instead of only instances +-- when implementing this make sure that the stop functions are called properly, i.e., that ZONE_CHANGED_NEW_AREA still fires when leaving +mod:SetZone(DBM_DISABLE_ZONE_DETECTION) +mod:RegisterEvents( + "LOADING_SCREEN_DISABLED", + "ZONE_CHANGED_NEW_AREA", + "PLAYER_ENTERING_WORLD", + "UPDATE_UI_WIDGET" +) + +local widgetIDs = { + [5360] = true, -- Alliance progress + [5361] = true, -- Horde progress + [5367] = true, -- Alliance bosses remaining + [5368] = true, -- Horde bosses remaining + [5378] = true, -- Event time remaining +} + +function mod:StartEvent() + DBM:Debug("Detected start of Ashenvale event") + local generalMod = DBM:GetModByName("PvPGeneral") + generalMod:StopTrackHealth() + generalMod:TrackHealth(212804, "RunestoneBoss", true, "YELL") + generalMod:TrackHealth(212707, "GlaiveBoss", true, "YELL") + generalMod:TrackHealth(212803, "ResearchBoss", true, "YELL") + generalMod:TrackHealth(212970, "MoonwellBoss", true, "YELL") + generalMod:TrackHealth(212801, "ShredderBoss", true, "YELL") + generalMod:TrackHealth(212730, "CatapultBoss", true, "YELL") + generalMod:TrackHealth(212802, "LumberBoss", true, "YELL") + generalMod:TrackHealth(212969, "BonfireBoss", true, "YELL") +end + +function mod:StopEvent() + DBM:Debug("Detected end of Ashenvale event or leaving zone") + local generalMod = DBM:GetModByName("PvPGeneral") + generalMod:StopTrackHealth() +end + +function mod:CheckEventState() + local eventTime = C_UIWidgetManager.GetIconAndTextWidgetVisualizationInfo(5378) + if eventTime and eventTime.state ~= Enum.IconAndTextWidgetState.Hidden then + if not self.eventRunning then + self.eventRunning = true + self:StartEvent() + end + elseif self.eventRunning then + self.eventRunning = false + self:StopEvent() + end +end + +function mod:UPDATE_UI_WIDGET(tbl) + if not self.inZone then + return + end + if tbl and widgetIDs[tbl.widgetID] then + self:CheckEventState() + end +end + +function mod:EnterAshenvale() + self.inZone = true + self:CheckEventState() +end + +function mod:LeaveAshenvale() + self.inZone = false + self:StopEvent() +end + +function mod:ZoneChanged() + local map = C_Map.GetBestMapForUnit("player") + if map == MAP_ASHENVALE and not self.inZone then + self:EnterAshenvale() + elseif map ~= MAP_ASHENVALE and self.inZone then + self:LeaveAshenvale() + end +end +mod.LOADING_SCREEN_DISABLED = mod.ZoneChanged +mod.ZONE_CHANGED_NEW_AREA = mod.ZoneChanged +mod.PLAYER_ENTERING_WORLD = mod.ZoneChanged +mod.OnInitialize = mod.ZoneChanged diff --git a/DBM-PvP/DBM-PvP.toc b/DBM-PvP/DBM-PvP.toc index c56191b..641e54d 100644 --- a/DBM-PvP/DBM-PvP.toc +++ b/DBM-PvP/DBM-PvP.toc @@ -50,6 +50,7 @@ localization.tw.lua PvPGeneral.lua +Ashenvale.lua Battlegrounds\Alterac.lua Battlegrounds\Arathi.lua Battlegrounds\Deepwind.lua diff --git a/DBM-PvP/PvPGeneral.lua b/DBM-PvP/PvPGeneral.lua index 8bbd333..4e69c21 100644 --- a/DBM-PvP/PvPGeneral.lua +++ b/DBM-PvP/PvPGeneral.lua @@ -118,41 +118,62 @@ do end do - local pairs, strsplit, tostring, format, twipe = pairs, strsplit, tostring, string.format, table.wipe + local strsplit, format, twipe = strsplit, string.format, table.wipe local UnitGUID, UnitHealth, UnitHealthMax, SendAddonMessage, RegisterAddonMessagePrefix, IsAddonMessagePrefixRegistered, NewTicker = UnitGUID, UnitHealth, UnitHealthMax, C_ChatInfo.SendAddonMessage, C_ChatInfo.RegisterAddonMessagePrefix, C_ChatInfo.IsAddonMessagePrefixRegistered, C_Timer.NewTicker - local healthScan, trackedUnits, trackedUnitsCount, syncTrackedUnits = nil, {}, 0, {} + local healthScan, trackedUnits, trackedUnitsCount, syncTrackedUnits, sortedTrackedUnits = nil, {}, 0, {}, {} local function UpdateInfoFrame() local lines, sortedLines = {}, {} - for cid, health in pairs(syncTrackedUnits) do - if trackedUnits[cid] then - lines[trackedUnits[cid]] = health .. "%" - sortedLines[#sortedLines + 1] = trackedUnits[cid] + for _, cid in ipairs(sortedTrackedUnits) do + local health = syncTrackedUnits[cid] + local hp = health and health.hp or 100 + local lastUpdate = GetTime() - (health and health.time or 0) + if lastUpdate < 60 then + lines[trackedUnits[cid]] = ("%d%%"):format(hp) + else + lines[trackedUnits[cid]] = ("(stale) %d%%"):format(hp) end + sortedLines[#sortedLines + 1] = trackedUnits[cid] end return lines, sortedLines end + local scanTargetsRaid = {"target"} + local scanTargetsWithNameplates = {"target"} + for i = 1, 40 do + scanTargetsRaid[#scanTargetsRaid + 1] = "raid" .. i .. "target" + scanTargetsWithNameplates[#scanTargetsWithNameplates + 1] = "raid" .. i .. "target" + scanTargetsWithNameplates[#scanTargetsWithNameplates + 1] = "nameplate" .. i + end + + local function sendSync(cid, hp) + hp = math.floor(hp + 0.5) + if not syncTrackedUnits[cid] or syncTrackedUnits[cid].hp ~= hp then + SendAddonMessage("DBM-PvP", format("%s:%d", cid, hp), mod.syncChannel) + end + end + local function HealthScanFunc() local syncs, syncCount = {}, 0 - for i = 1, 40 do + for _, target in ipairs(mod.scanNameplates and scanTargetsWithNameplates or scanTargetsRaid) do if syncCount >= trackedUnitsCount then -- We've already scanned all our tracked units, exit out to save CPU break end - local target = "raid" .. i .. "target" local guid = UnitGUID(target) if guid then local cid = mod:GetCIDFromGUID(guid) if trackedUnits[cid] and not syncs[cid] then syncs[cid] = true syncCount = syncCount + 1 - SendAddonMessage("DBM-PvP", format("%s:%.1f", cid, UnitHealth(target) / UnitHealthMax(target) * 100), "INSTANCE_CHAT") + sendSync(cid, UnitHealth(target) / UnitHealthMax(target) * 100) end end end end - function mod:TrackHealth(cid, name) + function mod:TrackHealth(cid, name, scanNameplates, syncChannel) + self.scanNameplates = scanNameplates + self.syncChannel = syncChannel or "INSTANCE_CHAT" if not healthScan then healthScan = NewTicker(1, HealthScanFunc) RegisterAddonMessagePrefix("DBM-PvP") @@ -160,8 +181,9 @@ do RegisterAddonMessagePrefix("Capping") -- Listen to capping for extra data end end - trackedUnits[tostring(cid)] = L[name] or name + trackedUnits[cid] = L[name] or name trackedUnitsCount = trackedUnitsCount + 1 + sortedTrackedUnits[#sortedTrackedUnits + 1] = cid self:RegisterShortTermEvents("CHAT_MSG_ADDON") if not DBM.InfoFrame:IsShown() then DBM.InfoFrame:SetHeader(L.InfoFrameHeader) @@ -178,16 +200,26 @@ do trackedUnitsCount = 0 twipe(trackedUnits) twipe(syncTrackedUnits) + twipe(sortedTrackedUnits) + self.scanNameplates = nil + self.syncChannel = nil self:UnregisterShortTermEvents() DBM.InfoFrame:Hide() end function mod:CHAT_MSG_ADDON(prefix, msg, channel) - if channel ~= "INSTANCE_CHAT" or (prefix ~= "DBM-PvP" and prefix ~= "Capping") then -- Lets listen to capping as well, for extra data. + if channel ~= self.syncChannel or (prefix ~= "DBM-PvP" and prefix ~= "Capping") then -- Lets listen to capping as well, for extra data. return end local cid, hp = strsplit(":", msg) - syncTrackedUnits[cid] = hp + if cid and tonumber(cid) and hp and tonumber(hp) and tonumber(hp) >= 0 and tonumber(hp) <= 100 then + hp = tonumber(hp) + cid = tonumber(cid) + local tbl = syncTrackedUnits[cid] or {} + syncTrackedUnits[cid] = tbl + tbl.hp = math.floor(hp + 0.5) + tbl.time = GetTime() + end end end diff --git a/DBM-PvP/localization.de.lua b/DBM-PvP/localization.de.lua index 5a1e202..4b80cfd 100644 --- a/DBM-PvP/localization.de.lua +++ b/DBM-PvP/localization.de.lua @@ -28,7 +28,10 @@ L:SetMiscLocalization({ ExprFlagCaptured = "(.+) hat die Flagge der (%w+) errungen!", ExprFlagReturn = "Die Flagge der (%w+) wurde von (.+) zu ihrem Stützpunkt zurückgebracht!", Vulnerable1 = "Eure Angriffe verursachen nun schwerere Verletzungen bei Flaggenträgern!", - Vulnerable2 = "Eure Angriffe verursachen nun sehr schwere Verletzungen bei Flaggenträgern!" + Vulnerable2 = "Eure Angriffe verursachen nun sehr schwere Verletzungen bei Flaggenträgern!", + InfoFrameHeader = "[DBM] Boss HP", + HordeBoss = "Horde-Boss", + AllianceBoss = "Allianz-Boss", }) ---------------------- -- Alterac Valley -- diff --git a/DBM-PvP/localization.en.lua b/DBM-PvP/localization.en.lua index 2bcfb9d..f99cd5e 100644 --- a/DBM-PvP/localization.en.lua +++ b/DBM-PvP/localization.en.lua @@ -52,14 +52,22 @@ L:SetMiscLocalization({ ExprFlagReturn = "The (%w+) Flag was returned to its base by (.+)!", -- Unused Vulnerable1 = "The flag carriers have become vulnerable to attack!", Vulnerable2 = "The flag carriers have become increasingly vulnerable to attack!", - -- Alterac/IsleOfConquest bosses - InfoFrameHeader = "Boss Health", + -- Alterac/IsleOfConquest/Ashenvale bosses + InfoFrameHeader = "[DBM] Boss Health", HordeBoss = "Horde Boss", AllianceBoss = "Alliance Boss", Galvangar = "Galvangar", Balinda = "Balinda", Ivus = "Ivus", Lokholar = "Lokholar", + RunestoneBoss = "Runestone", + GlaiveBoss = "Glaive", + ResearchBoss = "Research", + MoonwellBoss = "Moonwell", + ShredderBoss = "Shredder", + CatapultBoss = "Catapult", + LumberBoss = "Lumber", + BonfireBoss = "Bonfire", -- Ashran bosses Tremblade = "Grand Marshall Tremblade", Volrath = "High WArlord Volrath",