-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCore.lua
More file actions
311 lines (283 loc) · 12.9 KB
/
Core.lua
File metadata and controls
311 lines (283 loc) · 12.9 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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
-- NSRTEnhancer / Core
-- Shared namespace, saved-variable defaults, slash commands, event loader,
-- and shared helpers used by both features.
local ADDON_NAME, NSE = ...
_G.NSRTEnhancer = NSE
-- ---------------------------------------------------------------------------
-- Defaults
-- ---------------------------------------------------------------------------
NSE.defaults = {
pastReminders = {
enabled = true,
},
onDeck = {
enabled = true,
locked = true,
position = { point = "CENTER", relPoint = "CENTER", x = 0, y = -160 },
orientation = "HORIZONTAL", -- "HORIZONTAL" (upcoming-left, center, ready-right) | "VERTICAL" (upcoming-top, center, ready-bottom)
queueDepth = 3, -- how many icons total (center + N-1 on the left/top)
iconSize = 52, -- center icon size in px; left icons shrink from this
iconSpacing = 6, -- gap between adjacent icons
sizeStep = 0.75, -- each step left = size * this
alphaStep = 0.55, -- each step left = alpha * this
minAlpha = 0.15, -- floor on alpha (so far-left icons are still visible)
lingerSeconds = 5, -- how long a "use now" icon lingers in the right stack after hitting 0
readyStackMax = 3, -- max number of "use now" icons shown to the right of center (1-5)
suppressNSRT = false, -- hide NSRT's own reminder icons/bars/text (use NSE's On Deck as sole display)
font = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF",
fontSize = 20,
fontOutline = "OUTLINE",
fontColor = { 1, 0.9, 0.2, 1 }, -- slightly warm white/yellow
timerPosition = "CENTER", -- "CENTER" (overlaid on icon) | "ABOVE" (floating above icon)
showBackground = false,
backgroundColor = { 0, 0, 0, 0.35 },
pandemicGlow = {
enabled = true,
type = "Pixel", -- "Pixel" | "AutoCast" | "Button"
color = { 1, 0.6, 0.1, 1 }, -- orange-ish
},
},
voice = {
-- Per-source TTS voice overrides. false = "inherit NSRT default".
-- These are applied by wrapping NSAPI.TTS so NSRT's own code keeps
-- working untouched.
enabled = true,
personalVoiceID = false,
assignedVoiceID = false,
-- Volume boost: the SpeakText API caps volume at 100, but we can
-- layer multiple simultaneous calls for a louder effect. 1 = normal,
-- 2-4 = progressively louder via overlapping playback.
volumeBoost = 1,
},
onYou = {
-- Full-screen flash when DBM announces an ability that's on the
-- local player. Only active while DBM is installed.
enabled = true,
flashColor = { 0.6, 0.2, 0.9, 1 }, -- purple
flashOpacity = 0.6, -- peak alpha per pulse
flashCount = 3,
flashDuration = 0.35, -- seconds per pulse
textEnabled = true,
text = "THIS IS ON YOU",
textSize = 48,
textOutline = "THICKOUTLINE",
textColor = { 1, 1, 1, 1 },
-- Auto mode: fall back to flashing on any DBM "you*" warning or
-- "target*" warning where the text contains the local player's
-- name, for spells the user hasn't explicitly configured.
autoMode = true,
-- Per-spell opt-in with custom text. Populated by auto-discovery on
-- DBM_Pull (see OnYou.lua). Each entry:
-- { enabled, customText, bossName, defaultText, kind, modId }
-- keyed by numeric spellId.
spells = {},
},
}
-- Recursive defaults merge -- only fills in missing keys, preserving user changes.
local function applyDefaults(target, defaults)
for k, v in pairs(defaults) do
if type(v) == "table" then
if type(target[k]) ~= "table" then target[k] = {} end
applyDefaults(target[k], v)
elseif target[k] == nil then
target[k] = v
end
end
return target
end
-- ---------------------------------------------------------------------------
-- Runtime state + shared helpers
-- ---------------------------------------------------------------------------
NSE.state = {
encounterStart = nil,
}
-- Returns (elapsed_seconds, phase) for the active context, or nil if neither
-- an encounter nor the Timeline preview is running. Preview wins if both are
-- active (preview clock is authoritative).
function NSE:GetContext()
local tw = _G.NSUITimelineWindow
if tw and tw.previewActive and tw.previewStartTime then
return GetTime() - tw.previewStartTime, 1
end
if NSE.state.encounterStart then
return GetTime() - NSE.state.encounterStart, 1
end
return nil
end
-- Returns the pristine personal-reminder text (preferring frame.OriginalText,
-- falling back to what's currently drawn).
function NSE:GetReminderText()
local frame = _G.NSUIPersonalReminderFrame
if not frame then return nil end
return frame.OriginalText or (frame.Text and frame.Text:GetText())
end
-- ---------------------------------------------------------------------------
-- Shared note parser (single-parse cache consumed by PastReminders + OnDeck)
-- ---------------------------------------------------------------------------
--
-- Both features previously re-parsed the same note text every tick (up to
-- 14x/sec combined). Instead we parse once per *text change* and both
-- consumers scan the resulting array with zero regex work.
--
-- Each entry: {
-- raw = original line
-- phase = integer phase (inherited from last "Phase N" header)
-- isPhaseHeader = true if this line is the "Phase N" header itself
-- time = seconds (number) if line has an MM:SS timestamp
-- icon = texture path/id if line has a spell icon escape
-- minStr/secStr = the MM / SS substrings (for gsub-based rewrite)
-- }
NSE.NoteParser = {}
local _parseCacheText, _parseCacheEntries
function NSE.NoteParser:Get()
local frame = _G.NSUIPersonalReminderFrame
if not frame then return nil end
local text = frame.OriginalText or (frame.Text and frame.Text:GetText())
if not text or text == "" then return nil end
if text == _parseCacheText then return _parseCacheEntries end
local entries = {}
local curphase = 100
local t = text
if not t:match("\n$") then t = t .. "\n" end
for line in t:gmatch("([^\n]*)\n") do
local ph = line:match("Phase (%d+)")
if ph then curphase = tonumber(ph) or curphase end
local m, s = line:match("(%d+):(%d%d)")
local tsec
if m and s then tsec = tonumber(m) * 60 + tonumber(s) end
-- Spell icon is the LAST |T...|t in the line (raid markers before it).
local icon
if tsec then
for it in line:gmatch("|T([^:|]+)") do icon = it end
if icon then icon = tonumber(icon) or icon end
end
entries[#entries + 1] = {
raw = line,
phase = curphase,
isPhaseHeader = ph ~= nil,
time = tsec,
icon = icon,
minStr = m,
secStr = s,
}
end
_parseCacheText = text
_parseCacheEntries = entries
return entries
end
-- ---------------------------------------------------------------------------
-- Event loader
-- ---------------------------------------------------------------------------
local events = CreateFrame("Frame")
events:RegisterEvent("ADDON_LOADED")
events:RegisterEvent("PLAYER_LOGIN")
events:RegisterEvent("ENCOUNTER_START")
events:RegisterEvent("ENCOUNTER_END")
events:SetScript("OnEvent", function(self, event, arg1)
if event == "ADDON_LOADED" and arg1 == ADDON_NAME then
NSRTEnhancerDB = NSRTEnhancerDB or {}
applyDefaults(NSRTEnhancerDB, NSE.defaults)
NSE.db = NSRTEnhancerDB
-- Clamp saved values that exceed new lower caps (e.g. users who had
-- readyStackMax = 7 before we lowered the ceiling to 5).
if NSE.db.onDeck then
if type(NSE.db.onDeck.readyStackMax) == "number" and NSE.db.onDeck.readyStackMax > 5 then
NSE.db.onDeck.readyStackMax = 5
end
end
elseif event == "PLAYER_LOGIN" then
if NSE.PastReminders and NSE.PastReminders.Init then NSE.PastReminders:Init() end
if NSE.OnDeck and NSE.OnDeck.Init then NSE.OnDeck:Init() end
if NSE.Voice and NSE.Voice.Init then NSE.Voice:Init() end
if NSE.OnYou and NSE.OnYou.Init then NSE.OnYou:Init() end
if NSE.GUI and NSE.GUI.Init then NSE.GUI:Init() end
elseif event == "ENCOUNTER_START" then
NSE.state.encounterStart = GetTime()
elseif event == "ENCOUNTER_END" then
NSE.state.encounterStart = nil
end
end)
-- ---------------------------------------------------------------------------
-- Slash commands
-- ---------------------------------------------------------------------------
SLASH_NSRTENHANCER1 = "/nse"
SLASH_NSRTENHANCER2 = "/nsrte"
SlashCmdList["NSRTENHANCER"] = function(msg)
msg = (msg or ""):lower():match("^%s*(.-)%s*$")
if msg == "reset" then
-- Recover from anything dragged off-screen.
if _G.NSRTEnhancerConfigFrame then
_G.NSRTEnhancerConfigFrame:ClearAllPoints()
_G.NSRTEnhancerConfigFrame:SetPoint("CENTER")
end
if NSE.db and NSE.db.onDeck then
NSE.db.onDeck.position = { point = "CENTER", relPoint = "CENTER", x = 0, y = -160 }
if NSE.OnDeck and NSE.OnDeck.ApplyLayout then NSE.OnDeck:ApplyLayout() end
end
print("|cff33ccffNSRT Enhancer|r: config window and On Deck frame reset to center.")
return
end
if msg == "timeline" or msg == "tl" then
-- Delegate to NSRT's own `/ns timeline` handler so we hit the same
-- NSI:ToggleTimelineWindow() code path (NSI is private to NSRT).
if SlashCmdList and SlashCmdList["NSUI"] then
SlashCmdList["NSUI"]("timeline")
else
print("|cff33ccffNSRT Enhancer|r: NSRT slash handler not available -- is NSRT loaded?")
end
return
end
if msg == "clear" then
-- Equivalent to NSRT's own "Clear Reminder" button / `/ns pclear`:
-- deactivates the currently loaded personal reminder. Non-destructive
-- -- saved personal reminders in NSRT's reminder list are preserved.
-- We delegate to NSRT's slash handler because NSI is private to
-- that addon; this way NSRT gets to fully reprocess + update the
-- frame + fire its own NSRT_REMINDER_CHANGED callback.
if SlashCmdList and SlashCmdList["NSUI"] then
SlashCmdList["NSUI"]("pclear")
print("|cff33ccffNSRT Enhancer|r: active personal reminder cleared. Re-select one in NSRT when you want it back.")
else
print("|cff33ccffNSRT Enhancer|r: NSRT slash handler not available -- is NSRT loaded?")
end
return
end
if msg == "mute" or msg == "notes off" then
-- Hide NSRT's personal reminder note (the "timeline" in chat-speak).
-- Non-destructive: the user's saved personal reminders stay intact;
-- we just flip the display-enabled flag and hide the current frame.
if NSRT and NSRT.ReminderSettings and NSRT.ReminderSettings.PersonalReminderFrame then
NSRT.ReminderSettings.PersonalReminderFrame.enabled = false
end
if _G.NSUIPersonalReminderFrame then
_G.NSUIPersonalReminderFrame:Hide()
end
print("|cff33ccffNSRT Enhancer|r: personal reminder note muted. |cffffffff/nse unmute|r to restore.")
return
end
if msg == "unmute" or msg == "notes on" then
if NSRT and NSRT.ReminderSettings and NSRT.ReminderSettings.PersonalReminderFrame then
NSRT.ReminderSettings.PersonalReminderFrame.enabled = true
end
if _G.NSUIPersonalReminderFrame then
_G.NSUIPersonalReminderFrame:Show()
end
print("|cff33ccffNSRT Enhancer|r: personal reminder note restored.")
return
end
if msg == "help" or msg == "?" then
print("|cff33ccffNSRT Enhancer|r commands:")
print(" |cffffffff/nse|r Toggle the config window")
print(" |cffffffff/nse timeline|r Toggle NSRT's Timeline window (alias: tl)")
print(" |cffffffff/nse reset|r Reset window + On Deck to screen center")
print(" |cffffffff/nse clear|r Clear the active personal reminder (NSRT 'Clear Reminder')")
print(" |cffffffff/nse mute|r Hide the NSRT personal reminder note")
print(" |cffffffff/nse unmute|r Restore the NSRT personal reminder note")
return
end
if NSE.GUI and NSE.GUI.Toggle then
NSE.GUI:Toggle()
else
print("|cff33ccffNSRT Enhancer|r: GUI not ready yet.")
end
end