From c1c1741b6e9cf0c93c81fcb0d8c5dc4946bd861b Mon Sep 17 00:00:00 2001 From: Relationship <139162359+Relationship-OctoWoW@users.noreply.github.com> Date: Sun, 12 Jul 2026 12:30:17 +0100 Subject: [PATCH] Add files via upload --- Core.lua | 117 ++++++++++++++++++++++++++++++++-------- RelationshipsAttune.toc | 2 +- UI.lua | 6 +++ 3 files changed, 101 insertions(+), 24 deletions(-) diff --git a/Core.lua b/Core.lua index f56af78..5b03e40 100644 --- a/Core.lua +++ b/Core.lua @@ -67,6 +67,7 @@ function RA:InitDB() if not RelationshipsAttuneCharDB.quests then RelationshipsAttuneCharDB.quests = {} end if not RelationshipsAttuneCharDB.items then RelationshipsAttuneCharDB.items = {} end if not RelationshipsAttuneCharDB.completedAttunements then RelationshipsAttuneCharDB.completedAttunements = {} end + if not RelationshipsAttuneCharDB.announced then RelationshipsAttuneCharDB.announced = {} end if not RelationshipsAttuneCharDB.progress then RelationshipsAttuneCharDB.progress = {} end if not RelationshipsAttuneCharDB.expanded then RelationshipsAttuneCharDB.expanded = {} end end @@ -80,16 +81,34 @@ end -- --------------------------------------------------------------- function RA:ScanQuestLog() if not GetNumQuestLogEntries then return end + -- Rebuild transient quest states from the live log so that abandoning a + -- quest reverts its step colour. "turnedin" is authoritative and preserved. + local kept = {} + for qid, st in pairs(RelationshipsAttuneCharDB.quests) do + if st == "turnedin" then kept[qid] = "turnedin" end + end + RelationshipsAttuneCharDB.quests = kept + + RA:BuildNameIndex() + local qNameMap = RA._questNameToId or {} + local numEntries = GetNumQuestLogEntries() for i = 1, numEntries do local ok, title, level, tag, isHeader, _, isComplete, _, questId = pcall(GetQuestLogTitle, i) - if ok and (not isHeader) and questId then - if isComplete and isComplete == 1 then - RelationshipsAttuneCharDB.quests[questId] = "complete" - else - if not RelationshipsAttuneCharDB.quests[questId] then - RelationshipsAttuneCharDB.quests[questId] = "inlog" + if ok and (not isHeader) then + -- Prefer the Turtle/Octo backported questId; fall back to matching + -- the quest title against our data so stock 1.12 (no questId return) + -- and any titles the client failed to tag still get credited. + local qid = questId + if (not qid) and title then + qid = qNameMap[string.lower(title)] + end + if qid and RelationshipsAttuneCharDB.quests[qid] ~= "turnedin" then + if isComplete and isComplete == 1 then + RelationshipsAttuneCharDB.quests[qid] = "complete" + else + RelationshipsAttuneCharDB.quests[qid] = "inlog" end end end @@ -147,22 +166,27 @@ end -- for them (a known 1.12 / Turtle / Octo quirk for keyring slots). RA._nameToId = nil function RA:BuildNameIndex() - if RA._nameToId then return RA._nameToId end - local map = {} + if RA._nameToId and RA._questNameToId then return RA._nameToId end + local map, qmap = {}, {} if RelationshipsAttune_Data then for i = 1, table.getn(RelationshipsAttune_Data) do local att = RelationshipsAttune_Data[i] if att and att.steps then for j = 1, table.getn(att.steps) do local s = att.steps[j] - if s and s.type == "item" and s.name and s.id then - map[string.lower(s.name)] = s.id + if s and s.name and s.id then + if s.type == "item" then + map[string.lower(s.name)] = s.id + elseif s.type == "quest" then + qmap[string.lower(s.name)] = s.id + end end end end end end RA._nameToId = map + RA._questNameToId = qmap return map end @@ -298,36 +322,51 @@ end -- Compute attunement progress -- --------------------------------------------------------------- function RA:EvaluateStep(step) + -- Returns two values: done (boolean), inProgress (boolean). + -- inProgress = the player is actively working on this step but has not + -- yet finished it (e.g. quest accepted but not complete). if step.type == "level" then - return (UnitLevel("player") or 0) >= (step.level or 0) + return (UnitLevel("player") or 0) >= (step.level or 0), false elseif step.type == "quest" then local st = RelationshipsAttuneCharDB.quests[step.id] - return st == "complete" or st == "turnedin" + if st == "complete" or st == "turnedin" then + return true, false + elseif st == "inlog" then + return false, true + end + return false, false elseif step.type == "item" then - return RelationshipsAttuneCharDB.items[step.id] == true + return RelationshipsAttuneCharDB.items[step.id] == true, false elseif step.type == "rep" then local need = DATA_STANDING_MAP[step.standing] or step.standing or 5 local have = self:GetReputationStanding(step.faction) - return have >= need + if have >= need then return true, false end + -- Any positive rep with the faction below the required standing counts + -- as in-progress so the player sees they are working on it. + if have and have >= 4 then return false, true end + return false, false end - return false + return false, false end function RA:EvaluateAttunement(att) if att.faction and att.faction ~= "Both" and att.faction ~= RA.playerFaction then return { applicable = false, done = false, steps = {}, doneCount = 0, total = 0 } end - local steps, doneCount, total = {}, 0, 0 + local steps, stepsInProgress, doneCount, total = {}, {}, 0, 0 local numSteps = table.getn(att.steps) for i = 1, numSteps do local step = att.steps[i] if self:StepApplies(step) then - local ok = self:EvaluateStep(step) and true or false + local doneVal, ipVal = self:EvaluateStep(step) + local ok = doneVal and true or false steps[i] = ok + stepsInProgress[i] = (not ok) and (ipVal and true or false) or false total = total + 1 if ok then doneCount = doneCount + 1 end else steps[i] = nil + stepsInProgress[i] = nil end end -- Short-circuit: if the "final" step is complete, treat the whole @@ -372,18 +411,50 @@ function RA:EvaluateAttunement(att) RelationshipsAttuneCharDB.completedAttunements[att.id] = true end return { - applicable = true, - done = (total > 0 and doneCount == total), - steps = steps, - doneCount = doneCount, - total = total, + applicable = true, + done = (total > 0 and doneCount == total), + steps = steps, + stepsInProgress= stepsInProgress, + doneCount = doneCount, + total = total, } end +function RA:AnnounceCompletion(att) + if not att or not att.name then return end + if not RelationshipsAttuneCharDB.announced then + RelationshipsAttuneCharDB.announced = {} + end + if RelationshipsAttuneCharDB.announced[att.id] then return end + RelationshipsAttuneCharDB.announced[att.id] = true + + local inGuild = false + if IsInGuild then + local ok, res = pcall(IsInGuild) + if ok and res then inGuild = true end + end + if not inGuild and GetGuildInfo then + local ok, gname = pcall(GetGuildInfo, "player") + if ok and gname and gname ~= "" then inGuild = true end + end + local msg = "Attunement Complete: " .. (RA.playerName or "I") + .. " has fully completed the " .. att.name .. " attunement!" + if inGuild and SendChatMessage then + pcall(SendChatMessage, msg, "GUILD") + end + RA.print(msg) +end + function RA:RecomputeAll() for i = 1, table.getn(RelationshipsAttune_Data) do local att = RelationshipsAttune_Data[i] - RelationshipsAttuneCharDB.progress[att.id] = self:EvaluateAttunement(att) + local prev = RelationshipsAttuneCharDB.progress[att.id] + local wasDone = prev and prev.done + local prog = self:EvaluateAttunement(att) + RelationshipsAttuneCharDB.progress[att.id] = prog + if prog.applicable and prog.done and not wasDone then + self:AnnounceCompletion(att) + end end RelationshipsAttuneDB.players[RA.playerKey] = { name = RA.playerName, diff --git a/RelationshipsAttune.toc b/RelationshipsAttune.toc index f0d8490..e045c6c 100644 --- a/RelationshipsAttune.toc +++ b/RelationshipsAttune.toc @@ -2,7 +2,7 @@ ## Title: Relationships Attune ## Notes: Track Vanilla and Turtle/Octo WoW attunement progress ## Author: Relationship -## Version: 1.3 +## Version: 1.4 ## X-Category: Quest ## SavedVariables: RelationshipsAttuneDB ## SavedVariablesPerCharacter: RelationshipsAttuneCharDB diff --git a/UI.lua b/UI.lua index 33e0fef..46d3a0b 100644 --- a/UI.lua +++ b/UI.lua @@ -24,6 +24,7 @@ local C_NONE = { 0.90, 0.30, 0.30 } local C_UNKNOWN = { 0.55, 0.55, 0.55 } local C_TURTLE = { 0.55, 0.85, 1.00 } local C_KEYS = { 0.95, 0.75, 0.35 } +local C_INPROGRESS = { 1.00, 0.60, 0.15 } -- orange: quest accepted / step in progress local selectedPlayer = nil local selectedRaid = nil @@ -644,10 +645,15 @@ function UI:RenderDetail() row.name:SetText(step.name or "?") local ok = prog and prog.steps and prog.steps[origIdx] + local inProg = prog and prog.stepsInProgress and prog.stepsInProgress[origIdx] if ok then row.status:SetTexture(TEX_CHECK); row.status:Show() row.name:SetTextColor(C_DONE[1], C_DONE[2], C_DONE[3]) row.bg:SetVertexColor(0.20, 0.90, 0.30, 0.28) + elseif inProg then + row.status:SetTexture(TEX_WAIT); row.status:Show() + row.name:SetTextColor(C_INPROGRESS[1], C_INPROGRESS[2], C_INPROGRESS[3]) + row.bg:SetVertexColor(C_INPROGRESS[1], C_INPROGRESS[2], C_INPROGRESS[3], 0.22) elseif prog and prog.applicable then row.status:SetTexture(TEX_CROSS); row.status:Show() row.name:SetTextColor(1, 1, 1)