diff --git a/CHANGELOG.md b/CHANGELOG.md index 1621aa6..c0a88ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,14 @@ # Changelog -## v1.5.8 (2026-04-07) +## v1.5.9 (2026-04-08) ### Bug Fixes -- **[Fix — QuestLink Crash]** Resolved a critical LUA error in `Link.lua`: `attempt to concatenate local 'coloredQuestName' (a nil value)`. This was caused by the `ChatFilter` misidentifying non-quest bracketed patterns (like Keystone links `[Name (ID)]`) as quests. Added a defensive nil guard in `GetQuestHyperLink` and hardened the `ChatFilter` to verify quest names exist before attempting string replacement. +- **[Fix — QuestieQuest Crash]** Resolved a critical runtime crash occurring after killing certain NPCs (specifically Water Revenant 30877 in Wintergrasp). + - **Harden Error Handling**: Replaced the fragile `print(debugstack())` in `ERR_FUNCTION` with a robust `Questie:Error` handler to prevent secondary crashes from masking real errors. + - **Fix NPC Mapping**: Resolved a variable shadowing bug and fixed the mapping logic in `QuestieQuestPrivates:killcredit` to ensure NPC objective data is correctly populated during combat updates. + +## v1.5.8 (2026-04-07) ## Questie-X - Expanded Font Selection diff --git a/Modules/Quest/QuestieQuest.lua b/Modules/Quest/QuestieQuest.lua index 1304789..841f669 100644 --- a/Modules/Quest/QuestieQuest.lua +++ b/Modules/Quest/QuestieQuest.lua @@ -62,8 +62,13 @@ local NewThread = ThreadLib.ThreadSimple local NOP_FUNCTION = function() end local ERR_FUNCTION = function(err) - print(err) - print(debugstack()) + Questie:Error("[QuestieQuest] " .. tostring(err)) + if debugstack then + local stack = debugstack() + if stack and type(stack) == "string" then + Questie:Debug(Questie.DEBUG_CRITICAL, "Stack Trace:\n" .. stack:sub(1, 1000)) + end + end end -- forward declaration diff --git a/Modules/Quest/QuestieQuestPrivates.lua b/Modules/Quest/QuestieQuestPrivates.lua index 06e24ba..1312a27 100644 --- a/Modules/Quest/QuestieQuestPrivates.lua +++ b/Modules/Quest/QuestieQuestPrivates.lua @@ -73,7 +73,7 @@ killcredit = function(npcId, objective, objectiveData) local killCreditNpcId = objectiveData.IdList[npcIdIndex] if killCreditNpcId and killCreditNpcId > 0 then local monsterResult = monster(killCreditNpcId, objective) - if monsterResult then + if monsterResult and monsterResult[killCreditNpcId] then ret[killCreditNpcId] = monsterResult[killCreditNpcId] foundValid = true end @@ -96,7 +96,7 @@ killcredit = function(npcId, objective, objectiveData) for searchId, npcRecord in pairs(npcData) do if npcRecord and npcRecord[1] and string.lower(npcRecord[1]) == string.lower(targetName) then local monsterResult = monster(searchId, objective) - if monsterResult then + if monsterResult and monsterResult[searchId] then ret[searchId] = monsterResult[searchId] foundValid = true Questie:Debug(Questie.DEBUG_DEVELOP, "[killcredit] Found NPC by name fallback:", searchId, targetName) @@ -137,7 +137,7 @@ monster = function(npcId, objective) local enableWaypoints = enableSpawns and 2 ~= rank -- a rare mob spawn. todo: option for this ---@type SpawnListNPC - local monster = { + local monsterData = { Id = npcId, Name = name, Spawns = enableSpawns and spawns or {}, @@ -150,7 +150,7 @@ monster = function(npcId, objective) } return { - [npcId] = monster + [npcId] = monsterData } end @@ -231,16 +231,16 @@ item = function(itemId, objective) if (not itemId) then Questie:Error( "Corrupted objective data handed to objectiveSpawnListCallTable['item']:", - "'" .. objective.Description .. "' -", + "'" .. (objective.Description or "Unknown") .. "' -", "Please report this error on Discord or GitHub." ) return nil end local ret = {} - local item = QuestieDB:GetItem(itemId) - if item and item.Sources and (not item.Hidden) then - for _, source in pairs(item.Sources) do + local itemData = QuestieDB:GetItem(itemId) + if itemData and itemData.Sources and (not itemData.Hidden) then + for _, source in pairs(itemData.Sources) do if _QuestieQuest.objectiveSpawnListCallTable[source.Type] and source.Type ~= "item" then -- anti-recursive-loop check, should never be possible but would be bad if it was local sourceList = _QuestieQuest.objectiveSpawnListCallTable[source.Type](source.Id, objective) if not sourceList then @@ -261,7 +261,7 @@ item = function(itemId, objective) Id = id, Name = sourceData.Name, Hostile = true, - ItemId = item.Id, + ItemId = itemData.Id, TooltipKey = sourceData.TooltipKey, Spawns = {}, Waypoints = {}, @@ -312,7 +312,7 @@ spell = function(spellId, objective, objectiveData) if (not spellId) then Questie:Error( "Corrupted objective data handed to objectiveSpawnListCallTable['spell']:", - "'" .. objective.Description .. "' -", + "'" .. (objective.Description or "Unknown") .. "' -", "Please report this error on Discord or GitHub." ) return nil