Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ccfb78c3a6 | |||
| 9cdcc1814f | |||
| 0c9af0e9d2 | |||
| 8f4480bf14 | |||
| a276cca444 | |||
| 4502a1db7e | |||
| fda04907c2 | |||
| e95e65fca5 | |||
| 044b6593ec | |||
| fbb3e94b93 |
@@ -6,7 +6,7 @@ RelationshipsAttune = RelationshipsAttune or {}
|
||||
local RA = RelationshipsAttune
|
||||
local L = RelationshipsAttune_L
|
||||
|
||||
RA.VERSION = "1.4.0"
|
||||
RA.VERSION = "1.4.3"
|
||||
RA.COMM_PREFIX = "RATTUNE"
|
||||
|
||||
RA.playerName = nil
|
||||
@@ -70,6 +70,56 @@ function RA:InitDB()
|
||||
if not RelationshipsAttuneCharDB.announced then RelationshipsAttuneCharDB.announced = {} end
|
||||
if not RelationshipsAttuneCharDB.progress then RelationshipsAttuneCharDB.progress = {} 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
|
||||
|
||||
-- ---------------------------------------------------------------
|
||||
@@ -81,10 +131,16 @@ end
|
||||
-- ---------------------------------------------------------------
|
||||
function RA:ScanQuestLog()
|
||||
if not GetNumQuestLogEntries then return end
|
||||
-- Rebuild transient quest states from the live log so that abandoning a
|
||||
-- quest reverts its step colour. "turnedin" is authoritative and preserved.
|
||||
-- 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(RelationshipsAttuneCharDB.quests) do
|
||||
for qid, st in pairs(prev) do
|
||||
if st == "turnedin" then kept[qid] = "turnedin" end
|
||||
end
|
||||
RelationshipsAttuneCharDB.quests = kept
|
||||
@@ -92,6 +148,7 @@ function RA:ScanQuestLog()
|
||||
RA:BuildNameIndex()
|
||||
local qNameMap = RA._questNameToId or {}
|
||||
|
||||
local seenThisScan = {}
|
||||
local numEntries = GetNumQuestLogEntries()
|
||||
for i = 1, numEntries do
|
||||
local ok, title, level, tag, isHeader, _, isComplete, _, questId =
|
||||
@@ -104,7 +161,9 @@ function RA:ScanQuestLog()
|
||||
if (not qid) and title then
|
||||
qid = qNameMap[string.lower(title)]
|
||||
end
|
||||
if qid and RelationshipsAttuneCharDB.quests[qid] ~= "turnedin" then
|
||||
if qid then
|
||||
seenThisScan[qid] = true
|
||||
if RelationshipsAttuneCharDB.quests[qid] ~= "turnedin" then
|
||||
if isComplete and isComplete == 1 then
|
||||
RelationshipsAttuneCharDB.quests[qid] = "complete"
|
||||
else
|
||||
@@ -113,8 +172,18 @@ function RA:ScanQuestLog()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Retroactive turn-in detection: any quest we tracked as "complete" last
|
||||
-- scan that isn't in the log any more got handed in.
|
||||
for qid, st in pairs(prev) do
|
||||
if st == "complete" and not seenThisScan[qid] then
|
||||
RelationshipsAttuneCharDB.quests[qid] = "turnedin"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RA:MarkQuestTurnedIn(questId)
|
||||
if not questId then return end
|
||||
RelationshipsAttuneCharDB.quests[questId] = "turnedin"
|
||||
@@ -175,10 +244,24 @@ function RA:BuildNameIndex()
|
||||
for j = 1, table.getn(att.steps) do
|
||||
local s = att.steps[j]
|
||||
if s and s.name and s.id then
|
||||
local nlow = string.lower(s.name)
|
||||
if s.type == "item" then
|
||||
map[string.lower(s.name)] = s.id
|
||||
map[nlow] = s.id
|
||||
elseif s.type == "quest" then
|
||||
qmap[string.lower(s.name)] = s.id
|
||||
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
|
||||
@@ -329,9 +412,13 @@ function RA:EvaluateStep(step)
|
||||
return (UnitLevel("player") or 0) >= (step.level or 0), false
|
||||
elseif step.type == "quest" then
|
||||
local st = RelationshipsAttuneCharDB.quests[step.id]
|
||||
if st == "complete" or st == "turnedin" then
|
||||
if st == "turnedin" then
|
||||
return true, false
|
||||
elseif st == "inlog" then
|
||||
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
|
||||
@@ -369,6 +456,20 @@ function RA:EvaluateAttunement(att)
|
||||
stepsInProgress[i] = nil
|
||||
end
|
||||
end
|
||||
-- Apply per-step forced completions (manual overrides from the UI).
|
||||
-- These are treated exactly like a real completion for tracking purposes.
|
||||
local forced = RelationshipsAttuneCharDB.forcedSteps and RelationshipsAttuneCharDB.forcedSteps[att.id]
|
||||
if forced then
|
||||
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.
|
||||
@@ -398,6 +499,34 @@ function RA:EvaluateAttunement(att)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Retroactive completion: if the player is on a later step (done or in
|
||||
-- progress), any earlier quest/item steps must already be done. Quests
|
||||
-- get turned in and key items get consumed, so their live state can
|
||||
-- flip back to "not done" even though the player clearly finished
|
||||
-- them. Level and reputation steps have their own live truth and are
|
||||
-- left alone.
|
||||
local laterActive = false
|
||||
for i = numSteps, 1, -1 do
|
||||
local step = att.steps[i]
|
||||
if step and self:StepApplies(step) then
|
||||
if laterActive and steps[i] == false then
|
||||
local t = step.type
|
||||
if t == "quest" or t == "item" then
|
||||
steps[i] = true
|
||||
stepsInProgress[i] = false
|
||||
doneCount = doneCount + 1
|
||||
if t == "quest" then
|
||||
RelationshipsAttuneCharDB.quests[step.id] = "turnedin"
|
||||
elseif t == "item" then
|
||||
RelationshipsAttuneCharDB.items[step.id] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if steps[i] == true or stepsInProgress[i] == true then
|
||||
laterActive = true
|
||||
end
|
||||
end
|
||||
end
|
||||
local persistedDone = RelationshipsAttuneCharDB.completedAttunements and RelationshipsAttuneCharDB.completedAttunements[att.id]
|
||||
if persistedDone or (finalIdx and steps[finalIdx] == true) then
|
||||
for i = 1, numSteps do
|
||||
@@ -565,6 +694,34 @@ local function slashHandler(msg)
|
||||
print("Minimap button shown. Drag to reposition around the minimap.")
|
||||
end
|
||||
end
|
||||
elseif string.find(msg, "^pos") then
|
||||
-- /attune pos <x> <y> -- set exact offset from UIParent CENTER.
|
||||
-- Values may be off-screen (e.g. -9999) to park the button out of
|
||||
-- the way while still letting MinimapButtonBag collect it.
|
||||
local _, _, sx, sy = string.find(msg, "pos%s+(%-?%d+%.?%d*)%s+(%-?%d+%.?%d*)")
|
||||
local x, y = tonumber(sx), tonumber(sy)
|
||||
if x and y and RA.Minimap then
|
||||
local o = RelationshipsAttuneDB.options
|
||||
o.minimapX, o.minimapY = x, y
|
||||
RA.Minimap:Refresh()
|
||||
print("Minimap button moved to " .. x .. ", " .. y .. ".")
|
||||
else
|
||||
print("Usage: /attune pos <x> <y> (offsets from screen center; can be off-screen)")
|
||||
end
|
||||
elseif msg == "offscreen" or msg == "park" then
|
||||
if RA.Minimap then
|
||||
local o = RelationshipsAttuneDB.options
|
||||
o.minimapX, o.minimapY = -10000, -10000
|
||||
RA.Minimap:Refresh()
|
||||
print("Minimap button parked off-screen. MinimapButtonBag (if installed) can still collect it. Use /attune resetpos to bring it back.")
|
||||
end
|
||||
elseif msg == "resetpos" then
|
||||
if RA.Minimap then
|
||||
local o = RelationshipsAttuneDB.options
|
||||
o.minimapX, o.minimapY = 0, -140
|
||||
RA.Minimap:Refresh()
|
||||
print("Minimap button position reset.")
|
||||
end
|
||||
elseif msg == "sync" then
|
||||
if RA.Comm then RA.Comm:RequestSync() end
|
||||
print(L.MSG_SYNC_SENT)
|
||||
@@ -613,6 +770,9 @@ local function slashHandler(msg)
|
||||
print(" /attune show - open the window")
|
||||
print(" /attune hide - close the window (or hide the minimap button)")
|
||||
print(" /attune minimap - toggle the minimap button")
|
||||
print(" /attune pos x y - place the minimap button at exact offset (can be off-screen)")
|
||||
print(" /attune offscreen- park the minimap button off-screen (MBB can still collect it)")
|
||||
print(" /attune resetpos - restore the minimap button to a visible default position")
|
||||
print(" /attune scan - force a rescan of quests + bags")
|
||||
print(" /attune sync - request sync from your group")
|
||||
print(" /attune debug - dump keyring + item detection")
|
||||
|
||||
@@ -307,7 +307,7 @@ RelationshipsAttune_Data = {
|
||||
-- VANILLA KEYS & DUNGEON ACCESS
|
||||
----------------------------------------------------------------
|
||||
{
|
||||
id = "ubrs", name = "Upper Blackrock Spire (Seal of Ascension)", category = "Keys & Access", faction = "Both",
|
||||
id = "ubrs", name = "Upper Blackrock Spire (Seal)", category = "Keys & Access", faction = "Both",
|
||||
icon = "Interface\\Icons\\INV_Misc_Key_04",
|
||||
steps = {
|
||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||
@@ -537,17 +537,6 @@ RelationshipsAttune_Data = {
|
||||
start = "Discs of Norgannon, Chamber of Khaz'mul, Uldaman, Badlands (42, 20)." },
|
||||
},
|
||||
},
|
||||
{
|
||||
id = "hydraxian", name = "Hydraxian Waterlords (MC Runes)", category = "Keys & Access", faction = "Both",
|
||||
icon = "Interface\\Icons\\Spell_Frost_SummonWaterElemental",
|
||||
steps = {
|
||||
{ type = "level", level = 60, name = "Reach Level 60", icon = ICON_LEVEL },
|
||||
{ type = "rep", faction = "Hydraxian Waterlords", standing = 5,
|
||||
name = "Honored with the Hydraxian Waterlords", icon = ICON_REP,
|
||||
desc = "Needed to purchase Aqual Quintessence to douse the Molten Core runes for Majordomo.",
|
||||
start = "Duke Hydraxis, small island off south-east Azshara (79, 76). Turn in water elemental drops (Azshara/Silithus) and MC boss items." },
|
||||
},
|
||||
},
|
||||
----------------------------------------------------------------
|
||||
-- TURTLE / OCTO WOW CUSTOM CONTENT
|
||||
-- Placeholder ids where the live client id isn't confirmed; the
|
||||
@@ -579,56 +568,6 @@ RelationshipsAttune_Data = {
|
||||
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 = "Emerald Sanctum attunement", icon = ICON_QUEST, final = true,
|
||||
desc = "Emerald Sanctum attunement chain (Hinterlands portal). Speak with Keeper Remulos and collect the Sanctum Sigil from the four green dragons around Azeroth (Ysondre, Emeriss, Lethon, Taerar).",
|
||||
start = "Keeper Remulos avatar, eastern Hinterlands near Seradane (55, 22)." },
|
||||
},
|
||||
},
|
||||
{
|
||||
id = "cgrove", name = "Crescent Grove (Turtle 20-man)", category = "Turtle", faction = "Both",
|
||||
icon = "Interface\\Icons\\INV_Misc_Herb_02",
|
||||
steps = {
|
||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||
{ type = "quest", id = 40100, name = "Crescent Grove attunement", icon = ICON_QUEST, final = true,
|
||||
desc = "Turtle-WoW 20-man Emerald-themed raid in Ashenvale. Speak to the druid representative at the grove entrance to start the chain (collect corrupted samples inside the outer ring).",
|
||||
start = "Ashenvale, near the Crescent Grove portal south of Warsong Lumber Camp (~40, 63)." },
|
||||
},
|
||||
},
|
||||
{
|
||||
id = "gilneas", name = "Gilneas City", category = "Turtle", faction = "Both",
|
||||
icon = "Interface\\Icons\\Ability_Mount_WhiteDireWolf",
|
||||
steps = {
|
||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||
{ type = "quest", id = 40030, name = "Gilneas City attunement", icon = ICON_QUEST, final = true,
|
||||
desc = "Attunement for the Gilneas City dungeon. Speak with Lord Darius Crowley at the Greymane Wall and complete the intro quest chain in Silverpine.",
|
||||
start = "Lord Darius Crowley, Greymane Wall entrance, southern Silverpine Forest (43, 66)." },
|
||||
},
|
||||
},
|
||||
{
|
||||
id = "hateforge", name = "Hateforge Quarry", category = "Turtle", faction = "Both",
|
||||
icon = "Interface\\Icons\\INV_Hammer_16",
|
||||
steps = {
|
||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||
{ type = "quest", id = 40040, name = "Hateforge Quarry attunement", icon = ICON_QUEST, final = true,
|
||||
desc = "Attunement for the Hateforge Quarry dungeon. Turtle Dark Iron chain out of Burning Steppes.",
|
||||
start = "Overseer Maltorius, Flame Crest camp, northern Burning Steppes (62, 24)." },
|
||||
},
|
||||
},
|
||||
{
|
||||
id = "stormwind_vault", name = "Stormwind Vault", category = "Turtle", faction = "Both",
|
||||
icon = "Interface\\Icons\\INV_Misc_Coin_01",
|
||||
steps = {
|
||||
{ type = "level", level = 55, name = "Reach Level 55", icon = ICON_LEVEL },
|
||||
{ type = "quest", id = 40050, name = "Stormwind Vault attunement", icon = ICON_QUEST, final = true,
|
||||
desc = "Attunement for the Stormwind Vault dungeon (Turtle). Alliance intro from the Stockade warden; Horde variant from a SI:7 defector in Booty Bay.",
|
||||
start = "Warden Thelwater, Stormwind Stockade entrance, Mage Quarter, Stormwind City (50, 68). Horde variant: Booty Bay, Stranglethorn (27, 77)." },
|
||||
},
|
||||
},
|
||||
----------------------------------------------------------------
|
||||
-- DRAGONMAW RETREAT (Turtle/Octo custom, Wetlands, patch 1.18)
|
||||
----------------------------------------------------------------
|
||||
|
||||
+26
-5
@@ -52,22 +52,35 @@ end
|
||||
MM._updatePosition = applyPosition
|
||||
|
||||
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 scale = UIParent:GetEffectiveScale() or 1
|
||||
mx = mx / scale; my = my / scale
|
||||
mx = mx / bscale
|
||||
my = my / bscale
|
||||
local ucx, ucy = UIParent:GetCenter()
|
||||
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()
|
||||
o.minimapX = mx - ucx
|
||||
o.minimapY = my - ucy
|
||||
applyPosition(this)
|
||||
applyPosition(btn)
|
||||
end
|
||||
|
||||
function MM:Create()
|
||||
if getglobal(BTN_NAME) then return getglobal(BTN_NAME) end
|
||||
|
||||
-- Parent to UIParent so we're not clipped to the minimap area.
|
||||
local btn = CreateFrame("Button", BTN_NAME, UIParent)
|
||||
-- Parent to Minimap so button-collector addons (MinimapButtonBag /
|
||||
-- MBB, and similar) can discover and manage this button the same way
|
||||
-- they discover Blizzard's built-in minimap buttons. SetPoint still
|
||||
-- anchors to UIParent CENTER so the button can be dragged anywhere
|
||||
-- on screen -- the anchor frame is independent of the parent frame.
|
||||
local btn = CreateFrame("Button", BTN_NAME, Minimap)
|
||||
btn:SetWidth(31); btn:SetHeight(31)
|
||||
btn:SetFrameStrata("MEDIUM")
|
||||
btn:SetFrameLevel(8)
|
||||
@@ -75,6 +88,12 @@ function MM:Create()
|
||||
btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||||
btn:RegisterForDrag("LeftButton", "RightButton")
|
||||
btn:SetMovable(true)
|
||||
-- Allow the button to sit off-screen (via /attune pos or /attune offscreen)
|
||||
-- while remaining discoverable by MinimapButtonBag.
|
||||
if btn.SetClampedToScreen then btn:SetClampedToScreen(false) end
|
||||
-- MBB-friendly highlight so the button visually matches other
|
||||
-- minimap buttons once it has been swept into the bag.
|
||||
btn:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
|
||||
|
||||
-- Round border ring (standard minimap-button look)
|
||||
local overlay = btn:CreateTexture(nil, "OVERLAY")
|
||||
@@ -89,6 +108,7 @@ function MM:Create()
|
||||
icon:SetPoint("TOPLEFT", btn, "TOPLEFT", 7, -6)
|
||||
btn.icon = icon
|
||||
|
||||
|
||||
btn:SetScript("OnClick", function()
|
||||
if RA.UI and RA.UI.Toggle then RA.UI:Toggle() end
|
||||
end)
|
||||
@@ -107,6 +127,7 @@ function MM:Create()
|
||||
GameTooltip:AddLine("Relationships Attune", 1, 0.82, 0)
|
||||
GameTooltip:AddLine("Left-click: open / close window", 0.9, 0.9, 0.9)
|
||||
GameTooltip:AddLine("Drag: move anywhere on screen", 0.9, 0.9, 0.9)
|
||||
GameTooltip:AddLine("/attune offscreen - park off-screen (MBB safe)", 0.6, 0.8, 1)
|
||||
GameTooltip:AddLine("/attune hide - hide this button", 0.6, 0.8, 1)
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
|
||||
@@ -1,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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Title: Relationships Attune
|
||||
## Notes: Track Vanilla and Turtle/Octo WoW attunement progress
|
||||
## Author: Relationship
|
||||
## Version: 1.4
|
||||
## Version: 1.8
|
||||
## X-Category: Quest
|
||||
## SavedVariables: RelationshipsAttuneDB
|
||||
## SavedVariablesPerCharacter: RelationshipsAttuneCharDB
|
||||
|
||||
@@ -26,6 +26,55 @@ local C_TURTLE = { 0.55, 0.85, 1.00 }
|
||||
local C_KEYS = { 0.95, 0.75, 0.35 }
|
||||
local C_INPROGRESS = { 1.00, 0.60, 0.15 } -- orange: quest accepted / step in progress
|
||||
|
||||
-- ---------------------------------------------------------------
|
||||
-- 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 selectedRaid = nil
|
||||
|
||||
@@ -196,6 +245,29 @@ function UI:Build()
|
||||
detail.category = fs(frame.rightPane, "", 10, 0.75, 0.75, 0.75)
|
||||
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
|
||||
-- always has a resolvable width, then size the fill from that width.
|
||||
detail.barBG = solid(frame.rightPane, "BORDER", 0, 0, 0, 0.90)
|
||||
@@ -566,6 +638,20 @@ function UI:RenderDetail()
|
||||
detail.barFill:SetVertexColor(c[1], c[2], c[3], 0.95)
|
||||
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
|
||||
local applicable = {}
|
||||
for i = 1, table.getn(att.steps) do
|
||||
|
||||
Reference in New Issue
Block a user