-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.lua
331 lines (281 loc) · 12.1 KB
/
main.lua
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
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
--[[
The look of the buttons/numbers/arrow can be altered by adding this addon to the
OptionalDeps of an external addon which then overrides the functions under the "Overridables" header.
]]
local _, addon = ...
BossesKilled = addon
function addon:PLAYER_LOGIN()
-- Hook raid finder frame's onshow and onhide
if RaidFinderQueueFrame and RaidFinderQueueFrame_SetRaid then
local function myRaidFinderFrame_OnShow(frame)
self:CreateButtons(frame, GetNumRFDungeons, GetRFDungeonInfo, RaidFinderQueueFrame_SetRaid)
self:UpdateButtonsAndTooltips(frame)
self:UpdateQueueStatuses()
self.UpdateArrow()
self:RegisterEvent("LFG_UPDATE")
self.LFG_UPDATE = self.UpdateQueueStatuses -- Our event dispatcher calls functions like addon[eventName](...), so point it to the right update function
end
local function myRaidFinderFrame_OnHide(frame)
self:UnregisterEvent("LFG_UPDATE")
end
RaidFinderQueueFrame:HookScript("OnShow", myRaidFinderFrame_OnShow)
RaidFinderQueueFrame:HookScript("OnHide", myRaidFinderFrame_OnHide)
hooksecurefunc("RaidFinderQueueFrame_SetRaid", self.UpdateArrow)
end
end
addon:RegisterEvent("PLAYER_LOGIN")
-- Creates the buttons. LFR and Flex use different functions and dropdown menus so take them as arguments
function addon:CreateButtons(parentFrame, DungeonAmountFunc, DungeonInfoFunc, SetDropdownMenuFunc)
local scale = self:GetButtonScale(DungeonAmountFunc())
if not parentFrame.BossesKilledButtons then
parentFrame.BossesKilledButtons = {}
end
local buttons = parentFrame.BossesKilledButtons
for i = 1, DungeonAmountFunc() do
local id, name = DungeonInfoFunc(i)
local isAvailable, isAvailableToPlayer = IsLFGDungeonJoinable(id)
-- Only make a button if there's data for it, and it hasn't been already made. This gets called multiple times so it updates correctly when you open up more raids
if isAvailable and isAvailableToPlayer and not buttons[id] and self.raidData[id] then
local button = self:CreateButton(parentFrame, scale)
buttons[id] = button
button.dungeonID = id
button.dungeonName = name
parentFrame.lastButton = button
-- I just realised a CheckButton might already have it's own FontString, but uh... whatever.
button.number = self:CreateNumberFontstring(button)
button:SetScript("OnEnter", function(this)
if this.tooltip then
self:ShowTooltip(this)
end
end)
button:SetScript("OnClick", function(this)
SetDropdownMenuFunc(this.dungeonID)
self.UpdateArrow()
-- This is to override the automatic highlighting when you click the button, while we want to use that to show queue status instead.
-- I've no idea why simply overriding this OnClick and not doing a SetChecked doesn't disable the behavior.
-- I probably shouldn't be using a CheckButton at all, but the SpellBookSkillLineTabTemplate looks pretty nice for the job.
this:SetChecked(this.checked)
end)
button.checked = false
end
end
end
---------------------------------------- Overridables ----------------------------------------
-- Must return a CheckButton, or implement :SetChecked() and support OnClick scripts. Not 100% right now if anything else
function addon:CreateButton(parent, scale)
local button = CreateFrame("CheckButton", parent:GetName().."BossesKilledButton"..tostring(id), parent, "CommunitiesGuildPerksButtonTemplate") -- CommunitiesGuildPerksButtonTemplate SpellBookSkillLineTabTemplate
button:Show()
if parent.lastButton then
button:SetPoint("TOPLEFT", parent.lastButton, "BOTTOMLEFT", 0, -25) -- -15
else
local x = 3
-- SocialTabs compatibility
if C_AddOns.IsAddOnLoaded("SocialTabs") then
x = x + ceil(32 / scale)
end
button:SetPoint("TOPLEFT", parent, "TOPRIGHT", x, -50) -- -50
end
button:SetScale(scale)
button:SetWidth(66) -- Originally 32 66
button:SetHeight(37)
-- Need to find the button's texture in the regions so we can resize it. I don't like this part, but I can't think of a better way in case it's not the first region returned. (Is it ever not?)
for _, region in ipairs({button:GetRegions()}) do
--[[if type(region) ~= "userdata" and region.GetTexture and region:GetTexture() == "Interface\\SpellBook\\SpellBook-SkillLineTab" then
region:SetWidth(64 + 24) -- Originally 64 (64 + 24)
break
end]]
if type(region) ~= "userdata" then
region:SetWidth(0.1) -- Originally 64 (64 + 24) 120
region:SetHeight(30) -- 70
break
end
end
return button
end
function addon:GetButtonScale(numDungeons)
-- Ok, I still don't understand anything about the positioning and sizing of stuff in WoW, but the target frame is about 280'ish tall and buttons 32 and who gives a shit about margins and aaargh I'm going crazy /headexplode
-- Magic numbers! There's really no method to the madness, these numbers just happen to look ok
return min(480 / (numDungeons * 10), 1) -- 24 17
end
-- Must return a fontstring
function addon:CreateNumberFontstring(parentButton)
local number = parentButton:CreateFontString(parentButton:GetName().."Number", "OVERLAY", "SystemFont_Shadow_Huge3")
number:SetPoint("TOPLEFT", -4, 4)
number:SetPoint("BOTTOMRIGHT", 5, -5)
return number
end
-- Must return a texture, which will be pointing to selected dungeon's button
function addon:CreateArrow()
local arrow = GroupFinderFrame:CreateTexture("BossesKilledArrow", "ARTWORK")
arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow")
arrow:SetTexCoord(1, 0, 0, 1) -- This somehow turns the arrow other way around. Magic. /shrug
arrow:SetSize(32, 32) -- Originally 16, 16
arrow:Hide()
return arrow
end
--------------------------------------- Update functions -------------------------------------
function addon:UpdateButtonsAndTooltips(parentFrame)
local buttons = parentFrame.BossesKilledButtons
for id, button in pairs(buttons) do
local numKilled = 0
-- GetLFGDungeonNumEncounters returns the full set of bosses for the whole raid, while LFR and Flex raids
-- are split into several separate raids, so get the amount of bosses and where to start from from our data file
local index = self.raidData[id].startFrom
local numEncounters = self.raidData[id].numEncounters
-- Tooltip format:
-- Button.tooltip = {
-- { -- #1
-- text = "Text for the button",
-- color = { redValueFloat, greenValueFloat, blueValueFloat } -- Omit to get default color
-- },
-- {...} -- #2 etc etc
-- }
local tooltip = {{text = button.dungeonName}} -- Set up tooltip data with the dungeon name
for i = index, numEncounters + index - 1 do
if id == 847 and i == 3 then
i = 7
end
if id == 846 and i == 4 then
i = 3
end
if id == 846 and i == 6 then
i = 8
end
if id == 848 and i == 7 then
i = 4
end
if id == 848 and i == 8 then
i = 6
end
if id == 984 and i == 9 then
i = 11
end
if id == 985 and i == 10 then
i = 9
end
if id == 985 and i == 11 then
i = 10
end
local encounterLine = {}
local bossName, _, isDead = GetLFGDungeonEncounterInfo(id, i)
if isDead then
if ENABLE_COLORBLIND_MODE == "0" then -- TODO: figure out if it's 0/false/null when not set
encounterLine.color = {RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b}
end
if bossName == nil then
bossName = "bossname"
encounterLine.text = "Dead - "..bossName
else
encounterLine.text = "Dead - "..bossName
numKilled = numKilled + 1
end
else
if ENABLE_COLORBLIND_MODE == "0" then
encounterLine.color = {GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b}
end
if bossName == nil then
bossName = "bossname"
encounterLine.text = "Alive - "..bossName
else
encounterLine.text = "Alive - "..bossName
end
end
table.insert(tooltip, encounterLine)
end
button.tooltip = tooltip
local statusString = numKilled.."/"..numEncounters
if ENABLE_COLORBLIND_MODE == "1" then
button.number:SetFormattedText("|c00ffffff%s|r", statusString)
else
button.number:SetFormattedText(self.textColorTable[statusString], statusString)
end
end
end
function addon:UpdateQueueStatuses()
for id, button in pairs(RaidFinderQueueFrame.BossesKilledButtons) do
local mode = GetLFGMode(LE_LFG_CATEGORY_RF, id);
if mode == "queued" or mode == "listed" or mode == "rolecheck" or mode == "suspended" then
button:SetChecked(true)
button.checked = true -- This is for the PostClick script earlier
else
button:SetChecked(false)
button.checked = false
end
end
end
-- Not a method because it's used as callback for hooksecurefuncs so it would get the wrong "self"
function addon.UpdateArrow()
local self = addon
if not self.arrow then
self.arrow = self:CreateArrow()
end
local parent
if RaidFinderQueueFrame and RaidFinderQueueFrame:IsVisible() then
parent = RaidFinderQueueFrame
else
self.arrow:Hide()
return
end
if parent.raid and parent.BossesKilledButtons[parent.raid] then
local button = parent.BossesKilledButtons[parent.raid]
self.arrow:SetParent(button) -- Re-set the parent so we inherit the scale, so our smaller LFR buttons get a smaller arrow
self.arrow:SetPoint("LEFT", button, "RIGHT")
self.arrow:Show()
end
end
--------------------------------- Tooltip and colorization stuff -----------------------------
function addon:ShowTooltip(button)
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
for i = 1, #button.tooltip do
tooltip = button.tooltip[i]
if tooltip.color then
GameTooltip:AddLine(tooltip.text, unpack(tooltip.color))
else
GameTooltip:AddLine(tooltip.text)
end
end
GameTooltip:AddLine(" ")
GameTooltip:AddLine("<Click to select this raid>")
GameTooltip:AddLine(" ")
if ENABLE_COLORBLIND_MODE == "1" then -- TODO: Remove duplicates. Only check for not ENABLE_COLORBLIND_MODE in which case add the first AddLine. After outside of if, add second AddLine
GameTooltip:AddLine("(Button lights up if you're queued for this raid)")
else
GameTooltip:AddLine("(|c00ff0000Red|r for killed bosses, |c0000ff00green|r for alive ones,")
GameTooltip:AddLine(" button lights up if you're queued for this raid)")
end
GameTooltip:Show()
end
-- gets passed a "x/y" STRING. No sanity checks so make sure the calling function feeds it the expected format.
-- the vararg gets passed color triples, eg. 0.0,1.0,0.0, 1.0,0.0,0.0 (green to red)
function addon:TextColorGradient(str_percent, ...)
local num = select("#", ...)
local low, high = strmatch(str_percent, "(%d+)/(%d+)")
local percent = (low + 0) / (high + 0) -- implicit cast to number, cheaper than tonumber
local r, g, b
if percent >= 1 then
r, g, b = select(num - 2, ...), select(num - 1, ...), select(num, ...)
return format("|cff%02x%02x%02x%%s|r", r * 255, g * 255, b * 255)
elseif percent <= 0 then
r, g, b = ...
return format("|cff%02x%02x%02x%%s|r", r * 255, g * 255, b * 255)
end
local segment, relperc = math.modf(percent * (num / 3 - 1))
local r1, g1, b1, r2, g2, b2
r1, g1, b1 = select((segment * 3) + 1, ...), select((segment * 3) + 2, ...), select((segment * 3) + 3, ...)
r2, g2, b2 = select((segment * 3) + 4, ...), select((segment * 3) + 5, ...), select((segment * 3) + 6, ...)
if not r2 or not g2 or not b2 then
r, g, b = r1, g1, b1
else
r, g, b = r1 + (r2 - r1) * relperc,
g1 + (g2 - g1) * relperc,
b1 + (b2 - b1) * relperc
end
return format("|cff%02x%02x%02x%%s|r", r * 255, g * 255, b * 255)
end
-- Use a memoization table so each x/y colorstring is only computed once and then does a simple lookup
addon.textColorTable = setmetatable({}, {__index = function(t, k)
local colorStr = addon:TextColorGradient(k, GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b, -- "From" color
RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b) -- "To" color
rawset(t, k, colorStr)
return colorStr
end})