local _, private = ... local isRetail = WOW_PROJECT_ID == (WOW_PROJECT_MAINLINE or 1) local L = DBM_CORE_L local LibStub = _G["LibStub"] local LibLatency, LibDurability = LibStub("LibLatency", true), LibStub("LibDurability", true) local function Pull(timer) local LFGTankException = isRetail and IsPartyLFG() and UnitGroupRolesAssigned("player") == "TANK"--Tanks in LFG need to be able to send pull timer even if someone refuses to pass lead. LFG locks roles so no one can abuse this. if (DBM:GetRaidRank() == 0 and IsInGroup() and not LFGTankException) or select(2, IsInInstance()) == "pvp" or IsEncounterInProgress() then return DBM:AddMsg(L.ERROR_NO_PERMISSION) end if timer > 0 and timer < 3 then return DBM:AddMsg(L.TIME_TOO_SHORT) end local targetName = (UnitExists("target") and UnitIsEnemy("player", "target")) and UnitName("target") or nil--Filter non enemies in case player isn't targetting bos but another player/pet if targetName then private.sendSync("PT", timer .. "\t" .. DBM:GetCurrentArea() .. "\t" .. targetName) else private.sendSync("PT", timer .. "\t" .. DBM:GetCurrentArea()) end end local function Break(timer) if IsInGroup() and (DBM:GetRaidRank() == 0 or (isRetail and IsPartyLFG())) or IsEncounterInProgress() or select(2, IsInInstance()) == "pvp" then--No break timers if not assistant or if it's dungeon/raid finder/BG DBM:AddMsg(L.ERROR_NO_PERMISSION) return end if timer > 60 then DBM:AddMsg(L.BREAK_USAGE) return end private.sendSync("BT", timer * 60) end local ShowLag, ShowDurability do local tconcat, tinsert, tsort = table.concat, table.insert, table.sort local function SortLag(v1, v2) return (v1.worldlag or 0) < (v2.worldlag or 0) end function ShowLag() local sortLag, noLagResponse = {}, {} for _, v in pairs(DBM:GetRaidRoster()) do tinsert(sortLag, v) end tsort(sortLag, SortLag) DBM:AddMsg(L.LAG_HEADER) for _, v in ipairs(sortLag) do local name = v.name local playerColor = RAID_CLASS_COLORS[DBM:GetRaidClass(name)] if playerColor then name = ("|r|cff%.2x%.2x%.2x%s|r|cff%.2x%.2x%.2x"):format(playerColor.r * 255, playerColor.g * 255, playerColor.b * 255, name, 0.41 * 255, 0.8 * 255, 0.94 * 255) end if v.worldlag then DBM:AddMsg(L.LAG_ENTRY:format(name, v.worldlag, v.homelag), false) else tinsert(noLagResponse, v.name) end end if #noLagResponse > 0 then DBM:AddMsg(L.LAG_FOOTER:format(tconcat(noLagResponse, ", ")), false) end end if LibLatency then LibLatency:Register("DBM", function(homelag, worldlag, sender) if not sender then return end local player = DBM:GetRaidRoster()[sender] if player then player.homelag = homelag player.worldlag = worldlag end end) end local function SortDurability(v1, v2) return (v1.durpercent or 0) < (v2.durpercent or 0) end function ShowDurability() local sortDur, noDurResponse = {}, {} for _, v in pairs(DBM:GetRaidRoster()) do tinsert(sortDur, v) end tsort(sortDur, SortDurability) DBM:AddMsg(L.DUR_HEADER) for _, v in ipairs(sortDur) do local name = v.name local playerColor = RAID_CLASS_COLORS[DBM:GetRaidClass(name)] if playerColor then name = ("|r|cff%.2x%.2x%.2x%s|r|cff%.2x%.2x%.2x"):format(playerColor.r * 255, playerColor.g * 255, playerColor.b * 255, name, 0.41 * 255, 0.8 * 255, 0.94 * 255) end if v.durpercent then DBM:AddMsg(L.DUR_ENTRY:format(name, v.durpercent, v.durbroken), false) else tinsert(noDurResponse, v.name) end end if #noDurResponse > 0 then DBM:AddMsg(L.LAG_FOOTER:format(tconcat(noDurResponse, ", ")), false) end end if LibDurability then LibDurability:Register("DBM", function(percent, broken, sender) if not sender then return end local player = DBM:GetRaidRoster()[sender] if player then player.durpercent = percent player.durbroken = broken end end) end end if not _G["BigWigs"] then --Register pull and break slash commands for BW converts, if BW isn't loaded --This shouldn't raise an issue since BW SHOULD load before DBM in any case they are both present. SLASH_DEADLYBOSSMODSPULL1 = "/pull" SlashCmdList["DEADLYBOSSMODSPULL"] = function(msg) Pull(tonumber(msg) or 10) end SLASH_DEADLYBOSSMODSBREAK1 = "/break" SlashCmdList["DEADLYBOSSMODSBREAK"] = function(msg) Break(tonumber(msg) or 10) end end SLASH_DEADLYBOSSMODSRPULL1 = "/rpull" SlashCmdList["DEADLYBOSSMODSRPULL"] = function() Pull(30) end local trackedHudMarkers = {} SLASH_DEADLYBOSSMODS1 = "/dbm" SlashCmdList["DEADLYBOSSMODS"] = function(msg) local cmd = msg:lower() if cmd == "ver" or cmd == "version" then DBM:ShowVersions(false) elseif cmd == "ver2" or cmd == "version2" then DBM:ShowVersions(true) elseif cmd == "unlock" or cmd == "move" then DBT:ShowMovableBar() elseif cmd == "help2" then for _, v in ipairs(L.SLASHCMD_HELP2) do DBM:AddMsg(v) end elseif cmd == "help" then for _, v in ipairs(L.SLASHCMD_HELP) do DBM:AddMsg(v) end elseif cmd:sub(1, 13) == "timer endloop" then DBM:CreatePizzaTimer(time, "", nil, nil, nil, true) elseif cmd:sub(1, 5) == "timer" then local time, text = msg:match("^%w+ ([%d:]+) (.+)$") if not time and not text then for _, v in ipairs(L.TIMER_USAGE) do DBM:AddMsg(v) end return end local min, sec = string.split(":", time) min = tonumber(min or "") or 0 sec = tonumber(sec or "") if min and not sec then sec = min min = 0 end DBM:CreatePizzaTimer(min * 60 + sec, text) elseif cmd:sub(1, 6) == "ltimer" then local time, text = msg:match("^%w+ ([%d:]+) (.+)$") if not time and not text then DBM:AddMsg(L.PIZZA_ERROR_USAGE) return end local min, sec = string.split(":", time) min = tonumber(min or "") or 0 sec = tonumber(sec or "") if min and not sec then sec = min min = 0 end DBM:CreatePizzaTimer(min * 60 + sec, text, nil, nil, true) elseif cmd:sub(1, 15) == "broadcast timer" then--Standard Timer local difficultyIndex = DBM:GetCurrentDifficulty() local permission = true if DBM:GetRaidRank() == 0 or difficultyIndex == 7 or difficultyIndex == 17 then DBM:AddMsg(L.ERROR_NO_PERMISSION) permission = false end local time, text = msg:match("^%w+ %w+ ([%d:]+) (.+)$") if not time and not text then DBM:AddMsg(L.PIZZA_ERROR_USAGE) return end local min, sec = string.split(":", time) min = tonumber(min or "") or 0 sec = tonumber(sec or "") if min and not sec then sec = min min = 0 end DBM:CreatePizzaTimer(min * 60 + sec, text, permission) elseif cmd:sub(1, 16) == "broadcast ltimer" then local difficultyIndex = DBM:GetCurrentDifficulty() local permission = true if DBM:GetRaidRank() == 0 or difficultyIndex == 7 or difficultyIndex == 17 then DBM:AddMsg(L.ERROR_NO_PERMISSION) permission = false end local time, text = msg:match("^%w+ %w+ ([%d:]+) (.+)$") if not time and not text then DBM:AddMsg(L.PIZZA_ERROR_USAGE) return end local min, sec = string.split(":", time) min = tonumber(min or "") or 0 sec = tonumber(sec or "") if min and not sec then sec = min min = 0 end DBM:CreatePizzaTimer(min * 60 + sec, text, permission, nil, true) elseif cmd:sub(0,5) == "break" then Break(tonumber(cmd:sub(6)) or 5) elseif cmd:sub(1, 4) == "pull" then Pull(tonumber(cmd:sub(5)) or 10) elseif cmd:sub(1, 5) == "rpull" then Pull(30) elseif cmd:sub(1, 3) == "lag" then if not LibLatency then DBM:AddMsg(L.UPDATE_REQUIRES_RELAUNCH) return end LibLatency:RequestLatency() DBM:AddMsg(L.LAG_CHECKING) C_Timer.After(5, ShowLag) elseif cmd:sub(1, 10) == "durability" then if not LibDurability then DBM:AddMsg(L.UPDATE_REQUIRES_RELAUNCH) return end LibDurability:RequestDurability() DBM:AddMsg(L.DUR_CHECKING) C_Timer.After(5, ShowDurability) elseif cmd:sub(1, 3) == "hud" then if DBM:HasMapRestrictions() then DBM:AddMsg(L.NO_HUD) return end local hudType, target, duration = string.split(" ", cmd:sub(4):trim()) if hudType == "" then for _, v in ipairs(L.HUD_USAGE) do DBM:AddMsg(v) end return end local hudDuration = tonumber(duration) or 1200 -- If no duration defined. 20 minutes to cover even longest of fights if type(hudType) == "string" and hudType:trim() ~= "" then if hudType == "hide" then for _, name in ipairs(trackedHudMarkers) do DBM.HudMap:FreeEncounterMarkerByTarget(12345, name) end table.wipe(trackedHudMarkers) return end if not target then DBM:AddMsg(L.HUD_INVALID_TARGET) return end local uId if target == "target" and UnitExists("target") then uId = "target" elseif isRetail and target == "focus" and UnitExists("focus") then uId = "focus" else -- Try to use it as player name uId = DBM:GetRaidUnitId(target) end if not uId then DBM:AddMsg(L.HUD_INVALID_TARGET) return end if UnitIsUnit("player", uId) and not DBM.Options.DebugMode then -- Don't allow hud to self, except if debug mode is enabled, then hud to self useful for testing DBM:AddMsg(L.HUD_INVALID_SELF) return end local targetName = UnitName(uId) if hudType == "arrow" then local playerName = UnitName("player") local _, targetClass = UnitClass(uId) local color2 = RAID_CLASS_COLORS[targetClass] local m1 = DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, "party", playerName, 0.1, hudDuration, 0, 1, 0, 1, nil, false):Appear() local m2 = DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, "party", targetName, 0.75, hudDuration, color2.r, color2.g, color2.b, 1, nil, false):Appear() tinsert(trackedHudMarkers, playerName) tinsert(trackedHudMarkers, targetName) m2:EdgeTo(m1, nil, hudDuration, 0, 1, 0, 1) DBM:AddMsg(L.HUD_SUCCESS:format(DBM:strFromTime(hudDuration))) elseif hudType == "dot" then local _, targetClass = UnitClass(uId) local color2 = RAID_CLASS_COLORS[targetClass] DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, "party", targetName, 0.75, hudDuration, color2.r, color2.g, color2.b, 1, nil, false):Appear() tinsert(trackedHudMarkers, targetName) DBM:AddMsg(L.HUD_SUCCESS:format(DBM:strFromTime(hudDuration))) elseif hudType == "green" then DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, "highlight", targetName, 3.5, hudDuration, 0, 1, 0, 0.5, nil, false):Pulse(0.5, 0.5) tinsert(trackedHudMarkers, targetName) DBM:AddMsg(L.HUD_SUCCESS:format(DBM:strFromTime(hudDuration))) elseif hudType == "red" then DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, "highlight", targetName, 3.5, hudDuration, 1, 0, 0, 0.5, nil, false):Pulse(0.5, 0.5) tinsert(trackedHudMarkers, targetName) DBM:AddMsg(L.HUD_SUCCESS:format(DBM:strFromTime(hudDuration))) elseif hudType == "yellow" then DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, "highlight", targetName, 3.5, hudDuration, 1, 1, 0, 0.5, nil, false):Pulse(0.5, 0.5) tinsert(trackedHudMarkers, targetName) DBM:AddMsg(L.HUD_SUCCESS:format(DBM:strFromTime(hudDuration))) elseif hudType == "blue" then DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, "highlight", targetName, 3.5, hudDuration, 0, 0, 1, 0.5, nil, false):Pulse(0.5, 0.5) tinsert(trackedHudMarkers, targetName) DBM:AddMsg(L.HUD_SUCCESS:format(DBM:strFromTime(hudDuration))) elseif hudType == "icon" then local icon = GetRaidTargetIndex(uId) if not icon then DBM:AddMsg(L.HUD_INVALID_ICON) return end DBM.HudMap:RegisterRangeMarkerOnPartyMember(12345, DBM:IconNumToString(icon):lower(), targetName, 3.5, hudDuration, 1, 1, 1, 0.5, nil, false):Pulse(0.5, 0.5) tinsert(trackedHudMarkers, targetName) DBM:AddMsg(L.HUD_SUCCESS:format(DBM:strFromTime(hudDuration))) else DBM:AddMsg(L.HUD_INVALID_TYPE) end end elseif cmd:sub(1, 5) == "arrow" then if DBM:HasMapRestrictions() then DBM:AddMsg(L.NO_ARROW) return end local x, y, z = string.split(" ", cmd:sub(6):trim()) local xNum, yNum, zNum = tonumber(x or ""), tonumber(y or ""), tonumber(z or "") if xNum and yNum then DBM.Arrow:ShowRunTo(xNum, yNum, 0) return elseif type(x) == "string" and x:trim() ~= "" then local subCmd = x:trim() if subCmd== "hide" then DBM.Arrow:Hide() return elseif subCmd == "move" then DBM.Arrow:Move() return elseif subCmd == "target" then DBM.Arrow:ShowRunTo("target") return elseif isRetail and subCmd == "focus" then DBM.Arrow:ShowRunTo("focus") return elseif subCmd == "map" then DBM.Arrow:ShowRunTo(yNum, zNum, 0, nil, true) return elseif DBM:GetRaidUnitId(subCmd) then DBM.Arrow:ShowRunTo(subCmd) return end end for _, v in ipairs(L.ARROW_ERROR_USAGE) do DBM:AddMsg(v) end elseif cmd:sub(1, 10) == "debuglevel" then local level = tonumber(cmd:sub(11)) or 1 if level < 1 or level > 3 then DBM:AddMsg("Invalid Value. Debug Level must be between 1 and 3.") return end DBM.Options.DebugLevel = level DBM:AddMsg("Debug Level is " .. level) elseif cmd:sub(1, 5) == "debug" then DBM.Options.DebugMode = not DBM.Options.DebugMode DBM:AddMsg("Debug Message is " .. (DBM.Options.DebugMode and "ON" or "OFF")) private:GetModule("DevTools"):OnDebugToggle() elseif cmd:sub(1, 4) == "test" then DBM:DemoMode() elseif cmd:sub(1, 8) == "whereiam" or cmd:sub(1, 8) == "whereami" then local x, y, _, map = UnitPosition("player") local mapID = C_Map.GetBestMapForUnit("player") or "nil" if DBM:HasMapRestrictions() then DBM:AddMsg(("Location Information\nYou are at zone %u (%s).\nLocal Map ID %u (%s)"):format(map, GetRealZoneText(map), mapID, GetZoneText())) else local pos = C_Map.GetPlayerMapPosition(mapID, "player") DBM:AddMsg(("Location Information\nYou are at zone %u (%s): x=%f, y=%f.\nLocal Map ID %u (%s): x=%f, y=%f"):format(map, GetRealZoneText(map), x, y, mapID, GetZoneText(), pos.x, pos.y)) end elseif cmd:sub(1, 7) == "request" then DBM:Unschedule(DBM.RequestTimers) DBM:RequestTimers(1) DBM:RequestTimers(2) DBM:RequestTimers(3) elseif cmd:sub(1, 6) == "silent" then DBM.Options.SilentMode = not DBM.Options.SilentMode DBM:AddMsg(L.SILENTMODE_IS .. (DBM.Options.SilentMode and "ON" or "OFF")) elseif cmd:sub(1, 10) == "musicstart" then DBM:TransitionToDungeonBGM(true) elseif cmd:sub(1, 9) == "musicstop" then DBM:TransitionToDungeonBGM(false, true) elseif cmd:sub(1, 9) == "infoframe" then if DBM.InfoFrame:IsShown() then DBM.InfoFrame:Hide() else DBM.InfoFrame:Show(5, "test") end elseif cmd:sub(1, 10) == "aggroframe" then if DBM.InfoFrame:IsShown() then DBM.InfoFrame:Hide() else DBM.InfoFrame:SetHeader(L.INFOFRAME_AGGRO) DBM.InfoFrame:Show(7, "playeraggro", 1) end else DBM:LoadGUI() end end