Fix profsync guild-wide lag, price MC trash, bid on 0 GP items (10.20.5)
profsync: stop expanding skill headers on every read. Expand/CollapseSkillHeader fire SKILL_LINES_CHANGED, which this addon also listens to, so each read re-armed its own debounced check -- a permanent 15s cycle that dragged pfQuest's quest-giver rebuild and Cartographer's addon walk along with it on every guild member, whether or not they ever opened a profession. Reads are now plain scans that report whether a collapsed header may have censored them; an expand happens only where the difference actually matters (a known profession vanishing, the open window's own rank, /status), and is bracketed by a grace window so our own echo is ignored. A drop is never announced off an incomplete read. loot: only skip items with NO price entry. A price of 0 is a known item that just hasn't been priced yet, and it was silently skipping the bid/trade window. prices: Molten Core trash belts and bracers 0 -> 67 GP, Boots of Blistering Flames and Core Forged Helmet 100 -> 67, add Core Forged Greaves. minep default 300. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
879620200e
commit
f38395a95c
+21
-20
@@ -147,6 +147,7 @@ local prices = {
|
|||||||
[18808] = {125,"T1"}; --Gloves of the Hypnotic Flame
|
[18808] = {125,"T1"}; --Gloves of the Hypnotic Flame
|
||||||
[18809] = {125,"T1"}; --Sash of Whispered Secrets
|
[18809] = {125,"T1"}; --Sash of Whispered Secrets
|
||||||
[18812] = {125,"T1"}; --Wristguards of True Flight
|
[18812] = {125,"T1"}; --Wristguards of True Flight
|
||||||
|
[18806] = {9,"T1"}; --Core Forged Greaves
|
||||||
[19140] = {150,"T1"}; --Cauterizing Band
|
[19140] = {150,"T1"}; --Cauterizing Band
|
||||||
[18805] = {150,"T1"}; --Core Hound Tooth
|
[18805] = {150,"T1"}; --Core Hound Tooth
|
||||||
[18803] = {300,"T1"}; --Finkle's Lava Dredger
|
[18803] = {300,"T1"}; --Finkle's Lava Dredger
|
||||||
@@ -180,27 +181,27 @@ local prices = {
|
|||||||
[92080] = {9999,"T1"}; --Molten Corehound
|
[92080] = {9999,"T1"}; --Molten Corehound
|
||||||
|
|
||||||
--Trash Mobs
|
--Trash Mobs
|
||||||
[16817] = {0,"T1"}; --Girdle of Prophecy
|
[16817] = {67,"T1"}; --Girdle of Prophecy
|
||||||
[16802] = {0,"T1"}; --Arcanist Belt
|
[16802] = {67,"T1"}; --Arcanist Belt
|
||||||
[16806] = {0,"T1"}; --Felheart Belt
|
[16806] = {67,"T1"}; --Felheart Belt
|
||||||
[16827] = {0,"T1"}; --Nightslayer Belt
|
[16827] = {67,"T1"}; --Nightslayer Belt
|
||||||
[16828] = {0,"T1"}; --Cenarion Belt
|
[16828] = {67,"T1"}; --Cenarion Belt
|
||||||
[16851] = {0,"T1"}; --Giantstalker's Belt
|
[16851] = {67,"T1"}; --Giantstalker's Belt
|
||||||
[16838] = {0,"T1"}; --Earthfury Belt
|
[16838] = {67,"T1"}; --Earthfury Belt
|
||||||
[16858] = {0,"T1"}; --Lawbringer Belt
|
[16858] = {67,"T1"}; --Lawbringer Belt
|
||||||
[16864] = {0,"T1"}; --Belt of Might
|
[16864] = {67,"T1"}; --Belt of Might
|
||||||
[81260] = {150,"T1"}; --Lavashard Axe
|
[81260] = {150,"T1"}; --Lavashard Axe
|
||||||
[16819] = {0,"T1"}; --Vambraces of Prophecy
|
[16819] = {67,"T1"}; --Vambraces of Prophecy
|
||||||
[16799] = {0,"T1"}; --Arcanist Bindings
|
[16799] = {67,"T1"}; --Arcanist Bindings
|
||||||
[16804] = {0,"T1"}; --Felheart Bracers
|
[16804] = {67,"T1"}; --Felheart Bracers
|
||||||
[16825] = {0,"T1"}; --Nightslayer Bracelets
|
[16825] = {67,"T1"}; --Nightslayer Bracelets
|
||||||
[16830] = {0,"T1"}; --Cenarion Bracers
|
[16830] = {67,"T1"}; --Cenarion Bracers
|
||||||
[16850] = {0,"T1"}; --Giantstalker's Bracers
|
[16850] = {67,"T1"}; --Giantstalker's Bracers
|
||||||
[16840] = {0,"T1"}; --Earthfury Bracers
|
[16840] = {67,"T1"}; --Earthfury Bracers
|
||||||
[16857] = {0,"T1"}; --Lawbringer Bracers
|
[16857] = {67,"T1"}; --Lawbringer Bracers
|
||||||
[16861] = {0,"T1"}; --Bracers of Might
|
[16861] = {67,"T1"}; --Bracers of Might
|
||||||
[81261] = {100,"T1"}; --Boots of Blistering Flames
|
[81261] = {67,"T1"}; --Boots of Blistering Flames
|
||||||
[81262] = {100,"T1"}; --Core Forged Helmet
|
[81262] = {67,"T1"}; --Core Forged Helmet
|
||||||
[81263] = {125,"T1"}; --Lost Dark Iron Chain
|
[81263] = {125,"T1"}; --Lost Dark Iron Chain
|
||||||
[81264] = {125,"T1"}; --Shoulderpads of True Flight
|
[81264] = {125,"T1"}; --Shoulderpads of True Flight
|
||||||
[81265] = {125,"T1"}; --Ashskin Belt
|
[81265] = {125,"T1"}; --Ashskin Belt
|
||||||
|
|||||||
+109
-35
@@ -109,6 +109,11 @@ local LEARN_SETTLE = 12 -- quiet time after the last "you have learned"
|
|||||||
local LEARN_MAX_WAIT = 90 -- ...but never postpone a learn batch longer than this
|
local LEARN_MAX_WAIT = 90 -- ...but never postpone a learn batch longer than this
|
||||||
local RANK_MIN_GAP = 300 -- min seconds between two skill-level-only messages
|
local RANK_MIN_GAP = 300 -- min seconds between two skill-level-only messages
|
||||||
local SKILL_DEBOUNCE = 15 -- settle time after SKILL_LINES_CHANGED
|
local SKILL_DEBOUNCE = 15 -- settle time after SKILL_LINES_CHANGED
|
||||||
|
-- ⚠ Expanding or collapsing a skill header FIRES SKILL_LINES_CHANGED — see the
|
||||||
|
-- warning above ReadSkills. This is how long the addon disbelieves that event
|
||||||
|
-- after having caused it itself. A genuine skill-up landing inside the window is
|
||||||
|
-- simply missed, which costs a cosmetic rank line until the next idle sweep.
|
||||||
|
local SKILL_ECHO_GRACE = 1
|
||||||
local IDLE_CHECK = 300 -- background skill re-check cadence
|
local IDLE_CHECK = 300 -- background skill re-check cadence
|
||||||
local ACK_TIMEOUT = 60 -- how long a batch may sit unacknowledged
|
local ACK_TIMEOUT = 60 -- how long a batch may sit unacknowledged
|
||||||
local RETRY_DELAY = 600 -- pause everything after finding the relay offline
|
local RETRY_DELAY = 600 -- pause everything after finding the relay offline
|
||||||
@@ -186,6 +191,7 @@ local pending = {} -- [profId] = batch awaiting acknowledgement
|
|||||||
local metaCache = {} -- [profId][recipeId] = { n = name, i = icon }
|
local metaCache = {} -- [profId][recipeId] = { n = name, i = icon }
|
||||||
local metaRounds = 0
|
local metaRounds = 0
|
||||||
local skillsCheckAt = nil -- debounced SKILL_LINES_CHANGED handler
|
local skillsCheckAt = nil -- debounced SKILL_LINES_CHANGED handler
|
||||||
|
local skillEchoUntil = nil -- ignore SKILL_LINES_CHANGED we caused ourselves
|
||||||
local nextIdleCheck = nil
|
local nextIdleCheck = nil
|
||||||
local learnSettleAt = nil -- debounced "you have learned" burst
|
local learnSettleAt = nil -- debounced "you have learned" burst
|
||||||
local learnFirstAt = nil -- start of the current burst, bounds the debounce
|
local learnFirstAt = nil -- start of the current burst, bounds the debounce
|
||||||
@@ -523,32 +529,26 @@ local function RestoreSkillHeaders(collapsed)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns [profId] = { r = rank, m = max } for every tracked profession this
|
local function AnyCollapsedHeader()
|
||||||
-- character has, or nil when the pane could not be read cleanly right now.
|
|
||||||
local function ReadSkills()
|
|
||||||
local anyCollapsed = false
|
|
||||||
for i = 1, GetNumSkillLines() do
|
for i = 1, GetNumSkillLines() do
|
||||||
local _, isHeader, isExpanded = GetSkillLineInfo(i)
|
local _, isHeader, isExpanded = GetSkillLineInfo(i)
|
||||||
if isHeader and not isExpanded then anyCollapsed = true break end
|
if isHeader and not isExpanded then return true end
|
||||||
end
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local restore = nil
|
-- ⚠ A NAME CAN APPEAR TWICE. "Survival" is both a Turtle profession and a
|
||||||
if anyCollapsed then
|
-- hunter's class skill line, and a hunter sees both in this pane, so the last
|
||||||
restore = ExpandSkillHeaders()
|
-- one read must not win by accident — the higher cap does, which is always the
|
||||||
if not restore then return nil end
|
-- profession. A hunter who does NOT have the profession is caught later and
|
||||||
end
|
-- more cheaply: nothing in their spellbook opens it, so it is never scanned
|
||||||
|
-- and never reported.
|
||||||
-- ⚠ A NAME CAN APPEAR TWICE. "Survival" is both a Turtle profession and a
|
--
|
||||||
-- hunter's class skill line, and a hunter sees both in this pane, so the last
|
-- Deliberately no minimum-cap gate here. It would be a second way to tell the
|
||||||
-- one read must not win by accident — the higher cap does, which is always the
|
-- two apart, but it is also a single condition that could silently blank every
|
||||||
-- profession. A hunter who does NOT have the profession is caught later and
|
-- profession on a client whose returns differ, and the spellbook check already
|
||||||
-- more cheaply: nothing in their spellbook opens it, so it is never scanned
|
-- covers the case.
|
||||||
-- and never reported.
|
local function ScanSkillLines()
|
||||||
--
|
|
||||||
-- Deliberately no minimum-cap gate here. It would be a second way to tell the
|
|
||||||
-- two apart, but it is also a single condition that could silently blank every
|
|
||||||
-- profession on a client whose returns differ, and the spellbook check already
|
|
||||||
-- covers the case.
|
|
||||||
local out = {}
|
local out = {}
|
||||||
for i = 1, GetNumSkillLines() do
|
for i = 1, GetNumSkillLines() do
|
||||||
local name, isHeader, _, rank, _, _, maxRank = GetSkillLineInfo(i)
|
local name, isHeader, _, rank, _, _, maxRank = GetSkillLineInfo(i)
|
||||||
@@ -562,11 +562,48 @@ local function ReadSkills()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
RestoreSkillHeaders(restore)
|
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[ ⚠ EXPANDING A SKILL HEADER IS EXPENSIVE FOR THE WHOLE UI, NOT JUST FOR US.
|
||||||
|
|
||||||
|
ExpandSkillHeader/CollapseSkillHeader fire SKILL_LINES_CHANGED — FrameXML's own
|
||||||
|
expand button calls nothing else and relies on that event to redraw the pane —
|
||||||
|
and that event goes to EVERY addon. On a normal OctoWoW install it lands on
|
||||||
|
pfQuest, whose handler compares the visible skill-line names and, because
|
||||||
|
collapsing a header hides its children from GetSkillLineInfo, sees a change
|
||||||
|
every single time and runs a full pfDatabase:SearchQuests() quest-giver rebuild;
|
||||||
|
and on Cartographer's Professions module, which walks GetNumAddOns() calling
|
||||||
|
GetAddOnMetadata on every installed addon.
|
||||||
|
|
||||||
|
Worse, it used to feed itself: this addon listens to SKILL_LINES_CHANGED too,
|
||||||
|
so its own expand/collapse re-armed the debounced check, which read the skills
|
||||||
|
again, which expanded again — a permanent 15-second cycle of quest-giver
|
||||||
|
rebuilds on every guild member, whether or not they ever opened a profession.
|
||||||
|
That is what made the whole guild lag (2026-08-09).
|
||||||
|
|
||||||
|
So: the plain read NEVER touches a header, and callers that can live with a
|
||||||
|
partial answer ask for one. `mayExpand` is for the rare case where the
|
||||||
|
difference actually matters — telling "profession abandoned" apart from
|
||||||
|
"profession hidden under a collapsed header" — and it brackets the mutation in
|
||||||
|
skillEchoUntil so our own echo is not mistaken for a real skill change.
|
||||||
|
|
||||||
|
Returns skills, complete. `complete` false means a collapsed header may be
|
||||||
|
hiding professions, so a MISSING one proves nothing. ]]
|
||||||
|
local function ReadSkills(mayExpand)
|
||||||
|
local skills = ScanSkillLines()
|
||||||
|
if not AnyCollapsedHeader() then return skills, true end
|
||||||
|
if not mayExpand then return skills, false end
|
||||||
|
|
||||||
|
skillEchoUntil = GetTime() + SKILL_ECHO_GRACE
|
||||||
|
local restore = ExpandSkillHeaders() -- nil when the Skills pane is open
|
||||||
|
if not restore then return skills, false end
|
||||||
|
skills = ScanSkillLines()
|
||||||
|
RestoreSkillHeaders(restore)
|
||||||
|
skillEchoUntil = GetTime() + SKILL_ECHO_GRACE
|
||||||
|
return skills, true
|
||||||
|
end
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------------
|
-- ---------------------------------------------------------------------------
|
||||||
-- Reading an open profession window
|
-- Reading an open profession window
|
||||||
-- ---------------------------------------------------------------------------
|
-- ---------------------------------------------------------------------------
|
||||||
@@ -790,13 +827,31 @@ end
|
|||||||
|
|
||||||
local function CheckSkills()
|
local function CheckSkills()
|
||||||
if not CanSend() then return end
|
if not CanSend() then return end
|
||||||
local skills = ReadSkills()
|
local skills, complete = ReadSkills(false)
|
||||||
if not skills then
|
|
||||||
skillsCheckAt = GetTime() + SKILL_DEBOUNCE -- Skills pane open, come back
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local db = DB()
|
local db = DB()
|
||||||
|
|
||||||
|
-- ⚠ Only pay for a header expand when a profession we ALREADY KNOW ABOUT has
|
||||||
|
-- vanished from the read, because that is the single decision a partial read
|
||||||
|
-- cannot make (see ReadSkills for what an expand costs the rest of the UI). A
|
||||||
|
-- rank read off a visible line is trustworthy on its own, and a BRAND NEW
|
||||||
|
-- profession hidden under a collapsed header is not worth an expand either:
|
||||||
|
-- opening its window is the only way to use it, and that reports the rank
|
||||||
|
-- alongside the recipes.
|
||||||
|
if not complete then
|
||||||
|
local suspect = false
|
||||||
|
for id in pairs(db.profs) do
|
||||||
|
if PROF_BY_ID[id] and not skills[id] then suspect = true break end
|
||||||
|
end
|
||||||
|
if suspect then
|
||||||
|
local full, ok = ReadSkills(true)
|
||||||
|
if not ok then
|
||||||
|
skillsCheckAt = GetTime() + SKILL_DEBOUNCE -- Skills pane open, come back
|
||||||
|
return
|
||||||
|
end
|
||||||
|
skills, complete = full, ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Gone from the pane means abandoned. The row is kept, flagged, and only
|
-- Gone from the pane means abandoned. The row is kept, flagged, and only
|
||||||
-- deleted once the website confirms — otherwise a lost "dropped" message
|
-- deleted once the website confirms — otherwise a lost "dropped" message
|
||||||
-- would leave the site advertising recipes the player no longer has.
|
-- would leave the site advertising recipes the player no longer has.
|
||||||
@@ -809,7 +864,10 @@ local function CheckSkills()
|
|||||||
db.profs[id] = nil
|
db.profs[id] = nil
|
||||||
pending[id] = nil
|
pending[id] = nil
|
||||||
elseif not skills[id] then
|
elseif not skills[id] then
|
||||||
if not state.gone or not pending[id] then
|
-- Belt and braces: the suspect check above should have upgraded the read
|
||||||
|
-- to a complete one before we get here. Never announce a drop off a read
|
||||||
|
-- that a collapsed header could have censored.
|
||||||
|
if complete and (not state.gone or not pending[id]) then
|
||||||
state.gone = true
|
state.gone = true
|
||||||
pending[id] = { drop = true, at = GetTime() }
|
pending[id] = { drop = true, at = GetTime() }
|
||||||
Send("X", tostring(id))
|
Send("X", tostring(id))
|
||||||
@@ -1043,8 +1101,16 @@ local function OnWindowVisible(isCraft)
|
|||||||
|
|
||||||
if prof then
|
if prof then
|
||||||
local state = ProfState(prof.id)
|
local state = ProfState(prof.id)
|
||||||
local skills = ReadSkills()
|
-- The cheap read first; only if THIS profession is the one hidden under a
|
||||||
|
-- collapsed header is an expand worth it — and here it is, because the
|
||||||
|
-- alternative is publishing a rank of 0/0. This path already only runs when
|
||||||
|
-- the recipe list actually changed, so it is rare.
|
||||||
|
local skills = ReadSkills(false)
|
||||||
local info = skills and skills[prof.id]
|
local info = skills and skills[prof.id]
|
||||||
|
if not info then
|
||||||
|
skills = ReadSkills(true)
|
||||||
|
info = skills and skills[prof.id]
|
||||||
|
end
|
||||||
-- The stored rank is -1 until the website has confirmed one, which is not
|
-- The stored rank is -1 until the website has confirmed one, which is not
|
||||||
-- a number to put on the wire; fall back to 0 when the pane is unreadable.
|
-- a number to put on the wire; fall back to 0 when the pane is unreadable.
|
||||||
local rank = (info and info.r) or state.r
|
local rank = (info and info.r) or state.r
|
||||||
@@ -1107,6 +1173,12 @@ f:SetScript("OnEvent", function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if event == "SKILL_LINES_CHANGED" then
|
if event == "SKILL_LINES_CHANGED" then
|
||||||
|
-- ⚠ IGNORE OUR OWN ECHO. Expanding or collapsing a header to read the pane
|
||||||
|
-- fires this event, so without the grace window the check that did the
|
||||||
|
-- expanding re-arms itself and runs again forever, every SKILL_DEBOUNCE
|
||||||
|
-- seconds, dragging pfQuest's quest-giver rebuild along with it. See
|
||||||
|
-- ReadSkills.
|
||||||
|
if skillEchoUntil and GetTime() < skillEchoUntil then return end
|
||||||
-- Fires on every point of skill-up, so it only arms a debounced check; that
|
-- Fires on every point of skill-up, so it only arms a debounced check; that
|
||||||
-- check sends nothing unless a profession appeared, vanished, or moved.
|
-- check sends nothing unless a profession appeared, vanished, or moved.
|
||||||
skillsCheckAt = GetTime() + SKILL_DEBOUNCE
|
skillsCheckAt = GetTime() + SKILL_DEBOUNCE
|
||||||
@@ -1198,10 +1270,12 @@ local function PrintStatus()
|
|||||||
or (online and " online" or " OFFLINE"))
|
or (online and " online" or " OFFLINE"))
|
||||||
Say("guild " .. guild .. " | relay " .. relay)
|
Say("guild " .. guild .. " | relay " .. relay)
|
||||||
|
|
||||||
local skills = ReadSkills()
|
-- A human typed this, so the expand is worth it here whatever it costs.
|
||||||
if not skills then
|
local skills, complete = ReadSkills(true)
|
||||||
Say("could not read the Skills pane (close the character window)")
|
if not complete then
|
||||||
else
|
Say("partial reading — close the character window for the full picture")
|
||||||
|
end
|
||||||
|
do
|
||||||
local parts, any = {}, false
|
local parts, any = {}, false
|
||||||
for id, info in pairs(skills) do
|
for id, info in pairs(skills) do
|
||||||
local prof = PROF_BY_ID[id]
|
local prof = PROF_BY_ID[id]
|
||||||
|
|||||||
+9
-3
@@ -10,7 +10,7 @@ local T = AceLibrary("Tablet-2.0")
|
|||||||
local L = AceLibrary("AceLocale-2.2"):new("shootyepgp")
|
local L = AceLibrary("AceLocale-2.2"):new("shootyepgp")
|
||||||
sepgp.VARS = {
|
sepgp.VARS = {
|
||||||
basegp = 300,
|
basegp = 300,
|
||||||
minep = 0,
|
minep = 300,
|
||||||
baseaward_ep = 100,
|
baseaward_ep = 100,
|
||||||
decay = 0.9,
|
decay = 0.9,
|
||||||
max = 1000,
|
max = 1000,
|
||||||
@@ -2250,7 +2250,10 @@ function sepgp:tradeLoot(playerState,targetState)
|
|||||||
local link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])")
|
local link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])")
|
||||||
if (link_found) then
|
if (link_found) then
|
||||||
local price = sepgp_prices:GetPrice(itemString,sepgp_progress)
|
local price = sepgp_prices:GetPrice(itemString,sepgp_progress)
|
||||||
if not (price) or price == 0 then
|
-- Only skip items with NO price entry (untracked trash). A price of 0
|
||||||
|
-- means a known item that just hasn't been priced yet (Gear Points seeds
|
||||||
|
-- new items at 0) -- still open the window so it can be handed out/logged.
|
||||||
|
if not (price) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local bind = self:itemBinding(itemString)
|
local bind = self:itemBinding(itemString)
|
||||||
@@ -2380,7 +2383,10 @@ function sepgp:processLoot(player,itemLink,source)
|
|||||||
local bind = self:itemBinding(itemString)
|
local bind = self:itemBinding(itemString)
|
||||||
if not (bind) then return end
|
if not (bind) then return end
|
||||||
local price = sepgp_prices:GetPrice(itemString,sepgp_progress)
|
local price = sepgp_prices:GetPrice(itemString,sepgp_progress)
|
||||||
if (not (price)) or (price == 0) then
|
-- Only skip items with NO price entry (untracked trash). A price of 0 means
|
||||||
|
-- a known item that just hasn't been priced yet (Gear Points seeds new items
|
||||||
|
-- at 0) -- still open the MS/OS window so it can be handed out/logged.
|
||||||
|
if (not (price)) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local class,_
|
local class,_
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
## X-Website: https://github.com/cinecom/shootyepgp/
|
## X-Website: https://github.com/cinecom/shootyepgp/
|
||||||
## X-Category: Guild
|
## X-Category: Guild
|
||||||
## X-Credits: shooty, Qcat(zhCN)
|
## X-Credits: shooty, Qcat(zhCN)
|
||||||
## Version: 10.20.3 <ERROR>
|
## Version: 10.20.5 <ERROR>
|
||||||
## X-Alpha:
|
## X-Alpha:
|
||||||
## OptionalDeps: Ace2
|
## OptionalDeps: Ace2
|
||||||
## SavedVariables: sepgp_saychannel, sepgp_groupbyclass, sepgp_groupbyarmor, sepgp_groupbyrole, sepgp_raidonly, sepgp_dbver, sepgp_debug, sepgp_fubar, sepgp_sound, RaidStrikeDB, RaidStrikeResetTime
|
## SavedVariables: sepgp_saychannel, sepgp_groupbyclass, sepgp_groupbyarmor, sepgp_groupbyrole, sepgp_raidonly, sepgp_dbver, sepgp_debug, sepgp_fubar, sepgp_sound, RaidStrikeDB, RaidStrikeResetTime
|
||||||
|
|||||||
Reference in New Issue
Block a user