Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions WowAddon/DecktationContext/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Decktation Context Addon - Changelog

## Version 1.1.1 (2026-09-21)

### Classic & WoW Forever Compatibility Update

**Fixed:**
- Fixed Lua error calling nil `GetSpecialization()` on Classic Era and WoW Forever clients
- Added talent tree fallback to determine active spec based on spent talent points in Classic
- Registered `PLAYER_TALENT_UPDATE` and `CHARACTER_POINTS_CHANGED` events
- Fixed duplicate `EventFrame:SetScript("OnEvent")` call overwriting main event handlers
- Added fallback to Classic zone APIs (`GetRealZoneText`, `GetZoneText`, `GetSubZoneText`) when `C_Map` is unavailable or returns empty (e.g. on WoW Forever beta maps)

**Added:**
- Added interface numbers for Classic Era and WoW Forever to TOC

## Version 1.1.0 (2026-02-07)

### Midnight Compatibility Update
Expand Down
89 changes: 60 additions & 29 deletions WowAddon/DecktationContext/DecktationContext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,64 @@ local function Initialize()
SaveContext()
end

-- Get zone information using modern C_Map API (Midnight-compatible)
-- Get zone information using modern C_Map API with fallback to Classic APIs
local function GetZoneInfo()
local mapID = C_Map.GetBestMapForUnit("player")
if not mapID then
return "", ""
local zone = ""
local subzone = ""

-- Try modern C_Map API first (Retail / Midnight / TWW)
if C_Map and C_Map.GetBestMapForUnit and C_Map.GetMapInfo then
local mapID = C_Map.GetBestMapForUnit("player")
if mapID then
local mapInfo = C_Map.GetMapInfo(mapID)
if mapInfo and mapInfo.name and mapInfo.name ~= "" then
zone = mapInfo.name
end
end
end

local mapInfo = C_Map.GetMapInfo(mapID)
local zone = mapInfo and mapInfo.name or ""
-- Fallback to Classic / legacy zone APIs if C_Map returned nil or empty
if not zone or zone == "" then
if GetRealZoneText then
zone = GetRealZoneText() or ""
end
if (not zone or zone == "") and GetZoneText then
zone = GetZoneText() or ""
end
end

-- Get subzone from minimap text (still works in Midnight)
local subzone = GetMinimapZoneText() or ""
-- Get subzone from minimap or subzone text
if GetMinimapZoneText then
subzone = GetMinimapZoneText() or ""
end
if (not subzone or subzone == "") and GetSubZoneText then
subzone = GetSubZoneText() or ""
end

return zone, subzone
return zone or "", subzone or ""
end

-- Get specialization (Retail) or talent tree with most points (Classic)
local function GetPlayerSpec()
if GetSpecialization then
local specIndex = GetSpecialization()
if specIndex then
local _, specName = GetSpecializationInfo(specIndex)
return specName or ""
end
elseif GetNumTalentTabs and GetTalentTabInfo then
local maxPoints = 0
local activeSpec = ""
for tabIndex = 1, GetNumTalentTabs() do
local name, _, pointsSpent = GetTalentTabInfo(tabIndex)
if pointsSpent and pointsSpent > maxPoints then
maxPoints = pointsSpent
activeSpec = name or ""
end
end
return activeSpec
end
return ""
end

-- Update current context
Expand Down Expand Up @@ -145,13 +189,7 @@ function UpdateContext()
Context.class = classToken or ""

-- Get specialization
local specIndex = GetSpecialization()
if specIndex then
local _, specName = GetSpecializationInfo(specIndex)
Context.spec = specName or ""
else
Context.spec = ""
end
Context.spec = GetPlayerSpec()

Context.lastUpdate = time()
end)
Expand Down Expand Up @@ -300,6 +338,9 @@ EventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
EventFrame:RegisterEvent("ENCOUNTER_START")
EventFrame:RegisterEvent("ENCOUNTER_END")
EventFrame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
EventFrame:RegisterEvent("PLAYER_TALENT_UPDATE")
EventFrame:RegisterEvent("CHARACTER_POINTS_CHANGED")
EventFrame:RegisterEvent("PLAYER_LOGOUT")

EventFrame:SetScript("OnEvent", function(self, event, ...)
if event == "PLAYER_LOGIN" then
Expand All @@ -323,20 +364,10 @@ EventFrame:SetScript("OnEvent", function(self, event, ...)
elseif event == "ENCOUNTER_END" then
Context.boss = ""
SaveContext()
elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
local specIndex = GetSpecialization()
if specIndex then
local _, specName = GetSpecializationInfo(specIndex)
Context.spec = specName or ""
end
elseif event == "PLAYER_SPECIALIZATION_CHANGED" or event == "PLAYER_TALENT_UPDATE" or event == "CHARACTER_POINTS_CHANGED" then
Context.spec = GetPlayerSpec()
SaveContext()
end
end)

-- Force save on logout
EventFrame:RegisterEvent("PLAYER_LOGOUT")
EventFrame:SetScript("OnEvent", function(self, event)
if event == "PLAYER_LOGOUT" then
elseif event == "PLAYER_LOGOUT" then
SaveContext()
end
end)
4 changes: 2 additions & 2 deletions WowAddon/DecktationContext/DecktationContext.toc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Interface: 120000
## Interface: 120000, 11506, 16001, 160000
## Title: Decktation Context
## Notes: Exports WoW context for Decktation voice-to-text plugin
## Author: Decktation
## Version: 1.1.0
## Version: 1.1.1
## IconTexture: Interface\Icons\Ability_Warrior_CommandingShout
## SavedVariables: DecktationContextDB, DecktationErrorLog
## X-Category: Communication
Expand Down