Version 2.1.0-Beta #9

Open
Torsten wants to merge 8 commits from dev into main
4 changed files with 195 additions and 12 deletions
Showing only changes of commit 258cadeba5 - Show all commits

View File

@@ -558,6 +558,30 @@ function HMGT:SendOutdatedVersionWhisper(playerName, remoteVersion)
return true return true
end end
function HMGT:RegisterLibSpecializationBridge()
if self._libSpecializationBridgeRegistered then
return true
end
if not LibStub then
return false
end
local LibSpec = LibStub("LibSpecialization", true)
if not LibSpec or type(LibSpec.RegisterGroup) ~= "function" then
return false
end
LibSpec.RegisterGroup(self, function(specId, role, position, playerName, talentString)
if not playerName or not specId then
return
end
local classToken = HMGT:GetClassTokenForSpecId(specId)
HMGT:ApplyExternalSpecInfo("LibSpecialization", playerName, classToken, specId, talentString)
end)
self._libSpecializationBridgeRegistered = true
return true
end
function HMGT:SendReliableAck(target, messageId) function HMGT:SendReliableAck(target, messageId)
if not target or target == "" or not messageId or messageId == "" then if not target or target == "" or not messageId or messageId == "" then
return return
@@ -1814,6 +1838,7 @@ function HMGT:OnEnable()
self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED","OnPlayerTalentUpdate") self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED","OnPlayerTalentUpdate")
-- Gruppen-Sichtbarkeit neu auswerten wenn sich die Zusammensetzung ändert -- Gruppen-Sichtbarkeit neu auswerten wenn sich die Zusammensetzung ändert
self:RegisterEvent("RAID_ROSTER_UPDATE", "OnGroupRosterUpdate") self:RegisterEvent("RAID_ROSTER_UPDATE", "OnGroupRosterUpdate")
self:RegisterLibSpecializationBridge()
if not self.cleanupTicker then if not self.cleanupTicker then
self.cleanupTicker = C_Timer.NewTicker(15, function() self:CleanupStaleCooldowns() end) self.cleanupTicker = C_Timer.NewTicker(15, function() self:CleanupStaleCooldowns() end)
end end
@@ -3074,17 +3099,54 @@ function HMGT:RegisterExternalAddonSource(sourceName)
return true return true
end end
function HMGT:GetCanonicalExternalSpellEntry(spellId)
local sid = tonumber(spellId)
if not sid or sid <= 0 or not HMGT_SpellData then
return nil, sid
end
local spellEntry = HMGT_SpellData.InterruptLookup and HMGT_SpellData.InterruptLookup[sid]
or HMGT_SpellData.CooldownLookup and HMGT_SpellData.CooldownLookup[sid]
if not spellEntry then
return nil, sid
end
return spellEntry, tonumber(spellEntry.spellId) or sid
end
function HMGT:InferClassFromSpellEntry(spellEntry)
if type(spellEntry) ~= "table" or type(spellEntry.classes) ~= "table" then
return nil
end
local foundClass
for key, value in pairs(spellEntry.classes) do
local classToken = type(value) == "string" and value or key
if foundClass and foundClass ~= classToken then
return nil
end
foundClass = classToken
end
return foundClass
end
function HMGT:ApplyExternalKnownSpell(sourceName, playerName, spellId, class, cooldown) function HMGT:ApplyExternalKnownSpell(sourceName, playerName, spellId, class, cooldown)
local source = tostring(sourceName or "External") local source = tostring(sourceName or "External")
local normalizedName = self:NormalizePlayerName(playerName) local normalizedName = self:NormalizePlayerName(playerName)
local sid = tonumber(spellId) local sid = tonumber(spellId)
if not normalizedName or normalizedName == "" or not sid or sid <= 0 then if not normalizedName or normalizedName == "" or not sid or sid <= 0 then
return false return false, "invalid_args"
end end
if not self:IsPlayerInCurrentGroup(normalizedName) then if not self:IsPlayerInCurrentGroup(normalizedName) then
return false return false, "not_in_group"
end end
local spellEntry, canonicalSid = self:GetCanonicalExternalSpellEntry(sid)
if not spellEntry or not canonicalSid or canonicalSid <= 0 then
return false, "unknown_spell"
end
sid = canonicalSid
self:RegisterExternalAddonSource(source) self:RegisterExternalAddonSource(source)
local previous = self.playerData[normalizedName] or {} local previous = self.playerData[normalizedName] or {}
local knownSpells = previous.knownSpells local knownSpells = previous.knownSpells
@@ -3093,8 +3155,10 @@ function HMGT:ApplyExternalKnownSpell(sourceName, playerName, spellId, class, co
end end
knownSpells[sid] = true knownSpells[sid] = true
local classToken = class or previous.class or self:InferClassFromSpellEntry(spellEntry)
self.playerData[normalizedName] = { self.playerData[normalizedName] = {
class = class or previous.class, class = classToken,
specIndex = previous.specIndex, specIndex = previous.specIndex,
talentHash = previous.talentHash, talentHash = previous.talentHash,
talents = previous.talents or {}, talents = previous.talents or {},
@@ -3102,14 +3166,93 @@ function HMGT:ApplyExternalKnownSpell(sourceName, playerName, spellId, class, co
externalSource = source, externalSource = source,
} }
if tonumber(cooldown) and tonumber(cooldown) > 0 and HMGT_SpellData then if tonumber(cooldown) and tonumber(cooldown) > 0 then
local spellEntry = HMGT_SpellData.InterruptLookup and HMGT_SpellData.InterruptLookup[sid] spellEntry._hmgtExternalBaseCd = tonumber(cooldown)
or HMGT_SpellData.CooldownLookup and HMGT_SpellData.CooldownLookup[sid] end
if spellEntry then
spellEntry._hmgtExternalBaseCd = tonumber(cooldown) self:TriggerTrackerUpdate("trackers")
return true
end
function HMGT:GetClassTokenForSpecId(specId)
local sid = tonumber(specId)
if not sid or sid <= 0 then
return nil
end
if type(GetSpecializationInfoByID) == "function" then
local returns = { pcall(GetSpecializationInfoByID, sid) }
local ok = returns[1]
local classToken = returns[7]
if ok and type(classToken) == "string" and classToken ~= "" then
return classToken
end end
end end
if type(GetSpecializationInfoForClassID) ~= "function" then
return nil
end
for classID = 1, 20 do
local _, token = GetClassInfo(classID)
if token then
local count = 4
if type(GetNumSpecializationsForClassID) == "function" then
count = tonumber(GetNumSpecializationsForClassID(classID)) or 4
end
for index = 1, math.max(1, count) do
local foundSpecId = GetSpecializationInfoForClassID(classID, index)
if tonumber(foundSpecId) == sid then
return token
end
end
end
end
return nil
end
function HMGT:ApplyExternalSpecInfo(sourceName, playerName, class, specId, talentHash)
local source = tostring(sourceName or "External")
local normalizedName = self:NormalizePlayerName(playerName)
local spec = tonumber(specId)
local classToken = class and tostring(class) or self:GetClassTokenForSpecId(spec)
if not normalizedName or normalizedName == "" or not classToken or classToken == "" or not spec or spec <= 0 then
return false, "invalid_args"
end
if not self:IsPlayerInCurrentGroup(normalizedName) then
return false, "not_in_group"
end
self:RegisterExternalAddonSource(source)
local previous = self.playerData[normalizedName] or {}
local knownSpells = previous.knownSpells
if type(knownSpells) ~= "table" then
knownSpells = {}
end
if HMGT_SpellData and type(HMGT_SpellData.GetSpellsForSpec) == "function" then
for _, datasetName in ipairs({ "Interrupts", "RaidCooldowns", "GroupCooldowns" }) do
local dataset = HMGT_SpellData[datasetName]
for _, spellEntry in ipairs(HMGT_SpellData.GetSpellsForSpec(classToken, spec, dataset)) do
local sid = tonumber(spellEntry and spellEntry.spellId)
if sid and sid > 0 then
knownSpells[sid] = true
end
end
end
end
self.playerData[normalizedName] = {
class = classToken,
specIndex = spec,
talentHash = talentHash or previous.talentHash,
talents = self:ParseTalentHash(talentHash or previous.talentHash),
knownSpells = knownSpells,
externalSource = source,
}
self:PruneAvailabilityStates(normalizedName, knownSpells)
self:TriggerTrackerUpdate("trackers") self:TriggerTrackerUpdate("trackers")
return true return true
end end
@@ -3120,12 +3263,18 @@ function HMGT:ApplyExternalCooldown(sourceName, playerName, spellId, cooldown)
local sid = tonumber(spellId) local sid = tonumber(spellId)
local cd = tonumber(cooldown) local cd = tonumber(cooldown)
if not normalizedName or normalizedName == "" or not sid or sid <= 0 or not cd or cd <= 0 then if not normalizedName or normalizedName == "" or not sid or sid <= 0 or not cd or cd <= 0 then
return false return false, "invalid_args"
end end
if not self:IsPlayerInCurrentGroup(normalizedName) then if not self:IsPlayerInCurrentGroup(normalizedName) then
return false return false, "not_in_group"
end end
local spellEntry, canonicalSid = self:GetCanonicalExternalSpellEntry(sid)
if not spellEntry or not canonicalSid or canonicalSid <= 0 then
return false, "unknown_spell"
end
sid = canonicalSid
self:RegisterExternalAddonSource(source) self:RegisterExternalAddonSource(source)
self:ApplyExternalKnownSpell(source, normalizedName, sid, nil, cd) self:ApplyExternalKnownSpell(source, normalizedName, sid, nil, cd)
self:HandleRemoteSpellCast(normalizedName, sid, GetServerTime(), nil, nil, nil, cd) self:HandleRemoteSpellCast(normalizedName, sid, GetServerTime(), nil, nil, nil, cd)
@@ -3182,6 +3331,7 @@ function HMGT:ApplyRemoteSpellState(playerName, spellId, kind, revision, a, b, c
if not spellEntry then if not spellEntry then
return false return false
end end
sid = tonumber(spellEntry.spellId) or sid
local now = GetTime() local now = GetTime()
local stateKind = tostring(kind or "") local stateKind = tostring(kind or "")
@@ -3639,6 +3789,7 @@ function HMGT:HandleOwnSpellCast(spellId)
local spellEntry = HMGT_SpellData.InterruptLookup[spellId] local spellEntry = HMGT_SpellData.InterruptLookup[spellId]
or HMGT_SpellData.CooldownLookup[spellId] or HMGT_SpellData.CooldownLookup[spellId]
spellId = tonumber(spellEntry and spellEntry.spellId) or spellId
local name = self:NormalizePlayerName(UnitName("player")) local name = self:NormalizePlayerName(UnitName("player"))
local pData = self.playerData[name] local pData = self.playerData[name]
local talents = pData and pData.talents or {} local talents = pData and pData.talents or {}
@@ -3830,6 +3981,7 @@ function HMGT:RefreshOwnCooldownStateFromGame(spellId)
if not spellEntry or self:IsAvailabilitySpell(spellEntry) then if not spellEntry or self:IsAvailabilitySpell(spellEntry) then
return false return false
end end
sid = tonumber(spellEntry.spellId) or sid
local existing = self.activeCDs[ownName] and self.activeCDs[ownName][sid] local existing = self.activeCDs[ownName] and self.activeCDs[ownName][sid]
local before = BuildCooldownStateFingerprint(existing) local before = BuildCooldownStateFingerprint(existing)
@@ -4101,6 +4253,7 @@ function HMGT:DidOwnInterruptSucceed(triggerSpellId, talents)
local spellEntry = HMGT_SpellData and HMGT_SpellData.InterruptLookup and HMGT_SpellData.InterruptLookup[sid] local spellEntry = HMGT_SpellData and HMGT_SpellData.InterruptLookup and HMGT_SpellData.InterruptLookup[sid]
if not spellEntry then return false end if not spellEntry then return false end
sid = tonumber(spellEntry.spellId) or sid
local _, observedDuration = GetSpellCooldownInfo(sid) local _, observedDuration = GetSpellCooldownInfo(sid)
observedDuration = tonumber(observedDuration) or 0 observedDuration = tonumber(observedDuration) or 0
@@ -4407,6 +4560,7 @@ function HMGT:HandleRemoteSpellCast(playerName, spellId, castTimestamp, curCharg
local spellEntry = HMGT_SpellData.InterruptLookup[spellId] local spellEntry = HMGT_SpellData.InterruptLookup[spellId]
or HMGT_SpellData.CooldownLookup[spellId] or HMGT_SpellData.CooldownLookup[spellId]
if not spellEntry then return end if not spellEntry then return end
spellId = tonumber(spellEntry.spellId) or spellId
if self:IsAvailabilitySpell(spellEntry) then return end if self:IsAvailabilitySpell(spellEntry) then return end
local pData = self.playerData[playerName] local pData = self.playerData[playerName]
@@ -5016,6 +5170,14 @@ function HMGT:SlashCommand(input)
else else
self:Print(L["VERSION_WINDOW_DEVTOOLS_ONLY"] or "HMGT: /hmgt version is only available while developer tools are enabled.") self:Print(L["VERSION_WINDOW_DEVTOOLS_ONLY"] or "HMGT: /hmgt version is only available while developer tools are enabled.")
end end
elseif input == "bridge" then
if _G.HMGT_Bridge and _G.HMGT_Bridge.GetStatusLines then
for _, line in ipairs(_G.HMGT_Bridge:GetStatusLines()) do
self:Print(line)
end
else
self:Print("HMGT Bridge is not loaded.")
end
elseif input == "debug" then elseif input == "debug" then
if self.ToggleDevToolsWindow then if self.ToggleDevToolsWindow then
self:ToggleDevToolsWindow() self:ToggleDevToolsWindow()

View File

@@ -1,4 +1,4 @@
## Interface: 120000,120001 ## Interface: 120000,120001,120005
## IconTexture: Interface\Addons\HailMaryGuildTools\Media\HailMaryIcon.png ## IconTexture: Interface\Addons\HailMaryGuildTools\Media\HailMaryIcon.png
## Author: Torsten Brendgen ## Author: Torsten Brendgen
## Title: Hail Mary Guild Tools ## Title: Hail Mary Guild Tools

View File

@@ -97,14 +97,23 @@ HMGT_SpellData.Interrupts = {
-- WARLOCK -- WARLOCK
Spell(19647, "Spell Lock", { Spell(19647, "Spell Lock", {
classes = {"WARLOCK"}, classes = {"WARLOCK"},
specs = {2}, specs = {1, 3},
category = "interrupt", category = "interrupt",
state = { kind = "cooldown", cooldown = 24 }, state = { kind = "cooldown", cooldown = 24 },
}), }),
Spell(119914, "Axe Toss", {
classes = {"WARLOCK"},
specs = {2},
category = "interrupt",
aliases = { 89766 },
petSpellId = 89766,
state = { kind = "cooldown", cooldown = 30 },
}),
Spell(132409, "Spell Lock (Grimoire)", { Spell(132409, "Spell Lock (Grimoire)", {
classes = {"WARLOCK"}, classes = {"WARLOCK"},
specs = {1, 3}, specs = {1, 3},
category = "interrupt", category = "interrupt",
aliases = { 1276467 },
state = { kind = "cooldown", cooldown = 24 }, state = { kind = "cooldown", cooldown = 24 },
}), }),

View File

@@ -1077,6 +1077,18 @@ function HMGT_SpellData.RebuildLookups()
for _, entry in ipairs(HMGT_SpellData.Interrupts or {}) do for _, entry in ipairs(HMGT_SpellData.Interrupts or {}) do
entry._hmgtDataset = "Interrupts" entry._hmgtDataset = "Interrupts"
HMGT_SpellData.InterruptLookup[entry.spellId] = entry HMGT_SpellData.InterruptLookup[entry.spellId] = entry
if type(entry.aliases) == "table" then
for _, aliasId in ipairs(entry.aliases) do
local sid = tonumber(aliasId)
if sid and sid > 0 then
HMGT_SpellData.InterruptLookup[sid] = entry
end
end
end
local petSpellId = tonumber(entry.petSpellId)
if petSpellId and petSpellId > 0 then
HMGT_SpellData.InterruptLookup[petSpellId] = entry
end
end end
HMGT_SpellData.CooldownLookup = {} HMGT_SpellData.CooldownLookup = {}