Add experimental auto role detection

This commit is contained in:
OldManAlpha 2025-08-28 20:02:32 -07:00
parent 83736ac0c4
commit 87d27f4cc9
5 changed files with 161 additions and 7 deletions

View File

@ -354,6 +354,8 @@ function OnAddonLoaded()
end
end)
end
InitRoleDropdown()
SetLFTAutoRoleEnabled(PTOptions.LFTAutoRole)

View File

@ -133,6 +133,9 @@ function SetDefaults()
["Medium"] = 10, -- <=2 min
["Long"] = 60 * 2 -- >2 min
},
["Experiments"] = {
["AutoRole"] = false
},
["CastWhen"] = "Mouse Up", -- Mouse Up, Mouse Down
["CastWhenKey"] = "Key Up", -- Key Up, Key Down
["AutoResurrect"] = Puppeteer.ResurrectionSpells[util.GetClass("player")] ~= nil,

View File

@ -81,6 +81,7 @@ RegisterActionBind({
return
end
RoleAssignInfo.Name = UnitName(unit)
RoleAssignInfo.Class = util.GetClass(unit)
RoleAssignInfo.ClassColor = util.GetClassColor(util.GetClass(unit), true)
RoleAssignInfo.FrameGroup = unitFrame.owningGroup
local frame = unitFrame:GetRootContainer()

View File

@ -3,6 +3,7 @@ local _G = getfenv(0)
local util = PTUtil
local colorize = util.Colorize
local GetColoredRoleText = util.GetColoredRoleText
local SplitString = util.SplitString
AssignedRoles = nil
@ -120,15 +121,117 @@ function PruneAssignedRoles()
end
end
function SetRoleAndUpdate(name, role)
SetAssignedRole(name, role)
UpdateUnitFrameGroups()
end
function SetUnitRoleAndUpdate(unit, role)
if not SetUnitAssignedRole(unit, role) then
UpdateUnitFrameGroups()
end
end
-- Players will be considered as the role in the index if they have the highest talent points in said index.
-- Clases not listed have only DPS specs and are not bothered to be scanned.
TalentCountRoleMap = {
PRIEST = {
"Healer", "Healer", "Damage"
},
PALADIN = {
"Healer", "Tank", "Damage"
},
WARRIOR = {
"Damage", "Damage", "Tank"
},
SHAMAN = {
"Damage", "Damage", "Healer"
},
DRUID = { -- Spec #2(Feral) will be swapped to Tank if Thick Hide talent is found
"Damage", "Damage", "Healer"
}
}
local PlayerTalentData = {}
local talentScanner = CreateFrame("Frame", "PTTalentScanner")
talentScanner:RegisterEvent("CHAT_MSG_ADDON")
talentScanner:SetScript("OnEvent", function()
if arg1 == "TW_CHAT_MSG_WHISPER" then
local message = arg2
local sender = arg4
if not PlayerTalentData[sender] then
return
end
if string.find(message, "INSTalentTabInfo;", 1, true) then
-- This is sent right before receiving info for individual talents in the tree
local split = SplitString(message, ';')
local index = tonumber(split[2])
local pointsSpent = tonumber(split[4])
PlayerTalentData[sender].trees[index] = {points = pointsSpent, talents = {}}
elseif string.find(message, "INSTalentInfo;", 1, true) then
local split = SplitString(message, ';')
local tree = tonumber(split[2])
local tier = tonumber(split[5])
local column = tonumber(split[6])
local currRank = tonumber(split[7])
local cache = PlayerTalentData[sender]
local talents = cache.trees[tree].talents
talents[tier.."-"..column] = currRank
elseif string.find(message, "INSTalentEND;", 1, true) then
local data = PlayerTalentData[sender]
local trees = data.trees
local mostPoints = 0
local mostIndex = 1
for i = 1, 3 do
if trees[i].points > mostPoints then
mostPoints = trees[i].points
mostIndex = i
end
end
local class = data.class
-- Check for Druid Thick Hide talent, set as tank if they have it
if class == "DRUID" and (trees[2].talents["2-3"] or 0) > 0 then
SetRoleAndUpdate(sender, "Tank")
else
SetRoleAndUpdate(sender, mostPoints > 0 and TalentCountRoleMap[class][mostIndex] or "Damage")
end
PlayerTalentData[sender] = nil
end
end
end)
local function requestTalents(name)
SendAddonMessage("TW_CHAT_MSG_WHISPER<"..name..">", "INSShowTalents", "GUILD")
end
function AutoRole(unit)
local class = util.GetClass(unit)
if not TalentCountRoleMap[class] then
SetUnitRoleAndUpdate(unit, "Damage")
return
end
if not UnitIsConnected(unit) then -- Can't request offline player's talents
return
end
PlayerTalentData[UnitName(unit)] = {class = class, trees = {}}
requestTalents(UnitName(unit))
end
function AutoRoleByNameClass(name, class)
PlayerTalentData[name] = {class = class, trees = {}}
requestTalents(name)
end
RoleAssignInfo = {}
do
RoleDropdown = PTGuiLib.Get("dropdown", UIParent)
function InitRoleDropdown()
local initFunc = function(self)
self.checked = (GetAssignedRole(RoleAssignInfo.Name) or "No Role") == self.role
end
@ -165,7 +268,6 @@ do
}
end
RoleDropdown = PTGuiLib.Get("dropdown", UIParent)
local options = {
{
initFunc = function(self)
@ -178,7 +280,7 @@ do
genRole("Tank"),
genRole("Healer"),
genRole("Damage"),
genRole("No Role"),
genRole("No Role"),
{
notCheckable = true,
disabled = true
@ -202,5 +304,39 @@ do
func = massRoleFunc
}
}
if PTOptions.Experiments.AutoRole then
table.insert(options, 6, {
text = colorize("Auto Detect", 1, 0.6, 0),
func = function()
if not RoleAssignInfo.FrameGroup then
return
end
AutoRoleByNameClass(RoleAssignInfo.Name, RoleAssignInfo.Class)
end
})
local lastMassRole = 0
table.insert(options, 9, {
text = "Auto Detect Unassigned",
tooltipTitle = "Auto Detect Unassigned",
tooltipText = "Automatically detect the roles of unassigned players. Only applies to players contained in this UI group.",
notCheckable = true,
textHeight = 11,
func = function()
if not RoleAssignInfo.FrameGroup then
return
end
if lastMassRole + 6 > GetTime() then
DEFAULT_CHAT_FRAME:AddMessage("Please wait a moment before requesting roles again")
return
end
lastMassRole = GetTime()
for _, ui in pairs(RoleAssignInfo.FrameGroup.uis) do
if UnitIsPlayer(ui:GetUnit()) and not GetUnitAssignedRole(ui:GetUnit()) then
AutoRole(ui:GetUnit())
end
end
end
})
end
RoleDropdown:SetOptions(options)
end

View File

@ -436,7 +436,7 @@ function CreateTab_Options_SpellsTooltip(panel)
layout:offset(0, 10)
factory:dropdown("Anchor", "Where the tooltip should be anchored", "SpellsTooltip.Anchor",
{"Top Left", "Top Right", "Bottom Left", "Bottom Right"})
factory:checkbox("Show Item Count", {"Show the amount of your bound items", colorize("Warning: This causes lag!", 1, 0.2, 0.2)},
factory:checkbox("Show Item Count", {"Show the amount of your bound items", colorize("Warning: This causes lag!", 1, 0.4, 0.4)},
"SpellsTooltip.ShowItemCount")
end
@ -477,22 +477,26 @@ function CreateTab_Options_Other(panel)
"UseHealPredictions", function() Puppeteer.UpdateAllIncomingHealing() end)
factory:checkbox("(TWoW) LFT Auto Role", {"Automatically assign roles when joining LFT groups",
"This functionality was created for 1.17.2 and may break in future updates"}, "LFTAutoRole",
"This functionality was tested for 1.18.0 and may break in future updates"}, "LFTAutoRole",
function() Puppeteer.SetLFTAutoRoleEnabled(PTOptions.LFTAutoRole) end)
end
function CreateTab_Options_Advanced(panel)
local container = panel:CreateTab("Advanced")
local layout = NewLabeledColumnLayout(container, {150, 220, 300}, -20, 10)
local layout = NewLabeledColumnLayout(container, {150, 220, 300}, 0, 10)
local factory = NewComponentFactory(container, layout)
container.factory = factory
local TEXT_WIDTH = 370
local scriptsLabel = CreateLabel(container, "Load & Postload Scripts")
:SetPoint("TOP", container, "TOP", 0, -10)
:SetFontSize(14)
local loadScriptInfo = CreateLabel(container, "The Load Script runs after profiles are initialized, but before UIs are created, "..
"making it good for editing profile attributes. GetProfile and CreateProfile are defined locals.")
:SetWidth(TEXT_WIDTH)
:SetPoint("TOP", container, "TOP", 0, -10)
:SetPoint("TOP", scriptsLabel, "BOTTOM", 0, -10)
local loadScriptButton = PTGuiLib.Get("button", container)
:SetPoint("TOP", loadScriptInfo, "BOTTOM", 0, -5)
:SetSize(150, 20)
@ -547,6 +551,14 @@ function CreateTab_Options_Advanced(panel)
:OnClick(function()
ReloadUI()
end)
local experimentsLabel = CreateLabel(container, "Experiments")
:SetPoint("TOP", reloadButton, "BOTTOM", 0, -20)
:SetFontSize(14)
layout:offset(0, -260)
factory:checkbox("(TWoW) Auto Role", {"If enabled, the Role Action menu shows auto role detection options",
colorize("Using this functionality WILL cause errors and other unexpected behavior", 1, 0.4, 0.4)}, "Experiments.AutoRole",
Puppeteer.InitRoleDropdown)
end
function CreateTab_Options_Mods(panel)