vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | |
2 | assert( oRA, "oRA not found!") |
||
3 | |||
4 | ------------------------------ |
||
5 | -- Are you local? -- |
||
6 | ------------------------------ |
||
7 | |||
8 | local L = AceLibrary("AceLocale-2.2"):new("oRALReady") |
||
9 | |||
10 | ---------------------------- |
||
11 | -- Localization -- |
||
12 | ---------------------------- |
||
13 | |||
14 | L:RegisterTranslations("enUS", function() return { |
||
15 | ["ready"] = true, |
||
16 | ["readyleader"] = true, |
||
17 | ["Options for ready checks and votes."] = true, |
||
18 | ["sound"] = true, |
||
19 | ["Sound"] = true, |
||
20 | ["Toggle an audio warning upon a ready check or vote."] = true, |
||
21 | ["Ready"] = true, |
||
22 | ["Not Ready"] = true, |
||
23 | ["Are you Ready?"] = true, |
||
24 | ["Yes"] = true, |
||
25 | ["No"] = true, |
||
26 | ["Ready Check"] = true, |
||
27 | ["check"] = true, |
||
28 | ["Perform a ready check."] = true, |
||
29 | ["Close"] = true, |
||
30 | ["<CTRaid> %s has performed a ready check."] = true, |
||
31 | ["AFK: "] = true, |
||
32 | ["Not Ready: "] = true, |
||
33 | ["Yes: %d No: %d AFK: %d"] = true, |
||
34 | ["Vote Results for: "] = true, |
||
35 | ["<CTRaid> %s has performed a vote: %s"] = true, |
||
36 | ["Vote"] = true, |
||
37 | ["vote"] = true, |
||
38 | ["Perform a vote."] = true, |
||
39 | ["<vote>"] = true, |
||
40 | ["Leader/Ready"] = true, |
||
41 | } end) |
||
42 | |||
43 | L:RegisterTranslations("koKR", function() return { |
||
44 | |||
45 | ["Options for ready checks and votes."] = "준비확인과 투표 설정", |
||
46 | ["Sound"] = "소리", |
||
47 | ["Toggle an audio warning upon a ready check or vote."] = "준비확인시와 투표시에 경고음 재생 기능을 토글합니다.", |
||
48 | ["Ready"] = "준비완료", |
||
49 | ["Not Ready"] = "준비안됨", |
||
50 | ["Are you Ready?"] = "준비 되셨습니까?", |
||
51 | ["Yes"] = "예", |
||
52 | ["No"] = "아니오", |
||
53 | ["Ready Check"] = "준비 확인", |
||
54 | ["Perform a ready check."] = "준비 상태를 확인 합니다.", |
||
55 | ["Close"] = "닫기", |
||
56 | ["<CTRaid> %s has performed a ready check."] = "<공격대 도우미> %s님이 준비 상태를 확인합니다.", |
||
57 | ["AFK: "] = "자리비움: ", |
||
58 | ["Not Ready: "] = "준비안됨: ", |
||
59 | ["Yes: %d No: %d AFK: %d"] = "예: %d 아니오: %d 자리비움: %d", |
||
60 | ["Vote Results for: "] = "투표 결과: ", |
||
61 | ["<CTRaid> %s has performed a vote: %s"] = "<공격대 도우미> %s님이 투표를 실시합니다.: %s", |
||
62 | ["Vote"] = "투표", |
||
63 | ["Perform a vote."] = "투표를 실시합니다.", |
||
64 | ["<vote>"] = "투표", |
||
65 | ["Leader/Ready"] = "공격대장/준비확인", |
||
66 | } end) |
||
67 | |||
68 | L:RegisterTranslations("zhCN", function() return { |
||
69 | ["ready"] = "就位确认", |
||
70 | ["readyleader"] = "就位确认与投票助手", |
||
71 | ["Options for ready checks and votes."] = "就位确认与投票设置", |
||
72 | ["sound"] = "声音", |
||
73 | ["Sound"] = "声音", |
||
74 | ["Toggle an audio warning upon a ready check or vote."] = "就位确认与投票时播放音效", |
||
75 | ["Ready"] = "就位确认", |
||
76 | ["Not Ready"] = "未准备好", |
||
77 | ["Are you Ready?"] = "准备好了么?", |
||
78 | ["Yes"] = "是", |
||
79 | ["No"] = "否", |
||
80 | ["Ready Check"] = "就位确认", |
||
81 | ["check"] = "检查", |
||
82 | ["Perform a ready check."] = "进行检查", |
||
83 | ["Close"] = "关闭", |
||
84 | ["<CTRaid> %s has performed a ready check."] = "<CTRaid>%s正在进行就位检查", |
||
85 | ["AFK: "] = "暂离: ", |
||
86 | ["Not Ready: "] = "未就绪", |
||
87 | ["Yes: %d No: %d AFK: %d"] = "是:%d 否:%d 暂离:%d", |
||
88 | ["Vote Results for: "] = "投票结果:", |
||
89 | ["<CTRaid> %s has performed a vote: %s"] = "<CTRaid>%s开始一场投票:%s", |
||
90 | ["Vote"] = "投票", |
||
91 | ["vote"] = "投票", |
||
92 | ["Perform a vote."] = "进行投票", |
||
93 | ["<vote>"] = "<vote>", |
||
94 | ["Leader/Ready"] = "Leader/Ready", |
||
95 | } end) |
||
96 | |||
97 | L:RegisterTranslations("zhTW", function() return { |
||
98 | ["ready"] = "就位確認", |
||
99 | ["readyleader"] = "readyleader", |
||
100 | ["Options for ready checks and votes."] = "就位確認與投票選項", |
||
101 | ["sound"] = "聲音", |
||
102 | ["Sound"] = "聲音", |
||
103 | ["Toggle an audio warning upon a ready check or vote."] = "就位確認與投票時播放音效", |
||
104 | ["Ready"] = "已就緒", |
||
105 | ["Not Ready"] = "未就緒", |
||
106 | ["Are you Ready?"] = "準備好了嗎?", |
||
107 | ["Yes"] = "是", |
||
108 | ["No"] = "否", |
||
109 | ["Ready Check"] = "就位確認", |
||
110 | ["check"] = "檢查", |
||
111 | ["Perform a ready check."] = "進行就位確認", |
||
112 | ["Close"] = "關閉", |
||
113 | ["<CTRaid> %s has performed a ready check."] = "<CTRaid>%s正在進行就位確認", |
||
114 | ["AFK: "] = "暫離: ", |
||
115 | ["Not Ready: "] = "未就緒", |
||
116 | ["Yes: %d No: %d AFK: %d"] = "是:%d 否:%d 暫離:%d", |
||
117 | ["Vote Results for: "] = "投票結果:", |
||
118 | ["<CTRaid> %s has performed a vote: %s"] = "<CTRaid>%s開始一場投票:%s", |
||
119 | ["Vote"] = "投票", |
||
120 | ["vote"] = "投票", |
||
121 | ["Perform a vote."] = "進行投票", |
||
122 | ["<vote>"] = "<投票>", |
||
123 | ["Leader/Ready"] = "領隊/就位確認", |
||
124 | } end) |
||
125 | |||
126 | L:RegisterTranslations("frFR", function() return { |
||
127 | --["ready"] = true, |
||
128 | --["readyleader"] = true, |
||
129 | ["Options for ready checks and votes."] = "Options concernant les appels et les votes.", |
||
130 | --["sound"] = true, |
||
131 | ["Sound"] = "Son", |
||
132 | ["Toggle an audio warning upon a ready check or vote."] = "Joue ou non un avertissement sonore lors d'un appel ou d'un vote.", |
||
133 | ["Ready"] = "Pr\195\170t", |
||
134 | ["Not Ready"] = "Pas pr\195\170t", |
||
135 | ["Are you Ready?"] = "\195\138tes-vous pr\195\170t ?", |
||
136 | ["Yes"] = "Oui", |
||
137 | ["No"] = "Non", |
||
138 | ["Ready Check"] = "Appel", |
||
139 | --["check"] = true, |
||
140 | ["Perform a ready check."] = "Effectue l'appel.", |
||
141 | ["Close"] = "Fermer", |
||
142 | ["<CTRaid> %s has performed a ready check."] = "<CTRaid> %s a commenc\195\169 l'appel.", |
||
143 | ["AFK: "] = "ABS : ", |
||
144 | ["Not Ready: "] = "Pas pr\195\170t : ", |
||
145 | ["Yes: %d No: %d AFK: %d"] = "Oui : %d Non : %d ABS : %d", |
||
146 | ["Vote Results for: "] = "R\195\169sultat du vote pour : ", |
||
147 | ["<CTRaid> %s has performed a vote: %s"] = "<CTRaid> %s a lanc\195\169 un vote: %s", |
||
148 | --["Vote"] = true, |
||
149 | --["vote"] = true, |
||
150 | ["Perform a vote."] = "Soumet un vote au raid.", |
||
151 | --["<vote>"] = true, |
||
152 | ["Leader/Ready"] = "Chef/Appel", |
||
153 | } end) |
||
154 | |||
155 | ---------------------------------- |
||
156 | -- Module Declaration -- |
||
157 | ---------------------------------- |
||
158 | |||
159 | oRALReady = oRA:NewModule(L["readyleader"]) |
||
160 | oRALReady.defaults = { |
||
161 | sound = true, |
||
162 | } |
||
163 | oRALReady.leader = true |
||
164 | oRALReady.name = L["Leader/Ready"] |
||
165 | oRALReady.consoleCmd = L["ready"] |
||
166 | oRALReady.consoleOptions = { |
||
167 | type = "group", |
||
168 | desc = L["Options for ready checks and votes."], |
||
169 | name = L["Ready"], |
||
170 | args = { |
||
171 | [L["check"]] = { |
||
172 | name = L["Ready Check"], type = "execute", |
||
173 | desc = L["Perform a ready check."], |
||
174 | func = function() |
||
175 | oRALReady:PerformReadyCheck() |
||
176 | end, |
||
177 | disabled = function() return not oRA:IsModuleActive(oRALReady) or not oRALReady:IsValidRequest() end, |
||
178 | }, |
||
179 | [L["vote"]] = { |
||
180 | name = L["Vote"], type = "text", |
||
181 | desc = L["Perform a vote."], |
||
182 | usage = L["<vote>"], |
||
183 | get = false, |
||
184 | set = function(v) |
||
185 | oRALReady:PerformVote(v) |
||
186 | end, |
||
187 | validate = function(v) |
||
188 | return string.find(v, "^(.+)$") |
||
189 | end, |
||
190 | disabled = function() return not oRA:IsModuleActive(oRALReady) or not oRALReady:IsValidRequest() end, |
||
191 | } |
||
192 | } |
||
193 | } |
||
194 | |||
195 | ------------------------------ |
||
196 | -- Initialization -- |
||
197 | ------------------------------ |
||
198 | |||
199 | function oRALReady:OnEnable() |
||
200 | self.votes = {} |
||
201 | self.ready = {} |
||
202 | |||
203 | self:RegisterCheck("READY", "oRA_Ready") |
||
204 | self:RegisterCheck("NOTREADY", "oRA_NotReady") |
||
205 | self:RegisterCheck("VOTEYES", "oRA_VoteYes") |
||
206 | self:RegisterCheck("VOTENO", "oRA_VoteNo") |
||
207 | |||
208 | self:RegisterShorthand("raready", function() self:PerformReadyCheck() end ) |
||
209 | self:RegisterShorthand("rar", function() self:PerformReadyCheck() end ) |
||
210 | self:RegisterShorthand("ravote", function(vote) self:PerformVote(vote) end ) |
||
211 | |||
212 | self:SetupFrames() |
||
213 | end |
||
214 | |||
215 | function oRALReady:OnDisable() |
||
216 | |||
217 | self:UnregisterAllEvents() |
||
218 | |||
219 | self:UnregisterCheck("READY") |
||
220 | self:UnregisterCheck("NOTREADY") |
||
221 | self:UnregisterCheck("VOTEYES") |
||
222 | self:UnregisterCheck("VOTENO") |
||
223 | |||
224 | self:UnregisterShorthand("raready") |
||
225 | self:UnregisterShorthand("rar") |
||
226 | self:UnregisterShorthand("ravote") |
||
227 | |||
228 | self.ready = {} |
||
229 | self.votes = {} |
||
230 | |||
231 | end |
||
232 | |||
233 | ------------------------- |
||
234 | -- Command Handlers -- |
||
235 | ------------------------- |
||
236 | |||
237 | function oRALReady:PerformReadyCheck() |
||
238 | if not self:IsPromoted() then return end |
||
239 | self.ready = {} |
||
240 | for i = 1, GetNumRaidMembers(), 1 do |
||
241 | local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i) |
||
242 | if online then self.ready[name] = "no reply" end |
||
243 | end |
||
244 | |||
245 | name = UnitName("player") |
||
246 | self.ready[name] = "ready" |
||
247 | |||
248 | self.frames.rheader:SetText(L["Ready Check"]) |
||
249 | self.frames.leftinfo:SetText("") |
||
250 | self.frames.rightinfo:SetText("") |
||
251 | |||
252 | self.frames.closebuttontext:SetText(L["Close"]) |
||
253 | |||
254 | self.frames.closebutton:SetScript("OnClick", |
||
255 | function() |
||
256 | this.owner:ReportReadyStatus() |
||
257 | this.owner.frames.report:Hide() |
||
258 | end ) |
||
259 | |||
260 | self.frames.report:Show() |
||
261 | self:UpdateReport(self.ready, "ready", "not ready") |
||
262 | |||
263 | SendChatMessage(string.format( L["<CTRaid> %s has performed a ready check."], name), "RAID") |
||
264 | self:SendMessage("CHECKREADY") |
||
265 | end |
||
266 | |||
267 | function oRALReady:PerformVote( question ) |
||
268 | if not self:IsPromoted() then return end |
||
269 | if not question or question == "" then return end |
||
270 | |||
271 | self.question = question |
||
272 | self.votes = {} |
||
273 | |||
274 | for i = 1, GetNumRaidMembers(), 1 do |
||
275 | local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i) |
||
276 | if online and name ~= UnitName("player") then self.votes[name] = "no reply" end |
||
277 | end |
||
278 | |||
279 | self.frames.rheader:SetText(L["Vote"]) |
||
280 | self.frames.leftinfo:SetText("") |
||
281 | self.frames.rightinfo:SetText("") |
||
282 | |||
283 | self.frames.closebuttontext:SetText(L["Close"]) |
||
284 | |||
285 | self.frames.closebutton:SetScript("OnClick", |
||
286 | function() |
||
287 | this.owner:ReportVoteStatus() |
||
288 | this.owner.frames.report:Hide() |
||
289 | end ) |
||
290 | |||
291 | self.frames.report:Show() |
||
292 | self:UpdateReport(self.votes, "yes", "no") |
||
293 | SendChatMessage(string.format( L["<CTRaid> %s has performed a vote: %s"], UnitName("player"), question), "RAID") |
||
294 | self:SendMessage("VOTE "..question) |
||
295 | end |
||
296 | |||
297 | ------------------------- |
||
298 | -- Event Handlers -- |
||
299 | ------------------------- |
||
300 | |||
301 | function oRALReady:oRA_Ready(msg, author) |
||
302 | if not self:IsPromoted() then return end |
||
303 | self.ready[author] = "ready" |
||
304 | self:UpdateReport(self.ready, "ready", "not ready") |
||
305 | end |
||
306 | |||
307 | function oRALReady:oRA_NotReady(msg, author) |
||
308 | if not self:IsPromoted() then return end |
||
309 | self.ready[author] = "not ready" |
||
310 | self:UpdateReport(self.ready, "ready", "not ready") |
||
311 | end |
||
312 | |||
313 | function oRALReady:oRA_VoteYes(msg, author) |
||
314 | if not self:IsPromoted() then return end |
||
315 | self.votes[author] = "yes" |
||
316 | self:UpdateReport(self.votes, "yes", "no") |
||
317 | end |
||
318 | |||
319 | function oRALReady:oRA_VoteNo(msg, author) |
||
320 | if not self:IsPromoted() then return end |
||
321 | self.votes[author] = "no" |
||
322 | self:UpdateReport(self.votes, "yes", "no") |
||
323 | end |
||
324 | |||
325 | -------------------------- |
||
326 | -- Core function -- |
||
327 | -------------------------- |
||
328 | |||
329 | function oRALReady:ReportReadyStatus() |
||
330 | local noreply, notready = "", "" |
||
331 | for name, ready in pairs(self.ready) do |
||
332 | if ready == "no reply" then noreply = noreply..name.." " |
||
333 | elseif ready == "not ready" then notready = notready..name.." " |
||
334 | end |
||
335 | end |
||
336 | if noreply ~= "" then self:Print(L["AFK: "]..noreply) end |
||
337 | if notready ~= "" then self:Print(L["Not Ready: "]..notready) end |
||
338 | end |
||
339 | |||
340 | function oRALReady:ReportVoteStatus() |
||
341 | local noreply, yes, no = 0,0,0 |
||
342 | for name, vote in pairs(self.votes) do |
||
343 | if vote == "no reply" then noreply = noreply + 1 |
||
344 | elseif vote == "no" then no = no + 1 |
||
345 | else yes = yes + 1 |
||
346 | end |
||
347 | end |
||
348 | SendChatMessage( L["Vote Results for: "]..self.question, "RAID") |
||
349 | SendChatMessage( string.format(L["Yes: %d No: %d AFK: %d"], yes, no, noreply), "RAID") |
||
350 | end |
||
351 | |||
352 | |||
353 | ------------------------------------ |
||
354 | -- Frame Setup and Handling -- |
||
355 | ------------------------------------ |
||
356 | |||
357 | |||
358 | function oRALReady:UpdateReport(t, green, red) |
||
359 | local text = "" |
||
360 | local i = 0 |
||
361 | for name, state in pairs(t) do |
||
362 | i = i + 1 |
||
363 | if i == 21 then text = "" end |
||
364 | |||
365 | if state == "no reply" then |
||
366 | text = text .. "|c00CCCCCC" .. name .. "|r\n" |
||
367 | elseif state == red then |
||
368 | text = text .. "|c00FF0000" .. name .. "|r\n" |
||
369 | else |
||
370 | text = text .. "|c0000FF00" .. name .. "|r\n" |
||
371 | end |
||
372 | |||
373 | if i <= 20 then self.frames.leftinfo:SetText(text) |
||
374 | else self.frames.rightinfo:SetText(text) end |
||
375 | end |
||
376 | end |
||
377 | |||
378 | |||
379 | function oRALReady:SetupFrames() |
||
380 | local f, t |
||
381 | |||
382 | f, _, _ = GameFontNormal:GetFont() |
||
383 | |||
384 | self.frames = {} |
||
385 | |||
386 | self.frames.report = CreateFrame("Frame", nil, UIParent) |
||
387 | self.frames.report:Hide() |
||
388 | self.frames.report:SetWidth(325) |
||
389 | self.frames.report:SetHeight(325) |
||
390 | self.frames.report:EnableMouse(true) |
||
391 | self.frames.report:SetMovable(true) |
||
392 | self.frames.report:RegisterForDrag("LeftButton") |
||
393 | self.frames.report:SetScript("OnDragStart", function() this:StartMoving() end) |
||
394 | self.frames.report:SetScript("OnDragStop", function() this:StopMovingOrSizing() end) |
||
395 | self.frames.report:SetBackdrop({ |
||
396 | bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", tile = true, tileSize = 16, |
||
397 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 16, |
||
398 | insets = {left = 4, right = 4, top = 4, bottom = 4}, |
||
399 | }) |
||
400 | self.frames.report:SetBackdropBorderColor(.5, .5, .5) |
||
401 | self.frames.report:SetBackdropColor(0,0,0) |
||
402 | self.frames.report:ClearAllPoints() |
||
403 | self.frames.report:SetPoint("CENTER", WorldFrame, "CENTER", 0, 0) |
||
404 | |||
405 | self.frames.rfade = self.frames.report:CreateTexture(nil, "BORDER") |
||
406 | self.frames.rfade:SetWidth(319) |
||
407 | self.frames.rfade:SetHeight(25) |
||
408 | self.frames.rfade:SetTexture("Interface\\ChatFrame\\ChatFrameBackground") |
||
409 | self.frames.rfade:SetPoint("TOP", self.frames.report, "TOP", 0, -4) |
||
410 | self.frames.rfade:SetBlendMode("ADD") |
||
411 | self.frames.rfade:SetGradientAlpha("VERTICAL", .1, .1, .1, 0, .25, .25, .25, 1) |
||
412 | self.frames.report.Fade = self.frames.fade |
||
413 | |||
414 | self.frames.rheader = self.frames.report:CreateFontString(nil,"OVERLAY") |
||
415 | self.frames.rheader:SetFont(f, 14) |
||
416 | self.frames.rheader:SetWidth(300) |
||
417 | self.frames.rheader:SetText("header") |
||
418 | self.frames.rheader:SetTextColor(1, .8, 0) |
||
419 | self.frames.rheader:ClearAllPoints() |
||
420 | self.frames.rheader:SetPoint("TOP", self.frames.report, "TOP", 0, -10) |
||
421 | |||
422 | self.frames.leftinfo = self.frames.report:CreateFontString(nil,"OVERLAY") |
||
423 | self.frames.leftinfo:SetFont(f, 12) |
||
424 | self.frames.leftinfo:SetWidth(175) |
||
425 | self.frames.leftinfo:SetHeight(300) |
||
426 | self.frames.leftinfo:SetJustifyV("TOP") |
||
427 | self.frames.leftinfo:SetText("leftinfo") |
||
428 | self.frames.leftinfo:ClearAllPoints() |
||
429 | self.frames.leftinfo:SetPoint("TOPLEFT", self.frames.report, "TOPLEFT", 0, -30) |
||
430 | |||
431 | self.frames.rightinfo = self.frames.report:CreateFontString(nil,"OVERLAY") |
||
432 | self.frames.rightinfo:SetFont(f, 12) |
||
433 | self.frames.rightinfo:SetWidth(175) |
||
434 | self.frames.rightinfo:SetHeight(300) |
||
435 | self.frames.rightinfo:SetJustifyV("TOP") |
||
436 | self.frames.rightinfo:SetText("rightinfo") |
||
437 | self.frames.rightinfo:ClearAllPoints() |
||
438 | self.frames.rightinfo:SetPoint("TOPRIGHT", self.frames.report, "TOPRIGHT", 0, -30) |
||
439 | |||
440 | self.frames.closebutton = CreateFrame("Button", nil, self.frames.report) |
||
441 | self.frames.closebutton.owner = self |
||
442 | self.frames.closebutton:SetWidth(125) |
||
443 | self.frames.closebutton:SetHeight(32) |
||
444 | self.frames.closebutton:SetPoint("BOTTOM", self.frames.report, "BOTTOM", 0, 10) |
||
445 | |||
446 | t = self.frames.closebutton:CreateTexture() |
||
447 | t:SetWidth(125) |
||
448 | t:SetHeight(32) |
||
449 | t:SetPoint("CENTER", self.frames.closebutton, "CENTER") |
||
450 | t:SetTexture("Interface\\Buttons\\UI-Panel-Button-Up") |
||
451 | t:SetTexCoord(0, 0.625, 0, 0.6875) |
||
452 | self.frames.closebutton:SetNormalTexture(t) |
||
453 | |||
454 | t = self.frames.closebutton:CreateTexture(nil, "BACKGROUND") |
||
455 | t:SetTexture("Interface\\Buttons\\UI-Panel-Button-Down") |
||
456 | t:SetTexCoord(0, 0.625, 0, 0.6875) |
||
457 | t:SetAllPoints(self.frames.closebutton) |
||
458 | self.frames.closebutton:SetPushedTexture(t) |
||
459 | |||
460 | t = self.frames.closebutton:CreateTexture() |
||
461 | t:SetTexture("Interface\\Buttons\\UI-Panel-Button-Highlight") |
||
462 | t:SetTexCoord(0, 0.625, 0, 0.6875) |
||
463 | t:SetAllPoints(self.frames.closebutton) |
||
464 | t:SetBlendMode("ADD") |
||
465 | self.frames.closebutton:SetHighlightTexture(t) |
||
466 | self.frames.closebuttontext = self.frames.closebutton:CreateFontString(nil,"OVERLAY") |
||
467 | self.frames.closebuttontext:SetFontObject(GameFontHighlight) |
||
468 | self.frames.closebuttontext:SetText("left") |
||
469 | self.frames.closebuttontext:SetAllPoints(self.frames.closebutton) |
||
470 | end |