-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCore.lua
More file actions
248 lines (219 loc) · 7.69 KB
/
Core.lua
File metadata and controls
248 lines (219 loc) · 7.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
local ADDON, NS = ...
NS.GUILD_NAME = "Mischievous"
-- ===== Chat helpers =====
local function Print(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff88Mischievous|r: " .. tostring(msg))
end
local function DPrint(...)
local out = {}
for i = 1, select("#", ...) do out[i] = tostring(select(i, ...)) end
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff88Mischievous|r: " .. table.concat(out, " "))
end
Print("loaded") -- sanity ping
-- ===== Abbreviations =====
local ABBR = {
["Havoc"]="Havoc", ["Vengeance"]="Veng",
["Balance"]="Balance", ["Feral"]="Feral", ["Guardian"]="Guard", ["Restoration"]="Resto",
["Devastation"]="Deva", ["Preservation"]="Pres", ["Augmentation"]="Aug",
["Beast Mastery"]="BM", ["Marksmanship"]="MM", ["Survival"]="Surv",
["Arcane"]="Arc", ["Fire"]="Fire", ["Frost"]="Frost",
["Brewmaster"]="Brew", ["Mistweaver"]="Mist", ["Windwalker"]="WW",
["Holy"]="Holy", ["Protection"]="Prot", ["Retribution"]="Ret",
["Discipline"]="Disc", ["Shadow"]="Shad",
["Assassination"]="Assa", ["Outlaw"]="Out", ["Subtlety"]="Sub",
["Elemental"]="Ele", ["Enhancement"]="Enh",
["Affliction"]="Aff", ["Demonology"]="Demo", ["Destruction"]="Destro",
["Arms"]="Arms", ["Fury"]="Fury",
}
local function Abbreviate(specName) return ABBR[specName] or specName end
-- ===== SavedVariables & migration =====
MischievousAddonDB = MischievousAddonDB or {}
local function MigrateDB()
if MischievousAddonDB.specName and not MischievousAddonDB.specs then
MischievousAddonDB.specs = { [MischievousAddonDB.specName] = true }
MischievousAddonDB.specName = nil
end
MischievousAddonDB.specs = MischievousAddonDB.specs or {}
end
-- ===== API shims (Retail vs Classic) =====
local function RequestGuildRoster()
if C_GuildInfo and C_GuildInfo.GuildRoster then
C_GuildInfo.GuildRoster()
elseif GuildRoster then
GuildRoster()
end
end
local function SetPublicNoteByIndex(index, fullName, note)
if GuildRosterSetPublicNote then
GuildRosterSetPublicNote(index, note)
return true
elseif C_GuildInfo and C_GuildInfo.SetPublicNote and fullName then
C_GuildInfo.SetPublicNote(fullName, note)
return true
end
return false
end
-- ===== Helpers =====
local function GetEquippedIlvl()
local _, equipped = GetAverageItemLevel()
if not equipped or equipped <= 0 then return nil end
return math.floor(equipped + 0.0001)
end
local function GetChosenSpecs()
MigrateDB()
local t = {}
for specName, on in pairs(MischievousAddonDB.specs) do
if on then table.insert(t, specName) end
end
table.sort(t)
return t
end
local function IsTargetGuild()
if not IsInGuild() then return false end
local guildName = GetGuildInfo("player")
return guildName == NS.GUILD_NAME
end
-- Returns (index, fullName) for the player in the roster
local function FindSelfIndex()
if not IsInGuild() then return end
local pn, pr = UnitFullName("player")
for i = 1, GetNumGuildMembers() do
local name = GetGuildRosterInfo(i) -- first return is name
if name then
local bn, rm = strsplit("-", name)
if bn == pn and ((not rm or rm == "") or rm == pr) then
return i, name
end
end
end
end
-- Build desired note within 31 chars
local NOTE_LIMIT = 31
local function BuildNote(ilvl, specNames)
local base = tostring(ilvl) .. " / "
local out, added = base, 0
for _, s in ipairs(specNames) do
local a = Abbreviate(s)
local sep = (added == 0) and "" or ","
local candidate = out .. sep .. a
if #candidate <= NOTE_LIMIT then
out, added = candidate, added + 1
else
if #out + 1 <= NOTE_LIMIT then out = out .. "+" end
break
end
end
if out == base and #base > NOTE_LIMIT then out = string.sub(base, 1, NOTE_LIMIT) end
return out
end
-- ===== Debounce + rate limit state =====
local DEBOUNCE_SEC = 0.8 -- wait this long after last trigger
local MIN_INTERVAL = 3.0 -- don't set more often than this
local INFLIGHT_WINDOW= 1.2 -- ignore echoes for this long after a set
local _debouncePending = false
local _inflight = false
local _lastSentNote = nil
local _lastSentAt = 0
local function Now() return GetTime() end
-- ===== Core update (index setter + roster warmup retry) =====
local function PerformUpdate(verbose)
if not IsTargetGuild() then
if verbose then DPrint("Skipped: wrong guild:", tostring(GetGuildInfo("player"))) end
return
end
if _inflight then
if verbose then DPrint("Skipped: inflight guard") end
return
end
local ilvl = GetEquippedIlvl()
local picks = GetChosenSpecs()
if not ilvl or #picks == 0 then
if verbose then DPrint("Missing ilvl or no specs selected.") end
if not NS._setupHintShown then
Print("Type |cff00ff88/mischievous|r to choose your spec(s).")
NS._setupHintShown = true
end
return
end
local desired = BuildNote(ilvl, picks)
if desired == _lastSentNote and (Now() - _lastSentAt) < MIN_INTERVAL then
if verbose then DPrint("Skipped: same desired within rate limit.") end
return
end
RequestGuildRoster()
C_Timer.After(0.35, function()
local index, fullName = FindSelfIndex()
local function trySet(i, full)
local _, _, _, _, _, _, current = GetGuildRosterInfo(i)
if current == desired then
if verbose then DPrint("No change needed (already matches).") end
return
end
if (Now() - _lastSentAt) < MIN_INTERVAL then
if verbose then DPrint("Rate-limited; will skip.") end
return
end
if SetPublicNoteByIndex(i, full, desired) then
_inflight = true
_lastSentNote, _lastSentAt = desired, Now()
Print("Updated guild note to: |cff00ff88" .. desired .. "|r")
C_Timer.After(INFLIGHT_WINDOW, function() _inflight = false end)
elseif verbose then
DPrint("Set note call failed (API unavailable or throttled).")
end
end
if not index then
-- Try again shortly; roster may still be warming
C_Timer.After(0.6, function()
local i2, full2 = FindSelfIndex()
if i2 then trySet(i2, full2)
elseif verbose then DPrint("Roster not ready; will try again on next guild event.") end
end)
return
end
trySet(index, fullName)
end)
end
-- Debounced entry point
local function RequestUpdate(verbose)
if _debouncePending then return end
_debouncePending = true
C_Timer.After(DEBOUNCE_SEC, function()
_debouncePending = false
PerformUpdate(verbose)
end)
end
-- Expose for Config.lua
NS._UpdateNoteIfNeeded = function() RequestUpdate(false) end
-- ===== Frame & events =====
local f = CreateFrame("Frame")
f:RegisterEvent("PLAYER_ENTERING_WORLD")
f:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
f:RegisterEvent("PLAYER_AVG_ITEM_LEVEL_UPDATE")
f:RegisterEvent("GUILD_ROSTER_UPDATE")
f:RegisterEvent("PLAYER_GUILD_UPDATE") -- extra reliability
f:SetScript("OnEvent", function(_, event)
if event == "PLAYER_ENTERING_WORLD" then
MigrateDB()
C_Timer.After(2.0, function()
if IsTargetGuild() and next(MischievousAddonDB.specs) == nil then
NS.ShowConfig()
end
end)
C_Timer.After(3.0, function() RequestUpdate(false) end)
elseif event == "PLAYER_EQUIPMENT_CHANGED" or event == "PLAYER_AVG_ITEM_LEVEL_UPDATE" then
RequestUpdate(false)
elseif event == "GUILD_ROSTER_UPDATE" or event == "PLAYER_GUILD_UPDATE" then
RequestUpdate(false)
end
end)
-- ===== Slash commands =====
SLASH_MISCHIEVOUS1 = "/mischievous"
SlashCmdList["MISCHIEVOUS"] = function() NS.ShowConfig() end
SLASH_MISCHDEBUG1 = "/mischdebug" -- prints state & tries an update
SlashCmdList["MISCHDEBUG"] = function() RequestUpdate(true) end
SLASH_MISCHSET1 = "/mischset" -- force roster refresh then update
SlashCmdList["MISCHSET"] = function()
RequestGuildRoster()
C_Timer.After(0.5, function() RequestUpdate(true) end)
end