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.

435 lines
15 KiB

local _, private = ...
local isRetail = WOW_PROJECT_ID == (WOW_PROJECT_MAINLINE or 1)
local L = DBM_CORE_L
local LibStub = _G["LibStub"]
local LibLatency, LibDurability
if LibStub then
LibLatency, LibDurability = LibStub("LibLatency", true), LibStub("LibDurability", true)
end
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(private.DBMSyncProtocol, "PT", timer .. "\t" .. DBM:GetCurrentArea() .. "\t" .. targetName)
else
private.sendSync(private.DBMSyncProtocol, "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(private.DBMSyncProtocol, "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)
if not private.dbmIsEnabled then
DBM:ForceDisableSpam()
return
end
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