mirror of
https://github.com/OldManAlpha/Puppeteer.git
synced 2025-11-28 23:48:35 +00:00
346 lines
11 KiB
Lua
346 lines
11 KiB
Lua
PTUtil.SetEnvironment(Puppeteer)
|
|
local _G = getfenv(0)
|
|
local util = PTUtil
|
|
local colorize = util.Colorize
|
|
local GetColoredRoleText = util.GetColoredRoleText
|
|
local SplitString = util.SplitString
|
|
|
|
AssignedRoles = nil
|
|
|
|
LFTAutoRoleFrame = CreateFrame("Frame", "PT_LFTAutoRoleFrame")
|
|
function SetLFTAutoRoleEnabled(enabled)
|
|
if not util.IsTurtleWow() then
|
|
return
|
|
end
|
|
|
|
if not enabled then
|
|
LFTAutoRoleFrame:SetScript("OnEvent", nil)
|
|
LFTAutoRoleFrame:SetScript("OnUpdate", nil)
|
|
LFTAutoRoleFrame:UnregisterAllEvents()
|
|
return
|
|
end
|
|
|
|
if LFTAutoRoleFrame:GetScript("OnEvent") ~= nil then -- Already enabled
|
|
return
|
|
end
|
|
|
|
local roleMap = {
|
|
["t"] = "Tank",
|
|
["h"] = "Healer",
|
|
["d"] = "Damage"
|
|
}
|
|
local offerCompleteTime = -1 -- The time the offer is completed, used to verify rolecheck info is valid
|
|
local alreadyAssigned = {} -- The Tank & Healer names
|
|
local scanDPSTime = -1
|
|
local AutoRoleFrame_OnUpdate = function()
|
|
if scanDPSTime > GetTime() then
|
|
return
|
|
end
|
|
|
|
for _, unit in ipairs(PartyUnits) do
|
|
local name = UnitName(unit)
|
|
if name ~= "Unknown" and not util.ArrayContains(alreadyAssigned, name) then
|
|
print("Assuming "..name.." is Damage")
|
|
SetAssignedRole(name, "Damage")
|
|
end
|
|
end
|
|
UpdateUnitFrameGroups()
|
|
LFTAutoRoleFrame:SetScript("OnUpdate", nil)
|
|
end
|
|
LFTAutoRoleFrame:RegisterEvent("CHAT_MSG_ADDON")
|
|
LFTAutoRoleFrame:SetScript("OnEvent", function()
|
|
if arg1 == (LFT_ADDON_PREFIX or "TW_LFG") then
|
|
-- After an offer is complete, it is immediately followed by rolecheck info for the tank and healer
|
|
if strfind(arg2, "S2C_ROLECHECK_INFO") then
|
|
if GetNumPartyMembers() == 4 then
|
|
local params = util.SplitString(arg2, ";")
|
|
local member = params[2]
|
|
params = util.SplitString(params[3], ":") -- get confirmed roles
|
|
if offerCompleteTime + 0.5 > GetTime() and table.getn(params) == 1 then
|
|
local role = roleMap[params[1]]
|
|
table.insert(alreadyAssigned, member)
|
|
SetAssignedRole(member, role) -- Tank & Healer is sent after the offer is complete
|
|
print("Assigning "..member.." to "..role)
|
|
if table.getn(alreadyAssigned) == 2 then -- Set rest as Damage after Tank & Healer is sent
|
|
-- Delay scanning party members because their names might not be loaded yet
|
|
scanDPSTime = GetTime() + 1.5
|
|
LFTAutoRoleFrame:SetScript("OnUpdate", AutoRoleFrame_OnUpdate)
|
|
end
|
|
UpdateUnitFrameGroups()
|
|
end
|
|
end
|
|
elseif strfind(arg2, "S2C_OFFER_COMPLETE") then
|
|
alreadyAssigned = {}
|
|
offerCompleteTime = GetTime()
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
function GetAssignedRole(name)
|
|
if not AssignedRoles or not AssignedRoles[name] then
|
|
return
|
|
end
|
|
AssignedRoles[name]["lastSeen"] = time()
|
|
return AssignedRoles[name]["role"]
|
|
end
|
|
|
|
function GetUnitAssignedRole(unit)
|
|
if not UnitIsPlayer(unit) then
|
|
return
|
|
end
|
|
return GetAssignedRole(UnitName(unit))
|
|
end
|
|
|
|
function SetAssignedRole(name, role)
|
|
if role == nil or role == "No Role" then
|
|
AssignedRoles[name] = nil
|
|
return
|
|
end
|
|
AssignedRoles[name] = {
|
|
["role"] = role,
|
|
["lastSeen"] = time()
|
|
}
|
|
end
|
|
|
|
-- Returns true if role assignment failed
|
|
function SetUnitAssignedRole(unit, role)
|
|
if not UnitIsPlayer(unit) then
|
|
return true
|
|
end
|
|
SetAssignedRole(UnitName(unit), role)
|
|
end
|
|
|
|
function PruneAssignedRoles()
|
|
local currentTime = time()
|
|
for name, data in pairs(AssignedRoles) do
|
|
if not data["lastSeen"] or data["lastSeen"] < currentTime - (24 * 60 * 60) then
|
|
AssignedRoles[name] = nil
|
|
--print("Pruned "..name.."'s role")
|
|
end
|
|
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)
|
|
if not TalentCountRoleMap[class] then
|
|
SetRoleAndUpdate(name, "Damage")
|
|
return
|
|
end
|
|
PlayerTalentData[name] = {class = class, trees = {}}
|
|
requestTalents(name)
|
|
end
|
|
|
|
RoleAssignInfo = {}
|
|
|
|
RoleDropdown = PTGuiLib.Get("dropdown", UIParent)
|
|
|
|
function InitRoleDropdown()
|
|
local initFunc = function(self)
|
|
self.checked = (GetAssignedRole(RoleAssignInfo.Name) or "No Role") == self.role
|
|
end
|
|
|
|
local genRole = function(role)
|
|
return {
|
|
text = GetColoredRoleText(role),
|
|
role = role,
|
|
initFunc = initFunc,
|
|
func = function(info)
|
|
SetAssignedRole(RoleAssignInfo.Name, info.role)
|
|
UpdateUnitFrameGroups()
|
|
end
|
|
}
|
|
end
|
|
local massRoleFunc = function(info)
|
|
if not RoleAssignInfo.FrameGroup then
|
|
return
|
|
end
|
|
for _, ui in pairs(RoleAssignInfo.FrameGroup.uis) do
|
|
if (not ui:GetRole() or not info.role) and UnitIsPlayer(ui:GetUnit()) then
|
|
SetAssignedRole(UnitName(ui:GetUnit()), info.role)
|
|
end
|
|
end
|
|
UpdateUnitFrameGroups()
|
|
RoleDropdown:SetToggleState(false)
|
|
end
|
|
local genMassRole = function(role)
|
|
return {
|
|
text = GetColoredRoleText(role),
|
|
role = role,
|
|
notCheckable = true,
|
|
func = massRoleFunc
|
|
}
|
|
end
|
|
|
|
local options = {
|
|
{
|
|
initFunc = function(self)
|
|
self.text = colorize(RoleAssignInfo.Name.."'s Role", RoleAssignInfo.ClassColor)
|
|
end,
|
|
notCheckable = true,
|
|
disabled = true,
|
|
textHeight = 12
|
|
},
|
|
genRole("Tank"),
|
|
genRole("Healer"),
|
|
genRole("Damage"),
|
|
genRole("No Role"),
|
|
{
|
|
notCheckable = true,
|
|
disabled = true
|
|
}, {
|
|
text = "Set Unassigned As",
|
|
tooltipTitle = "Set Unassigned As",
|
|
tooltipText = "Mass-set the roles of unassigned players. Only applies to players contained in this UI group.",
|
|
notCheckable = true,
|
|
textHeight = 11,
|
|
children = {
|
|
genMassRole("Tank"),
|
|
genMassRole("Healer"),
|
|
genMassRole("Damage")
|
|
}
|
|
}, {
|
|
text = "Clear Roles",
|
|
tooltipTitle = "Clear Roles",
|
|
tooltipText = "Clear all players' roles. Only applies to players contained in this UI group.",
|
|
notCheckable = true,
|
|
textHeight = 11,
|
|
func = massRoleFunc
|
|
}
|
|
}
|
|
if PTGlobalOptions.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 |