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.
4247 lines
146 KiB
4247 lines
146 KiB
|
|
|
|
local Details = _G.Details
|
|
local Loc = LibStub("AceLocale-3.0"):GetLocale ( "Details" )
|
|
local _
|
|
local addonName, Details222 = ...
|
|
|
|
local CreateFrame = CreateFrame
|
|
local pairs = pairs
|
|
local UIParent = UIParent
|
|
local UnitGUID = UnitGUID
|
|
local tonumber= tonumber
|
|
local LoggingCombat = LoggingCombat
|
|
local GetSpellInfo = Details222.GetSpellInfo
|
|
|
|
SLASH_PLAYEDCLASS1 = "/playedclass"
|
|
function SlashCmdList.PLAYEDCLASS(msg, editbox)
|
|
print(Details.GetPlayTimeOnClassString())
|
|
end
|
|
|
|
SLASH_DUMPTABLE1 = "/dumpt"
|
|
function SlashCmdList.DUMPTABLE(msg, editbox)
|
|
local result = "return function() return " .. msg .. " end"
|
|
local extractValue = loadstring(result)
|
|
return dumpt(extractValue()())
|
|
end
|
|
|
|
SLASH_DETAILS1, SLASH_DETAILS2, SLASH_DETAILS3 = "/details", "/dt", "/de"
|
|
|
|
---@type detailsframework
|
|
local detailsFramework = DetailsFramework
|
|
|
|
--lower case
|
|
local lowerCase_SLASH_CHANGES = string.lower(Loc ["STRING_SLASH_CHANGES"])
|
|
local lowerCase_SLASH_CHANGES_ALIAS1 = string.lower(Loc ["STRING_SLASH_CHANGES_ALIAS1"])
|
|
local lowerCase_CHANGES_ALIAS2 = string.lower(Loc ["STRING_SLASH_CHANGES_ALIAS2"])
|
|
local lowerCase_SLASH_HISTORY = string.lower(Loc ["STRING_SLASH_HISTORY"])
|
|
local lowerCase_SLASH_OPTIONS = string.lower(Loc ["STRING_SLASH_OPTIONS"])
|
|
local lowerCase_SLASH_WORLDBOSS = string.lower(Loc ["STRING_SLASH_WORLDBOSS"])
|
|
|
|
function SlashCmdList.DETAILS (msg, editbox)
|
|
local command, rest = msg:match("^(%S*)%s*(.-)$")
|
|
command = string.lower(command)
|
|
|
|
if (command == Loc ["STRING_SLASH_WIPE"] or command == "wipe") then
|
|
|
|
elseif (command == "api") then
|
|
Details.OpenAPI()
|
|
|
|
elseif (command == Loc ["STRING_SLASH_NEW"] or command == "new") then
|
|
Details:CriarInstancia(nil, true)
|
|
|
|
elseif (command == Loc ["STRING_SLASH_HISTORY"] or
|
|
command == "history" or
|
|
command == "score" or
|
|
command == "rank" or
|
|
command == "ranking" or
|
|
command == "statistics" or
|
|
command == lowerCase_SLASH_HISTORY or
|
|
command == "stats") then
|
|
Details:OpenRaidHistoryWindow()
|
|
|
|
elseif (command == Loc ["STRING_SLASH_TOGGLE"] or command == "toggle") then
|
|
local instance = rest:match ("^(%S*)%s*(.-)$")
|
|
instance = tonumber(instance)
|
|
if (instance) then
|
|
Details:ToggleWindow (instance)
|
|
else
|
|
Details:ToggleWindows()
|
|
end
|
|
|
|
elseif (command == Loc ["STRING_SLASH_HIDE"] or command == Loc ["STRING_SLASH_HIDE_ALIAS1"] or command == "hide") then
|
|
local instance = rest:match ("^(%S*)%s*(.-)$")
|
|
instance = tonumber(instance)
|
|
if (instance) then
|
|
local this_instance = Details:GetInstance(instance)
|
|
if (not this_instance) then
|
|
return Details:Msg(Loc ["STRING_WINDOW_NOTFOUND"])
|
|
end
|
|
if (this_instance:IsEnabled() and this_instance.baseframe) then
|
|
this_instance:ShutDown()
|
|
end
|
|
else
|
|
Details:ShutDownAllInstances()
|
|
end
|
|
|
|
elseif (command == "classtime" or command == "playedclass") then
|
|
Details.played_class_time = not Details.played_class_time
|
|
Details:Msg("played class:", Details.played_class_time and "enabled" or "disabled")
|
|
|
|
elseif (command == "stopperfcheck") then
|
|
Details.check_stuttering = not Details.check_stuttering
|
|
Details:Msg("stuttering/freeze checker:", Details.check_stuttering and "enabled" or "disabled")
|
|
if (Details.check_stuttering) then
|
|
_G["UpdateAddOnMemoryUsage"] = Details.UpdateAddOnMemoryUsage_Custom
|
|
else
|
|
_G["UpdateAddOnMemoryUsage"] = Details.UpdateAddOnMemoryUsage_Original
|
|
end
|
|
|
|
elseif (command == "perf") then
|
|
local performanceData = Details.performanceData
|
|
local framesLost = ceil(performanceData.deltaTime / 60)
|
|
local callStack = performanceData.callStack
|
|
|
|
local returnTable = {}
|
|
|
|
returnTable[#returnTable+1] = "Stuttering Information:"
|
|
returnTable[#returnTable+1] = "An addon feature, script is using: " .. performanceData.culpritFunc .. ""
|
|
|
|
returnTable[#returnTable+1] = ""
|
|
|
|
returnTable[#returnTable+1] = "Description: " .. performanceData.culpritDesc
|
|
|
|
returnTable[#returnTable+1] = ""
|
|
|
|
returnTable[#returnTable+1] = "You may first: disable the addon feature that uses the functionality."
|
|
returnTable[#returnTable+1] = "Second: disable a script which are using the function call: " .. performanceData.culpritFunc .. "."
|
|
|
|
returnTable[#returnTable+1] = ""
|
|
|
|
returnTable[#returnTable+1] = "Callstack for Debug:"
|
|
local callStackTable = detailsFramework:SplitTextInLines(callStack)
|
|
for i = 1, #callStackTable do
|
|
returnTable[#returnTable+1] = callStackTable[i]
|
|
end
|
|
|
|
dumpt(returnTable)
|
|
|
|
elseif (command == "mythic+") then
|
|
local statName = "mythicdungeoncompletedDF2"
|
|
local mythicDungeonRuns = Details222.PlayerStats:GetStat(statName)
|
|
|
|
dumpt(mythicDungeonRuns)
|
|
|
|
for mapChallengeModeID, mapChallengeModeData in pairs(mythicDungeonRuns) do
|
|
local mapName = C_ChallengeMode.GetMapUIInfo(mapChallengeModeID)
|
|
print(mapName, mapChallengeModeData.level, mapChallengeModeData.completed, mapChallengeModeData.time)
|
|
end
|
|
|
|
elseif (command == "mergepetspells") then --deprecated
|
|
Details.merge_pet_abilities = not Details.merge_pet_abilities
|
|
Details:Msg("Merging pet spells:", Details.merge_pet_abilities or "false")
|
|
|
|
elseif (command == "softhide") then
|
|
for instanceID, instance in Details:ListInstances() do
|
|
if (instance:IsEnabled()) then
|
|
if (instance.hide_in_combat_type > 1) then
|
|
instance:SetWindowAlphaForCombat(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (command == "softshow") then
|
|
for instanceID, instance in Details:ListInstances() do
|
|
if (instance:IsEnabled()) then
|
|
if (instance.hide_in_combat_type > 1) then
|
|
instance:SetWindowAlphaForCombat(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (command == "softtoggle") then
|
|
for instanceID, instance in Details:ListInstances() do
|
|
if (instance:IsEnabled()) then
|
|
if (instance.hide_in_combat_type > 1) then
|
|
if (instance.baseframe:GetAlpha() > 0.1) then
|
|
--show
|
|
instance:SetWindowAlphaForCombat(true)
|
|
else
|
|
--hide
|
|
instance:SetWindowAlphaForCombat(false)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (command == Loc ["STRING_SLASH_SHOW"] or command == Loc ["STRING_SLASH_SHOW_ALIAS1"] or command == "show") then
|
|
Details.LastShowCommand = GetTime()
|
|
local instanceId = rest:match("^(%S*)%s*(.-)$")
|
|
instanceId = tonumber(instanceId)
|
|
if (instanceId) then
|
|
---@type instance
|
|
local instanceObject = Details:GetInstance(instanceId)
|
|
if (not instanceObject) then
|
|
return Details:Msg(Loc ["STRING_WINDOW_NOTFOUND"])
|
|
end
|
|
if (not instanceObject:IsEnabled() and instanceObject.baseframe) then
|
|
instanceObject:EnableInstance()
|
|
end
|
|
else
|
|
Details:ReabrirTodasInstancias()
|
|
end
|
|
|
|
elseif (command == Loc ["STRING_SLASH_WIPECONFIG"] or command == "reinstall") then
|
|
Details:WipeConfig()
|
|
|
|
elseif (command == Loc ["STRING_SLASH_RESET"] or command == Loc ["STRING_SLASH_RESET_ALIAS1"] or command == "reset") then
|
|
Details.tabela_historico:ResetAllCombatData()
|
|
|
|
elseif (command == Loc ["STRING_SLASH_DISABLE"] or command == "disable") then
|
|
Details:CaptureSet(false, "damage", true)
|
|
Details:CaptureSet(false, "heal", true)
|
|
Details:CaptureSet(false, "energy", true)
|
|
Details:CaptureSet(false, "miscdata", true)
|
|
Details:CaptureSet(false, "aura", true)
|
|
Details:CaptureSet(false, "spellcast", true)
|
|
print(Loc ["STRING_DETAILS1"] .. Loc ["STRING_SLASH_CAPTUREOFF"])
|
|
|
|
elseif (command == Loc ["STRING_SLASH_ENABLE"] or command == "enable") then
|
|
Details:CaptureSet(true, "damage", true)
|
|
Details:CaptureSet(true, "heal", true)
|
|
Details:CaptureSet(true, "energy", true)
|
|
Details:CaptureSet(true, "miscdata", true)
|
|
Details:CaptureSet(true, "aura", true)
|
|
Details:CaptureSet(true, "spellcast", true)
|
|
print(Loc ["STRING_DETAILS1"] .. Loc ["STRING_SLASH_CAPTUREON"])
|
|
|
|
elseif (command == Loc ["STRING_SLASH_OPTIONS"] or
|
|
command == "options" or
|
|
command == lowerCase_SLASH_OPTIONS or
|
|
command == "config") then
|
|
|
|
if (rest and tonumber(rest)) then
|
|
local instanceN = tonumber(rest)
|
|
if (instanceN > 0 and instanceN <= #Details.tabela_instancias) then
|
|
local instance = Details:GetInstance(instanceN)
|
|
Details:OpenOptionsWindow (instance)
|
|
end
|
|
else
|
|
local lower_instance = Details:GetLowerInstanceNumber()
|
|
if (not lower_instance) then
|
|
local instance = Details:GetInstance(1)
|
|
Details.CriarInstancia (_, _, 1)
|
|
Details:OpenOptionsWindow (instance)
|
|
else
|
|
Details:OpenOptionsWindow (Details:GetInstance(lower_instance))
|
|
end
|
|
|
|
end
|
|
|
|
elseif (command == Loc ["STRING_SLASH_WORLDBOSS"] or command == "worldboss" or command == lowerCase_SLASH_WORLDBOSS) then --deprecated
|
|
local questIds = {{"Tarlna the Ageless", 81535}, {"Drov the Ruiner ", 87437}, {"Rukhmar", 87493}}
|
|
for _, _table in pairs(questIds) do
|
|
print(format("%s: \124cff%s\124r", _table [1], IsQuestFlaggedCompleted (_table [2]) and "ff0000"..Loc ["STRING_KILLED"] or "00ff00"..Loc ["STRING_ALIVE"]))
|
|
end
|
|
|
|
elseif (
|
|
command == lowerCase_SLASH_CHANGES or
|
|
command == lowerCase_SLASH_CHANGES_ALIAS1 or
|
|
command == lowerCase_CHANGES_ALIAS2 or
|
|
command == Loc ["STRING_SLASH_CHANGES"] or
|
|
command == Loc ["STRING_SLASH_CHANGES_ALIAS1"] or
|
|
command == Loc ["STRING_SLASH_CHANGES_ALIAS2"] or
|
|
command == "news" or
|
|
command == "updates") then
|
|
Details:OpenNewsWindow()
|
|
|
|
elseif (command == "discord") then
|
|
Details:CopyPaste ("https://discord.gg/AGSzAZX")
|
|
|
|
|
|
elseif (command == "m+log") then
|
|
Details:Dump(Details.mythic_plus_log)
|
|
|
|
elseif (command == "exitlog") then
|
|
local resultLog = {}
|
|
for _, str in ipairs(_detalhes_global.exit_log) do
|
|
resultLog[#resultLog+1] = str
|
|
end
|
|
|
|
resultLog[#resultLog+1] = ""
|
|
|
|
for _, str in ipairs(_detalhes_global.exit_errors) do
|
|
resultLog[#resultLog+1] = str
|
|
end
|
|
|
|
resultLog[#resultLog+1] = ""
|
|
|
|
--from backup
|
|
if (__details_backup._exit_error) then
|
|
for _, str in ipairs(__details_backup._exit_error) do
|
|
resultLog[#resultLog+1] = str
|
|
end
|
|
end
|
|
|
|
Details:Dump(resultLog)
|
|
|
|
elseif (command == "erasesegment") then
|
|
local segmentId = rest and tonumber(rest)
|
|
if (segmentId and segmentId ~= 1) then
|
|
local segmentToErase = tonumber(segmentId)
|
|
local combatObject = table.remove(Details:GetCombatSegments(), segmentToErase)
|
|
|
|
if (combatObject) then
|
|
Details:DestroyCombat(combatObject)
|
|
Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED")
|
|
Details:Msg("segment removed.")
|
|
collectgarbage()
|
|
else
|
|
Details:Msg("segment not found.")
|
|
end
|
|
else
|
|
Details:Msg("segment ID invalid.")
|
|
end
|
|
return
|
|
|
|
elseif (command == "bosstimers" or command == "bosstimer" or command == "timer" or command == "timers") then
|
|
Details.OpenForge()
|
|
DetailsForgePanel.SelectModule (_, _, 4)
|
|
|
|
elseif (command == "spells") then
|
|
Details.OpenForge()
|
|
DetailsForgePanel.SelectModule (_, _, 1)
|
|
|
|
elseif (msg == "WA" or msg == "wa" or msg == "Wa" or msg == "wA") then
|
|
_G.DetailsPluginContainerWindow.OpenPlugin(_G.DetailsAuraPanel)
|
|
_G.DetailsAuraPanel.RefreshWindow()
|
|
|
|
elseif (command == "feedback") then
|
|
Details.OpenFeedbackWindow()
|
|
|
|
elseif (command == "profile") then
|
|
local profileName = rest
|
|
if (profileName and profileName ~= "") then
|
|
|
|
local profile = Details:GetProfile(profileName)
|
|
if (not profile) then
|
|
return Details:Msg("Profile Not Found.")
|
|
end
|
|
|
|
if (not Details:ApplyProfile(profileName)) then
|
|
return
|
|
end
|
|
|
|
Details:Msg(Loc ["STRING_OPTIONS_PROFILE_LOADED"], profileName)
|
|
if (_G.DetailsOptionsWindow and _G.DetailsOptionsWindow:IsShown()) then
|
|
_G.DetailsOptionsWindow:Hide()
|
|
GameCooltip:Close()
|
|
end
|
|
else
|
|
Details:Msg("/details profile <profile name>")
|
|
end
|
|
|
|
elseif (msg == "tr") then
|
|
local f = CreateFrame("frame", nil, UIParent)
|
|
f:SetSize(300, 300)
|
|
f:SetPoint("center")
|
|
|
|
-- /run TTT:SetTexture("Interface\\1024.tga")
|
|
local texture = f:CreateTexture("TTT", "background")
|
|
texture:SetAllPoints()
|
|
texture:SetTexture("Interface\\1023.tga")
|
|
|
|
local A = detailsFramework:CreateAnimationHub (texture)
|
|
|
|
local b = detailsFramework:CreateAnimation(A, "ROTATION", 1, 40, 360)
|
|
b:SetTarget (texture)
|
|
A:Play()
|
|
|
|
C_Timer.NewTicker(1, function()
|
|
texture:SetTexCoord(math.random(), math.random(), math.random(), math.random(), math.random(), math.random(), math.random(), math.random())
|
|
end)
|
|
|
|
elseif (msg == "load") then
|
|
print(DetailsDataStorage)
|
|
local loaded, reason = LoadAddOn ("Details_DataStorage")
|
|
print(loaded, reason, DetailsDataStorage)
|
|
|
|
elseif (msg == "chaticon") then
|
|
Details:Msg("|TInterface\\AddOns\\Details\\images\\icones_barra:" .. 14 .. ":" .. 14 .. ":0:0:256:32:0:32:0:32|tteste")
|
|
|
|
elseif (msg == "align") then
|
|
local c = RightChatPanel
|
|
local w,h = c:GetSize()
|
|
print(w,h)
|
|
|
|
local instance1 = Details.tabela_instancias [1]
|
|
local instance2 = Details.tabela_instancias [2]
|
|
|
|
instance1.baseframe:ClearAllPoints()
|
|
instance2.baseframe:ClearAllPoints()
|
|
|
|
instance1.baseframe:SetSize(w/2 - 4, h-20-21-8)
|
|
instance2.baseframe:SetSize(w/2 - 4, h-20-21-8)
|
|
|
|
instance1.baseframe:SetPoint("bottomleft", RightChatDataPanel, "topleft", 1, 1)
|
|
instance2.baseframe:SetPoint("bottomright", RightChatToggleButton, "topright", -1, 1)
|
|
|
|
elseif (msg == "pets") then
|
|
Details.DebugPets()
|
|
|
|
elseif (msg == "mypets") then
|
|
Details.DebugMyPets()
|
|
|
|
elseif (msg == "model") then
|
|
local frame = CreateFrame("PlayerModel");
|
|
frame:SetPoint("center",UIParent,"center");
|
|
frame:SetHeight(600);
|
|
frame:SetWidth(300);
|
|
frame:SetDisplayInfo (49585);
|
|
|
|
elseif (msg == "time") then
|
|
print("GetTime()", GetTime())
|
|
print("time()", time())
|
|
|
|
elseif (msg == "copy") then
|
|
_G.DetailsCopy:Show()
|
|
_G.DetailsCopy.MyObject.text:HighlightText()
|
|
_G.DetailsCopy.MyObject.text:SetFocus()
|
|
|
|
elseif (msg == "unitname") then
|
|
local nome, realm = UnitName("target")
|
|
if (realm) then
|
|
nome = nome.."-"..realm
|
|
end
|
|
print(nome, realm)
|
|
|
|
elseif (msg == "cacheparser") then
|
|
Details:PrintParserCacheIndexes()
|
|
elseif (msg == "parsercache") then
|
|
Details:PrintParserCacheIndexes()
|
|
|
|
elseif (msg == "captures") then
|
|
for k, v in pairs(Details.capture_real) do
|
|
print("real -",k,":",v)
|
|
end
|
|
for k, v in pairs(Details.capture_current) do
|
|
print("current -",k,":",v)
|
|
end
|
|
|
|
elseif (msg == "slider") then
|
|
|
|
local f = CreateFrame("frame", "TESTEDESCROLL", UIParent)
|
|
f:SetPoint("center", UIParent, "center", 200, -2)
|
|
f:SetWidth(300)
|
|
f:SetHeight(150)
|
|
f:SetBackdrop({bgFile = "Interface\\AddOns\\Details\\images\\background", tile = true, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}})
|
|
f:SetBackdropColor(0, 0, 0, 1)
|
|
f:EnableMouseWheel(true)
|
|
|
|
local rows = {}
|
|
for i = 1, 7 do
|
|
local row = CreateFrame("frame", nil, UIParent)
|
|
row:SetPoint("topleft", f, "topleft", 10, -(i-1)*21)
|
|
row:SetWidth(200)
|
|
row:SetHeight(20)
|
|
row:SetBackdrop({bgFile = "Interface\\AddOns\\Details\\images\\background", tile = true, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}})
|
|
local t = row:CreateFontString(nil, "overlay", "GameFontHighlightSmall")
|
|
t:SetPoint("left", row, "left")
|
|
row.text = t
|
|
rows [#rows+1] = row
|
|
end
|
|
|
|
local data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
|
|
|
|
|
|
|
|
elseif (msg == "bcollor") then
|
|
|
|
--local instancia = _detalhes.tabela_instancias [1]
|
|
Details.ResetButton.Middle:SetVertexColor(1, 1, 0, 1)
|
|
|
|
--print(_detalhes.ResetButton:GetHighlightTexture())
|
|
|
|
local t = Details.ResetButton:GetHighlightTexture()
|
|
t:SetVertexColor(0, 1, 0, 1)
|
|
--print(t:GetObjectType())
|
|
--_detalhes.ResetButton:SetHighlightTexture(t)
|
|
Details.ResetButton:SetNormalTexture(t)
|
|
|
|
print("backdrop", Details.ResetButton:GetBackdrop())
|
|
|
|
Details.ResetButton:SetBackdropColor(0, 0, 1, 1)
|
|
|
|
--Details.VarDump (_detalhes.ResetButton)
|
|
|
|
elseif (command == "trinket") then
|
|
local tooltipData = GameTooltip:GetTooltipData()
|
|
if (tooltipData) then
|
|
local spellId = tooltipData.id
|
|
local spellName = GetSpellInfo(spellId)
|
|
|
|
if (spellName) then
|
|
|
|
local itemLink = GetInventoryItemLink("player", 13)
|
|
if (itemLink) then
|
|
local itemName = GetItemInfo(itemLink)
|
|
if (itemName) then
|
|
local itemID, enchantID, gemID1, gemID2, gemID3, gemID4, suffixID, uniqueID, linkLevel, specializationID, modifiersMask, itemContext = select(2, strsplit(":", itemLink))
|
|
|
|
itemID = tonumber(itemID)
|
|
|
|
if (itemID) then
|
|
local s = "["..spellId.."] = {name = formatTextForItem("..itemID..")}, --trinket: ".. itemName
|
|
dumpt({s})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (command == "mini") then
|
|
local instance = Details.tabela_instancias [1]
|
|
--Details.VarDump ()
|
|
--print(instance, instance.StatusBar.options, instance.StatusBar.left)
|
|
print(instance.StatusBar.options [instance.StatusBar.left.mainPlugin.real_name].textSize)
|
|
print(instance.StatusBar.left.options.textSize)
|
|
|
|
elseif (command == "owner") then
|
|
|
|
local petname = rest:match ("^(%S*)%s*(.-)$")
|
|
local petGUID = UnitGUID("target")
|
|
|
|
if (not _G.DetailsScanTooltip) then
|
|
local scanTool = CreateFrame("GameTooltip", "DetailsScanTooltip", nil, "GameTooltipTemplate")
|
|
scanTool:SetOwner(WorldFrame, "ANCHOR_NONE")
|
|
end
|
|
|
|
function getPetOwner (petName)
|
|
local scanTool = _G.DetailsScanTooltip
|
|
local scanText = _G ["DetailsScanTooltipTextLeft2"] -- This is the line with <[Player]'s Pet>
|
|
|
|
scanTool:ClearLines()
|
|
|
|
print(petName)
|
|
scanTool:SetUnit(petName)
|
|
|
|
local ownerText = scanText:GetText()
|
|
if (not ownerText) then
|
|
return nil
|
|
end
|
|
local owner, _ = string.split ("'", ownerText)
|
|
|
|
return owner -- This is the pet's owner
|
|
end
|
|
|
|
--print(getPetOwner (petname))
|
|
print(getPetOwner (petGUID))
|
|
|
|
|
|
elseif (command == "buffsof") then
|
|
|
|
local playername, segment = rest:match("^(%S*)%s*(.-)$")
|
|
segment = tonumber(segment or 0)
|
|
print("dumping buffs of ", playername, segment)
|
|
|
|
local c = Details:GetCombat("current")
|
|
if (c) then
|
|
|
|
local playerActor
|
|
|
|
if (segment and segment ~= 0) then
|
|
local c = Details:GetCombat(segment)
|
|
playerActor = c (4, playername)
|
|
print("using segment", segment, c, "player actor:", playerActor)
|
|
else
|
|
playerActor = c (4, playername)
|
|
end
|
|
|
|
print("actor table: ", playerActor)
|
|
|
|
if (not playerActor) then
|
|
print("actor table not found")
|
|
return
|
|
end
|
|
|
|
if (playerActor and playerActor.buff_uptime_spells and playerActor.buff_uptime_spells._ActorTable) then
|
|
for spellid, spellTable in pairs(playerActor.buff_uptime_spells._ActorTable) do
|
|
local spellname = GetSpellInfo(spellid)
|
|
if (spellname) then
|
|
print(spellid, spellname, spellTable.uptime)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (msg == "yesno") then
|
|
--_detalhes:Show()
|
|
|
|
elseif (msg == "imageedit") then
|
|
|
|
local callback = function(width, height, overlayColor, alpha, texCoords)
|
|
print(width, height, alpha)
|
|
print("overlay: ", unpack(overlayColor))
|
|
print("crop: ", unpack(texCoords))
|
|
end
|
|
|
|
Details.gump:ImageEditor (callback, "Interface\\TALENTFRAME\\bg-paladin-holy", nil, {1, 1, 1, 1}) -- {0.25, 0.25, 0.25, 0.25}
|
|
|
|
elseif (msg == "chat") then
|
|
|
|
local name, fontSize, r, g, b, a, shown, locked = FCF_GetChatWindowInfo (1);
|
|
print(name,"|",fontSize,"|", r,"|", g,"|", b,"|", a,"|", shown,"|", locked)
|
|
|
|
--local fontFile, unused, fontFlags = self:GetFont();
|
|
--self:SetFont(fontFile, fontSize, fontFlags);
|
|
|
|
elseif (msg == "error") then
|
|
a = nil + 1
|
|
|
|
--debug
|
|
elseif (command == "resetcapture") then
|
|
Details.capture_real = {
|
|
["damage"] = true,
|
|
["heal"] = true,
|
|
["energy"] = true,
|
|
["miscdata"] = true,
|
|
["aura"] = true,
|
|
}
|
|
Details.capture_current = Details.capture_real
|
|
Details:CaptureRefresh()
|
|
print(Loc ["STRING_DETAILS1"] .. "capture has been reseted.")
|
|
|
|
--debug
|
|
elseif (command == "barra") then
|
|
|
|
local whichRowLine = rest and tonumber(rest) or 1
|
|
|
|
local instancia = Details.tabela_instancias [1]
|
|
local barra = instancia.barras [whichRowLine]
|
|
|
|
for i = 1, barra:GetNumPoints() do
|
|
local point, relativeTo, relativePoint, xOfs, yOfs = barra:GetPoint(i)
|
|
print(point, relativeTo, relativePoint, xOfs, yOfs)
|
|
end
|
|
|
|
elseif (msg == "opened") then
|
|
print("Instances opened: " .. Details.opened_windows)
|
|
|
|
--debug, get a guid of something
|
|
elseif (command == "backdrop") then --localize-me
|
|
local f = MacroFrameTextBackground
|
|
local backdrop = MacroFrameTextBackground:GetBackdrop()
|
|
|
|
Details.VarDump (backdrop)
|
|
Details.VarDump (backdrop.insets)
|
|
|
|
print("bgcolor:",f:GetBackdropColor())
|
|
print("bordercolor",f:GetBackdropBorderColor())
|
|
|
|
elseif (command == "myguid") then --localize-me
|
|
|
|
local g = UnitGUID("player")
|
|
print(type(g))
|
|
print(g)
|
|
print(string.len(g))
|
|
local serial = g:sub (12, 18)
|
|
serial = tonumber("0x"..serial)
|
|
print(serial)
|
|
|
|
--tonumber((UnitGUID("target")):sub(-12, -9), 16))
|
|
|
|
elseif (command == "npcid") then
|
|
if (UnitExists("target")) then
|
|
local serial = UnitGUID("target")
|
|
if (serial) then
|
|
local npcId = _G.DetailsFramework:GetNpcIdFromGuid(serial)
|
|
if (npcId) then
|
|
|
|
if (not Details.id_frame) then
|
|
local backdrop = {
|
|
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
|
edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
|
tile = true, edgeSize = 1, tileSize = 5,
|
|
}
|
|
|
|
Details.id_frame = CreateFrame("Frame", "DetailsID", UIParent, "BackdropTemplate")
|
|
Details.id_frame:SetHeight(14)
|
|
Details.id_frame:SetWidth(120)
|
|
Details.id_frame:SetPoint("center", UIParent, "center")
|
|
Details.id_frame:SetBackdrop(backdrop)
|
|
|
|
table.insert(UISpecialFrames, "DetailsID")
|
|
|
|
Details.id_frame.texto = CreateFrame("editbox", nil, Details.id_frame, "BackdropTemplate")
|
|
Details.id_frame.texto:SetPoint("topleft", Details.id_frame, "topleft")
|
|
Details.id_frame.texto:SetAutoFocus(false)
|
|
Details.id_frame.texto:SetFontObject(GameFontHighlightSmall)
|
|
Details.id_frame.texto:SetHeight(14)
|
|
Details.id_frame.texto:SetWidth(120)
|
|
Details.id_frame.texto:SetJustifyH("CENTER")
|
|
Details.id_frame.texto:EnableMouse(true)
|
|
Details.id_frame.texto:SetBackdropColor(0, 0, 0, 0.5)
|
|
Details.id_frame.texto:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
|
|
Details.id_frame.texto:SetText("")
|
|
Details.id_frame.texto.perdeu_foco = nil
|
|
|
|
Details.id_frame.texto:SetScript("OnEnterPressed", function()
|
|
Details.id_frame.texto:ClearFocus()
|
|
Details.id_frame:Hide()
|
|
end)
|
|
|
|
Details.id_frame.texto:SetScript("OnEscapePressed", function()
|
|
Details.id_frame.texto:ClearFocus()
|
|
Details.id_frame:Hide()
|
|
end)
|
|
|
|
end
|
|
|
|
C_Timer.After(0.1, function()
|
|
Details.id_frame:Show()
|
|
Details.id_frame.texto:SetFocus()
|
|
Details.id_frame.texto:SetText("" .. npcId)
|
|
Details.id_frame.texto:HighlightText()
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
elseif (command == "guid") then
|
|
if (UnitExists("target")) then
|
|
local serial = UnitGUID("target")
|
|
if (serial) then
|
|
local npcId = serial
|
|
if (not Details.id_frame) then
|
|
local backdrop = {
|
|
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
|
edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
|
tile = true, edgeSize = 1, tileSize = 5,
|
|
}
|
|
|
|
Details.id_frame = CreateFrame("Frame", "DetailsID", UIParent, "BackdropTemplate")
|
|
Details.id_frame:SetHeight(14)
|
|
Details.id_frame:SetWidth(120)
|
|
Details.id_frame:SetPoint("center", UIParent, "center")
|
|
Details.id_frame:SetBackdrop(backdrop)
|
|
|
|
table.insert(UISpecialFrames, "DetailsID")
|
|
|
|
Details.id_frame.texto = CreateFrame("editbox", nil, Details.id_frame, "BackdropTemplate")
|
|
Details.id_frame.texto:SetPoint("topleft", Details.id_frame, "topleft")
|
|
Details.id_frame.texto:SetAutoFocus(false)
|
|
Details.id_frame.texto:SetFontObject(GameFontHighlightSmall)
|
|
Details.id_frame.texto:SetHeight(14)
|
|
Details.id_frame.texto:SetWidth(120)
|
|
Details.id_frame.texto:SetJustifyH("CENTER")
|
|
Details.id_frame.texto:EnableMouse(true)
|
|
Details.id_frame.texto:SetBackdropColor(0, 0, 0, 0.5)
|
|
Details.id_frame.texto:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
|
|
Details.id_frame.texto:SetText("")
|
|
Details.id_frame.texto.perdeu_foco = nil
|
|
|
|
Details.id_frame.texto:SetScript("OnEnterPressed", function()
|
|
Details.id_frame.texto:ClearFocus()
|
|
Details.id_frame:Hide()
|
|
end)
|
|
|
|
Details.id_frame.texto:SetScript("OnEscapePressed", function()
|
|
Details.id_frame.texto:ClearFocus()
|
|
Details.id_frame:Hide()
|
|
end)
|
|
|
|
end
|
|
|
|
C_Timer.After(0.1, function()
|
|
Details.id_frame:Show()
|
|
Details.id_frame.texto:SetFocus()
|
|
Details.id_frame.texto:SetText("" .. npcId)
|
|
Details.id_frame.texto:HighlightText()
|
|
end)
|
|
end
|
|
end
|
|
|
|
elseif (command == "spellid") then
|
|
if (Details222.FocusedSpellId) then
|
|
local npcId = Details222.FocusedSpellId
|
|
if (not Details.id_frame) then
|
|
local backdrop = {
|
|
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
|
edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
|
tile = true, edgeSize = 1, tileSize = 5,
|
|
}
|
|
|
|
Details.id_frame = CreateFrame("Frame", "DetailsID", UIParent, "BackdropTemplate")
|
|
Details.id_frame:SetHeight(14)
|
|
Details.id_frame:SetWidth(120)
|
|
Details.id_frame:SetPoint("center", UIParent, "center")
|
|
Details.id_frame:SetBackdrop(backdrop)
|
|
|
|
table.insert(UISpecialFrames, "DetailsID")
|
|
|
|
Details.id_frame.texto = CreateFrame("editbox", nil, Details.id_frame, "BackdropTemplate")
|
|
Details.id_frame.texto:SetPoint("topleft", Details.id_frame, "topleft")
|
|
Details.id_frame.texto:SetAutoFocus(false)
|
|
Details.id_frame.texto:SetFontObject(GameFontHighlightSmall)
|
|
Details.id_frame.texto:SetHeight(14)
|
|
Details.id_frame.texto:SetWidth(120)
|
|
Details.id_frame.texto:SetJustifyH("CENTER")
|
|
Details.id_frame.texto:EnableMouse(true)
|
|
Details.id_frame.texto:SetBackdropColor(0, 0, 0, 0.5)
|
|
Details.id_frame.texto:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
|
|
Details.id_frame.texto:SetText("")
|
|
Details.id_frame.texto.perdeu_foco = nil
|
|
|
|
Details.id_frame.texto:SetScript("OnEnterPressed", function()
|
|
Details.id_frame.texto:ClearFocus()
|
|
Details.id_frame:Hide()
|
|
end)
|
|
|
|
Details.id_frame.texto:SetScript("OnEscapePressed", function()
|
|
Details.id_frame.texto:ClearFocus()
|
|
Details.id_frame:Hide()
|
|
end)
|
|
|
|
end
|
|
|
|
C_Timer.After(0.1, function()
|
|
Details.id_frame:Show()
|
|
Details.id_frame.texto:SetFocus()
|
|
Details.id_frame.texto:SetText("" .. npcId)
|
|
Details.id_frame.texto:HighlightText()
|
|
end)
|
|
end
|
|
|
|
elseif (command == "profile") then
|
|
|
|
local profile = rest:match("^(%S*)%s*(.-)$")
|
|
|
|
print("Force apply profile: ", profile)
|
|
|
|
Details:ApplyProfile (profile, false)
|
|
|
|
elseif (msg == "version") then
|
|
Details.ShowCopyValueFrame(Details.GetVersionString())
|
|
|
|
elseif (msg == "users" or msg == "versioncheck") then
|
|
Details.SendHighFive()
|
|
|
|
print(Loc ["STRING_DETAILS1"] .. "highfive sent, HI!")
|
|
|
|
C_Timer.After(0.3, function()
|
|
Details.RefreshUserList()
|
|
end)
|
|
C_Timer.After(0.6, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
C_Timer.After(0.9, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
C_Timer.After(1.3, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
C_Timer.After(1.6, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
C_Timer.After(3, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
C_Timer.After(4, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
C_Timer.After(5, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
C_Timer.After(8, function()
|
|
Details.RefreshUserList (true)
|
|
end)
|
|
|
|
elseif (command == "names") then
|
|
local t, filter = rest:match("^(%S*)%s*(.-)$")
|
|
|
|
t = tonumber(t)
|
|
if (not t) then
|
|
return print("not T found.")
|
|
end
|
|
|
|
local f = Details.ListPanel
|
|
if (not f) then
|
|
f = Details:CreateListPanel()
|
|
end
|
|
|
|
local container = Details.tabela_vigente [t]._NameIndexTable
|
|
|
|
local i = 0
|
|
for name, _ in pairs(container) do
|
|
i = i + 1
|
|
f:add (name, i)
|
|
end
|
|
|
|
print(i, "names found.")
|
|
|
|
f:Show()
|
|
|
|
elseif (command == "actors") then
|
|
|
|
local t, filter = rest:match("^(%S*)%s*(.-)$")
|
|
|
|
t = tonumber(t)
|
|
if (not t) then
|
|
return print("not T found.")
|
|
end
|
|
|
|
local f = Details.ListPanel
|
|
if (not f) then
|
|
f = Details:CreateListPanel()
|
|
end
|
|
|
|
local container = Details.tabela_vigente [t]._ActorTable
|
|
print(#container, "actors found.")
|
|
for index, actor in ipairs(container) do
|
|
f:add (actor.nome, index, filter)
|
|
end
|
|
|
|
f:Show()
|
|
|
|
--debug
|
|
elseif (msg == "save") then
|
|
print("running... this is a debug command, details wont work until next /reload.")
|
|
Details:PrepareTablesForSave()
|
|
|
|
elseif (msg == "buffs") then
|
|
for i = 1, 40 do
|
|
local name, texture, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal, spellid = UnitBuff ("player", i)
|
|
if (not name) then
|
|
return
|
|
end
|
|
print(spellid, name)
|
|
end
|
|
|
|
elseif (msg == "id") then
|
|
local one, two = rest:match("^(%S*)%s*(.-)$")
|
|
if (one ~= "") then
|
|
print("NPC ID:", one:sub(-12, -9), 16)
|
|
print("NPC ID:", tonumber((one):sub(-12, -9), 16))
|
|
else
|
|
print("NPC ID:", tonumber((UnitGUID("target")):sub(-12, -9), 16) )
|
|
end
|
|
|
|
--debug
|
|
elseif (command == "debugnet") then
|
|
if (Details.debugnet) then
|
|
Details.debugnet = false
|
|
print(Loc["STRING_DETAILS1"] .. "net diagnostic mode has been turned off.")
|
|
return
|
|
else
|
|
Details.debugnet = true
|
|
print(Loc["STRING_DETAILS1"] .. "net diagnostic mode has been turned on.")
|
|
end
|
|
|
|
elseif (command == "m+debug") then
|
|
Details222.Debug.SetMythicPlusDebugState() --passing nothing will toggle the debug state
|
|
|
|
elseif (command == "m+debugloot") then
|
|
Details222.Debug.SetMythicPlusLootDebugState() --passing nothing will toggle the debug state
|
|
|
|
elseif (command == "debug") then
|
|
Details.ShowDebugOptionsPanel()
|
|
|
|
--debug combat log
|
|
elseif (msg == "combatlog") then
|
|
if (Details.isLoggingCombat) then
|
|
LoggingCombat (false)
|
|
print("Wow combatlog record turned OFF.")
|
|
Details.isLoggingCombat = nil
|
|
else
|
|
LoggingCombat (true)
|
|
print("Wow combatlog record turned ON.")
|
|
Details.isLoggingCombat = true
|
|
end
|
|
|
|
elseif (msg == "gs") then
|
|
Details:teste_grayscale()
|
|
|
|
elseif (msg == "bwload") then
|
|
if not BigWigs then LoadAddOn("BigWigs_Core") end
|
|
BigWigs:Enable()
|
|
|
|
LoadAddOn ("BigWigs_Highmaul")
|
|
|
|
local mod = BigWigs:GetBossModule("Imperator Mar'gok")
|
|
mod:Enable()
|
|
|
|
elseif (msg == "bwsend") then
|
|
local mod = BigWigs:GetBossModule("Imperator Mar'gok")
|
|
mod:Message("stages", "Neutral", "Long", "Phase 2", false)
|
|
|
|
elseif (msg == "bwregister") then
|
|
|
|
local addon = {}
|
|
BigWigs.RegisterMessage(addon, "BigWigs_Message")
|
|
function addon:BigWigs_Message(event, module, key, text)
|
|
if module.journalId == 1197 and text:match("^Phase %d$") then -- 1197 = Margok
|
|
print("Phase Changed!", event, module, key, text)
|
|
end
|
|
end
|
|
|
|
elseif (msg == "pos") then
|
|
local x, y = GetPlayerMapPosition ("player")
|
|
|
|
if (not DetailsPosBox) then
|
|
Details.gump:CreateTextEntry(UIParent, function()end, 200, 20, nil, "DetailsPosBox")
|
|
DetailsPosBox:SetPoint("center", UIParent, "center")
|
|
end
|
|
|
|
local one, two = rest:match("^(%S*)%s*(.-)$")
|
|
if (one == "2") then
|
|
DetailsPosBox.MyObject.text = "{x2 = " .. x .. ", y2 = " .. y .. "}"
|
|
else
|
|
DetailsPosBox.MyObject.text = "{x1 = " .. x .. ", y1 = " .. y .. "}"
|
|
end
|
|
DetailsPosBox.MyObject:SetFocus()
|
|
DetailsPosBox.MyObject:HighlightText()
|
|
|
|
elseif (msg == "outline") then
|
|
|
|
local instancia = Details.tabela_instancias [1]
|
|
for _, barra in ipairs(instancia.barras) do
|
|
local _, _, flags = barra.lineText1:GetFont()
|
|
print("outline:",flags)
|
|
end
|
|
|
|
elseif (msg == "sell") then
|
|
|
|
--sell gray
|
|
local c, i, n, v = 0
|
|
for b = 0, 4 do
|
|
for s = 1, GetContainerNumSlots(b) do
|
|
i = {GetContainerItemInfo (b, s)}
|
|
n = i[7]
|
|
if n and string.find(n,"9d9d9d") then
|
|
v = {GetItemInfo(n)}
|
|
q = i[2]
|
|
c = c+v[11]*q
|
|
UseContainerItem (b, s)
|
|
print(n, q)
|
|
end
|
|
end
|
|
end
|
|
print(GetCoinText(c))
|
|
|
|
--sell green equip
|
|
local c, i, n, v = 0
|
|
for b = 0, 4 do
|
|
for s = 1, GetContainerNumSlots(b) do
|
|
local texture, itemCount, locked, quality, readable, lootable, itemLink = GetContainerItemInfo (b, s)
|
|
if (quality == 2) then --a green item
|
|
local itemName, itemLink, itemRarity, itemLevel, _, itemType, itemSubType = GetItemInfo (itemLink)
|
|
if (itemType == "Armor" or itemType == "Weapon") then --a weapon or armor
|
|
if (itemLevel < 460) then
|
|
print("Selling", itemName, itemType)
|
|
UseContainerItem (b, s)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (msg == "forge") then
|
|
Details:OpenForge()
|
|
|
|
elseif (msg == "parser") then
|
|
|
|
Details:OnParserEvent (
|
|
"COMBAT_LOG_EVENT_UNFILTERED", --evento =
|
|
1548754114, --time =
|
|
"SPELL_DAMAGE", --token =
|
|
nil, --hidding =
|
|
"0000000000000000", --who_serial =
|
|
nil, --who_name =
|
|
0x514, --who_flags =
|
|
0x0, --who_flags2 =
|
|
"Player-3676-06F3C3FA", --alvo_serial =
|
|
"Icybluefur-Area52", --alvo_name =
|
|
0x514, --alvo_flags =
|
|
0x0, --alvo_flags2 =
|
|
157247, --spellid =
|
|
"Reverberations", --spellname =
|
|
0x1, --spelltype =
|
|
4846, --amount =
|
|
-1, --overkill =
|
|
1 --school =
|
|
)
|
|
|
|
elseif (msg == "ilvl" or msg == "itemlevel" or msg == "ilevel") then
|
|
local item_amount = 16
|
|
local item_level = 0
|
|
local failed = 0
|
|
local unitid = "player"
|
|
local two_hand = {
|
|
["INVTYPE_2HWEAPON"] = true,
|
|
["INVTYPE_RANGED"] = true,
|
|
["INVTYPE_RANGEDRIGHT"] = true,
|
|
}
|
|
|
|
Details:Msg("======== Item Level Debug ========")
|
|
|
|
for equip_id = 1, 17 do
|
|
if (equip_id ~= 4) then --shirt slot
|
|
local item = GetInventoryItemLink (unitid, equip_id)
|
|
if (item) then
|
|
local _, _, itemRarity, iLevel, _, _, _, _, equipSlot = GetItemInfo (item)
|
|
if (iLevel) then
|
|
item_level = item_level + iLevel
|
|
print(iLevel, item)
|
|
--16 = main hand 17 = off hand
|
|
-- if using a two-hand, ignore the off hand slot
|
|
if (equip_id == 16 and two_hand [equipSlot]) then
|
|
item_amount = 15
|
|
break
|
|
end
|
|
end
|
|
else
|
|
failed = failed + 1
|
|
if (failed > 2) then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local average = item_level / item_amount
|
|
Details:Msg("gear score: " .. item_level, "| item amount:", item_amount, "| ilvl:", average)
|
|
|
|
Details.ilevel:CalcItemLevel ("player", UnitGUID("player"), true)
|
|
|
|
elseif (msg == "score") then
|
|
|
|
Details:OpenRaidHistoryWindow ("Hellfire Citadel", 1800, 15, "DAMAGER", "Rock Lobster", 2, "Keyspell")
|
|
|
|
elseif (msg == "bar") then
|
|
local bar = _G.DetailsTestBar
|
|
if (not bar) then
|
|
bar = Details.gump:CreateBar (UIParent, nil, 600, 200, 100, nil, "DetailsTestBar")
|
|
_G.DetailsTestBar = bar
|
|
bar:SetPoint("center", 0, 0)
|
|
bar.RightTextIsTimer = true
|
|
bar.BarIsInverse = true
|
|
end
|
|
|
|
bar.color = "HUNTER"
|
|
|
|
local start = GetTime()-45
|
|
local fim = GetTime()+5
|
|
|
|
bar:SetTimer (start, fim)
|
|
|
|
--C_Timer.After(5, function() bar:CancelTimerBar() end)
|
|
|
|
|
|
elseif (msg == "q") then
|
|
|
|
local myframe = TestFrame
|
|
if (not myframe) then
|
|
myframe = TestFrame or CreateFrame("frame", "TestFrame", UIParent)
|
|
myframe:SetPoint("center", UIParent, "center")
|
|
myframe:SetSize(300, 300)
|
|
myframe.texture = myframe:CreateTexture(nil, "overlay")
|
|
myframe.texture:SetAllPoints()
|
|
myframe.texture:SetTexture([[Interface\AddOns\WorldQuestTracker\media\icon_flag_common]])
|
|
else
|
|
if (myframe.texture:IsShown()) then
|
|
myframe.texture:Hide()
|
|
else
|
|
print(myframe.texture:GetTexture())
|
|
myframe.texture:Show()
|
|
print(myframe.texture:GetTexture())
|
|
end
|
|
end
|
|
|
|
|
|
|
|
if (true) then
|
|
return
|
|
end
|
|
|
|
local y = -50
|
|
local allspecs = {}
|
|
|
|
for a, b in pairs(Details.class_specs_coords) do
|
|
table.insert(allspecs, a)
|
|
end
|
|
|
|
for i = 1, 10 do
|
|
|
|
local a = CreateFrame("statusbar", nil, UIParent)
|
|
a:SetPoint("topleft", UIParent, "topleft", i*32, y)
|
|
a:SetSize(32, 32)
|
|
a:SetMinMaxValues(0, 1)
|
|
|
|
local texture = a:CreateTexture(nil, "overlay")
|
|
texture:SetSize(32, 32)
|
|
texture:SetPoint("topleft")
|
|
|
|
if (i%10 == 0) then
|
|
y = y - 32
|
|
end
|
|
|
|
-- /run for o=1,10 do local f=CreateFrame("frame");f:SetPoint("center");f:SetSize(300,300); local t=f:CreateTexture(nil,"overlay");t:SetAllPoints();f:SetScript("OnUpdate",function() t:SetTexture("Interface\\1024")end);end;
|
|
-- https://www.dropbox.com/s/ulyeqa2z0ummlu7/1024.tga?dl=0
|
|
|
|
local elapsedTime = 0
|
|
a:SetScript("OnUpdate", function(self, deltaTime)
|
|
elapsedTime = elapsedTime + deltaTime
|
|
|
|
--texture:SetSize(math.random(50, 300), math.random(50, 300))
|
|
--local spec = allspecs [math.random(#allspecs)]
|
|
texture:SetTexture([[Interface\AddOns\Details\images\options_window]])
|
|
--texture:SetTexture([[Interface\Store\Store-Splash]])
|
|
--texture:SetTexture([[Interface\AddOns\Details\images\options_window]])
|
|
--texture:SetTexture([[Interface\CHARACTERFRAME\Button_BloodPresence_DeathKnight]])
|
|
--texture:SetTexCoord(unpack(_detalhes.class_specs_coords [spec]))
|
|
|
|
--a:SetAlpha(abs(math.sin (time)))
|
|
--a:SetValue(abs(math.sin (time)))
|
|
end)
|
|
end
|
|
|
|
elseif (msg == "alert") then
|
|
--local instancia = _detalhes.tabela_instancias [1]
|
|
local f = function(a, b, c, d, e, f, g) print(a, b, c, d, e, f, g) end
|
|
--instancia:InstanceAlert (Loc ["STRING_PLEASE_WAIT"], {[[Interface\COMMON\StreamCircle]], 22, 22, true}, 5, {f, 1, 2, 3, 4, 5})
|
|
|
|
local lower_instance = Details:GetLowerInstanceNumber()
|
|
if (lower_instance) then
|
|
local instance = Details:GetInstance(lower_instance)
|
|
if (instance) then
|
|
local func = {Details.OpenRaidHistoryWindow, Details, "Hellfire Citadel", 1800, 15, "DAMAGER", "Rock Lobster", 2, "Keyspell"}
|
|
instance:InstanceAlert ("Boss Defeated, Open History! ", {[[Interface\AddOns\Details\images\icons]], 16, 16, false, 434/512, 466/512, 243/512, 273/512}, 40, func, true)
|
|
end
|
|
end
|
|
|
|
elseif (msg == "teste1") then -- /de teste1
|
|
Details:OpenRaidHistoryWindow (1530, 1886, 15, "damage", "Rock Lobster", 2, "Keyspell") --, _role, _guild, _player_base, _player_name)
|
|
|
|
elseif (msg == "qq") then
|
|
local my_role = "DAMAGER"
|
|
local raid_name = "Tomb of Sargeras"
|
|
local guildName = "Rock Lobster"
|
|
local func = {Details.OpenRaidHistoryWindow, Details, raid_name, 2050, 15, my_role, guildName} --, 2, UnitName ("player")
|
|
--local icon = {[[Interface\AddOns\Details\images\icons]], 16, 16, false, 434/512, 466/512, 243/512, 273/512}
|
|
local icon = {[[Interface\PvPRankBadges\PvPRank08]], 16, 16, false, 0, 1, 0, 1}
|
|
|
|
local lower_instance = Details:GetLowerInstanceNumber()
|
|
local instance = Details:GetInstance(lower_instance)
|
|
|
|
instance:InstanceAlert ("Boss Defeated! Show Ranking", icon, 10, func, true)
|
|
|
|
elseif (msg == "scroll" or msg == "scrolldamage" or msg == "scrolling") then
|
|
Details:ScrollDamage()
|
|
|
|
elseif (msg == "me" or msg == "ME" or msg == "Me" or msg == "mE") then
|
|
Details.slash_me_used = true
|
|
local UnitGroupRolesAssigned = detailsFramework.UnitGroupRolesAssigned
|
|
local role = UnitGroupRolesAssigned("player")
|
|
if (role == "HEALER") then
|
|
Details:OpenPlayerDetails(2)
|
|
else
|
|
Details:OpenPlayerDetails(1)
|
|
end
|
|
|
|
elseif (msg == "spec") then
|
|
|
|
local spec = detailsFramework.GetSpecialization()
|
|
if (spec) then
|
|
local specID = detailsFramework.GetSpecializationInfo(spec)
|
|
if (specID and specID ~= 0) then
|
|
print("Current SpecID: ", specID)
|
|
end
|
|
end
|
|
|
|
elseif (msg == "senditemlevel") then
|
|
Details:SendCharacterData()
|
|
print("Item level dispatched.")
|
|
|
|
elseif (msg == "talents") then
|
|
local talents = {}
|
|
for i = 1, 7 do
|
|
for o = 1, 3 do
|
|
local talentID, name, texture, selected, available = GetTalentInfo (i, o, 1)
|
|
if (selected) then
|
|
table.insert(talents, talentID)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
print("talentID", "name", "texture", "selected", "available", "spellID", "unknown", "row", "column", "unknown", "unknown")
|
|
for i = 1, #talents do
|
|
print(GetTalentInfoByID (talents [i]))
|
|
end
|
|
|
|
elseif (msg == "merge") then
|
|
|
|
--at this point, details! should not be in combat
|
|
if (Details.in_combat) then
|
|
Details:Msg("already in combat, closing current segment.")
|
|
Details:SairDoCombate()
|
|
end
|
|
|
|
--create a new combat to be the overall for the mythic run
|
|
Details222.StartCombat()
|
|
|
|
--get the current combat just created and the table with all past segments
|
|
local newCombat = Details:GetCurrentCombat()
|
|
local segmentHistory = Details:GetCombatSegments()
|
|
local totalTime = 0
|
|
local startDate, endDate = "", ""
|
|
local lastSegment
|
|
local segmentsAdded = 0
|
|
|
|
--add all boss segments from this run to this new segment
|
|
for i = 1, 25 do
|
|
local pastCombat = segmentHistory [i]
|
|
if (pastCombat and pastCombat ~= newCombat) then
|
|
newCombat = newCombat + pastCombat
|
|
totalTime = totalTime + pastCombat:GetCombatTime()
|
|
if (i == 1) then
|
|
local _, endedDate = pastCombat:GetDate()
|
|
endDate = endedDate
|
|
end
|
|
lastSegment = pastCombat
|
|
segmentsAdded = segmentsAdded + 1
|
|
end
|
|
end
|
|
|
|
if (lastSegment) then
|
|
startDate = lastSegment:GetDate()
|
|
end
|
|
|
|
newCombat.is_trash = false
|
|
Details:Msg("done merging, segments: " .. segmentsAdded .. ", total time: " .. detailsFramework:IntegerToTimer(totalTime))
|
|
|
|
--set some data
|
|
newCombat:SetStartTime(GetTime() - totalTime)
|
|
newCombat:SetEndTime(GetTime())
|
|
|
|
newCombat:SetDate(startDate, endDate)
|
|
|
|
--immediatly finishes the segment just started
|
|
Details:SairDoCombate()
|
|
|
|
--cleanup the past segments table
|
|
for i = 25, 1, -1 do
|
|
local pastCombat = segmentHistory [i]
|
|
if (pastCombat and pastCombat ~= newCombat) then
|
|
Details:DestroyCombat(pastCombat)
|
|
--send the event segment removed
|
|
Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED")
|
|
segmentHistory [i] = nil
|
|
end
|
|
end
|
|
|
|
--clear memory
|
|
collectgarbage()
|
|
|
|
Details:InstanceCallDetailsFunc(Details.FadeHandler.Fader, "in", nil, "barras")
|
|
Details:InstanceCallDetailsFunc(Details.UpdateCombatObjectInUse)
|
|
Details:InstanceCallDetailsFunc(Details.AtualizaSoloMode_AfertReset)
|
|
Details:InstanceCallDetailsFunc(Details.ResetaGump)
|
|
Details:RefreshMainWindow(-1, true)
|
|
|
|
elseif (msg == "ej") then
|
|
|
|
local result = {}
|
|
local spellIDs = {}
|
|
|
|
--uldir
|
|
detailsFramework.EncounterJournal.EJ_SelectInstance (1031)
|
|
|
|
-- pega o root section id do boss
|
|
local name, description, encounterID, rootSectionID, link = detailsFramework.EncounterJournal.EJ_GetEncounterInfo (2168) --taloc (primeiro boss de Uldir)
|
|
|
|
--overview
|
|
local sectionInfo = C_EncounterJournal.GetSectionInfo (rootSectionID)
|
|
local nextID = {sectionInfo.siblingSectionID}
|
|
|
|
while (nextID [1]) do
|
|
--get the deepest section in the hierarchy
|
|
local ID = table.remove(nextID)
|
|
local sectionInfo = C_EncounterJournal.GetSectionInfo (ID)
|
|
|
|
if (sectionInfo) then
|
|
table.insert(result, sectionInfo)
|
|
|
|
if (sectionInfo.spellID and type(sectionInfo.spellID) == "number" and sectionInfo.spellID ~= 0) then
|
|
table.insert(spellIDs, sectionInfo.spellID)
|
|
end
|
|
|
|
local nextChild, nextSibling = sectionInfo.firstChildSectionID, sectionInfo.siblingSectionID
|
|
if (nextSibling) then
|
|
table.insert(nextID, nextSibling)
|
|
end
|
|
if (nextChild) then
|
|
table.insert(nextID, nextChild)
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
Details:DumpTable (result)
|
|
|
|
elseif (msg == "saveskin") then
|
|
local skin = Details.skins["Minimalistic"].instance_cprops
|
|
local instance1 = Details:GetInstance(1)
|
|
if (instance1) then
|
|
local exportedValues = {}
|
|
for key, _ in pairs(skin) do
|
|
local value = instance1[key]
|
|
if (value) then
|
|
exportedValues[key] = value
|
|
end
|
|
end
|
|
Details:Dump(exportedValues)
|
|
end
|
|
|
|
elseif (msg == "parselog") then
|
|
|
|
local splitLineInArguments = function(lineText)
|
|
local parsedLine = {}
|
|
for piece in lineText:gmatch("([^,]+)") do
|
|
parsedLine[#parsedLine+1] = piece
|
|
end
|
|
return unpack(parsedLine)
|
|
end
|
|
|
|
local spellsWithMorePayload = {
|
|
["SPELL_DAMAGE"] = true,
|
|
["SPELL_HEAL"] = true,
|
|
["SWING_DAMAGE"] = true,
|
|
["SWING_DAMAGE_LANDED"] = true,
|
|
["RANGE_DAMAGE"] = true,
|
|
["SPELL_DRAIN"] = true,
|
|
["SPELL_ENERGIZE"] = true,
|
|
["DAMAGE_SPLIT"] = true,
|
|
["SPELL_PERIODIC_ENERGIZE"] = true,
|
|
["SPELL_PERIODIC_DAMAGE"] = true,
|
|
["SPELL_PERIODIC_HEAL"] = true,
|
|
}
|
|
|
|
local data = DETAILS_EXTERNAL_LOG
|
|
local t = detailsFramework:SplitTextInLines(data)
|
|
local a = {}
|
|
|
|
local parser = Details.LogParserEvent
|
|
|
|
for i = 1, #t do
|
|
print("line:", i)
|
|
local line = t[i]
|
|
line = line:gsub("\"", "")
|
|
local tokenId = line:match("%s%s(.*)"):match("^(.-),")
|
|
|
|
if (tokenId == "ENCOUNTER_START") then
|
|
Details222.StartCombat()
|
|
end
|
|
|
|
if (tokenId == "ENCOUNTER_END") then
|
|
Details:EndCombat()
|
|
end
|
|
|
|
local newPayload = {0, tokenId, false}
|
|
local payload = {splitLineInArguments(line)}
|
|
|
|
if (spellsWithMorePayload[tokenId]) then
|
|
if (tokenId == "SWING_DAMAGE") then
|
|
for o = 2, 9 do
|
|
newPayload[#newPayload+1] = payload[o]
|
|
end
|
|
|
|
for o = 9+17, #payload do
|
|
newPayload[#newPayload+1] = payload[o]
|
|
end
|
|
else
|
|
for o = 2, 12 do
|
|
newPayload[#newPayload+1] = payload[o]
|
|
end
|
|
|
|
for o = 12+17, #payload do
|
|
newPayload[#newPayload+1] = payload[o]
|
|
end
|
|
end
|
|
|
|
parser(unpack(newPayload))
|
|
else
|
|
for o = 2, #payload do
|
|
newPayload[#newPayload+1] = payload[o]
|
|
print(o, payload[o])
|
|
end
|
|
parser(unpack(newPayload))
|
|
end
|
|
|
|
--local payload = {splitLineInArguments(line)}
|
|
--if (#payload > 25) then
|
|
-- a[tokenId] = payload
|
|
--end
|
|
end
|
|
|
|
--for tokenId, payload in pairs(a) do
|
|
-- print(tokenId, unpack(payload))
|
|
--end
|
|
|
|
elseif (msg == "coach") then
|
|
--if (not UnitIsGroupLeader("player")) then
|
|
-- Details:Msg("you aren't the raid leader.")
|
|
-- return
|
|
--end
|
|
|
|
if (not Details.coach.enabled) then
|
|
Details.Coach.WelcomePanel()
|
|
else
|
|
Details:Msg("coach disabled.")
|
|
Details.Coach.Disable()
|
|
end
|
|
|
|
elseif (msg == "9") then
|
|
print("skin:", Details.skin)
|
|
print("current profile:", Details:GetCurrentProfileName())
|
|
print("always use profile:", Details.always_use_profile)
|
|
print("profile name:", Details.always_use_profile_name)
|
|
print("version:", Details.build_counter >= Details.alpha_build_counter and Details.build_counter or Details.alpha_build_counter)
|
|
|
|
elseif (msg == "recordtest") then
|
|
|
|
local f = DetailsRecordFrameAnimation
|
|
if (not f) then
|
|
f = CreateFrame("frame", "DetailsRecordFrameAnimation", UIParent)
|
|
|
|
--estrela no inicio dando um giro
|
|
--Interface\Cooldown\star4
|
|
--efeito de batida?
|
|
--Interface\Artifacts\ArtifactAnim2
|
|
local animationHub = detailsFramework:CreateAnimationHub (f, function() f:Show() end)
|
|
|
|
detailsFramework:CreateAnimation(animationHub, "Scale", 1, .10, .9, .9, 1.1, 1.1)
|
|
detailsFramework:CreateAnimation(animationHub, "Scale", 2, .10, 1.2, 1.2, 1, 1)
|
|
end
|
|
|
|
--BFA BETA
|
|
--elseif (msg == "update") then
|
|
-- _detalhes:CopyPaste ([[https://www.wowinterface.com/downloads/info23056-DetailsDamageMeter8.07.3.5.html]])
|
|
|
|
elseif (msg == "auras") then
|
|
Details.AuraTracker.Open()
|
|
|
|
elseif (msg == "generatespelllist") then
|
|
Details.GenerateSpecSpellList()
|
|
|
|
elseif (msg == "generateracialslist") then
|
|
Details.GenerateRacialSpellList()
|
|
|
|
elseif (msg == "bug") then
|
|
dumpt(DETAILS_FAILED_ACTOR or {"No bug to report here."})
|
|
|
|
elseif (msg == "spellcat") then
|
|
Details.Survey.OpenSurveyPanel()
|
|
|
|
elseif (msg == "pstate") then
|
|
local sEngineState = Details222.Parser.GetState()
|
|
Details:Msg("Parser State:", sEngineState)
|
|
else
|
|
|
|
--if (_detalhes.opened_windows < 1) then
|
|
-- _detalhes:CriarInstancia()
|
|
--end
|
|
|
|
if (command) then
|
|
--check if the line passed is a parameters in the default profile
|
|
if (Details.default_profile [command]) then
|
|
if (rest and (rest ~= "" and rest ~= " ")) then
|
|
local whichType = type(Details.default_profile [command])
|
|
|
|
--attempt to cast the passed value to the same value as the type in the profile
|
|
if (whichType == "number") then
|
|
rest = tonumber(rest)
|
|
if (rest) then
|
|
Details [command] = rest
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' set to " .. rest)
|
|
else
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' expects a number")
|
|
end
|
|
|
|
elseif (whichType == "string") then
|
|
rest = tostring(rest)
|
|
if (rest) then
|
|
Details [command] = rest
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' set to " .. rest)
|
|
else
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' expects a string")
|
|
end
|
|
|
|
elseif (whichType == "boolean") then
|
|
if (rest == "true") then
|
|
Details [command] = true
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' set to true")
|
|
|
|
elseif (rest == "false") then
|
|
Details [command] = false
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' set to false")
|
|
|
|
else
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' expects true or false")
|
|
end
|
|
end
|
|
|
|
else
|
|
local value = Details [command]
|
|
if (type(value) == "boolean") then
|
|
value = value and "true" or "false"
|
|
end
|
|
print(Loc ["STRING_DETAILS1"] .. "config '" .. command .. "' current value is: " .. value)
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
end
|
|
|
|
print("|cffffaeae/details|r |cffffff33" .. Loc ["STRING_SLASH_SHOW"] .. " " .. Loc ["STRING_SLASH_HIDE"] .. " " .. Loc ["STRING_SLASH_TOGGLE"] .. "|r|cfffcffb0 <" .. Loc ["STRING_WINDOW_NUMBER"] .. ">|r: " .. Loc ["STRING_SLASH_SHOWHIDETOGGLE_DESC"])
|
|
print("|cffffaeae/details|r |cffffff33" .. Loc ["STRING_SLASH_RESET"] .. "|r: " .. Loc ["STRING_SLASH_RESET_DESC"])
|
|
print("|cffffaeae/details|r |cffffff33" .. Loc ["STRING_SLASH_OPTIONS"] .. "|r|cfffcffb0 <" .. Loc ["STRING_WINDOW_NUMBER"] .. ">|r: " .. Loc ["STRING_SLASH_OPTIONS_DESC"])
|
|
print("|cffffaeae/details|r |cffffff33" .. "API" .. "|r: " .. Loc ["STRING_SLASH_API_DESC"])
|
|
print("|cffffaeae/details|r |cffffff33" .. "me" .. "|r: open the player breakdown for you.") --localize-me
|
|
print("|cffffaeae/details|r |cffffff33" .. "spells" .. "|r: list of spells already saw.") --localize-me
|
|
|
|
print("|cFFFFFF00DETAILS! VERSION|r:|cFFFFAA00" .. " " .. Details.GetVersionString())
|
|
print("|cffffaeae/details|r |cffffff33" .. "version" .. "|r: copy version.")
|
|
|
|
end
|
|
end
|
|
|
|
function Details.RefreshUserList (ignoreIfHidden)
|
|
|
|
if (ignoreIfHidden and DetailsUserPanel and not DetailsUserPanel:IsShown()) then
|
|
return
|
|
end
|
|
|
|
local newList = detailsFramework.table.copy({}, Details.users or {})
|
|
|
|
table.sort (newList, function(t1, t2)
|
|
return t1[3] > t2[3]
|
|
end)
|
|
|
|
--search for people that didn't answered
|
|
if (IsInRaid()) then
|
|
for i = 1, GetNumGroupMembers() do
|
|
local playerName = UnitName ("raid" .. i)
|
|
local foundPlayer
|
|
|
|
for o = 1, #newList do
|
|
if (newList[o][1]:find(playerName)) then
|
|
foundPlayer = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if (not foundPlayer) then
|
|
table.insert(newList, {playerName, "--", "--"})
|
|
end
|
|
end
|
|
end
|
|
|
|
Details:UpdateUserPanel (newList)
|
|
end
|
|
|
|
function Details:UpdateUserPanel(usersTable)
|
|
if (not Details.UserPanel) then
|
|
local frameWidth, frameHeight = 470, 605
|
|
DetailsUserPanel = detailsFramework:CreateSimplePanel(UIParent)
|
|
DetailsUserPanel:SetSize(frameWidth, frameHeight)
|
|
DetailsUserPanel:SetTitle("Details! Version Check")
|
|
DetailsUserPanel.Data = {}
|
|
DetailsUserPanel:ClearAllPoints()
|
|
DetailsUserPanel:SetPoint("left", UIParent, "left", 5, 100)
|
|
DetailsUserPanel:Hide()
|
|
|
|
detailsFramework:ApplyStandardBackdrop(DetailsUserPanel)
|
|
|
|
Details.UserPanel = DetailsUserPanel
|
|
|
|
local scroll_width = frameWidth - 30
|
|
local scroll_height = 605 - 60
|
|
local scroll_lines = 26
|
|
local scroll_line_height = 20
|
|
|
|
local backdrop_color = {.2, .2, .2, 0.2}
|
|
local backdrop_color_on_enter = {.8, .8, .8, 0.4}
|
|
local backdrop_color_is_critical = {.4, .4, .2, 0.2}
|
|
local backdrop_color_is_critical_on_enter = {1, 1, .8, 0.4}
|
|
|
|
local y = -15
|
|
local headerY = y - 15
|
|
local scrollY = headerY - 20
|
|
|
|
--header
|
|
local headerTable = {
|
|
{text = "User Name", width = 160},
|
|
{text = "Realm", width = 130},
|
|
{text = "Version", width = 140},
|
|
}
|
|
|
|
local headerOptions = {
|
|
padding = 2,
|
|
}
|
|
|
|
DetailsUserPanel.Header = detailsFramework:CreateHeader(DetailsUserPanel, headerTable, headerOptions)
|
|
DetailsUserPanel.Header:SetPoint("topleft", DetailsUserPanel, "topleft", 5, headerY)
|
|
|
|
local scrollRefresh = function(self, data, offset, total_lines)
|
|
--store user names shown
|
|
local userShown = {}
|
|
local lineId = 1
|
|
for i = 1, total_lines do
|
|
local index = i + offset
|
|
local userTable = data [index]
|
|
|
|
if (userTable) then
|
|
local userName, userRealm, userVersion = unpack(userTable)
|
|
if (not userShown[userName]) then
|
|
local line = self:GetLine(lineId)
|
|
local onlyUserName = detailsFramework:RemoveRealmName(userName)
|
|
line.UserNameText.text = onlyUserName
|
|
line.RealmText.text = userRealm
|
|
line.VersionText.text = userVersion
|
|
userShown[userName] = true
|
|
lineId = lineId + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local lineOnEnter = function(self)
|
|
if (self.IsCritical) then
|
|
self:SetBackdropColor(unpack(backdrop_color_is_critical_on_enter))
|
|
else
|
|
self:SetBackdropColor(unpack(backdrop_color_on_enter))
|
|
end
|
|
end
|
|
|
|
local lineOnLeave = function(self)
|
|
if (self.IsCritical) then
|
|
self:SetBackdropColor(unpack(backdrop_color_is_critical))
|
|
else
|
|
self:SetBackdropColor(unpack(backdrop_color))
|
|
end
|
|
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local scroll_createline = function(self, index)
|
|
local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate")
|
|
line:SetPoint("topleft", self, "topleft", 3, -((index-1)*(scroll_line_height+1)) - 1)
|
|
line:SetSize(scroll_width - 2, scroll_line_height)
|
|
|
|
line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
line:SetBackdropColor(unpack(backdrop_color))
|
|
|
|
detailsFramework:Mixin(line, detailsFramework.HeaderFunctions)
|
|
|
|
line:SetScript("OnEnter", lineOnEnter)
|
|
line:SetScript("OnLeave", lineOnLeave)
|
|
|
|
--username
|
|
local userNameText = detailsFramework:CreateLabel(line)
|
|
|
|
--realm
|
|
local realmText = detailsFramework:CreateLabel(line)
|
|
|
|
--version
|
|
local versionText = detailsFramework:CreateLabel(line)
|
|
|
|
line:AddFrameToHeaderAlignment (userNameText)
|
|
line:AddFrameToHeaderAlignment (realmText)
|
|
line:AddFrameToHeaderAlignment (versionText)
|
|
|
|
line:AlignWithHeader (DetailsUserPanel.Header, "left")
|
|
|
|
line.UserNameText = userNameText
|
|
line.RealmText = realmText
|
|
line.VersionText = versionText
|
|
|
|
return line
|
|
end
|
|
|
|
local usersScroll = detailsFramework:CreateScrollBox (DetailsUserPanel, "$parentUsersScroll", scrollRefresh, DetailsUserPanel.Data, scroll_width, scroll_height, scroll_lines, scroll_line_height)
|
|
detailsFramework:ReskinSlider(usersScroll)
|
|
usersScroll:SetPoint("topleft", DetailsUserPanel, "topleft", 5, scrollY)
|
|
Details.UserPanel.ScrollBox = usersScroll
|
|
|
|
--create lines
|
|
for i = 1, scroll_lines do
|
|
usersScroll:CreateLine (scroll_createline)
|
|
end
|
|
|
|
DetailsUserPanel:SetScript("OnShow", function()
|
|
end)
|
|
|
|
DetailsUserPanel:SetScript("OnHide", function()
|
|
end)
|
|
end
|
|
|
|
Details.UserPanel.ScrollBox:SetData (usersTable)
|
|
Details.UserPanel.ScrollBox:Refresh()
|
|
DetailsUserPanel:Show()
|
|
end
|
|
|
|
function Details:CreateListPanel(name)
|
|
name = name or ("DetailsListPanel" .. math.random(100000, 1000000))
|
|
local newListPanel = Details.gump:NewPanel(UIParent, nil, name, nil, 800, 600)
|
|
newListPanel:SetPoint("center", UIParent, "center", 300, 0)
|
|
newListPanel.lines = {}
|
|
|
|
detailsFramework:ApplyStandardBackdrop(newListPanel.widget)
|
|
|
|
table.insert(UISpecialFrames, name)
|
|
newListPanel.close_with_right = true
|
|
|
|
local container_barras_window = CreateFrame("ScrollFrame", "$parentActorsBarrasScroll", newListPanel.widget, "BackdropTemplate")
|
|
local container_barras = CreateFrame("Frame", "$parentActorsBarras", container_barras_window, "BackdropTemplate")
|
|
newListPanel.container = container_barras
|
|
|
|
newListPanel.width = 835
|
|
newListPanel.locked = false
|
|
|
|
container_barras_window:SetBackdrop({
|
|
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5,
|
|
insets = {left = 1, right = 1, top = 0, bottom = 1},})
|
|
container_barras_window:SetBackdropBorderColor(0, 0, 0, 0)
|
|
|
|
container_barras:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
|
|
insets = {left = 1, right = 1, top = 0, bottom = 1},})
|
|
container_barras:SetBackdropColor(0, 0, 0, 0)
|
|
|
|
container_barras:SetAllPoints(container_barras_window)
|
|
container_barras:SetWidth(800)
|
|
container_barras:SetHeight(550)
|
|
container_barras:EnableMouse(true)
|
|
container_barras:SetResizable(false)
|
|
container_barras:SetMovable(true)
|
|
|
|
container_barras_window:SetWidth(800)
|
|
container_barras_window:SetHeight(550)
|
|
container_barras_window:SetScrollChild(container_barras)
|
|
container_barras_window:SetPoint("TOPLEFT", newListPanel.widget, "TOPLEFT", 21, -10)
|
|
|
|
Details.gump:NewScrollBar (container_barras_window, container_barras, -10, -17)
|
|
container_barras_window.slider:Altura(550)
|
|
container_barras_window.slider:cimaPoint (0, 1)
|
|
container_barras_window.slider:baixoPoint (0, -3)
|
|
container_barras_window.slider:SetFrameLevel(10)
|
|
|
|
container_barras_window.ultimo = 0
|
|
|
|
container_barras_window.gump = container_barras
|
|
|
|
detailsFramework:ReskinSlider(container_barras_window)
|
|
|
|
function newListPanel:reset()
|
|
for i = 1, #newListPanel.lines do
|
|
newListPanel.lines[i].text:Hide()
|
|
end
|
|
end
|
|
|
|
function newListPanel:add(text, index, filter)
|
|
local row = newListPanel.lines[index]
|
|
if (not row) then
|
|
row = {text = newListPanel.container:CreateFontString(nil, "overlay", "GameFontNormal")}
|
|
newListPanel.lines [index] = row
|
|
row.text:SetPoint("topleft", newListPanel.container, "topleft", 0, -index * 15)
|
|
end
|
|
|
|
if (filter and text:find(filter)) then
|
|
row.text:SetTextColor(1, 1, 0)
|
|
else
|
|
row.text:SetTextColor(1, 1, 1)
|
|
end
|
|
|
|
row.text:SetText(text)
|
|
row.text:Show()
|
|
end
|
|
|
|
return newListPanel
|
|
end
|
|
|
|
|
|
--this table store addons which want to replace the keystone command
|
|
--more than one addon can be registered and all of them will be called when the user type /keystone
|
|
--is up to the user to decide which addon to use
|
|
local keystoneCallbacks = {}
|
|
|
|
---register an addon and a callback function to be called when the user type /keystone
|
|
---@param addonObject table
|
|
---@param memberName string
|
|
---@param ... any
|
|
---@return boolean true if the addon was registered, false if it was already registered and got unregistered
|
|
function Details:ReplaceKeystoneCommand(addonObject, memberName, ...)
|
|
--check if the parameters passed are valid types
|
|
if (type(addonObject) ~= "table") then
|
|
error("Details:ReplaceKeystoneCommand: addonObject must be a table")
|
|
|
|
elseif (type(memberName) ~= "string") then
|
|
error("Details:ReplaceKeystoneCommand: memberName must be a string")
|
|
|
|
elseif (type(addonObject[memberName]) ~= "function") then
|
|
error("Details:ReplaceKeystoneCommand: t[memberName] doesn't point to a function.")
|
|
end
|
|
|
|
--check if the addonObject is already registered and remove it
|
|
for i = #keystoneCallbacks, 1, -1 do
|
|
if (keystoneCallbacks[i].addonObject == addonObject) then
|
|
--check if the memberName is the same
|
|
if (keystoneCallbacks[i].memberName == memberName) then
|
|
table.remove(keystoneCallbacks, i)
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
local payload = {...}
|
|
|
|
keystoneCallbacks[#keystoneCallbacks+1] = {
|
|
addonObject = addonObject,
|
|
memberName = memberName,
|
|
payload = payload
|
|
}
|
|
|
|
return true
|
|
end
|
|
|
|
if (WOW_PROJECT_ID == WOW_PROJECT_MAINLINE) then
|
|
SLASH_KEYSTONE1 = "/keystone"
|
|
SLASH_KEYSTONE2 = "/keys"
|
|
SLASH_KEYSTONE3 = "/key"
|
|
|
|
function SlashCmdList.KEYSTONE(msg, editbox)
|
|
--if there is addons registered to use the keystone command, call them and do not show the default frame from details!
|
|
if (#keystoneCallbacks > 0) then
|
|
--loop through all registered addons and call their callback function
|
|
local bCallbackSuccess = false
|
|
for i = 1, #keystoneCallbacks do
|
|
local thisCallback = keystoneCallbacks[i]
|
|
|
|
local addonObject = thisCallback.addonObject
|
|
local memberName = thisCallback.memberName
|
|
local payload = thisCallback.payload
|
|
|
|
if (type(addonObject[memberName]) == "function") then
|
|
local result = detailsFramework:Dispatch(addonObject[memberName], unpack(payload)) --uses xpcall
|
|
if (result ~= false) then
|
|
bCallbackSuccess = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if (bCallbackSuccess) then
|
|
return
|
|
end
|
|
end
|
|
|
|
local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true)
|
|
if (openRaidLib) then
|
|
if (not DetailsKeystoneInfoFrame) then
|
|
---@type detailsframework
|
|
local detailsFramework = detailsFramework
|
|
|
|
local CONST_WINDOW_WIDTH = 614
|
|
local CONST_WINDOW_HEIGHT = 720
|
|
local CONST_SCROLL_LINE_HEIGHT = 20
|
|
local CONST_SCROLL_LINE_AMOUNT = 30
|
|
|
|
local backdrop_color = {.2, .2, .2, 0.2}
|
|
local backdrop_color_on_enter = {.8, .8, .8, 0.4}
|
|
|
|
local backdrop_color_inparty = {.5, .5, .8, 0.2}
|
|
local backdrop_color_on_enter_inparty = {.5, .5, 1, 0.4}
|
|
|
|
local backdrop_color_inguild = {.5, .8, .5, 0.2}
|
|
local backdrop_color_on_enter_inguild = {.5, 1, .5, 0.4}
|
|
|
|
local f = detailsFramework:CreateSimplePanel(UIParent, CONST_WINDOW_WIDTH, CONST_WINDOW_HEIGHT, "M+ Keystones (/key)", "DetailsKeystoneInfoFrame")
|
|
f:SetPoint("center", UIParent, "center", 0, 0)
|
|
|
|
f:SetScript("OnMouseDown", nil) --disable framework native moving scripts
|
|
f:SetScript("OnMouseUp", nil) --disable framework native moving scripts
|
|
|
|
local LibWindow = LibStub("LibWindow-1.1")
|
|
LibWindow.RegisterConfig(f, Details.keystone_frame.position)
|
|
LibWindow.MakeDraggable(f)
|
|
LibWindow.RestorePosition(f)
|
|
|
|
f:SetScript("OnEvent", function(self, event, ...)
|
|
if (f:IsShown()) then
|
|
if (event == "GUILD_ROSTER_UPDATE") then
|
|
self:RefreshData()
|
|
end
|
|
end
|
|
end)
|
|
|
|
local scaleBar = detailsFramework:CreateScaleBar(f, Details.keystone_frame)
|
|
f:SetScale(Details.keystone_frame.scale)
|
|
|
|
local statusBar = detailsFramework:CreateStatusBar(f)
|
|
statusBar.text = statusBar:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
statusBar.text:SetPoint("left", statusBar, "left", 5, 0)
|
|
statusBar.text:SetText("By Terciob | From Details! Damage Meter")
|
|
detailsFramework:SetFontSize(statusBar.text, 12)
|
|
detailsFramework:SetFontColor(statusBar.text, "gray")
|
|
|
|
local requestFromGuildButton = detailsFramework:CreateButton(f, function()
|
|
local guildName = GetGuildInfo("player")
|
|
if (guildName) then
|
|
f:RegisterEvent("GUILD_ROSTER_UPDATE")
|
|
|
|
C_Timer.NewTicker(1, function()
|
|
f:RefreshData()
|
|
end, 30)
|
|
|
|
C_Timer.After(30, function()
|
|
f:UnregisterEvent("GUILD_ROSTER_UPDATE")
|
|
end)
|
|
C_GuildInfo.GuildRoster()
|
|
|
|
openRaidLib.RequestKeystoneDataFromGuild()
|
|
end
|
|
end, 100, 22, "Request from Guild")
|
|
requestFromGuildButton:SetPoint("bottomleft", statusBar, "topleft", 2, 2)
|
|
requestFromGuildButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
requestFromGuildButton:SetIcon("UI-RefreshButton", 20, 20, "overlay", {0, 1, 0, 1}, "lawngreen")
|
|
requestFromGuildButton:SetFrameLevel(f:GetFrameLevel()+5)
|
|
f.RequestFromGuildButton = requestFromGuildButton
|
|
|
|
--header
|
|
local headerTable = {
|
|
{text = "Class", width = 40, canSort = true, dataType = "number", order = "DESC", offset = 0},
|
|
{text = "Player Name", width = 140, canSort = true, dataType = "string", order = "DESC", offset = 0},
|
|
{text = "Level", width = 60, canSort = true, dataType = "number", order = "DESC", offset = 0, selected = true},
|
|
{text = "Dungeon", width = 240, canSort = true, dataType = "string", order = "DESC", offset = 0},
|
|
--{text = "Classic Dungeon", width = 120, canSort = true, dataType = "string", order = "DESC", offset = 0},
|
|
{text = "Mythic+ Rating", width = 100, canSort = true, dataType = "number", order = "DESC", offset = 0},
|
|
}
|
|
|
|
local headerOnClickCallback = function(headerFrame, columnHeader)
|
|
f.RefreshData()
|
|
end
|
|
|
|
local headerOptions = {
|
|
padding = 1,
|
|
header_backdrop_color = {.3, .3, .3, .8},
|
|
header_backdrop_color_selected = {.5, .5, .5, 0.8},
|
|
use_line_separators = true,
|
|
line_separator_color = {.1, .1, .1, .5},
|
|
line_separator_width = 1,
|
|
line_separator_height = CONST_WINDOW_HEIGHT-30,
|
|
line_separator_gap_align = true,
|
|
header_click_callback = headerOnClickCallback,
|
|
}
|
|
|
|
f.Header = detailsFramework:CreateHeader(f, headerTable, headerOptions, "DetailsKeystoneInfoFrameHeader")
|
|
f.Header:SetPoint("topleft", f, "topleft", 3, -25)
|
|
|
|
--scroll
|
|
local refreshScrollLines = function(self, data, offset, totalLines)
|
|
local RaiderIO = _G.RaiderIO
|
|
local faction = UnitFactionGroup("player") --this can get problems with 9.2.5 cross faction raiding
|
|
|
|
for i = 1, totalLines do
|
|
local index = i + offset
|
|
local unitTable = data[index]
|
|
|
|
if (unitTable) then
|
|
local line = self:GetLine(i)
|
|
|
|
local unitName, level, mapID, challengeMapID, classID, rating, mythicPlusMapID, classIconTexture, iconTexCoords, mapName, inMyParty, isOnline, isGuildMember = unpack(unitTable)
|
|
|
|
if (mapName == "") then
|
|
mapName = "user need update details!"
|
|
end
|
|
|
|
local rioProfile
|
|
if (RaiderIO) then
|
|
local playerName, playerRealm = unitName:match("(.+)%-(.+)")
|
|
if (playerName and playerRealm) then
|
|
rioProfile = RaiderIO.GetProfile(playerName, playerRealm, faction == "Horde" and 2 or 1)
|
|
if (rioProfile) then
|
|
rioProfile = rioProfile.mythicKeystoneProfile
|
|
end
|
|
else
|
|
rioProfile = RaiderIO.GetProfile(unitName, GetRealmName(), faction == "Horde" and 2 or 1)
|
|
if (rioProfile) then
|
|
rioProfile = rioProfile.mythicKeystoneProfile
|
|
end
|
|
end
|
|
end
|
|
|
|
line.icon:SetTexture(classIconTexture)
|
|
local L, R, T, B = unpack(iconTexCoords)
|
|
line.icon:SetTexCoord(L+0.02, R-0.02, T+0.02, B-0.02)
|
|
|
|
--remove the realm name from the player name (if any)
|
|
local unitNameNoRealm = detailsFramework:RemoveRealmName(unitName)
|
|
line.playerNameText.text = unitNameNoRealm
|
|
line.keystoneLevelText.text = level
|
|
line.dungeonNameText.text = mapName
|
|
detailsFramework:TruncateText(line.dungeonNameText, 240)
|
|
line.classicDungeonNameText.text = "" --mapNameChallenge
|
|
detailsFramework:TruncateText(line.classicDungeonNameText, 120)
|
|
line.inMyParty = inMyParty > 0
|
|
line.inMyGuild = isGuildMember
|
|
|
|
if (rioProfile) then
|
|
local score = rioProfile.currentScore or 0
|
|
local previousScore = rioProfile.previousScore or 0
|
|
if (previousScore > score) then
|
|
score = previousScore
|
|
line.ratingText.text = rating .. " (" .. score .. ")"
|
|
else
|
|
line.ratingText.text = rating
|
|
end
|
|
else
|
|
line.ratingText.text = rating
|
|
end
|
|
|
|
if (line.inMyParty) then
|
|
line:SetBackdropColor(unpack(backdrop_color_inparty))
|
|
elseif (isGuildMember) then
|
|
line:SetBackdropColor(unpack(backdrop_color_inguild))
|
|
else
|
|
line:SetBackdropColor(unpack(backdrop_color))
|
|
end
|
|
|
|
if (isOnline) then
|
|
line.playerNameText.textcolor = "white"
|
|
line.keystoneLevelText.textcolor = "white"
|
|
line.dungeonNameText.textcolor = "white"
|
|
line.classicDungeonNameText.textcolor = "white"
|
|
line.ratingText.textcolor = "white"
|
|
line.icon:SetAlpha(1)
|
|
else
|
|
line.playerNameText.textcolor = "gray"
|
|
line.keystoneLevelText.textcolor = "gray"
|
|
line.dungeonNameText.textcolor = "gray"
|
|
line.classicDungeonNameText.textcolor = "gray"
|
|
line.ratingText.textcolor = "gray"
|
|
line.icon:SetAlpha(.6)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local scrollFrame = detailsFramework:CreateScrollBox(f, "$parentScroll", refreshScrollLines, {}, CONST_WINDOW_WIDTH-10, CONST_WINDOW_HEIGHT-90, CONST_SCROLL_LINE_AMOUNT, CONST_SCROLL_LINE_HEIGHT)
|
|
detailsFramework:ReskinSlider(scrollFrame)
|
|
scrollFrame:SetPoint("topleft", f.Header, "bottomleft", -1, -1)
|
|
scrollFrame:SetPoint("topright", f.Header, "bottomright", 0, -1)
|
|
|
|
local lineOnEnter = function(self)
|
|
if (self.inMyParty) then
|
|
self:SetBackdropColor(unpack(backdrop_color_on_enter_inparty))
|
|
elseif (self.inMyGuild) then
|
|
self:SetBackdropColor(unpack(backdrop_color_on_enter_inguild))
|
|
else
|
|
self:SetBackdropColor(unpack(backdrop_color_on_enter))
|
|
end
|
|
end
|
|
local lineOnLeave = function(self)
|
|
if (self.inMyParty) then
|
|
self:SetBackdropColor(unpack(backdrop_color_inparty))
|
|
elseif (self.inMyGuild) then
|
|
self:SetBackdropColor(unpack(backdrop_color_inguild))
|
|
else
|
|
self:SetBackdropColor(unpack(backdrop_color))
|
|
end
|
|
end
|
|
|
|
local createLineForScroll = function(self, index)
|
|
local line = CreateFrame("frame", "$parentLine" .. index, self, "BackdropTemplate")
|
|
line:SetPoint("topleft", self, "topleft", 1, -((index-1) * (CONST_SCROLL_LINE_HEIGHT + 1)) - 1)
|
|
line:SetSize(scrollFrame:GetWidth() - 2, CONST_SCROLL_LINE_HEIGHT)
|
|
|
|
line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
line:SetBackdropColor(unpack(backdrop_color))
|
|
|
|
detailsFramework:Mixin(line, detailsFramework.HeaderFunctions)
|
|
|
|
line:SetScript("OnEnter", lineOnEnter)
|
|
line:SetScript("OnLeave", lineOnLeave)
|
|
|
|
--class icon
|
|
local icon = line:CreateTexture("$parentClassIcon", "overlay")
|
|
icon:SetSize(CONST_SCROLL_LINE_HEIGHT - 2, CONST_SCROLL_LINE_HEIGHT - 2)
|
|
|
|
--player name
|
|
local playerNameText = detailsFramework:CreateLabel(line, "")
|
|
|
|
--keystone level
|
|
local keystoneLevelText = detailsFramework:CreateLabel(line, "")
|
|
|
|
--dungeon name
|
|
local dungeonNameText = detailsFramework:CreateLabel(line, "")
|
|
|
|
--classic dungeon name
|
|
local classicDungeonNameText = detailsFramework:CreateLabel(line, "")
|
|
|
|
--player rating
|
|
local ratingText = detailsFramework:CreateLabel(line, "")
|
|
|
|
line.icon = icon
|
|
line.playerNameText = playerNameText
|
|
line.keystoneLevelText = keystoneLevelText
|
|
line.dungeonNameText = dungeonNameText
|
|
line.classicDungeonNameText = classicDungeonNameText
|
|
line.ratingText = ratingText
|
|
|
|
line:AddFrameToHeaderAlignment(icon)
|
|
line:AddFrameToHeaderAlignment(playerNameText)
|
|
line:AddFrameToHeaderAlignment(keystoneLevelText)
|
|
line:AddFrameToHeaderAlignment(dungeonNameText)
|
|
--line:AddFrameToHeaderAlignment(classicDungeonNameText)
|
|
line:AddFrameToHeaderAlignment(ratingText)
|
|
|
|
line:AlignWithHeader(f.Header, "left")
|
|
return line
|
|
end
|
|
|
|
--create lines
|
|
for i = 1, CONST_SCROLL_LINE_AMOUNT do
|
|
scrollFrame:CreateLine(createLineForScroll)
|
|
end
|
|
|
|
function f.RefreshData()
|
|
local newData = {}
|
|
newData.offlineGuildPlayers = {}
|
|
local keystoneData = openRaidLib.GetAllKeystonesInfo()
|
|
|
|
--[=[
|
|
["Exudragão"] = {
|
|
["mapID"] = 2526,
|
|
["challengeMapID"] = 402,
|
|
["mythicPlusMapID"] = 0,
|
|
["rating"] = 215,
|
|
["classID"] = 13,
|
|
["level"] = 6,
|
|
},
|
|
--]=]
|
|
|
|
local guildUsers = {}
|
|
local totalMembers, onlineMembers, onlineAndMobileMembers = GetNumGuildMembers()
|
|
|
|
--[=[
|
|
local unitsInMyGroup = {
|
|
[Details:GetFullName("player")] = true,
|
|
}
|
|
for i = 1, GetNumGroupMembers() do
|
|
local unitName = Details:GetFullName("party" .. i)
|
|
unitsInMyGroup[unitName] = true
|
|
end
|
|
--]=]
|
|
|
|
--create a string to use into the gsub call when removing the realm name from the player name, by default all player names returned from GetGuildRosterInfo() has PlayerName-RealmName format
|
|
local realmNameGsub = "%-.*"
|
|
local guildName = GetGuildInfo("player")
|
|
|
|
if (guildName) then
|
|
for i = 1, totalMembers do
|
|
local fullName, rank, rankIndex, level, class, zone, note, officernote, online, isAway, classFileName, achievementPoints, achievementRank, isMobile, canSoR, repStanding, guid = GetGuildRosterInfo(i)
|
|
if (fullName) then
|
|
fullName = fullName:gsub(realmNameGsub, "")
|
|
if (online) then
|
|
guildUsers[fullName] = true
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if (keystoneData) then
|
|
local unitsAdded = {}
|
|
local isOnline = true
|
|
|
|
for unitName, keystoneInfo in pairs(keystoneData) do
|
|
local classId = keystoneInfo.classID
|
|
local classIcon = [[Interface\GLUES\CHARACTERCREATE\UI-CharacterCreate-Classes]]
|
|
local coords = CLASS_ICON_TCOORDS
|
|
local _, class = GetClassInfo(classId)
|
|
|
|
local mapName = C_ChallengeMode.GetMapUIInfo(keystoneInfo.mythicPlusMapID)
|
|
if (not mapName) then
|
|
mapName = C_ChallengeMode.GetMapUIInfo(keystoneInfo.challengeMapID)
|
|
end
|
|
if (not mapName and keystoneInfo.mapID) then
|
|
mapName = C_ChallengeMode.GetMapUIInfo(keystoneInfo.mapID)
|
|
end
|
|
|
|
mapName = mapName or "map name not found"
|
|
|
|
--local mapInfoChallenge = C_Map.GetMapInfo(keystoneInfo.challengeMapID)
|
|
--local mapNameChallenge = mapInfoChallenge and mapInfoChallenge.name or ""
|
|
|
|
local isInMyParty = UnitInParty(unitName) and (string.byte(unitName, 1) + string.byte(unitName, 2)) or 0
|
|
local isGuildMember = guildName and guildUsers[unitName] and true
|
|
|
|
if (keystoneInfo.level > 0 or keystoneInfo.rating > 0) then
|
|
local keystoneTable = {
|
|
unitName,
|
|
keystoneInfo.level,
|
|
keystoneInfo.mapID,
|
|
keystoneInfo.challengeMapID,
|
|
keystoneInfo.classID,
|
|
keystoneInfo.rating,
|
|
keystoneInfo.mythicPlusMapID,
|
|
classIcon,
|
|
coords[class],
|
|
mapName, --10
|
|
isInMyParty,
|
|
isOnline, --is false when the unit is from the cache
|
|
isGuildMember, --is a guild member
|
|
--mapNameChallenge,
|
|
}
|
|
|
|
newData[#newData+1] = keystoneTable --this is the table added into the keystone cache
|
|
unitsAdded[unitName] = true
|
|
|
|
--is this unitName listed as a player in the player's guild?
|
|
if (isGuildMember) then
|
|
--store the player information into a cache
|
|
keystoneTable.guild_name = guildName
|
|
keystoneTable.date = time()
|
|
Details.keystone_cache[unitName] = keystoneTable
|
|
end
|
|
end
|
|
end
|
|
|
|
local cutoffDate = time() - (86400 * 7) --7 days
|
|
for unitName, keystoneTable in pairs(Details.keystone_cache) do
|
|
--this unit in the cache isn't shown?
|
|
if (not unitsAdded[unitName] and keystoneTable.guild_name == guildName and keystoneTable.date > cutoffDate) then
|
|
if (keystoneTable[2] > 0 or keystoneTable[6] > 0) then
|
|
keystoneTable[11] = UnitInParty(unitName) and (string.byte(unitName, 1) + string.byte(unitName, 2)) or 0 --isInMyParty
|
|
keystoneTable[12] = false --isOnline
|
|
newData[#newData+1] = keystoneTable
|
|
unitsAdded[unitName] = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--get which column is currently selected and the sort order
|
|
local columnIndex, order = f.Header:GetSelectedColumn()
|
|
local sortByIndex = 2
|
|
|
|
--sort by player class
|
|
if (columnIndex == 1) then
|
|
sortByIndex = 5
|
|
|
|
--sort by player name
|
|
elseif (columnIndex == 2) then
|
|
sortByIndex = 1
|
|
|
|
--sort by keystone level
|
|
elseif (columnIndex == 3) then
|
|
sortByIndex = 2
|
|
|
|
--sort by dungeon name
|
|
elseif (columnIndex == 4) then
|
|
sortByIndex = 3
|
|
|
|
--sort by classic dungeon name
|
|
--elseif (columnIndex == 5) then
|
|
-- sortByIndex = 4
|
|
|
|
--sort by mythic+ ranting
|
|
elseif (columnIndex == 5) then
|
|
sortByIndex = 6
|
|
end
|
|
|
|
if (order == "DESC") then
|
|
table.sort(newData, function(t1, t2) return t1[sortByIndex] > t2[sortByIndex] end)
|
|
else
|
|
table.sort(newData, function(t1, t2) return t1[sortByIndex] < t2[sortByIndex] end)
|
|
end
|
|
|
|
--remove offline guild players from the list
|
|
for i = #newData, 1, -1 do
|
|
local keystoneTable = newData[i]
|
|
if (not keystoneTable[12]) then
|
|
table.remove(newData, i)
|
|
newData.offlineGuildPlayers[#newData.offlineGuildPlayers+1] = keystoneTable
|
|
end
|
|
end
|
|
|
|
newData.offlineGuildPlayers = detailsFramework.table.reverse(newData.offlineGuildPlayers)
|
|
|
|
--put players in the group at the top of the list
|
|
if (IsInGroup() and not IsInRaid()) then
|
|
local playersInTheParty = {}
|
|
for i = #newData, 1, -1 do
|
|
local keystoneTable = newData[i]
|
|
if (keystoneTable[11] > 0) then
|
|
playersInTheParty[#playersInTheParty+1] = keystoneTable
|
|
table.remove(newData, i)
|
|
end
|
|
end
|
|
|
|
if (#playersInTheParty > 0) then
|
|
table.sort(playersInTheParty, function(t1, t2) return t1[11] > t2[11] end)
|
|
for i = 1, #playersInTheParty do
|
|
local keystoneTable = playersInTheParty[i]
|
|
table.insert(newData, 1, keystoneTable)
|
|
end
|
|
end
|
|
end
|
|
|
|
--reinsert offline guild players into the data
|
|
local offlinePlayers = newData.offlineGuildPlayers
|
|
for i = 1, #offlinePlayers do
|
|
local keystoneTable = offlinePlayers[i]
|
|
newData[#newData+1] = keystoneTable
|
|
end
|
|
|
|
scrollFrame:SetData(newData)
|
|
scrollFrame:Refresh()
|
|
end
|
|
|
|
function f.OnKeystoneUpdate(unitId, keystoneInfo, allKeystonesInfo)
|
|
if (f:IsShown()) then
|
|
f.RefreshData()
|
|
end
|
|
end
|
|
|
|
f:SetScript("OnHide", function()
|
|
openRaidLib.UnregisterCallback(DetailsKeystoneInfoFrame, "KeystoneUpdate", "OnKeystoneUpdate")
|
|
end)
|
|
|
|
f:SetScript("OnUpdate", function(self, deltaTime)
|
|
if (not self.lastUpdate) then
|
|
self.lastUpdate = 0
|
|
end
|
|
|
|
self.lastUpdate = self.lastUpdate + deltaTime
|
|
if (self.lastUpdate > 1) then
|
|
self.lastUpdate = 0
|
|
self.RefreshData()
|
|
end
|
|
end)
|
|
end
|
|
|
|
--show the frame
|
|
DetailsKeystoneInfoFrame:Show()
|
|
|
|
openRaidLib.RegisterCallback(DetailsKeystoneInfoFrame, "KeystoneUpdate", "OnKeystoneUpdate")
|
|
|
|
local guildName = GetGuildInfo("player")
|
|
if (guildName) then
|
|
--call an update on the guild roster
|
|
if (C_GuildInfo and C_GuildInfo.GuildRoster) then
|
|
C_GuildInfo.GuildRoster()
|
|
end
|
|
DetailsKeystoneInfoFrame.RequestFromGuildButton:Enable()
|
|
else
|
|
DetailsKeystoneInfoFrame.RequestFromGuildButton:Disable()
|
|
end
|
|
|
|
--openRaidLib.WipeKeystoneData()
|
|
|
|
if (IsInRaid()) then
|
|
openRaidLib.RequestKeystoneDataFromRaid()
|
|
elseif (IsInGroup()) then
|
|
openRaidLib.RequestKeystoneDataFromParty()
|
|
end
|
|
|
|
DetailsKeystoneInfoFrame.RefreshData()
|
|
end
|
|
end
|
|
end
|
|
|
|
--ñote ~note ~notes ~notepad
|
|
---@class notereplacement : table
|
|
---@field addonObject table
|
|
---@field memberName string
|
|
---@field payload any[]
|
|
|
|
--this table store addons which want to replace the note command
|
|
--more than one addon can be registered and all of them will be called when the user type /note
|
|
--is up to the user to decide which addon to use
|
|
local noteCallbacks = {
|
|
---@type notereplacement[]
|
|
["NOTE"] = {},
|
|
---@type notereplacement[]
|
|
["NOTES"] = {},
|
|
---@type notereplacement[]
|
|
["NOTEPAD"] = {},
|
|
}
|
|
|
|
---@alias notecommand
|
|
---| "NOTE"
|
|
---| "NOTES"
|
|
---| "NOTEPAD"
|
|
|
|
---register an addon and a callback function to be called when the user type /keystone
|
|
---@param addonObject table a table containing the function to be called, example: {[memberName] = function()end}
|
|
---@param memberName string a function name that exists inside the addonObject table
|
|
---@param noteCommandToReplace notecommand which note command to replace
|
|
---@param ... any any number of parameters to be passed to the callback function
|
|
---@return boolean bGotRegistered true if the addon was registered, false if it was already registered and got unregistered
|
|
function Details:ReplaceNoteCommand(addonObject, memberName, noteCommandToReplace, ...)
|
|
--check if the parameters passed are valid types
|
|
if (type(addonObject) ~= "table") then
|
|
error("Details:ReplaceNoteCommand: addonObject must be a table")
|
|
|
|
elseif (type(memberName) ~= "string") then
|
|
error("Details:ReplaceNoteCommand: memberName must be a string")
|
|
|
|
elseif (type(addonObject[memberName]) ~= "function") then
|
|
error("Details:ReplaceNoteCommand: t[memberName] doesn't point to a function.")
|
|
|
|
elseif (noteCommandToReplace ~= "NOTE" and noteCommandToReplace ~= "NOTES" and noteCommandToReplace ~= "NOTEPAD") then
|
|
error("Details:ReplaceNoteCommand: noteCommandToReplace must be 'NOTE', 'NOTES' or 'NOTEPAD'")
|
|
end
|
|
|
|
local commandRegisteredCallbacks = noteCallbacks[noteCommandToReplace]
|
|
|
|
--check if the addonObject is already registered and remove it
|
|
for i = #commandRegisteredCallbacks, 1, -1 do
|
|
if (commandRegisteredCallbacks[i].addonObject == addonObject) then
|
|
--check if the memberName is the same
|
|
if (commandRegisteredCallbacks[i].memberName == memberName) then
|
|
table.remove(commandRegisteredCallbacks, i)
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
local payload = {...}
|
|
|
|
commandRegisteredCallbacks[#commandRegisteredCallbacks+1] = {
|
|
addonObject = addonObject,
|
|
memberName = memberName,
|
|
payload = payload
|
|
}
|
|
|
|
return true
|
|
end
|
|
|
|
SLASH_NOTE1 = "/note"
|
|
SLASH_NOTES1 = "/notes"
|
|
SLASH_NOTEPAD1 = "/notepad"
|
|
|
|
local noteEditor = {}
|
|
local canAcceptNoteOn = {
|
|
[8] = true, --mythic dungeon difficulty
|
|
[23] = true, --mythic dungeon difficulty
|
|
}
|
|
|
|
---@alias notename string
|
|
|
|
---@class unitnote : table
|
|
---@field note string
|
|
---@field commId string
|
|
|
|
---@class savednote : table
|
|
---@field name string
|
|
---@field note string
|
|
---@field renamed boolean
|
|
|
|
---@class noteconfigs : table
|
|
---@field enabled boolean
|
|
---@field framepos table
|
|
---@field screenpos table
|
|
---@field notes savednote[]
|
|
---@field banlist table<actorname, boolean>
|
|
---@field printtochat boolean
|
|
---@field fontsize number
|
|
---@field transparency number
|
|
---@field leftclickthrough boolean
|
|
---@field rightclickthrough boolean
|
|
---@field showheader boolean
|
|
---@field showrightclicktoclose boolean
|
|
---@field showclosebutton boolean
|
|
---@field showbansenderbutton boolean
|
|
---@field showoptionsbutton boolean
|
|
---@field showresizebutton boolean
|
|
---@field framecolor number[]
|
|
|
|
noteEditor.OpenNoteOptionsPanel = function()
|
|
if (not DetailsNoteOptionsFrame) then
|
|
local mainFrame = detailsFramework:CreateSimplePanel(UIParent, 600, 400, "Notes (/note) Options", "DetailsNoteOptionsFrame")
|
|
detailsFramework:ApplyStandardBackdrop(mainFrame)
|
|
--dont allow the mainframe go off screen
|
|
mainFrame:SetClampedToScreen(true)
|
|
mainFrame:SetToplevel(true)
|
|
|
|
---@type noteconfigs
|
|
local config = Details.third_party.openraid_notecache
|
|
|
|
local options = {
|
|
always_boxfirst = true,
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.enabled
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.enabled = value
|
|
end,
|
|
name = "Enabled",
|
|
desc = "Enabled",
|
|
},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.printtochat
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.printtochat = value
|
|
end,
|
|
name = "No Window, just print to chat",
|
|
desc = "Print to Chat",
|
|
},
|
|
|
|
{type = "blank"},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.leftclickthrough
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.leftclickthrough = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Don't move with LEFT mouse click",
|
|
desc = "Window cannot interact with LEFT clicks",
|
|
},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.rightclickthrough
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.rightclickthrough = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Don't close with RIGHT mouse click",
|
|
desc = "Window cannot interact with RIGHT clicks",
|
|
},
|
|
|
|
{type = "blank"},
|
|
|
|
{
|
|
type = "button",
|
|
func = function()
|
|
config.notes = {}
|
|
end,
|
|
name = "Clear Notes",
|
|
desc = "Clear all notes",
|
|
icontexture = [[Interface\BUTTONS\UI-StopButton]],
|
|
},
|
|
|
|
{
|
|
type = "button",
|
|
func = function()
|
|
config.banlist = {}
|
|
end,
|
|
name = "Clear Banlist",
|
|
desc = "Clear all banlist",
|
|
icontexture = [[Interface\BUTTONS\UI-StopButton]],
|
|
},
|
|
|
|
{
|
|
type = "button",
|
|
func = function()
|
|
config.framepos.scale = 1
|
|
wipe(config.framepos.position)
|
|
config.screenpos.scale = 1
|
|
wipe(config.screenpos.position)
|
|
|
|
config.screenpos.width = 275
|
|
config.screenpos.height = 350
|
|
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Reset Positions",
|
|
desc = "Reset all positions",
|
|
icontexture = "UI-RefreshButton", --atlasname
|
|
},
|
|
|
|
{type = "blank"},
|
|
|
|
{
|
|
type = "range",
|
|
get = function() return config.fontsize end,
|
|
set = function(self, fixedparam, value)
|
|
config.fontsize = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshNoteTextSettings()
|
|
end
|
|
end,
|
|
min = 8,
|
|
max = 16,
|
|
step = 1,
|
|
name = "Text Size",
|
|
desc = "Text Size",
|
|
},
|
|
|
|
{type = "blank"},
|
|
|
|
{
|
|
type = "color",
|
|
get = function()
|
|
local r, g, b = unpack(config.framecolor)
|
|
return r, g, b
|
|
end,
|
|
set = function(widget, r, g, b)
|
|
local colorTable = config.framecolor
|
|
colorTable[1], colorTable[2], colorTable[3] = r, g, b
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Background color",
|
|
desc = "Background color",
|
|
},
|
|
|
|
{
|
|
type = "range",
|
|
get = function() return config.transparency end,
|
|
set = function(self, fixedparam, value)
|
|
config.transparency = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
min = 0,
|
|
max = 1,
|
|
step = 0.1,
|
|
usedecimals = true,
|
|
name = "Transparency",
|
|
desc = "Transparency",
|
|
},
|
|
|
|
{
|
|
type = "button",
|
|
func = function()
|
|
config.transparency = 0.02
|
|
local colorTable = config.framecolor
|
|
local red, green, blue = detailsFramework:GetDefaultBackdropColor()
|
|
colorTable[1], colorTable[2], colorTable[3] = red, green, blue
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
mainFrame:RefreshOptions()
|
|
end
|
|
end,
|
|
icontexture = "UI-RefreshButton", --atlasname
|
|
name = "Reset Color",
|
|
desc = "Reset Color",
|
|
},
|
|
|
|
{type = "breakline"},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.showheader
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.showheader = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Show header where it says 'Notes (/note)'",
|
|
desc = "Show header where it says 'Notes (/note)'",
|
|
},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.showrightclicktoclose
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.showrightclicktoclose = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Show 'Right click to close'",
|
|
desc = "Show 'Right click to close'",
|
|
},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.showclosebutton
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.showclosebutton = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Show close button",
|
|
desc = "Show close button",
|
|
},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.showbansenderbutton
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.showbansenderbutton = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Show ban sender button",
|
|
desc = "Show ban sender button",
|
|
},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.showoptionsbutton
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.showoptionsbutton = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Show options button (/note to open options then)",
|
|
desc = "There is a button on the note window to open the options",
|
|
},
|
|
|
|
{
|
|
type = "toggle",
|
|
get = function()
|
|
return config.showresizebutton
|
|
end,
|
|
set = function(self, fixedparam, value)
|
|
config.showresizebutton = value
|
|
if (DetailsNoteScreenFrame) then
|
|
DetailsNoteScreenFrame.RefreshFrameSettings()
|
|
end
|
|
end,
|
|
name = "Show resize button",
|
|
desc = "Show resize button",
|
|
},
|
|
}
|
|
|
|
--create a details framework label using with the text: options for the window where the note is shown
|
|
---@type df_label
|
|
local label = detailsFramework:CreateLabel(mainFrame, "Options for the window where the note is shown", "GameFontNormal")
|
|
label:SetPoint("topleft", mainFrame, "topleft", 3, -30)
|
|
|
|
local options_text_template = detailsFramework:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")
|
|
options_text_template = detailsFramework.table.copy({}, options_text_template)
|
|
options_text_template.size = 11
|
|
|
|
local options_dropdown_template = detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
|
|
local options_switch_template = detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_TEMPLATE")
|
|
local options_slider_template = detailsFramework:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE")
|
|
local options_button_template = detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")
|
|
|
|
detailsFramework:BuildMenu(mainFrame, options, 3, -57, 580, false, options_text_template, options_dropdown_template, options_switch_template, true, options_slider_template, options_button_template)
|
|
end
|
|
|
|
local screenFrame = DetailsNoteScreenFrame
|
|
if (not screenFrame or not screenFrame:IsShown()) then
|
|
local testText = "This currently text shown here is just a test text because you have opened the options panel for this feature. It is intended to changes made in the options panel to be immediately applied here."
|
|
local invalidCommId = ""
|
|
local bIsSimulateOnClient = true
|
|
noteEditor.OpenNoteScreenPanel(UnitName("player"), testText, invalidCommId, bIsSimulateOnClient)
|
|
screenFrame = DetailsNoteScreenFrame
|
|
end
|
|
|
|
DetailsNoteOptionsFrame:ClearAllPoints()
|
|
|
|
DetailsNoteOptionsFrame:SetPoint("left", screenFrame, "right", 50, 0)
|
|
DetailsNoteOptionsFrame:Show()
|
|
end
|
|
|
|
--this is a function which open a frame with a text entry with text telling about the api of the note feature
|
|
local openAPIFrame = function()
|
|
local CONST_WINDOW_WIDTH = 614
|
|
local CONST_WINDOW_HEIGHT = 720
|
|
local editorAlpha = 0.1
|
|
|
|
local mainFrame = detailsFramework:CreateSimplePanel(UIParent, CONST_WINDOW_WIDTH, CONST_WINDOW_HEIGHT, "Notes (/note) API", "DetailsNoteAPIFrame")
|
|
mainFrame:SetPoint("left", UIParent, "left", 50, 0)
|
|
mainFrame:SetToplevel(true)
|
|
|
|
--create a lua text entry to show the api text
|
|
local editboxNotes = detailsFramework:NewSpecialLuaEditorEntry(mainFrame, CONST_WINDOW_WIDTH - 10, CONST_WINDOW_HEIGHT - 30, "editboxNotes", "$parentAPIEditbox", true)
|
|
editboxNotes:SetPoint("topleft", mainFrame, "topleft", 2, -25)
|
|
editboxNotes:SetBackdrop(nil)
|
|
detailsFramework:ReskinSlider(editboxNotes.scroll)
|
|
mainFrame.EditboxNotes = editboxNotes
|
|
|
|
editboxNotes.scroll:ClearAllPoints()
|
|
editboxNotes.scroll:SetPoint("topleft", editboxNotes, "topleft", 1, -1)
|
|
editboxNotes.scroll:SetPoint("bottomright", editboxNotes, "bottomright", -1, 0)
|
|
|
|
local font, h, flags = editboxNotes.editbox:GetFont()
|
|
editboxNotes.editbox:SetFont(font, 12, flags)
|
|
editboxNotes.editbox:SetAllPoints()
|
|
editboxNotes.editbox:SetBackdrop(nil)
|
|
editboxNotes.editbox:SetTextInsets(4, 4, 4, 4)
|
|
|
|
local CONST_EDITBOX_COLOR = {.6, .6, .6, .5}
|
|
local rr, gg, bb = unpack(CONST_EDITBOX_COLOR)
|
|
local backgroundTexture1 = editboxNotes.scroll:CreateTexture(nil, "background", nil, -6)
|
|
backgroundTexture1:SetAllPoints()
|
|
backgroundTexture1:SetColorTexture(rr, gg, bb, editorAlpha)
|
|
|
|
local backgroundTexture2 = editboxNotes.editbox:CreateTexture(nil, "background", nil, -6)
|
|
backgroundTexture2:SetAllPoints()
|
|
backgroundTexture2:SetColorTexture(rr, gg, bb, editorAlpha)
|
|
|
|
local backgroundTexture3 = editboxNotes:CreateTexture(nil, "background", nil, -6)
|
|
backgroundTexture3:SetAllPoints()
|
|
backgroundTexture3:SetColorTexture(0, 0, 0, 1)
|
|
|
|
editboxNotes.backgroundTexture1 = backgroundTexture1
|
|
editboxNotes.backgroundTexture2 = backgroundTexture2
|
|
editboxNotes.backgroundTexture3 = backgroundTexture3
|
|
|
|
editboxNotes:SetText([[
|
|
Open Raid API:
|
|
|
|
- Notes sent using OpenRaid are logged on the server so players can be reported. Check the report code on details/functions/slash.lua
|
|
- OpenRaid will error if the note has less than 50 characters or more than 1500 characters.
|
|
|
|
---@alias playername string
|
|
|
|
---@class unitnote : table
|
|
---@field note string
|
|
---@field commId string
|
|
|
|
--register a callback to receive notes sent by other players:
|
|
local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true)
|
|
if (openRaidLib) then
|
|
local anObject = {
|
|
---@param unitId string who sent the note
|
|
---@param unitNote unitnote the note object
|
|
---@param allUnitsNote table<playername, unitnote> a table containing all notes sent by all players
|
|
OnNoteUpdate = function(unitId, unitNote, allUnitsNote)
|
|
--unitNote.note is the note
|
|
--unitNote.commId is the communication id used at the report player dialog
|
|
|
|
if (unitNote.commId:len() < 8) then
|
|
--there was a problem registering the note on the server, and the note should be discarded.
|
|
return
|
|
end
|
|
end
|
|
}
|
|
openRaidLib.RegisterCallback(anObject, "NoteUpdated", "OnNoteUpdate")
|
|
end
|
|
|
|
--send a note to other player in the group:
|
|
local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true)
|
|
if (openRaidLib) then
|
|
local noteText = "Hello, I'm sending a note to the group!, how are you?"
|
|
--tell OpenRaid that the note of this player is noteText
|
|
openRaidLib.SetPlayerNote(noteText)
|
|
--tell OpenRaid to send the note set by the player to all other players in the group
|
|
openRaidLib.SendPlayerNote()
|
|
end
|
|
|
|
|
|
Details API:
|
|
|
|
- Each once of the slashes /note /notes /notepad can be replaced by an addon to handle the note feature, use:
|
|
|
|
---@alias notecommand
|
|
---| "NOTE"
|
|
---| "NOTES"
|
|
---| "NOTEPAD"
|
|
|
|
---@param addonObject table a table containing the function to be called, example: {[memberName] = function()end}
|
|
---@param memberName string a function name that exists inside the addonObject table
|
|
---@param noteCommandToReplace notecommand which note command to replace
|
|
---@param ... any any number of parameters to be passed to the callback function
|
|
---@return boolean bGotRegistered true if the addon was registered, false if it was already registered and got unregistered
|
|
Details:ReplaceNoteCommand(addonObject, memberName, noteCommandToReplace, ...)
|
|
|
|
]])
|
|
end
|
|
|
|
|
|
---@param unitIds unit[]
|
|
---@return unit[], unit[], unit[]
|
|
function noteEditor.PrepareUnitRoleTables(unitIds)
|
|
local dpsList = {}
|
|
local healerList = {}
|
|
local tankList = {}
|
|
|
|
for unitIndex, unitId in ipairs(unitIds) do
|
|
if (UnitExists(unitId)) then
|
|
local unitRole = detailsFramework.UnitGroupRolesAssigned(unitId)
|
|
if (unitRole == "TANK") then
|
|
table.insert(tankList, unitId)
|
|
elseif (unitRole == "HEALER") then
|
|
table.insert(healerList, unitId)
|
|
else
|
|
table.insert(dpsList, unitId)
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
return tankList, healerList, dpsList
|
|
end
|
|
|
|
local replaceText = function(unitIdList, index, token, text, bNoColoring)
|
|
local bCanAddClassColor = not bNoColoring
|
|
local unitId = unitIdList[index]
|
|
local unitName = UnitName(unitId)
|
|
local unitClass = select(2, UnitClass(unitId))
|
|
|
|
local tokenId = token .. index
|
|
|
|
if (text:find(tokenId)) then
|
|
text = text:gsub(tokenId, bCanAddClassColor and detailsFramework:AddClassColorToText(unitName, unitClass) or unitName)
|
|
else
|
|
--remove the tokenId from the text
|
|
text = text:gsub(tokenId .. ",", "")
|
|
text = text:gsub(tokenId .. ";", "")
|
|
text = text:gsub(tokenId, "")
|
|
end
|
|
return text
|
|
end
|
|
|
|
function noteEditor.FindAndColorUnitNames(text)
|
|
local unitIds
|
|
if (IsInRaid()) then
|
|
unitIds = Details222.UnitIdCache.Raid
|
|
else
|
|
unitIds = Details222.UnitIdCache.Party
|
|
end
|
|
|
|
for i = 1, #unitIds do
|
|
local unitId = unitIds[i]
|
|
if (UnitExists(unitId)) then
|
|
local unitName = UnitName(unitId)
|
|
local unitClass = select(2, UnitClass(unitId))
|
|
--text = text:gsub(unitName .. "(?!%|r)", detailsFramework:AddClassColorToText(unitName, unitClass))
|
|
|
|
if (unitClass) then
|
|
local currentPosition = 1
|
|
local attempts = 10
|
|
while (attempts > 0) do
|
|
local startPos, endPos = string.find(text, unitName, currentPosition)
|
|
|
|
if (not startPos) then
|
|
break
|
|
end
|
|
|
|
if (string.sub(text, endPos+1, endPos+2) ~= "|r") then
|
|
text = string.sub(text, 1, startPos - 1) .. detailsFramework:AddClassColorToText(unitName, unitClass) .. string.sub(text, endPos + 1)
|
|
currentPosition = startPos + 12 + #unitName -- 12 accounts for "|c00000000" and "|r"
|
|
else
|
|
currentPosition = endPos + 1
|
|
end
|
|
|
|
attempts = attempts - 1
|
|
if (attempts == 0) then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return text
|
|
end
|
|
|
|
--this function get the text of the note and replace any special tags
|
|
function noteEditor.ParseNoteText(text, bNoColoring)
|
|
local unitIds
|
|
if (IsInRaid()) then
|
|
unitIds = Details222.UnitIdCache.Raid
|
|
else
|
|
unitIds = Details222.UnitIdCache.Party
|
|
end
|
|
|
|
local tankList, healerList, dpsList = noteEditor.PrepareUnitRoleTables(unitIds)
|
|
|
|
for i = 1, #tankList do
|
|
text = replaceText(tankList, i, "tank", text, bNoColoring)
|
|
end
|
|
for i = 1, #healerList do
|
|
text = replaceText(healerList, i, "healer", text, bNoColoring)
|
|
end
|
|
for i = 1, #dpsList do
|
|
text = replaceText(dpsList, i, "dps", text, bNoColoring)
|
|
end
|
|
|
|
return text
|
|
end
|
|
|
|
noteEditor.OpenNoteEditor = function()
|
|
--check if the client is running retail version
|
|
if (not detailsFramework.IsDragonflightAndBeyond()) then
|
|
Details:Msg("This feature is only available on retail version.")
|
|
return
|
|
end
|
|
|
|
local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true)
|
|
if (openRaidLib) then
|
|
if (not DetailsNoteFrame) then
|
|
local CONST_WINDOW_WIDTH = 614
|
|
local CONST_WINDOW_HEIGHT = 720
|
|
local CONST_LINE_HEIGHT = 20
|
|
local CONST_LINE_AMOUNT = 20
|
|
local CONST_NOTESELECTOR_WIDTH = 224
|
|
local CONST_NOTEEDITOR_HEIGHT = CONST_WINDOW_HEIGHT - 155
|
|
local CONST_NOTEEDITOR_WIDTH = CONST_WINDOW_WIDTH - 230
|
|
local CONST_NOTE_MIN_CHARACTERS = 20
|
|
local CONST_NOTE_MAX_CHARACTERS = 1500
|
|
|
|
local editorAlpha = 0.1
|
|
|
|
local mainFrame = detailsFramework:CreateSimplePanel(UIParent, CONST_WINDOW_WIDTH, CONST_WINDOW_HEIGHT, "Notes (/note)", "DetailsNoteFrame")
|
|
mainFrame:SetPoint("center", UIParent, "center", -200, 0)
|
|
mainFrame:SetScript("OnMouseDown", nil) --disable framework native moving scripts
|
|
mainFrame:SetScript("OnMouseUp", nil) --disable framework native moving scripts
|
|
mainFrame:SetToplevel(true)
|
|
|
|
local config = Details.third_party.openraid_notecache
|
|
---@type table<notename, savednote>
|
|
local savedNotes = config["notes"]
|
|
|
|
function mainFrame.HasAnyNoteSaved()
|
|
return #savedNotes > 0
|
|
end
|
|
|
|
---@return string
|
|
function mainFrame.GenerateNewNoteName()
|
|
local name, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceID = GetInstanceInfo()
|
|
local pattern = "(%w)%w*"
|
|
local shortInstanceName = name:gsub(pattern, "%1")
|
|
shortInstanceName = shortInstanceName:gsub("%s", "")
|
|
local noteName = shortInstanceName .. " " .. date("%m-%d %H:%M")
|
|
return noteName
|
|
end
|
|
|
|
--get the current text from the note editor and save it
|
|
---@param noteIndex number?
|
|
function mainFrame.SaveNote(noteIndex)
|
|
local noteText = mainFrame.EditboxNotes.editbox:GetText()
|
|
|
|
if (noteText and noteText ~= "") then
|
|
if (#savedNotes == 0) then
|
|
savedNotes[#savedNotes+1] = {name = "default", note = noteText}
|
|
else
|
|
local noteName = mainFrame.GenerateNewNoteName()
|
|
if (noteIndex and type(noteIndex) == "number") then
|
|
if (not savedNotes[noteIndex].renamed) then
|
|
savedNotes[noteIndex].name = noteName
|
|
end
|
|
savedNotes[noteIndex].note = noteText
|
|
else
|
|
--no note is selected, create a new note
|
|
savedNotes[#savedNotes+1] = {name = noteName, note = noteText, renamed = false}
|
|
end
|
|
end
|
|
|
|
mainFrame.NoteSelectionScrollFrame:Refresh()
|
|
end
|
|
end
|
|
|
|
function mainFrame.SetNoteName(noteIndex, newName)
|
|
savedNotes[noteIndex].name = newName
|
|
savedNotes[noteIndex].renamed = true
|
|
mainFrame.NoteSelectionScrollFrame:Refresh()
|
|
end
|
|
|
|
function mainFrame.SelectNote(noteIndex)
|
|
if (mainFrame.currentNoteIndex) then
|
|
mainFrame.SaveNote(mainFrame.currentNoteIndex)
|
|
end
|
|
|
|
local noteData = savedNotes[noteIndex]
|
|
mainFrame.currentNoteIndex = noteIndex
|
|
mainFrame.EditboxNotes.editbox:SetText(noteData.note)
|
|
mainFrame.NoteSelectionScrollFrame:Refresh()
|
|
end
|
|
|
|
function mainFrame.CreateEmptyNote()
|
|
savedNotes[#savedNotes+1] = {name = mainFrame.GenerateNewNoteName(), note = "", renamed = false}
|
|
mainFrame.SelectNote(#savedNotes)
|
|
mainFrame.NoteSelectionScrollFrame:Refresh()
|
|
end
|
|
|
|
--erase note by name and then refresh the note selection scroll
|
|
---@param noteIndex number
|
|
function mainFrame.EraseNote(noteIndex)
|
|
table.remove(savedNotes, noteIndex)
|
|
|
|
if (noteIndex == mainFrame.currentNoteIndex) then
|
|
mainFrame.currentNoteIndex = nil
|
|
mainFrame.EditboxNotes.editbox:SetText("")
|
|
|
|
elseif (mainFrame.currentNoteIndex and noteIndex < mainFrame.currentNoteIndex) then
|
|
mainFrame.currentNoteIndex = mainFrame.currentNoteIndex - 1
|
|
|
|
elseif (not mainFrame.currentNoteIndex) then
|
|
mainFrame.EditboxNotes.editbox:SetText("")
|
|
end
|
|
|
|
mainFrame.NoteSelectionScrollFrame:Refresh()
|
|
end
|
|
|
|
do --create scale and statusbar, register to libwindow
|
|
local LibWindow = LibStub("LibWindow-1.1")
|
|
LibWindow.RegisterConfig(mainFrame, config.framepos.position)
|
|
LibWindow.MakeDraggable(mainFrame)
|
|
LibWindow.RestorePosition(mainFrame)
|
|
|
|
local scaleBar = detailsFramework:CreateScaleBar(mainFrame, config.framepos)
|
|
mainFrame:SetScale(config.framepos.scale)
|
|
|
|
local statusBar = detailsFramework:CreateStatusBar(mainFrame)
|
|
statusBar.text = statusBar:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
statusBar.text:SetPoint("left", statusBar, "left", 5, 0)
|
|
statusBar.text:SetText("By Terciob | From Details! Damage Meter")
|
|
detailsFramework:SetFontSize(statusBar.text, 12)
|
|
detailsFramework:SetFontColor(statusBar.text, "silver")
|
|
end
|
|
|
|
do --create the note textarea
|
|
local editboxNotes = detailsFramework:NewSpecialLuaEditorEntry(mainFrame, CONST_NOTEEDITOR_WIDTH, CONST_NOTEEDITOR_HEIGHT, "editboxNotes", "DetailsNoteFrameNoteEditbox", true)
|
|
editboxNotes:SetPoint("topleft", mainFrame, "topleft", 2, -25)
|
|
editboxNotes:SetBackdrop(nil)
|
|
detailsFramework:ReskinSlider(editboxNotes.scroll)
|
|
mainFrame.EditboxNotes = editboxNotes
|
|
|
|
editboxNotes.scroll:ClearAllPoints()
|
|
editboxNotes.scroll:SetPoint("topleft", editboxNotes, "topleft", 1, -1)
|
|
editboxNotes.scroll:SetPoint("bottomright", editboxNotes, "bottomright", -1, 0)
|
|
|
|
local font, h, flags = editboxNotes.editbox:GetFont()
|
|
editboxNotes.editbox:SetFont(font, 12, flags)
|
|
editboxNotes.editbox:SetAllPoints()
|
|
editboxNotes.editbox:SetBackdrop(nil)
|
|
editboxNotes.editbox:SetTextInsets(4, 4, 4, 4)
|
|
|
|
local CONST_EDITBOX_COLOR = {.6, .6, .6, .5}
|
|
local rr, gg, bb = unpack(CONST_EDITBOX_COLOR)
|
|
local backgroundTexture1 = editboxNotes.scroll:CreateTexture(nil, "background", nil, -6)
|
|
backgroundTexture1:SetAllPoints()
|
|
backgroundTexture1:SetColorTexture(rr, gg, bb, editorAlpha)
|
|
|
|
local backgroundTexture2 = editboxNotes.editbox:CreateTexture(nil, "background", nil, -6)
|
|
backgroundTexture2:SetAllPoints()
|
|
backgroundTexture2:SetColorTexture(rr, gg, bb, editorAlpha)
|
|
|
|
local backgroundTexture3 = editboxNotes:CreateTexture(nil, "background", nil, -6)
|
|
backgroundTexture3:SetAllPoints()
|
|
backgroundTexture3:SetColorTexture(0, 0, 0, 1)
|
|
|
|
editboxNotes.backgroundTexture1 = backgroundTexture1
|
|
editboxNotes.backgroundTexture2 = backgroundTexture2
|
|
editboxNotes.backgroundTexture3 = backgroundTexture3
|
|
|
|
DetailsNoteFrameNoteEditboxScrollBar:SetPoint("topleft", editboxNotes, "topright", -20, -19)
|
|
DetailsNoteFrameNoteEditboxScrollBar:SetPoint("bottomleft", editboxNotes, "bottomright", -20, 19)
|
|
|
|
local currentChars = editboxNotes:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
currentChars:SetPoint("topright", editboxNotes, "topright", -25, -5)
|
|
currentChars:SetText("0")
|
|
detailsFramework:SetFontColor(currentChars, "gray")
|
|
|
|
--when the user types into the editbox, update the current amount of characters
|
|
editboxNotes.editbox:HookScript("OnTextChanged", function(self)
|
|
local text = self:GetText()
|
|
local len = text:len()
|
|
currentChars:SetText(len)
|
|
|
|
if (len < CONST_NOTE_MIN_CHARACTERS) then
|
|
detailsFramework:SetFontColor(currentChars, "red")
|
|
else
|
|
detailsFramework:SetFontColor(currentChars, "gray")
|
|
end
|
|
end)
|
|
|
|
--create a string with the text "Type your note here" and it attach center to center of the editbox
|
|
local typeYourNote = editboxNotes:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
typeYourNote:SetPoint("center", editboxNotes, "center", 0, 0)
|
|
typeYourNote:SetText("CLICK TO START YOUR NOTE")
|
|
detailsFramework:SetFontColor(typeYourNote, "gray")
|
|
detailsFramework:SetFontSize(typeYourNote, 14)
|
|
|
|
--when the editbox is focused, hide the "type your note here" text
|
|
editboxNotes.editbox:HookScript("OnEditFocusGained", function(self)
|
|
typeYourNote:Hide()
|
|
end)
|
|
|
|
--when the editbox is unfocused and the text is empty, show the "type your note here" text
|
|
editboxNotes.editbox:HookScript("OnEditFocusLost", function(self)
|
|
if (self:GetText() == "") then
|
|
typeYourNote:Show()
|
|
end
|
|
end)
|
|
|
|
--when the editbox receives any character modification, hide the "type your note here" text
|
|
editboxNotes.editbox:HookScript("OnTextChanged", function(self)
|
|
if (self:GetText() == "" and not editboxNotes.editbox:HasFocus()) then
|
|
typeYourNote:Show()
|
|
else
|
|
typeYourNote:Hide()
|
|
end
|
|
end)
|
|
end
|
|
|
|
do --floating frame above the bottom of the text editor
|
|
local bottomFrameFloating = CreateFrame("frame", "$parentFloatingFrame", mainFrame.EditboxNotes, "BackdropTemplate")
|
|
bottomFrameFloating:SetPoint("bottomleft", mainFrame.EditboxNotes, "bottomleft", 0, 0)
|
|
bottomFrameFloating:SetPoint("bottomright", mainFrame.EditboxNotes, "bottomright", 0, 0)
|
|
bottomFrameFloating:SetHeight(130)
|
|
detailsFramework:ApplyStandardBackdrop(bottomFrameFloating)
|
|
bottomFrameFloating:SetFrameLevel(mainFrame.EditboxNotes:GetFrameLevel() + 5)
|
|
|
|
--create a gradient texture from black to transparent from the top side of the framefloating
|
|
local topGradient = DetailsFramework:CreateTexture(bottomFrameFloating, {gradient = "vertical", fromColor = "transparent", toColor = {0, 0, 0, 0.25}}, 1, 60, "artwork", {0, 1, 0, 1}, "GradientTexture")
|
|
topGradient:SetPoint("tops")
|
|
|
|
--create a minimize button at the topleft of the framefloating
|
|
local minimizeButton = detailsFramework:CreateButton(bottomFrameFloating, function()
|
|
bottomFrameFloating:Hide()
|
|
bottomFrameFloating.MaximizeButton:Show()
|
|
bottomFrameFloating.MinimizeButton:Hide()
|
|
end, 16, 16, "minimize")
|
|
minimizeButton:SetPoint("topleft", bottomFrameFloating, "topleft", -1, -2)
|
|
minimizeButton:SetIcon("Interface\\BUTTONS\\UI-Panel-HideButton-Up", 16, 16, "overlay", {0.2, 0.8, 0.2, 0.8})
|
|
bottomFrameFloating.MinimizeButton = minimizeButton
|
|
|
|
--create a miximize button at the bottomleft of the editbox, this button is shown when the bottomFrameFloating is hidden (minimized)
|
|
local maximizeButton = detailsFramework:CreateButton(mainFrame.EditboxNotes, function()
|
|
bottomFrameFloating:Show()
|
|
bottomFrameFloating.MaximizeButton:Hide()
|
|
bottomFrameFloating.MinimizeButton:Show()
|
|
end, 16, 16, "miximize")
|
|
maximizeButton:SetPoint("bottomleft", mainFrame.EditboxNotes, "bottomleft", 0, 0)
|
|
maximizeButton:SetIcon("Interface\\BUTTONS\\UI-Panel-CollapseButton-Up", 16, 16, "overlay", {0.2, 0.8, 0.2, 0.8})
|
|
maximizeButton:SetFrameLevel(mainFrame.EditboxNotes:GetFrameLevel() + 5)
|
|
maximizeButton:Hide()
|
|
bottomFrameFloating.MaximizeButton = maximizeButton
|
|
|
|
local createNewPlayerSelectionButton = function()
|
|
local newButton = detailsFramework:CreateButton(bottomFrameFloating, function()end, 100, 22, "")
|
|
detailsFramework:CreateHighlightTexture(newButton)
|
|
return newButton
|
|
end
|
|
|
|
local playerSelectionPool = detailsFramework:CreatePool(createNewPlayerSelectionButton)
|
|
playerSelectionPool.onReset = function(button)
|
|
button:Hide()
|
|
button:ClearAllPoints()
|
|
end
|
|
playerSelectionPool.onAcquire = function(button)
|
|
button:Show()
|
|
end
|
|
|
|
function mainFrame.RefreshPickPlayer()
|
|
local unitIds
|
|
if (IsInRaid()) then
|
|
unitIds = Details222.UnitIdCache.Raid
|
|
else
|
|
unitIds = Details222.UnitIdCache.Party
|
|
end
|
|
|
|
playerSelectionPool:ReleaseAll()
|
|
|
|
local column = 1
|
|
local row = 1
|
|
local maxColumns = 5
|
|
local maxRows = 5
|
|
local columnWidth = 80
|
|
local rowHeight = 22
|
|
|
|
local tankIndex = 1
|
|
local healerIndex = 1
|
|
local dpsIndex = 1
|
|
|
|
for unitIndex, unitId in ipairs(unitIds) do
|
|
if (UnitExists(unitId)) then
|
|
---@type df_button
|
|
local selectPlayerButton = playerSelectionPool:Acquire()
|
|
|
|
--calculate where this button should be placed, the coulumn increments when the row reaches the maxRows, then it jumps the columnWidth and start from row 1 again
|
|
selectPlayerButton:SetPoint("topleft", bottomFrameFloating, "topleft", 3 + ((column-1) * columnWidth), -((row-1) * rowHeight) - 20)
|
|
|
|
--increment the row
|
|
row = row + 1
|
|
if (row > maxRows) then
|
|
row = 1
|
|
column = column + 1
|
|
end
|
|
|
|
--if the column is bigger than the maxColumns, then stop creating buttons
|
|
if (column > maxColumns) then
|
|
break
|
|
end
|
|
|
|
local role = detailsFramework.UnitGroupRolesAssigned(unitId)
|
|
local roleTexture, left, right, top, bottom = detailsFramework:GetRoleIconAndCoords(role)
|
|
local unitName = UnitName(unitId)
|
|
local unitClass = select(2, UnitClass(unitId))
|
|
|
|
selectPlayerButton:SetTextTruncated(unitName, columnWidth - 30)
|
|
selectPlayerButton:SetTextColor(unitClass)
|
|
selectPlayerButton:SetSize(columnWidth - 2, rowHeight - 2)
|
|
selectPlayerButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
selectPlayerButton:SetIcon(roleTexture, 14, 14, "overlay", {left, right, top, bottom})
|
|
selectPlayerButton:SetAlpha(0.834)
|
|
|
|
selectPlayerButton:SetScript("OnClick", function()
|
|
local textToInsert = ""
|
|
if (role == "TANK") then
|
|
textToInsert = "tank" .. tankIndex
|
|
tankIndex = tankIndex + 1
|
|
|
|
elseif (role == "HEALER") then
|
|
textToInsert = "healer" .. healerIndex
|
|
healerIndex = healerIndex + 1
|
|
else
|
|
textToInsert = "dps" .. dpsIndex
|
|
dpsIndex = dpsIndex + 1
|
|
end
|
|
|
|
textToInsert = textToInsert .. " "
|
|
mainFrame.editboxNotes.editbox:Insert(textToInsert)
|
|
end)
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
bottomFrameFloating:RegisterEvent("GROUP_ROSTER_UPDATE")
|
|
bottomFrameFloating:SetScript("OnEvent", function(self, event)
|
|
if (bottomFrameFloating:IsShown()) then
|
|
mainFrame.RefreshPickPlayer()
|
|
end
|
|
end)
|
|
|
|
bottomFrameFloating:HookScript("OnShow", function(self)
|
|
mainFrame.RefreshPickPlayer()
|
|
end)
|
|
|
|
mainFrame.RefreshPickPlayer()
|
|
end
|
|
|
|
do --create the note selection scroll
|
|
local lastClick = 0
|
|
local lastLineClicked = nil
|
|
|
|
local doSelectNote = function(line)
|
|
lastLineClicked = line
|
|
local noteData = line.noteData
|
|
if (noteData) then
|
|
mainFrame.SelectNote(line.index)
|
|
end
|
|
end
|
|
|
|
local selectNoteOnClick = function(line)
|
|
local now = GetTime()
|
|
if (now - lastClick < 0.3) then
|
|
lastClick = 0
|
|
if (lastLineClicked == line) then
|
|
--start renaming the note
|
|
line.RenameTextEntry:Show()
|
|
line.RenameTextEntry:SetText(line.NoteName:GetText() or "")
|
|
line.RenameTextEntry:SetFocus(true)
|
|
line.RenameTextEntry:HighlightText(0)
|
|
line.NoteName:Hide()
|
|
else
|
|
doSelectNote(line)
|
|
end
|
|
else
|
|
lastClick = now
|
|
doSelectNote(line)
|
|
end
|
|
end
|
|
|
|
local onPressEnterToRenameNote = function(textentry, object, text)
|
|
local line = textentry:GetParent()
|
|
local noteData = line.noteData
|
|
|
|
if (noteData) then
|
|
mainFrame.SetNoteName(line.index, textentry:GetText() or "")
|
|
end
|
|
|
|
textentry:Hide()
|
|
textentry:SetFocus(false)
|
|
line.NoteName:Show()
|
|
mainFrame.NoteSelectionScrollFrame:Refresh()
|
|
end
|
|
|
|
local onEscapePressedRenameNote = function(self)
|
|
local line = self:GetParent()
|
|
self:Hide()
|
|
line.NoteName:Show()
|
|
end
|
|
|
|
local onEnterLine = function(self)
|
|
GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT")
|
|
GameTooltip:SetText("double click to rename")
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
local onLeaveLine = function(self)
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local createdNoteSelectionLine = function(self, index)
|
|
local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate")
|
|
line:SetPoint("topleft", self, "topleft", 1, -((index-1) * (CONST_LINE_HEIGHT+1)) - 1)
|
|
line:SetSize(mainFrame.NoteSelectionScrollFrame:GetWidth()-22, CONST_LINE_HEIGHT)
|
|
detailsFramework:ApplyStandardBackdrop(line, index % 2 == 0)
|
|
|
|
line:SetScript("OnClick", selectNoteOnClick)
|
|
line:SetScript("OnEnter", onEnterLine)
|
|
line:SetScript("OnLeave", onLeaveLine)
|
|
|
|
local selectedHighlightTexture = line:CreateTexture("$parentSelectedHighlight", "overlay")
|
|
selectedHighlightTexture:SetAllPoints()
|
|
selectedHighlightTexture:SetColorTexture(1, 1, 1, 0.2)
|
|
|
|
detailsFramework:CreateHighlightTexture(line)
|
|
|
|
local iconTexture = line:CreateTexture("$parentNoteIcon", "overlay")
|
|
iconTexture:SetSize(CONST_LINE_HEIGHT-2, CONST_LINE_HEIGHT-2)
|
|
iconTexture:SetPoint("left", line, "left", 2, 0)
|
|
|
|
local noteName = line:CreateFontString("$parentNoteName", "overlay", "GameFontNormal")
|
|
noteName:SetPoint("left", iconTexture, "right", 2, 0)
|
|
|
|
local deleteButton = detailsFramework:CreateButton(line, function()
|
|
---@type savednote
|
|
local noteData = line.noteData
|
|
if (noteData) then
|
|
mainFrame.EraseNote(line.index)
|
|
end
|
|
end, 20, 20, "")
|
|
deleteButton:SetPoint("right", line, "right", -5, 0)
|
|
deleteButton:SetIcon("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Disabled", 16, 16, "overlay", {0.2, 0.8, 0.2, 0.8})
|
|
deleteButton:SetSize(20, 20)
|
|
|
|
--create a textentry to rename the note
|
|
local renameTextEntry = detailsFramework:CreateTextEntry(line, function()end, 20, 20, _, _, _, detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
|
renameTextEntry:SetPoint("topleft", line, "topleft", 20, 0) --after the note icon
|
|
renameTextEntry:SetPoint("bottomright", line, "bottomright", -20, 0) --before the delete button
|
|
renameTextEntry:Hide()
|
|
--on lose focus
|
|
renameTextEntry:SetScript("OnEnterPressed", onPressEnterToRenameNote)
|
|
renameTextEntry:SetScript("OnEscapePressed", onEscapePressedRenameNote)
|
|
renameTextEntry:SetScript("OnEditFocusLost", onEscapePressedRenameNote)
|
|
|
|
line.SelectedHighlightTexture = selectedHighlightTexture
|
|
line.IconTexture = iconTexture
|
|
line.NoteName = noteName
|
|
line.DeleteButton = deleteButton
|
|
line.RenameTextEntry = renameTextEntry
|
|
|
|
return line
|
|
end
|
|
|
|
local refreshNotes = function(self, data, offset, totalLines)
|
|
for i = 1, totalLines do
|
|
local index = i + offset
|
|
---@type savednote
|
|
local noteData = data[index]
|
|
if (noteData) then
|
|
local line = self:GetLine(i)
|
|
if (line) then
|
|
line.IconTexture:SetTexture([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]])
|
|
line.NoteName:SetText(noteData.name)
|
|
line.noteData = noteData
|
|
line.index = index
|
|
|
|
line.SelectedHighlightTexture:Hide()
|
|
if (index == mainFrame.currentNoteIndex) then
|
|
line.SelectedHighlightTexture:Show()
|
|
end
|
|
|
|
--cancel any rename in progress
|
|
line.RenameTextEntry:SetFocus(false)
|
|
line.RenameTextEntry:Hide()
|
|
line.NoteName:Show()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--scrollframe to select the note
|
|
local scrollHeight = CONST_LINE_AMOUNT + (CONST_LINE_AMOUNT * CONST_LINE_HEIGHT) --as each line has 1 pixel of spacing, the first CONST_LINE_AMOUNT is to compensate the spacing
|
|
local noteSelectionScrollFrame = detailsFramework:CreateScrollBox(mainFrame, "$parentNoteSelectionScrollBox", refreshNotes, savedNotes, CONST_NOTESELECTOR_WIDTH, scrollHeight, CONST_LINE_HEIGHT, CONST_LINE_AMOUNT)
|
|
noteSelectionScrollFrame:SetPoint("topleft", mainFrame.EditboxNotes, "topright", 2, 0)
|
|
detailsFramework:ReskinSlider(noteSelectionScrollFrame)
|
|
DetailsNoteFrameNoteSelectionScrollBoxScrollBar:SetPoint("topleft", noteSelectionScrollFrame, "topright", -20, -19)
|
|
DetailsNoteFrameNoteSelectionScrollBoxScrollBar:SetPoint("bottomleft", noteSelectionScrollFrame, "bottomright", -20, 19)
|
|
|
|
mainFrame.NoteSelectionScrollFrame = noteSelectionScrollFrame
|
|
|
|
for i = 1, CONST_LINE_AMOUNT do
|
|
noteSelectionScrollFrame:CreateLine(createdNoteSelectionLine)
|
|
end
|
|
|
|
noteSelectionScrollFrame:Refresh()
|
|
end
|
|
|
|
do --create the bottom panel
|
|
local bottomFrame = CreateFrame("frame", "$parentBottomFrame", mainFrame, "BackdropTemplate")
|
|
bottomFrame:SetPoint("topleft", mainFrame.EditboxNotes, "bottomleft", 0, -2)
|
|
bottomFrame:SetPoint("topright", mainFrame.NoteSelectionScrollFrame, "bottomright", 0, -2)
|
|
bottomFrame:SetPoint("bottomleft", mainFrame, "bottomleft", 0, 22)
|
|
detailsFramework:ApplyStandardBackdrop(bottomFrame)
|
|
mainFrame.BottomFrame = bottomFrame
|
|
|
|
local buttonWidth = 136
|
|
local buttonHeight = 22
|
|
|
|
local sendButton = detailsFramework:CreateButton(bottomFrame, function()
|
|
local noteText = mainFrame.EditboxNotes.editbox:GetText()
|
|
if (noteText:len() < CONST_NOTE_MIN_CHARACTERS) then
|
|
local msg = "Note is too short, must have at least " .. CONST_NOTE_MIN_CHARACTERS .. " characters."
|
|
Details:Msg(msg)
|
|
mainFrame.ShowErrorMsg(msg)
|
|
return
|
|
end
|
|
|
|
--if there's no note saved, save this note as the default note
|
|
if (#savedNotes == 0) then
|
|
mainFrame.SaveNote()
|
|
mainFrame.currentNoteIndex = 1
|
|
else
|
|
mainFrame.SaveNote(mainFrame.currentNoteIndex)
|
|
end
|
|
|
|
if (not IsInRaid()) then
|
|
--need to replace the special keywords now, as the unitIds isn't the same on different clients, also passes the bNoColoring flag to avoid coloring the names
|
|
local bNoColoring = true
|
|
noteText = noteEditor.ParseNoteText(noteText, bNoColoring)
|
|
end
|
|
|
|
--set the player note in the open raid
|
|
openRaidLib.SetPlayerNote(noteText)
|
|
|
|
--open raid do not send the note to the local player, need to trigger the screen panel manually
|
|
local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo()
|
|
if (not canAcceptNoteOn[difficultyID] and not Details.debug) then --at the moment, players can only receive notes if inside a mythic dungeon
|
|
local msg = "At the moment, you can only send and receive notes inside a mythic dungeon."
|
|
Details:Msg(msg)
|
|
mainFrame.ShowErrorMsg(msg)
|
|
return
|
|
end
|
|
|
|
openRaidLib.SendPlayerNote()
|
|
|
|
local bIsSimulateOnClient = true
|
|
noteEditor.OpenNoteScreenPanel(UnitName("player"), noteText, "", bIsSimulateOnClient)
|
|
|
|
end, buttonWidth, buttonHeight, "Send Note")
|
|
sendButton:SetPoint("topleft", bottomFrame, "topleft", 0, -2)
|
|
sendButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
sendButton:SetIcon("Interface\\BUTTONS\\JumpUpArrow", 18, 18, "overlay", {0, 1, 0, 1})
|
|
detailsFramework:CreateHighlightTexture(sendButton)
|
|
|
|
local saveNoteButton = detailsFramework:CreateButton(bottomFrame, function()
|
|
--print("mainFrame.currentNoteIndex", mainFrame.currentNoteIndex) --nil when no note is selected
|
|
mainFrame.SaveNote(mainFrame.currentNoteIndex)
|
|
end, buttonWidth, buttonHeight, "Save Note")
|
|
saveNoteButton:SetPoint("bottomleft", sendButton, "bottomright", 4, 0)
|
|
saveNoteButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
saveNoteButton:SetIcon([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]], 16, 16, "overlay")
|
|
saveNoteButton:SetAlpha(1)
|
|
detailsFramework:CreateHighlightTexture(saveNoteButton)
|
|
|
|
local newNoteButton = detailsFramework:CreateButton(bottomFrame, function()
|
|
mainFrame.CreateEmptyNote()
|
|
end, buttonWidth, buttonHeight, "New Empty Note")
|
|
newNoteButton:SetPoint("bottomleft", saveNoteButton, "bottomright", 4, 0)
|
|
newNoteButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
newNoteButton:SetIcon([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]], 16, 16, "overlay")
|
|
newNoteButton:SetAlpha(1)
|
|
detailsFramework:CreateHighlightTexture(newNoteButton)
|
|
|
|
local optionsButton = detailsFramework:CreateButton(bottomFrame, function()
|
|
noteEditor.OpenNoteOptionsPanel()
|
|
end, buttonWidth, buttonHeight, "OPTIONS")
|
|
optionsButton:SetPoint("bottomleft", newNoteButton, "bottomright", 4, 0)
|
|
optionsButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
optionsButton:SetIcon([[Interface\Scenarios\ScenarioIcon-Interact]], 16, 16, "overlay")
|
|
optionsButton:SetAlpha(1)
|
|
detailsFramework:CreateHighlightTexture(optionsButton)
|
|
|
|
local apiButton = detailsFramework:CreateButton(bottomFrame, function()
|
|
openAPIFrame()
|
|
end, 50, buttonHeight, "API")
|
|
apiButton:SetPoint("bottomleft", optionsButton, "bottomright", 4, 0)
|
|
apiButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
apiButton:SetAlpha(1)
|
|
detailsFramework:CreateHighlightTexture(apiButton)
|
|
|
|
--error msg fontstring, this text is used to show errors to the user, its color is red, size 13 and it is placed centered and below the buttons above
|
|
--it also has an animation to fade out after 5 seconds, and a shake animation when it's shown
|
|
local errorMsg = bottomFrame:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
errorMsg:SetPoint("top", bottomFrame, "top", 0, (buttonHeight + 14) * -1)
|
|
errorMsg:SetWidth(bottomFrame:GetWidth() - 10)
|
|
errorMsg:SetJustifyH("center")
|
|
errorMsg:SetAlpha(0)
|
|
detailsFramework:SetFontColor(errorMsg, "orangered")
|
|
detailsFramework:SetFontSize(errorMsg, 13)
|
|
mainFrame.ErrorMsg = errorMsg
|
|
|
|
--fade out animation using details framework animation hub
|
|
local fadeOutAnimationHub = detailsFramework:CreateAnimationHub(errorMsg, function()end, function() errorMsg:SetAlpha(0) end)
|
|
detailsFramework:CreateAnimation(fadeOutAnimationHub, "Alpha", 1, 2, 1, 0)
|
|
|
|
--fade in animation using details framework animation hub
|
|
local fadeInAnimationHub = detailsFramework:CreateAnimationHub(errorMsg, function() errorMsg:SetAlpha(0) end, function() errorMsg:SetAlpha(1) end)
|
|
detailsFramework:CreateAnimation(fadeInAnimationHub, "Alpha", 1, 0.1, 0, 1)
|
|
|
|
--shake animation using details framework
|
|
local shake = detailsFramework:CreateFrameShake(errorMsg, 0.4, 6, 20, false, true, 0, 1, 0, 0.3)
|
|
|
|
function mainFrame.ShowErrorMsg(msg)
|
|
fadeInAnimationHub:Play()
|
|
mainFrame.ErrorMsg:SetText(msg)
|
|
mainFrame.ErrorMsg:PlayFrameShake(shake)
|
|
|
|
if (errorMsg.HideTimer) then
|
|
return
|
|
end
|
|
|
|
errorMsg.HideTimer = C_Timer.NewTimer(4, function()
|
|
fadeOutAnimationHub:Play()
|
|
errorMsg.HideTimer = nil
|
|
end)
|
|
end
|
|
|
|
|
|
--create a texture of size 16 16 with the texture [[Interface\BUTTONS\UI-SliderBar-Button-Vertical]], the point is the same as the whats this text
|
|
local whatsThisIcon = bottomFrame:CreateTexture(nil, "overlay")
|
|
whatsThisIcon:SetTexture([[Interface\BUTTONS\UI-SliderBar-Button-Vertical]])
|
|
whatsThisIcon:SetSize(16, 16)
|
|
whatsThisIcon:SetPoint("bottomleft", bottomFrame, "bottomleft", 2, 25)
|
|
whatsThisIcon:SetTexCoord(0.25, 0.75, 0.25, 0.75)
|
|
|
|
--make a fontstring with the text: "This panel allows you to create a note and share it with your group. Can contain route info, interrupt order, bloodlust timers, boss order, skips, rogue shroud, etc."
|
|
local whatsThisText = bottomFrame:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
whatsThisText:SetPoint("left", whatsThisIcon, "right", 5, 0)
|
|
whatsThisText:SetText("This panel allows you to create a note and share it with your group. Can contain route info, interrupt order, bloodlust timers, boss order, skips, rogue shroud, etc.")
|
|
whatsThisText:SetWidth(bottomFrame:GetWidth() - 10)
|
|
whatsThisText:SetJustifyH("left")
|
|
detailsFramework:SetFontSize(whatsThisText, 12)
|
|
detailsFramework:SetFontColor(whatsThisText, "orange")
|
|
whatsThisText:SetAlpha(0.7)
|
|
|
|
local warningTextIcon = bottomFrame:CreateTexture(nil, "overlay")
|
|
warningTextIcon:SetTexture([[Interface\BUTTONS\UI-SliderBar-Button-Vertical]])
|
|
warningTextIcon:SetSize(16, 16)
|
|
warningTextIcon:SetPoint("bottomleft", bottomFrame, "bottomleft", 2, 2)
|
|
warningTextIcon:SetTexCoord(0.25, 0.75, 0.25, 0.75)
|
|
|
|
local warningText = bottomFrame:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
warningText:SetPoint("left", warningTextIcon, "right", 5, 0)
|
|
warningText:SetText("You may report any offensive notes you receive. The text is logged on the server.")
|
|
warningText:SetAlpha(0.7)
|
|
|
|
local versionText = bottomFrame:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
versionText:SetPoint("bottomright", bottomFrame, "bottomright", -2, 2)
|
|
versionText:SetText("v1.0")
|
|
versionText:SetAlpha(0.7)
|
|
end
|
|
|
|
do --create a panel below the note selection scroll frame
|
|
local belowScrollFrame = CreateFrame("frame", "$parentBelowScrollFrame", mainFrame, "BackdropTemplate")
|
|
detailsFramework:ApplyStandardBackdrop(belowScrollFrame)
|
|
belowScrollFrame:SetPoint("topleft", mainFrame.NoteSelectionScrollFrame, "bottomleft", 0, -2)
|
|
belowScrollFrame:SetPoint("topright", mainFrame.NoteSelectionScrollFrame, "bottomright", 0, -2)
|
|
belowScrollFrame:SetPoint("bottomright", mainFrame.BottomFrame, "topright", 0, 2)
|
|
|
|
local reuseText = belowScrollFrame:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
reuseText:SetPoint("topleft", belowScrollFrame, "topleft", 4, -5)
|
|
reuseText:SetText("Use dps1 dps2 dps3 healer1 tank1 in order to reuse the note without typing player names.")
|
|
detailsFramework:SetFontSize(reuseText, 11)
|
|
detailsFramework:SetFontColor(reuseText, "silver")
|
|
reuseText:SetWidth(belowScrollFrame:GetWidth() - 6)
|
|
reuseText:SetJustifyH("left")
|
|
end
|
|
|
|
function mainFrame.RefreshData()
|
|
local keystoneData = openRaidLib.GetAllKeystonesInfo()
|
|
end
|
|
end
|
|
DetailsNoteFrame:Show()
|
|
end
|
|
end
|
|
|
|
local currentSenderName = nil
|
|
local currentNoteId = nil
|
|
|
|
---@param senderName string
|
|
---@param noteText string
|
|
---@param commId string
|
|
---@param bIsSimulateOnClient boolean
|
|
noteEditor.OpenNoteScreenPanel = function(senderName, noteText, commId, bIsSimulateOnClient)
|
|
local config = Details.third_party.openraid_notecache
|
|
currentSenderName = senderName
|
|
|
|
if (not bIsSimulateOnClient) then
|
|
if (not commId or type(commId) ~= "string" or commId:len() < 8) then
|
|
return
|
|
end
|
|
currentNoteId = commId
|
|
else
|
|
currentNoteId = nil
|
|
end
|
|
|
|
if (not DetailsNoteScreenFrame) then
|
|
local screenFrame = CreateFrame("button", "DetailsNoteScreenFrame", UIParent, "BackdropTemplate")
|
|
screenFrame:SetSize(config.screenpos.width or 275, config.screenpos.height or 350)
|
|
screenFrame:SetPoint("topleft", UIParent, "topleft", 5, -5)
|
|
screenFrame:EnableMouse(true)
|
|
screenFrame:SetFrameStrata("DIALOG")
|
|
screenFrame:SetMovable(true)
|
|
screenFrame:SetResizable(true)
|
|
detailsFramework:AddRoundedCornersToFrame(screenFrame, Details.PlayerBreakdown.RoundedCornerPreset)
|
|
local red, green, blue = detailsFramework:GetDefaultBackdropColor()
|
|
screenFrame:SetColor(red, green, blue, 0.98)
|
|
screenFrame:SetClampedToScreen(true)
|
|
|
|
local rightClickFrame = CreateFrame("button", "$parentRightClickFrame", screenFrame)
|
|
rightClickFrame:SetAllPoints()
|
|
rightClickFrame:SetScript("OnClick", function(self, button)
|
|
if (button == "RightButton") then
|
|
screenFrame:Hide()
|
|
end
|
|
end)
|
|
|
|
--create a texture to use in a flash animation, this texture is attached to the titleRoundedFrame
|
|
local flashTexture = screenFrame:CreateTexture(nil, "overlay")
|
|
flashTexture:SetTexture([[Interface\CHATFRAME\CHATFRAMEBACKGROUND]])
|
|
flashTexture:SetBlendMode("ADD")
|
|
flashTexture:SetTexCoord(44/512, 354/512, 50/256, 120/256)
|
|
flashTexture:SetHeight(40)
|
|
flashTexture:SetPoint("topleft", screenFrame, "topleft", 0, 0)
|
|
flashTexture:SetPoint("topright", screenFrame, "topright", 0, 0)
|
|
screenFrame.FlashTexture = flashTexture
|
|
|
|
--create the flash animation usin details framework animation hub
|
|
local animGroup = detailsFramework:CreateAnimationHub(flashTexture, function() flashTexture:Show() end, function() flashTexture:Hide() end)
|
|
local flashInAnim = detailsFramework:CreateAnimation(animGroup, "Alpha", 1, 0.1, 0.03, 0.03)
|
|
local flashOutAnim = detailsFramework:CreateAnimation(animGroup, "Alpha", 2, 0.1, 0.01, 0)
|
|
local transInAnim = detailsFramework:CreateAnimation(animGroup, "Translation", 1, 0.1, 0, -150)
|
|
local transOutAnim = detailsFramework:CreateAnimation(animGroup, "Translation", 2, 0.1, 0, -150)
|
|
animGroup.flashInAnim = flashInAnim
|
|
animGroup.transInAnim = transInAnim
|
|
animGroup.flashOutAnim = flashOutAnim
|
|
animGroup.transOutAnim = transOutAnim
|
|
flashTexture.FadeInAnimation = animGroup
|
|
|
|
local screenFrameFadeInAnimGroup = detailsFramework:CreateAnimationHub(screenFrame, function() flashTexture:Hide() end, function() --[[flashTexture.FadeInAnimation:Play()]] end)
|
|
local scaleInAnim1 = detailsFramework:CreateAnimation(screenFrameFadeInAnimGroup, "Scale", 1, 0.075, 0, 0, 1.1, 1.1, "center", 0, 0)
|
|
local scaleInAnim2 = detailsFramework:CreateAnimation(screenFrameFadeInAnimGroup, "Scale", 2, 0.05, 1, 1, 0.9, 0.9, "center", 0, 0)
|
|
local alphaInAnim = detailsFramework:CreateAnimation(screenFrameFadeInAnimGroup, "Alpha", 1, 0.075, 0, 1)
|
|
screenFrame.FadeInAnimation = screenFrameFadeInAnimGroup
|
|
|
|
local titleRoundedFrame = CreateFrame("frame", "DetailsNoteScreenTitleFrame", screenFrame, "BackdropTemplate")
|
|
titleRoundedFrame:SetPoint("bottomleft", screenFrame, "topleft", 5, -17)
|
|
titleRoundedFrame:SetPoint("bottomright", screenFrame, "topright", -5, -17)
|
|
titleRoundedFrame:SetHeight(34)
|
|
titleRoundedFrame:SetFrameLevel(screenFrame:GetFrameLevel() - 1)
|
|
local roundedSettings = detailsFramework.table.copy({}, Details.PlayerBreakdown.RoundedCornerPreset)
|
|
roundedSettings.roundness = 8
|
|
detailsFramework:AddRoundedCornersToFrame(titleRoundedFrame, roundedSettings)
|
|
titleRoundedFrame:SetColor(red-0.02, green-0.02, blue-0.02, 0.94)
|
|
|
|
local titleFrameText = titleRoundedFrame:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
titleFrameText:SetPoint("center", titleRoundedFrame, "center", 0, 8)
|
|
titleFrameText:SetText("Notes (/note)")
|
|
|
|
local LibWindow = LibStub("LibWindow-1.1")
|
|
LibWindow.RegisterConfig(screenFrame, config.screenpos.position)
|
|
LibWindow.MakeDraggable(screenFrame)
|
|
LibWindow.RestorePosition(screenFrame)
|
|
|
|
local titleText = screenFrame:CreateFontString(nil, "overlay", "GameFontNormal") --sent by
|
|
PixelUtil.SetPoint(titleText, "topleft", screenFrame, "topleft", 3, -3)
|
|
titleText:SetAlpha(0.934)
|
|
detailsFramework:SetFontSize(titleText, 11)
|
|
|
|
--create a report button to report the sender
|
|
local reportButton = detailsFramework:CreateButton(screenFrame, function()end, 100, 20, REPORT_PLAYER)
|
|
PixelUtil.SetPoint(reportButton, "topright", screenFrame, "topright", -26, 0)
|
|
reportButton:SetAlpha(0.934)
|
|
reportButton.textsize = 11
|
|
screenFrame.ReportButton = reportButton
|
|
|
|
local rightClickToCloseText = screenFrame:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
rightClickToCloseText:SetPoint("center", screenFrame, "center", 0, 0)
|
|
rightClickToCloseText:SetPoint("bottom", screenFrame, "bottom", 0, 27)
|
|
rightClickToCloseText:SetAlpha(0.934)
|
|
rightClickToCloseText:SetText("Right Click to Close")
|
|
detailsFramework:SetFontSize(rightClickToCloseText, 14)
|
|
|
|
--create close button in the top right corner, can use the framework
|
|
local closeButton = detailsFramework:CreateButton(screenFrame, function() screenFrame:Hide() end, 20, 20)
|
|
closeButton:SetIcon("perks-dropdown-clear", 16, 16, "overlay", {.4, .6, .4, .6})
|
|
closeButton:SetPoint("topright", screenFrame, "topright", 8, -1)
|
|
closeButton:SetAlpha(0.634)
|
|
closeButton.icon:SetDesaturated(true)
|
|
|
|
--text area for the note
|
|
local textArea = CreateFrame("EditBox", "$parentTextArea", screenFrame, "BackdropTemplate")
|
|
textArea:SetPoint("topleft", screenFrame, "topleft", 3, -27)
|
|
textArea:SetPoint("bottomright", screenFrame, "bottomright", -2, 22)
|
|
textArea:ClearFocus()
|
|
textArea:EnableMouse(false)
|
|
textArea:SetScript("OnEditFocusGained", function(self)
|
|
self:ClearFocus()
|
|
end)
|
|
textArea:SetFontObject("GameFontNormal")
|
|
textArea:SetMultiLine(true)
|
|
textArea:SetTextColor(1, 1, 1)
|
|
textArea:SetAlpha(0.934)
|
|
|
|
local resizerButton = CreateFrame("button", "$parentReziser", screenFrame)
|
|
resizerButton:SetSize(20, 20)
|
|
resizerButton:SetAlpha(0.734)
|
|
resizerButton:SetPoint("bottomright", screenFrame, "bottomright", -2, 2)
|
|
resizerButton:SetNormalTexture("Interface\\CHATFRAME\\UI-ChatIM-SizeGrabber-Up")
|
|
resizerButton:SetPushedTexture("Interface\\CHATFRAME\\UI-ChatIM-SizeGrabber-Down")
|
|
resizerButton:SetHighlightTexture("Interface\\CHATFRAME\\UI-ChatIM-SizeGrabber-Highlight")
|
|
|
|
resizerButton:SetScript("OnMouseDown", function()
|
|
screenFrame:StartSizing("BOTTOMRIGHT")
|
|
end)
|
|
resizerButton:SetScript("OnMouseUp", function()
|
|
screenFrame:StopMovingOrSizing()
|
|
config.screenpos.width = screenFrame:GetWidth()
|
|
config.screenpos.height = screenFrame:GetHeight()
|
|
end)
|
|
|
|
local banSender = detailsFramework:CreateButton(screenFrame, function()
|
|
config.banlist[senderName] = true
|
|
screenFrame:Hide()
|
|
end, 110, 20, "Ignore Sender")
|
|
--banSender:SetPoint("bottomleft", screenFrame, "bottomleft", 4, 4)
|
|
banSender:SetPoint("bottomright", screenFrame, "bottom", -1, 4)
|
|
banSender:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
banSender:SetIcon([[Interface\Scenarios\ScenarioIcon-Fail]], 16, 16, "overlay")
|
|
banSender:SetAlpha(0.934)
|
|
|
|
local optionsButton = detailsFramework:CreateButton(screenFrame, function()
|
|
noteEditor.OpenNoteOptionsPanel()
|
|
end, 110, 20, "OPTIONS")
|
|
--optionsButton:SetPoint("bottomleft", banSender, "bottomright", 4, 0)
|
|
optionsButton:SetPoint("bottomleft", screenFrame, "bottom", 1, 4)
|
|
optionsButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
optionsButton:SetIcon([[Interface\Scenarios\ScenarioIcon-Interact]], 16, 16, "overlay")
|
|
optionsButton:SetAlpha(0.934)
|
|
|
|
screenFrame.TextArea = textArea
|
|
screenFrame.TitleText = titleText
|
|
screenFrame.CloseButton = closeButton
|
|
screenFrame.ResizerButton = resizerButton
|
|
|
|
function screenFrame.SetNote(sender, text)
|
|
text = detailsFramework:Trim(text)
|
|
|
|
local unitRole = UnitGroupRolesAssigned(sender)
|
|
if (unitRole and unitRole ~= "NONE") then
|
|
local size = 16
|
|
sender = detailsFramework:AddRoleIconToText(sender, unitRole, size)
|
|
end
|
|
|
|
screenFrame.TitleText:SetText("From: " .. sender)
|
|
|
|
--find all unit names in the text and color them
|
|
text = noteEditor.FindAndColorUnitNames(text)
|
|
|
|
if (IsInRaid()) then
|
|
--no need to replace them on party as the token are already changed before the note is sent
|
|
text = noteEditor.ParseNoteText(text)
|
|
end
|
|
|
|
screenFrame.TextArea:SetText(text)
|
|
|
|
detailsFramework:SetFontSize(screenFrame.TextArea, config.fontsize)
|
|
screenFrame:Show()
|
|
end
|
|
|
|
function screenFrame.RefreshNoteTextSettings()
|
|
detailsFramework:SetFontSize(screenFrame.TextArea, config.fontsize)
|
|
end
|
|
|
|
function screenFrame.RefreshFrameSettings()
|
|
rightClickToCloseText:Show()
|
|
|
|
if (config.leftclickthrough and config.rightclickthrough) then
|
|
screenFrame:EnableMouse(false)
|
|
rightClickFrame:EnableMouse(false)
|
|
rightClickToCloseText:Hide()
|
|
|
|
elseif (config.leftclickthrough) then
|
|
screenFrame:EnableMouse(false)
|
|
rightClickFrame:EnableMouse(true)
|
|
rightClickFrame:RegisterForClicks("RightButtonDown")
|
|
rightClickFrame:RegisterForMouse("RightButtonDown")
|
|
rightClickFrame:SetPassThroughButtons("LeftButton")
|
|
|
|
elseif (config.rightclickthrough) then
|
|
screenFrame:EnableMouse(true)
|
|
screenFrame:RegisterForDrag("LeftButton")
|
|
screenFrame:RegisterForMouse("LeftButtonDown", "LeftButtonUp") --here the right click should be passed throught
|
|
screenFrame:SetPassThroughButtons("RightButton")
|
|
rightClickFrame:EnableMouse(false)
|
|
rightClickToCloseText:Hide()
|
|
|
|
else
|
|
screenFrame:EnableMouse(true)
|
|
screenFrame:RegisterForDrag("LeftButton")
|
|
rightClickFrame:EnableMouse(true)
|
|
rightClickFrame:RegisterForClicks("RightButtonDown")
|
|
rightClickFrame:RegisterForMouse("RightButtonDown")
|
|
rightClickFrame:SetPassThroughButtons("LeftButton")
|
|
end
|
|
|
|
local screenRed, screenGreen, screenBlue = unpack(config["framecolor"])
|
|
screenFrame:SetColor(screenRed, screenGreen, screenBlue, detailsFramework.Math.InvertInRange(0, 1, config["transparency"]))
|
|
titleRoundedFrame:SetColor(max(screenRed-0.02, 0), max(screenGreen-0.02, 0), max(screenBlue-0.02, 0), detailsFramework.Math.InvertInRange(0, 1, config["transparency"]))
|
|
titleRoundedFrame:SetShown(config["showheader"])
|
|
|
|
if (config.rightclickthrough) then
|
|
rightClickToCloseText:Hide()
|
|
else
|
|
rightClickToCloseText:SetShown(config["showrightclicktoclose"])
|
|
end
|
|
|
|
screenFrame:SetSize(config.screenpos.width or 275, config.screenpos.height or 350)
|
|
|
|
closeButton:SetShown(config["showclosebutton"])
|
|
banSender:SetShown(config["showbansenderbutton"])
|
|
optionsButton:SetShown(config["showoptionsbutton"])
|
|
resizerButton:SetShown(config["showresizebutton"])
|
|
end
|
|
end
|
|
|
|
local screenFrame = DetailsNoteScreenFrame
|
|
|
|
if (currentNoteId) then
|
|
screenFrame.ReportButton:SetClickFunction(function()
|
|
--open a dialog to report the sender
|
|
local reportType = 0 --chat
|
|
local playerLocation = nil
|
|
local bIsBnetReport = false
|
|
local bSendReportWithoutDialog = false
|
|
|
|
local reportInfo = ReportInfo:CreateReportInfoFromType(reportType)
|
|
reportInfo:SetReportTarget(currentSenderName)
|
|
|
|
ReportFrame:SetMajorType(Enum.ReportMajorCategory.InappropriateCommunication)
|
|
ReportFrame:InitiateReport(reportInfo, currentSenderName, playerLocation, bIsBnetReport, bSendReportWithoutDialog)
|
|
ReportFrame:MajorTypeSelected(reportType, Enum.ReportMajorCategory.InappropriateCommunication)
|
|
ReportFrame.Comment.EditBox:SetText("NOTEID: #" .. currentNoteId)
|
|
end)
|
|
|
|
screenFrame.ReportButton:Show()
|
|
else
|
|
screenFrame.ReportButton:Hide()
|
|
end
|
|
|
|
if (not config["tutorial1"]) then --~helptip
|
|
local helpTipInfo = {
|
|
text = "You received a note from another player.\n\nThis note contains instructions for the content you are about to engage in.\n\nIf the note is offensive, you may report the player to Blizzard using the 'Report Player' button.",
|
|
buttonStyle = HelpTip.ButtonStyle.Close,
|
|
targetPoint = HelpTip.Point.RightEdgeCenter,
|
|
offsetX = 8,
|
|
onHideCallback = function() config["tutorial1"] = true end,
|
|
}
|
|
HelpTip:Show(screenFrame, helpTipInfo)
|
|
end
|
|
|
|
screenFrame.RefreshNoteTextSettings()
|
|
screenFrame.RefreshFrameSettings()
|
|
screenFrame.SetNote(senderName, noteText)
|
|
|
|
local screenFrameHeight = screenFrame:GetHeight()
|
|
screenFrame.FlashTexture.FadeInAnimation.transInAnim:SetOffset(0, -screenFrameHeight/2)
|
|
local endOffset = ((screenFrameHeight/2) - (screenFrameHeight/8)) * -1
|
|
screenFrame.FlashTexture.FadeInAnimation.transOutAnim:SetOffset(0, endOffset)
|
|
screenFrame.FadeInAnimation:Play()
|
|
end
|
|
|
|
function Details222.Notes.RegisterForOpenRaidNotes()
|
|
local config = Details.third_party.openraid_notecache
|
|
--ñotedefault ~notedefault
|
|
config["banlist"] = config["banlist"] or {}
|
|
config["framepos"] = config["framepos"] or {scale = 1, position = {}}
|
|
config["screenpos"] = config["screenpos"] or {scale = 1, position = {}}
|
|
config["notes"] = config["notes"] or {}
|
|
config["fontsize"] = config["fontsize"] or 12
|
|
config["transparency"] = config["transparency"] or 0.02
|
|
|
|
if (not config["framecolor"]) then
|
|
local red, green, blue = detailsFramework:GetDefaultBackdropColor()
|
|
config["framecolor"] = {red, green, blue}
|
|
end
|
|
|
|
if (type(config["tutorial1"]) ~= "boolean") then
|
|
config["tutorial1"] = false
|
|
end
|
|
if (type(config["enabled"]) ~= "boolean") then
|
|
config["enabled"] = true
|
|
end
|
|
if (type(config["printtochat"]) ~= "boolean") then
|
|
config["printtochat"] = false
|
|
end
|
|
if (type(config["leftclickthrough"]) ~= "boolean") then
|
|
config["leftclickthrough"] = false
|
|
end
|
|
if (type(config["rightclickthrough"]) ~= "boolean") then
|
|
config["rightclickthrough"] = false
|
|
end
|
|
if (type(config["showheader"]) ~= "boolean") then --to show the "Notes (/note)"
|
|
config["showheader"] = true
|
|
end
|
|
if (type(config["showrightclicktoclose"]) ~= "boolean") then --to show the "right click to close"
|
|
config["showrightclicktoclose"] = true
|
|
end
|
|
if (type(config["showclosebutton"]) ~= "boolean") then
|
|
config["showclosebutton"] = true
|
|
end
|
|
if (type(config["showbansenderbutton"]) ~= "boolean") then
|
|
config["showbansenderbutton"] = true
|
|
end
|
|
if (type(config["showoptionsbutton"]) ~= "boolean") then
|
|
config["showoptionsbutton"] = true
|
|
end
|
|
if (type(config["showresizebutton"]) ~= "boolean") then
|
|
config["showresizebutton"] = true
|
|
end
|
|
|
|
local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true)
|
|
if (openRaidLib) then
|
|
--registering the callback:
|
|
local object = {
|
|
---@param unitId string
|
|
---@param unitNote unitnote
|
|
---@param allUnitsNote table<actorname, unitnote>
|
|
OnNoteUpdate = function(unitId, unitNote, allUnitsNote)
|
|
if (not config.enabled) then
|
|
return
|
|
end
|
|
|
|
local unitName = GetUnitName(unitId, true)
|
|
if (config.banlist[unitName]) then
|
|
return
|
|
end
|
|
|
|
local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo()
|
|
if (not canAcceptNoteOn[difficultyID] and not Details.debug) then --at the moment, players can only receive notes if inside a mythic dungeon
|
|
return
|
|
end
|
|
|
|
if (config.printtochat) then
|
|
print("|cFFFFAA00 Note Sent by:", unitName, "|r")
|
|
print(unitNote.note)
|
|
else
|
|
noteEditor.OpenNoteScreenPanel(unitName, unitNote.note, unitNote.commId, false)
|
|
end
|
|
end
|
|
}
|
|
openRaidLib.RegisterCallback(object, "NoteUpdated", "OnNoteUpdate")
|
|
end
|
|
end
|
|
|
|
local checkForRegisteredNoteCommandOverride = function(command)
|
|
local commandRegisteredCallbacks = noteCallbacks[command]
|
|
|
|
--if there is addons registered to use the keystone command, call them and do not show the default frame from details!
|
|
if (#commandRegisteredCallbacks > 0) then
|
|
--loop through all registered addons and call their callback function
|
|
local bCallbackSuccess = false
|
|
for i = 1, #commandRegisteredCallbacks do
|
|
local thisCallback = commandRegisteredCallbacks[i]
|
|
|
|
local addonObject = thisCallback.addonObject
|
|
local memberName = thisCallback.memberName
|
|
local payload = thisCallback.payload
|
|
|
|
if (type(addonObject[memberName]) == "function") then
|
|
local result = detailsFramework:Dispatch(addonObject[memberName], unpack(payload)) --uses xpcall
|
|
if (result ~= false) then
|
|
bCallbackSuccess = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if (bCallbackSuccess) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function SlashCmdList.NOTE(msg, editbox)
|
|
if (checkForRegisteredNoteCommandOverride("NOTE")) then
|
|
return
|
|
else
|
|
noteEditor.OpenNoteEditor()
|
|
end
|
|
end
|
|
|
|
function SlashCmdList.NOTES(msg, editbox)
|
|
if (checkForRegisteredNoteCommandOverride("NOTES")) then
|
|
return
|
|
else
|
|
noteEditor.OpenNoteEditor()
|
|
end
|
|
end
|
|
|
|
function SlashCmdList.NOTEPAD(msg, editbox)
|
|
if (checkForRegisteredNoteCommandOverride("NOTEPAD")) then
|
|
return
|
|
else
|
|
noteEditor.OpenNoteEditor()
|
|
end
|
|
end
|
|
|
|
--debugging
|
|
C_Timer.After(3, function()
|
|
--noteEditor.OpenNoteEditor()
|
|
end)
|
|
C_Timer.After(0, function()
|
|
if (SubscriptionInterstitialFrame) then
|
|
if (SubscriptionInterstitialFrame:IsShown()) then
|
|
SubscriptionInterstitialFrame.ClosePanelButton:Click()
|
|
end
|
|
end
|
|
end)
|
|
|
|
|