Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ccfb78c3a6 | |||
| 9cdcc1814f | |||
| 0c9af0e9d2 | |||
| 8f4480bf14 | |||
| a276cca444 | |||
| 4502a1db7e | |||
| fda04907c2 | |||
| e95e65fca5 | |||
| 044b6593ec | |||
| fbb3e94b93 | |||
| cca57c7adc | |||
| c1c1741b6e | |||
| 9669809096 | |||
| 04f87e5b42 |
@@ -6,7 +6,7 @@ RelationshipsAttune = RelationshipsAttune or {}
|
|||||||
local RA = RelationshipsAttune
|
local RA = RelationshipsAttune
|
||||||
local L = RelationshipsAttune_L
|
local L = RelationshipsAttune_L
|
||||||
|
|
||||||
RA.VERSION = "1.2.7"
|
RA.VERSION = "1.4.3"
|
||||||
RA.COMM_PREFIX = "RATTUNE"
|
RA.COMM_PREFIX = "RATTUNE"
|
||||||
|
|
||||||
RA.playerName = nil
|
RA.playerName = nil
|
||||||
@@ -58,7 +58,7 @@ function RA:InitDB()
|
|||||||
end
|
end
|
||||||
local o = RelationshipsAttuneDB.options
|
local o = RelationshipsAttuneDB.options
|
||||||
if o.autoShare == nil then o.autoShare = true end
|
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.minimapAngle) ~= "number" then o.minimapAngle = 200 end
|
||||||
if type(o.minimapRadius) ~= "number" then o.minimapRadius = 80 end
|
if type(o.minimapRadius) ~= "number" then o.minimapRadius = 80 end
|
||||||
if o.minimapHide == nil then o.minimapHide = false end
|
if o.minimapHide == nil then o.minimapHide = false end
|
||||||
@@ -67,31 +67,123 @@ function RA:InitDB()
|
|||||||
if not RelationshipsAttuneCharDB.quests then RelationshipsAttuneCharDB.quests = {} end
|
if not RelationshipsAttuneCharDB.quests then RelationshipsAttuneCharDB.quests = {} end
|
||||||
if not RelationshipsAttuneCharDB.items then RelationshipsAttuneCharDB.items = {} end
|
if not RelationshipsAttuneCharDB.items then RelationshipsAttuneCharDB.items = {} end
|
||||||
if not RelationshipsAttuneCharDB.completedAttunements then RelationshipsAttuneCharDB.completedAttunements = {} 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.progress then RelationshipsAttuneCharDB.progress = {} end
|
||||||
if not RelationshipsAttuneCharDB.expanded then RelationshipsAttuneCharDB.expanded = {} end
|
if not RelationshipsAttuneCharDB.expanded then RelationshipsAttuneCharDB.expanded = {} end
|
||||||
|
if not RelationshipsAttuneCharDB.forcedSteps then RelationshipsAttuneCharDB.forcedSteps = {} end
|
||||||
|
if not RelationshipsAttuneCharDB.forcedAtt then RelationshipsAttuneCharDB.forcedAtt = {} end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- Force-complete (manual override) helpers
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
function RA:IsStepForced(attId, i)
|
||||||
|
local t = RelationshipsAttuneCharDB.forcedSteps
|
||||||
|
return t and t[attId] and t[attId][i] == true
|
||||||
|
end
|
||||||
|
|
||||||
|
function RA:SetStepForced(attId, i, v)
|
||||||
|
if not attId or not i then return end
|
||||||
|
local t = RelationshipsAttuneCharDB.forcedSteps
|
||||||
|
if not t then RelationshipsAttuneCharDB.forcedSteps = {}; t = RelationshipsAttuneCharDB.forcedSteps end
|
||||||
|
if not t[attId] then t[attId] = {} end
|
||||||
|
if v then t[attId][i] = true else t[attId][i] = nil end
|
||||||
|
self:RecomputeAll()
|
||||||
|
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
|
||||||
|
end
|
||||||
|
|
||||||
|
function RA:IsAttForced(attId)
|
||||||
|
local t = RelationshipsAttuneCharDB.forcedAtt
|
||||||
|
return t and t[attId] == true
|
||||||
|
end
|
||||||
|
|
||||||
|
function RA:SetAttForced(attId, v)
|
||||||
|
if not attId then return end
|
||||||
|
if not RelationshipsAttuneCharDB.forcedAtt then
|
||||||
|
RelationshipsAttuneCharDB.forcedAtt = {}
|
||||||
|
end
|
||||||
|
if not RelationshipsAttuneCharDB.completedAttunements then
|
||||||
|
RelationshipsAttuneCharDB.completedAttunements = {}
|
||||||
|
end
|
||||||
|
if v then
|
||||||
|
RelationshipsAttuneCharDB.forcedAtt[attId] = true
|
||||||
|
RelationshipsAttuneCharDB.completedAttunements[attId] = true
|
||||||
|
else
|
||||||
|
RelationshipsAttuneCharDB.forcedAtt[attId] = nil
|
||||||
|
RelationshipsAttuneCharDB.completedAttunements[attId] = nil
|
||||||
|
if RelationshipsAttuneCharDB.forcedSteps then
|
||||||
|
RelationshipsAttuneCharDB.forcedSteps[attId] = nil
|
||||||
|
end
|
||||||
|
if RelationshipsAttuneCharDB.announced then
|
||||||
|
RelationshipsAttuneCharDB.announced[attId] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:RecomputeAll()
|
||||||
|
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ---------------------------------------------------------------
|
-- ---------------------------------------------------------------
|
||||||
-- Quest log scan (vanilla API)
|
-- 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()
|
function RA:ScanQuestLog()
|
||||||
if not GetNumQuestLogEntries then return end
|
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()
|
local numEntries = GetNumQuestLogEntries()
|
||||||
for i = 1, numEntries do
|
for i = 1, numEntries do
|
||||||
local title, level, tag, isHeader, _, isComplete, _, questId =
|
local ok, title, level, tag, isHeader, _, isComplete, _, questId =
|
||||||
GetQuestLogTitle(i)
|
pcall(GetQuestLogTitle, i)
|
||||||
if (not isHeader) and questId then
|
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
|
if isComplete and isComplete == 1 then
|
||||||
RelationshipsAttuneCharDB.quests[questId] = "complete"
|
RelationshipsAttuneCharDB.quests[qid] = "complete"
|
||||||
else
|
else
|
||||||
if not RelationshipsAttuneCharDB.quests[questId] then
|
RelationshipsAttuneCharDB.quests[qid] = "inlog"
|
||||||
RelationshipsAttuneCharDB.quests[questId] = "inlog"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
|
|
||||||
function RA:MarkQuestTurnedIn(questId)
|
function RA:MarkQuestTurnedIn(questId)
|
||||||
if not questId then return end
|
if not questId then return end
|
||||||
RelationshipsAttuneCharDB.quests[questId] = "turnedin"
|
RelationshipsAttuneCharDB.quests[questId] = "turnedin"
|
||||||
@@ -112,11 +204,6 @@ local function rememberItemLink(link)
|
|||||||
end
|
end
|
||||||
-- Resolve by name so a custom Turtle/Octo item whose live client id
|
-- Resolve by name so a custom Turtle/Octo item whose live client id
|
||||||
-- differs from the id declared in Data.lua still gets credited.
|
-- 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
|
local resolvedName
|
||||||
if GetItemInfo then
|
if GetItemInfo then
|
||||||
local ok, n = pcall(GetItemInfo, link)
|
local ok, n = pcall(GetItemInfo, link)
|
||||||
@@ -148,22 +235,41 @@ end
|
|||||||
-- for them (a known 1.12 / Turtle / Octo quirk for keyring slots).
|
-- for them (a known 1.12 / Turtle / Octo quirk for keyring slots).
|
||||||
RA._nameToId = nil
|
RA._nameToId = nil
|
||||||
function RA:BuildNameIndex()
|
function RA:BuildNameIndex()
|
||||||
if RA._nameToId then return RA._nameToId end
|
if RA._nameToId and RA._questNameToId then return RA._nameToId end
|
||||||
local map = {}
|
local map, qmap = {}, {}
|
||||||
if RelationshipsAttune_Data then
|
if RelationshipsAttune_Data then
|
||||||
for i = 1, table.getn(RelationshipsAttune_Data) do
|
for i = 1, table.getn(RelationshipsAttune_Data) do
|
||||||
local att = RelationshipsAttune_Data[i]
|
local att = RelationshipsAttune_Data[i]
|
||||||
if att and att.steps then
|
if att and att.steps then
|
||||||
for j = 1, table.getn(att.steps) do
|
for j = 1, table.getn(att.steps) do
|
||||||
local s = att.steps[j]
|
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
|
||||||
map[string.lower(s.name)] = s.id
|
local nlow = string.lower(s.name)
|
||||||
|
if s.type == "item" then
|
||||||
|
map[nlow] = s.id
|
||||||
|
elseif s.type == "quest" then
|
||||||
|
qmap[nlow] = s.id
|
||||||
|
-- Data.lua disambiguates faction-specific quests
|
||||||
|
-- with a "(Alliance)" / "(Horde)" suffix that
|
||||||
|
-- the in-game quest log does NOT include. Index
|
||||||
|
-- the stripped variant so the name fallback in
|
||||||
|
-- ScanQuestLog matches on stock 1.12 clients
|
||||||
|
-- that don't return a questId.
|
||||||
|
local _, _, stripped = string.find(nlow, "^(.-)%s*%(alliance%)%s*$")
|
||||||
|
if not stripped then
|
||||||
|
_, _, stripped = string.find(nlow, "^(.-)%s*%(horde%)%s*$")
|
||||||
|
end
|
||||||
|
if stripped and stripped ~= "" and not qmap[stripped] then
|
||||||
|
qmap[stripped] = s.id
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
RA._nameToId = map
|
RA._nameToId = map
|
||||||
|
RA._questNameToId = qmap
|
||||||
return map
|
return map
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -200,19 +306,10 @@ local function scanContainer(containerId)
|
|||||||
end
|
end
|
||||||
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)
|
local function scanKeyringContainer(bag)
|
||||||
if not GetContainerNumSlots then return end
|
if not GetContainerNumSlots then return end
|
||||||
local ok, slots = pcall(GetContainerNumSlots, bag)
|
local ok, slots = pcall(GetContainerNumSlots, bag)
|
||||||
if not ok or not slots then slots = 0 end
|
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
|
local probe = slots
|
||||||
if probe < 1 then probe = 32 end
|
if probe < 1 then probe = 32 end
|
||||||
|
|
||||||
@@ -224,13 +321,11 @@ local function scanKeyringContainer(bag)
|
|||||||
local setOk = false
|
local setOk = false
|
||||||
pcall(function() tip:SetBagItem(bag, slot); setOk = true end)
|
pcall(function() tip:SetBagItem(bag, slot); setOk = true end)
|
||||||
|
|
||||||
-- Path 1: link
|
|
||||||
local link
|
local link
|
||||||
local okL, l = pcall(GetContainerItemLink, bag, slot)
|
local okL, l = pcall(GetContainerItemLink, bag, slot)
|
||||||
if okL then link = l end
|
if okL then link = l end
|
||||||
if link then rememberItemLink(link) end
|
if link then rememberItemLink(link) end
|
||||||
|
|
||||||
-- Path 2: tooltip visible name (works even when link is nil).
|
|
||||||
if setOk then
|
if setOk then
|
||||||
local name = tipItemName()
|
local name = tipItemName()
|
||||||
if name and nameMap then
|
if name and nameMap then
|
||||||
@@ -239,11 +334,6 @@ local function scanKeyringContainer(bag)
|
|||||||
end
|
end
|
||||||
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
|
if GetContainerItemInfo then
|
||||||
pcall(GetContainerItemInfo, bag, slot)
|
pcall(GetContainerItemInfo, bag, slot)
|
||||||
end
|
end
|
||||||
@@ -251,11 +341,6 @@ local function scanKeyringContainer(bag)
|
|||||||
pcall(function() tip:Hide() end)
|
pcall(function() tip:Hide() end)
|
||||||
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()
|
function RA:WarmItemCache()
|
||||||
if not GetItemInfo or not RelationshipsAttune_Data then return end
|
if not GetItemInfo or not RelationshipsAttune_Data then return end
|
||||||
for i = 1, table.getn(RelationshipsAttune_Data) do
|
for i = 1, table.getn(RelationshipsAttune_Data) do
|
||||||
@@ -278,10 +363,6 @@ function RA:ScanBags()
|
|||||||
scanContainer(bag)
|
scanContainer(bag)
|
||||||
end
|
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 seen = {}
|
||||||
local function tryBag(b)
|
local function tryBag(b)
|
||||||
if b == nil or seen[b] then return end
|
if b == nil or seen[b] then return end
|
||||||
@@ -301,7 +382,6 @@ function RA:ScanBags()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Back-compat shim: older code paths may still call this.
|
|
||||||
function RA:ForceKeyringResolve()
|
function RA:ForceKeyringResolve()
|
||||||
scanKeyringContainer(-2)
|
scanKeyringContainer(-2)
|
||||||
end
|
end
|
||||||
@@ -325,43 +405,74 @@ end
|
|||||||
-- Compute attunement progress
|
-- Compute attunement progress
|
||||||
-- ---------------------------------------------------------------
|
-- ---------------------------------------------------------------
|
||||||
function RA:EvaluateStep(step)
|
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
|
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
|
elseif step.type == "quest" then
|
||||||
local st = RelationshipsAttuneCharDB.quests[step.id]
|
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
|
elseif step.type == "item" then
|
||||||
return RelationshipsAttuneCharDB.items[step.id] == true
|
return RelationshipsAttuneCharDB.items[step.id] == true, false
|
||||||
elseif step.type == "rep" then
|
elseif step.type == "rep" then
|
||||||
local need = DATA_STANDING_MAP[step.standing] or step.standing or 5
|
local need = DATA_STANDING_MAP[step.standing] or step.standing or 5
|
||||||
local have = self:GetReputationStanding(step.faction)
|
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
|
end
|
||||||
return false
|
return false, false
|
||||||
end
|
end
|
||||||
|
|
||||||
function RA:EvaluateAttunement(att)
|
function RA:EvaluateAttunement(att)
|
||||||
if att.faction and att.faction ~= "Both" and att.faction ~= RA.playerFaction then
|
if att.faction and att.faction ~= "Both" and att.faction ~= RA.playerFaction then
|
||||||
return { applicable = false, done = false, steps = {}, doneCount = 0, total = 0 }
|
return { applicable = false, done = false, steps = {}, doneCount = 0, total = 0 }
|
||||||
end
|
end
|
||||||
local steps, doneCount, total = {}, 0, 0
|
local steps, stepsInProgress, doneCount, total = {}, {}, 0, 0
|
||||||
local numSteps = table.getn(att.steps)
|
local numSteps = table.getn(att.steps)
|
||||||
for i = 1, numSteps do
|
for i = 1, numSteps do
|
||||||
local step = att.steps[i]
|
local step = att.steps[i]
|
||||||
if self:StepApplies(step) then
|
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
|
steps[i] = ok
|
||||||
|
stepsInProgress[i] = (not ok) and (ipVal and true or false) or false
|
||||||
total = total + 1
|
total = total + 1
|
||||||
if ok then doneCount = doneCount + 1 end
|
if ok then doneCount = doneCount + 1 end
|
||||||
else
|
else
|
||||||
steps[i] = nil
|
steps[i] = nil
|
||||||
|
stepsInProgress[i] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Short-circuit: if the player already owns the final key/item (or a step
|
-- Apply per-step forced completions (manual overrides from the UI).
|
||||||
-- explicitly flagged final=true) then the entire attunement is done, even
|
-- These are treated exactly like a real completion for tracking purposes.
|
||||||
-- if earlier bookkeeping steps (prereq quests, reputation) can no longer
|
local forced = RelationshipsAttuneCharDB.forcedSteps and RelationshipsAttuneCharDB.forcedSteps[att.id]
|
||||||
-- be detected on this character. This handles the case where the key was
|
if forced then
|
||||||
-- earned before the addon was installed.
|
for i = 1, numSteps do
|
||||||
|
local step = att.steps[i]
|
||||||
|
if step and self:StepApplies(step) and forced[i] and steps[i] == false then
|
||||||
|
steps[i] = true
|
||||||
|
stepsInProgress[i] = false
|
||||||
|
doneCount = doneCount + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 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
|
local finalIdx = nil
|
||||||
for i = numSteps, 1, -1 do
|
for i = numSteps, 1, -1 do
|
||||||
local step = att.steps[i]
|
local step = att.steps[i]
|
||||||
@@ -371,7 +482,6 @@ function RA:EvaluateAttunement(att)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not finalIdx then
|
if not finalIdx then
|
||||||
-- Fall back to the last applicable item step (typically the key).
|
|
||||||
for i = numSteps, 1, -1 do
|
for i = numSteps, 1, -1 do
|
||||||
local step = att.steps[i]
|
local step = att.steps[i]
|
||||||
if step.type == "item" and self:StepApplies(step) then
|
if step.type == "item" and self:StepApplies(step) then
|
||||||
@@ -381,8 +491,6 @@ function RA:EvaluateAttunement(att)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not finalIdx then
|
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
|
for i = numSteps, 1, -1 do
|
||||||
local step = att.steps[i]
|
local step = att.steps[i]
|
||||||
if self:StepApplies(step) then
|
if self:StepApplies(step) then
|
||||||
@@ -391,6 +499,34 @@ function RA:EvaluateAttunement(att)
|
|||||||
end
|
end
|
||||||
end
|
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]
|
local persistedDone = RelationshipsAttuneCharDB.completedAttunements and RelationshipsAttuneCharDB.completedAttunements[att.id]
|
||||||
if persistedDone or (finalIdx and steps[finalIdx] == true) then
|
if persistedDone or (finalIdx and steps[finalIdx] == true) then
|
||||||
for i = 1, numSteps do
|
for i = 1, numSteps do
|
||||||
@@ -407,15 +543,47 @@ function RA:EvaluateAttunement(att)
|
|||||||
applicable = true,
|
applicable = true,
|
||||||
done = (total > 0 and doneCount == total),
|
done = (total > 0 and doneCount == total),
|
||||||
steps = steps,
|
steps = steps,
|
||||||
|
stepsInProgress= stepsInProgress,
|
||||||
doneCount = doneCount,
|
doneCount = doneCount,
|
||||||
total = total,
|
total = total,
|
||||||
}
|
}
|
||||||
end
|
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()
|
function RA:RecomputeAll()
|
||||||
for i = 1, table.getn(RelationshipsAttune_Data) do
|
for i = 1, table.getn(RelationshipsAttune_Data) do
|
||||||
local att = RelationshipsAttune_Data[i]
|
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
|
end
|
||||||
RelationshipsAttuneDB.players[RA.playerKey] = {
|
RelationshipsAttuneDB.players[RA.playerKey] = {
|
||||||
name = RA.playerName,
|
name = RA.playerName,
|
||||||
@@ -433,21 +601,28 @@ end
|
|||||||
-- Throttled auto-scan
|
-- Throttled auto-scan
|
||||||
-- ---------------------------------------------------------------
|
-- ---------------------------------------------------------------
|
||||||
RA._throttle = 0
|
RA._throttle = 0
|
||||||
|
RA._periodic = 0
|
||||||
RA._dirty = false
|
RA._dirty = false
|
||||||
RA._minRescan = 2.0
|
RA._minRescan = 1.5
|
||||||
|
|
||||||
function RA:MarkDirty() RA._dirty = true end
|
function RA:MarkDirty() RA._dirty = true end
|
||||||
|
|
||||||
function RA:_OnUpdate(elapsed)
|
-- Full periodic rescan (quest log + bags + recompute + UI refresh).
|
||||||
RA._throttle = RA._throttle + (elapsed or 0)
|
function RA:AutoScan()
|
||||||
local interval = (RelationshipsAttuneDB and RelationshipsAttuneDB.options
|
RA:ScanQuestLog()
|
||||||
and RelationshipsAttuneDB.options.autoScanSeconds) or 20
|
RA:ScanBags()
|
||||||
if interval < 5 then interval = 5 end
|
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
|
if RA._retryAt and GetTime then
|
||||||
local now = GetTime()
|
local now = GetTime()
|
||||||
local pending = {}
|
local pending = {}
|
||||||
@@ -473,22 +648,22 @@ function RA:_OnUpdate(elapsed)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Event-driven rescan: something changed, catch up quickly.
|
||||||
if RA._dirty and RA._throttle >= RA._minRescan then
|
if RA._dirty and RA._throttle >= RA._minRescan then
|
||||||
RA._dirty = false
|
RA._dirty = false
|
||||||
RA._throttle = 0
|
RA._throttle = 0
|
||||||
RA:ScanQuestLog()
|
RA._periodic = 0
|
||||||
RA:ScanBags()
|
RA:AutoScan()
|
||||||
RA:RecomputeAll()
|
|
||||||
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
|
|
||||||
return
|
return
|
||||||
end
|
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._throttle = 0
|
||||||
RA:ScanQuestLog()
|
RA:AutoScan()
|
||||||
RA:ScanBags()
|
|
||||||
RA:RecomputeAll()
|
|
||||||
if RA.UI and RA.UI.Refresh then RA.UI:Refresh() end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -497,14 +672,12 @@ end
|
|||||||
-- ---------------------------------------------------------------
|
-- ---------------------------------------------------------------
|
||||||
local function slashHandler(msg)
|
local function slashHandler(msg)
|
||||||
msg = string.lower(msg or "")
|
msg = string.lower(msg or "")
|
||||||
-- trim
|
|
||||||
msg = string.gsub(msg, "^%s+", "")
|
msg = string.gsub(msg, "^%s+", "")
|
||||||
msg = string.gsub(msg, "%s+$", "")
|
msg = string.gsub(msg, "%s+$", "")
|
||||||
|
|
||||||
if msg == "show" then
|
if msg == "show" then
|
||||||
if RA.UI then RA.UI:Show() end
|
if RA.UI then RA.UI:Show() end
|
||||||
elseif msg == "hide" then
|
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
|
if RA.UI and RA.UI:IsShown() then
|
||||||
RA.UI:Hide()
|
RA.UI:Hide()
|
||||||
elseif RA.Minimap then
|
elseif RA.Minimap then
|
||||||
@@ -521,6 +694,34 @@ local function slashHandler(msg)
|
|||||||
print("Minimap button shown. Drag to reposition around the minimap.")
|
print("Minimap button shown. Drag to reposition around the minimap.")
|
||||||
end
|
end
|
||||||
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
|
elseif msg == "sync" then
|
||||||
if RA.Comm then RA.Comm:RequestSync() end
|
if RA.Comm then RA.Comm:RequestSync() end
|
||||||
print(L.MSG_SYNC_SENT)
|
print(L.MSG_SYNC_SENT)
|
||||||
@@ -563,13 +764,15 @@ local function slashHandler(msg)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
pcall(function() tip:Hide() end)
|
pcall(function() tip:Hide() end)
|
||||||
print("Scarlet Key (7146) owned: " .. tostring(RelationshipsAttuneCharDB.items[7146] == true))
|
|
||||||
elseif msg == "help" or msg == "?" then
|
elseif msg == "help" or msg == "?" then
|
||||||
print("Relationships Attune - commands:")
|
print("Relationships Attune - commands:")
|
||||||
print(" /attune - toggle the window")
|
print(" /attune - toggle the window")
|
||||||
print(" /attune show - open the window")
|
print(" /attune show - open the window")
|
||||||
print(" /attune hide - close the window (or hide the minimap button)")
|
print(" /attune hide - close the window (or hide the minimap button)")
|
||||||
print(" /attune minimap - toggle 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 scan - force a rescan of quests + bags")
|
||||||
print(" /attune sync - request sync from your group")
|
print(" /attune sync - request sync from your group")
|
||||||
print(" /attune debug - dump keyring + item detection")
|
print(" /attune debug - dump keyring + item detection")
|
||||||
@@ -596,8 +799,15 @@ ef:RegisterEvent("BAG_UPDATE")
|
|||||||
ef:RegisterEvent("PLAYER_LEVEL_UP")
|
ef:RegisterEvent("PLAYER_LEVEL_UP")
|
||||||
ef:RegisterEvent("UPDATE_FACTION")
|
ef:RegisterEvent("UPDATE_FACTION")
|
||||||
ef:RegisterEvent("CHAT_MSG_ADDON")
|
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("QUEST_TURNED_IN") end)
|
||||||
pcall(function() ef:RegisterEvent("KEYRING_UPDATE") 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()
|
ef:SetScript("OnEvent", function()
|
||||||
local e = event
|
local e = event
|
||||||
@@ -610,9 +820,6 @@ ef:SetScript("OnEvent", function()
|
|||||||
RA:BuildNameIndex()
|
RA:BuildNameIndex()
|
||||||
RA:WarmItemCache()
|
RA:WarmItemCache()
|
||||||
RA:ScanQuestLog(); RA:ScanBags(); RA:RecomputeAll()
|
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 }
|
RA._retryAt = { GetTime() + 3, GetTime() + 10 }
|
||||||
if RA.Comm and RA.Comm.Init then RA.Comm:Init() end
|
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.UI and RA.UI.Init then RA.UI:Init() end
|
||||||
@@ -631,7 +838,12 @@ ef:SetScript("OnEvent", function()
|
|||||||
or e == "BAG_UPDATE"
|
or e == "BAG_UPDATE"
|
||||||
or e == "KEYRING_UPDATE"
|
or e == "KEYRING_UPDATE"
|
||||||
or e == "PLAYER_LEVEL_UP"
|
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
|
if RA.initialized then RA:MarkDirty() end
|
||||||
|
|
||||||
elseif e == "QUEST_TURNED_IN" then
|
elseif e == "QUEST_TURNED_IN" then
|
||||||
|
|||||||
@@ -1,28 +1,31 @@
|
|||||||
-- RelationshipsAttune: Data.lua
|
-- RelationshipsAttune: Data.lua
|
||||||
-- Attunement definitions with icons + hover descriptions for the UI.
|
-- Attunement definitions with icons + hover descriptions for the UI.
|
||||||
--
|
--
|
||||||
-- Sources: wowhead classic attunement guides (Onyxia, MC, BWL, Naxx, AQ40).
|
-- Sources: wowhead classic guides + turtle-wow wiki for custom raids/keys.
|
||||||
-- Turtle/Octo custom raids keep placeholder ids until server confirms them.
|
-- 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:
|
-- Each step:
|
||||||
-- { type = "level", level = 60, name = "...", icon = "..." }
|
-- { type = "level", level = 60, name = "...", icon = "..." }
|
||||||
-- { type = "quest", id = <qid>, 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 = "item", id = <iid>, name = "...", icon = "...", desc = "...", start = "..." }
|
||||||
-- { type = "rep", faction = "Argent Dawn", standing = 5, name = "...",
|
-- { type = "rep", faction = "Argent Dawn", standing = 5, name = "...",
|
||||||
-- desc = "...", start = "..." }
|
-- desc = "...", start = "..." }
|
||||||
--
|
--
|
||||||
-- Standing: 1=Hostile ... 4=Neutral, 5=Honored, 6=Revered, 7=Exalted.
|
-- 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_QUEST = "Interface\\GossipFrame\\AvailableQuestIcon"
|
||||||
local ICON_ACTIVE = "Interface\\GossipFrame\\ActiveQuestIcon"
|
local ICON_ACTIVE = "Interface\\GossipFrame\\ActiveQuestIcon"
|
||||||
local ICON_KEY = "Interface\\Icons\\INV_Misc_Key_03"
|
local ICON_KEY = "Interface\\Icons\\INV_Misc_Key_03"
|
||||||
local ICON_LEVEL = "Interface\\Icons\\Spell_Nature_EnchantArmor"
|
local ICON_LEVEL = "Interface\\Icons\\Spell_Nature_EnchantArmor"
|
||||||
local ICON_REP = "Interface\\Icons\\Achievement_Reputation_01"
|
local ICON_REP = "Interface\\Icons\\Achievement_Reputation_01"
|
||||||
local ICON_ITEM = "Interface\\Icons\\INV_Misc_QuestionMark"
|
local ICON_ITEM = "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||||
|
|
||||||
RelationshipsAttune_Data = {
|
RelationshipsAttune_Data = {
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
-- ONYXIA'S LAIR - full Drakefire Amulet chain (both factions)
|
-- ONYXIA'S LAIR - full Drakefire Amulet chain (both factions)
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@@ -32,10 +35,8 @@ RelationshipsAttune_Data = {
|
|||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL,
|
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL,
|
||||||
desc = "Minimum level to start either faction's Onyxia attunement chain." },
|
desc = "Minimum level to start either faction's Onyxia attunement chain." },
|
||||||
|
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
-- ALLIANCE CHAIN (starts Burning Steppes -> Redridge -> Stormwind
|
-- ALLIANCE CHAIN
|
||||||
-- -> BRD -> back to Stormwind -> Winterspring -> UBRS).
|
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
{ type = "quest", id = 4182, faction = "Alliance",
|
{ type = "quest", id = 4182, faction = "Alliance",
|
||||||
name = "Dragonkin Menace", icon = ICON_QUEST,
|
name = "Dragonkin Menace", icon = ICON_QUEST,
|
||||||
@@ -44,47 +45,47 @@ RelationshipsAttune_Data = {
|
|||||||
{ type = "quest", id = 4183, faction = "Alliance",
|
{ type = "quest", id = 4183, faction = "Alliance",
|
||||||
name = "The True Masters (Helendis)", icon = ICON_QUEST,
|
name = "The True Masters (Helendis)", icon = ICON_QUEST,
|
||||||
desc = "Deliver Helendis Riverhorn's Letter to Magistrate Solomon in Lakeshire.",
|
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",
|
{ type = "quest", id = 4184, faction = "Alliance",
|
||||||
name = "The True Masters (Solomon -> Bolvar)", icon = ICON_QUEST,
|
name = "The True Masters (Solomon -> Bolvar)", icon = ICON_QUEST,
|
||||||
desc = "Take Solomon's Plea to Highlord Bolvar Fordragon in Stormwind Keep.",
|
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",
|
{ type = "quest", id = 4185, faction = "Alliance",
|
||||||
name = "The True Masters (Prestor)", icon = ICON_QUEST,
|
name = "The True Masters (Prestor)", icon = ICON_QUEST,
|
||||||
desc = "Speak with Lady Katrana Prestor, then return to Bolvar.",
|
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",
|
{ type = "quest", id = 4186, faction = "Alliance",
|
||||||
name = "The True Masters (Bolvar's Decree)", icon = ICON_QUEST,
|
name = "The True Masters (Bolvar's Decree)", icon = ICON_QUEST,
|
||||||
desc = "Return Bolvar's Decree to Magistrate Solomon in Lakeshire.",
|
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",
|
{ type = "quest", id = 4223, faction = "Alliance",
|
||||||
name = "The True Masters (Maxwell)", icon = ICON_QUEST,
|
name = "The True Masters (Maxwell)", icon = ICON_QUEST,
|
||||||
desc = "Report to Marshal Maxwell at Morgan's Vigil.",
|
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",
|
{ type = "quest", id = 4224, faction = "Alliance",
|
||||||
name = "The True Masters (Ragged John)", icon = ICON_QUEST,
|
name = "The True Masters (Ragged John)", icon = ICON_QUEST,
|
||||||
desc = "Find Ragged John in a cave north of Thaurissan, then return to Maxwell.",
|
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",
|
{ type = "quest", id = 4241, faction = "Alliance",
|
||||||
name = "Marshal Windsor", icon = ICON_QUEST,
|
name = "Marshal Windsor", icon = ICON_QUEST,
|
||||||
desc = "Enter Blackrock Depths and find Marshal Windsor in his cell.",
|
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",
|
{ type = "quest", id = 4242, faction = "Alliance",
|
||||||
name = "Abandoned Hope", icon = ICON_QUEST,
|
name = "Abandoned Hope", icon = ICON_QUEST,
|
||||||
desc = "Return the bad news from Windsor to Marshal Maxwell.",
|
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",
|
{ type = "quest", id = 4264, faction = "Alliance",
|
||||||
name = "A Crumpled Up Note", icon = ICON_QUEST,
|
name = "A Crumpled Up Note", icon = ICON_QUEST,
|
||||||
desc = "Random drop item from BRD slaves/mobs; return it to Windsor.",
|
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",
|
{ type = "quest", id = 4282, faction = "Alliance",
|
||||||
name = "A Shred of Hope", icon = ICON_QUEST,
|
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.",
|
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",
|
{ type = "quest", id = 4322, faction = "Alliance",
|
||||||
name = "Jail Break!", icon = ICON_QUEST,
|
name = "Jail Break!", icon = ICON_QUEST,
|
||||||
desc = "Escort Marshal Windsor out of BRD, then report to Marshal Maxwell.",
|
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",
|
{ type = "quest", id = 6402, faction = "Alliance",
|
||||||
name = "Stormwind Rendezvous", icon = ICON_QUEST,
|
name = "Stormwind Rendezvous", icon = ICON_QUEST,
|
||||||
desc = "Speak to Squire Rowe at the Stormwind gates to summon Reginald Windsor.",
|
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",
|
{ type = "quest", id = 6403, faction = "Alliance",
|
||||||
name = "The Great Masquerade", icon = ICON_ACTIVE,
|
name = "The Great Masquerade", icon = ICON_ACTIVE,
|
||||||
desc = "Escort Reginald Windsor to Stormwind Keep; unmask Lady Prestor as Onyxia.",
|
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",
|
{ type = "quest", id = 6501, faction = "Alliance",
|
||||||
name = "The Dragon's Eye", icon = ICON_QUEST,
|
name = "The Dragon's Eye", icon = ICON_QUEST,
|
||||||
desc = "Take the Fragment of the Dragon's Eye to Haleh in Mazthoril, Winterspring.",
|
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",
|
{ type = "quest", id = 6502, faction = "Alliance",
|
||||||
name = "Drakefire Amulet (Alliance)", icon = ICON_ACTIVE,
|
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.",
|
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
|
-- HORDE CHAIN
|
||||||
-- -> Western Plaguelands -> Dustwallow -> Tanaris/Winterspring/
|
|
||||||
-- Swamp of Sorrows/Wetlands -> Desolace -> UBRS).
|
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
{ type = "quest", id = 4903, faction = "Horde",
|
{ type = "quest", id = 4903, faction = "Horde",
|
||||||
name = "Warlord's Command", icon = ICON_QUEST,
|
name = "Warlord's Command", icon = ICON_QUEST,
|
||||||
@@ -114,11 +112,11 @@ RelationshipsAttune_Data = {
|
|||||||
{ type = "quest", id = 4941, faction = "Horde",
|
{ type = "quest", id = 4941, faction = "Horde",
|
||||||
name = "Eitrigg's Wisdom", icon = ICON_QUEST,
|
name = "Eitrigg's Wisdom", icon = ICON_QUEST,
|
||||||
desc = "Speak to Eitrigg in Orgrimmar, then turn in to Thrall.",
|
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",
|
{ type = "quest", id = 4974, faction = "Horde",
|
||||||
name = "For The Horde!", icon = ICON_QUEST,
|
name = "For The Horde!", icon = ICON_QUEST,
|
||||||
desc = "Kill Warchief Rend Blackhand in UBRS and return his head to Thrall (grants Warchief's Blessing).",
|
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",
|
{ type = "quest", id = 6566, faction = "Horde",
|
||||||
name = "What the Wind Carries", icon = ICON_QUEST,
|
name = "What the Wind Carries", icon = ICON_QUEST,
|
||||||
desc = "Listen to Thrall's tale and turn in.",
|
desc = "Listen to Thrall's tale and turn in.",
|
||||||
@@ -126,15 +124,15 @@ RelationshipsAttune_Data = {
|
|||||||
{ type = "quest", id = 6567, faction = "Horde",
|
{ type = "quest", id = 6567, faction = "Horde",
|
||||||
name = "The Champion of the Horde", icon = ICON_QUEST,
|
name = "The Champion of the Horde", icon = ICON_QUEST,
|
||||||
desc = "Find Rexxar patrolling between Desolace, Stonetalon and Feralas.",
|
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",
|
{ type = "quest", id = 6568, faction = "Horde",
|
||||||
name = "The Testament of Rexxar", icon = ICON_QUEST,
|
name = "The Testament of Rexxar", icon = ICON_QUEST,
|
||||||
desc = "Deliver Rexxar's Testament to Myranda the Hag in Western Plaguelands.",
|
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",
|
{ type = "quest", id = 6569, faction = "Horde",
|
||||||
name = "Oculus Illusions", icon = ICON_QUEST,
|
name = "Oculus Illusions", icon = ICON_QUEST,
|
||||||
desc = "Collect 20 Black Dragonspawn Eyes from UBRS dragonkin for your disguise.",
|
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",
|
{ type = "quest", id = 6570, faction = "Horde",
|
||||||
name = "Emberstrife", icon = ICON_QUEST,
|
name = "Emberstrife", icon = ICON_QUEST,
|
||||||
desc = "Use Amulet of Draconic Subversion and speak to Emberstrife in his den, Dustwallow Marsh.",
|
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",
|
{ type = "quest", id = 6582, faction = "Horde",
|
||||||
name = "The Test of Skulls, Scryer", icon = ICON_QUEST,
|
name = "The Test of Skulls, Scryer", icon = ICON_QUEST,
|
||||||
desc = "Kill Scryer (Blue) inside Mazthoril cave, Winterspring.",
|
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",
|
{ type = "quest", id = 6583, faction = "Horde",
|
||||||
name = "The Test of Skulls, Somnus", icon = ICON_QUEST,
|
name = "The Test of Skulls, Somnus", icon = ICON_QUEST,
|
||||||
desc = "Kill Somnus (Green) patrolling south-east Swamp of Sorrows.",
|
desc = "Kill Somnus (Green) patrolling south-east Swamp of Sorrows.",
|
||||||
@@ -154,26 +152,24 @@ RelationshipsAttune_Data = {
|
|||||||
{ type = "quest", id = 6585, faction = "Horde",
|
{ type = "quest", id = 6585, faction = "Horde",
|
||||||
name = "The Test of Skulls, Axtroz", icon = ICON_QUEST,
|
name = "The Test of Skulls, Axtroz", icon = ICON_QUEST,
|
||||||
desc = "Unlocks after the other three Skull quests. Kill Axtroz (Red) at Grim Batol, Wetlands.",
|
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",
|
{ type = "quest", id = 6601, faction = "Horde",
|
||||||
name = "Ascension...", icon = ICON_QUEST,
|
name = "Ascension...", icon = ICON_QUEST,
|
||||||
desc = "Take the Dull Drakefire Amulet to Rexxar in Desolace (not to Drakkisath).",
|
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",
|
{ type = "quest", id = 6602, faction = "Horde",
|
||||||
name = "Blood of the Black Dragon Champion", icon = ICON_ACTIVE,
|
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.",
|
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).
|
-- Final reward (both factions).
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
{ type = "item", id = 16309, name = "Drakefire Amulet",
|
{ type = "item", id = 16309, name = "Drakefire Amulet",
|
||||||
icon = "Interface\\Icons\\INV_Jewelry_Talisman_11",
|
icon = "Interface\\Icons\\INV_Jewelry_Talisman_11",
|
||||||
desc = "Must be in every raid member's bags (not bank) to enter Onyxia's Lair.",
|
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
|
-- MOLTEN CORE
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@@ -182,19 +178,11 @@ RelationshipsAttune_Data = {
|
|||||||
icon = "Interface\\Icons\\Spell_Fire_SelfDestruct",
|
icon = "Interface\\Icons\\Spell_Fire_SelfDestruct",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||||
{ type = "item", id = 17203, name = "Sulfuron Ingot (optional binder)",
|
{ type = "quest", id = 7487, name = "Attunement to the Core", icon = ICON_ACTIVE, final = true,
|
||||||
icon = "Interface\\Icons\\INV_Ingot_08",
|
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.",
|
||||||
desc = "Not required for attunement itself, but drops in MC; listed for group planning.",
|
start = "Lothos Riftwaker, BRD instance entrance platform inside Blackrock Mountain (~30, 37), Burning Steppes, next to the Molten Core portal." },
|
||||||
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)." },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
-- BLACKWING LAIR
|
-- BLACKWING LAIR
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@@ -205,13 +193,12 @@ RelationshipsAttune_Data = {
|
|||||||
{ type = "level", level = 58, name = "Reach Level 58", icon = ICON_LEVEL },
|
{ 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,
|
{ 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.",
|
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)." },
|
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,
|
{ 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.",
|
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
|
-- NAXXRAMAS
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@@ -224,18 +211,17 @@ RelationshipsAttune_Data = {
|
|||||||
name = "Honored with the Argent Dawn", icon = ICON_REP,
|
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 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)." },
|
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.",
|
desc = "Pay 60g to Angela Dosantos - available at Honored with Argent Dawn.",
|
||||||
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
|
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.",
|
desc = "Discounted Naxx attunement offered at Revered with Argent Dawn.",
|
||||||
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
|
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.",
|
desc = "Cheapest Naxx attunement, offered only at Exalted with Argent Dawn.",
|
||||||
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
|
start = "Archmage Angela Dosantos, Light's Hope Chapel, Eastern Plaguelands (76, 53)." },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
-- AQ20 - Ruins of Ahn'Qiraj
|
-- AQ20 - Ruins of Ahn'Qiraj
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@@ -248,15 +234,13 @@ RelationshipsAttune_Data = {
|
|||||||
name = "Neutral with Cenarion Circle", icon = ICON_REP,
|
name = "Neutral with Cenarion Circle", icon = ICON_REP,
|
||||||
desc = "Automatic from Silithus mobs after the war effort opens; no separate attunement item.",
|
desc = "Automatic from Silithus mobs after the war effort opens; no separate attunement item.",
|
||||||
start = "Windcaller Yessendra / Proudhorn, Cenarion Hold, Silithus (50, 33)." },
|
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.",
|
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)
|
-- 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",
|
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 = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 8286, name = "What Tomorrow Brings", icon = ICON_QUEST,
|
{ 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.",
|
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,
|
{ type = "quest", id = 8288, name = "Only One May Rise", icon = ICON_QUEST,
|
||||||
desc = "Kill Vaelastrasz in Blackwing Lair and loot the Vessel of Rebirth.",
|
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,
|
{ type = "quest", id = 8301, name = "The Path of the Righteous", icon = ICON_QUEST,
|
||||||
desc = "Continue Anachronos' story after handing in the Vessel.",
|
desc = "Continue Anachronos' story after handing in the Vessel.",
|
||||||
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
|
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
|
||||||
{ type = "rep", faction = "Brood of Nozdormu", standing = 4,
|
{ type = "rep", faction = "Brood of Nozdormu", standing = 4,
|
||||||
name = "Neutral with Brood of Nozdormu", icon = ICON_REP,
|
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.",
|
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,
|
{ type = "quest", id = 8303, name = "Chamber of the Aspects", icon = ICON_QUEST,
|
||||||
desc = "Anachronos sends you to speak with the four dragon Aspect representatives.",
|
desc = "Anachronos sends you to speak with the four dragon Aspect representatives.",
|
||||||
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
|
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
|
||||||
@@ -287,90 +271,130 @@ RelationshipsAttune_Data = {
|
|||||||
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
|
start = "Anachronos, Caverns of Time entrance, Tanaris (65, 50)." },
|
||||||
{ type = "quest", id = 8555, name = "The Nightmare's Corruption (Red)", icon = ICON_QUEST,
|
{ type = "quest", id = 8555, name = "The Nightmare's Corruption (Red)", icon = ICON_QUEST,
|
||||||
desc = "Kill Vaelastrasz (BWL), loot Vaelastrasz's Tooth for Caelestrasz.",
|
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,
|
{ type = "quest", id = 8733, name = "Beyond the Grave (Green)", icon = ICON_QUEST,
|
||||||
desc = "Investigate the pool inside The Temple of Atal'Hakkar for Merithra.",
|
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,
|
{ type = "quest", id = 8734, name = "Draconic for Dummies (Blue)", icon = ICON_QUEST,
|
||||||
desc = "Arygos sends you to research Nightmare Scale fragments across Azeroth.",
|
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,
|
{ 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.",
|
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,
|
{ type = "quest", id = 8736, name = "Preparations", icon = ICON_QUEST,
|
||||||
desc = "Return to Anachronos with the Nightmare Scale.",
|
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,
|
{ 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.",
|
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,
|
{ type = "quest", id = 8742, name = "The Hand of the Righteous", icon = ICON_QUEST,
|
||||||
desc = "Final scepter reforging quest. Rewards Scepter of the Shifting Sands.",
|
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",
|
{ type = "item", id = 21175, name = "Scepter of the Shifting Sands",
|
||||||
icon = "Interface\\Icons\\INV_Hammer_25",
|
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.",
|
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'." },
|
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,
|
{ 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.",
|
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)",
|
{ type = "item", id = 21176, name = "Black Qiraji Resonating Crystal (Scarab Lord mount)",
|
||||||
icon = "Interface\\Icons\\INV_Misc_QirajiCrystal_04",
|
icon = "Interface\\Icons\\INV_Misc_QirajiCrystal_04",
|
||||||
desc = "Awarded only to the player who rings the gong within the 10-hour war window.",
|
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." },
|
start = "Reward for completing 'Bang a Gong!' at the AQ gates, Silithus (28, 92) 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." },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
-- VANILLA KEYS & DUNGEON ACCESS
|
-- 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",
|
icon = "Interface\\Icons\\INV_Misc_Key_04",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
{ 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,
|
{ type = "item", id = 12219, name = "Unadorned Seal of Ascension", icon = ICON_KEY,
|
||||||
desc = "Opens Jorgen's Seal of Ascension chain.",
|
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 = "Kibler, Flame Crest, Burning Steppes (62, 24)." },
|
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 = 4743, name = "Seal of Ascension", icon = ICON_QUEST,
|
{ type = "quest", id = 4742, name = "Seal of Ascension", icon = ICON_QUEST,
|
||||||
desc = "Requires the Unadorned Seal of Ascension (drops in LBRS) plus three gemstones from LBRS bosses.",
|
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 = "Jorgen, Morgan's Vigil, Burning Steppes (85, 68)." },
|
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,
|
{ type = "item", id = 12344, name = "Seal of Ascension", icon = ICON_KEY, final = true,
|
||||||
desc = "Opens the door to Upper Blackrock Spire at the top of the LBRS instance.",
|
desc = "Uses the orb at the top of UBRS to open the instance portal. Required to enter UBRS.",
|
||||||
start = "Awarded by Jorgen at Morgan's Vigil after completing the Seal of Ascension chain." },
|
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",
|
icon = "Interface\\Icons\\INV_Misc_Key_06",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 47, name = "Reach Level 47", icon = ICON_LEVEL },
|
{ type = "level", level = 47, name = "Reach Level 47", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 4136, name = "Dark Iron Legacy", icon = ICON_QUEST,
|
{ type = "quest", id = 3802, name = "Dark Iron Legacy", icon = ICON_QUEST,
|
||||||
desc = "Rewards the Shadowforge Key for opening the deeper doors in BRD.",
|
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, inside Blackrock Depths (Detention Block hallway near his statue)." },
|
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,
|
{ type = "item", id = 11000, name = "Shadowforge Key", icon = ICON_KEY,
|
||||||
desc = "Opens Shadowforge City / Manufactory doors deep in BRD.",
|
desc = "Opens the Shadowforge Lock and every Dark Iron door in the deeper half of BRD.",
|
||||||
start = "Reward from 'Dark Iron Legacy'." },
|
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",
|
icon = "Interface\\Icons\\INV_Misc_Key_11",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 5382, name = "The Key to Scholomance", icon = ICON_QUEST,
|
{ type = "quest", id = 5537, faction = "Alliance",
|
||||||
desc = "Requires Blood of Innocents (Scarlet Monastery), Viewing Room Key (Scholomance) and Deed to Caer Darrow.",
|
name = "Skeletal Fragments (Alliance)", icon = ICON_QUEST,
|
||||||
start = "Alliance: Alexi Barov, Hearthglen, Western Plaguelands (44, 21). Horde: Alexi Barov, Ruins of Andorhal (42, 68)." },
|
desc = "Collect 15 Skeletal Fragments from the reanimated skeletons around Andorhal / Sorrow Hill for the Alchemist to imbue.",
|
||||||
{ type = "item", id = 13704, name = "Skeleton Key", icon = ICON_KEY,
|
start = "Alchemist Arbington, Chillwind Camp, Western Plaguelands (43, 84)." },
|
||||||
desc = "Opens the front door of Scholomance in Caer Darrow.",
|
{ type = "quest", id = 5538, faction = "Horde",
|
||||||
start = "Reward from 'The Key to Scholomance'." },
|
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",
|
id = "strat_live", name = "Stratholme (Service Entrance)", category = "Keys & Access", faction = "Both",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Key_07",
|
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 = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||||
{ type = "item", id = 12382, name = "Key to the City", icon = ICON_KEY,
|
{ type = "item", id = 12382, name = "Key to the City", icon = ICON_KEY,
|
||||||
desc = "Opens the Service Entrance shortcut into Stratholme Live.",
|
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",
|
icon = "Interface\\Icons\\INV_Misc_Key_09",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||||
{ type = "item", id = 18249, name = "Crescent Key", icon = ICON_KEY,
|
{ type = "item", id = 18249, name = "Crescent Key", icon = ICON_KEY,
|
||||||
desc = "Opens locked doors and cages throughout Dire Maul (all three wings).",
|
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",
|
id = "gnomer", name = "Gnomeregan (Workshop Shortcut)", category = "Keys & Access", faction = "Both",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Key_08",
|
icon = "Interface\\Icons\\INV_Misc_Key_08",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 24, name = "Reach Level 24", icon = ICON_LEVEL },
|
{ type = "level", level = 24, name = "Reach Level 24", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 2904, name = "Grime-Encrusted Ring", icon = ICON_QUEST,
|
{ type = "quest", id = 2945, name = "Grime-Encrusted Ring", icon = ICON_QUEST,
|
||||||
desc = "Drop-quest item off Gnomeregan mobs; leads into 'Return to Marvon'.",
|
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 inside Gnomeregan (Dun Morogh 25, 40)." },
|
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 = "quest", id = 2905, name = "Return to Marvon", icon = ICON_QUEST,
|
{ type = "item", id = 6893, name = "Workshop Key", icon = ICON_KEY,
|
||||||
desc = "Rewards the Workshop Key for skipping Grubbis.",
|
desc = "Opens the Workshop shortcut door in Gnomeregan, letting you skip most of the trash on the way to Mekgineer Thermaplugg.",
|
||||||
start = "Marvon Rivetseeker, Steamwheedle Port camp, Tanaris (66, 22)." },
|
start = "Reward for cleaning the Grime-Encrusted Ring at the Sparklematic 5200 (Tinker Town, Ironforge, or inside Gnomeregan entrance Dun Morogh 25, 40)." },
|
||||||
{ 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'." },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id = "mara", name = "Maraudon (Portal Shortcut)", category = "Keys & Access", faction = "Both",
|
id = "mara", name = "Maraudon (Portal Shortcut)", category = "Keys & Access", faction = "Both",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Idol_02",
|
icon = "Interface\\Icons\\INV_Misc_Idol_02",
|
||||||
@@ -417,175 +448,128 @@ RelationshipsAttune_Data = {
|
|||||||
{ type = "level", level = 40, name = "Reach Level 40", icon = ICON_LEVEL },
|
{ type = "level", level = 40, name = "Reach Level 40", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 7064, name = "Legends of Maraudon", icon = ICON_QUEST,
|
{ type = "quest", id = 7064, name = "Legends of Maraudon", icon = ICON_QUEST,
|
||||||
desc = "Prereq for the Scepter of Celebras.",
|
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,
|
{ type = "quest", id = 7065, name = "The Scepter of Celebras", icon = ICON_QUEST,
|
||||||
desc = "Rewards Scepter of Celebras (teleport into inner Maraudon).",
|
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,
|
{ type = "item", id = 17191, name = "Scepter of Celebras", icon = ICON_KEY,
|
||||||
desc = "Teleports directly to the Princess wing of Maraudon.",
|
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",
|
icon = "Interface\\Icons\\INV_Misc_Idol_03",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 50, name = "Reach Level 50", icon = ICON_LEVEL },
|
{ 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,
|
{ type = "quest", id = 3373, name = "The Ancient Egg (Yeh'kinya intro)", icon = ICON_QUEST,
|
||||||
desc = "Activates the six-statue puzzle so Jammal'an can be summoned.",
|
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). Sunken Temple: Swamp of Sorrows (69, 53)." },
|
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 = "hydraxian", name = "Hydraxian Waterlords (MC Runes)", category = "Keys & Access", faction = "Both",
|
id = "zf", name = "Zul'Farrak (Sacred Mallet)", category = "Keys & Access", faction = "Both",
|
||||||
icon = "Interface\\Icons\\Spell_Frost_SummonWaterElemental",
|
icon = "Interface\\Icons\\INV_Hammer_16",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
|
{ type = "level", level = 45, name = "Reach Level 45", icon = ICON_LEVEL },
|
||||||
{ type = "rep", faction = "Hydraxian Waterlords", standing = 5,
|
{ type = "item", id = 9241, name = "Sacred Mallet", icon = ICON_KEY,
|
||||||
name = "Honored with the Hydraxian Waterlords", icon = ICON_REP,
|
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.",
|
||||||
desc = "Needed to purchase Aqual Quintessence to douse the Molten Core runes for Majordomo.",
|
start = "Top of the Altar of Zul, Jintha'Alor, Hinterlands (~63, 74). The whole hill is heavily patrolled by level 46-50 Vilebranch trolls." },
|
||||||
start = "Duke Hydraxis, small island off south-east Azshara (79, 76). Turn in water elemental drops (Azshara/Silithus) and MC boss items." },
|
{ 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",
|
id = "sm_cath", name = "Scarlet Monastery (Cathedral)", category = "Keys & Access", faction = "Both",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Key_02",
|
icon = "Interface\\Icons\\INV_Misc_Key_02",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 35, name = "Reach Level 35", icon = ICON_LEVEL },
|
{ type = "level", level = 35, name = "Reach Level 35", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 1050, name = "Clear the Scarlet Monastery Library", icon = ICON_QUEST,
|
{ type = "item", id = 7146, name = "Scarlet Key", icon = ICON_KEY, final = true,
|
||||||
desc = "Clear the Library wing and loot the small chest behind the final boss to obtain the Scarlet Key.",
|
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 = "Scarlet Monastery Library wing entrance, Tirisfal Glades (85, 32)." },
|
start = "Ill-Fated Chest behind Arcanist Doan, end of the Library wing, Scarlet Monastery, 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",
|
id = "sgorge", name = "Key to Searing Gorge", category = "Keys & Access", faction = "Alliance",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Key_05",
|
icon = "Interface\\Icons\\INV_Misc_Key_14",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 52, name = "Reach Level 52", icon = ICON_LEVEL },
|
{ type = "level", level = 43, name = "Reach Level 43", icon = ICON_LEVEL,
|
||||||
{ type = "item", id = 11266, name = "Prison Cell Key", icon = ICON_KEY,
|
desc = "Minimum recommended level to survive the trip into south-east Searing Gorge." },
|
||||||
desc = "Unlocks the Detention Block cells in Blackrock Depths (frees Marshal Windsor, Dughal, Kharan, etc).",
|
{ type = "quest", id = 3181, faction = "Alliance",
|
||||||
start = "Drops from Warder Stilgiss in the Detention Block, Blackrock Depths." },
|
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 = "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",
|
id = "uldaman", name = "Uldaman (Discs of Norgannon)", category = "Keys & Access", faction = "Both",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Gem_Diamond_01",
|
icon = "Interface\\Icons\\INV_Misc_Gem_Diamond_01",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 40, name = "Reach Level 40", icon = ICON_LEVEL },
|
{ type = "level", level = 40, name = "Reach Level 40", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 2278, name = "The Lost Tablets of Will", icon = ICON_QUEST,
|
{ type = "quest", id = 1139, faction = "Alliance",
|
||||||
desc = "Prereq to activating the Discs of Norgannon so Archaedas can be reached.",
|
name = "The Lost Tablets of Will", icon = ICON_QUEST,
|
||||||
start = "Alliance: Advisor Belgrum, Ironforge. Horde: Rigglefuzz, Hillsbrad Foothills." },
|
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.",
|
||||||
{ type = "quest", id = 2418, name = "The Platinum Discs", icon = ICON_QUEST,
|
start = "Advisor Belgrum, Great Forge, Ironforge (55, 46). Uldaman entrance: Badlands (42, 20)." },
|
||||||
desc = "Interact with the Discs of Norgannon inside the Chamber of Khaz'mul to spawn Archaedas.",
|
{ type = "quest", id = 2418, faction = "Both",
|
||||||
start = "Uldaman, Badlands (42, 20)." },
|
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)." },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
-- TURTLE / OCTO WOW CUSTOM CONTENT
|
-- 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",
|
id = "kara10", name = "Karazhan Crypt (10)", category = "Turtle", faction = "Both",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Gem_Sapphire_02",
|
icon = "Interface\\Icons\\INV_Misc_Gem_Sapphire_02",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 40001, name = "TODO: Crypt attunement quest", icon = ICON_QUEST,
|
{ type = "quest", id = 40001, name = "Karazhan Crypt attunement (Koren)", icon = ICON_QUEST, final = true,
|
||||||
desc = "Custom Turtle attunement chain for Karazhan Crypt (10-man).",
|
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)." },
|
start = "Koren the Seeker, Morgan's Plot camp, Deadwind Pass (40, 75). Karazhan: Deadwind Pass (47, 75)." },
|
||||||
{ type = "item", id = 60001, name = "TODO: Crypt Key", icon = ICON_KEY,
|
{ type = "item", id = 60001, name = "Karazhan Crypt Key", icon = ICON_KEY,
|
||||||
desc = "Key required to enter the crypt beneath Karazhan.",
|
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 after completing the Karazhan Crypt attunement chain." },
|
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",
|
id = "kara40", name = "Lower Karazhan Halls (40)", category = "Turtle", faction = "Both",
|
||||||
icon = "Interface\\Icons\\INV_Misc_Gem_Sapphire_01",
|
icon = "Interface\\Icons\\INV_Misc_Gem_Sapphire_01",
|
||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
|
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
|
||||||
{ type = "quest", id = 40010, name = "TODO: LKH attunement", icon = ICON_QUEST,
|
{ 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).",
|
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)." },
|
start = "Archmage Alturus, Morgan's Plot camp, Deadwind Pass (40, 75). Karazhan: Deadwind Pass (47, 75)." },
|
||||||
{ type = "item", id = 60010, name = "TODO: LKH Key", icon = ICON_KEY,
|
{ type = "item", id = 60010, name = "Master's Key (LKH)", icon = ICON_KEY,
|
||||||
desc = "40-man Karazhan key.",
|
desc = "40-man Karazhan raid key. Matches by tooltip name if the numeric id differs on your build.",
|
||||||
start = "Awarded from Archmage Alturus at the end of the LKH attunement." },
|
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).",
|
|
||||||
start = "Keeper Remulos avatar, eastern Hinterlands near Seradane (55, 22)." },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
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.",
|
|
||||||
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.",
|
|
||||||
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)." },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
-- DRAGONMAW RETREAT (Turtle/Octo custom, Wetlands, patch 1.18)
|
-- 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",
|
id = "dmr", name = "Dragonmaw Retreat", category = "Turtle", faction = "Both",
|
||||||
@@ -593,36 +577,32 @@ RelationshipsAttune_Data = {
|
|||||||
steps = {
|
steps = {
|
||||||
{ type = "level", level = 25, name = "Reach Level 25", icon = ICON_LEVEL,
|
{ type = "level", level = 25, name = "Reach Level 25", icon = ICON_LEVEL,
|
||||||
desc = "Minimum level to enter Dragonmaw Retreat." },
|
desc = "Minimum level to enter Dragonmaw Retreat." },
|
||||||
|
|
||||||
{ type = "quest", id = 41810, faction = "Alliance",
|
{ type = "quest", id = 41810, faction = "Alliance",
|
||||||
name = "To Crush The Dragonmaw", icon = ICON_QUEST,
|
name = "To Crush The Dragonmaw", icon = ICON_QUEST,
|
||||||
desc = "Alliance intro quest for Dragonmaw Retreat.",
|
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",
|
{ type = "quest", id = 41811, faction = "Alliance",
|
||||||
name = "Blackheart's Demise", icon = ICON_QUEST,
|
name = "Blackheart's Demise", icon = ICON_QUEST,
|
||||||
desc = "Alliance follow-up to slay Overlord Blackheart inside the dungeon.",
|
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",
|
{ type = "quest", id = 41820, faction = "Horde",
|
||||||
name = "Cavernweb Extract", icon = ICON_QUEST,
|
name = "Cavernweb Extract", icon = ICON_QUEST,
|
||||||
desc = "Horde intro quest — collect spider extract inside Dragonmaw Retreat.",
|
desc = "Horde intro quest - collect spider extract inside Dragonmaw Retreat.",
|
||||||
start = "Okul, Hammerfall, Arathi Highlands." },
|
start = "Okul, Hammerfall, Arathi Highlands (73, 33)." },
|
||||||
{ type = "quest", id = 41821, faction = "Horde",
|
{ type = "quest", id = 41821, faction = "Horde",
|
||||||
name = "A Blaze Unending", icon = ICON_QUEST,
|
name = "A Blaze Unending", icon = ICON_QUEST,
|
||||||
desc = "Horde follow-up in Dragonmaw Retreat.",
|
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,
|
{ type = "quest", id = 41830, name = "Gowlfang's Defeat", icon = ICON_QUEST,
|
||||||
desc = "Neutral quest — defeat the gnoll leader Gowlfang.",
|
desc = "Neutral quest - defeat the gnoll leader Gowlfang.",
|
||||||
start = "Grimbite, Green Belt gnoll camp, central Wetlands." },
|
start = "Grimbite, Green Belt gnoll camp, central Wetlands (~46, 50)." },
|
||||||
{ type = "quest", id = 41831, name = "The Dragonmaw Brood", icon = ICON_QUEST,
|
{ type = "quest", id = 41831, name = "The Dragonmaw Brood", icon = ICON_QUEST,
|
||||||
desc = "Neutral quest — cull the drakes and whelps inside the retreat.",
|
desc = "Neutral quest - cull the drakes and whelps inside the retreat.",
|
||||||
start = "Nidiszanz, Dragonmaw Gates, Wetlands." },
|
start = "Nidiszanz, Dragonmaw Gates, Wetlands (~70, 40)." },
|
||||||
|
|
||||||
{ type = "item", id = 61810, name = "Lower Reserve Key",
|
{ type = "item", id = 61810, name = "Lower Reserve Key",
|
||||||
icon = ICON_KEY, final = true,
|
icon = ICON_KEY, final = true,
|
||||||
desc = "Opens the gates of Dragonmaw Retreat / Dragonmaw Reserve in the Wetlands.",
|
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)." },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-5
@@ -52,22 +52,35 @@ end
|
|||||||
MM._updatePosition = applyPosition
|
MM._updatePosition = applyPosition
|
||||||
|
|
||||||
local function onDragUpdate()
|
local function onDragUpdate()
|
||||||
|
-- Do all math in the button's own effective scale. The button is
|
||||||
|
-- parented to Minimap, whose effective scale can differ from
|
||||||
|
-- UIParent's; mixing scales makes the icon drift away from the cursor.
|
||||||
|
local btn = this
|
||||||
|
local bscale = btn:GetEffectiveScale() or 1
|
||||||
|
local uscale = UIParent:GetEffectiveScale() or 1
|
||||||
local mx, my = GetCursorPosition()
|
local mx, my = GetCursorPosition()
|
||||||
local scale = UIParent:GetEffectiveScale() or 1
|
mx = mx / bscale
|
||||||
mx = mx / scale; my = my / scale
|
my = my / bscale
|
||||||
local ucx, ucy = UIParent:GetCenter()
|
local ucx, ucy = UIParent:GetCenter()
|
||||||
if not ucx then return end
|
if not ucx then return end
|
||||||
|
-- Convert UIParent center from UIParent scale into btn scale.
|
||||||
|
ucx = ucx * uscale / bscale
|
||||||
|
ucy = ucy * uscale / bscale
|
||||||
local o = opts()
|
local o = opts()
|
||||||
o.minimapX = mx - ucx
|
o.minimapX = mx - ucx
|
||||||
o.minimapY = my - ucy
|
o.minimapY = my - ucy
|
||||||
applyPosition(this)
|
applyPosition(btn)
|
||||||
end
|
end
|
||||||
|
|
||||||
function MM:Create()
|
function MM:Create()
|
||||||
if getglobal(BTN_NAME) then return getglobal(BTN_NAME) end
|
if getglobal(BTN_NAME) then return getglobal(BTN_NAME) end
|
||||||
|
|
||||||
-- Parent to UIParent so we're not clipped to the minimap area.
|
-- Parent to Minimap so button-collector addons (MinimapButtonBag /
|
||||||
local btn = CreateFrame("Button", BTN_NAME, UIParent)
|
-- 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:SetWidth(31); btn:SetHeight(31)
|
||||||
btn:SetFrameStrata("MEDIUM")
|
btn:SetFrameStrata("MEDIUM")
|
||||||
btn:SetFrameLevel(8)
|
btn:SetFrameLevel(8)
|
||||||
@@ -75,6 +88,12 @@ function MM:Create()
|
|||||||
btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||||||
btn:RegisterForDrag("LeftButton", "RightButton")
|
btn:RegisterForDrag("LeftButton", "RightButton")
|
||||||
btn:SetMovable(true)
|
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)
|
-- Round border ring (standard minimap-button look)
|
||||||
local overlay = btn:CreateTexture(nil, "OVERLAY")
|
local overlay = btn:CreateTexture(nil, "OVERLAY")
|
||||||
@@ -89,6 +108,7 @@ function MM:Create()
|
|||||||
icon:SetPoint("TOPLEFT", btn, "TOPLEFT", 7, -6)
|
icon:SetPoint("TOPLEFT", btn, "TOPLEFT", 7, -6)
|
||||||
btn.icon = icon
|
btn.icon = icon
|
||||||
|
|
||||||
|
|
||||||
btn:SetScript("OnClick", function()
|
btn:SetScript("OnClick", function()
|
||||||
if RA.UI and RA.UI.Toggle then RA.UI:Toggle() end
|
if RA.UI and RA.UI.Toggle then RA.UI:Toggle() end
|
||||||
end)
|
end)
|
||||||
@@ -107,6 +127,7 @@ function MM:Create()
|
|||||||
GameTooltip:AddLine("Relationships Attune", 1, 0.82, 0)
|
GameTooltip:AddLine("Relationships Attune", 1, 0.82, 0)
|
||||||
GameTooltip:AddLine("Left-click: open / close window", 0.9, 0.9, 0.9)
|
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("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:AddLine("/attune hide - hide this button", 0.6, 0.8, 1)
|
||||||
GameTooltip:Show()
|
GameTooltip:Show()
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<img src="https://cdn.discordapp.com/attachments/1510333697277300856/1524819837270884362/kkk.gif?ex=6a5122a2&is=6a4fd122&hm=b82d19b995b2d1f8b252fcbaf44dcaa7b5f30255fb1401f50f931919c980a4ce&"/>
|
<img src="https://i.postimg.cc/rwVg8mmF/v.png"/>
|
||||||
|
|
||||||
|
|
||||||
# RelationshipsAttune
|
# RelationshipsAttune
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## Title: Relationships Attune
|
## Title: Relationships Attune
|
||||||
## Notes: Track Vanilla and Turtle/Octo WoW attunement progress
|
## Notes: Track Vanilla and Turtle/Octo WoW attunement progress
|
||||||
## Author: Relationship
|
## Author: Relationship
|
||||||
## Version: 1.0
|
## Version: 1.8
|
||||||
## X-Category: Quest
|
## X-Category: Quest
|
||||||
## SavedVariables: RelationshipsAttuneDB
|
## SavedVariables: RelationshipsAttuneDB
|
||||||
## SavedVariablesPerCharacter: RelationshipsAttuneCharDB
|
## SavedVariablesPerCharacter: RelationshipsAttuneCharDB
|
||||||
|
|||||||
@@ -24,6 +24,56 @@ local C_NONE = { 0.90, 0.30, 0.30 }
|
|||||||
local C_UNKNOWN = { 0.55, 0.55, 0.55 }
|
local C_UNKNOWN = { 0.55, 0.55, 0.55 }
|
||||||
local C_TURTLE = { 0.55, 0.85, 1.00 }
|
local C_TURTLE = { 0.55, 0.85, 1.00 }
|
||||||
local C_KEYS = { 0.95, 0.75, 0.35 }
|
local C_KEYS = { 0.95, 0.75, 0.35 }
|
||||||
|
local C_INPROGRESS = { 1.00, 0.60, 0.15 } -- orange: quest accepted / step in progress
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- Force-complete confirmation dialogs (StaticPopup)
|
||||||
|
-- In vanilla 1.12, StaticPopup OnAccept is called as OnAccept(dialog.data),
|
||||||
|
-- so the data arrives as arg1 (Lua 5.0 vararg). `this` inside OnAccept is
|
||||||
|
-- NOT the dialog frame, so this.data is nil. We stash the data on the
|
||||||
|
-- dialog itself via OnShow (which does run with this = dialog) and read
|
||||||
|
-- it back from arg1 with a dialog fallback for safety.
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
StaticPopupDialogs = StaticPopupDialogs or {}
|
||||||
|
|
||||||
|
local function RATTUNE_StashData()
|
||||||
|
-- OnShow runs with `this` = the dialog frame. StaticPopup_Show already
|
||||||
|
-- assigns dialog.data, but we snapshot it into an upvalue table so the
|
||||||
|
-- OnAccept closures can find it even on clients that don't forward arg1.
|
||||||
|
if this then RATTUNE_LastPopupData = this.data end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Attunement id awaiting the user's confirmation for a force / unforce.
|
||||||
|
-- StaticPopup OnAccept in vanilla 1.12 does not reliably receive dialog.data
|
||||||
|
-- as arg1, so we snapshot the id here at click time and read it back on accept.
|
||||||
|
RATTUNE_PendingForceAtt = nil
|
||||||
|
|
||||||
|
StaticPopupDialogs["RATTUNE_FORCE_ATT"] = {
|
||||||
|
text = "Force complete the entire \"%s\" attunement?\n\nEvery step will be marked as done for tracking. You can undo this later.",
|
||||||
|
button1 = "Force Complete",
|
||||||
|
button2 = "Cancel",
|
||||||
|
OnAccept = function()
|
||||||
|
local id = RATTUNE_PendingForceAtt
|
||||||
|
RATTUNE_PendingForceAtt = nil
|
||||||
|
if id then RA:SetAttForced(id, true) end
|
||||||
|
end,
|
||||||
|
OnCancel = function() RATTUNE_PendingForceAtt = nil end,
|
||||||
|
timeout = 0, whileDead = 1, hideOnEscape = 1, showAlert = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticPopupDialogs["RATTUNE_UNFORCE_ATT"] = {
|
||||||
|
text = "Undo forced completion for \"%s\"?\n\nProgress will revert to real, scanned state.",
|
||||||
|
button1 = "Undo",
|
||||||
|
button2 = "Cancel",
|
||||||
|
OnAccept = function()
|
||||||
|
local id = RATTUNE_PendingForceAtt
|
||||||
|
RATTUNE_PendingForceAtt = nil
|
||||||
|
if id then RA:SetAttForced(id, false) end
|
||||||
|
end,
|
||||||
|
OnCancel = function() RATTUNE_PendingForceAtt = nil end,
|
||||||
|
timeout = 0, whileDead = 1, hideOnEscape = 1, showAlert = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
local selectedPlayer = nil
|
local selectedPlayer = nil
|
||||||
local selectedRaid = nil
|
local selectedRaid = nil
|
||||||
@@ -195,6 +245,29 @@ function UI:Build()
|
|||||||
detail.category = fs(frame.rightPane, "", 10, 0.75, 0.75, 0.75)
|
detail.category = fs(frame.rightPane, "", 10, 0.75, 0.75, 0.75)
|
||||||
detail.category:SetPoint("TOPLEFT", detail.name, "BOTTOMLEFT", 0, -2)
|
detail.category:SetPoint("TOPLEFT", detail.name, "BOTTOMLEFT", 0, -2)
|
||||||
|
|
||||||
|
-- Force Complete (attunement-level) button. Sits in the top-right of the
|
||||||
|
-- right pane, hidden when viewing another player's data.
|
||||||
|
detail.forceBtn = CreateFrame("Button", nil, frame.rightPane, "UIPanelButtonTemplate")
|
||||||
|
detail.forceBtn:SetWidth(150); detail.forceBtn:SetHeight(20)
|
||||||
|
detail.forceBtn:SetPoint("TOPRIGHT", frame.rightPane, "TOPRIGHT", -4, -4)
|
||||||
|
detail.forceBtn:SetText("Force Complete")
|
||||||
|
detail.forceBtn:SetScript("OnClick", function()
|
||||||
|
local attId = selectedRaid
|
||||||
|
if not attId then return end
|
||||||
|
local att
|
||||||
|
local data = RelationshipsAttune_Data
|
||||||
|
for i = 1, table.getn(data) do
|
||||||
|
if data[i].id == attId then att = data[i]; break end
|
||||||
|
end
|
||||||
|
if not att then return end
|
||||||
|
RATTUNE_PendingForceAtt = attId
|
||||||
|
if RA:IsAttForced(attId) then
|
||||||
|
StaticPopup_Show("RATTUNE_UNFORCE_ATT", att.name)
|
||||||
|
else
|
||||||
|
StaticPopup_Show("RATTUNE_FORCE_ATT", att.name)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
-- Progress bar: give it explicit left+right anchors AND a border so it
|
-- Progress bar: give it explicit left+right anchors AND a border so it
|
||||||
-- always has a resolvable width, then size the fill from that width.
|
-- always has a resolvable width, then size the fill from that width.
|
||||||
detail.barBG = solid(frame.rightPane, "BORDER", 0, 0, 0, 0.90)
|
detail.barBG = solid(frame.rightPane, "BORDER", 0, 0, 0, 0.90)
|
||||||
@@ -565,6 +638,20 @@ function UI:RenderDetail()
|
|||||||
detail.barFill:SetVertexColor(c[1], c[2], c[3], 0.95)
|
detail.barFill:SetVertexColor(c[1], c[2], c[3], 0.95)
|
||||||
detail.barText:SetText(done .. " / " .. total .. " (" .. math.floor(pct * 100 + 0.5) .. "%)")
|
detail.barText:SetText(done .. " / " .. total .. " (" .. math.floor(pct * 100 + 0.5) .. "%)")
|
||||||
|
|
||||||
|
-- Update attunement-level Force button (only for your own data)
|
||||||
|
if detail.forceBtn then
|
||||||
|
if selectedPlayer ~= nil then
|
||||||
|
detail.forceBtn:Hide()
|
||||||
|
else
|
||||||
|
if RA:IsAttForced(att.id) then
|
||||||
|
detail.forceBtn:SetText("Undo Force Complete")
|
||||||
|
else
|
||||||
|
detail.forceBtn:SetText("Force Complete")
|
||||||
|
end
|
||||||
|
detail.forceBtn:Show()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Build applicable step list
|
-- Build applicable step list
|
||||||
local applicable = {}
|
local applicable = {}
|
||||||
for i = 1, table.getn(att.steps) do
|
for i = 1, table.getn(att.steps) do
|
||||||
@@ -644,10 +731,15 @@ function UI:RenderDetail()
|
|||||||
row.name:SetText(step.name or "?")
|
row.name:SetText(step.name or "?")
|
||||||
|
|
||||||
local ok = prog and prog.steps and prog.steps[origIdx]
|
local ok = prog and prog.steps and prog.steps[origIdx]
|
||||||
|
local inProg = prog and prog.stepsInProgress and prog.stepsInProgress[origIdx]
|
||||||
if ok then
|
if ok then
|
||||||
row.status:SetTexture(TEX_CHECK); row.status:Show()
|
row.status:SetTexture(TEX_CHECK); row.status:Show()
|
||||||
row.name:SetTextColor(C_DONE[1], C_DONE[2], C_DONE[3])
|
row.name:SetTextColor(C_DONE[1], C_DONE[2], C_DONE[3])
|
||||||
row.bg:SetVertexColor(0.20, 0.90, 0.30, 0.28)
|
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
|
elseif prog and prog.applicable then
|
||||||
row.status:SetTexture(TEX_CROSS); row.status:Show()
|
row.status:SetTexture(TEX_CROSS); row.status:Show()
|
||||||
row.name:SetTextColor(1, 1, 1)
|
row.name:SetTextColor(1, 1, 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user