adam@0
|
1 local _, AskMrRobot = ...
|
adam@0
|
2
|
adam@0
|
3 -- initialize the ExportTab class
|
adam@0
|
4 AskMrRobot.CombatLogTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
|
adam@0
|
5
|
adam@0
|
6 -- helper to create text for this tab
|
adam@0
|
7 local function CreateText(tab, font, relativeTo, xOffset, yOffset, text)
|
adam@0
|
8 local t = tab:CreateFontString(nil, "ARTWORK", font)
|
adam@0
|
9 t:SetPoint("TOPLEFT", relativeTo, "BOTTOMLEFT", xOffset, yOffset)
|
adam@0
|
10 t:SetPoint("RIGHT", tab, "RIGHT", -25, 0)
|
adam@0
|
11 t:SetWidth(t:GetWidth())
|
adam@0
|
12 t:SetJustifyH("LEFT")
|
adam@0
|
13 t:SetText(text)
|
adam@0
|
14
|
adam@0
|
15 return t
|
adam@0
|
16 end
|
adam@0
|
17
|
adam@0
|
18 local function newCheckbox(tab, label, tooltipTitle, description, onClick)
|
adam@0
|
19 local check = CreateFrame("CheckButton", "AmrCheck" .. label, tab, "InterfaceOptionsCheckButtonTemplate")
|
adam@0
|
20 check:SetScript("OnClick", function(self)
|
adam@0
|
21 PlaySound(self:GetChecked() and "igMainMenuOptionCheckBoxOn" or "igMainMenuOptionCheckBoxOff")
|
adam@0
|
22 onClick(self, self:GetChecked() and true or false)
|
adam@0
|
23 end)
|
adam@0
|
24 check.label = _G[check:GetName() .. "Text"]
|
adam@0
|
25 check.label:SetText(label)
|
adam@0
|
26 check.tooltipText = tooltipTitle
|
adam@0
|
27 check.tooltipRequirement = description
|
adam@0
|
28 return check
|
adam@0
|
29 end
|
adam@0
|
30
|
adam@0
|
31 function AskMrRobot.CombatLogTab:new(parent)
|
adam@0
|
32
|
adam@0
|
33 local tab = AskMrRobot.Frame:new(nil, parent)
|
adam@0
|
34 setmetatable(tab, { __index = AskMrRobot.CombatLogTab })
|
adam@0
|
35 tab:SetPoint("TOPLEFT")
|
adam@0
|
36 tab:SetPoint("BOTTOMRIGHT")
|
adam@0
|
37 tab:Hide()
|
adam@0
|
38
|
adam@0
|
39 local text = tab:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
|
adam@0
|
40 text:SetPoint("TOPLEFT", 0, -5)
|
adam@0
|
41 text:SetText("Combat Logging")
|
adam@0
|
42
|
adam@0
|
43 local manulText = CreateText(tab, "GameFontWhite", text, 0, -15, "Manual:")
|
adam@0
|
44 manulText:SetJustifyV("MIDDLE")
|
adam@0
|
45 manulText:SetHeight(30)
|
adam@0
|
46
|
adam@0
|
47 local btn = CreateFrame("Button", "AmrCombatLogStart", tab, "UIPanelButtonTemplate")
|
adam@0
|
48 btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 75, -15)
|
adam@0
|
49 btn:SetText("Start Logging")
|
adam@0
|
50 btn:SetWidth(120)
|
adam@0
|
51 btn:SetHeight(30)
|
adam@0
|
52 tab.btnStart = btn
|
adam@0
|
53
|
adam@0
|
54 btn:SetScript("OnClick", function()
|
adam@0
|
55 tab:StartLogging()
|
adam@0
|
56 end)
|
adam@0
|
57
|
adam@0
|
58 btn = CreateFrame("Button", "AmrCombatLogEnd", tab, "UIPanelButtonTemplate")
|
adam@0
|
59 btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 225, -15)
|
adam@0
|
60 btn:SetText("Stop Logging")
|
adam@0
|
61 btn:SetWidth(120)
|
adam@0
|
62 btn:SetHeight(30)
|
adam@0
|
63 tab.btnEnd = btn
|
adam@0
|
64
|
adam@0
|
65 btn:SetScript("OnClick", function()
|
adam@0
|
66 tab:StopLogging()
|
adam@0
|
67 end)
|
adam@0
|
68
|
adam@0
|
69 local autoText = CreateText(tab, "GameFontWhite", text, 0, -50, "Automatic:")
|
adam@0
|
70 autoText:SetJustifyV("MIDDLE")
|
adam@0
|
71 autoText:SetHeight(28)
|
adam@0
|
72
|
adam@0
|
73 local autoChk = newCheckbox(tab,
|
adam@0
|
74 "Always log Siege of Orgrimmar",
|
adam@0
|
75 "Auto-Log Siege of Orgrimmar",
|
adam@0
|
76 "Automatically start logging when you enter SoO and stop when you leave SoO.\n\nNote that you should disable similar features in other addons to avoid conflicts.",
|
adam@0
|
77 function(self, value)
|
adam@0
|
78 if value then
|
adam@0
|
79 AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] = "enabled"
|
adam@0
|
80 else
|
adam@0
|
81 AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] = "disabled"
|
adam@0
|
82 end
|
adam@0
|
83
|
adam@0
|
84 AmrLogData._lastZone = nil
|
adam@0
|
85 AmrLogData._lastDiff = nil
|
adam@0
|
86 tab:UpdateAutoLogging()
|
adam@0
|
87 end
|
adam@0
|
88 )
|
adam@0
|
89 autoChk:SetChecked(AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] == "enabled")
|
adam@0
|
90 autoChk:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 75, -50)
|
adam@0
|
91 autoChk:SetHeight(30)
|
adam@0
|
92
|
adam@0
|
93 text = CreateText(tab, "GameFontNormalLarge", text, 0, -100, "Character Data")
|
adam@0
|
94
|
adam@0
|
95 btn = CreateFrame("Button", "AmrCombatLogSaveCharData", tab, "UIPanelButtonTemplate")
|
adam@0
|
96 btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -5)
|
adam@0
|
97 btn:SetText("Save Character Data")
|
adam@0
|
98 btn:SetWidth(150)
|
adam@0
|
99 btn:SetHeight(30)
|
adam@0
|
100
|
adam@0
|
101 btn:SetScript("OnClick", function()
|
adam@0
|
102 -- reload the UI will save character data to disk
|
adam@0
|
103 ReloadUI()
|
adam@0
|
104 end)
|
adam@0
|
105
|
adam@0
|
106 text = CreateText(tab, "GameFontNormalLarge", btn, 0, -30, "INSTRUCTIONS")
|
adam@0
|
107 text = CreateText(tab, "GameFontWhite", text, 0, -10, "1. Use the Start/Stop buttons or check 'Always log Siege of Orgrimmar'.")
|
adam@0
|
108 text = CreateText(tab, "GameFontWhite", text, 0, -10, "2. When you are ready to upload, press 'Save Character Data'. *")
|
adam@0
|
109 text = CreateText(tab, "GameFontWhite", text, 0, -10, "3. Exit World of Warcraft. **")
|
adam@0
|
110 text = CreateText(tab, "GameFontWhite", text, 0, -10, "4. Launch the Ask Mr. Robot client and follow the instructions. ***")
|
adam@0
|
111
|
adam@0
|
112 text = CreateText(tab, "GameFontNormalSmall", text, 0, -30, "|c00999999* This will reload your UI to ensure that all collected data is saved to disk. This step is not necessary if you log out of the game before uploading.|r")
|
adam@0
|
113 text = CreateText(tab, "GameFontNormalSmall", text, 0, -10, "|c00999999** Exiting WoW before uploading your combat log is optional, but highly recommended. This prevents your log file from getting ridiculously large and slowing down your uploads.|r")
|
adam@0
|
114 text = CreateText(tab, "GameFontNormalSmall", text, 0, -10, "|c00999999*** You can download the client program at|r |c003333ffhttp://www.askmrrobot.com/wow/combatlog/upload|r|c00999999.|r")
|
adam@0
|
115
|
adam@0
|
116 --[[
|
adam@0
|
117 btn = CreateFrame("Button", "AmrCombatLogTest", tab, "UIPanelButtonTemplate")
|
adam@0
|
118 btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -15)
|
adam@0
|
119 btn:SetText("Test")
|
adam@0
|
120 btn:SetWidth(120)
|
adam@0
|
121 btn:SetHeight(30)
|
adam@0
|
122
|
adam@0
|
123 btn:SetScript("OnClick", function()
|
adam@0
|
124 AskMrRobot.ExportToAddonChat(time())
|
adam@0
|
125 end)
|
adam@0
|
126 ]]
|
adam@0
|
127
|
adam@0
|
128 -- when we start up, ensure that logging is still enabled if it was enabled when they last used the addon
|
adam@0
|
129 if (tab:IsLogging()) then
|
adam@0
|
130 SetCVar("advancedCombatLogging", 1)
|
adam@0
|
131 LoggingCombat(true)
|
adam@0
|
132 end
|
adam@0
|
133
|
adam@0
|
134 -- if auto-logging is enabled, do a check when the addon is loaded to make sure that state is set correctly
|
adam@0
|
135 if AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] == "enabled" then
|
adam@0
|
136 tab:UpdateAutoLogging()
|
adam@0
|
137 end
|
adam@0
|
138
|
adam@0
|
139 tab:SetScript("OnShow", function()
|
adam@0
|
140 tab:Update()
|
adam@0
|
141 end)
|
adam@0
|
142
|
adam@0
|
143 return tab
|
adam@0
|
144 end
|
adam@0
|
145
|
adam@0
|
146 function AskMrRobot.CombatLogTab:IsLogging()
|
adam@0
|
147 return AmrLogData._logging == true
|
adam@0
|
148 end
|
adam@0
|
149
|
adam@0
|
150 function AskMrRobot.CombatLogTab:StartLogging()
|
adam@0
|
151
|
adam@0
|
152 -- archive the current logging session so that users don't accidentally blow away data before uploading it
|
adam@0
|
153 if AmrLogData._current2 ~= nil then
|
adam@0
|
154 if not AmrLogData._history2 then AmrLogData._history2 = {} end
|
adam@0
|
155
|
adam@0
|
156 -- add new entries
|
adam@0
|
157 for name, timeList in AskMrRobot.spairs(AmrLogData._current2) do
|
adam@0
|
158 if not AmrLogData._history2[name] then AmrLogData._history2[name] = {} end
|
adam@0
|
159 for timestamp, dataString in AskMrRobot.spairs(timeList) do
|
adam@0
|
160 AmrLogData._history2[name][timestamp] = dataString
|
adam@0
|
161 end
|
adam@0
|
162 end
|
adam@0
|
163
|
adam@0
|
164 -- delete entries that are more than 10 days old
|
adam@0
|
165 local now = time()
|
adam@0
|
166 local interval = 60 * 60 * 24 * 10
|
adam@0
|
167 for name, timeList in AskMrRobot.spairs(AmrLogData._history2) do
|
adam@0
|
168 for timestamp, dataString in AskMrRobot.spairs(timeList) do
|
adam@0
|
169 if difftime(now, tonumber(timestamp)) > interval then
|
adam@0
|
170 timeList[timestamp] = nil
|
adam@0
|
171 end
|
adam@0
|
172 end
|
adam@0
|
173
|
adam@0
|
174 local count = 0
|
adam@0
|
175 for timestamp, dataString in pairs(timeList) do
|
adam@0
|
176 count = count + 1
|
adam@0
|
177 end
|
adam@0
|
178 if count == 0 then
|
adam@0
|
179 AmrLogData._history2[name] = nil
|
adam@0
|
180 end
|
adam@0
|
181 end
|
adam@0
|
182 end
|
adam@0
|
183
|
adam@0
|
184 -- clean up old-style logging data from previous versions of the addon
|
adam@0
|
185 for k, v in AskMrRobot.spairs(AmrLogData) do
|
adam@0
|
186 if k ~= "_logging" and k ~= "_autoLog" and k ~= "_lastZone" and k ~= "_lastDiff" and k ~= "_current2" and k ~= "_history2" then
|
adam@0
|
187 AmrLogData[k] = nil
|
adam@0
|
188 end
|
adam@0
|
189 end
|
adam@0
|
190
|
adam@0
|
191 -- start a new logging session
|
adam@0
|
192 AmrLogData._current2 = {}
|
adam@0
|
193 AmrLogData._logging = true
|
adam@0
|
194
|
adam@0
|
195 -- always enable advanced combat logging via our addon, gathers more detailed data for better analysis
|
adam@0
|
196 SetCVar("advancedCombatLogging", 1)
|
adam@0
|
197
|
adam@0
|
198 LoggingCombat(true)
|
adam@0
|
199 self:Update()
|
adam@0
|
200
|
adam@0
|
201 print("You are now logging combat, and Mr. Robot is logging character data for your raid.")
|
adam@0
|
202 end
|
adam@0
|
203
|
adam@0
|
204 function AskMrRobot.CombatLogTab:StopLogging()
|
adam@0
|
205 LoggingCombat(false)
|
adam@0
|
206 AmrLogData._logging = false
|
adam@0
|
207 self:Update()
|
adam@0
|
208
|
adam@0
|
209 print("Combat logging has been stopped.")
|
adam@0
|
210 end
|
adam@0
|
211
|
adam@0
|
212 -- update the panel and state
|
adam@0
|
213 function AskMrRobot.CombatLogTab:Update()
|
adam@0
|
214 local isLogging = self:IsLogging()
|
adam@0
|
215
|
adam@0
|
216 if isLogging then
|
adam@0
|
217 self.btnStart:Disable()
|
adam@0
|
218 self.btnEnd:Enable()
|
adam@0
|
219 else
|
adam@0
|
220 self.btnStart:Enable()
|
adam@0
|
221 self.btnEnd:Disable()
|
adam@0
|
222 end
|
adam@0
|
223 end
|
adam@0
|
224
|
adam@0
|
225 -- called to update logging state when auto-logging is enabled
|
adam@0
|
226 function AskMrRobot.CombatLogTab:UpdateAutoLogging()
|
adam@0
|
227
|
adam@0
|
228 -- get the info about the instance
|
adam@0
|
229 --local zone, zonetype, difficultyIndex, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID = GetInstanceInfo()
|
adam@0
|
230 local zone, _, difficultyIndex, _, _, _, _, instanceMapID = GetInstanceInfo()
|
adam@0
|
231 --local difficulty = difficultyIndex
|
adam@0
|
232 -- Unless Blizzard fixes scenarios to not return nil, let's hardcode this into returning "scenario" -Znuff
|
adam@0
|
233 --if zonetype == nil and difficultyIndex == 1 then
|
adam@0
|
234 --zonetype = "scenario"
|
adam@0
|
235 --end
|
adam@0
|
236
|
adam@0
|
237 if zone == AmrLogData._lastZone and difficultyIndex == AmrLogData._lastDiff then
|
adam@0
|
238 -- do nothing if the zone hasn't actually changed, otherwise we may override the user's manual enable/disable
|
adam@0
|
239 return
|
adam@0
|
240 end
|
adam@0
|
241
|
adam@0
|
242 AmrLogData._lastZone = zone
|
adam@0
|
243 AmrLogData._lastDiff = difficultyIndex
|
adam@0
|
244
|
adam@0
|
245 if AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] == "enabled" then
|
adam@0
|
246 if tonumber(instanceMapID) == AskMrRobot.instanceIds.SiegeOfOrgrimmar then
|
adam@0
|
247 -- if in SoO, make sure logging is on
|
adam@0
|
248 if not self:IsLogging() then
|
adam@0
|
249 self:StartLogging()
|
adam@0
|
250 end
|
adam@0
|
251 else
|
adam@0
|
252 -- not in SoO, turn logging off
|
adam@0
|
253 if self:IsLogging() then
|
adam@0
|
254 self:StopLogging()
|
adam@0
|
255 end
|
adam@0
|
256 end
|
adam@0
|
257 end
|
adam@0
|
258
|
adam@0
|
259 end
|
adam@0
|
260
|
adam@0
|
261 -- read a message sent to the addon channel with a player's info at the time an encounter started
|
adam@0
|
262 function AskMrRobot.CombatLogTab:ReadAddonMessage(message)
|
adam@0
|
263
|
adam@0
|
264 -- message will be of format: timestamp\nrealm\nname\n[stuff]
|
adam@0
|
265 local parts = {}
|
adam@0
|
266 for part in string.gmatch(message, "([^\n]+)") do
|
adam@0
|
267 tinsert(parts, part)
|
adam@0
|
268 end
|
adam@0
|
269
|
adam@0
|
270 local timestamp = parts[1]
|
adam@0
|
271 local name = parts[2] .. ":" .. parts[3]
|
adam@0
|
272 local data = parts[4]
|
adam@0
|
273
|
adam@0
|
274 if (data == "done") then
|
adam@0
|
275 -- we have finished receiving this message; now process it to reduce the amount of duplicate data
|
adam@0
|
276 local setup = AmrLogData._current2[name][timestamp]
|
adam@0
|
277
|
adam@0
|
278 if (AmrLogData._previousSetup == nil) then
|
adam@0
|
279 AmrLogData._previousSetup = {}
|
adam@0
|
280 end
|
adam@0
|
281
|
adam@0
|
282 local previousSetup = AmrLogData._previousSetup[name]
|
adam@0
|
283
|
adam@0
|
284 if (previousSetup == setup) then
|
adam@0
|
285 -- if the last-seen setup for this player is the same as the current one, we don't need this entry
|
adam@0
|
286 AmrLogData._current2[name][timestamp] = nil
|
adam@0
|
287 else
|
adam@0
|
288 -- record the last-seen setup
|
adam@0
|
289 AmrLogData._previousSetup[name] = setup
|
adam@0
|
290 end
|
adam@0
|
291 else
|
adam@0
|
292 -- concatenate messages with the same timestamp+name
|
adam@0
|
293 if (AmrLogData._current2[name] == nil) then
|
adam@0
|
294 AmrLogData._current2[name] = {}
|
adam@0
|
295 end
|
adam@0
|
296
|
adam@0
|
297 if (AmrLogData._current2[name][timestamp] == nil) then
|
adam@0
|
298 AmrLogData._current2[name][timestamp] = data
|
adam@0
|
299 else
|
adam@0
|
300 AmrLogData._current2[name][timestamp] = AmrLogData._current2[name][timestamp] .. data
|
adam@0
|
301 end
|
adam@0
|
302 end
|
adam@0
|
303 end
|