10 Commits

Author SHA1 Message Date
Relationship a276cca444 Add files via upload 2026-07-16 17:34:22 +01:00
Relationship 4502a1db7e Add files via upload 2026-07-16 17:03:20 +01:00
Relationship fda04907c2 Update README.md 2026-07-15 15:32:46 +01:00
Relationship e95e65fca5 Add files via upload 2026-07-12 17:16:47 +01:00
Relationship 044b6593ec Add files via upload 2026-07-12 17:06:21 +01:00
Relationship fbb3e94b93 Add files via upload 2026-07-12 17:02:18 +01:00
Relationship cca57c7adc Add files via upload 2026-07-12 16:58:48 +01:00
Relationship c1c1741b6e Add files via upload 2026-07-12 12:30:17 +01:00
Relationship 9669809096 Update RelationshipsAttune.toc 2026-07-11 11:18:43 +01:00
Relationship 04f87e5b42 Add files via upload 2026-07-11 11:12:12 +01:00
6 changed files with 521 additions and 328 deletions
+218 -84
View File
@@ -6,7 +6,7 @@ RelationshipsAttune = RelationshipsAttune or {}
local RA = RelationshipsAttune
local L = RelationshipsAttune_L
RA.VERSION = "1.2.7"
RA.VERSION = "1.4.2"
RA.COMM_PREFIX = "RATTUNE"
RA.playerName = nil
@@ -58,7 +58,7 @@ function RA:InitDB()
end
local o = RelationshipsAttuneDB.options
if o.autoShare == nil then o.autoShare = true end
if o.autoScanSeconds == nil then o.autoScanSeconds = 20 end
if o.autoScanSeconds == nil then o.autoScanSeconds = 10 end
if type(o.minimapAngle) ~= "number" then o.minimapAngle = 200 end
if type(o.minimapRadius) ~= "number" then o.minimapRadius = 80 end
if o.minimapHide == nil then o.minimapHide = false end
@@ -67,31 +67,73 @@ 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
-- ---------------------------------------------------------------
-- Quest log scan (vanilla API)
--
-- Note: vanilla 1.12's GetQuestLogTitle returns 6 values without a questId.
-- Turtle/Octo backported questId as the 8th return. We pcall + accept both
-- shapes so the addon degrades gracefully on stock 1.12.
-- ---------------------------------------------------------------
function RA:ScanQuestLog()
if not GetNumQuestLogEntries then return end
-- Snapshot previous transient states so we can detect a turn-in on clients
-- that don't fire QUEST_TURNED_IN (stock 1.12). A quest that was
-- "complete" (ready to hand in) and is now missing from the log is
-- almost certainly turned in -- abandoning a quest requires it to be
-- accepted-but-not-complete. This is what actually credits MC's
-- "Attunement to the Core" (7487), BWL, Naxx, and any other
-- quest-only final step.
local prev = RelationshipsAttuneCharDB.quests or {}
local kept = {}
for qid, st in pairs(prev) do
if st == "turnedin" then kept[qid] = "turnedin" end
end
RelationshipsAttuneCharDB.quests = kept
RA:BuildNameIndex()
local qNameMap = RA._questNameToId or {}
local seenThisScan = {}
local numEntries = GetNumQuestLogEntries()
for i = 1, numEntries do
local title, level, tag, isHeader, _, isComplete, _, questId =
GetQuestLogTitle(i)
if (not isHeader) and questId then
local ok, title, level, tag, isHeader, _, isComplete, _, questId =
pcall(GetQuestLogTitle, i)
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 then
seenThisScan[qid] = true
if RelationshipsAttuneCharDB.quests[qid] ~= "turnedin" then
if isComplete and isComplete == 1 then
RelationshipsAttuneCharDB.quests[questId] = "complete"
RelationshipsAttuneCharDB.quests[qid] = "complete"
else
if not RelationshipsAttuneCharDB.quests[questId] then
RelationshipsAttuneCharDB.quests[questId] = "inlog"
RelationshipsAttuneCharDB.quests[qid] = "inlog"
end
end
end
end
end
-- Retroactive turn-in detection: any quest we tracked as "complete" last
-- scan that isn't in the log any more got handed in.
for qid, st in pairs(prev) do
if st == "complete" and not seenThisScan[qid] then
RelationshipsAttuneCharDB.quests[qid] = "turnedin"
end
end
end
function RA:MarkQuestTurnedIn(questId)
if not questId then return end
RelationshipsAttuneCharDB.quests[questId] = "turnedin"
@@ -112,11 +154,6 @@ local function rememberItemLink(link)
end
-- Resolve by name so a custom Turtle/Octo item whose live client id
-- differs from the id declared in Data.lua still gets credited.
-- Try GetItemInfo first (works when the item is cached), then fall back
-- to parsing the bracketed display name straight out of the link. On
-- 1.12 / Turtle / Octo, keyring items very often return a link but
-- GetItemInfo returns nil because the item is not cached client-side,
-- so the bracketed-name parse is what actually credits the item.
local resolvedName
if GetItemInfo then
local ok, n = pcall(GetItemInfo, link)
@@ -148,22 +185,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
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
@@ -200,19 +242,10 @@ local function scanContainer(containerId)
end
end
-- Scan a keyring-like container. Uses every fallback we know of so that
-- keys register on vanilla 1.12, Turtle, and Octo regardless of which
-- bag id / API path actually works on that client build:
-- 1) GetContainerItemLink -> parse item id + bracketed name from link.
-- 2) SetBagItem tooltip -> read visible line as name.
-- 3) GetContainerItemInfo -> at minimum proves a slot is occupied so
-- we keep probing even when NumSlots lies.
local function scanKeyringContainer(bag)
if not GetContainerNumSlots then return end
local ok, slots = pcall(GetContainerNumSlots, bag)
if not ok or not slots then slots = 0 end
-- Some 1.12 clients report 0 slots for the keyring until it has been
-- opened at least once. Probe a reasonable upper bound in that case.
local probe = slots
if probe < 1 then probe = 32 end
@@ -224,13 +257,11 @@ local function scanKeyringContainer(bag)
local setOk = false
pcall(function() tip:SetBagItem(bag, slot); setOk = true end)
-- Path 1: link
local link
local okL, l = pcall(GetContainerItemLink, bag, slot)
if okL then link = l end
if link then rememberItemLink(link) end
-- Path 2: tooltip visible name (works even when link is nil).
if setOk then
local name = tipItemName()
if name and nameMap then
@@ -239,11 +270,6 @@ local function scanKeyringContainer(bag)
end
end
-- Path 3: GetContainerItemInfo. We can't get a name from it, but
-- if it returns a texture the slot is definitely occupied; that
-- lets us know it's worth continuing to probe even when the
-- earlier paths returned nothing on this build.
-- (No-op for identification, kept for future diagnostics.)
if GetContainerItemInfo then
pcall(GetContainerItemInfo, bag, slot)
end
@@ -251,11 +277,6 @@ local function scanKeyringContainer(bag)
pcall(function() tip:Hide() end)
end
-- Warm the client-side item cache for every item id we care about. On
-- vanilla 1.12 the first GetItemInfo(id) call for an uncached item kicks
-- off a server fetch and returns nil; a later call returns real data.
-- Doing this at load time (and again after a short delay) means that by
-- the time we parse a keyring link, GetItemInfo can actually resolve it.
function RA:WarmItemCache()
if not GetItemInfo or not RelationshipsAttune_Data then return end
for i = 1, table.getn(RelationshipsAttune_Data) do
@@ -278,10 +299,6 @@ function RA:ScanBags()
scanContainer(bag)
end
-- Keyring: try every index the various 1.12 forks use. Vanilla/Turtle/
-- Octo typically expose it as -2; a few builds use -1, -3, or define
-- KEYRING_CONTAINER to something else entirely. Scanning a bogus id
-- is harmless because scanKeyringContainer pcall-guards every call.
local seen = {}
local function tryBag(b)
if b == nil or seen[b] then return end
@@ -301,7 +318,6 @@ function RA:ScanBags()
end
end
-- Back-compat shim: older code paths may still call this.
function RA:ForceKeyringResolve()
scanKeyringContainer(-2)
end
@@ -325,43 +341,60 @@ 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 == "turnedin" then
return true, false
elseif st == "complete" or st == "inlog" then
-- Quest is in the log (either accepted or ready to turn in).
-- Treat both as "on this step" (orange) until it is actually
-- turned in. Retroactive completion will still mark this
-- step green once the player advances to a later step.
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 player already owns the final key/item (or a step
-- explicitly flagged final=true) then the entire attunement is done, even
-- if earlier bookkeeping steps (prereq quests, reputation) can no longer
-- be detected on this character. This handles the case where the key was
-- earned before the addon was installed.
-- Short-circuit: if the "final" step is complete, treat the whole
-- attunement as done. Prefer an explicit final=true step; fall back to
-- the last item step (key), then the last applicable step.
local finalIdx = nil
for i = numSteps, 1, -1 do
local step = att.steps[i]
@@ -371,7 +404,6 @@ function RA:EvaluateAttunement(att)
end
end
if not finalIdx then
-- Fall back to the last applicable item step (typically the key).
for i = numSteps, 1, -1 do
local step = att.steps[i]
if step.type == "item" and self:StepApplies(step) then
@@ -381,8 +413,6 @@ function RA:EvaluateAttunement(att)
end
end
if not finalIdx then
-- If there is no key/item step, the last applicable step is the final
-- proof we can see. This covers quest-only or reputation attunements.
for i = numSteps, 1, -1 do
local step = att.steps[i]
if self:StepApplies(step) then
@@ -391,6 +421,34 @@ function RA:EvaluateAttunement(att)
end
end
end
-- Retroactive completion: if the player is on a later step (done or in
-- progress), any earlier quest/item steps must already be done. Quests
-- get turned in and key items get consumed, so their live state can
-- flip back to "not done" even though the player clearly finished
-- them. Level and reputation steps have their own live truth and are
-- left alone.
local laterActive = false
for i = numSteps, 1, -1 do
local step = att.steps[i]
if step and self:StepApplies(step) then
if laterActive and steps[i] == false then
local t = step.type
if t == "quest" or t == "item" then
steps[i] = true
stepsInProgress[i] = false
doneCount = doneCount + 1
if t == "quest" then
RelationshipsAttuneCharDB.quests[step.id] = "turnedin"
elseif t == "item" then
RelationshipsAttuneCharDB.items[step.id] = true
end
end
end
if steps[i] == true or stepsInProgress[i] == true then
laterActive = true
end
end
end
local persistedDone = RelationshipsAttuneCharDB.completedAttunements and RelationshipsAttuneCharDB.completedAttunements[att.id]
if persistedDone or (finalIdx and steps[finalIdx] == true) then
for i = 1, numSteps do
@@ -407,15 +465,47 @@ function RA:EvaluateAttunement(att)
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,
@@ -433,21 +523,28 @@ end
-- Throttled auto-scan
-- ---------------------------------------------------------------
RA._throttle = 0
RA._periodic = 0
RA._dirty = false
RA._minRescan = 2.0
RA._minRescan = 1.5
function RA:MarkDirty() RA._dirty = true end
function RA:_OnUpdate(elapsed)
RA._throttle = RA._throttle + (elapsed or 0)
local interval = (RelationshipsAttuneDB and RelationshipsAttuneDB.options
and RelationshipsAttuneDB.options.autoScanSeconds) or 20
if interval < 5 then interval = 5 end
-- Full periodic rescan (quest log + bags + recompute + UI refresh).
function RA:AutoScan()
RA:ScanQuestLog()
RA:ScanBags()
RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
end
function RA:_OnUpdate(elapsed)
elapsed = elapsed or 0
RA._throttle = RA._throttle + elapsed
RA._periodic = RA._periodic + elapsed
local interval = (RelationshipsAttuneDB and RelationshipsAttuneDB.options
and RelationshipsAttuneDB.options.autoScanSeconds) or 10
if interval < 3 then interval = 3 end
-- Delayed post-login retry passes. GetItemInfo populates async on
-- 1.12, and the keyring itself may not be populated at PLAYER_LOGIN,
-- so we re-warm the cache and rescan a couple of times shortly after
-- login to catch keys that weren't resolvable on the first pass.
if RA._retryAt and GetTime then
local now = GetTime()
local pending = {}
@@ -473,22 +570,22 @@ function RA:_OnUpdate(elapsed)
end
end
-- Event-driven rescan: something changed, catch up quickly.
if RA._dirty and RA._throttle >= RA._minRescan then
RA._dirty = false
RA._throttle = 0
RA:ScanQuestLog()
RA:ScanBags()
RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
RA._periodic = 0
RA:AutoScan()
return
end
if RA._throttle >= interval then
-- Unconditional periodic rescan so state stays fresh even if no events fire
-- (e.g. reputation ticks from mob kills, quest turn-ins on stock 1.12
-- without QUEST_TURNED_IN, background item pickups by other addons).
if RA._periodic >= interval then
RA._periodic = 0
RA._throttle = 0
RA:ScanQuestLog()
RA:ScanBags()
RA:RecomputeAll()
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
RA:AutoScan()
end
end
@@ -497,14 +594,12 @@ end
-- ---------------------------------------------------------------
local function slashHandler(msg)
msg = string.lower(msg or "")
-- trim
msg = string.gsub(msg, "^%s+", "")
msg = string.gsub(msg, "%s+$", "")
if msg == "show" then
if RA.UI then RA.UI:Show() end
elseif msg == "hide" then
-- If the window is open, /attune hide closes it; otherwise it hides the minimap button.
if RA.UI and RA.UI:IsShown() then
RA.UI:Hide()
elseif RA.Minimap then
@@ -521,6 +616,34 @@ local function slashHandler(msg)
print("Minimap button shown. Drag to reposition around the minimap.")
end
end
elseif string.find(msg, "^pos") then
-- /attune pos <x> <y> -- set exact offset from UIParent CENTER.
-- Values may be off-screen (e.g. -9999) to park the button out of
-- the way while still letting MinimapButtonBag collect it.
local _, _, sx, sy = string.find(msg, "pos%s+(%-?%d+%.?%d*)%s+(%-?%d+%.?%d*)")
local x, y = tonumber(sx), tonumber(sy)
if x and y and RA.Minimap then
local o = RelationshipsAttuneDB.options
o.minimapX, o.minimapY = x, y
RA.Minimap:Refresh()
print("Minimap button moved to " .. x .. ", " .. y .. ".")
else
print("Usage: /attune pos <x> <y> (offsets from screen center; can be off-screen)")
end
elseif msg == "offscreen" or msg == "park" then
if RA.Minimap then
local o = RelationshipsAttuneDB.options
o.minimapX, o.minimapY = -10000, -10000
RA.Minimap:Refresh()
print("Minimap button parked off-screen. MinimapButtonBag (if installed) can still collect it. Use /attune resetpos to bring it back.")
end
elseif msg == "resetpos" then
if RA.Minimap then
local o = RelationshipsAttuneDB.options
o.minimapX, o.minimapY = 0, -140
RA.Minimap:Refresh()
print("Minimap button position reset.")
end
elseif msg == "sync" then
if RA.Comm then RA.Comm:RequestSync() end
print(L.MSG_SYNC_SENT)
@@ -563,13 +686,15 @@ local function slashHandler(msg)
end
end
pcall(function() tip:Hide() end)
print("Scarlet Key (7146) owned: " .. tostring(RelationshipsAttuneCharDB.items[7146] == true))
elseif msg == "help" or msg == "?" then
print("Relationships Attune - commands:")
print(" /attune - toggle the window")
print(" /attune show - open the window")
print(" /attune hide - close the window (or hide the minimap button)")
print(" /attune minimap - toggle the minimap button")
print(" /attune pos x y - place the minimap button at exact offset (can be off-screen)")
print(" /attune offscreen- park the minimap button off-screen (MBB can still collect it)")
print(" /attune resetpos - restore the minimap button to a visible default position")
print(" /attune scan - force a rescan of quests + bags")
print(" /attune sync - request sync from your group")
print(" /attune debug - dump keyring + item detection")
@@ -596,8 +721,15 @@ ef:RegisterEvent("BAG_UPDATE")
ef:RegisterEvent("PLAYER_LEVEL_UP")
ef:RegisterEvent("UPDATE_FACTION")
ef:RegisterEvent("CHAT_MSG_ADDON")
-- These events don't exist on stock 1.12 but Turtle/Octo backports them.
-- pcall prevents a hard failure on builds that don't recognise them.
pcall(function() ef:RegisterEvent("QUEST_TURNED_IN") end)
pcall(function() ef:RegisterEvent("KEYRING_UPDATE") end)
pcall(function() ef:RegisterEvent("UNIT_INVENTORY_CHANGED") end)
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)
ef:SetScript("OnEvent", function()
local e = event
@@ -610,9 +742,6 @@ ef:SetScript("OnEvent", function()
RA:BuildNameIndex()
RA:WarmItemCache()
RA:ScanQuestLog(); RA:ScanBags(); RA:RecomputeAll()
-- Retry pass: on 1.12 GetItemInfo populates async, and the
-- keyring is not always populated at PLAYER_LOGIN. Schedule two
-- delayed rescans so keys still get credited without user action.
RA._retryAt = { GetTime() + 3, 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
@@ -631,7 +760,12 @@ ef:SetScript("OnEvent", function()
or e == "BAG_UPDATE"
or e == "KEYRING_UPDATE"
or e == "PLAYER_LEVEL_UP"
or e == "UPDATE_FACTION" then
or e == "UPDATE_FACTION"
or e == "UNIT_INVENTORY_CHANGED"
or e == "ITEM_PUSH"
or e == "PLAYER_XP_UPDATE"
or e == "ZONE_CHANGED_NEW_AREA"
or e == "SKILL_LINES_CHANGED" then
if RA.initialized then RA:MarkDirty() end
elseif e == "QUEST_TURNED_IN" then
+271 -230
View File
@@ -1,28 +1,31 @@
-- RelationshipsAttune: Data.lua
-- Attunement definitions with icons + hover descriptions for the UI.
--
-- Sources: wowhead classic attunement guides (Onyxia, MC, BWL, Naxx, AQ40).
-- Turtle/Octo custom raids keep placeholder ids until server confirms them.
-- Sources: wowhead classic guides + turtle-wow wiki for custom raids/keys.
-- Turtle/Octo custom raids keep placeholder ids where the live server
-- hasn't been confirmed; the scanner also identifies items by tooltip
-- name so a name-match will still credit the step.
--
-- Each step:
-- { type = "level", level = 60, name = "...", icon = "..." }
-- { type = "quest", id = <qid>, name = "...", icon = "...",
-- faction = "Alliance"|"Horde"|nil, desc = "...", start = "..." }
-- faction = "Alliance"|"Horde"|nil, desc = "...", start = "...",
-- final = true|nil }
-- { type = "item", id = <iid>, name = "...", icon = "...", desc = "...", start = "..." }
-- { type = "rep", faction = "Argent Dawn", standing = 5, name = "...",
-- desc = "...", start = "..." }
--
-- Standing: 1=Hostile ... 4=Neutral, 5=Honored, 6=Revered, 7=Exalted.
-- final=true marks the "you are attuned" step so that if it's complete
-- the whole attunement is treated as done (used for quest-only chains
-- that have no key item at the end, e.g. Naxx/BWL/MC).
local ICON_QUEST = "Interface\\GossipFrame\\AvailableQuestIcon"
local ICON_ACTIVE = "Interface\\GossipFrame\\ActiveQuestIcon"
local ICON_KEY = "Interface\\Icons\\INV_Misc_Key_03"
local ICON_LEVEL = "Interface\\Icons\\Spell_Nature_EnchantArmor"
local ICON_REP = "Interface\\Icons\\Achievement_Reputation_01"
local ICON_ITEM = "Interface\\Icons\\INV_Misc_QuestionMark"
RelationshipsAttune_Data = {
----------------------------------------------------------------
-- ONYXIA'S LAIR - full Drakefire Amulet chain (both factions)
----------------------------------------------------------------
@@ -32,10 +35,8 @@ RelationshipsAttune_Data = {
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL,
desc = "Minimum level to start either faction's Onyxia attunement chain." },
------------------------------------------------------------------
-- ALLIANCE CHAIN (starts Burning Steppes -> Redridge -> Stormwind
-- -> BRD -> back to Stormwind -> Winterspring -> UBRS).
-- ALLIANCE CHAIN
------------------------------------------------------------------
{ type = "quest", id = 4182, faction = "Alliance",
name = "Dragonkin Menace", icon = ICON_QUEST,
@@ -44,47 +45,47 @@ RelationshipsAttune_Data = {
{ type = "quest", id = 4183, faction = "Alliance",
name = "The True Masters (Helendis)", icon = ICON_QUEST,
desc = "Deliver Helendis Riverhorn's Letter to Magistrate Solomon in Lakeshire.",
start = "Helendis Riverhorn, Morgan's Vigil, Burning Steppes (86, 69)." },
start = "Helendis Riverhorn, Morgan's Vigil, Burning Steppes (86, 69). Solomon: Lakeshire town hall, Redridge (30, 44)." },
{ type = "quest", id = 4184, faction = "Alliance",
name = "The True Masters (Solomon -> Bolvar)", icon = ICON_QUEST,
desc = "Take Solomon's Plea to Highlord Bolvar Fordragon in Stormwind Keep.",
start = "Magistrate Solomon, Lakeshire town hall, Redridge Mountains (30, 44)." },
start = "Magistrate Solomon, Lakeshire town hall, Redridge Mountains (30, 44). Bolvar: Stormwind Keep throne room (78, 18)." },
{ type = "quest", id = 4185, faction = "Alliance",
name = "The True Masters (Prestor)", icon = ICON_QUEST,
desc = "Speak with Lady Katrana Prestor, then return to Bolvar.",
start = "Highlord Bolvar Fordragon, Stormwind Keep throne room (78, 18)." },
start = "Highlord Bolvar Fordragon, Stormwind Keep throne room (78, 18). Prestor stands next to him." },
{ type = "quest", id = 4186, faction = "Alliance",
name = "The True Masters (Bolvar's Decree)", icon = ICON_QUEST,
desc = "Return Bolvar's Decree to Magistrate Solomon in Lakeshire.",
start = "Highlord Bolvar Fordragon, Stormwind Keep (78, 18)." },
start = "Highlord Bolvar Fordragon, Stormwind Keep (78, 18). Solomon: Lakeshire, Redridge (30, 44)." },
{ type = "quest", id = 4223, faction = "Alliance",
name = "The True Masters (Maxwell)", icon = ICON_QUEST,
desc = "Report to Marshal Maxwell at Morgan's Vigil.",
start = "Magistrate Solomon, Lakeshire, Redridge Mountains (30, 44)." },
start = "Magistrate Solomon, Lakeshire, Redridge Mountains (30, 44). Maxwell: Morgan's Vigil, Burning Steppes (85, 69)." },
{ type = "quest", id = 4224, faction = "Alliance",
name = "The True Masters (Ragged John)", icon = ICON_QUEST,
desc = "Find Ragged John in a cave north of Thaurissan, then return to Maxwell.",
start = "Marshal Maxwell, Morgan's Vigil, Burning Steppes (85, 69). Ragged John: cave at (65, 24)." },
start = "Marshal Maxwell, Morgan's Vigil, Burning Steppes (85, 69). Ragged John: cave at Burning Steppes (65, 24)." },
{ type = "quest", id = 4241, faction = "Alliance",
name = "Marshal Windsor", icon = ICON_QUEST,
desc = "Enter Blackrock Depths and find Marshal Windsor in his cell.",
start = "Marshal Maxwell, Morgan's Vigil, Burning Steppes (85, 69). BRD: Blackrock Mountain." },
start = "Marshal Maxwell, Morgan's Vigil, Burning Steppes (85, 69). BRD entrance: Blackrock Mountain (~30, 37) in Burning Steppes." },
{ type = "quest", id = 4242, faction = "Alliance",
name = "Abandoned Hope", icon = ICON_QUEST,
desc = "Return the bad news from Windsor to Marshal Maxwell.",
start = "Marshal Windsor, Windsor Cell, Blackrock Depths jail." },
start = "Marshal Windsor, Windsor Cell, Blackrock Depths jail (inside BRD, entrance at Blackrock Mountain ~30, 37, Burning Steppes)." },
{ type = "quest", id = 4264, faction = "Alliance",
name = "A Crumpled Up Note", icon = ICON_QUEST,
desc = "Random drop item from BRD slaves/mobs; return it to Windsor.",
start = "Loot A Crumpled Up Note from BRD slaves (outside instance) or trash inside." },
start = "Loot A Crumpled Up Note from BRD slaves (Shadowforge City) or trash inside Blackrock Depths (entrance Blackrock Mountain ~30, 37, Burning Steppes)." },
{ type = "quest", id = 4282, faction = "Alliance",
name = "A Shred of Hope", icon = ICON_QUEST,
desc = "Kill General Angerforge and Golem Lord Argelmach in BRD and loot Windsor's Lost Information from each.",
start = "Marshal Windsor, Windsor Cell, Blackrock Depths jail." },
start = "Marshal Windsor, Windsor Cell, Blackrock Depths jail (BRD entrance Blackrock Mountain ~30, 37, Burning Steppes)." },
{ type = "quest", id = 4322, faction = "Alliance",
name = "Jail Break!", icon = ICON_QUEST,
desc = "Escort Marshal Windsor out of BRD, then report to Marshal Maxwell.",
start = "Marshal Windsor, Windsor Cell, Blackrock Depths jail." },
start = "Marshal Windsor, Windsor Cell, Blackrock Depths jail. Turn in to Maxwell, Morgan's Vigil, Burning Steppes (85, 69)." },
{ type = "quest", id = 6402, faction = "Alliance",
name = "Stormwind Rendezvous", icon = ICON_QUEST,
desc = "Speak to Squire Rowe at the Stormwind gates to summon Reginald Windsor.",
@@ -92,7 +93,7 @@ RelationshipsAttune_Data = {
{ type = "quest", id = 6403, faction = "Alliance",
name = "The Great Masquerade", icon = ICON_ACTIVE,
desc = "Escort Reginald Windsor to Stormwind Keep; unmask Lady Prestor as Onyxia.",
start = "Reginald Windsor, Stormwind City gates (after Rendezvous)." },
start = "Reginald Windsor, Stormwind City gates (70, 86) after Rendezvous; escort ends in Stormwind Keep (78, 18)." },
{ type = "quest", id = 6501, faction = "Alliance",
name = "The Dragon's Eye", icon = ICON_QUEST,
desc = "Take the Fragment of the Dragon's Eye to Haleh in Mazthoril, Winterspring.",
@@ -100,12 +101,9 @@ RelationshipsAttune_Data = {
{ type = "quest", id = 6502, faction = "Alliance",
name = "Drakefire Amulet (Alliance)", icon = ICON_ACTIVE,
desc = "Kill General Drakkisath in Upper Blackrock Spire and loot Blood of the Black Dragon Champion; return to Haleh.",
start = "Haleh, Mazthoril cave, Winterspring (55, 51)." },
start = "Haleh, Mazthoril cave, Winterspring (55, 51). UBRS entrance: Blackrock Mountain (~30, 37), Burning Steppes." },
------------------------------------------------------------------
-- HORDE CHAIN (Kargath -> LBRS -> Orgrimmar -> UBRS -> Desolace
-- -> Western Plaguelands -> Dustwallow -> Tanaris/Winterspring/
-- Swamp of Sorrows/Wetlands -> Desolace -> UBRS).
-- HORDE CHAIN
------------------------------------------------------------------
{ type = "quest", id = 4903, faction = "Horde",
name = "Warlord's Command", icon = ICON_QUEST,
@@ -114,11 +112,11 @@ RelationshipsAttune_Data = {
{ type = "quest", id = 4941, faction = "Horde",
name = "Eitrigg's Wisdom", icon = ICON_QUEST,
desc = "Speak to Eitrigg in Orgrimmar, then turn in to Thrall.",
start = "Warlord Goretooth, Kargath, Badlands (6, 48). Eitrigg/Thrall: Valley of Wisdom, Orgrimmar (32, 38)." },
start = "Warlord Goretooth, Kargath, Badlands (6, 48). Eitrigg/Thrall: Grommash Hold, Valley of Wisdom, Orgrimmar (32, 38)." },
{ type = "quest", id = 4974, faction = "Horde",
name = "For The Horde!", icon = ICON_QUEST,
desc = "Kill Warchief Rend Blackhand in UBRS and return his head to Thrall (grants Warchief's Blessing).",
start = "Thrall, Grommash Hold, Valley of Wisdom, Orgrimmar (32, 38)." },
start = "Thrall, Grommash Hold, Valley of Wisdom, Orgrimmar (32, 38). UBRS: Blackrock Mountain (~30, 37), Burning Steppes." },
{ type = "quest", id = 6566, faction = "Horde",
name = "What the Wind Carries", icon = ICON_QUEST,
desc = "Listen to Thrall's tale and turn in.",
@@ -126,15 +124,15 @@ RelationshipsAttune_Data = {
{ type = "quest", id = 6567, faction = "Horde",
name = "The Champion of the Horde", icon = ICON_QUEST,
desc = "Find Rexxar patrolling between Desolace, Stonetalon and Feralas.",
start = "Thrall, Grommash Hold, Orgrimmar (32, 38). Rexxar: Desolace patrol path." },
start = "Thrall, Grommash Hold, Orgrimmar (32, 38). Rexxar: Desolace patrol between (35, 10) and (65, 70)." },
{ type = "quest", id = 6568, faction = "Horde",
name = "The Testament of Rexxar", icon = ICON_QUEST,
desc = "Deliver Rexxar's Testament to Myranda the Hag in Western Plaguelands.",
start = "Rexxar, Desolace (roaming). Myranda: near Uther's Tomb, Western Plaguelands (51, 78)." },
start = "Rexxar, Desolace patrol (35-65, 10-70). Myranda: near Uther's Tomb, Western Plaguelands (51, 78)." },
{ type = "quest", id = 6569, faction = "Horde",
name = "Oculus Illusions", icon = ICON_QUEST,
desc = "Collect 20 Black Dragonspawn Eyes from UBRS dragonkin for your disguise.",
start = "Myranda the Hag, Western Plaguelands (51, 78)." },
start = "Myranda the Hag, Western Plaguelands (51, 78). UBRS: Blackrock Mountain (~30, 37), Burning Steppes." },
{ type = "quest", id = 6570, faction = "Horde",
name = "Emberstrife", icon = ICON_QUEST,
desc = "Use Amulet of Draconic Subversion and speak to Emberstrife in his den, Dustwallow Marsh.",
@@ -146,7 +144,7 @@ RelationshipsAttune_Data = {
{ type = "quest", id = 6582, faction = "Horde",
name = "The Test of Skulls, Scryer", icon = ICON_QUEST,
desc = "Kill Scryer (Blue) inside Mazthoril cave, Winterspring.",
start = "Emberstrife, Emberstrife's Den, Dustwallow Marsh (57, 87). Scryer: Mazthoril (53, 56)." },
start = "Emberstrife, Emberstrife's Den, Dustwallow Marsh (57, 87). Scryer: Mazthoril, Winterspring (53, 56)." },
{ type = "quest", id = 6583, faction = "Horde",
name = "The Test of Skulls, Somnus", icon = ICON_QUEST,
desc = "Kill Somnus (Green) patrolling south-east Swamp of Sorrows.",
@@ -154,26 +152,24 @@ RelationshipsAttune_Data = {
{ type = "quest", id = 6585, faction = "Horde",
name = "The Test of Skulls, Axtroz", icon = ICON_QUEST,
desc = "Unlocks after the other three Skull quests. Kill Axtroz (Red) at Grim Batol, Wetlands.",
start = "Emberstrife, Emberstrife's Den, Dustwallow Marsh (57, 87). Axtroz: Wetlands (85, 49)." },
start = "Emberstrife, Emberstrife's Den, Dustwallow Marsh (57, 87). Axtroz: Grim Batol entrance, Wetlands (85, 49)." },
{ type = "quest", id = 6601, faction = "Horde",
name = "Ascension...", icon = ICON_QUEST,
desc = "Take the Dull Drakefire Amulet to Rexxar in Desolace (not to Drakkisath).",
start = "Emberstrife, Emberstrife's Den, Dustwallow Marsh (57, 87). Rexxar: Desolace patrol." },
start = "Emberstrife, Emberstrife's Den, Dustwallow Marsh (57, 87). Rexxar: Desolace patrol (35-65, 10-70)." },
{ type = "quest", id = 6602, faction = "Horde",
name = "Blood of the Black Dragon Champion", icon = ICON_ACTIVE,
desc = "Kill General Drakkisath in UBRS, loot his blood and return to Rexxar for the Drakefire Amulet.",
start = "Rexxar, Desolace patrol path." },
start = "Rexxar, Desolace patrol (35-65, 10-70). UBRS: Blackrock Mountain (~30, 37), Burning Steppes." },
------------------------------------------------------------------
-- Final reward (both factions).
------------------------------------------------------------------
{ type = "item", id = 16309, name = "Drakefire Amulet",
icon = "Interface\\Icons\\INV_Jewelry_Talisman_11",
desc = "Must be in every raid member's bags (not bank) to enter Onyxia's Lair.",
start = "Awarded by Haleh (Alliance, Winterspring) or Rexxar (Horde, Desolace patrol)." },
start = "Awarded by Haleh (Alliance, Mazthoril, Winterspring 55, 51) or Rexxar (Horde, Desolace patrol 35-65, 10-70)." },
},
},
----------------------------------------------------------------
-- MOLTEN CORE
----------------------------------------------------------------
@@ -182,19 +178,11 @@ RelationshipsAttune_Data = {
icon = "Interface\\Icons\\Spell_Fire_SelfDestruct",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "item", id = 17203, name = "Sulfuron Ingot (optional binder)",
icon = "Interface\\Icons\\INV_Ingot_08",
desc = "Not required for attunement itself, but drops in MC; listed for group planning.",
start = "Trash drops throughout Molten Core." },
{ type = "quest", id = 7487, name = "The Molten Core (BRD group summon)", icon = ICON_QUEST,
desc = "Group prereq that starts the Attunement chain via Lothos Riftwaker.",
start = "Lothos Riftwaker, Blackrock Mountain (top of chained platform near the MC portal)." },
{ type = "quest", id = 7848, name = "Attunement to the Core", icon = ICON_ACTIVE,
desc = "Turn in a Core Fragment (from Molten Core mobs) to Lothos Riftwaker; grants direct teleport into MC from BRD.",
start = "Lothos Riftwaker, Blackrock Mountain (BRD entrance platform)." },
{ type = "quest", id = 7487, name = "Attunement to the Core", icon = ICON_ACTIVE, final = true,
desc = "Fight through Blackrock Depths to the Molten Bridge and loot a Core Fragment from the elementals near the MC portal, then hand it to Lothos Riftwaker. Grants direct teleport into MC from the BRD entrance instance portal.",
start = "Lothos Riftwaker, BRD instance entrance platform inside Blackrock Mountain (~30, 37), Burning Steppes, next to the Molten Core portal." },
},
},
----------------------------------------------------------------
-- BLACKWING LAIR
----------------------------------------------------------------
@@ -205,13 +193,12 @@ RelationshipsAttune_Data = {
{ type = "level", level = 58, name = "Reach Level 58", icon = ICON_LEVEL },
{ type = "item", id = 12344, name = "Seal of Ascension (UBRS key prereq)", icon = ICON_KEY,
desc = "You must be able to enter UBRS to reach Vaelan; requires the Seal of Ascension chain.",
start = "Chain starts with Kibler at Flame Crest, Burning Steppes (62, 24), and Jorgen at Morgan's Vigil (85, 68)." },
{ type = "quest", id = 7761, name = "Blackhand's Command", icon = ICON_ACTIVE,
start = "Jorgen at Morgan's Vigil, Burning Steppes (85, 68) points you to Vaelan in UBRS (Blackrock Mountain ~30, 37, Burning Steppes)." },
{ type = "quest", id = 7761, name = "Blackhand's Command", icon = ICON_ACTIVE, final = true,
desc = "Read the scroll dropped by Vaelan behind the hidden door in UBRS, then use the orb at the top of UBRS to enter BWL.",
start = "Vaelan, hidden alcove past the UBRS orb room, Upper Blackrock Spire." },
start = "Vaelan, hidden alcove past the UBRS orb room, Upper Blackrock Spire (Blackrock Mountain ~30, 37, Burning Steppes)." },
},
},
----------------------------------------------------------------
-- NAXXRAMAS
----------------------------------------------------------------
@@ -224,18 +211,17 @@ RelationshipsAttune_Data = {
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).",
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,
{ 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.",
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,
{ 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.",
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,
{ 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.",
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
},
},
----------------------------------------------------------------
-- AQ20 - Ruins of Ahn'Qiraj
----------------------------------------------------------------
@@ -248,15 +234,13 @@ RelationshipsAttune_Data = {
name = "Neutral with Cenarion Circle", icon = ICON_REP,
desc = "Automatic from Silithus mobs after the war effort opens; no separate attunement item.",
start = "Windcaller Yessendra / Proudhorn, Cenarion Hold, Silithus (50, 33)." },
{ type = "quest", id = 8743, name = "The Gates of Ahn'Qiraj (server-wide event)", icon = ICON_QUEST,
{ type = "quest", id = 8743, name = "The Gates of Ahn'Qiraj (server-wide event)", icon = ICON_QUEST, final = true,
desc = "The AQ gates must have been opened server-side. Once open, anyone can walk in.",
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50). AQ gates: southern Silithus (28, 92)." },
},
},
----------------------------------------------------------------
-- AQ40 - Temple of Ahn'Qiraj (Scepter of the Shifting Sands)
-- Chain sourced from CixiDelmont's Attune addon (AttuneData id=10).
----------------------------------------------------------------
{
id = "aq40", name = "Temple of Ahn'Qiraj (40)", category = "Vanilla", faction = "Both",
@@ -265,17 +249,17 @@ RelationshipsAttune_Data = {
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
{ type = "quest", id = 8286, name = "What Tomorrow Brings", icon = ICON_QUEST,
desc = "Speak with Anachronos at the Caverns of Time to begin the Scepter chain.",
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50). Talk to him at the Gates of Ahn'Qiraj first (Silithus)." },
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50). Talk to him at the Gates of Ahn'Qiraj first, Silithus (28, 92)." },
{ type = "quest", id = 8288, name = "Only One May Rise", icon = ICON_QUEST,
desc = "Kill Vaelastrasz in Blackwing Lair and loot the Vessel of Rebirth.",
start = "Anachronos, Silithus / Caverns of Time." },
start = "Anachronos, Silithus AQ gates (28, 92) / Caverns of Time, Tanaris (65, 50). BWL: Blackrock Mountain (~30, 37), Burning Steppes." },
{ type = "quest", id = 8301, name = "The Path of the Righteous", icon = ICON_QUEST,
desc = "Continue Anachronos' story after handing in the Vessel.",
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
{ type = "rep", faction = "Brood of Nozdormu", standing = 4,
name = "Neutral with Brood of Nozdormu", icon = ICON_REP,
desc = "Kill AQ40 trash / bosses to raise Nozdormu rep from Hated to Neutral; required before Anachronos will continue.",
start = "Kill Qiraji inside AQ40; automatic once AQ40 is open." },
start = "Kill Qiraji inside AQ40, southern Silithus (28, 92); automatic once AQ40 is open." },
{ type = "quest", id = 8303, name = "Chamber of the Aspects", icon = ICON_QUEST,
desc = "Anachronos sends you to speak with the four dragon Aspect representatives.",
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
@@ -287,90 +271,130 @@ RelationshipsAttune_Data = {
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
{ type = "quest", id = 8555, name = "The Nightmare's Corruption (Red)", icon = ICON_QUEST,
desc = "Kill Vaelastrasz (BWL), loot Vaelastrasz's Tooth for Caelestrasz.",
start = "Caelestrasz, Anachronos' platform, Caverns of Time." },
start = "Caelestrasz, Anachronos' platform, Caverns of Time, Tanaris (65, 50)." },
{ type = "quest", id = 8733, name = "Beyond the Grave (Green)", icon = ICON_QUEST,
desc = "Investigate the pool inside The Temple of Atal'Hakkar for Merithra.",
start = "Merithra of the Dream, Caverns of Time." },
start = "Merithra of the Dream, Anachronos' platform, Caverns of Time, Tanaris (65, 50). Sunken Temple: Swamp of Sorrows (69, 53)." },
{ type = "quest", id = 8734, name = "Draconic for Dummies (Blue)", icon = ICON_QUEST,
desc = "Arygos sends you to research Nightmare Scale fragments across Azeroth.",
start = "Arygos, Caverns of Time." },
start = "Arygos, Anachronos' platform, Caverns of Time, Tanaris (65, 50)." },
{ type = "quest", id = 8735, name = "Stones of Binding (Bronze)", icon = ICON_QUEST,
desc = "Retrieve five Nightmare Engravings from world dragons (Ysondre, Emeriss, Lethon, Taerar and Azuregos) for Kalecgos.",
start = "Kalecgos, Caverns of Time." },
start = "Kalecgos, Anachronos' platform, Caverns of Time, Tanaris (65, 50). Azuregos: Azshara (56, 42)." },
{ type = "quest", id = 8736, name = "Preparations", icon = ICON_QUEST,
desc = "Return to Anachronos with the Nightmare Scale.",
start = "Anachronos, Caverns of Time." },
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
{ type = "quest", id = 8741, name = "The Charge of the Dragonflights", icon = ICON_QUEST,
desc = "The Aspects reforge the scepter. Deliver the Fragment of the Nightmare's Corruption.",
start = "Anachronos, Caverns of Time." },
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
{ type = "quest", id = 8742, name = "The Hand of the Righteous", icon = ICON_QUEST,
desc = "Final scepter reforging quest. Rewards Scepter of the Shifting Sands.",
start = "Anachronos, Caverns of Time." },
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
{ type = "item", id = 21175, name = "Scepter of the Shifting Sands",
icon = "Interface\\Icons\\INV_Hammer_25",
desc = "Use this item at the Scarab Gong outside AQ to trigger the 10-hour war and open the gates server-wide.",
start = "Reward from 'The Hand of the Righteous'." },
{ type = "quest", id = 8743, name = "Bang a Gong!", icon = ICON_ACTIVE,
start = "Reward from 'The Hand of the Righteous' (Anachronos, Caverns of Time, Tanaris 65, 50)." },
{ type = "quest", id = 8743, name = "Bang a Gong!", icon = ICON_ACTIVE, final = true,
desc = "Ring the Scarab Gong at the Gates of Ahn'Qiraj to open both AQ raids server-wide. First person to ring gets Scarab Lord title + mount.",
start = "Scarab Gong, Gates of Ahn'Qiraj, Silithus." },
start = "Scarab Gong, Gates of Ahn'Qiraj, southern Silithus (28, 92)." },
{ type = "item", id = 21176, name = "Black Qiraji Resonating Crystal (Scarab Lord mount)",
icon = "Interface\\Icons\\INV_Misc_QirajiCrystal_04",
desc = "Awarded only to the player who rings the gong within the 10-hour war window.",
start = "Reward for completing 'Bang a Gong!' during the war event." },
{ type = "quest", id = 8745, name = "Ouro's Message (post-war attunement)", icon = ICON_QUEST,
desc = "Anyone can walk into AQ40 once the gates are open; no personal attunement item required after the event.",
start = "Anachronos - concludes the Scepter chain." },
start = "Reward for completing 'Bang a Gong!' at the AQ gates, Silithus (28, 92) during the war event." },
},
},
----------------------------------------------------------------
-- VANILLA KEYS & DUNGEON ACCESS
----------------------------------------------------------------
{
id = "ubrs", name = "Upper Blackrock Spire", category = "Keys & Access", faction = "Both",
id = "ubrs", name = "Upper Blackrock Spire (Seal)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_04",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "quest", id = 4903, name = "Kibler's Exotic Pets (chain start)", icon = ICON_QUEST,
desc = "Opens Jorgen's Seal of Ascension chain.",
start = "Kibler, Flame Crest, Burning Steppes (62, 24)." },
{ type = "quest", id = 4743, name = "Seal of Ascension", icon = ICON_QUEST,
desc = "Requires the Unadorned Seal of Ascension (drops in LBRS) plus three gemstones from LBRS bosses.",
start = "Jorgen, Morgan's Vigil, Burning Steppes (85, 68)." },
{ type = "item", id = 12344, name = "Seal of Ascension", icon = ICON_KEY,
desc = "Opens the door to Upper Blackrock Spire at the top of the LBRS instance.",
start = "Awarded by Jorgen at Morgan's Vigil after completing the Seal of Ascension chain." },
{ type = "item", id = 12219, name = "Unadorned Seal of Ascension", icon = ICON_KEY,
desc = "Opens the UBRS door at the top of LBRS. Drops from The Beast in UBRS, Overlord Wyrmthalak in LBRS, and Pyroguard Emberseer, and is provided by Vaelan for the attunement chain.",
start = "Loot from LBRS/UBRS bosses, or given directly by Vaelan (hidden alcove past the orb room in UBRS, Blackrock Mountain ~30, 37, Burning Steppes)." },
{ type = "quest", id = 4742, name = "Seal of Ascension", icon = ICON_QUEST,
desc = "Collect the three Gemstones of Command (Smolderthorn from War Master Voone, Spirestone from Highlord Omokk, Bloodaxe from Overlord Wyrmthalak - all in LBRS) and return them with the Unadorned Seal of Ascension to Vaelan.",
start = "Vaelan, hidden alcove past the orb room, Upper Blackrock Spire (Blackrock Mountain ~30, 37, Burning Steppes)." },
{ type = "item", id = 12344, name = "Seal of Ascension", icon = ICON_KEY, final = true,
desc = "Uses the orb at the top of UBRS to open the instance portal. Required to enter UBRS.",
start = "Reward from Vaelan for turning in 'Seal of Ascension' inside UBRS (Blackrock Mountain ~30, 37, Burning Steppes)." },
},
},
{
id = "brd", name = "Blackrock Depths", category = "Keys & Access", faction = "Both",
id = "brd", name = "Blackrock Depths (Shadowforge Key)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_06",
steps = {
{ type = "level", level = 47, name = "Reach Level 47", icon = ICON_LEVEL },
{ type = "quest", id = 4136, name = "Dark Iron Legacy", icon = ICON_QUEST,
desc = "Rewards the Shadowforge Key for opening the deeper doors in BRD.",
start = "Franclorn Forgewright's ghost, inside Blackrock Depths (Detention Block hallway near his statue)." },
{ type = "quest", id = 3802, name = "Dark Iron Legacy", icon = ICON_QUEST,
desc = "Kill Fineous Darkvire in the Hall of Crafting inside BRD and loot Ironfel, then place Ironfel on Franclorn Forgewright's statue at the Shrine of Thaurissan. Turn-in rewards the Shadowforge Key.",
start = "Franclorn Forgewright's ghost at the Shrine of Thaurissan inside Blackrock Depths (BRD entrance: Blackrock Mountain ~30, 37, Burning Steppes). Accept 3801 first, then 3802." },
{ type = "item", id = 11000, name = "Shadowforge Key", icon = ICON_KEY,
desc = "Opens Shadowforge City / Manufactory doors deep in BRD.",
start = "Reward from 'Dark Iron Legacy'." },
desc = "Opens the Shadowforge Lock and every Dark Iron door in the deeper half of BRD.",
start = "Reward from completing 'Dark Iron Legacy' (quest 3802) inside BRD (Blackrock Mountain ~30, 37, Burning Steppes)." },
},
},
{
id = "scholo", name = "Scholomance", category = "Keys & Access", faction = "Both",
id = "brd_prison", name = "BRD Prison Cell Key", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_05",
steps = {
{ type = "level", level = 52, name = "Reach Level 52", icon = ICON_LEVEL },
{ type = "item", id = 11140, name = "Prison Cell Key", icon = ICON_KEY,
desc = "Unlocks the Detention Block cells in Blackrock Depths (frees Marshal Windsor, Dughal Stormwing, Kharan Mighthammer, etc). Rogues can also pick these locks around 250 lockpicking.",
start = "Drops from Warder Stilgiss (patrolling the Detention Block corridor with his frost hound Frostwrath, inside Blackrock Depths - entrance Blackrock Mountain ~30, 37, Burning Steppes)." },
},
},
{
id = "scholo", name = "Scholomance (Skeleton Key)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_11",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "quest", id = 5382, name = "The Key to Scholomance", icon = ICON_QUEST,
desc = "Requires Blood of Innocents (Scarlet Monastery), Viewing Room Key (Scholomance) and Deed to Caer Darrow.",
start = "Alliance: Alexi Barov, Hearthglen, Western Plaguelands (44, 21). Horde: Alexi Barov, Ruins of Andorhal (42, 68)." },
{ type = "item", id = 13704, name = "Skeleton Key", icon = ICON_KEY,
desc = "Opens the front door of Scholomance in Caer Darrow.",
start = "Reward from 'The Key to Scholomance'." },
{ type = "quest", id = 5537, faction = "Alliance",
name = "Skeletal Fragments (Alliance)", icon = ICON_QUEST,
desc = "Collect 15 Skeletal Fragments from the reanimated skeletons around Andorhal / Sorrow Hill for the Alchemist to imbue.",
start = "Alchemist Arbington, Chillwind Camp, Western Plaguelands (43, 84)." },
{ type = "quest", id = 5538, faction = "Horde",
name = "Skeletal Fragments (Horde)", icon = ICON_QUEST,
desc = "Horde version of the fragment collection quest for the Skeleton Key.",
start = "Apothecary Dithers, The Bulwark, Western Plaguelands (81, 71)." },
{ type = "quest", id = 5514, faction = "Alliance",
name = "Mold Rhymes With... (Alliance)", icon = ICON_QUEST,
desc = "Bring the Imbued Skeletal Fragments and 15 gold to Krinkle Goodsteel in Gadgetzan to buy the Skeleton Key Mold.",
start = "Alchemist Arbington, Chillwind Camp, Western Plaguelands (43, 84). Krinkle: Gadgetzan, Tanaris (51, 29)." },
{ type = "quest", id = 5515, faction = "Horde",
name = "Mold Rhymes With... (Horde)", icon = ICON_QUEST,
desc = "Horde variant: bring the Imbued Skeletal Fragments and 15 gold to Krinkle Goodsteel in Gadgetzan.",
start = "Apothecary Dithers, The Bulwark, Western Plaguelands (81, 71). Krinkle: Gadgetzan, Tanaris (51, 29)." },
{ type = "quest", id = 5801, faction = "Alliance",
name = "Fire Plume Forged (Alliance)", icon = ICON_QUEST,
desc = "Use the Skeleton Key Mold plus 2 Thorium Bars at the lava lake atop Fire Plume Ridge in Un'Goro Crater to cast the Unfinished Skeleton Key.",
start = "Krinkle Goodsteel, Gadgetzan, Tanaris (51, 29). Fire Plume Ridge: Un'Goro Crater (49, 60)." },
{ type = "quest", id = 5802, faction = "Horde",
name = "Fire Plume Forged (Horde)", icon = ICON_QUEST,
desc = "Horde variant: forge the Unfinished Skeleton Key at Fire Plume Ridge in Un'Goro Crater.",
start = "Krinkle Goodsteel, Gadgetzan, Tanaris (51, 29). Fire Plume Ridge: Un'Goro Crater (49, 60)." },
{ type = "quest", id = 5803, faction = "Alliance",
name = "Araj's Scarab (Alliance)", icon = ICON_QUEST,
desc = "Slay Araj the Summoner (elite lich, center of ruined Andorhal) and loot Araj's Scarab - the head of the key. Group quest.",
start = "Alchemist Arbington, Chillwind Camp, Western Plaguelands (43, 84). Araj: center of Andorhal (42, 68)." },
{ type = "quest", id = 5804, faction = "Horde",
name = "Araj's Scarab (Horde)", icon = ICON_QUEST,
desc = "Horde variant of the Araj kill quest.",
start = "Apothecary Dithers, The Bulwark, Western Plaguelands (81, 71). Araj: center of Andorhal (42, 68)." },
{ type = "quest", id = 5505, faction = "Alliance",
name = "The Key to Scholomance (Alliance)", icon = ICON_ACTIVE,
desc = "Turn in Araj's Scarab and receive the Skeleton Key.",
start = "Alchemist Arbington, Chillwind Camp, Western Plaguelands (43, 84)." },
{ type = "quest", id = 5506, faction = "Horde",
name = "The Key to Scholomance (Horde)", icon = ICON_ACTIVE,
desc = "Horde turn-in for the Skeleton Key.",
start = "Apothecary Dithers, The Bulwark, Western Plaguelands (81, 71)." },
{ type = "item", id = 13704, name = "Skeleton Key", icon = ICON_KEY, final = true,
desc = "Opens the front door of Scholomance on Caer Darrow. Rogues can pick the door at 280 lockpicking, so the key is optional but persistent.",
start = "Reward from the final 'The Key to Scholomance' turn-in (Chillwind Camp 43, 84 Alliance / The Bulwark 81, 71 Horde, Western Plaguelands). Scholomance door: Caer Darrow, Western Plaguelands (69, 73)." },
},
},
{
id = "strat_live", name = "Stratholme (Service Entrance)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_07",
@@ -378,38 +402,45 @@ RelationshipsAttune_Data = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "item", id = 12382, name = "Key to the City", icon = ICON_KEY,
desc = "Opens the Service Entrance shortcut into Stratholme Live.",
start = "Drops from Magistrate Barthilas, patrolling the main road of Stratholme Live." },
start = "Drops from Magistrate Barthilas, patrolling the main road of Stratholme Live (instance entrance: Eastern Plaguelands 27, 12)." },
},
},
{
id = "dm", name = "Dire Maul", category = "Keys & Access", faction = "Both",
id = "dm", name = "Dire Maul (Crescent Key)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_09",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "item", id = 18249, name = "Crescent Key", icon = ICON_KEY,
desc = "Opens locked doors and cages throughout Dire Maul (all three wings).",
start = "Pickpocket from Kobold Geomancers inside Dire Maul West (Rogue only), lockpick at 300, or buy from the AH." },
start = "Pickpocket from Kobold Geomancers inside Dire Maul West (Rogue only, DM entrance: Feralas 61, 30), lockpick at 300, or buy from the AH." },
},
},
{
id = "dm_tribute", name = "Dire Maul North (Gordok Tribute Run)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Crown_02",
steps = {
{ type = "level", level = 58, name = "Reach Level 58", icon = ICON_LEVEL },
{ type = "item", id = 18249, name = "Crescent Key", icon = ICON_KEY,
desc = "Needed to open the doors within Dire Maul North for the King run.",
start = "Same source as regular DM Crescent Key (DM entrance: Feralas 61, 30)." },
{ type = "item", id = 18746, name = "Ogre Tannin", icon = ICON_ITEM,
desc = "Bring Ogre Tannin from Knot Thimblejack's Cache in Dire Maul North (found via lockpicking or Crescent Key) to Cho'Rush the Observer AFTER King Gordok dies. Skipping this makes the tribute run impossible.",
start = "Knot Thimblejack's Cache, Dire Maul North past the Warpwood Quarter (DM entrance: Feralas 61, 30)." },
},
},
{
id = "gnomer", name = "Gnomeregan (Workshop Shortcut)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_08",
steps = {
{ type = "level", level = 24, name = "Reach Level 24", icon = ICON_LEVEL },
{ type = "quest", id = 2904, name = "Grime-Encrusted Ring", icon = ICON_QUEST,
desc = "Drop-quest item off Gnomeregan mobs; leads into 'Return to Marvon'.",
start = "Loot Grime-Encrusted Ring inside Gnomeregan (Dun Morogh 25, 40)." },
{ type = "quest", id = 2905, name = "Return to Marvon", icon = ICON_QUEST,
desc = "Rewards the Workshop Key for skipping Grubbis.",
start = "Marvon Rivetseeker, Steamwheedle Port camp, Tanaris (66, 22)." },
{ type = "item", id = 9240, name = "Workshop Key", icon = ICON_KEY,
desc = "Opens the shortcut door in Gnomeregan bypassing the Grubbis wing.",
start = "Reward from 'Return to Marvon'." },
{ type = "quest", id = 2945, name = "Grime-Encrusted Ring", icon = ICON_QUEST,
desc = "Loot a Grime-Encrusted Ring off Dark Iron mobs inside Gnomeregan and clean it in the Sparklematic 5200 (Tinker Town, Ironforge or the Gnomeregan Sparklematic). Cleaning it produces a Workshop Key.",
start = "Loot Grime-Encrusted Ring from Dark Iron dwarves inside Gnomeregan (entrance: Dun Morogh 25, 40). Clean it at any Sparklematic 5200 (Tinker Town, Ironforge)." },
{ type = "item", id = 6893, name = "Workshop Key", icon = ICON_KEY,
desc = "Opens the Workshop shortcut door in Gnomeregan, letting you skip most of the trash on the way to Mekgineer Thermaplugg.",
start = "Reward for cleaning the Grime-Encrusted Ring at the Sparklematic 5200 (Tinker Town, Ironforge, or inside Gnomeregan entrance Dun Morogh 25, 40)." },
},
},
{
id = "mara", name = "Maraudon (Portal Shortcut)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Idol_02",
@@ -417,27 +448,95 @@ RelationshipsAttune_Data = {
{ type = "level", level = 40, name = "Reach Level 40", icon = ICON_LEVEL },
{ type = "quest", id = 7064, name = "Legends of Maraudon", icon = ICON_QUEST,
desc = "Prereq for the Scepter of Celebras.",
start = "Celebras the Redeemed, freed on the Orange side of Maraudon after the vine tunnel." },
start = "Celebras the Redeemed, freed on the Orange side of Maraudon after the vine tunnel (Maraudon entrance: Desolace 29, 63)." },
{ type = "quest", id = 7065, name = "The Scepter of Celebras", icon = ICON_QUEST,
desc = "Rewards Scepter of Celebras (teleport into inner Maraudon).",
start = "Celebras the Redeemed, Maraudon (Orange side)." },
start = "Celebras the Redeemed, Maraudon Orange side (entrance: Desolace 29, 63)." },
{ type = "item", id = 17191, name = "Scepter of Celebras", icon = ICON_KEY,
desc = "Teleports directly to the Princess wing of Maraudon.",
start = "Reward from 'The Scepter of Celebras'." },
start = "Reward from 'The Scepter of Celebras' (Maraudon entrance: Desolace 29, 63)." },
},
},
{
id = "st", name = "Sunken Temple (Jammal'an)", category = "Keys & Access", faction = "Both",
id = "st", name = "Sunken Temple (Atal'ai + Jammal'an)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Idol_03",
steps = {
{ type = "level", level = 50, name = "Reach Level 50", icon = ICON_LEVEL },
{ type = "quest", id = 3373, name = "The Ancient Egg / Jammal'an the Prophet", icon = ICON_QUEST,
desc = "Activates the six-statue puzzle so Jammal'an can be summoned.",
start = "Yeh'kinya, Steamwheedle Port, Tanaris (66, 22). Sunken Temple: Swamp of Sorrows (69, 53)." },
{ type = "quest", id = 3373, name = "The Ancient Egg (Yeh'kinya intro)", icon = ICON_QUEST,
desc = "Long chain leading to Hakkar's summoning ritual; obtains the Ancient Egg from the pool at the bottom of Sunken Temple.",
start = "Yeh'kinya, Steamwheedle Port, Tanaris (66, 22)." },
{ type = "quest", id = 3380, name = "The Atal'ai Exile", icon = ICON_QUEST,
desc = "Prereq for the raid form; introduces you to Atal'alarion / Jammal'an's followers.",
start = "Al'tabim the All-Seeing, Marshal's Refuge, Un'Goro Crater (44, 6)." },
{ type = "quest", id = 3441, name = "Screecher Spirits", icon = ICON_QUEST,
desc = "Kills for Atal'ai Screechers around Sunken Temple; part of the Hakkar summoning chain.",
start = "Fel'zerul, Stonard, Swamp of Sorrows (46, 55)." },
{ type = "quest", id = 3446, name = "Into the Depths / Jammal'an", icon = ICON_QUEST, final = true,
desc = "Activate the six statues around the central pit in Sunken Temple to summon Jammal'an the Prophet; no key required, but the puzzle must be solved (kill six Atal'ai Defenders in the correct order).",
start = "Fel'zerul, Stonard, Swamp of Sorrows (46, 55) - Horde / Brohann Caskbelly, Hall of Explorers, Ironforge (76, 12) - Alliance. Sunken Temple entrance: Swamp of Sorrows (69, 53)." },
},
},
{
id = "zf", name = "Zul'Farrak (Sacred Mallet)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Hammer_16",
steps = {
{ type = "level", level = 45, name = "Reach Level 45", icon = ICON_LEVEL },
{ type = "item", id = 9241, name = "Sacred Mallet", icon = ICON_KEY,
desc = "No quest required. Fight your way to the top of the Altar of Zul in the Hinterlands (Vilebranch troll city Jintha'Alor) and loot the Sacred Mallet from the pedestal at the summit.",
start = "Top of the Altar of Zul, Jintha'Alor, Hinterlands (~63, 74). The whole hill is heavily patrolled by level 46-50 Vilebranch trolls." },
{ type = "item", id = 9240, name = "Mallet of Zul'Farrak", icon = ICON_KEY, final = true,
desc = "Right-click the Sacred Mallet while standing on the Altar of the Storms (the small square platform south of the Altar of Zul) to transform it into the Mallet of Zul'Farrak. Ring the gong in the Gahz'rilla arena inside Zul'Farrak to summon the boss.",
start = "Altar of the Storms, Hinterlands (~59, 62), while carrying the Sacred Mallet. Zul'Farrak entrance: Tanaris (39, 20)." },
},
},
{
id = "sm_cath", name = "Scarlet Monastery (Cathedral)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_02",
steps = {
{ type = "level", level = 35, name = "Reach Level 35", icon = ICON_LEVEL },
{ type = "item", id = 7146, name = "Scarlet Key", icon = ICON_KEY, final = true,
desc = "Opens the front doors of the Scarlet Monastery Armory, Cathedral and Graveyard wings. NOT a quest reward: the key is looted from a small chest ('Ill-Fated Chest') behind Arcanist Doan at the end of the Library wing, so run Library first. Rogues can also pick these doors around 175 lockpicking.",
start = "Ill-Fated Chest behind Arcanist Doan, end of the Library wing, Scarlet Monastery, Tirisfal Glades (85, 32)." },
},
},
{
id = "sgorge", name = "Key to Searing Gorge", category = "Keys & Access", faction = "Alliance",
icon = "Interface\\Icons\\INV_Misc_Key_14",
steps = {
{ type = "level", level = 43, name = "Reach Level 43", icon = ICON_LEVEL,
desc = "Minimum recommended level to survive the trip into south-east Searing Gorge." },
{ type = "quest", id = 3181, faction = "Alliance",
name = "The Horn of the Beast", icon = ICON_QUEST,
desc = "Travel through the Badlands into Searing Gorge, slay Margol the Rager (level 48 elite Stegodon in the south-east corner of Searing Gorge), and loot Margol's Gigantic Horn. Return it to Mountaineer Pebblebitty.",
start = "Mountaineer Pebblebitty, Stonewrought Pass gate, southern Loch Modan (33, 51). Margol: south-east Searing Gorge (~78, 70)." },
{ type = "quest", id = 3182, faction = "Alliance",
name = "Proof of Deed", icon = ICON_QUEST,
desc = "Pebblebitty doesn't believe the horn is real. Take Margol's Gigantic Horn to Curator Thorius in the Ironforge museum (Hall of Explorers) for authentication.",
start = "Mountaineer Pebblebitty, Stonewrought Pass gate, southern Loch Modan (33, 51). Curator Thorius: Hall of Explorers, Ironforge (73, 10)." },
{ type = "quest", id = 3201, faction = "Alliance",
name = "At Last!", icon = ICON_QUEST,
desc = "Return to Mountaineer Pebblebitty with the Proof of Deed to receive the Key to Searing Gorge.",
start = "Curator Thorius, Hall of Explorers, Ironforge (73, 10). Pebblebitty: Stonewrought Pass, southern Loch Modan (33, 51)." },
{ type = "item", id = 5396, name = "Key to Searing Gorge", icon = ICON_KEY, final = true,
desc = "Opens the Stonewrought Pass gate between Loch Modan and Searing Gorge. Horde do not need a key - they reach Searing Gorge via the Kargath / Badlands back road.",
start = "Reward from 'At Last!' handed in to Mountaineer Pebblebitty, Stonewrought Pass gate, southern Loch Modan (33, 51)." },
},
},
{
id = "uldaman", name = "Uldaman (Discs of Norgannon)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Gem_Diamond_01",
steps = {
{ type = "level", level = 40, name = "Reach Level 40", icon = ICON_LEVEL },
{ type = "quest", id = 1139, faction = "Alliance",
name = "The Lost Tablets of Will", icon = ICON_QUEST,
desc = "Alliance prereq that leads to the Discs of Norgannon and spawning Archaedas. Fetch the Tablet of Will from inside Uldaman for Advisor Belgrum. Part of the longer 'Passing Word of a Threat' -> 'An Ambassador of Evil' -> 'The Lost Tablets of Will' -> Discs chain.",
start = "Advisor Belgrum, Great Forge, Ironforge (55, 46). Uldaman entrance: Badlands (42, 20)." },
{ type = "quest", id = 2418, faction = "Both",
name = "The Platinum Discs", icon = ICON_QUEST, final = true,
desc = "Interact with the Discs of Norgannon inside the Chamber of Khaz'mul (deepest room in Uldaman) to spawn Archaedas. Uldaman itself is open to everyone - no attunement is required to enter, only to finish the disc/Archaedas storyline.",
start = "Discs of Norgannon, Chamber of Khaz'mul, Uldaman, Badlands (42, 20)." },
},
},
{
id = "hydraxian", name = "Hydraxian Waterlords (MC Runes)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\Spell_Frost_SummonWaterElemental",
@@ -449,143 +548,89 @@ RelationshipsAttune_Data = {
start = "Duke Hydraxis, small island off south-east Azshara (79, 76). Turn in water elemental drops (Azshara/Silithus) and MC boss items." },
},
},
{
id = "sm_cath", name = "Scarlet Monastery (Cathedral)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_02",
steps = {
{ type = "level", level = 35, name = "Reach Level 35", icon = ICON_LEVEL },
{ type = "quest", id = 1050, name = "Clear the Scarlet Monastery Library", icon = ICON_QUEST,
desc = "Clear the Library wing and loot the small chest behind the final boss to obtain the Scarlet Key.",
start = "Scarlet Monastery Library wing entrance, Tirisfal Glades (85, 32)." },
{ type = "item", id = 7146, name = "Scarlet Key", icon = ICON_KEY,
desc = "Opens the front doors to the Scarlet Monastery Cathedral wing.",
start = "Found in a small loot chest behind Arcanist Doan at the end of the Library wing (not a boss drop)." },
},
},
{
id = "brd_prison", name = "BRD Prison Cell Key", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Key_05",
steps = {
{ type = "level", level = 52, name = "Reach Level 52", icon = ICON_LEVEL },
{ type = "item", id = 11266, name = "Prison Cell Key", icon = ICON_KEY,
desc = "Unlocks the Detention Block cells in Blackrock Depths (frees Marshal Windsor, Dughal, Kharan, etc).",
start = "Drops from Warder Stilgiss in the Detention Block, Blackrock Depths." },
},
},
{
id = "sgorge", name = "Searing Gorge Access", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Gem_Ruby_02",
steps = {
{ type = "level", level = 45, name = "Reach Level 45", icon = ICON_LEVEL },
{ type = "quest", id = 3441, faction = "Alliance",
name = "A Bindings Blockade (Alliance)", icon = ICON_QUEST,
desc = "Opens the Thorium Brotherhood gate from Loch Modan into Searing Gorge.",
start = "Prospector Stormpike, The Military Ward, Ironforge." },
{ type = "quest", id = 3701, faction = "Horde",
name = "The Flame's Casing (Horde)", icon = ICON_QUEST,
desc = "Rewards Horde access through the Thorium Brotherhood gate into Searing Gorge.",
start = "Krakle, Kargath, Badlands (3, 45)." },
},
},
{
id = "uldaman", name = "Uldaman (Discs of Norgannon)", category = "Keys & Access", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Gem_Diamond_01",
steps = {
{ type = "level", level = 40, name = "Reach Level 40", icon = ICON_LEVEL },
{ type = "quest", id = 2278, name = "The Lost Tablets of Will", icon = ICON_QUEST,
desc = "Prereq to activating the Discs of Norgannon so Archaedas can be reached.",
start = "Alliance: Advisor Belgrum, Ironforge. Horde: Rigglefuzz, Hillsbrad Foothills." },
{ type = "quest", id = 2418, name = "The Platinum Discs", icon = ICON_QUEST,
desc = "Interact with the Discs of Norgannon inside the Chamber of Khaz'mul to spawn Archaedas.",
start = "Uldaman, Badlands (42, 20)." },
},
},
----------------------------------------------------------------
-- TURTLE / OCTO WOW CUSTOM CONTENT
-- Placeholder ids; replace once your server confirms them.
-- Placeholder ids where the live client id isn't confirmed; the
-- scanner also matches by tooltip name so keys are still credited.
----------------------------------------------------------------
{
id = "kara10", name = "Karazhan Crypt (10)", category = "Turtle", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Gem_Sapphire_02",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "quest", id = 40001, name = "TODO: Crypt attunement quest", icon = ICON_QUEST,
desc = "Custom Turtle attunement chain for Karazhan Crypt (10-man).",
start = "Koren the Seeker, Morgan's Plot camp, Deadwind Pass (40, 75)." },
{ type = "item", id = 60001, name = "TODO: Crypt Key", icon = ICON_KEY,
desc = "Key required to enter the crypt beneath Karazhan.",
start = "Awarded from Koren the Seeker after completing the Karazhan Crypt attunement chain." },
{ type = "quest", id = 40001, name = "Karazhan Crypt attunement (Koren)", icon = ICON_QUEST, final = true,
desc = "Custom Turtle attunement chain for Karazhan Crypt (10-man). Follow the chain from Koren the Seeker in Deadwind Pass; involves clearing the outer crypt trash and delivering an item to the Alturus circle at Karazhan.",
start = "Koren the Seeker, Morgan's Plot camp, Deadwind Pass (40, 75). Karazhan: Deadwind Pass (47, 75)." },
{ type = "item", id = 60001, name = "Karazhan Crypt Key", icon = ICON_KEY,
desc = "Key required to enter the crypt beneath Karazhan (10-man). Matches by tooltip name if the numeric id differs on your build.",
start = "Awarded from Koren the Seeker (Morgan's Plot, Deadwind Pass 40, 75) after completing the Karazhan Crypt attunement chain." },
},
},
{
id = "kara40", name = "Lower Karazhan Halls (40)", category = "Turtle", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Gem_Sapphire_01",
steps = {
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
{ type = "quest", id = 40010, name = "TODO: LKH attunement", icon = ICON_QUEST,
desc = "Custom Turtle attunement chain for Lower Karazhan Halls (40-man).",
start = "Archmage Alturus, Morgan's Plot camp, Deadwind Pass (40, 75)." },
{ type = "item", id = 60010, name = "TODO: LKH Key", icon = ICON_KEY,
desc = "40-man Karazhan key.",
start = "Awarded from Archmage Alturus at the end of the LKH attunement." },
{ type = "quest", id = 40010, name = "Lower Karazhan Halls attunement", icon = ICON_QUEST, final = true,
desc = "Custom Turtle attunement chain for Lower Karazhan Halls (40-man). Alturus / Kamsis at Karazhan will guide you through several steps culminating in the Master's Key.",
start = "Archmage Alturus, Morgan's Plot camp, Deadwind Pass (40, 75). Karazhan: Deadwind Pass (47, 75)." },
{ type = "item", id = 60010, name = "Master's Key (LKH)", icon = ICON_KEY,
desc = "40-man Karazhan raid key. Matches by tooltip name if the numeric id differs on your build.",
start = "Awarded from Archmage Alturus (Morgan's Plot, Deadwind Pass 40, 75) at the end of the LKH attunement." },
},
},
{
id = "es", name = "Emerald Sanctum", category = "Turtle", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Head_Dragon_Green",
steps = {
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
{ type = "quest", id = 40020, name = "TODO: ES attunement", icon = ICON_QUEST,
desc = "Emerald Sanctum attunement chain (Hinterlands portal).",
{ type = "quest", id = 40020, name = "Emerald Sanctum attunement", icon = ICON_QUEST, final = true,
desc = "Emerald Sanctum attunement chain (Hinterlands portal). Speak with Keeper Remulos and collect the Sanctum Sigil from the four green dragons around Azeroth (Ysondre, Emeriss, Lethon, Taerar).",
start = "Keeper Remulos avatar, eastern Hinterlands near Seradane (55, 22)." },
},
},
{
id = "cgrove", name = "Crescent Grove (Turtle 20-man)", category = "Turtle", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Herb_02",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "quest", id = 40100, name = "Crescent Grove attunement", icon = ICON_QUEST, final = true,
desc = "Turtle-WoW 20-man Emerald-themed raid in Ashenvale. Speak to the druid representative at the grove entrance to start the chain (collect corrupted samples inside the outer ring).",
start = "Ashenvale, near the Crescent Grove portal south of Warsong Lumber Camp (~40, 63)." },
},
},
{
id = "gilneas", name = "Gilneas City", category = "Turtle", faction = "Both",
icon = "Interface\\Icons\\Ability_Mount_WhiteDireWolf",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "quest", id = 40030, name = "TODO: Gilneas attunement", icon = ICON_QUEST,
desc = "Attunement for the Gilneas City dungeon.",
{ type = "quest", id = 40030, name = "Gilneas City attunement", icon = ICON_QUEST, final = true,
desc = "Attunement for the Gilneas City dungeon. Speak with Lord Darius Crowley at the Greymane Wall and complete the intro quest chain in Silverpine.",
start = "Lord Darius Crowley, Greymane Wall entrance, southern Silverpine Forest (43, 66)." },
},
},
{
id = "hateforge", name = "Hateforge Quarry", category = "Turtle", faction = "Both",
icon = "Interface\\Icons\\INV_Hammer_16",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "quest", id = 40040, name = "TODO: Hateforge attunement", icon = ICON_QUEST,
desc = "Attunement for the Hateforge Quarry dungeon.",
{ type = "quest", id = 40040, name = "Hateforge Quarry attunement", icon = ICON_QUEST, final = true,
desc = "Attunement for the Hateforge Quarry dungeon. Turtle Dark Iron chain out of Burning Steppes.",
start = "Overseer Maltorius, Flame Crest camp, northern Burning Steppes (62, 24)." },
},
},
{
id = "stormwind_vault", name = "Stormwind Vault", category = "Turtle", faction = "Both",
icon = "Interface\\Icons\\INV_Misc_Coin_01",
steps = {
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
{ type = "quest", id = 40050, name = "TODO: SW Vault attunement", icon = ICON_QUEST,
desc = "Attunement for the Stormwind Vault dungeon.",
start = "Warden Thelwater, Stormwind Stockade entrance, Mage Quarter, Stormwind City (50, 68)." },
{ type = "quest", id = 40050, name = "Stormwind Vault attunement", icon = ICON_QUEST, final = true,
desc = "Attunement for the Stormwind Vault dungeon (Turtle). Alliance intro from the Stockade warden; Horde variant from a SI:7 defector in Booty Bay.",
start = "Warden Thelwater, Stormwind Stockade entrance, Mage Quarter, Stormwind City (50, 68). Horde variant: Booty Bay, Stranglethorn (27, 77)." },
},
},
----------------------------------------------------------------
-- DRAGONMAW RETREAT (Turtle/Octo custom, Wetlands, patch 1.18)
-- Key: "Lower Reserve Key". The scanner also identifies keyring
-- items by tooltip name, so this works even if the live client
-- assigns a different numeric id than the placeholder below.
----------------------------------------------------------------
{
id = "dmr", name = "Dragonmaw Retreat", category = "Turtle", faction = "Both",
@@ -593,36 +638,32 @@ RelationshipsAttune_Data = {
steps = {
{ type = "level", level = 25, name = "Reach Level 25", icon = ICON_LEVEL,
desc = "Minimum level to enter Dragonmaw Retreat." },
{ type = "quest", id = 41810, faction = "Alliance",
name = "To Crush The Dragonmaw", icon = ICON_QUEST,
desc = "Alliance intro quest for Dragonmaw Retreat.",
start = "Captain Stoutfist, Menethil Harbor, Wetlands." },
start = "Captain Stoutfist, Menethil Harbor, Wetlands (10, 58)." },
{ type = "quest", id = 41811, faction = "Alliance",
name = "Blackheart's Demise", icon = ICON_QUEST,
desc = "Alliance follow-up to slay Overlord Blackheart inside the dungeon.",
start = "Captain Stoutfist, Menethil Harbor, Wetlands." },
start = "Captain Stoutfist, Menethil Harbor, Wetlands (10, 58)." },
{ type = "quest", id = 41820, faction = "Horde",
name = "Cavernweb Extract", icon = ICON_QUEST,
desc = "Horde intro quest collect spider extract inside Dragonmaw Retreat.",
start = "Okul, Hammerfall, Arathi Highlands." },
desc = "Horde intro quest - collect spider extract inside Dragonmaw Retreat.",
start = "Okul, Hammerfall, Arathi Highlands (73, 33)." },
{ type = "quest", id = 41821, faction = "Horde",
name = "A Blaze Unending", icon = ICON_QUEST,
desc = "Horde follow-up in Dragonmaw Retreat.",
start = "Shara Blazen, Tarren Mill, Hillsbrad Foothills." },
start = "Shara Blazen, Tarren Mill, Hillsbrad Foothills (60, 20)." },
{ type = "quest", id = 41830, name = "Gowlfang's Defeat", icon = ICON_QUEST,
desc = "Neutral quest defeat the gnoll leader Gowlfang.",
start = "Grimbite, Green Belt gnoll camp, central Wetlands." },
desc = "Neutral quest - defeat the gnoll leader Gowlfang.",
start = "Grimbite, Green Belt gnoll camp, central Wetlands (~46, 50)." },
{ type = "quest", id = 41831, name = "The Dragonmaw Brood", icon = ICON_QUEST,
desc = "Neutral quest cull the drakes and whelps inside the retreat.",
start = "Nidiszanz, Dragonmaw Gates, Wetlands." },
desc = "Neutral quest - cull the drakes and whelps inside the retreat.",
start = "Nidiszanz, Dragonmaw Gates, Wetlands (~70, 40)." },
{ type = "item", id = 61810, name = "Lower Reserve Key",
icon = ICON_KEY, final = true,
desc = "Opens the gates of Dragonmaw Retreat / Dragonmaw Reserve in the Wetlands.",
start = "Looted from Dragonmaw guards in the Dragonmaw Reserve outpost, Wetlands." },
start = "Looted from Dragonmaw guards in the Dragonmaw Reserve outpost, Wetlands (~70, 40)." },
},
},
}
+14 -2
View File
@@ -66,8 +66,12 @@ end
function MM:Create()
if getglobal(BTN_NAME) then return getglobal(BTN_NAME) end
-- Parent to UIParent so we're not clipped to the minimap area.
local btn = CreateFrame("Button", BTN_NAME, UIParent)
-- Parent to Minimap so button-collector addons (MinimapButtonBag /
-- MBB, and similar) can discover and manage this button the same way
-- they discover Blizzard's built-in minimap buttons. SetPoint still
-- anchors to UIParent CENTER so the button can be dragged anywhere
-- on screen -- the anchor frame is independent of the parent frame.
local btn = CreateFrame("Button", BTN_NAME, Minimap)
btn:SetWidth(31); btn:SetHeight(31)
btn:SetFrameStrata("MEDIUM")
btn:SetFrameLevel(8)
@@ -75,6 +79,12 @@ function MM:Create()
btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
btn:RegisterForDrag("LeftButton", "RightButton")
btn:SetMovable(true)
-- Allow the button to sit off-screen (via /attune pos or /attune offscreen)
-- while remaining discoverable by MinimapButtonBag.
if btn.SetClampedToScreen then btn:SetClampedToScreen(false) end
-- MBB-friendly highlight so the button visually matches other
-- minimap buttons once it has been swept into the bag.
btn:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
-- Round border ring (standard minimap-button look)
local overlay = btn:CreateTexture(nil, "OVERLAY")
@@ -89,6 +99,7 @@ function MM:Create()
icon:SetPoint("TOPLEFT", btn, "TOPLEFT", 7, -6)
btn.icon = icon
btn:SetScript("OnClick", function()
if RA.UI and RA.UI.Toggle then RA.UI:Toggle() end
end)
@@ -107,6 +118,7 @@ function MM:Create()
GameTooltip:AddLine("Relationships Attune", 1, 0.82, 0)
GameTooltip:AddLine("Left-click: open / close window", 0.9, 0.9, 0.9)
GameTooltip:AddLine("Drag: move anywhere on screen", 0.9, 0.9, 0.9)
GameTooltip:AddLine("/attune offscreen - park off-screen (MBB safe)", 0.6, 0.8, 1)
GameTooltip:AddLine("/attune hide - hide this button", 0.6, 0.8, 1)
GameTooltip:Show()
end)
+1 -1
View File
@@ -1,4 +1,4 @@
<img src="https://cdn.discordapp.com/attachments/1510333697277300856/1524819837270884362/kkk.gif?ex=6a5122a2&is=6a4fd122&hm=b82d19b995b2d1f8b252fcbaf44dcaa7b5f30255fb1401f50f931919c980a4ce&"/>
<img src="https://cdn.discordapp.com/attachments/1158418666883395656/1526959667941474304/v.png?ex=6a58eb82&is=6a579a02&hm=dbc8525f4040f4cc7d276f22c3a8ecce16a4930bdf168676d7075e116097b8e2&"/>
# RelationshipsAttune
+1 -1
View File
@@ -2,7 +2,7 @@
## Title: Relationships Attune
## Notes: Track Vanilla and Turtle/Octo WoW attunement progress
## Author: Relationship
## Version: 1.0
## Version: 1.6
## X-Category: Quest
## SavedVariables: RelationshipsAttuneDB
## SavedVariablesPerCharacter: RelationshipsAttuneCharDB
+6
View File
@@ -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)