3 Commits

Author SHA1 Message Date
Relationship fc4dbc4fb3 Upload files to "/" 2026-07-23 12:29:47 +00:00
Relationship 7b57a45a1b Upload files to "/" 2026-07-23 12:29:41 +00:00
Relationship a5633fd9e2 Add files via upload 2026-07-18 20:15:06 +01:00
3 changed files with 120 additions and 15 deletions
+112 -7
View File
@@ -6,7 +6,7 @@ RelationshipsAttune = RelationshipsAttune or {}
local RA = RelationshipsAttune
local L = RelationshipsAttune_L
RA.VERSION = "1.4.3"
RA.VERSION = "1.4.4"
RA.COMM_PREFIX = "RATTUNE"
RA.playerName = nil
@@ -183,6 +183,75 @@ function RA:ScanQuestLog()
end
end
-- ---------------------------------------------------------------
-- Completed-quest scan (server-side completed quest cache).
--
-- Turtle WoW / OctoWoW backport QueryQuestsCompleted() +
-- GetQuestsCompleted(t), which return every quest the character has
-- ever turned in -- including quests completed BEFORE the addon was
-- installed. Without this, the addon can only see quests that are
-- currently in the log (or that were "complete" in a previous scan
-- and then vanished), so a player who is already half-way through a
-- chain shows no progress until they accept the next quest.
--
-- We pcall everything so stock 1.12 clients that don't expose these
-- APIs simply skip the scan and keep the existing behaviour.
-- ---------------------------------------------------------------
function RA:ScanCompletedQuests()
-- Build the set of quest ids we actually care about so we don't
-- pollute the DB with thousands of unrelated turn-ins.
if not RelationshipsAttune_Data then return end
local wanted = {}
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 == "quest" and s.id then
wanted[s.id] = true
end
end
end
end
local completed = {}
local haveAny = false
-- Preferred: bulk table fill.
if type(GetQuestsCompleted) == "function" then
local ok = pcall(GetQuestsCompleted, completed)
if ok then
for _ in pairs(completed) do haveAny = true break end
end
end
-- Fallback: per-id check (Turtle exposes IsQuestCompleted on some builds).
if not haveAny and type(IsQuestCompleted) == "function" then
for qid in pairs(wanted) do
local ok, res = pcall(IsQuestCompleted, qid)
if ok and res then
completed[qid] = true
haveAny = true
end
end
end
if not haveAny then
-- Kick the server to populate the cache; the QUEST_QUERY_COMPLETE
-- event handler will re-run this scan when the reply arrives.
if type(QueryQuestsCompleted) == "function" then
pcall(QueryQuestsCompleted)
end
return
end
for qid in pairs(wanted) do
if completed[qid] and RelationshipsAttuneCharDB.quests[qid] ~= "turnedin" then
RelationshipsAttuneCharDB.quests[qid] = "turnedin"
end
end
end
function RA:MarkQuestTurnedIn(questId)
if not questId then return end
@@ -610,12 +679,27 @@ function RA:MarkDirty() RA._dirty = true end
-- Full periodic rescan (quest log + bags + recompute + UI refresh).
function RA:AutoScan()
RA:ScanQuestLog()
RA:ScanCompletedQuests()
RA:ScanBags()
RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
end
function RA:_OnUpdate(elapsed)
-- Elapsed can arrive as a function argument, as the global arg1, or
-- (on some 1.12 builds) not at all. Fall back to GetTime() deltas so
-- the periodic auto-scan always advances.
if type(elapsed) ~= "number" then elapsed = nil end
if not elapsed and type(arg1) == "number" then elapsed = arg1 end
if not elapsed and GetTime then
local now = GetTime()
if RA._lastUpdate then
elapsed = now - RA._lastUpdate
else
elapsed = 0
end
RA._lastUpdate = now
end
elapsed = elapsed or 0
RA._throttle = RA._throttle + elapsed
RA._periodic = RA._periodic + elapsed
@@ -637,6 +721,7 @@ function RA:_OnUpdate(elapsed)
end
if fired then
RA:WarmItemCache()
RA:ScanCompletedQuests()
RA:ScanBags()
RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
@@ -726,13 +811,13 @@ local function slashHandler(msg)
if RA.Comm then RA.Comm:RequestSync() end
print(L.MSG_SYNC_SENT)
elseif msg == "scan" then
RA:ScanQuestLog(); RA:ScanBags(); RA:RecomputeAll()
RA:ScanQuestLog(); RA:ScanCompletedQuests(); RA:ScanBags(); RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
print(L.MSG_SCANNED)
elseif msg == "reset" then
RelationshipsAttuneCharDB = nil
RA:InitDB()
RA:ScanQuestLog(); RA:ScanBags(); RA:RecomputeAll()
RA:ScanQuestLog(); RA:ScanCompletedQuests(); RA:ScanBags(); RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
print(L.MSG_RESET)
elseif msg == "debug" or string.find(msg, "^find") then
@@ -808,6 +893,7 @@ pcall(function() ef:RegisterEvent("ITEM_PUSH") end)
pcall(function() ef:RegisterEvent("PLAYER_XP_UPDATE") end)
pcall(function() ef:RegisterEvent("ZONE_CHANGED_NEW_AREA") end)
pcall(function() ef:RegisterEvent("SKILL_LINES_CHANGED") end)
pcall(function() ef:RegisterEvent("QUEST_QUERY_COMPLETE") end)
ef:SetScript("OnEvent", function()
local e = event
@@ -819,8 +905,15 @@ ef:SetScript("OnEvent", function()
RA.playerFaction = UnitFactionGroup("player") or "Neutral"
RA:BuildNameIndex()
RA:WarmItemCache()
RA:ScanQuestLog(); RA:ScanBags(); RA:RecomputeAll()
RA._retryAt = { GetTime() + 3, GetTime() + 10 }
-- ScanCompletedQuests seeds the "already turned-in" state from the
-- server's completed-quest cache so mid-chain attunements show the
-- player's actual current step immediately at load, instead of
-- waiting until the next quest in the chain is accepted.
RA:ScanQuestLog(); RA:ScanCompletedQuests(); RA:ScanBags(); RA:RecomputeAll()
-- The completed-quest cache is often empty on first login until
-- QueryQuestsCompleted() round-trips to the server. Schedule extra
-- rescans so the UI catches up as soon as the cache is populated.
RA._retryAt = { GetTime() + 2, GetTime() + 5, GetTime() + 10 }
if RA.Comm and RA.Comm.Init then RA.Comm:Init() end
if RA.UI and RA.UI.Init then RA.UI:Init() end
if RA.Minimap and RA.Minimap.Init then RA.Minimap:Init() end
@@ -849,6 +942,13 @@ ef:SetScript("OnEvent", function()
elseif e == "QUEST_TURNED_IN" then
if arg1 then RA:MarkQuestTurnedIn(arg1) end
elseif e == "QUEST_QUERY_COMPLETE" then
if RA.initialized then
RA:ScanCompletedQuests()
RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
end
elseif e == "CHAT_MSG_ADDON" then
if arg1 == RA.COMM_PREFIX and RA.Comm and RA.Comm.OnMessage then
RA.Comm:OnMessage(arg2, arg3, arg4)
@@ -856,7 +956,12 @@ ef:SetScript("OnEvent", function()
end
end)
ef:SetScript("OnUpdate", function()
ef:SetScript("OnUpdate", function(_self, _elapsed)
if not RA.initialized then return end
RA:_OnUpdate(arg1)
-- Vanilla 1.12 delivers elapsed via the global arg1; some private-server
-- builds pass it as a positional parameter instead. Try both.
local e = arg1
if type(e) ~= "number" then e = _elapsed end
if type(e) ~= "number" then e = _self end
RA:_OnUpdate(e)
end)
+7 -7
View File
@@ -209,16 +209,16 @@ RelationshipsAttune_Data = {
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
{ type = "rep", faction = "Argent Dawn", standing = 5,
name = "Honored with the Argent Dawn", icon = ICON_REP,
desc = "Required to purchase the Naxxramas attunement from Archmage Angela Dosantos. Higher rep reduces the gold cost (60g Honored, 40g Revered, 20g Exalted).",
desc = "Required to purchase the Naxxramas attunement from Archmage Angela Dosantos. Higher rep with the Argent Dawn drastically reduces the material cost (see steps below).",
start = "Turn in Scourgestones / Minion's Scourgestones to Argent Dawn quartermasters at Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
{ type = "quest", id = 9121, name = "The Dread Citadel - Naxxramas! (Honored, 60g)", icon = ICON_ACTIVE, final = true,
desc = "Pay 60g to Angela Dosantos - available at Honored with Argent Dawn.",
{ type = "quest", id = 9121, name = "The Dread Citadel - Naxxramas! (Honored)", icon = ICON_ACTIVE, final = true,
desc = "Honored cost: 60 gold, 5 Arcane Crystals, 2 Nexus Crystals, and 1 Righteous Orb. Turn in to Archmage Angela Dosantos.",
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
{ type = "quest", id = 9122, name = "The Dread Citadel - Naxxramas! (Revered, 40g)", icon = ICON_ACTIVE, final = true,
desc = "Discounted Naxx attunement offered at Revered with Argent Dawn.",
{ type = "quest", id = 9122, name = "The Dread Citadel - Naxxramas! (Revered)", icon = ICON_ACTIVE, final = true,
desc = "Revered cost: 30 gold, 2 Arcane Crystals, and 1 Nexus Crystal. Turn in to Archmage Angela Dosantos.",
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
{ type = "quest", id = 9123, name = "The Dread Citadel - Naxxramas! (Exalted, 20g)", icon = ICON_ACTIVE, final = true,
desc = "Cheapest Naxx attunement, offered only at Exalted with Argent Dawn.",
{ type = "quest", id = 9123, name = "The Dread Citadel - Naxxramas! (Exalted)", icon = ICON_ACTIVE, final = true,
desc = "Exalted cost: completely free. Turn in to Archmage Angela Dosantos.",
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
},
},
+1 -1
View File
@@ -2,7 +2,7 @@
## Title: Relationships Attune
## Notes: Track Vanilla and Turtle/Octo WoW attunement progress
## Author: Relationship
## Version: 1.8
## Version: 1.9
## X-Category: Quest
## SavedVariables: RelationshipsAttuneDB
## SavedVariablesPerCharacter: RelationshipsAttuneCharDB