From cebe150e163aa3a2d749c3946c5810eedc0409ec Mon Sep 17 00:00:00 2001 From: Tercio Jose Date: Tue, 16 May 2023 15:21:04 -0300 Subject: [PATCH] General Fixes and Improvements --- Definitions.lua | 1 + classes/class_combat.lua | 2 + classes/container_actors.lua | 33 +- classes/container_spells.lua | 7 + core/parser.lua | 32 ++ frames/window_main.lua | 1 + functions/classes.lua | 142 +++++-- functions/mixin.lua | 10 + functions/playerclass.lua | 700 +++++++++++++++-------------------- startup.lua | 10 +- 10 files changed, 483 insertions(+), 455 deletions(-) diff --git a/Definitions.lua b/Definitions.lua index ecd2145c..5ae28689 100644 --- a/Definitions.lua +++ b/Definitions.lua @@ -436,6 +436,7 @@ ---@field Tempo fun(actor: actor) : number get the activity or effective time of the actor ---@field GetPets fun(actor: actor) : table get a table with all pet names that belong to the player ---@field GetSpellList fun(actor: actor) : table +---@field GetSpellContainerNames fun(container: actorcontainer) : string[] get the table which contains the names of the spell containers ---@class actordamage : actor ---@field friendlyfire_total number diff --git a/classes/class_combat.lua b/classes/class_combat.lua index 1dfdca32..42eda4de 100644 --- a/classes/class_combat.lua +++ b/classes/class_combat.lua @@ -8,6 +8,8 @@ --[[global]] DETAILS_SEGMENTID_OVERALL = -1 --[[global]] DETAILS_SEGMENTID_CURRENT = 0 +--[[global]] DETAILS_COMBAT_AMOUNT_CONTAINERS = 4 + --enum segments type --[[global]] DETAILS_SEGMENTTYPE_GENERIC = 0 diff --git a/classes/container_actors.lua b/classes/container_actors.lua index 108ffc84..5eda4313 100644 --- a/classes/container_actors.lua +++ b/classes/container_actors.lua @@ -30,6 +30,8 @@ local pet_tooltip_frame = _G.DetailsPetOwnerFinder + local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --constants @@ -469,26 +471,17 @@ end --try to get the actor class from name local getActorClass = function(actorObject, actorName, actorFlags, actorSerial) --get spec - if (Details.track_specs) then - local specId = Details.cached_specs[actorSerial] - if (specId) then - actorObject:SetSpecId(specId) - --check is didn't changed the spec: - if (Details.streamer_config.quick_detection) then - --validate the spec more times if on quick detection - Details:ScheduleTimer("ReGuessSpec", 2, {actorObject}) - Details:ScheduleTimer("ReGuessSpec", 4, {actorObject}) - Details:ScheduleTimer("ReGuessSpec", 6, {actorObject}) - end - Details:ScheduleTimer("ReGuessSpec", 15, {actorObject}) - else - if (Details.streamer_config.quick_detection) then - --shoot detection early if in quick detection - Details:ScheduleTimer("GuessSpec", 1, {actorObject, nil, 1}) - else - Details:ScheduleTimer("GuessSpec", 3, {actorObject, nil, 1}) - end - end + local specId = Details.cached_specs[actorSerial] + if (specId) then + actorObject:SetSpecId(specId) + end + + if (not specId and Details.track_specs) then + Details:ScheduleTimer("GuessSpec", 2, {actorObject, nil, 1}) +-- if (Details.streamer_config.quick_detection) then +-- else +-- Details:ScheduleTimer("GuessSpec", 3, {actorObject, nil, 1}) +-- end end local _, engClass = UnitClass(actorName or "") diff --git a/classes/container_spells.lua b/classes/container_spells.lua index dce4dbe8..e6012355 100644 --- a/classes/container_spells.lua +++ b/classes/container_spells.lua @@ -44,6 +44,13 @@ local addonName, Details222 = ... return self._ActorTable[spellId] end + + ---return a table containing keys as spellid and value as spelltable + ---@return table + function container_habilidades:GetRawSpellTable() + return self._ActorTable + end + ---return the value of the spellTable[key] for the passed spellId ---@param spellId number ---@param key string diff --git a/core/parser.lua b/core/parser.lua index c79ab6b5..54201a50 100755 --- a/core/parser.lua +++ b/core/parser.lua @@ -6484,6 +6484,38 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 end end + + function Details:GetUnitId(unitName) + unitName = unitName or self.nome + local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) + if (openRaidLib) then + local unitId = openRaidLib.GetUnitID(unitName) + if (unitId) then + return unitId + end + end + + if (IsInRaid()) then + for i = 1, GetNumGroupMembers() do + local unitId = "raid" .. i + if (GetUnitName(unitId, true) == unitName) then + return unitId + end + end + + elseif (IsInGroup()) then + for i = 1, GetNumGroupMembers() -1 do + local unitId = "party" .. i + if (GetUnitName(unitId, true) == unitName) then + return unitId + end + end + if (UnitName("player") == unitName) then + return "player" + end + end + end + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --battleground parser diff --git a/frames/window_main.lua b/frames/window_main.lua index d7f116c3..3a11a9fd 100644 --- a/frames/window_main.lua +++ b/frames/window_main.lua @@ -3303,6 +3303,7 @@ Details.snap_alert:Hide() Details.snap_alert:SetFrameStrata("FULLSCREEN") function Details:SnapAlert() + print("alert started") Details.snap_alert:ClearAllPoints() Details.snap_alert:SetPoint("topleft", self.baseframe.cabecalho.modo_selecao.widget, "topleft", -8, 6) Details.snap_alert:SetPoint("bottomright", self.baseframe.cabecalho.modo_selecao.widget, "bottomright", 8, -6) diff --git a/functions/classes.lua b/functions/classes.lua index 48ee9f56..9404e8c5 100644 --- a/functions/classes.lua +++ b/functions/classes.lua @@ -33,7 +33,7 @@ do _detalhes.atributo_damage = {} _detalhes.atributo_damage.__index = _detalhes.atributo_damage setmetatable(_detalhes.atributo_damage, _detalhes.container_combatentes) - + -------------------------------- cura das habilidades. _detalhes.atributo_heal = {} _detalhes.atributo_heal.__index = _detalhes.atributo_heal @@ -43,17 +43,17 @@ do _detalhes.atributo_energy = {} _detalhes.atributo_energy.__index = _detalhes.atributo_energy setmetatable(_detalhes.atributo_energy, _detalhes.container_combatentes) - + -------------------------------- outros atributos _detalhes.atributo_misc = {} _detalhes.atributo_misc.__index = _detalhes.atributo_misc setmetatable(_detalhes.atributo_misc, _detalhes.container_combatentes) - + -------------------------------- atributos customizados _detalhes.atributo_custom = {} _detalhes.atributo_custom.__index = _detalhes.atributo_custom setmetatable(_detalhes.atributo_custom, _detalhes.container_combatentes) - + -------------------------------- armazena as classes de habilidades usadas pelo combatente _detalhes.container_habilidades = {} _detalhes.container_habilidades.__index = _detalhes.container_habilidades @@ -63,12 +63,12 @@ do _detalhes.habilidade_cura = {} _detalhes.habilidade_cura.__index = _detalhes.habilidade_cura setmetatable(_detalhes.habilidade_cura, _detalhes.container_habilidades) - + ---------------------------------------- classe das habilidades que d�o danos _detalhes.habilidade_dano = {} _detalhes.habilidade_dano.__index = _detalhes.habilidade_dano setmetatable(_detalhes.habilidade_dano, _detalhes.container_habilidades) - + ---------------------------------------- classe das habilidades que d�o e_energy _detalhes.habilidade_e_energy = {} _detalhes.habilidade_e_energy.__index = _detalhes.habilidade_e_energy @@ -78,13 +78,13 @@ do _detalhes.habilidade_misc = {} _detalhes.habilidade_misc.__index = _detalhes.habilidade_misc setmetatable(_detalhes.habilidade_misc, _detalhes.container_habilidades) - + ---------------------------------------- classe dos alvos das habilidads _detalhes.alvo_da_habilidade = {} _detalhes.alvo_da_habilidade.__index = _detalhes.alvo_da_habilidade setmetatable(_detalhes.alvo_da_habilidade, _detalhes.container_combatentes) - + --[[ Armazena os diferentes tipos de containers ]] --[[ Container Types ]] _detalhes.container_type = { @@ -121,10 +121,10 @@ do self.spec = initialSpecListOverride[specId] or specId end - function _detalhes:Name (actor) + function _detalhes:Name(actor) return self.nome or actor and actor.nome end - function _detalhes:GetName (actor) + function _detalhes:GetName(actor) return self.nome or actor and actor.nome end @@ -133,7 +133,7 @@ do return Details:GetOnlyName(name) end - function _detalhes:GetDisplayName (actor) + function _detalhes:GetDisplayName(actor) return self.displayName or actor and actor.displayName end @@ -152,16 +152,16 @@ do end return self.nome:gsub(("%-.*"), "") end - - function _detalhes:RemoveOwnerName (string) + + function _detalhes:RemoveOwnerName(string) if (string) then return string:gsub((" <.*"), "") end return self.nome:gsub((" <.*"), "") end - + function _detalhes:GetCLName(id) - local name, realm = UnitName (id) + local name, realm = UnitName(id) if (name) then if (realm and realm ~= "") then name = name .. "-" .. realm @@ -169,50 +169,134 @@ do return name end end - function _detalhes:Class (actor) + + function Details:Class(actor) return self.classe or actor and actor.classe end - function _detalhes:GetActorClass (actor) + + function Details:GetActorClass(actor) return self.classe or actor and actor.classe end - function _detalhes:GetGUID (actor) + + function Details:GetGUID(actor) return self.serial or actor and actor.serial end - function _detalhes:GetFlag (actor) + + function Details:GetFlag(actor) return self.flag_original or actor and actor.flag_original end - function _detalhes:GetSpells() - return self.spells._ActorTable - end - function _detalhes:GetActorSpells() + function Details:GetSpells() return self.spells._ActorTable end - function _detalhes:GetSpell(spellid) + function Details:GetActorSpells() + return self.spells._ActorTable + end + + function Details:GetSpell(spellid) return self.spells._ActorTable [spellid] end ---return an array of pet names ---@return table - function _detalhes:GetPets() + function Details:GetPets() return self.pets end ---return an array of pet names ---@return table - function _detalhes:Pets() + function Details:Pets() return self.pets end - function _detalhes:GetSpec(actor) + function Details:GetSpec(actor) return self.spec or actor and actor.spec end - function _detalhes:Spec(actor) + function Details:Spec(actor) return self.spec or actor and actor.spec end - + + ---add the class color to the string passed + ---@param thisString string + ---@param class string + ---@return string + function Details:AddColorString(thisString, class) + --check if the class colors exists + local classColors = _G["RAID_CLASS_COLORS"] + if (classColors) then + local color = classColors[class] + --check if the player name is valid + if (type(thisString) == "string" and color) then + thisString = "|c" .. color.colorStr .. thisString .. "|r" + return thisString + end + end + + --if failed, return the string without modifications + return thisString + end + + ---add the role icon to the string passed + ---@param thisString string + ---@param role string + ---@param size number|nil default is 14 + ---@return string + function Details:AddRoleIcon(thisString, role, size) + --check if is a valid role + local roleIcon = Details.role_texcoord [role] + if (type(thisString) == "string" and roleIcon and role ~= "NONE") then + --add the role icon + size = size or 14 + thisString = "|TInterface\\LFGFRAME\\UI-LFG-ICON-ROLES:" .. size .. ":" .. size .. ":0:0:256:256:" .. roleIcon .. "|t " .. thisString + return thisString + end + + --if failed, return the string without modifications + return thisString + end + + ---add the spec icon or class icon to the string passed + ---@param thisString string + ---@param class string|nil + ---@param spec number|nil + ---@param iconSize number|nil default is 16 + ---@param useAlphaIcons boolean|nil default is false + ---@return string + function Details:AddClassOrSpecIcon(thisString, class, spec, iconSize, useAlphaIcons) + iconSize = iconSize or 16 + + if (spec) then + local specString = "" + local L, R, T, B = unpack(Details.class_specs_coords[spec]) + if (L) then + if (useAlphaIcons) then + specString = "|TInterface\\AddOns\\Details\\images\\spec_icons_normal_alpha:" .. iconSize .. ":" .. iconSize .. ":0:0:512:512:" .. (L * 512) .. ":" .. (R * 512) .. ":" .. (T * 512) .. ":" .. (B * 512) .. "|t" + else + specString = "|TInterface\\AddOns\\Details\\images\\spec_icons_normal:" .. iconSize .. ":" .. iconSize .. ":0:0:512:512:" .. (L * 512) .. ":" .. (R * 512) .. ":" .. (T * 512) .. ":" .. (B * 512) .. "|t" + end + return specString .. " " .. thisString + end + end + + if (class) then + local classString = "" + local L, R, T, B = unpack(Details.class_coords[class]) + if (L) then + local imageSize = 128 + if (useAlphaIcons) then + classString = "|TInterface\\AddOns\\Details\\images\\classes_small_alpha:" .. iconSize .. ":" .. iconSize .. ":0:0:" .. imageSize .. ":" .. imageSize .. ":" .. (L * imageSize) .. ":" .. (R * imageSize) .. ":" .. (T * imageSize) .. ":" .. (B * imageSize) .. "|t" + else + classString = "|TInterface\\AddOns\\Details\\images\\classes_small:" .. iconSize .. ":" .. iconSize .. ":0:0:" .. imageSize .. ":" .. imageSize .. ":" .. (L * imageSize) .. ":" .. (R * imageSize) .. ":" .. (T * imageSize) .. ":" .. (B * imageSize) .. "|t" + end + return classString .. " " .. thisString + end + end + + return thisString + end + --inherits to all actors without placing it on _detalhes namespace. _detalhes.container_combatentes.guid = _detalhes.GetGUID _detalhes.container_combatentes.name = _detalhes.GetName diff --git a/functions/mixin.lua b/functions/mixin.lua index f0fc22a7..f2429bcc 100644 --- a/functions/mixin.lua +++ b/functions/mixin.lua @@ -4,7 +4,17 @@ local detailsFramework = _G.DetailsFramework local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) local addonName, Details222 = ... +local actorSpellContainers = { + "debuff", "buff", "spell", "cooldowns" +} + Details222.Mixins.ActorMixin = { + ---return a table containing the spellContainers names: 'debuff', 'buff', 'spell', 'cooldowns' + ---@return string[] + GetSpellContainerNames = function() + return actorSpellContainers + end, + ---return a spellContainer from an actor ---@param actor actor ---@param containerType string diff --git a/functions/playerclass.lua b/functions/playerclass.lua index d9aae4b6..33a9af46 100644 --- a/functions/playerclass.lua +++ b/functions/playerclass.lua @@ -1,16 +1,24 @@ ---[[ detect actor class ]] do - local Details = _G.Details local _ local addonName, Details222 = ... local pairs = pairs local ipairs = ipairs local unpack = table.unpack or _G.unpack + local GetSpellInfo = GetSpellInfo + local UnitClass = UnitClass + local UnitGUID = UnitGUID - local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) - local unknown_class_coords = {0.75, 1, 0.75, 1} + local CONST_UNKNOWN_CLASS_COORDS = {0.75, 1, 0.75, 1} + local CONST_DEFAULT_COLOR = {1, 1, 1, 1} + + local roles = { + DAMAGER = {421/512, 466/512, 381/512, 427/512}, + HEALER = {467/512, 512/512, 381/512, 427/512}, + TANK = {373/512, 420/512, 381/512, 427/512}, + NONE = {0, 50/512, 110/512, 150/512}, + } ---return a table containing information about the texture to use for the actor icon ---@param actorObject actor @@ -63,23 +71,27 @@ do return textureTable end - + ---return the path to a texture file and the texture coordinates + ---@return string, number, number, number, number function Details:GetUnknownClassIcon() - return [[Interface\AddOns\Details\images\classes_small]], unpack(unknown_class_coords) + return [[Interface\AddOns\Details\images\classes_small]], unpack(CONST_UNKNOWN_CLASS_COORDS) end - function Details:GetIconTexture(iconType, withAlpha) + ---return a path to a texture file + ---@param iconType "spec"|"class" + ---@param bWithAlpha boolean + ---@return string texturePath + function Details:GetIconTexture(iconType, bWithAlpha) iconType = string.lower(iconType) if (iconType == "spec") then - if (withAlpha) then + if (bWithAlpha) then return [[Interface\AddOns\Details\images\spec_icons_normal_alpha]] else return [[Interface\AddOns\Details\images\spec_icons_normal]] end - - elseif (iconType == "class") then - if (withAlpha) then + else --if is class + if (bWithAlpha) then return [[Interface\AddOns\Details\images\classes_small_alpha]] else return [[Interface\AddOns\Details\images\classes_small]] @@ -87,50 +99,84 @@ do end end - -- try get the class from actor name - function Details:GetClass(name) - local _, class = UnitClass(name) + ---attempt to get the class of an actor by its name, if the actor isn't found, it searches the overall data for the actor + ---@param actorName string + ---@return string className, number left, number right, number top, number bottom, number red, number green, number blue, number alpha + function Details:GetClass(actorName) + local _, class = UnitClass(actorName) - if (not class) then - for index, container in ipairs(Details.tabela_overall) do - local index = container._NameIndexTable[name] - if (index) then - local actor = container._ActorTable[index] - if (actor.classe ~= "UNGROUPPLAYER") then - local left, right, top, bottom = unpack(Details.class_coords[actor.classe] or unknown_class_coords) - local r, g, b = unpack(Details.class_colors[actor.classe]) - return actor.classe, left, right, top, bottom, r or 1, g or 1, b or 1 + if (class) then + local left, right, top, bottom = unpack(Details.class_coords[class]) + local r, g, b = unpack(Details.class_colors[class]) + return class, left, right, top, bottom, r or 1, g or 1, b or 1, 1 + else + local overallCombatObject = Details:GetCombat(DETAILS_SEGMENTID_OVERALL) + for containerId = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + local actorContainer = overallCombatObject:GetContainer(containerId) + local actorObject = actorContainer:GetActor(actorName) + + if (actorObject) then + class = actorObject:Class() + if (class) then + --found the class of the actor + local left, right, top, bottom = unpack(Details.class_coords[class] or CONST_UNKNOWN_CLASS_COORDS) + local r, g, b = unpack(Details.class_colors[class]) + return class, left, right, top, bottom, r or 1, g or 1, b or 1, 1 end end end return "UNKNOW", 0.75, 1, 0.75, 1, 1, 1, 1, 1 - else - local left, right, top, bottom = unpack(Details.class_coords[class]) - local r, g, b = unpack(Details.class_colors[class]) - return class, left, right, top, bottom, r or 1, g or 1, b or 1 end end - local CLASS_ICON_TCOORDS = CLASS_ICON_TCOORDS - local roles = { - DAMAGER = {421/512, 466/512, 381/512, 427/512}, - HEALER = {467/512, 512/512, 381/512, 427/512}, - TANK = {373/512, 420/512, 381/512, 427/512}, - NONE = {0, 50/512, 110/512, 150/512}, - } - function Details:GetRoleIcon (role) + --note: this could return the coords and color as well to match Details:GetClass() + ---attempt to get the spec of an actor by its name, if the actor isn't found, it searches the overall data for the actor + ---@param actorName string + ---@return number|nil + function Details:GetSpecFromActorName(actorName) + local GUID = UnitGUID(actorName) + local spec = Details:GetSpecByGUID(GUID) + + if (spec) then + return spec + end + + local overallCombatObject = Details:GetCombat(DETAILS_SEGMENTID_OVERALL) + for containerId = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + local actorContainer = overallCombatObject:GetContainer(containerId) + local actorObject = actorContainer:GetActor(actorName) + + if (actorObject) then + spec = actorObject:Spec() + if (spec) then + return spec + end + end + end + end + + ---return the path to a texture file and the texture coordinates + ---@param role string + ---@return string texturePath, number left, number right, number top, number bottom + function Details:GetRoleIcon(role) return [[Interface\AddOns\Details\images\icons2]], unpack(roles[role]) end + ---return the path to a texture file and the texture coordinates for the given class + ---@param class string + ---@return string texturePath, number left, number right, number top, number bottom function Details:GetClassIcon(class) if (self.classe) then class = self.classe + elseif (type(class) == "table" and class.classe) then class = class.classe + elseif (type(class) == "string") then class = class + else class = "UNKNOW" end @@ -149,192 +195,293 @@ do end end + ---return the path to a texture file and the texture coordinates for the given spec + ---@param spec number + ---@param useAlpha boolean + ---@return string texturePath, number left, number right, number top, number bottom function Details:GetSpecIcon(spec, useAlpha) - if (spec) then - if (spec == 0) then - return [[Interface\AddOns\Details\images\classes_small]], unpack(Details.class_coords["UNKNOW"]) - end + if (not spec or spec == 0) then + --this returns the icon for "unknown" spec (gotten from the class icon file) + return [[Interface\AddOns\Details\images\classes_small]], unpack(Details.class_coords["UNKNOW"]) + end - if (useAlpha) then - return [[Interface\AddOns\Details\images\spec_icons_normal_alpha]], unpack(Details.class_specs_coords [spec]) - else - return [[Interface\AddOns\Details\images\spec_icons_normal]], unpack(Details.class_specs_coords [spec]) - end + if (useAlpha) then + return [[Interface\AddOns\Details\images\spec_icons_normal_alpha]], unpack(Details.class_specs_coords [spec]) + else + return [[Interface\AddOns\Details\images\spec_icons_normal]], unpack(Details.class_specs_coords[spec]) end end - local default_color = {1, 1, 1, 1} - function Details:GetClassColor (class) + ---return the red, green, blue and alpha values for the given class + ---@param class string + ---@return number red, number green, number blue, number alpha + function Details:GetClassColor(class) if (self.classe) then - return unpack(Details.class_colors [self.classe] or default_color) + return unpack(Details.class_colors[self.classe] or CONST_DEFAULT_COLOR) elseif (type(class) == "table" and class.classe) then - return unpack(Details.class_colors [class.classe] or default_color) + return unpack(Details.class_colors[class.classe] or CONST_DEFAULT_COLOR) elseif (type(class) == "string") then - return unpack(Details.class_colors [class] or default_color) + return unpack(Details.class_colors[class] or CONST_DEFAULT_COLOR) elseif (self.color) then return unpack(self.color) else - return unpack(default_color) + return unpack(CONST_DEFAULT_COLOR) end end - function Details:GetPlayerIcon (playerName, segment) - segment = segment or Details.tabela_vigente + ---get the spec or class texture and coordinates for the given player name and combat object, if the actor isn't found return unknown icon + ---@param playerName string + ---@param combatObject combat + ---@return string texturePath, number left, number right, number top, number bottom + function Details:GetPlayerIcon(playerName, combatObject) + combatObject = combatObject or Details:GetCurrentCombat() - local texture - local L, R, T, B + local texturePath, left, right, top, bottom - local playerObject = segment (1, playerName) + ---@type actor + local playerObject = combatObject:GetActor(DETAILS_ATTRIBUTE_DAMAGE, playerName) if (not playerObject or not playerObject.spec) then - playerObject = segment (2, playerName) + ---@type actor + playerObject = combatObject:GetActor(DETAILS_ATTRIBUTE_HEAL, playerName) end if (playerObject) then local spec = playerObject.spec if (spec) then - texture = [[Interface\AddOns\Details\images\spec_icons_normal]] - L, R, T, B = unpack(Details.class_specs_coords [spec]) - else - texture = [[Interface\AddOns\Details\images\classes_small]] - L, R, T, B = unpack(Details.class_coords [playerObject.classe or "UNKNOW"]) + texturePath = [[Interface\AddOns\Details\images\spec_icons_normal]] + left, right, top, bottom = unpack(Details.class_specs_coords[spec]) + + elseif (playerObject.classe) then + texturePath = [[Interface\AddOns\Details\images\classes_small]] + left, right, top, bottom = unpack(Details.class_coords[playerObject.classe or "UNKNOW"]) end - else - texture = [[Interface\AddOns\Details\images\classes_small]] - L, R, T, B = unpack(Details.class_coords ["UNKNOW"]) end - return texture, L, R, T, B + if (not texturePath) then + texturePath = [[Interface\AddOns\Details\images\classes_small]] + left, right, top, bottom = unpack(Details.class_coords["UNKNOW"]) + end + + return texturePath, left, right, top, bottom end - function Details:GuessClass (t) + ---return specId if it exists in the spec cache + ---@param unitSerial string this is also called GUID + ---@return number|nil + function Details:GetSpecByGUID(unitSerial) + return Details.cached_specs[unitSerial] + end - local Actor, container, tries = t[1], t[2], t[3] - if (not Actor) then + +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + ---comment + ---@param payload table + ---@return any + function Details:GuessClass(payload) + ---@type actor, actorcontainer, number + local actorObject, actorContainer, attempts = payload[1], payload[2], payload[3] + + if (not actorObject) then return false end - if (Actor.spells) then --correcao pros containers misc, precisa pegar os diferentes tipos de containers de l� - for spellid, _ in pairs(Actor.spells._ActorTable) do - local class = Details.ClassSpellList [spellid] - if (class) then - Actor.classe = class - Actor.guessing_class = nil + local spellContainerNames = actorObject:GetSpellContainerNames() + for i = 1, #spellContainerNames do + local spellContainer = actorObject:GetSpellContainer(spellContainerNames[i]) + if (spellContainer) then + for spellId in spellContainer:ListSpells() do + local class = Details.ClassSpellList[spellId] + if (class) then + actorObject.classe = class + actorObject.guessing_class = nil - if (container) then - container.need_refresh = true + if (actorContainer) then + actorContainer.need_refresh = true + end + + if (actorObject.minha_barra and type(actorObject.minha_barra) == "table") then + actorObject.minha_barra.minha_tabela = nil + Details:ScheduleWindowUpdate(2, true) + end + + return class end - - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) - end - - return class end end end - if (not Actor.nome) then - if (not Details.NoActorNameWarning) then - print("==============") - Details:Msg("Unhandled Exception: Actor has no name, ContainerID: ", container.tipo) - Details:Msg("After the current combat, reset data and use /reload.") - Details:Msg("Report this issue to the Author: Actor with no name, container: ", container.tipo) - print("==============") - Details.NoActorNameWarning = true - end - return - end - - local class = Details:GetClass(Actor.nome) + local class = Details:GetClass(actorObject:Name()) if (class and class ~= "UNKNOW") then - Actor.classe = class - Actor.need_refresh = true - Actor.guessing_class = nil + actorObject.classe = class + actorObject.need_refresh = true + actorObject.guessing_class = nil - if (container) then - container.need_refresh = true + if (actorContainer) then + actorContainer.need_refresh = true end - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) + if (actorObject.minha_barra and type(actorObject.minha_barra) == "table") then + actorObject.minha_barra.minha_tabela = nil + Details:ScheduleWindowUpdate(2, true) end return class end - if (tries and tries < 10) then - t[3] = tries + 1 --thanks @Farmbuyer on curseforge + if (attempts and attempts < 10) then + payload[3] = attempts + 1 --thanks @Farmbuyer on curseforge --_detalhes:ScheduleTimer("GuessClass", 2, {Actor, container, tries+1}) - Details:ScheduleTimer("GuessClass", 2, t) --passing the same table instead of creating a new one + Details:ScheduleTimer("GuessClass", 2, payload) --passing the same table instead of creating a new one end return false end --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - function Details:GetSpecByGUID (unitSerial) - return Details.cached_specs [unitSerial] - end - - -- try get the spec from actor name - function Details:GetSpec (name) - - local guid = UnitGUID(name) - if (guid) then - local spec = Details.cached_specs [guid] - if (spec) then - return spec - end + ---comment + ---@param payload table + ---@return any + function Details:GuessSpec(payload) + ---@type actor, actorcontainer, number + local actorObject, actorContainer, attempts = payload[1], payload[2], payload[3] + if (not actorObject) then + return false end - for index, container in ipairs(Details.tabela_overall) do - local index = container._NameIndexTable [name] - if (index) then - local actor = container._ActorTable [index] - return actor and actor.spec - end + local actorSpec + + --attempt the obvious + if (actorObject.spec) then + actorSpec = actorObject.spec end - end + local specSpellList = Details.SpecSpellList - function Details:GetUnitId(unitName) - unitName = unitName or self.nome - if (openRaidLib) then - local unitId = openRaidLib.GetUnitID(unitName) - if (unitId) then - return unitId - end - end - - if (IsInRaid()) then - for i = 1, GetNumGroupMembers() do - local unitId = "raid" .. i - if (GetUnitName(unitId, true) == unitName) then - return unitId + --attempt to get from OpenRaid + if (not actorSpec) then + local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) + if (openRaidLib) then + local unitInfo = openRaidLib.GetUnitInfo(actorObject:Name()) + if (unitInfo and unitInfo.specId and unitInfo.specId ~= 0) then + actorSpec = unitInfo.specId end end + end - elseif (IsInGroup()) then - for i = 1, GetNumGroupMembers() -1 do - local unitId = "party" .. i - if (GetUnitName(unitId, true) == unitName) then - return unitId + --attempt to get from the spec cache + if (not actorSpec) then + actorSpec = Details.cached_specs[actorObject.serial] + end + + --attempt to get from the spells the actor used in the current combat + if (not actorSpec) then + local currentCombatObject = Details:GetCombat(DETAILS_SEGMENTID_CURRENT) + for containerId = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + if (actorSpec) then + break + end + + ---@type actorcontainer + local currentActorContainer = currentCombatObject:GetContainer(containerId) + ---@type actor + local currentActorObject = currentActorContainer:GetActor(actorObject:Name()) + + if (currentActorObject) then + --iterate among all spells the actor used + if (not actorSpec) then + local spellContainerNames = currentActorObject:GetSpellContainerNames() + for i = 1, #spellContainerNames do + local spellContainer = currentActorObject:GetSpellContainer(spellContainerNames[i]) + if (spellContainer) then + for spellId in spellContainer:ListSpells() do + local spec = specSpellList[spellId] + if (spec) then + actorSpec = spec + break + end + end + end + end + end end end - if (UnitName("player") == unitName) then - return "player" + end + + --attempt to get from overall combat object + if (not actorSpec) then + local overallCombatObject = Details:GetCombat(DETAILS_SEGMENTID_OVERALL) + for containerId = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + if (actorSpec) then + break + end + + local overallActorContainer = overallCombatObject:GetContainer(containerId) + local overallActorObject = overallActorContainer:GetActor(actorObject:Name()) + if (overallActorObject) then + if (overallActorObject.spec and overallActorObject.spec ~= 0) then + actorSpec = overallActorObject.spec + break + end + + --iterate among all spells the actor used + if (not actorSpec) then + local spellContainerNames = overallActorObject:GetSpellContainerNames() + for i = 1, #spellContainerNames do + local spellContainer = overallActorObject:GetSpellContainer(spellContainerNames[i]) + if (spellContainer) then + for spellId in spellContainer:ListSpells() do + local spec = specSpellList[spellId] + if (spec) then + actorSpec = spec + break + end + end + end + end + end + end end end + + if (actorSpec) then + Details.cached_specs[actorObject.serial] = actorSpec + + actorObject:SetSpecId(actorSpec) + actorObject.classe = Details.SpecIDToClass[actorSpec] or actorObject.classe + actorObject.guessing_spec = nil + + if (actorContainer) then + actorContainer.need_refresh = true + end + + if (actorObject.minha_barra and type(actorObject.minha_barra) == "table") then + actorObject.minha_barra.minha_tabela = nil + Details:ScheduleWindowUpdate(2, true) + end + + return actorSpec + end + + if (Details.streamer_config.quick_detection) then + if (attempts and attempts < 30) then + payload[3] = attempts + 1 + Details:ScheduleTimer("GuessSpec", 1, payload) --todo: replace schedule from ace3 and use our own + end + else + if (attempts and attempts < 10) then + payload[3] = attempts + 1 + Details:ScheduleTimer("GuessSpec", 3, payload) + end + end + + return false end - function Details:ReGuessSpec (t) + function Details:ReGuessSpec(t) --deprecated local actorObject, container = t[1], t[2] local SpecSpellList = Details.SpecSpellList @@ -435,256 +582,7 @@ do end end end - end end end - - function Details:GuessSpec(t) - local Actor, container, tries = t[1], t[2], t[3] - if (not Actor) then - return false - end - - local SpecSpellList = Details.SpecSpellList - --get from the spec cache - local spec = Details.cached_specs [Actor.serial] - if (spec) then - Actor:SetSpecId(spec) - Actor.classe = Details.SpecIDToClass [spec] or Actor.classe - - Actor.guessing_spec = nil - - if (container) then - container.need_refresh = true - end - - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) - end - - return spec - end - - --get from the spell cast list - if (Details.tabela_vigente) then - local spellCastTable = Details.tabela_vigente:GetSpellCastTable(Actor.nome) - - for spellName, _ in pairs(spellCastTable) do - local _, _, _, _, _, _, spellid = GetSpellInfo(spellName) - local spec = SpecSpellList[spellid] - if (spec) then - Details.cached_specs [Actor.serial] = spec - - Actor:SetSpecId(spec) - Actor.classe = Details.SpecIDToClass [spec] or Actor.classe - - Details:SendEvent("UNIT_SPEC", nil, Actor:GetUnitId(), spec, Actor.serial) - - Actor.guessing_spec = nil - - if (container) then - container.need_refresh = true - end - - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) - end - - return spec - end - end - - if (Actor.spells) then --correcao pros containers misc, precisa pegar os diferentes tipos de containers de l� - for spellid, _ in pairs(Actor.spells._ActorTable) do - local spec = SpecSpellList [spellid] - if (spec) then - Details.cached_specs [Actor.serial] = spec - - Actor:SetSpecId(spec) - Actor.classe = Details.SpecIDToClass [spec] or Actor.classe - Actor.guessing_spec = nil - - Details:SendEvent("UNIT_SPEC", nil, Actor:GetUnitId(), spec, Actor.serial) - - if (container) then - container.need_refresh = true - end - - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) - end - - return spec - end - end - end - else - - if (Actor.spells) then --correcao pros containers misc, precisa pegar os diferentes tipos de containers de l� - for spellid, _ in pairs(Actor.spells._ActorTable) do - local spec = SpecSpellList [spellid] - if (spec) then - Details.cached_specs [Actor.serial] = spec - - Actor:SetSpecId(spec) - Actor.classe = Details.SpecIDToClass [spec] or Actor.classe - Actor.guessing_spec = nil - - Details:SendEvent("UNIT_SPEC", nil, Actor:GetUnitId(), spec, Actor.serial) - - if (container) then - container.need_refresh = true - end - - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) - end - - return spec - end - end - end - end - - if (Actor.classe == "HUNTER") then - local container_misc = Details.tabela_vigente[4] - local index = container_misc._NameIndexTable [Actor.nome] - if (index) then - local misc_actor = container_misc._ActorTable [index] - local buffs = misc_actor.buff_uptime_spells and misc_actor.buff_uptime_spells._ActorTable - if (buffs) then - for spellid, spell in pairs(buffs) do - local spec = SpecSpellList [spellid] - if (spec) then - - Details.cached_specs [Actor.serial] = spec - - Actor:SetSpecId(spec) - Actor.classe = Details.SpecIDToClass [spec] or Actor.classe - Actor.guessing_spec = nil - - Details:SendEvent("UNIT_SPEC", nil, Actor:GetUnitId(), spec, Actor.serial) - - if (container) then - container.need_refresh = true - end - - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) - end - - return spec - end - end - end - end - end - - local spec = Details:GetSpec (Actor.nome) - if (spec) then - - Details.cached_specs [Actor.serial] = spec - - Actor:SetSpecId(spec) - Actor.classe = Details.SpecIDToClass [spec] or Actor.classe - Actor.need_refresh = true - Actor.guessing_spec = nil - - if (container) then - container.need_refresh = true - end - - if (Actor.minha_barra and type(Actor.minha_barra) == "table") then - Actor.minha_barra.minha_tabela = nil - Details:ScheduleWindowUpdate (2, true) - end - - return spec - end - - if (Details.streamer_config.quick_detection) then - if (tries and tries < 30) then - t[3] = tries + 1 - Details:ScheduleTimer("GuessSpec", 1, t) - end - else - if (tries and tries < 10) then - t[3] = tries + 1 - Details:ScheduleTimer("GuessSpec", 3, t) - end - end - - return false - end - -end - - -function Details:AddColorString (player_name, class) - --check if the class colors exists - local classColors = _G.RAID_CLASS_COLORS - if (classColors) then - local color = classColors [class] - --check if the player name is valid - if (type(player_name) == "string" and color) then - player_name = "|c" .. color.colorStr .. player_name .. "|r" - return player_name - end - end - - --if failed, return the player name without modifications - return player_name -end - -function Details:AddRoleIcon (player_name, role, size) - --check if is a valid role - local roleIcon = Details.role_texcoord [role] - if (type(player_name) == "string" and roleIcon and role ~= "NONE") then - --add the role icon - size = size or 14 - player_name = "|TInterface\\LFGFRAME\\UI-LFG-ICON-ROLES:" .. size .. ":" .. size .. ":0:0:256:256:" .. roleIcon .. "|t " .. player_name - return player_name - end - - return player_name -end - -function Details:AddClassOrSpecIcon (playerName, class, spec, iconSize, useAlphaIcons) - - local size = iconSize or 16 - - if (spec) then - local specString = "" - local L, R, T, B = unpack(Details.class_specs_coords [spec]) - if (L) then - if (useAlphaIcons) then - specString = "|TInterface\\AddOns\\Details\\images\\spec_icons_normal_alpha:" .. size .. ":" .. size .. ":0:0:512:512:" .. (L * 512) .. ":" .. (R * 512) .. ":" .. (T * 512) .. ":" .. (B * 512) .. "|t" - else - specString = "|TInterface\\AddOns\\Details\\images\\spec_icons_normal:" .. size .. ":" .. size .. ":0:0:512:512:" .. (L * 512) .. ":" .. (R * 512) .. ":" .. (T * 512) .. ":" .. (B * 512) .. "|t" - end - return specString .. " " .. playerName - end - end - - if (class) then - local classString = "" - local L, R, T, B = unpack(Details.class_coords [class]) - if (L) then - local imageSize = 128 - if (useAlphaIcons) then - classString = "|TInterface\\AddOns\\Details\\images\\classes_small_alpha:" .. size .. ":" .. size .. ":0:0:" .. imageSize .. ":" .. imageSize .. ":" .. (L * imageSize) .. ":" .. (R * imageSize) .. ":" .. (T * imageSize) .. ":" .. (B * imageSize) .. "|t" - else - classString = "|TInterface\\AddOns\\Details\\images\\classes_small:" .. size .. ":" .. size .. ":0:0:" .. imageSize .. ":" .. imageSize .. ":" .. (L * imageSize) .. ":" .. (R * imageSize) .. ":" .. (T * imageSize) .. ":" .. (B * imageSize) .. "|t" - end - return classString .. " " .. playerName - end - end - - return playerName -end +end \ No newline at end of file diff --git a/startup.lua b/startup.lua index 613339a8..ba794749 100644 --- a/startup.lua +++ b/startup.lua @@ -27,6 +27,11 @@ function Details:StartMeUp() return Details.AddOnStartTime or GetTime() end + C_Timer.After(3, function() + --load custom spells on login + Details:FillUserCustomSpells() + end) + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --row single click, this determines what happen when the user click on a bar @@ -391,11 +396,6 @@ function Details:StartMeUp() Details:AddDefaultCustomDisplays() end - C_Timer.After(1, function() - --load custom spells on every login - Details:FillUserCustomSpells() - end) - local lowerInstanceId = Details:GetLowerInstanceNumber() if (lowerInstanceId) then local instance = Details:GetInstance(lowerInstanceId)