vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Recap 3.32 - Gello
3  
4 An AddOn for WoW to track and summarize all damage done around the user.
5 ]]
6  
7 Recap_Version = 3.32
8  
9 --[[ local tables ]]
10  
11 -- colors for the gauges
12 local gaugecolor = { ["DmgIn"] = { r=.66,g=.25,b=.25 }, ["DmgOut"] = { r=.25,g=.66,b=.35 }, ["Heal"] = { r=.25,g=.5,b=.85 },
13 ["Time"] = { r=.75, g=.75, b=.75 }, ["Kills"] = { r=.75, g=.75, b=.75 }, ["MaxHit"] = { r=.75, g=.75, b=.75 },
14 ["DPS"] = { r=.25, g=.66, b=.35 }, ["Over"] = { r=.25, g=.5, b=.85 } }
15  
16 -- keys for (det)ails and (inc)oming data sets
17 local detkey = { ["HitsDmg"]="d", ["Hits"]="n", ["HitsMax"]="x", ["CritsDmg"]="D", ["Crits"]="N",
18 ["CritsMax"]="X", ["CritsEvents"]="e", ["Missed"]="m", ["TicksDmg"]="t", ["TicksMax"]="T" }
19 local inckey = { ["MeleeDamage"]="a", ["MeleeMax"]="b", ["MeleeHits"]="c", ["MeleeCrits"]="d", ["MeleeMissed"]="e",
20 ["MeleeDodged"]="f", ["MeleeParried"]="g", ["MeleeBlocked"]="h", ["NonMeleeDamage"]="i",
21 ["NonMeleeMax"]="j", ["NonMeleeHits"]="k", ["NonMeleeCrits"]="l", ["NonMeleeMissed"]="m" }
22  
23 -- .Opt.x and its buttons
24 local recapbuttons = { ["Minimized"] = "RecapMinimizeButton", ["Pinned"] = "RecapPinButton",
25 ["Paused"] = "RecapPauseButton", ["SelfView"] = "RecapSelfViewButton" }
26  
27  
28 --[[ Saved Variables ]]
29  
30 recap = {} -- options and current data
31 recap_set = {} -- fight data sets
32  
33 --[[ Callback functions ]]
34  
35 function Recap_OnLoad()
36  
37 this:RegisterEvent("VARIABLES_LOADED")
38 this:RegisterEvent("PLAYER_ENTERING_WORLD")
39 this:RegisterEvent("UNIT_NAME_UPDATE")
40  
41 -- function overrides: recap.NormalExit is true on a successful /quit or /logout
42 Recap_OldQuit = Quit
43 Recap_OldLogout = Logout
44 Recap_OldCancelLogout = CancelLogout
45 Quit = function() recap.NormalExit = true; Recap_OldQuit(); end
46 Logout = function() recap.NormalExit = true; Recap_OldLogout(); end
47 CancelLogout = function() recap.NormalExit = nil; Recap_OldCancelLogout(); end
48  
49 end
50  
51 function Recap_OnEvent()
52  
53 if event=="VARIABLES_LOADED" then
54  
55 SlashCmdList["RecapCOMMAND"] = Recap_SlashHandler
56 SLASH_RecapCOMMAND1 = "/Recap"
57  
58 elseif event=="PLAYER_ENTERING_WORLD" or event=="UNIT_NAME_UPDATE" then
59 Recap_Initialize()
60  
61 elseif event=="PLAYER_REGEN_DISABLED" then
62 if recap.Opt.LimitFights.value then
63 Recap_StartFight()
64 end
65  
66 elseif event=="PLAYER_REGEN_ENABLED" then
67 Recap_EndFight()
68  
69 elseif event=="PARTY_MEMBERS_CHANGED" or event=="RAID_ROSTER_UPDATE" then
70 Recap_MakeFriends()
71  
72 elseif event=="CHAT_MSG_CHANNEL_NOTICE" then
73 if string.find(arg4,"recaplog"..string.lower(UnitName("player"))) and arg1=="YOU_JOINED" then
74 RecapOpt_WriteLogLabel:SetText(RECAP_CHANNEL_JOINED_WRITING)
75 ChatFrameLog(1)
76 RecapFrame:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
77 RecapFrame:RegisterEvent("CHAT_MSG_CHANNEL")
78 Recap_WriteLog()
79 end
80 elseif event=="CHAT_MSG_CHANNEL" then
81 if string.find(string.lower(arg4),"recaplog") and arg2==UnitName("player") and arg1=="EOF" then
82 ChatFrameLog(0)
83 RecapOpt_WriteLogLabel:SetText(RECAP_SAVE_TO_WOWCHATLOG_TXT)
84 LeaveChannelByName("recaplog"..UnitName("player"))
85 RecapFrame:UnregisterEvent("CHAT_MSG_CHANNEL")
86 DEFAULT_CHAT_FRAME:AddMessage(recap_temp.Local.LogWritten)
87 end
88 end
89 end
90  
91 function Recap_Idle_OnUpdate(arg1)
92  
93 -- timer to end idle fights if option checked
94 if recap_temp.IdleTimer~=-1 and recap_temp.Loaded and recap.Opt.IdleFight.value then
95 recap_temp.IdleTimer = recap_temp.IdleTimer + arg1
96 if recap_temp.IdleTimer > recap.Opt.IdleFightTimer.value then
97 recap_temp.IdleTimer = -1
98 Recap_EndFight()
99 end
100 end
101  
102 -- if fighting and a plugin loaded or we're minimized, update min dps every half second
103 if recap_temp.Loaded and recap_temp.UpdateTimer~=-1 and recap.Opt.State.value=="Active" and
104 ((IB_Recap_Update or TitanPanelRecap_Update) or recap.Opt.Minimized.value) then
105 recap_temp.UpdateTimer = recap_temp.UpdateTimer + arg1
106 if recap_temp.UpdateTimer>.5 then
107 recap_temp.UpdateTimer = 0
108 Recap_UpdateMinimizedDPS()
109 end
110 end
111 end
112  
113 function Recap_OnUpdate(arg1)
114  
115 -- update fade timer if option checked
116 if recap_temp.Loaded and recap.Opt.AutoFade.value and not recap.Opt.Minimized.value and MouseIsOver(RecapFrame) and recap_temp.FadeTimer<recap.Opt.AutoFadeTimer.value then
117 recap_temp.FadeTimer = 0
118 elseif recap_temp.Loaded and recap_temp.FadeTimer~=-1 and recap.Opt.AutoFade.value and not recap.Opt.Minimized.value then
119 recap_temp.FadeTimer = recap_temp.FadeTimer + arg1
120 if recap_temp.FadeTimer > recap.Opt.AutoFadeTimer.value then
121 RecapFrame:SetAlpha( max(1-min(2*(recap_temp.FadeTimer-recap.Opt.AutoFadeTimer.value),1),.1))
122 if recap_temp.FadeTimer > (recap.Opt.AutoFadeTimer.value+.5) then
123 RecapFrame_Hide()
124 end
125 end
126 end
127  
128 if recap_temp.Loaded and recap.Opt.AutoMinimize.value and recap_temp.Selected==0 then
129 if not recap.Opt.Minimized.value and not MouseIsOver(RecapFrame) and not IsShiftKeyDown() then
130 Recap_Minimize()
131 elseif recap.Opt.Minimized.value and MouseIsOver(RecapFrame) and not IsShiftKeyDown() then
132 Recap_Maximize()
133 end
134 end
135  
136 end
137  
138 function Recap_SlashHandler(arg1)
139  
140 Recap_Initialize()
141  
142 if arg1 and arg1=="reset" then
143 RecapFrame:ClearAllPoints()
144 RecapFrame:SetPoint("CENTER","UIParent","CENTER")
145 RecapOptFrame:ClearAllPoints()
146 RecapOptFrame:SetPoint("CENTER","UIParent","CENTER")
147 Recap_SetView()
148 elseif arg1=="debug" then
149 if recap.debug then
150 DEFAULT_CHAT_FRAME:AddMessage("recap.debug is ON. To turn it off: /recap debug off")
151 for i=1,150 do
152 if recap.debug_Filter[i] then
153 DEFAULT_CHAT_FRAME:AddMessage("["..i.."] \""..recap.debug_Filter[i].pattern.."\" hits: "..recap.debug_Filter[i].hits..", total: "..recap.debug_Filter[i].total)
154 end
155 end
156 DEFAULT_CHAT_FRAME:AddMessage("__ Filters not used __")
157 Recap_DebugUnusedFilters("Filter")
158 Recap_DebugUnusedFilters("HealFilter")
159 Recap_DebugUnusedFilters("DeathFilter")
160 else
161 DEFAULT_CHAT_FRAME:AddMessage("recap.debug is OFF. To turn it on: /recap debug on")
162 end
163 elseif arg1=="debug on" then
164 recap.debug = true
165 DEFAULT_CHAT_FRAME:AddMessage("recap.debug is now ON.")
166 elseif arg1=="debug off" then
167 recap.debug = false
168 DEFAULT_CHAT_FRAME:AddMessage("recap.debug is now OFF.")
169 elseif arg1=="debug reset" then
170 recap.debug_Filter = {}
171 DEFAULT_CHAT_FRAME:AddMessage("recap.debug_Filter is RESET.")
172 elseif string.find(arg1,"opt") then
173 if RecapOptFrame:IsShown() then
174 RecapOptFrame:Hide()
175 else
176 RecapOptFrame:Show()
177 end
178 elseif RecapFrame:IsShown() then
179 RecapFrame_Hide()
180 RecapOptFrame:Hide()
181 else
182 RecapFrame_Show()
183 Recap_CheckWindowBounds()
184 if recap.Opt.State.value == "Stopped" then
185 Recap_SetState("Idle")
186 recap.Opt.Paused.value = false
187 Recap_SetButtons()
188 end
189 end
190 end
191  
192 --[[ Window appearance functions ]]
193  
194 function Recap_SetState(arg1)
195 if arg1 then
196 recap.Opt.State.value = arg1
197 end
198 if recap.Opt.State.value=="Stopped" then
199 RecapStatusTexture:SetVertexColor(1,0,0)
200 Recap_Unregister_CombatEvents()
201 elseif recap.Opt.State.value=="Active" then
202 RecapStatusTexture:SetVertexColor(0,1,0)
203 Recap_Register_CombatEvents()
204 else
205 RecapStatusTexture:SetVertexColor(.5,.5,.5)
206 Recap_Register_CombatEvents()
207 end
208 Recap_UpdatePlugins()
209 end
210  
211 function RecapFrame_Hide()
212  
213 if not recap_temp.Loaded then
214 Recap_Initialize()
215 end
216 recap_temp.FadeTimer = -1
217 RecapFrame:SetAlpha(1)
218 RecapFrame:Hide()
219 recap.Opt.Visible.value = false
220 end
221  
222 function RecapFrame_Show()
223  
224 if not recap_temp.Loaded then
225 Recap_Initialize()
226 end
227 RecapFrame:Show()
228 recap.Opt.Visible.value = true
229 end
230  
231 function RecapOptFrame_Hide()
232 --[[
233 RecapSetEditBox:SetText("")
234 RecapSetEditBox:ClearFocus()
235 if RecapOptClipFrame:IsVisible() then
236 RecapClipEditBox:ClearFocus()
237 RecapOptClipFrame:Hide()
238 RecapOptSubFrame4:Show()
239 end
240 ]]
241 RecapOptFrame:Hide()
242 end
243  
244 function RecapFrame_Toggle()
245 if RecapFrame:IsShown() then
246 RecapFrame_Hide()
247 RecapOptFrame:Hide()
248 else
249 RecapFrame_Show()
250 end
251 end
252  
253 function Recap_Shutdown()
254  
255 recap.Opt.Paused.value = true
256 Recap_EndFight()
257 Recap_SetState("Stopped")
258 Recap_SetButtons()
259 RecapOptFrame:Hide()
260 RecapFrame_Hide()
261 RecapCombatEvents:UnregisterAll()
262 end
263  
264 function Recap_ToggleView()
265  
266 if recap.Opt.View.value=="All" then
267 Recap_SetView("Last")
268 else
269 Recap_SetView("All")
270 end
271 end
272  
273 -- changes button textures depending on their state
274 function Recap_SetButtons()
275  
276 local i
277  
278 for i in recapbuttons do
279 if recap.Opt[i].value then
280 getglobal(recapbuttons[i]):SetNormalTexture("Interface\\AddOns\\Recap\\RecapButtons-Down")
281 getglobal(recapbuttons[i]):SetPushedTexture("Interface\\AddOns\\Recap\\RecapButtons-Up")
282 else
283 getglobal(recapbuttons[i]):SetNormalTexture("Interface\\AddOns\\Recap\\RecapButtons-Up")
284 getglobal(recapbuttons[i]):SetPushedTexture("Interface\\AddOns\\Recap\\RecapButtons-Down")
285 end
286 end
287  
288 if recap.Opt.View.value=="Last" then
289 RecapShowAllButton:SetNormalTexture("Interface\\AddOns\\Recap\\RecapButtons-Up")
290 RecapShowAllButton:SetPushedTexture("Interface\\AddOns\\Recap\\RecapButtons-Down")
291 else
292 RecapShowAllButton:SetNormalTexture("Interface\\AddOns\\Recap\\RecapButtons-Down")
293 RecapShowAllButton:SetPushedTexture("Interface\\AddOns\\Recap\\RecapButtons-Up")
294 end
295 end
296  
297 -- this resizes the window width to the columns defined in options
298 function Recap_SetColumns()
299  
300 local cx = 168 -- 8(edge)+120(name)+32(scroll)+8(edge)
301  
302 local i,j,icx,item
303  
304 RecapHeader_Name:Show()
305 RecapTotals:Show()
306  
307 if recap.Opt.SelfView.value then
308 for i in recap.Opt do
309 if recap.Opt[i].ewidth then
310 if recap.Opt[i].value then
311 getglobal("RecapHeader_"..i):SetWidth(recap_temp.DefaultOpt[i].ewidth)
312 getglobal("RecapHeader_"..i):Show()
313 for j=1,15 do
314 getglobal("RecapSelf"..j.."_"..i):SetWidth(recap_temp.DefaultOpt[i].ewidth)
315 getglobal("RecapSelf"..j.."_"..i):Show()
316 end
317 cx = cx + recap_temp.DefaultOpt[i].ewidth
318 else
319 getglobal("RecapHeader_"..i):SetWidth(1)
320 getglobal("RecapHeader_"..i):Hide()
321 for j=1,15 do
322 getglobal("RecapSelf"..j.."_"..i):SetWidth(1)
323 getglobal("RecapSelf"..j.."_"..i):Hide()
324 end
325 cx = cx + 1
326 end
327 elseif recap.Opt[i].width then
328 getglobal("RecapHeader_"..i):Hide()
329 end
330 end
331  
332 RecapHeader_EName:Show()
333 RecapHeader_Name:Hide()
334 RecapTotals:Hide()
335  
336 for i=1,15 do
337 getglobal("RecapList"..i):Hide()
338 getglobal("RecapSelf"..i):Show()
339 getglobal("RecapSelf"..i):SetWidth(cx-48)
340 end
341 RecapTotals_DPSIn:Hide()
342  
343 else
344  
345 for i in recap.Opt do
346 if recap.Opt[i].width then
347 if recap.Opt[i].value then
348 item = getglobal("RecapHeader_"..i)
349 item:SetWidth(recap_temp.DefaultOpt[i].width)
350 item:Show()
351 item = getglobal("RecapTotals_"..i)
352 item:SetWidth(recap_temp.DefaultOpt[i].width)
353 item:Show()
354 for j=1,15 do
355 item = getglobal("RecapList"..j.."_"..i)
356 item:SetWidth(recap_temp.DefaultOpt[i].width)
357 item:Show()
358 end
359 cx = cx + recap_temp.DefaultOpt[i].width
360 else
361 item = getglobal("RecapHeader_"..i)
362 item:SetWidth(1)
363 item:Hide()
364 item = getglobal("RecapTotals_"..i)
365 item:SetWidth(1)
366 item:Hide()
367 for j=1,15 do
368 item = getglobal("RecapList"..j.."_"..i)
369 item:SetWidth(1)
370 item:Hide()
371 end
372 cx = cx + 1
373 end
374 elseif recap.Opt[i].ewidth then
375 getglobal("RecapHeader_"..i):Hide()
376 end
377 end
378  
379 for i=1,15 do
380 getglobal("RecapSelf"..i):Hide()
381 getglobal("RecapList"..i):Show()
382 getglobal("RecapList"..i):SetWidth(cx-48)
383 end
384 RecapHeader_EName:Hide()
385  
386 if recap.Opt.DPSIn.value then
387 RecapTotals_DPSIn:Show()
388 else
389 RecapTotals_DPSIn:Hide()
390 end
391  
392 end
393  
394 RecapTotals:SetWidth(cx-48)
395  
396 if recap.Opt.GrowLeftwards.value and RecapFrame then
397 i = RecapFrame:GetRight()
398 j = RecapFrame:GetTop()
399 if i and j then
400 RecapFrame:ClearAllPoints()
401 RecapFrame:SetPoint("TOPLEFT","UIParent","BOTTOMLEFT",i-cx,j) -- *** i not defined sometimes :( **
402 end
403 end
404  
405 RecapTopBar:SetWidth(cx-8)
406 RecapBottomBar:SetWidth(cx-16)
407 RecapFrame:SetWidth(cx)
408 RecapScrollBar:SetWidth(cx-16)
409  
410 recap_temp.GaugeWidth = cx-51 - ( (not recap.Opt.SelfView.value) and ((((recap.Opt.Faction.value and recap.Opt.Faction.width) or 1) + ((recap.Opt.Class.value and recap.Opt.Class.width) or 1) + ((recap.Opt.Ranks.value and recap.Opt.Ranks.width) or 1)) or 0) or 0)
411  
412 Recap_CheckWindowBounds()
413 Recap_SetView()
414 RecapScrollBar_Update()
415  
416 end
417  
418 -- changes view mode
419 function Recap_SetView(arg1)
420  
421 local text
422  
423 if arg1 then
424 recap.Opt.View.value = arg1
425 end
426  
427 Recap_SetButtons()
428 Recap_ConstructList()
429  
430 cx = RecapFrame:GetWidth()
431  
432 -- change titlebar
433 if cx and cx>300 and recap.Opt.SelfView.value then
434 text = recap_temp.Player.."'s Details"
435 elseif cx and cx>230 and recap.Opt.SelfView.value then
436 text = recap_temp.Player
437 elseif cx and cx<230 or recap.Opt.Minimized.value then
438 text = ""
439 if cx>180 and not recap.Opt.SelfView.value then
440 text = recap.Opt.View.value
441 end
442 elseif cx and cx<260 then
443 text = recap_temp.Local.LastAll[recap.Opt.View.value]
444 else
445 text = "Recap of "..recap_temp.Local.LastAll[recap.Opt.View.value]
446 end
447  
448 RecapTitle:SetText(text)
449 RecapHeader_Name:SetText((recap_temp.ListSize-1).." Combatants")
450 Recap_ChangeBack()
451 end
452  
453 function Recap_SetColors()
454  
455 if recap.Opt.UseColor.value then
456 recap_temp.ColorDmgIn = recap_temp.ColorRed
457 recap_temp.ColorDmgOut = recap_temp.ColorGreen
458 recap_temp.ColorHeal = recap_temp.ColorBlue
459 recap_temp.ColorHits = recap_temp.ColorCyan
460 recap_temp.ColorTicks = recap_temp.ColorYellow
461 recap_temp.ColorCrits = recap_temp.ColorLime
462 recap_temp.ColorMiss = recap_temp.ColorPink
463 else
464 recap_temp.ColorDmgIn = recap_temp.ColorWhite
465 recap_temp.ColorDmgOut = recap_temp.ColorNone
466 recap_temp.ColorHeal = recap_temp.ColorWhite
467 recap_temp.ColorHits = recap_temp.ColorWhite
468 recap_temp.ColorTicks = recap_temp.ColorWhite
469 recap_temp.ColorCrits = recap_temp.ColorWhite
470 recap_temp.ColorMiss = recap_temp.ColorWhite
471 end
472  
473 RecapTotals_DmgIn:SetTextColor(recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b)
474 RecapTotals_DmgOut:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
475 RecapTotals_DPS:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
476 RecapTotals_DPSvsAll:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
477 RecapTotals_DPSIn:SetTextColor(recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b)
478 RecapTotals_Heal:SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
479 RecapTotals_Over:SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
480 RecapMinDPSIn_Text:SetTextColor(recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b)
481 RecapMinDPSOut_Text:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
482 for i=1,15 do
483 getglobal("RecapList"..i.."_HealP"):SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
484 getglobal("RecapList"..i.."_Over"):SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
485 getglobal("RecapList"..i.."_DmgInP"):SetTextColor(recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b)
486 getglobal("RecapList"..i.."_DmgOutP"):SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
487 getglobal("RecapSelf"..i.."_EHits"):SetTextColor(recap_temp.ColorHits.r,recap_temp.ColorHits.g,recap_temp.ColorHits.b)
488 getglobal("RecapSelf"..i.."_EHitsAvg"):SetTextColor(recap_temp.ColorHits.r,recap_temp.ColorHits.g,recap_temp.ColorHits.b)
489 getglobal("RecapSelf"..i.."_EHitsMax"):SetTextColor(recap_temp.ColorHits.r,recap_temp.ColorHits.g,recap_temp.ColorHits.b)
490 getglobal("RecapSelf"..i.."_ETicks"):SetTextColor(recap_temp.ColorTicks.r,recap_temp.ColorTicks.g,recap_temp.ColorTicks.b)
491 getglobal("RecapSelf"..i.."_ETicksAvg"):SetTextColor(recap_temp.ColorTicks.r,recap_temp.ColorTicks.g,recap_temp.ColorTicks.b)
492 getglobal("RecapSelf"..i.."_ETicksMax"):SetTextColor(recap_temp.ColorTicks.r,recap_temp.ColorTicks.g,recap_temp.ColorTicks.b)
493 getglobal("RecapSelf"..i.."_ECrits"):SetTextColor(recap_temp.ColorCrits.r,recap_temp.ColorCrits.g,recap_temp.ColorCrits.b)
494 getglobal("RecapSelf"..i.."_ECritsAvg"):SetTextColor(recap_temp.ColorCrits.r,recap_temp.ColorCrits.g,recap_temp.ColorCrits.b)
495 getglobal("RecapSelf"..i.."_ECritsMax"):SetTextColor(recap_temp.ColorCrits.r,recap_temp.ColorCrits.g,recap_temp.ColorCrits.b)
496 getglobal("RecapSelf"..i.."_ECritsP"):SetTextColor(recap_temp.ColorCrits.r,recap_temp.ColorCrits.g,recap_temp.ColorCrits.b)
497 getglobal("RecapSelf"..i.."_EMiss"):SetTextColor(recap_temp.ColorMiss.r,recap_temp.ColorMiss.g,recap_temp.ColorMiss.b)
498 getglobal("RecapSelf"..i.."_EMissP"):SetTextColor(recap_temp.ColorMiss.r,recap_temp.ColorMiss.g,recap_temp.ColorMiss.b)
499 end
500 Recap_ChangeBack()
501 end
502  
503 function Recap_ChangeBack()
504  
505 if recap.Opt.UseColor.value and (recap.Opt.MinBack.value or not recap.Opt.Minimized.value) then
506  
507 if recap.Opt.SelfView.value and not recap.Opt.Minimized.value then
508 RecapTitleBack:SetVertexColor(0,0,.8)
509 elseif recap.Opt.View.value=="Last" then
510 RecapTitleBack:SetVertexColor(0,.66,0)
511 else
512 RecapTitleBack:SetVertexColor(.66,0,0)
513 end
514 RecapTitleBack:Show()
515 else
516 RecapTitleBack:Hide()
517 end
518 end
519  
520  
521 --[[ Initialization ]]
522  
523 -- Can be called often, will immediately dump out if it ran through successfully
524 function Recap_Initialize()
525  
526 local i,x
527 local init_time
528  
529 if not recap_temp.Loaded then
530  
531 if UnitName("player") and UnitName("player")~=UNKNOWNOBJECT and RecapFrame and RecapOptFrame then
532  
533 init_time = GetTime()
534  
535 recap_temp.Player = UnitName("player")
536 recap_temp.Server = GetCVar("realmName")
537  
538 -- recap index for this player
539 recap_temp.p = recap_temp.Player..recap_temp.Server -- use for stuff that can be made global
540 recap_temp.s = recap_temp.Player..recap_temp.Server -- use for stuff that should never be global
541  
542 if recap and recap.UseOneSettings and recap.User then
543 recap_temp.p = recap.User
544 end
545  
546 -- sources of damage/heals otherwise not declared in chat spam
547 recap_temp.FilterIndex[6] = recap_temp.Player
548 recap_temp.FilterIndex[7] = "Melee"
549 recap_temp.FilterIndex[8] = "Damage Shields"
550 recap_temp.FilterIndex[13] = 0
551  
552 Recap_InitializeData()
553  
554 if not recap[recap_temp.p].WindowTop and RecapFrame then
555 RecapFrame:ClearAllPoints()
556 RecapFrame:SetPoint("CENTER","UIParent","CENTER")
557 RecapOptFrame:ClearAllPoints()
558 RecapOptFrame:SetPoint("CENTER", "UIParent", "CENTER")
559 elseif recap[recap_temp.p].WindowTop and RecapFrame then
560 RecapFrame:ClearAllPoints()
561 RecapFrame:SetPoint("TOPLEFT","UIParent","BOTTOMLEFT",recap[recap_temp.p].WindowLeft,recap[recap_temp.p].WindowTop)
562 RecapFrame:SetWidth(recap[recap_temp.p].WindowWidth)
563 RecapFrame:SetHeight(recap[recap_temp.p].WindowHeight)
564 end
565  
566 for i in recap.Combatant do
567 recap.Combatant[i].WasInLast = false
568 recap.Combatant[i].WasInCurrent = false
569 end
570 recap[recap_temp.p].LastDuration = 0
571  
572 Recap_SetColors()
573  
574 -- if we loaded out of stopped state, force into idle state
575 if recap.Opt.State.value ~= "Stopped" then
576 recap.Opt.State.value = "Idle"
577 end
578 Recap_SetState()
579  
580 RecapTotals_Name:SetWidth(82)
581  
582 Recap_InitDataSets()
583  
584 if recap.Opt.LightData.value then
585 recap.Opt.SelfView.value = false
586 RecapSelfViewButton:Hide()
587 end
588  
589 if recap.Opt.Minimized.value then
590 Recap_SetButtons()
591 Recap_ConstructList()
592 Recap_Minimize()
593 else
594 Recap_Maximize()
595 end
596  
597 -- we're in the world (in theory), register active events
598 this:RegisterEvent("PLAYER_REGEN_DISABLED")
599 this:RegisterEvent("PLAYER_REGEN_ENABLED")
600 this:RegisterEvent("PARTY_MEMBERS_CHANGED")
601 this:RegisterEvent("RAID_ROSTER_UPDATE")
602  
603 Recap_Register_CombatEvents()
604  
605 recap_temp.Loaded = true
606  
607 Recap_InitializeOptions()
608 Recap_MoveMinimize()
609  
610 -- initialize panel
611 recap_temp.Selected = 0
612 if recap.Opt.LightData.value then
613 recap.Opt.PanelView.value = 3
614 RecapPanelTab1:SetAlpha(.5)
615 RecapPanelTab2:SetAlpha(.5)
616 end
617 RecapPanel_SwitchPanels(recap.Opt.PanelView.value)
618 if recap.Opt.PanelAnchor.value then
619 RecapPanel:ClearAllPoints()
620 RecapPanel:SetPoint(recap.Opt.PanelAnchor.Panel,"RecapFrame",recap.Opt.PanelAnchor.Main,Recap_PanelOffset("x"),Recap_PanelOffset("y"))
621 end
622 RecapPanelFaction:SetAlpha(.75)
623  
624 for i=1,15 do
625 getglobal("RecapList"..i.."_Faction"):SetAlpha(.75)
626 end
627  
628 if recap.Opt.Visible.value then
629 RecapFrame_Show()
630 else
631 RecapFrame_Hide()
632 end
633  
634 if recap.Opt.Paused.value then
635 RecapFrame_Hide()
636 end
637  
638 if recap.debug then
639 DEFAULT_CHAT_FRAME:AddMessage("[recap.debug] Time to initialize: "..string.format("%.4f",GetTime()-init_time).." seconds.")
640 end
641  
642 -- warn if user has a lot of data (over 500 combatants)
643 x = 0
644 for i in recap.Combatant do
645 x = x + 1
646 end
647 if x>500 and recap.Opt.WarnData.value then
648 StaticPopupDialogs["RECAP_LOTS_OF_DATA_WARNING"] = {
649 text = TEXT(string.format(recap_temp.Local.LotsOfDataWarning,x)),
650 button1 = TEXT(OKAY),
651 timeout = 0,
652 showAlert = 1,
653 whileDead = 1
654 }
655 StaticPopup_Show("RECAP_LOTS_OF_DATA_WARNING")
656 end
657  
658 table.insert(UISpecialFrames,"RecapOptFrame")
659 table.insert(UISpecialFrames,"RecapPanel")
660  
661 end
662  
663 end
664  
665 end
666  
667 -- arg1==1 to hide buttons, 16 to show
668 function Recap_ShowButtons(arg1)
669  
670 RecapCloseButton:SetWidth(arg1)
671 RecapPinButton:SetWidth(arg1)
672 RecapPauseButton:SetWidth(arg1)
673 RecapOptionsButton:SetWidth(arg1)
674 RecapShowAllButton:SetWidth(arg1)
675  
676 if arg1==16 then
677 RecapCloseButton:Show()
678 RecapPinButton:Show()
679 RecapPauseButton:Show()
680 RecapOptionsButton:Show()
681 RecapShowAllButton:Show()
682 else
683 RecapCloseButton:Hide()
684 RecapPinButton:Hide()
685 RecapPauseButton:Hide()
686 RecapOptionsButton:Hide()
687 RecapShowAllButton:Hide()
688 end
689 end
690  
691 function Recap_Minimize()
692  
693 local i,j
694 local cx = 20 -- 8(edge)+4(space right of status)+8
695  
696 recap.Opt.Minimized.value = true
697  
698 for i in recap.Opt do
699 if recap.Opt[i].minwidth then
700 if recap.Opt[i].value then
701 item = getglobal("Recap"..i)
702 item:SetWidth(recap.Opt[i].minwidth)
703 item:Show()
704 cx = cx + recap.Opt[i].minwidth
705 else
706 item = getglobal("Recap"..i)
707 item:SetWidth(1)
708 item:Hide()
709 cx = cx + 1
710 end
711 elseif recap.Opt[i].width or recap.Opt[i].ewidth then
712 getglobal("RecapHeader_"..i):Hide()
713 end
714 end
715  
716 if recap.Opt.MinButtons.value then
717 cx = cx + 108
718 Recap_ShowButtons(16)
719 else
720 Recap_ShowButtons(1)
721 cx = cx + 23 -- 5 + 18
722 end
723  
724 RecapTitle:SetText(recap.Opt.View.value)
725  
726 RecapTopBar:Hide()
727 RecapBottomBar:Hide()
728 RecapTotals_DPSIn:Hide()
729 RecapResetButton:Hide()
730 for i=1,15 do
731 getglobal("RecapList"..i):Hide()
732 getglobal("RecapSelf"..i):Hide()
733 end
734 RecapTotals:Hide()
735 RecapHeader_EName:Hide()
736 RecapHeader_Name:Hide()
737 RecapScrollBar:Hide()
738  
739 if recap.Opt.AutoMinimize.value then
740 cx = cx-15
741 end
742  
743 if recap.Opt.GrowLeftwards.value and RecapFrame then
744 i = RecapFrame:GetRight()
745 j = RecapFrame:GetTop()
746 if i and j then
747 RecapFrame:ClearAllPoints()
748 RecapFrame:SetPoint("TOPLEFT","UIParent","BOTTOMLEFT",i-cx,j)
749 end
750 end
751 RecapFrame:SetWidth(cx)
752 Recap_SetHeight(28)
753  
754 if recap.Opt.MinBack.value then
755 RecapFrame:SetBackdropColor(1,1,1,1)
756 RecapFrame:SetBackdropBorderColor(.5,.5,.5,1)
757 else
758 RecapFrame:SetBackdropColor(0,0,0,0)
759 RecapFrame:SetBackdropBorderColor(0,0,0,0)
760 end
761  
762 RecapSelfViewButton:Hide()
763 RecapPanel_Hide(1)
764 Recap_MoveMinimize()
765 Recap_ChangeBack()
766  
767 RecapMinView:GetLeft()
768  
769 end
770  
771 function Recap_Maximize()
772  
773 recap.Opt.Minimized.value = false
774  
775 for i in recap.Opt do
776 if recap.Opt[i].minwidth then
777 item = getglobal("Recap"..i)
778 item:SetWidth(recap.Opt[i].minwidth)
779 item:Hide()
780 end
781 end
782 RecapMinStatus:Show()
783 RecapMinView:Show()
784 Recap_ShowButtons(16)
785  
786 RecapTopBar:Show()
787 RecapBottomBar:Show()
788 RecapResetButton:Show()
789  
790 RecapTotals:Show()
791 RecapHeader_Name:Show()
792  
793 RecapScrollBar:Show()
794 Recap_SetColumns()
795  
796 RecapFrame:SetBackdropColor(1,1,1,1)
797 RecapFrame:SetBackdropBorderColor(.5,.5,.5,1)
798 if not recap.Opt.LightData.value then
799 RecapSelfViewButton:Show()
800 end
801 Recap_MoveMinimize()
802 end
803  
804 function Recap_SetHeight(newcy)
805  
806 local i,j
807  
808 if recap.Opt.GrowUpwards.value and RecapFrame then
809 i = RecapFrame:GetBottom()
810 j = RecapFrame:GetLeft()
811 if i and j then
812 RecapFrame:ClearAllPoints()
813 RecapFrame:SetPoint("TOPLEFT","UIParent","BOTTOMLEFT",j,i+newcy)
814 end
815 end
816  
817 RecapFrame:SetHeight(newcy)
818 Recap_CheckWindowBounds()
819 end
820  
821 function RecapScrollBar_Update()
822  
823 local i, index, item
824 local listsize = recap.Opt.SelfView.value and recap_temp.SelfListSize or recap_temp.ListSize
825  
826  
827 if not recap.Opt.Minimized.value then
828  
829 i = 72 + ( math.max( math.min(listsize-1,recap.Opt.MaxRows.value),1 )*14 )
830 Recap_SetHeight(i)
831 RecapScrollBar:SetHeight(i-63)
832 FauxScrollFrame_Update(RecapScrollBar,listsize-1,recap.Opt.MaxRows.value,10)
833  
834 for i=1,recap.Opt.MaxRows.value do
835 index = i + FauxScrollFrame_GetOffset(RecapScrollBar)
836  
837 if not recap.Opt.SelfView.value then
838  
839 if index < listsize then
840  
841 getglobal("RecapList"..i.."_Ranks"):SetText(index..".")
842  
843 Recap_SetFactionIcon(i,recap.Combatant[recap_temp.List[index].Name].Faction)
844 Recap_SetClassIcon(i,recap.Combatant[recap_temp.List[index].Name].Class)
845 if recap.Opt.Faction.value and recap.Combatant[recap_temp.List[index].Name].Level==-1 then
846 getglobal("RecapList"..i.."_Level"):SetText("??")
847 elseif recap.Opt.Faction.value and recap.Combatant[recap_temp.List[index].Name].Level and tonumber(recap.Combatant[recap_temp.List[index].Name].Level)>0 then
848 getglobal("RecapList"..i.."_Level"):SetText(recap.Combatant[recap_temp.List[index].Name].Level)
849 else
850 getglobal("RecapList"..i.."_Level"):SetText(" ")
851 end
852  
853 item = getglobal("RecapList"..i.."_Name")
854 item:SetText(recap_temp.List[index].Name)
855 if recap.Combatant[recap_temp.List[index].Name].Friend then
856 item:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
857 else
858 item:SetTextColor(recap_temp.ColorWhite.r,recap_temp.ColorWhite.g,recap_temp.ColorWhite.b)
859 end
860  
861 item = getglobal("RecapList"..i.."_Gauge")
862 if recap.Opt.ShowGauges.value and recap_temp.GaugeMax>0 and recap.Combatant[recap_temp.List[index].Name].Friend and recap_temp.GaugeBy then
863 item:SetWidth(1+recap_temp.GaugeWidth*recap_temp.List[index][recap_temp.GaugeBy]/recap_temp.GaugeMax)
864 item:Show()
865 else
866 item:Hide()
867 end
868  
869 getglobal("RecapList"..i.."_Kills"):SetText(recap_temp.List[index].Kills)
870  
871 getglobal("RecapList"..i.."_Time"):SetText(Recap_FormatTime(recap_temp.List[index].Time))
872  
873 item = getglobal("RecapList"..i.."_Heal")
874 item:SetText(recap_temp.List[index].Heal)
875 if recap.Combatant[recap_temp.List[index].Name].Friend then
876 item:SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
877 else
878 item:SetTextColor(recap_temp.ColorWhite.r,recap_temp.ColorWhite.g,recap_temp.ColorWhite.b)
879 end
880  
881 getglobal("RecapList"..i.."_HealP"):SetText(recap.Combatant[recap_temp.List[index].Name].Friend and recap_temp.List[index].HealP.."%" or "")
882 getglobal("RecapList"..i.."_Over"):SetText(recap.Combatant[recap_temp.List[index].Name].Friend and recap_temp.List[index].Over.."%" or "")
883  
884 getglobal("RecapList"..i.."_MaxHit"):SetText(recap_temp.List[index].MaxHit)
885  
886 item = getglobal("RecapList"..i.."_DmgIn")
887 item:SetText(recap_temp.List[index].DmgIn)
888 if recap.Combatant[recap_temp.List[index].Name].Friend then
889 item:SetTextColor(recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b)
890 else
891 item:SetTextColor(recap_temp.ColorWhite.r,recap_temp.ColorWhite.g,recap_temp.ColorWhite.b)
892 end
893  
894 getglobal("RecapList"..i.."_DmgInP"):SetText(recap.Combatant[recap_temp.List[index].Name].Friend and recap_temp.List[index].DmgInP.."%" or "")
895  
896 item = getglobal("RecapList"..i.."_DmgOut")
897 item:SetText(recap_temp.List[index].DmgOut)
898 if recap.Combatant[recap_temp.List[index].Name].Friend then
899 item:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
900 else
901 item:SetTextColor(recap_temp.ColorWhite.r,recap_temp.ColorWhite.g,recap_temp.ColorWhite.b)
902 end
903  
904 getglobal("RecapList"..i.."_DmgOutP"):SetText(recap.Combatant[recap_temp.List[index].Name].Friend and recap_temp.List[index].DmgOutP.."%" or "")
905  
906 item = getglobal("RecapList"..i.."_DPS")
907 item:SetText(format(recap_temp.List[index].DPS<1000 and "%.1f" or "%d",recap_temp.List[index].DPS))
908 if recap.Combatant[recap_temp.List[index].Name].Friend then
909 item:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
910 else
911 item:SetTextColor(recap_temp.ColorWhite.r,recap_temp.ColorWhite.g,recap_temp.ColorWhite.b)
912 end
913 item = getglobal("RecapList"..i.."_DPSvsAll")
914 item:SetText(format(recap_temp.List[index].DPSvsAll<1000 and "%.1f" or "%d",recap_temp.List[index].DPSvsAll))
915 if recap.Combatant[recap_temp.List[index].Name].Friend then
916 item:SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
917 else
918 item:SetTextColor(recap_temp.ColorWhite.r,recap_temp.ColorWhite.g,recap_temp.ColorWhite.b)
919 end
920  
921 item = getglobal("RecapList"..i)
922 item:Show()
923 if recap_temp.Selected == index then
924 item:LockHighlight()
925 else
926 item:UnlockHighlight()
927 end
928  
929 else
930 getglobal("RecapList"..i):Hide()
931 getglobal("RecapList"..i):UnlockHighlight()
932 end
933  
934 for i=recap.Opt.MaxRows.value+1,15 do
935 getglobal("RecapList"..i):Hide()
936 end
937  
938 elseif recap.Opt.SelfView.value then
939  
940 if index < listsize then
941  
942 getglobal("RecapSelf"..i.."_EName"):SetText(string.sub(recap_temp.SelfList[index].EName,2))
943 getglobal("RecapSelf"..i.."_ETotal"):SetText(recap_temp.SelfList[index].ETotal)
944 getglobal("RecapSelf"..i.."_EHits"):SetText(recap_temp.SelfList[index].EHits)
945 getglobal("RecapSelf"..i.."_ETicks"):SetText(recap_temp.SelfList[index].ETicks)
946 getglobal("RecapSelf"..i.."_ECrits"):SetText(recap_temp.SelfList[index].ECrits)
947 getglobal("RecapSelf"..i.."_EHitsAvg"):SetText(recap_temp.SelfList[index].EHitsAvg)
948 getglobal("RecapSelf"..i.."_ETicksAvg"):SetText(recap_temp.SelfList[index].ETicksAvg)
949 getglobal("RecapSelf"..i.."_ECritsAvg"):SetText(recap_temp.SelfList[index].ECritsAvg)
950 getglobal("RecapSelf"..i.."_EHitsMax"):SetText(recap_temp.SelfList[index].EHitsMax)
951 getglobal("RecapSelf"..i.."_ETicksMax"):SetText(recap_temp.SelfList[index].ETicksMax)
952 getglobal("RecapSelf"..i.."_ECritsMax"):SetText(recap_temp.SelfList[index].ECritsMax)
953 getglobal("RecapSelf"..i.."_ECritsP"):SetText(recap_temp.SelfList[index].ECritsP)
954 getglobal("RecapSelf"..i.."_EMiss"):SetText(recap_temp.SelfList[index].EMiss)
955 getglobal("RecapSelf"..i.."_EMissP"):SetText(recap_temp.SelfList[index].EMissP)
956 getglobal("RecapSelf"..i.."_EMaxAll"):SetText(recap_temp.SelfList[index].EMaxAll)
957 getglobal("RecapSelf"..i.."_ETotalP"):SetText(recap_temp.SelfList[index].ETotalP)
958 if string.sub(recap_temp.SelfList[index].EName,1,1)<"3" then
959 getglobal("RecapSelf"..i.."_EName"):SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
960 getglobal("RecapSelf"..i.."_ETotal"):SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
961 getglobal("RecapSelf"..i.."_ETotalP"):SetTextColor(recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
962 else
963 getglobal("RecapSelf"..i.."_EName"):SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
964 getglobal("RecapSelf"..i.."_ETotal"):SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
965 getglobal("RecapSelf"..i.."_ETotalP"):SetTextColor(recap_temp.ColorHeal.r,recap_temp.ColorHeal.g,recap_temp.ColorHeal.b)
966 end
967 getglobal("RecapSelf"..i):Show()
968 else
969 getglobal("RecapSelf"..i):Hide()
970 end
971  
972 for i=recap.Opt.MaxRows.value+1,15 do
973 getglobal("RecapSelf"..i):Hide()
974 end
975  
976 end
977  
978 end
979  
980 end
981 end
982  
983 --[[ Fight functions ]]
984  
985 function Recap_CreateCombatant(arg1,is_source)
986  
987 if not arg1 then
988 return
989 end
990  
991 -- if arg1 not a .Combatant, add an entry for them
992 if not recap.Combatant[arg1] then
993 Recap_CreateBlankCombatant(arg1)
994 end
995 -- if they haven't fought this session, add a .Last entry for them
996 if not recap_temp.Last[arg1] then
997 recap_temp.Last[arg1] = { Start = 0, End = 0, DmgIn = 0, DmgOut = 0, MaxHit = 0, Kills = 0, Heal = 0 }
998 end
999 -- if arg1 is hitting others, update their start or end time
1000 if is_source then
1001  
1002 if recap_temp.FightStart==0 then
1003 recap_temp.FightStart = GetTime()
1004 recap_temp.FightEnd = recap_temp.FightStart
1005 else
1006 recap_temp.FightEnd = GetTime()
1007 end
1008  
1009 if recap_temp.Last[arg1].Start==0 then
1010 recap_temp.Last[arg1].Start = GetTime()
1011 recap_temp.Last[arg1].End = recap_temp.Last[arg1].Start
1012 else
1013 recap_temp.Last[arg1].End = GetTime()
1014 end
1015 end
1016  
1017 recap.Combatant[arg1].WasInCurrent = true
1018 end
1019  
1020 function Recap_StartFight()
1021  
1022 local i
1023  
1024 if recap.Opt.State.value=="Idle" then
1025 if recap.Opt.AutoHide.value and not recap.Opt.Minimized.value then
1026 RecapFrame_Hide()
1027 end
1028 for i in recap.Combatant do
1029 recap.Combatant[i].WasInCurrent = false
1030 end
1031 if not recap.Opt.LimitFights.value and recap.Opt.IdleFight.value then
1032 recap_temp.IdleTimer = 0
1033 end
1034 RecapIdleFrame:Show() -- start idle OnUpdates
1035 Recap_SetState("Active")
1036 end
1037 end
1038  
1039 -- returns the current DPS of combatant named arg1 if it exists. UpdateDuration/DamageOut reused to save allocations
1040 function Recap_GetCurrentDPS(arg1)
1041  
1042 if arg1 and recap_temp.Last[arg1] and recap_temp.Last[arg1].DmgOut>0 then
1043 recap_temp.UpdateDuration = recap_temp.Last[arg1].End - recap_temp.Last[arg1].Start
1044 if recap.Opt.View.value=="All" then
1045 recap_temp.UpdateDuration = recap_temp.UpdateDuration + recap.Combatant[arg1].TotalTime
1046 end
1047 recap_temp.UpdateDamageOut = recap_temp.Last[arg1].DmgOut
1048 if recap.Opt.View.value=="All" then
1049 recap_temp.UpdateDamageOut = recap_temp.UpdateDamageOut + recap.Combatant[arg1].TotalDmgOut
1050 end
1051  
1052 if recap_temp.UpdateDuration > recap_temp.MinTime then
1053 return (recap_temp.UpdateDamageOut / recap_temp.UpdateDuration)
1054 end
1055 end
1056  
1057 return 0
1058 end
1059  
1060 function Recap_UpdateMinimizedDPS()
1061  
1062 if recap.Opt.State.value=="Active" then
1063  
1064 if recap_temp.Last[recap_temp.Player] and recap_temp.Last[recap_temp.Player].DmgOut>0 then
1065 i = Recap_GetCurrentDPS(recap_temp.Player)+Recap_GetCurrentDPS(UnitName("pet"))
1066 RecapMinYourDPS_Text:SetText(string.format("%.1f",i))
1067 end
1068  
1069 -- calculate running total DPS In and Out
1070 recap_temp.UpdateDuration = 0
1071 if recap_temp.FightEnd>0 and recap_temp.FightStart>0 then
1072 recap_temp.UpdateDuration = recap_temp.FightEnd - recap_temp.FightStart
1073 end
1074 if recap.Opt.View.value=="All" then
1075 recap_temp.UpdateDuration = recap_temp.UpdateDuration + recap[recap_temp.p].TotalDuration
1076 end
1077  
1078 if recap_temp.UpdateDuration>recap_temp.MinTime then
1079  
1080 recap_temp.UpdateDmgIn = 0
1081 recap_temp.UpdateDmgOut = 0
1082 for i in recap_temp.Last do
1083 if recap.Combatant[i].Friend then
1084 recap_temp.UpdateDmgIn = recap_temp.UpdateDmgIn + recap_temp.Last[i].DmgIn
1085 recap_temp.UpdateDmgOut = recap_temp.UpdateDmgOut + recap_temp.Last[i].DmgOut
1086 end
1087 end
1088  
1089 if recap.Opt.View.value=="All" then
1090 for i in recap.Combatant do
1091 if recap.Combatant[i].Friend then
1092 recap_temp.UpdateDmgIn = recap_temp.UpdateDmgIn + recap.Combatant[i].TotalDmgIn
1093 recap_temp.UpdateDmgOut = recap_temp.UpdateDmgOut + recap.Combatant[i].TotalDmgOut
1094 end
1095 end
1096 end
1097  
1098 RecapMinDPSIn_Text:SetText(string.format("%.1f",recap_temp.UpdateDmgIn/recap_temp.UpdateDuration))
1099 RecapMinDPSOut_Text:SetText(string.format("%.1f",recap_temp.UpdateDmgOut/recap_temp.UpdateDuration))
1100  
1101 end
1102  
1103 Recap_UpdatePlugins()
1104 end
1105 end
1106  
1107 function Recap_AddPetToOwner(pet,owner)
1108  
1109 local earliest,latest
1110 local peteffect
1111  
1112 -- times are only for DAMAGE
1113 if (recap.Combatant[pet].WasInCurrent and recap_temp.Last[pet].DmgOut>0) and (recap.Combatant[owner].WasInCurrent and recap_temp.Last[owner].DmgOut>0) then
1114 -- both pet and owner were in fight
1115 earliest = math.min(recap_temp.Last[pet].Start,recap_temp.Last[owner].Start)
1116 latest = math.max(recap_temp.Last[pet].End,recap_temp.Last[owner].End)
1117 recap_temp.Last[owner].Start = earliest
1118 recap_temp.Last[owner].End = latest
1119 elseif (recap.Combatant[pet].WasInCurrent and recap_temp.Last[pet].DmgOut>0) and (not recap.Combatant[owner].WasInCurrent or recap_temp.Last[owner].DmgOut==0) then
1120 -- just the pet was in fight
1121 recap_temp.Last[owner].Start = recap_temp.Last[pet].Start
1122 recap_temp.Last[owner].End = recap_temp.Last[pet].End
1123 else
1124 return -- temp fix for attempt to index field ? (a nil value) in line below ***
1125 end
1126  
1127 recap_temp.Last[owner].DmgIn = recap_temp.Last[owner].DmgIn + recap_temp.Last[pet].DmgIn
1128 recap_temp.Last[owner].DmgOut = recap_temp.Last[owner].DmgOut + recap_temp.Last[pet].DmgOut
1129 recap_temp.Last[owner].MaxHit = math.max(recap_temp.Last[owner].MaxHit,recap_temp.Last[pet].MaxHit)
1130  
1131 Recap_AccumulateCombatant(owner)
1132  
1133 recap_temp.Last[pet].Start = 0
1134 recap_temp.Last[pet].End = 0
1135 recap_temp.Last[pet].DmgIn = 0
1136 recap_temp.Last[pet].DmgOut = 0
1137 recap_temp.Last[pet].MaxHit = 0
1138 recap_temp.Last[pet].Kills = 0
1139 recap_temp.Last[pet].Heal = 0
1140 recap.Combatant[pet].WasInLast = false
1141 recap.Combatant[owner].WasInLast = true
1142 recap.Combatant[pet].WasInCurrent = false
1143 recap.Combatant[owner].WasInCurrent = false
1144  
1145 if not recap.Opt.LightData.value then
1146 for i in recap.Combatant[pet].Detail do
1147 if string.sub(i,1,1)=="1" then
1148 peteffect = "2"..pet.."'s "..string.sub(i,2)
1149 else
1150 peteffect = "4"..pet.."'s "..string.sub(i,2)
1151 end
1152 recap.Combatant[owner].Detail[peteffect] = {
1153 Hits = recap.Combatant[pet].Detail[i].Hits, HitsDmg = recap.Combatant[pet].Detail[i].HitsDmg,
1154 HitsMax = recap.Combatant[pet].Detail[i].HitsMax, Crits = recap.Combatant[pet].Detail[i].Crits,
1155 CritsEvents = recap.Combatant[pet].Detail[i].CritsEvents, CritsDmg = recap.Combatant[pet].Detail[i].CritsDmg,
1156 CritsMax = recap.Combatant[pet].Detail[i].CritsMax, Missed = recap.Combatant[pet].Detail[i].Missed,
1157 TicksDmg = recap.Combatant[pet].Detail[i].TicksDmg, TicksMax = recap.Combatant[pet].Detail[i].TicksMax }
1158 if owner==recap_temp.Player then
1159 recap.Self[recap_temp.s][peteffect] = {
1160 Hits = recap.Combatant[pet].Detail[i].Hits, HitsDmg = recap.Combatant[pet].Detail[i].HitsDmg,
1161 HitsMax = recap.Combatant[pet].Detail[i].HitsMax, Crits = recap.Combatant[pet].Detail[i].Crits,
1162 CritsEvents = recap.Combatant[pet].Detail[i].CritsEvents, CritsDmg = recap.Combatant[pet].Detail[i].CritsDmg,
1163 CritsMax = recap.Combatant[pet].Detail[i].CritsMax, Missed = recap.Combatant[pet].Detail[i].Missed,
1164 TicksDmg = recap.Combatant[pet].Detail[i].TicksDmg, TicksMax = recap.Combatant[pet].Detail[i].TicksMax }
1165 end
1166 end
1167 end
1168  
1169 end
1170  
1171 function Recap_AccumulateCombatant(i)
1172  
1173 recap.Combatant[i].LastDmgIn = recap_temp.Last[i].DmgIn
1174 recap.Combatant[i].LastDmgOut = recap_temp.Last[i].DmgOut
1175 recap.Combatant[i].LastTime = recap_temp.Last[i].End-recap_temp.Last[i].Start
1176 recap.Combatant[i].LastMaxHit = recap_temp.Last[i].MaxHit
1177 recap.Combatant[i].LastKills = recap_temp.Last[i].Kills
1178 recap.Combatant[i].LastHeal = recap_temp.Last[i].Heal
1179  
1180 recap_temp.Last[i].Start = 0
1181 recap_temp.Last[i].End = 0
1182 recap_temp.Last[i].DmgIn = 0
1183 recap_temp.Last[i].DmgOut = 0
1184 recap_temp.Last[i].MaxHit = 0
1185 recap_temp.Last[i].Kills = 0
1186 recap_temp.Last[i].Heal = 0
1187  
1188 recap.Combatant[i].TotalDmgIn = recap.Combatant[i].TotalDmgIn + recap.Combatant[i].LastDmgIn
1189 recap.Combatant[i].TotalDmgOut = recap.Combatant[i].TotalDmgOut + recap.Combatant[i].LastDmgOut
1190 recap.Combatant[i].TotalTime = recap.Combatant[i].TotalTime + recap.Combatant[i].LastTime
1191 recap.Combatant[i].TotalKills = recap.Combatant[i].TotalKills + recap.Combatant[i].LastKills
1192 recap.Combatant[i].TotalHeal = recap.Combatant[i].TotalHeal + recap.Combatant[i].LastHeal
1193  
1194 if recap.Combatant[i].LastTime > recap_temp.MinTime then
1195 recap.Combatant[i].LastDPS = recap.Combatant[i].LastDmgOut/recap.Combatant[i].LastTime
1196 else
1197 recap.Combatant[i].LastDPS = 0
1198 end
1199 if recap.Combatant[i].TotalTime > recap_temp.MinTime then
1200 recap.Combatant[i].TotalDPS = recap.Combatant[i].TotalDmgOut/recap.Combatant[i].TotalTime
1201 else
1202 recap.Combatant[i].TotalDPS = 0
1203 end
1204  
1205 recap.Combatant[i].TotalMaxHit = math.max(recap.Combatant[i].LastMaxHit,recap.Combatant[i].TotalMaxHit)
1206  
1207 recap.Combatant[i].WasInLast = true
1208 end
1209  
1210 function Recap_EndFight()
1211  
1212 recap_temp.IdleTimer = -1
1213  
1214 RecapIdleFrame:Hide()
1215  
1216 if recap.Opt.State.value=="Active" then
1217  
1218 recap.Opt.State.value = "Stopped" -- suspend logging to calculate
1219  
1220 local debug_time = GetTime()
1221  
1222 Recap_MakeFriends()
1223  
1224 if recap_temp.FightEnd>recap_temp.FightStart then
1225 recap[recap_temp.p].LastDuration = recap_temp.FightEnd-recap_temp.FightStart
1226 else
1227 recap[recap_temp.p].LastDuration = 0
1228 end
1229 recap[recap_temp.p].TotalDuration = recap[recap_temp.p].TotalDuration + recap[recap_temp.p].LastDuration
1230 recap_temp.FightStart = 0
1231 recap_temp.FightEnd = 0
1232  
1233 recap_temp.ListSize = 1
1234 for i in recap_temp.Last do
1235  
1236 if recap.Combatant[i].WasInCurrent then
1237 if recap.Combatant[i].OwnedBy and recap.Opt.MergePets.value then
1238 Recap_AddPetToOwner(i,recap.Combatant[i].OwnedBy)
1239 elseif recap.Combatant[i].OwnsPet and recap.Opt.MergePets.value then
1240 Recap_AddPetToOwner(recap.Combatant[i].OwnsPet,i)
1241 else
1242 Recap_AccumulateCombatant(i)
1243 end
1244 else
1245 recap.Combatant[i].WasInLast = false
1246 end
1247  
1248 end
1249  
1250 if recap.Opt.AutoPost.value then
1251 recap.Opt.SortBy.value = Recap_AutoPostGetStatID(recap.Opt.AutoPost.Stat)
1252 recap.Opt.SortDir.value = false
1253 end
1254  
1255 Recap_ConstructList()
1256 Recap_SetState("Idle")
1257  
1258 if not recap.Opt.Minimized.value and recap.Opt.AutoHide.value then
1259 RecapFrame_Show()
1260 if recap.Opt.AutoFade.value then
1261 recap_temp.FadeTimer = 0
1262 end
1263 end
1264  
1265 if recap.Opt.AutoPost.value then
1266 Recap_PostFight()
1267 end
1268  
1269 if recap.Opt.AutoLeader.value then
1270 Recap_PostLeader()
1271 end
1272  
1273 if recap.debug then
1274 DEFAULT_CHAT_FRAME:AddMessage("[recap.debug] Fight processed in "..string.format("%.4f",GetTime()-debug_time).." seconds for "..(recap_temp.ListSize-1).." combatants.")
1275 end
1276  
1277 end
1278 end
1279  
1280 -- parses CHAT_MSG_SPELL/COMBAT messages to .Last running totals
1281 function Recap_DamageEvent(arg1)
1282  
1283 local i, source, dest, damage, miss, effect
1284 local found = false
1285 local blocked = false
1286  
1287 if recap.Opt.State.value~="Stopped" then
1288  
1289 blocked = string.find(arg1,string.gsub(BLOCK_TRAILER,"%%d","%%d+")) -- true if (%d blocked)
1290 arg1 = string.gsub(arg1," %(.+%)","") -- strip trailing ()'s we don't use
1291 arg1 = string.gsub(arg1,"%.$","") -- strip trailing .'s
1292  
1293 for i=1,recap_temp.FilterSize do
1294 found,_,recap_temp.FilterIndex[1],recap_temp.FilterIndex[2],recap_temp.FilterIndex[3],recap_temp.FilterIndex[4],recap_temp.FilterIndex[5] = string.find(arg1,recap_temp.Filter[i].pattern)
1295 if found then
1296  
1297 source=recap_temp.FilterIndex[recap_temp.Filter[i].source]
1298 dest=recap_temp.FilterIndex[recap_temp.Filter[i].dest]
1299 if recap_temp.Local.SelfPronouns[string.lower(dest)] then
1300 dest = recap_temp.Player
1301 end
1302 if recap_temp.Filter[i].damage then
1303 damage=tonumber(recap_temp.FilterIndex[recap_temp.Filter[i].damage])
1304 end
1305 if recap_temp.Filter[i].effect then
1306 effect = recap_temp.FilterIndex[recap_temp.Filter[i].effect]
1307 end
1308  
1309 if (recap.Combatant[source] and recap.Combatant[source].Ignore) or (recap.Combatant[dest] and recap.Combatant[dest].Ignore) then
1310 return -- this is an ignored combatant, pretend the hit didn't happen at all
1311 end
1312  
1313 if not recap.Opt.LimitFights.value then
1314 if recap.Opt.IdleFight.value then
1315 recap_temp.IdleTimer = 0
1316 end
1317 if recap.Opt.State.value=="Idle" then
1318 Recap_StartFight()
1319 end
1320 end
1321  
1322 if recap.debug then
1323 if not recap.debug_Filter then
1324 recap.debug_Filter = {}
1325 end
1326 if not recap.debug_Filter[i] then
1327 recap.debug_Filter[i] = { hits=1, total=(damage or 1), pattern=recap_temp.Filter[i].pattern }
1328 else
1329 recap.debug_Filter[i].hits = recap.debug_Filter[i].hits + 1
1330 recap.debug_Filter[i].total = recap.debug_Filter[i].total + (damage or 1)
1331 end
1332 if recap_temp.Filter[i].watch then
1333 DEFAULT_CHAT_FRAME:AddMessage("["..i.."] \""..recap_temp.Filter[i].pattern.."\" triggered!")
1334 DEFAULT_CHAT_FRAME:AddMessage("source="..tostring(source)..", dest="..tostring(dest)..", damage="..tostring(damage)..", miss="..tostring(miss))
1335 end
1336 end
1337  
1338 if damage~=0 then -- if this wasn't just a cast
1339 Recap_CreateCombatant(source,1)
1340 Recap_CreateCombatant(dest)
1341 -- remove friend flag from hostiles no longer charmed
1342 if recap.Combatant[source].Friend and recap.Combatant[dest].Friend then
1343 recap.Combatant[source].Friend = false
1344 end
1345 else
1346 if (not recap.Opt.LightData.value) and recap.Combatant[source] and recap.Combatant[source].Detail["1"..effect] then
1347 Recap_CreateCombatant(source,1) -- if this was a cast that's done damage before, start timer
1348 end
1349 end
1350  
1351 if damage and damage>0 then
1352 -- process totals
1353 recap_temp.Last[source].DmgOut = recap_temp.Last[source].DmgOut + damage
1354 if damage > recap_temp.Last[source].MaxHit then
1355 recap_temp.Last[source].MaxHit = damage
1356 end
1357 recap_temp.Last[dest].DmgIn = recap_temp.Last[dest].DmgIn + damage
1358  
1359 if recap_temp.Last[dest].HP then
1360 recap_temp.Last[dest].HP = recap_temp.Last[dest].HP - damage
1361 end
1362  
1363 if not recap.Opt.LightData.value then
1364 if recap_temp.Filter[i].effect==7 then -- melee damage
1365 recap.Combatant[dest].Incoming.MeleeDamage = (recap.Combatant[dest].Incoming.MeleeDamage or 0) + damage
1366 if recap_temp.Filter[i].crit==1 then
1367 recap.Combatant[dest].Incoming.MeleeCrits = (recap.Combatant[dest].Incoming.MeleeCrits or 0) + 1
1368 else
1369 recap.Combatant[dest].Incoming.MeleeHits = (recap.Combatant[dest].Incoming.MeleeHits or 0) + 1
1370 end
1371 recap.Combatant[dest].Incoming.MeleeMax = math.max(damage,recap.Combatant[dest].Incoming.MeleeMax or 0)
1372 if blocked then
1373 recap.Combatant[dest].Incoming.MeleeBlocked = (recap.Combatant[dest].Incoming.MeleeBlocked or 0)+ 1
1374 end
1375 else
1376 recap.Combatant[dest].Incoming.NonMeleeDamage = (recap.Combatant[dest].Incoming.NonMeleeDamage or 0) + damage
1377 if recap_temp.Filter[i].crit==1 then
1378 recap.Combatant[dest].Incoming.NonMeleeCrits = (recap.Combatant[dest].Incoming.NonMeleeCrits or 0) + 1
1379 else
1380 recap.Combatant[dest].Incoming.NonMeleeHits = (recap.Combatant[dest].Incoming.NonMeleeHits or 0) + 1
1381 end
1382 recap.Combatant[dest].Incoming.NonMeleeMax = math.max(damage,recap.Combatant[dest].Incoming.NonMeleeMax or 0)
1383 end
1384 Recap_CreateEffect(source,effect,1,damage,recap_temp.Filter[i].crit)
1385 end
1386  
1387 elseif recap_temp.Filter[i].miss and not recap.Opt.LightData.value then
1388 if recap_temp.Filter[i].miss==9 and recap_temp.Filter[i].effect==7 then -- melee normal miss
1389 recap.Combatant[dest].Incoming.MeleeMissed = (recap.Combatant[dest].Incoming.MeleeMissed or 0) + 1
1390 elseif recap_temp.Filter[i].miss==9 then -- non-melee miss
1391 recap.Combatant[dest].Incoming.NonMeleeMissed = (recap.Combatant[dest].Incoming.NonMeleeMissed or 0) + 1
1392 elseif recap_temp.Filter[i].miss==10 then -- melee dodge
1393 recap.Combatant[dest].Incoming.MeleeDodged = (recap.Combatant[dest].Incoming.MeleeDodged or 0) + 1
1394 elseif recap_temp.Filter[i].miss==11 then -- melee parry
1395 recap.Combatant[dest].Incoming.MeleeParried = (recap.Combatant[dest].Incoming.MeleeParried or 0) + 1
1396 elseif recap_temp.Filter[i].miss==12 then -- melee block
1397 recap.Combatant[dest].Incoming.MeleeBlocked = (recap.Combatant[dest].Incoming.MeleeBlocked or 0) + 1
1398 end
1399 Recap_CreateEffect(source,effect,1,0)
1400 end
1401  
1402 i=recap_temp.FilterSize+1
1403 end
1404 end
1405 end
1406 end
1407  
1408 -- did_crit=1 for a crit, =0 for a normal hit but it could crit
1409 -- total = amount of hit/heal, 0 for a miss
1410 function Recap_CreateEffect(source,effect,type,total,did_crit)
1411  
1412 effect = type..effect
1413  
1414 -- skip misses that aren't a stored effect yet, to prevent logging debuff resists
1415 if not (total==0 and not recap.Combatant[source].Detail[effect]) then
1416  
1417 -- ChatFrame2:AddMessage("effect: "..effect..", source: "..source..", total: "..total..", did_crit: "..tostring(did_crit))
1418  
1419 if not recap.Combatant[source].Detail[effect] then
1420 recap.Combatant[source].Detail[effect] = {} -- Hits=0, HitsDmg=0, HitsMax=0, Crits=0, CritsEvents=0, CritsDmg=0, CritsMax=0, Missed=0, TicksDmg, TicksMax }
1421 end
1422  
1423 if source==recap_temp.Player and not recap.Self[recap_temp.s][effect] then
1424 recap.Self[recap_temp.s][effect] = {}
1425 end
1426  
1427 if did_crit==1 then
1428 recap.Combatant[source].Detail[effect].CritsEvents = (recap.Combatant[source].Detail[effect].CritsEvents or 0) + 1
1429 recap.Combatant[source].Detail[effect].Crits = (recap.Combatant[source].Detail[effect].Crits or 0) + did_crit
1430 recap.Combatant[source].Detail[effect].CritsDmg = (recap.Combatant[source].Detail[effect].CritsDmg or 0) + total
1431 recap.Combatant[source].Detail[effect].CritsMax = math.max(total,recap.Combatant[source].Detail[effect].CritsMax or 0)
1432 if source==recap_temp.Player then
1433 recap.Self[recap_temp.s][effect].CritsEvents = (recap.Self[recap_temp.s][effect].CritsEvents or 0) + 1
1434 recap.Self[recap_temp.s][effect].Crits = (recap.Self[recap_temp.s][effect].Crits or 0) + did_crit
1435 recap.Self[recap_temp.s][effect].CritsDmg = (recap.Self[recap_temp.s][effect].CritsDmg or 0) + total
1436 recap.Self[recap_temp.s][effect].CritsMax = math.max(total,recap.Self[recap_temp.s][effect].CritsMax or 0)
1437 end
1438 elseif did_crit==0 then
1439 recap.Combatant[source].Detail[effect].CritsEvents = (recap.Combatant[source].Detail[effect].CritsEvents or 0) + 1
1440 recap.Combatant[source].Detail[effect].Hits = (recap.Combatant[source].Detail[effect].Hits or 0) + 1
1441 recap.Combatant[source].Detail[effect].HitsDmg = (recap.Combatant[source].Detail[effect].HitsDmg or 0) + total
1442 recap.Combatant[source].Detail[effect].HitsMax = math.max(total,recap.Combatant[source].Detail[effect].HitsMax or 0)
1443 if source==recap_temp.Player then
1444 recap.Self[recap_temp.s][effect].CritsEvents = (recap.Self[recap_temp.s][effect].CritsEvents or 0) + 1
1445 recap.Self[recap_temp.s][effect].Hits = (recap.Self[recap_temp.s][effect].Hits or 0) + 1
1446 recap.Self[recap_temp.s][effect].HitsDmg = (recap.Self[recap_temp.s][effect].HitsDmg or 0) + total
1447 recap.Self[recap_temp.s][effect].HitsMax = math.max(total,recap.Self[recap_temp.s][effect].HitsMax or 0)
1448 end
1449 elseif total==0 then
1450 recap.Combatant[source].Detail[effect].Missed = (recap.Combatant[source].Detail[effect].Missed or 0) + 1
1451 if source==recap_temp.Player then
1452 recap.Self[recap_temp.s][effect].Missed = (recap.Self[recap_temp.s][effect].Missed or 0) + 1
1453 end
1454 else
1455 recap.Combatant[source].Detail[effect].Hits = (recap.Combatant[source].Detail[effect].Hits or 0) + 1
1456 recap.Combatant[source].Detail[effect].TicksDmg = (recap.Combatant[source].Detail[effect].TicksDmg or 0) + total
1457 recap.Combatant[source].Detail[effect].TicksMax = math.max(total,recap.Combatant[source].Detail[effect].TicksMax or 0)
1458 if source==recap_temp.Player then
1459 recap.Self[recap_temp.s][effect].Hits = (recap.Self[recap_temp.s][effect].Hits or 0) + 1
1460 recap.Self[recap_temp.s][effect].TicksDmg = (recap.Self[recap_temp.s][effect].TicksDmg or 0) + total
1461 recap.Self[recap_temp.s][effect].TicksMax = math.max(total,recap.Self[recap_temp.s][effect].TicksMax or 0)
1462 end
1463 end
1464 end
1465 end
1466  
1467 function Recap_DeathEvent(arg1)
1468  
1469 local i, victim, spot
1470 local found = false
1471  
1472 if recap.Opt.State.value~="Stopped" then
1473  
1474 for i=1,recap_temp.DeathFilterSize do
1475 found,_,recap_temp.FilterIndex[1] = string.find(arg1,recap_temp.DeathFilter[i].pattern)
1476  
1477 if found then
1478  
1479 victim = recap_temp.FilterIndex[recap_temp.DeathFilter[i].victim]
1480  
1481 -- check for FD
1482 if recap.Combatant[victim] and recap.Combatant[victim].Class=="Hunter" then
1483 if UnitName("player")==victim then
1484 spot = "player"
1485 end
1486 for j=1,4 do
1487 if UnitName("party"..j)==victim then
1488 spot = "party"..j
1489 end
1490 end
1491 for j=1,40 do
1492 if UnitName("raid"..j)==victim then
1493 spot = "raid"..j
1494 end
1495 end
1496 if spot then
1497 for j=1,16 do
1498 if UnitBuff(spot,j)=="Interface\\Icons\\Ability_Rogue_FeignDeath" then
1499 victim = nil
1500 end
1501 end
1502 end
1503 end
1504  
1505 if victim and recap_temp.Last[victim] then
1506 recap_temp.Last[victim].Kills = recap_temp.Last[victim].Kills + 1
1507 end
1508  
1509 if recap.debug then
1510 if not recap.debug_Filter then
1511 recap.debug_Filter = {}
1512 end
1513 if not recap.debug_Filter[i+60] then
1514 recap.debug_Filter[i+60] = { hits=1, total=1, pattern=recap_temp.DeathFilter[i].pattern }
1515 else
1516 recap.debug_Filter[i+60].hits = recap.debug_Filter[i+60].hits + 1
1517 recap.debug_Filter[i+60].total = recap.debug_Filter[i+60].total + 1
1518 end
1519 if recap_temp.Filter[i].watch then
1520 DEFAULT_CHAT_FRAME:AddMessage("["..i.."] \""..recap_temp.DeathFilter[i].pattern.."\" triggered!")
1521 DEFAULT_CHAT_FRAME:AddMessage("victim="..tostring(victim))
1522 end
1523 end
1524  
1525 i = recap_temp.DeathFilterSize+1
1526  
1527 end
1528 end
1529 end
1530 end
1531  
1532 function Recap_HealEvent(arg1)
1533  
1534 local i, source, dest, heal, effect, fullheal
1535 local found = false
1536  
1537 if recap.Opt.State.value~="Stopped" then
1538  
1539 -- strip out period at end of chat line, if one exists
1540 arg1 = string.gsub(arg1,"%.$","")
1541  
1542 for i=1,recap_temp.HealFilterSize do
1543 found,_,recap_temp.FilterIndex[1],recap_temp.FilterIndex[2],recap_temp.FilterIndex[3],recap_temp.FilterIndex[4],recap_temp.FilterIndex[5] = string.find(arg1,recap_temp.HealFilter[i].pattern)
1544  
1545 if found then
1546  
1547 if not recap.Opt.LimitFights.value then
1548 if recap.Opt.IdleFight.value then
1549 recap_temp.IdleTimer = 0
1550 end
1551 if recap.Opt.State.value=="Idle" then
1552 Recap_StartFight()
1553 end
1554 end
1555  
1556 source=recap_temp.FilterIndex[recap_temp.HealFilter[i].source]
1557 dest=recap_temp.FilterIndex[recap_temp.HealFilter[i].dest]
1558 if recap_temp.Local.SelfPronouns[string.lower(dest)] then
1559 dest = recap_temp.Player
1560 end
1561 heal=tonumber(recap_temp.FilterIndex[recap_temp.HealFilter[i].heal])
1562 if recap_temp.HealFilter[i].effect then
1563 effect = recap_temp.FilterIndex[recap_temp.HealFilter[i].effect]
1564 end
1565  
1566 Recap_CreateCombatant(source)
1567  
1568 if recap_temp.Last[dest] and recap_temp.Last[dest].HP then
1569 fullheal = heal
1570 heal = math.min(recap_temp.Last[dest].MaxHP-recap_temp.Last[dest].HP,heal)
1571 recap_temp.Last[dest].HP = recap_temp.Last[dest].HP + heal
1572 if recap.debug and heal~=fullheal then
1573 ChatFrame2:AddMessage("|cff3fbfff"..source.."'s "..effect.." actually healed "..dest.." for "..heal..". ("..fullheal.." reported)")
1574 end
1575 end
1576 recap_temp.Last[source].Heal = recap_temp.Last[source].Heal + heal
1577  
1578 if recap.debug then
1579 if not recap.debug_Filter then
1580 recap.debug_Filter = {}
1581 end
1582 if not recap.debug_Filter[i+75] then
1583 recap.debug_Filter[i+75] = { hits=1, total=heal, pattern=recap_temp.HealFilter[i].pattern }
1584 else
1585 recap.debug_Filter[i+75].hits = recap.debug_Filter[i+75].hits + 1
1586 recap.debug_Filter[i+75].total = recap.debug_Filter[i+75].total + heal
1587 end
1588 if recap_temp.Filter[i].watch then
1589 DEFAULT_CHAT_FRAME:AddMessage("["..i.."] \""..recap_temp.HealFilter[i].pattern.."\" triggered!")
1590 DEFAULT_CHAT_FRAME:AddMessage("source="..tostring(source)..", dest="..tostring(dest)..", heal="..tostring(heal))
1591 end
1592 end
1593  
1594 if not recap.Opt.LightData.value then
1595 Recap_CreateEffect(source,effect,3,heal,recap_temp.HealFilter[i].crit)
1596  
1597 if fullheal and heal~=fullheal and recap.Combatant[source].Detail["3"..effect] then
1598 -- reuse .Missed detail to store overhealing since heals never miss
1599 recap.Combatant[source].Detail["3"..effect].Missed = (recap.Combatant[source].Detail["3"..effect].Missed or 0) + math.max(0,fullheal-heal)
1600 end
1601 end
1602  
1603 i = recap_temp.HealFilterSize+1
1604  
1605 end
1606 end
1607 end
1608 end
1609  
1610 local function Recap_SelfDamageSort(e1,e2)
1611  
1612 local effect1,effect2 = string.sub(e1.EName,1,1),string.sub(e2.EName,1,1)
1613  
1614 if e1 and e2 and ( ((e1.ETotal>e2.ETotal) and (effect1==effect2)) or (effect1<effect2) ) then
1615 return true
1616 else
1617 return false
1618 end
1619 end
1620  
1621 local function Recap_ConstructSelf()
1622  
1623 local idx,i,j = 1
1624 local damage, heal = 0,0
1625  
1626 recap_temp.SelfListSize = 1
1627  
1628 for i in recap.Self[recap_temp.s] do
1629 if not recap_temp.SelfList[idx] then
1630 recap_temp.SelfList[idx] = {}
1631 end
1632 recap_temp.SelfList[idx].EName = i
1633 recap_temp.SelfList[idx].ETotal = (recap.Self[recap_temp.s][i].HitsDmg or 0) + (recap.Self[recap_temp.s][i].TicksDmg or 0) + (recap.Self[recap_temp.s][i].CritsDmg or 0)
1634 recap_temp.SelfList[idx].EHits = (recap.Self[recap_temp.s][i].CritsEvents or 0)-(recap.Self[recap_temp.s][i].Crits or 0)
1635 recap_temp.SelfList[idx].ETicks = (recap.Self[recap_temp.s][i].Hits or 0) - recap_temp.SelfList[idx].EHits
1636 recap_temp.SelfList[idx].ECrits = recap.Self[recap_temp.s][i].Crits or 0
1637 recap_temp.SelfList[idx].EHitsMax = recap.Self[recap_temp.s][i].HitsMax or 0
1638 recap_temp.SelfList[idx].ETicksMax = recap.Self[recap_temp.s][i].TicksMax or 0
1639 recap_temp.SelfList[idx].ECritsMax = recap.Self[recap_temp.s][i].CritsMax or 0
1640 recap_temp.SelfList[idx].EHitsAvg = string.format("%d",((recap_temp.SelfList[idx].EHits>0) and ((recap.Self[recap_temp.s][i].HitsDmg or 0)/recap_temp.SelfList[idx].EHits) or 0))
1641 recap_temp.SelfList[idx].ETicksAvg = string.format("%d",((recap_temp.SelfList[idx].ETicks>0) and ((recap.Self[recap_temp.s][i].TicksDmg or 0)/recap_temp.SelfList[idx].ETicks) or 0))
1642 recap_temp.SelfList[idx].ECritsAvg = string.format("%d",((recap_temp.SelfList[idx].ECrits>0) and ((recap.Self[recap_temp.s][i].CritsDmg or 0)/recap_temp.SelfList[idx].ECrits) or 0))
1643 recap_temp.SelfList[idx].ECritsP = string.format("%.1f%%",((recap.Self[recap_temp.s][i].CritsEvents or 0)>0) and (100*recap_temp.SelfList[idx].ECrits/recap.Self[recap_temp.s][i].CritsEvents) or 0)
1644 recap_temp.SelfList[idx].EMaxAll = math.max( recap_temp.SelfList[idx].EHitsMax, math.max(recap_temp.SelfList[idx].ETicksMax,recap_temp.SelfList[idx].ECritsMax) )
1645 if tonumber(string.sub(i,1,1))<3 then -- damage event
1646 recap_temp.SelfList[idx].EMiss = recap.Self[recap_temp.s][i].Missed or 0
1647 j = recap_temp.SelfList[idx].EHits + recap_temp.SelfList[idx].ECrits + recap_temp.SelfList[idx].EMiss
1648 recap_temp.SelfList[idx].EMissP = string.format("%.1f%%",(j>0) and (100*(recap_temp.SelfList[idx].EMiss/j)) or 0)
1649 damage = damage + recap_temp.SelfList[idx].ETotal
1650 else
1651 recap_temp.SelfList[idx].EMiss = "--"
1652 recap_temp.SelfList[idx].EMissP = "--"
1653 heal = heal + recap_temp.SelfList[idx].ETotal
1654 end
1655  
1656 if recap_temp.SelfList[idx].ETicks==0 then
1657 recap_temp.SelfList[idx].ETicks = "--"
1658 recap_temp.SelfList[idx].ETicksAvg = "--"
1659 recap_temp.SelfList[idx].ETicksMax = "--"
1660 end
1661 if not recap.Self[recap_temp.s][i].CritsEvents then
1662 recap_temp.SelfList[idx].ECrits = "--"
1663 recap_temp.SelfList[idx].ECritsAvg = "--"
1664 recap_temp.SelfList[idx].ECritsMax = "--"
1665 recap_temp.SelfList[idx].ECritsP = "--"
1666 recap_temp.SelfList[idx].EHits = "--"
1667 recap_temp.SelfList[idx].EHitsAvg = "--"
1668 recap_temp.SelfList[idx].EHitsMax = "--"
1669 end
1670  
1671 idx = idx + 1
1672 end
1673  
1674 recap_temp.SelfListSize = idx
1675  
1676 if recap_temp.SelfListSize>1 then
1677 for i=1,recap_temp.SelfListSize-1 do
1678 if string.sub(recap_temp.SelfList[i].EName,1,1)<"3" and damage>0 then
1679 recap_temp.SelfList[i].ETotalP = string.format("%d%%",100*recap_temp.SelfList[i].ETotal/damage)
1680 elseif string.sub(recap_temp.SelfList[i].EName,1,1)>"2" and heal>0 then
1681 recap_temp.SelfList[i].ETotalP = string.format("%d%%",100*recap_temp.SelfList[i].ETotal/heal)
1682 else
1683 recap_temp.SelfList[i].ETotalP = "--"
1684 end
1685 end
1686 end
1687  
1688 table.sort(recap_temp.SelfList,Recap_SelfDamageSort)
1689  
1690 end
1691  
1692 function Recap_ConstructList()
1693  
1694 local i, j, dpsin, dpsout, entry, duration, tempname, over
1695 local maxhit = 0
1696 local dmgin = 0
1697 local dmgout = 0
1698 local kills = 0
1699 local heal = 0
1700 local allover = 0
1701  
1702  
1703 if recap.Opt.SelfView.value then
1704 Recap_ConstructSelf()
1705 end
1706  
1707 recap_temp.ListSize = 1
1708 if recap_temp.Selected~=0 then
1709 tempname = recap_temp.List[recap_temp.Selected].Name
1710 end
1711  
1712 if recap.Opt.View.value=="Last" then
1713 duration = recap[recap_temp.p].LastDuration
1714 else
1715 duration = recap[recap_temp.p].TotalDuration
1716 end
1717  
1718 for i in recap.Combatant do
1719 if not recap_temp.List[recap_temp.ListSize] then
1720 recap_temp.List[recap_temp.ListSize] = {}
1721 end
1722 entry = false
1723 if (recap.Combatant[i].LastDmgIn==0 and recap.Combatant[i].LastDmgOut==0 and
1724 recap.Combatant[i].TotalDmgOut==0 and recap.Combatant[i].TotalDmgIn==0) or
1725 (recap.Opt.HideFoe.value and not recap.Combatant[i].Friend) or
1726 (recap.Opt.HideYardTrash.value and (not recap.Combatant[i].Friend and recap.Combatant[i].TotalKills~=1)) or
1727 (recap.Combatant[i].Ignore) then
1728 entry = false -- strip out unwanted combatants
1729 elseif recap.Opt.View.value=="Last" and recap.Combatant[i].WasInLast then
1730 if not recap.Opt.HideZero.value or recap.Combatant[i].LastTime>recap_temp.MinTime then
1731 recap_temp.List[recap_temp.ListSize].Name = i
1732 recap_temp.List[recap_temp.ListSize].Time = recap.Combatant[i].LastTime
1733 recap_temp.List[recap_temp.ListSize].MaxHit = recap.Combatant[i].LastMaxHit
1734 recap_temp.List[recap_temp.ListSize].DmgIn = recap.Combatant[i].LastDmgIn
1735 recap_temp.List[recap_temp.ListSize].DmgOut = recap.Combatant[i].LastDmgOut
1736 recap_temp.List[recap_temp.ListSize].DPS = recap.Combatant[i].LastDPS
1737 recap_temp.List[recap_temp.ListSize].DPSvsAll = duration>recap_temp.MinTime and recap.Combatant[i].LastDmgOut/duration or 0
1738 recap_temp.List[recap_temp.ListSize].Kills = recap.Combatant[i].LastKills
1739 recap_temp.List[recap_temp.ListSize].Heal = recap.Combatant[i].LastHeal
1740 entry = true
1741 end
1742 elseif recap.Opt.View.value=="All" then
1743 if not recap.Opt.HideZero.value or recap.Combatant[i].TotalTime>recap_temp.MinTime then
1744 recap_temp.List[recap_temp.ListSize].Name = i
1745 recap_temp.List[recap_temp.ListSize].Time = recap.Combatant[i].TotalTime
1746 recap_temp.List[recap_temp.ListSize].MaxHit = recap.Combatant[i].TotalMaxHit
1747 recap_temp.List[recap_temp.ListSize].DmgIn = recap.Combatant[i].TotalDmgIn
1748 recap_temp.List[recap_temp.ListSize].DmgOut = recap.Combatant[i].TotalDmgOut
1749 recap_temp.List[recap_temp.ListSize].DPS = recap.Combatant[i].TotalDPS
1750 recap_temp.List[recap_temp.ListSize].DPSvsAll = duration>recap_temp.MinTime and recap.Combatant[i].TotalDmgOut/duration or 0
1751 recap_temp.List[recap_temp.ListSize].Kills = recap.Combatant[i].TotalKills
1752 recap_temp.List[recap_temp.ListSize].Heal = recap.Combatant[i].TotalHeal
1753 entry = true
1754 end
1755 end
1756 if entry then
1757 recap_temp.List[recap_temp.ListSize].Over = 0 -- overhealing
1758 if recap.Combatant[recap_temp.List[recap_temp.ListSize].Name].Friend then
1759 if recap_temp.List[recap_temp.ListSize].MaxHit > maxhit then
1760 maxhit = recap_temp.List[recap_temp.ListSize].MaxHit
1761 end
1762 dmgin = dmgin + recap_temp.List[recap_temp.ListSize].DmgIn
1763 dmgout = dmgout + recap_temp.List[recap_temp.ListSize].DmgOut
1764 kills = kills + recap_temp.List[recap_temp.ListSize].Kills
1765 heal = heal + recap_temp.List[recap_temp.ListSize].Heal
1766 if (recap_temp.List[recap_temp.ListSize].Heal>0) and not recap.Opt.LightData.value then
1767 over = 0
1768 for j in recap.Combatant[i].Detail do
1769 if string.sub(j,1,1)=="3" then -- a heal
1770 over = over + (recap.Combatant[i].Detail[j].Missed or 0)
1771 end
1772 end
1773 recap_temp.List[recap_temp.ListSize].Over = math.floor(((100*over)/(over+recap.Combatant[i].TotalHeal))+.5)
1774 allover = allover + over
1775 end
1776 end
1777 recap_temp.ListSize = recap_temp.ListSize + 1
1778 end
1779 end
1780  
1781 if not recap_temp.List[recap_temp.ListSize] then
1782 recap_temp.List[recap_temp.ListSize] = {}
1783 end
1784 -- the final entry is the totals
1785 recap_temp.List[recap_temp.ListSize].Name = "Totals"
1786 recap_temp.List[recap_temp.ListSize].Time = duration
1787 RecapTotals_Time:SetText(Recap_FormatTime(duration))
1788 recap_temp.List[recap_temp.ListSize].MaxHit = maxhit
1789 RecapTotals_MaxHit:SetText(maxhit)
1790 recap_temp.List[recap_temp.ListSize].DmgIn = dmgin
1791 RecapTotals_DmgIn:SetText(dmgin)
1792 recap_temp.List[recap_temp.ListSize].DmgOut = dmgout
1793 RecapTotals_DmgOut:SetText(dmgout)
1794 recap_temp.List[recap_temp.ListSize].Kills = kills
1795 RecapTotals_Kills:SetText(kills)
1796 recap_temp.List[recap_temp.ListSize].Heal = heal
1797 RecapTotals_Heal:SetText(heal)
1798 recap_temp.List[recap_temp.ListSize].Over = recap.Opt.View.value=="All" and ((100*allover)/(allover+heal)) or 0
1799 RecapTotals_Over:SetText(string.format("%d%%",recap_temp.List[recap_temp.ListSize].Over))
1800 if duration > recap_temp.MinTime then
1801 recap_temp.List[recap_temp.ListSize].DPSIn = dmgin/duration
1802 recap_temp.List[recap_temp.ListSize].DPSOut = dmgout/duration
1803 else
1804 recap_temp.List[recap_temp.ListSize].DPSIn = 0
1805 recap_temp.List[recap_temp.ListSize].DPSOut = 0
1806 end
1807 RecapTotals_DPS:SetText(string.format("%.1f",recap_temp.List[recap_temp.ListSize].DPSOut))
1808 RecapTotals_DPSvsAll:SetText(string.format("%.1f",recap_temp.List[recap_temp.ListSize].DPSOut))
1809 RecapTotals_DPSIn:SetText(string.format("%.1f",recap_temp.List[recap_temp.ListSize].DPSIn))
1810  
1811 RecapMinDPSIn_Text:SetText(string.format("%.1f",recap_temp.List[recap_temp.ListSize].DPSIn))
1812 RecapMinDPSOut_Text:SetText(string.format("%.1f",recap_temp.List[recap_temp.ListSize].DPSOut))
1813 if recap.Combatant[recap_temp.Player] and recap.Opt.View.value=="Last" then
1814 i = recap.Combatant[recap_temp.Player].LastDPS
1815 if UnitName("pet") and UnitName("pet")~=UNKNOWNOBJECT and recap.Combatant[UnitName("pet")] then
1816 i = i + recap.Combatant[UnitName("pet")].LastDPS
1817 end
1818 RecapMinYourDPS_Text:SetText(string.format("%.1f",i))
1819 elseif recap.Combatant[recap_temp.Player] and recap.Opt.View.value=="All" then
1820 i = recap.Combatant[recap_temp.Player].TotalDPS
1821 if UnitName("pet") and UnitName("pet")~=UNKNOWNOBJECT and recap.Combatant[UnitName("pet")] then
1822 i = i + recap.Combatant[UnitName("pet")].TotalDPS
1823 end
1824 RecapMinYourDPS_Text:SetText(string.format("%.1f",i))
1825 else
1826 RecapMinYourDPS_Text:SetText("n/a")
1827 end
1828  
1829 -- calculate percentages
1830 for i=1,recap_temp.ListSize-1 do
1831 recap_temp.List[i].HealP = 0
1832 recap_temp.List[i].DmgInP = 0
1833 recap_temp.List[i].DmgOutP = 0
1834 if recap.Combatant[recap_temp.List[i].Name].Friend then
1835 if recap_temp.List[recap_temp.ListSize].Heal>0 then
1836 recap_temp.List[i].HealP = math.floor(.5+100*recap_temp.List[i].Heal/recap_temp.List[recap_temp.ListSize].Heal)
1837 end
1838 if recap_temp.List[recap_temp.ListSize].DmgIn>0 then
1839 recap_temp.List[i].DmgInP = math.floor(.5+100*recap_temp.List[i].DmgIn/recap_temp.List[recap_temp.ListSize].DmgIn)
1840 end
1841 if recap_temp.List[recap_temp.ListSize].DmgOut>0 then
1842 recap_temp.List[i].DmgOutP = math.floor(.5+100*recap_temp.List[i].DmgOut/recap_temp.List[recap_temp.ListSize].DmgOut)
1843 end
1844 end
1845 end
1846  
1847 Recap_SortList()
1848  
1849 if tempname then -- follow name to pre-sort selected
1850 recap_temp.Selected = Recap_GetSelectedByName(tempname)
1851 if recap_temp.Selected~=0 then
1852 RecapPanel_Show(tempname)
1853 else
1854 RecapPanel_Hide()
1855 end
1856 end
1857  
1858 RecapScrollBar_Update()
1859 Recap_UpdatePlugins()
1860  
1861 end
1862  
1863 function Recap_DefineGauges()
1864  
1865 local i
1866  
1867 recap_temp.GaugeMax = 0
1868  
1869 if recap_temp.ListSize>1 then
1870  
1871 recap_temp.GaugeBy = string.gsub(recap.Opt.SortBy.value,"P$","")
1872 recap_temp.GaugeBy = recap_temp.GaugeBy=="DPSvsAll" and "DmgOut" or recap_temp.GaugeBy
1873 if not gaugecolor[recap_temp.GaugeBy] then
1874 recap_temp.GaugeBy = nil
1875 else
1876 for i=1,recap_temp.ListSize-1 do
1877 recap_temp.GaugeMax = math.max(recap.Combatant[recap_temp.List[i].Name].Friend and recap_temp.List[i][recap_temp.GaugeBy] or 0,recap_temp.GaugeMax)
1878 end
1879 for i=1,15 do
1880 getglobal("RecapList"..i.."_Gauge"):SetVertexColor(gaugecolor[recap_temp.GaugeBy].r,gaugecolor[recap_temp.GaugeBy].g,gaugecolor[recap_temp.GaugeBy].b)
1881 end
1882 end
1883 end
1884 end
1885  
1886  
1887 function Recap_GetSelectedByName(arg1)
1888  
1889 local sel,i = 0
1890  
1891 if arg1 and recap_temp.ListSize>1 then
1892 for i=1,recap_temp.ListSize-1 do
1893 if recap_temp.List[i].Name==arg1 then
1894 sel = i
1895 end
1896 end
1897 end
1898  
1899 return sel
1900 end
1901  
1902 --[[ Sorting functions ]]
1903  
1904 -- initial sort by field done with table.sort for speed, then
1905 -- friends shifted to top with an insertion sort for "stable" list
1906 function Recap_SortList()
1907  
1908 local temp,tempname
1909  
1910 if recap_temp.Selected~=0 then
1911 tempname = recap_temp.List[recap_temp.Selected].Name
1912 end
1913  
1914 temp = recap_temp.List[recap_temp.ListSize]
1915 recap_temp.List[recap_temp.ListSize] = nil
1916  
1917 if recap.Opt.SortDir.value then
1918 table.sort(recap_temp.List,function(e1,e2) if e1 and e2 and ( e1[recap.Opt.SortBy.value] < e2[recap.Opt.SortBy.value] ) then return true else return false end end)
1919 else
1920 table.sort(recap_temp.List,function(e1,e2) if e1 and e2 and ( e1[recap.Opt.SortBy.value] > e2[recap.Opt.SortBy.value] ) then return true else return false end end)
1921 end
1922 Recap_SortFriends()
1923  
1924 recap_temp.List[recap_temp.ListSize] = temp
1925  
1926 Recap_DefineGauges()
1927 recap_temp.Selected = Recap_GetSelectedByName(tempname)
1928  
1929 end
1930  
1931 function Recap_SortDown(e1,e2)
1932  
1933 if e1 and e2 and ( e1[recap.Opt.SortBy.value] < e2[recap.Opt.SortBy.value] ) then
1934 return true
1935 else
1936 return false
1937 end
1938 end
1939  
1940 function Recap_SortUp(e1,e2)
1941  
1942 if e1 and e2 and ( e1[recap.Opt.SortBy.value] > e2[recap.Opt.SortBy.value] ) then
1943 return true
1944 else
1945 return false
1946 end
1947 end
1948  
1949 -- perform stable insertion sort on the list
1950 function Recap_SortFriends()
1951  
1952 local i,j
1953 local changed = true
1954 local temp = {}
1955  
1956 if recap_temp.ListSize>2 then
1957  
1958 for i=2,(recap_temp.ListSize-1) do
1959 temp = recap_temp.List[i]
1960 j=i
1961 while (j>1) and (not recap.Combatant[recap_temp.List[j-1].Name].Friend and recap.Combatant[temp.Name].Friend) do
1962 recap_temp.List[j] = recap_temp.List[j-1]
1963 j = j - 1
1964 end
1965 recap_temp.List[j] = temp
1966 end
1967  
1968 end
1969 end
1970  
1971 --[[ Window movement functions ]]
1972  
1973 function Recap_OnMouseDown(arg1)
1974  
1975 if recap_temp.Loaded and arg1=="LeftButton" and not recap.Opt.Pinned.value then
1976 RecapFrame:StartMoving()
1977 end
1978 end
1979  
1980 function Recap_OnMouseUp(arg1)
1981  
1982 if recap_temp.Loaded and arg1=="LeftButton" and not recap.Opt.Pinned.value then
1983 RecapFrame:StopMovingOrSizing()
1984 Recap_CheckWindowBounds()
1985 elseif arg1=="RightButton" and recap.Opt.Minimized.value then
1986 RecapCreateMenu(recap_temp.MinMenu)
1987 end
1988 end
1989  
1990 -- repositions RecapFrame if any part of it goes off the screen
1991 function Recap_CheckWindowBounds()
1992  
1993 local x1, y1, x2, y2, cx, cy
1994 local needs_moved = false
1995  
1996 if recap_temp.Loaded and RecapFrame then
1997  
1998 x1 = RecapFrame:GetLeft()
1999 y1 = RecapFrame:GetTop()
2000 cx = RecapFrame:GetWidth()
2001 cy = RecapFrame:GetHeight()
2002  
2003 if x1 and y1 and cx and cy then
2004  
2005 x2 = RecapFrame:GetRight()
2006 y2 = RecapFrame:GetBottom()
2007 uix2 = UIParent:GetRight()
2008 uix1 = UIParent:GetLeft()
2009 uiy1 = UIParent:GetTop()
2010 uiy2 = UIParent:GetBottom()
2011  
2012 if x2 and uix2 and x2 > uix2 then
2013 x1 = x1 + uix2 - x2
2014 needs_moved = true
2015 elseif uix1 and uix1 > x1 then
2016 x1 = x1 + uix1 - x1
2017 needs_moved = true
2018 end
2019  
2020 if y1 and y1 > uiy1 then
2021 y1 = y1 + uiy1 - y1
2022 needs_moved = true
2023 elseif uiy2 and uiy2 > y2 then
2024 y1 = y1 + uiy2 - y2
2025 needs_moved = true
2026 end
2027  
2028 if needs_moved then
2029 RecapFrame:ClearAllPoints()
2030 RecapFrame:SetPoint("TOPLEFT","UIParent","BOTTOMLEFT",x1,y1)
2031 end
2032  
2033 recap[recap_temp.p].WindowTop = RecapFrame:GetTop()
2034 recap[recap_temp.p].WindowLeft = RecapFrame:GetLeft()
2035 recap[recap_temp.p].WindowHeight = RecapFrame:GetHeight()
2036 recap[recap_temp.p].WindowWidth = RecapFrame:GetWidth()
2037  
2038 end
2039  
2040 end
2041 end
2042  
2043 --[[ Dialog control functions ]]
2044  
2045 function Recap_OnClick(arg1)
2046  
2047 if not recap_temp.Loaded then
2048 return
2049 end
2050  
2051 local fight_count = 0
2052 local total_fight_count = 0
2053 local filen = RecapSetEditBox:GetText()
2054 local set_friend, set_dmgin, set_dmgout, set_maxhit, set_kills, set_heal, set_time
2055  
2056 PlaySound("GAMEGENERICBUTTONPRESS")
2057  
2058 if arg1=="Close" then
2059 RecapFrame_Hide()
2060 elseif arg1=="Minimize" then
2061  
2062 if recap.Opt.Minimized.value then
2063 Recap_Maximize()
2064 else
2065 Recap_Minimize()
2066 end
2067 RecapFrame:SetAlpha(1)
2068 recap_temp.FadeTimer = -1
2069 Recap_SetButtons()
2070 Recap_OnTooltip("Minimize")
2071 elseif arg1=="Pin" then
2072 recap.Opt.Pinned.value = not recap.Opt.Pinned.value
2073 Recap_SetButtons()
2074 Recap_OnTooltip("Pin")
2075 elseif arg1=="Pause" then
2076 if recap.Opt.Paused.value then
2077 recap.Opt.Paused.value = false
2078 Recap_SetState("Idle")
2079 else
2080 recap.Opt.Paused.value = true
2081 Recap_EndFight()
2082 Recap_SetState("Stopped")
2083 end
2084 Recap_SetButtons()
2085 Recap_OnTooltip("Pause")
2086 elseif arg1=="ShowAll" then
2087 if recap.Opt.SelfView.value then
2088 recap.Opt.SelfView.value = false
2089 if not recap.Opt.Minimized.value then
2090 Recap_SetColumns()
2091 end
2092 end
2093 if recap.Opt.View.value=="Last" then
2094 Recap_SetView("All")
2095 else
2096 Recap_SetView("Last")
2097 end
2098 Recap_OnTooltip("ShowAll")
2099 elseif arg1=="Options" then
2100 if RecapOptFrame:IsShown() then
2101 RecapOptFrame:Hide()
2102 else
2103 RecapOptFrame:Show()
2104 end
2105 elseif arg1=="Reset" then
2106  
2107 if recap.Opt.SelfView.value then
2108 recap.Self[recap_temp.s] = {}
2109 Recap_SetView()
2110 elseif recap.Opt.View.value=="All" then
2111 -- wipe everything --
2112 Recap_ResetAllCombatants()
2113 Recap_SetView()
2114 Recap_MakeFriends()
2115 elseif recap.Opt.View.value=="Last" then
2116 -- remove just the last fight --
2117 for i in recap.Combatant do
2118 if recap.Combatant[i].WasInLast then
2119 Recap_ResetLastFight(i)
2120 end
2121 end
2122 recap[recap_temp.p].TotalDuration = recap[recap_temp.p].TotalDuration - recap[recap_temp.p].LastDuration
2123 recap[recap_temp.p].LastDuration = 0
2124 Recap_SetView()
2125 end
2126  
2127 elseif arg1=="SaveSet" then
2128 RecapSetEditBox:ClearFocus()
2129 if filen and filen~="" then
2130 filen = string.gsub(filen,"\"","'") -- convert "s to 's
2131 filen = string.gsub(filen,"%[","(") -- convert [s to (s
2132 filen = string.gsub(filen,"%]",")") -- convert ]s to )s
2133 end
2134 RecapSetEditBox:SetText("")
2135 Recap_SaveCombatants(filen,recap.Opt.ReplaceSet.value)
2136 Recap_BuildFightSets()
2137 recap_temp.FightSetSelected = 0
2138 RecapFightSetsScrollBar_Update()
2139  
2140 elseif arg1=="LoadSet" then
2141 RecapSetEditBox:SetText("")
2142 RecapSetEditBox:ClearFocus()
2143 Recap_LoadCombatants(filen,recap.Opt.ReplaceSet.value)
2144 Recap_MakeFriends()
2145 Recap_SetView("All")
2146  
2147 elseif arg1=="DeleteSet" then
2148 RecapSetEditBox:SetText("")
2149 RecapSetEditBox:ClearFocus()
2150 recap_set[filen] = nil
2151 Recap_BuildFightSets()
2152  
2153 elseif arg1=="SelfView" then
2154 recap.Opt.SelfView.value = not recap.Opt.SelfView.value
2155 RecapPanel_Hide(1)
2156 Recap_SetColumns()
2157 Recap_OnTooltip("SelfView")
2158 end
2159 end
2160  
2161 -- removes combatant i from last fight
2162 function Recap_ResetLastFight(i)
2163 recap.Combatant[i].TotalTime = recap.Combatant[i].TotalTime - recap.Combatant[i].LastTime
2164 recap.Combatant[i].TotalDmgIn = recap.Combatant[i].TotalDmgIn - recap.Combatant[i].LastDmgIn
2165 recap.Combatant[i].TotalDmgOut = recap.Combatant[i].TotalDmgOut - recap.Combatant[i].LastDmgOut
2166 recap.Combatant[i].TotalHeal = recap.Combatant[i].TotalHeal - recap.Combatant[i].LastHeal
2167 recap.Combatant[i].TotalKills = recap.Combatant[i].TotalKills - recap.Combatant[i].LastKills
2168 if recap.Combatant[i].TotalTime> recap_temp.MinTime then
2169 recap.Combatant[i].TotalDPS = recap.Combatant[i].TotalDmgOut/recap.Combatant[i].TotalTime
2170 else
2171 recap.Combatant[i].TotalDPS = 0
2172 end
2173 recap.Combatant[i].WasInLast = false
2174 recap.Combatant[i].LastTime = 0
2175 recap.Combatant[i].LastDmgIn = 0
2176 recap.Combatant[i].LastDmgOut = 0
2177 recap.Combatant[i].LastDPS = 0
2178 recap.Combatant[i].LastMaxHit = 0
2179 recap.Combatant[i].LastKills = 0
2180 recap.Combatant[i].LastHeal = 0
2181 end
2182  
2183 function RecapHeader_OnEnter()
2184  
2185 local msg=string.gsub(this:GetName(),"RecapHeader_","Header")
2186 Recap_OnTooltip(msg)
2187 end
2188  
2189 function RecapHeader_OnMouseUp(arg1)
2190  
2191 if arg1=="RightButton" then
2192 RecapCreateMenu(recap_temp.ColumnMenu)
2193 end
2194 end
2195  
2196 -- sort column, toggle dir for new headers, name=ascending, rest=descending
2197 function RecapHeader_OnClick()
2198  
2199 local text=""
2200 local channel = "" -- "Guild" "Say" etc or "Channel"
2201 local chatnumber = 0 -- if channel is "Channel", this is the channel numbers
2202 local arg1= string.gsub(this:GetName(),"RecapHeader_","")
2203  
2204 if not IsShiftKeyDown() then
2205 if recap.Opt.SortBy.value==string.gsub(arg1,"P$","") then
2206 recap.Opt.SortDir.value = not recap.Opt.SortDir.value
2207 else
2208 recap.Opt.SortBy.value = string.gsub(arg1,"P$","")
2209  
2210 if arg1=="Name" then
2211 recap.Opt.SortDir.value = true
2212 else
2213 recap.Opt.SortDir.value = false
2214 end
2215 end
2216 Recap_SortList()
2217 RecapScrollBar_Update()
2218 elseif ChatFrameEditBox:IsVisible() and recap_temp.ListSize>1 and arg1~="Name" then
2219  
2220 recap.Opt.SortBy.value = arg1
2221 recap.Opt.SortDir.value = false
2222 Recap_SortList()
2223 RecapScrollBar_Update()
2224  
2225 if recap.Opt.SpamRows.value then
2226  
2227 channel = ChatFrameEditBox.chatType
2228 chatnumber = nil
2229  
2230 if channel=="WHISPER" then
2231 chatnumber = ChatFrameEditBox.tellTarget
2232 elseif channel=="CHANNEL" then
2233 chatnumber = ChatFrameEditBox.channelTarget
2234 end
2235  
2236 Recap_PostSpamRows(arg1,channel,chatnumber)
2237  
2238 else
2239 Recap_InsertChat(Recap_PostSpamLine(arg1))
2240 end
2241  
2242 elseif not ChatFrameEditBox:IsVisible() then
2243 DEFAULT_CHAT_FRAME:AddMessage(recap_temp.Local.RankUsage)
2244 end
2245  
2246 end
2247  
2248 function Recap_List_OnClick(arg1)
2249  
2250 local id, index
2251 local text = ""
2252  
2253 id = this:GetID()
2254 index = id + FauxScrollFrame_GetOffset(RecapScrollBar)
2255  
2256 if index<recap_temp.ListSize then
2257 recap_temp.DetailSelected = 0
2258 if recap_temp.Selected==index and arg1=="LeftButton" then
2259 recap_temp.Selected = 0
2260 getglobal("RecapList"..id):UnlockHighlight()
2261 RecapPanel_Hide()
2262 else
2263 recap_temp.Selected = index
2264 RecapScrollBar_Update()
2265 RecapPanel_Show(recap_temp.List[index].Name)
2266 end
2267 end
2268  
2269 if arg1=="RightButton" and index<recap_temp.ListSize and IsShiftKeyDown() and ChatFrameEditBox:IsVisible() then
2270 ChatFrameEditBox:Insert(recap_temp.List[index].Name.." "..getglobal("RecapList"..id.."_DPS"):GetText().." DPS ")
2271 elseif arg1=="LeftButton" and index<recap_temp.ListSize and IsShiftKeyDown() and ChatFrameEditBox:IsVisible() then
2272 ChatFrameEditBox:Insert(string.format(recap_temp.Local.VerboseLinkStart,
2273 recap_temp.List[index].Name,
2274 getglobal("RecapList"..id.."_DmgIn"):GetText(),
2275 getglobal("RecapList"..id.."_DmgOut"):GetText(),
2276 getglobal("RecapList"..id.."_Time"):GetText(),
2277 getglobal("RecapList"..id.."_DPS"):GetText(),
2278 getglobal("RecapList"..id.."_MaxHit"):GetText() ).." for "..
2279 recap_temp.Local.LastAll[recap.Opt.View.value])
2280 elseif arg1=="RightButton" and index<recap_temp.ListSize and not IsShiftKeyDown() then
2281 if recap.Combatant[recap_temp.List[index].Name].Friend then
2282 RecapCreateMenu(recap_temp.DropMenu,1)
2283 else
2284 RecapCreateMenu(recap_temp.AddMenu,1)
2285 end
2286 end
2287 end
2288  
2289 --[[ Tooltip functions ]]
2290  
2291 function Recap_Tooltip(arg1,arg2)
2292  
2293 if recap_temp.Loaded and recap.Opt.ShowTooltips.value then
2294 if not recap.Opt.TooltipFollow.value then
2295 GameTooltip_SetDefaultAnchor(GameTooltip,this)
2296 else
2297 GameTooltip:SetOwner(this,Recap_TooltipAnchor())
2298 end
2299 GameTooltip:SetText(arg1)
2300 GameTooltip:AddLine(arg2, .75, .75, .75, 1)
2301 GameTooltip:Show()
2302 end
2303 end
2304  
2305 -- returns line1,line2 of a tooltip for arg1 in OptList (for generic static tooltips)
2306 function Recap_GetTooltip(arg1)
2307  
2308 local i
2309  
2310 if arg1 then
2311 for i in recap_temp.OptList do
2312 if recap_temp.OptList[i][1]==arg1 then
2313 return recap_temp.OptList[i][2],recap_temp.OptList[i][3]
2314 end
2315 end
2316 end
2317 end
2318  
2319 -- arg1=tooltip index, arg2=optional addition to header
2320 function Recap_OnTooltip(arg1,arg2)
2321  
2322 local line1, line2
2323  
2324 if arg1=="Status" then
2325 Recap_Tooltip("Recap Status: "..recap.Opt.State.value,recap_temp.Local.StatusTooltip)
2326 elseif arg1=="Close" then
2327 if recap.Opt.State.value=="Stopped" then
2328 Recap_OnTooltip("ExitRecap")
2329 else
2330 Recap_OnTooltip("HideWindow")
2331 end
2332 elseif arg1=="Minimize" then
2333 if recap.Opt.Minimized.value then
2334 Recap_OnTooltip("ExpandWindow")
2335 else
2336 Recap_OnTooltip("MinimizeWindow")
2337 end
2338 elseif arg1=="Pin" then
2339 if recap.Opt.Pinned.value then
2340 Recap_OnTooltip("UnPinWindow")
2341 else
2342 Recap_OnTooltip("PinWindow")
2343 end
2344 elseif arg1=="Pause" then
2345 if recap.Opt.State.value=="Stopped" then
2346 Recap_OnTooltip("Resume")
2347 else
2348 Recap_OnTooltip("PauseMonitoring")
2349 end
2350 elseif arg1=="ShowAll" then
2351 if recap.Opt.View.value=="Last" then
2352 Recap_OnTooltip("ShowAllFights")
2353 else
2354 Recap_OnTooltip("ShowLastFight")
2355 end
2356 elseif arg1=="HeaderName" then
2357 if recap.Opt.View.value=="Last" then
2358 Recap_OnTooltip("CombatLast")
2359 else
2360 Recap_OnTooltip("CombatAll")
2361 end
2362 elseif arg1=="Reset" then
2363 if recap.Opt.SelfView.value then
2364 Recap_OnTooltip("ResetSelfView")
2365 elseif recap.Opt.View.value=="Last" then
2366 Recap_OnTooltip("ResetLastFight")
2367 else
2368 Recap_OnTooltip("ResetAllTotals")
2369 end
2370 elseif arg1=="SelfView" then
2371 if recap.Opt.SelfView.value then
2372 Recap_OnTooltip("HideSelfView")
2373 else
2374 Recap_OnTooltip("ShowSelfView")
2375 end
2376 else
2377 line1,line2 = Recap_GetTooltip(arg1)
2378 if line1 and line2 then
2379 if arg2 then
2380 Recap_Tooltip(line1..": "..arg2,line2)
2381 else
2382 Recap_Tooltip(line1, line2)
2383 end
2384 end
2385  
2386 end
2387 end
2388  
2389 function Recap_List_OnEnter()
2390  
2391 local index, id
2392  
2393 id = this:GetID()
2394 index = id + FauxScrollFrame_GetOffset(RecapScrollBar)
2395  
2396 if getglobal("RecapList"..id.."_Name"):GetStringWidth()>110 then
2397 Recap_Tooltip(recap_temp.List[index].Name)
2398 end
2399  
2400 if (index<recap_temp.ListSize) and recap_temp.Selected==0 then
2401 RecapPanel_Show(recap_temp.List[index].Name)
2402 end
2403 end
2404  
2405 function Recap_Totals_OnEnter()
2406  
2407 local r = recap_temp.ColorWhite.r
2408 local g = recap_temp.ColorWhite.g
2409 local b = recap_temp.ColorWhite.b
2410 local other_kills = 0
2411  
2412 if recap.Opt.ShowTooltips.value then
2413  
2414 if recap.Opt.TooltipFollow.value then
2415 GameTooltip:SetOwner(this,Recap_TooltipAnchor())
2416 else
2417 GameTooltip_SetDefaultAnchor(GameTooltip,this)
2418 end
2419  
2420 GameTooltip:AddLine("Totals for "..recap_temp.Local.LastAll[recap.Opt.View.value])
2421  
2422 if recap_temp.ListSize>1 then
2423  
2424 for i=1,(recap_temp.ListSize-1) do
2425 if not recap.Combatant[recap_temp.List[i].Name].Friend then
2426 other_kills = other_kills + recap_temp.List[i].Kills
2427 end
2428 end
2429 GameTooltip:AddDoubleLine("Combatants:",recap_temp.ListSize-1,r,g,b,r,g,b)
2430 GameTooltip:AddDoubleLine("Time Fighting:",Recap_FormatTime(recap_temp.List[recap_temp.ListSize].Time),r,g,b,r,g,b)
2431 GameTooltip:AddDoubleLine("Max Hit:",recap_temp.List[recap_temp.ListSize].MaxHit,r,g,b,r,g,b)
2432 GameTooltip:AddDoubleLine("Deaths:",recap_temp.List[recap_temp.ListSize].Kills,r,g,b,r,g,b)
2433 GameTooltip:AddDoubleLine("Kills:",other_kills,r,g,b,r,g,b)
2434 GameTooltip:AddDoubleLine("Heals:",recap_temp.List[recap_temp.ListSize].Heal,r,g,b,r,g,b)
2435 GameTooltip:AddDoubleLine("Damage In:",recap_temp.List[recap_temp.ListSize].DmgIn,recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b,recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b)
2436 GameTooltip:AddDoubleLine("DPS In:",string.format("%.1f",recap_temp.List[recap_temp.ListSize].DPSIn),recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b,recap_temp.ColorDmgIn.r,recap_temp.ColorDmgIn.g,recap_temp.ColorDmgIn.b)
2437 GameTooltip:AddDoubleLine("Damage Out:",recap_temp.List[recap_temp.ListSize].DmgOut,recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b,recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
2438 GameTooltip:AddDoubleLine("DPS Out:",string.format("%.1f",recap_temp.List[recap_temp.ListSize].DPSOut),recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b,recap_temp.ColorDmgOut.r,recap_temp.ColorDmgOut.g,recap_temp.ColorDmgOut.b)
2439 else
2440 GameTooltip:AddLine("Combatants: none",r,g,b)
2441 end
2442  
2443 GameTooltip:Show()
2444 end
2445 end
2446  
2447 function Recap_TooltipAnchor()
2448  
2449 local anchor = "ANCHOR_LEFT"
2450  
2451 if GetCursorPosition("UIParent")<(UIParent:GetWidth()/2) then
2452 anchor = "ANCHOR_RIGHT"
2453 end
2454 return anchor
2455 end
2456  
2457 --[[ Plug-in functions ]]
2458  
2459 function Recap_GetIB_Tooltip()
2460 return recap_temp.Local.LastAll[recap.Opt.View.value]..":\nYour DPS: "..RecapMinYourDPS_Text:GetText().."\nMax hit: "..RecapTotals_MaxHit:GetText().."\nTotal DPS Out: "..RecapTotals_DPS:GetText().."\nTotal DPS In: "..RecapTotals_DPSIn:GetText()
2461 end
2462  
2463 function Recap_UpdatePlugins()
2464  
2465 local yourdps = RecapMinYourDPS_Text:GetText()
2466 local dpsin = RecapMinDPSIn_Text:GetText()
2467 local dpsout = RecapMinDPSOut_Text:GetText()
2468  
2469 if IB_Recap_Update then
2470 IB_Recap_Update("DPS: "..yourdps)
2471 end
2472  
2473 if TitanPanelRecap_Update then
2474 TitanPanelRecap_Update(recap.Opt.State.value,yourdps,dpsin,dpsout)
2475 end
2476 end
2477  
2478 --[[ Misc functions ]]
2479  
2480 -- if this is a pet, pass owner's name to ownedby
2481 function Recap_AddFriend(arg1,ownedby)
2482  
2483 if arg1 and arg~=UNKNOWNOBJECT and recap.Combatant[arg1] then
2484 recap.Combatant[arg1].Friend = true
2485 if recap.Combatant[arg1] and ownedby then
2486 -- pet could potentially do damage without owner, add owner if so
2487 if not recap.Combatant[ownedby] then
2488 Recap_CreateBlankCombatant(ownedby)
2489 recap.Combatant[ownedby].Friend = true
2490 end
2491 if not recap_temp.Last[ownedby] then
2492 recap_temp.Last[ownedby] = { Start = 0, End = 0, DmgIn = 0, DmgOut = 0, MaxHit = 0, Kills = 0, Heal = 0 }
2493 end
2494 recap.Combatant[arg1].OwnedBy = ownedby
2495 recap.Combatant[ownedby].OwnsPet = arg1
2496 end
2497 end
2498 end
2499  
2500 function Recap_MakeFriends()
2501  
2502 local i,item,u
2503  
2504 Recap_GetUnitInfo("player")
2505 Recap_AddFriend(recap_temp.Player)
2506 if UnitExists("pet") then
2507 Recap_GetUnitInfo("pet")
2508 Recap_AddFriend(UnitName("pet"),UnitName("player"))
2509 end
2510 for i=1,4 do
2511 if UnitExists("party"..i) then
2512 Recap_GetUnitInfo("party"..i)
2513 Recap_AddFriend(UnitName("party"..i))
2514 if UnitExists("partypet"..i) then
2515 Recap_GetUnitInfo("partypet"..i)
2516 Recap_AddFriend(UnitName("partypet"..i),UnitName("party"..i))
2517 end
2518 end
2519 end
2520  
2521 if (GetNumRaidMembers()>0) then
2522 for i=1,40 do
2523 if UnitExists("raid"..i) then
2524 Recap_GetUnitInfo("raid"..i)
2525 Recap_AddFriend(UnitName("raid"..i))
2526 if UnitExists("raidpet"..i) then
2527 Recap_GetUnitInfo("raidpet"..i)
2528 Recap_AddFriend(UnitName("raidpet"..i),UnitName("raid"..i))
2529 end
2530 end
2531 end
2532 end
2533 end
2534  
2535 -- returns a string of seconds converted to 0:00:00 format
2536 function Recap_FormatTime(arg1)
2537  
2538 local hours, minutes, seconds
2539 local text
2540  
2541 seconds = math.floor(arg1+.5)
2542 hours = math.floor(seconds/3600)
2543 seconds = seconds - hours*3600
2544 minutes = math.floor(seconds/60)
2545 seconds = seconds - minutes*60
2546  
2547 return ((hours>0) and (hours..":") or "") .. string.format("%02d:",minutes) .. string.format("%02d",seconds)
2548 end
2549  
2550 function Recap_SetClassIcon(id,class)
2551 if class and recap_temp.ClassIcons[class] then
2552 getglobal("RecapList"..id.."_Class"):SetTexCoord(recap_temp.ClassIcons[class].left,recap_temp.ClassIcons[class].right,recap_temp.ClassIcons[class].top,recap_temp.ClassIcons[class].bottom)
2553 else
2554 getglobal("RecapList"..id.."_Class"):SetTexCoord(.9,1,.9,1)
2555 end
2556 end
2557  
2558 function Recap_SetFactionIcon(id,faction)
2559  
2560 item = getglobal("RecapList"..id.."_Faction")
2561  
2562 if faction and recap_temp.FactionIcons[faction] then
2563 item:SetTexture(recap_temp.FactionIcons[faction])
2564 else
2565 item:SetTexture("")
2566 end
2567  
2568 end
2569  
2570 function Recap_GetUnitInfo(unit)
2571  
2572 local u=UnitName(unit)
2573  
2574 if u then
2575 if recap.Combatant[u] then
2576 _,recap.Combatant[u].Class = UnitClass(unit)
2577 _,recap.Combatant[u].Faction = UnitFactionGroup(unit)
2578 if UnitCreatureFamily(unit) and recap.Combatant[u].Faction then
2579 recap.Combatant[u].Class = "Pet"
2580 end
2581 recap.Combatant[u].Level = UnitLevel(unit)
2582 end
2583 end
2584  
2585 if unit~="target" and unit~="mouseover" and recap_temp.Last[u] then
2586 if UnitIsVisible(unit) then
2587 recap_temp.Last[u].HP = UnitHealth(unit)
2588 recap_temp.Last[u].MaxHP = UnitHealthMax(unit)
2589 else
2590 recap_temp.Last[u].HP = nil -- discredit
2591 end
2592 end
2593  
2594 end
2595  
2596 -- creates a new .Combatant[arg1] that is a copy of DefaultCombatant
2597 function Recap_CreateBlankCombatant(arg1)
2598  
2599 if not recap.Combatant[arg1] then
2600  
2601 recap.Combatant[arg1] = {
2602 TotalTime = 0,
2603 TotalDmgIn = 0,
2604 TotalDmgOut = 0,
2605 TotalDPS = 0,
2606 TotalMaxHit = 0,
2607 TotalKills = 0,
2608 TotalHeal = 0,
2609 LastTime = 0,
2610 LastDmgIn = 0,
2611 LastDmgOut = 0,
2612 LastDPS = 0,
2613 LastMaxHit = 0,
2614 LastKills = 0,
2615 LastHeal = 0,
2616 WasInLast = false,
2617 Friend = false,
2618 Ignore = nil,
2619 Owner = nil,
2620 Incoming = {},
2621 Detail = {}
2622 }
2623  
2624 end
2625  
2626 end
2627  
2628 -- populates .Opt with a copy of DefaultOpt
2629 function Recap_LoadDefaultOpt()
2630  
2631 recap.Opt = {}
2632 for i in recap_temp.DefaultOpt do
2633 recap.Opt[i] = {}
2634 for j in recap_temp.DefaultOpt[i] do
2635 recap.Opt[i][j] = recap_temp.DefaultOpt[i][j]
2636 end
2637 end
2638 end
2639  
2640 function Recap_SaveOpt(user)
2641  
2642 if user and string.len(user)>0 then
2643 recap[user].Opt = {}
2644 for i in recap.Opt do
2645 text = ""
2646 for j in recap.Opt[i] do
2647 text = text..tostring(j).."="..tostring(recap.Opt[i][j]).." "
2648 end
2649 recap[user].Opt[i] = text
2650 end
2651 end
2652 end
2653  
2654 function Recap_LoadOpt(user)
2655  
2656 if user and recap[user] and recap[user].Opt then
2657 for i in recap[user].Opt do
2658 if recap_temp.DefaultOpt[i] then
2659 for t,v in string.gfind(recap[user].Opt[i],"(%w+)=(%d-%--%w+) ") do
2660 if v=="true" then
2661 v = true
2662 elseif v=="false" then
2663 v = false
2664 elseif tonumber(v) then
2665 v = tonumber(v)
2666 end
2667 if t=="type" and recap_temp.DefaultOpt[i][t] then
2668 v = recap_temp.DefaultOpt[i][t]
2669 end
2670 if recap.Opt[i] then
2671 recap.Opt[i][t] = v
2672 end
2673 end
2674 end
2675 end
2676 end
2677 end
2678  
2679 -- saves current data to data set "filen", overwrite~=nil to overwrite existing data
2680 function Recap_SaveCombatants(filen,overwrite)
2681  
2682 local sd = {}
2683  
2684 if not filen or string.len(filen)<1 then
2685 return
2686 end
2687  
2688 if not recap_set[filen] then
2689 recap_set[filen] = {}
2690 recap_set[filen].TimeStamp = date()
2691 recap_set[filen].TotalDuration = 0
2692 recap_set[filen].Combatant = {}
2693 end
2694  
2695 recap_set[filen] = {}
2696 recap_set[filen].TimeStamp = date()
2697 recap_set[filen].TotalDuration = recap[recap_temp.p].TotalDuration
2698 recap_set[filen].Combatant = {}
2699 for i in recap.Combatant do
2700 if (not recap.Opt.SaveFriends.value or recap.Combatant[i].Friend) then
2701 recap_set[filen].Combatant[i] = string.format("%s %d %d %d %d %d %.3f ~%d %d %d",
2702 tostring(recap.Combatant[i].Friend),
2703 recap.Combatant[i].TotalDmgIn,
2704 recap.Combatant[i].TotalDmgOut,
2705 recap.Combatant[i].TotalMaxHit,
2706 recap.Combatant[i].TotalHeal,
2707 recap.Combatant[i].TotalKills,
2708 recap.Combatant[i].TotalTime,
2709 Recap_MakeKey(recap.Combatant[i].Faction),
2710 Recap_MakeKey(recap.Combatant[i].Class),
2711 recap.Combatant[i].Level or 0)
2712 if recap.Opt.LightData and not recap.Opt.LightData.value then
2713 -- save .Incoming
2714 recap_set[filen].Combatant[i] = recap_set[filen].Combatant[i].."^"
2715 for k in recap.Combatant[i].Incoming do
2716 if recap.Combatant[i].Incoming[k]>0 then
2717 recap_set[filen].Combatant[i] = recap_set[filen].Combatant[i]..inckey[k]..recap.Combatant[i].Incoming[k]
2718 end
2719 end
2720 recap_set[filen].Combatant[i] = recap_set[filen].Combatant[i].."^"
2721  
2722 for j in recap.Combatant[i].Detail do
2723 recap_set[filen].Combatant[i] = recap_set[filen].Combatant[i].."["..j..">"
2724 for k in recap.Combatant[i].Detail[j] do
2725 recap_set[filen].Combatant[i] = recap_set[filen].Combatant[i]..detkey[k]..recap.Combatant[i].Detail[j][k]
2726 end
2727 recap_set[filen].Combatant[i] = recap_set[filen].Combatant[i].."]"
2728 end
2729  
2730 end
2731 end
2732 end
2733  
2734 fight_count = 0
2735 for i in recap_set[filen].Combatant do
2736 fight_count = fight_count + 1
2737 end
2738 recap_set[filen].ListSize = fight_count
2739 end
2740  
2741 function Recap_MakeKey(arg1)
2742  
2743 local key = 0
2744  
2745 for i in recap_temp.Keys do
2746 if arg1==recap_temp.Keys[i] then
2747 key = i
2748 end
2749 end
2750 return key
2751 end
2752  
2753 function Recap_GetKey(arg1)
2754  
2755 local key = nil
2756  
2757 if not arg1 or not tonumber(arg1) or arg1==0 then
2758 key=nil
2759 else
2760 key=recap_temp.Keys[tonumber(arg1)]
2761 end
2762 return key
2763 end
2764  
2765 function Recap_LoadCombatants(filen,overwrite)
2766  
2767 local sd = {} -- temp holding place for fields that may not exist
2768 local found,set_friend,set_dmgin,set_dmgout,set_maxhit,set_heal,set_kills,set_time,set_faction,set_class,set_level
2769  
2770 if not filen or string.len(filen)<1 or not recap_set[filen] then
2771 return
2772 end
2773  
2774 Recap_ResetAllCombatants()
2775  
2776 recap[recap_temp.p].TotalDuration = recap[recap_temp.p].TotalDuration + recap_set[filen].TotalDuration
2777  
2778 for i in recap_set[filen].Combatant do
2779 if not recap.Combatant[i] then
2780 Recap_CreateBlankCombatant(i)
2781 end
2782 found,_,set_friend,set_dmgin,set_dmgout,set_maxhit,set_heal,set_kills,set_time = string.find(recap_set[filen].Combatant[i],"(%w+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+%.?%d+)")
2783 if found then
2784 if set_friend == "true" then
2785 recap.Combatant[i].Friend = true
2786 end
2787 if tonumber(set_maxhit) > recap.Combatant[i].TotalMaxHit then
2788 recap.Combatant[i].TotalMaxHit = tonumber(set_maxhit)
2789 end
2790 recap.Combatant[i].TotalDmgIn = recap.Combatant[i].TotalDmgIn + tonumber(set_dmgin)
2791 recap.Combatant[i].TotalDmgOut = recap.Combatant[i].TotalDmgOut + tonumber(set_dmgout)
2792 recap.Combatant[i].TotalKills = recap.Combatant[i].TotalKills + tonumber(set_kills)
2793 recap.Combatant[i].TotalHeal = recap.Combatant[i].TotalHeal + tonumber(set_heal)
2794 recap.Combatant[i].TotalTime = recap.Combatant[i].TotalTime + tonumber(set_time)
2795 if recap.Combatant[i].TotalTime > recap_temp.MinTime then
2796 recap.Combatant[i].TotalDPS = recap.Combatant[i].TotalDmgOut/recap.Combatant[i].TotalTime
2797 else
2798 recap.Combatant[i].TotalDPS = 0
2799 end
2800 end
2801 found,_,set_faction,set_class,set_level = string.find(recap_set[filen].Combatant[i],"~(%d+) (%d+) (%d+)")
2802 if not found then
2803 found,_,set_faction,set_class = string.find(recap_set[filen].Combatant[i],"~(%d+) (%d+)")
2804 end
2805 if found then
2806 recap.Combatant[i].Faction = Recap_GetKey(set_faction)
2807 recap.Combatant[i].Class = Recap_GetKey(set_class)
2808 recap.Combatant[i].Level = recap.Combatant[i].Level or set_level or 0
2809 end
2810  
2811 if not recap.Opt.LightData.value then
2812  
2813 -- process incoming: ^a000b000c000^
2814 for k in sd do sd[k] = nil end -- wipe temp buffer
2815 found,_,j = string.find(recap_set[filen].Combatant[i],"%^(.-)%^")
2816 if found then
2817 for k in inckey do
2818 _,_,sd[k] = string.find(j,inckey[k].."(%d+)")
2819 end
2820 elseif string.find(recap_set[filen].Combatant[i],"%^%d+ %d+ %d+ %d+ %d+ %d+ %d+ %d+ %d+ %d+ %d+ %d+ %d+") then
2821 found,_,sd.MeleeDamage,sd.MeleeMax,sd.MeleeHits,sd.MeleeCrits,sd.MeleeMissed,sd.MeleeDodged,sd.MeleeParried,sd.MeleeBlocked,
2822 sd.NonMeleeDamage,sd.NonMeleeMax,sd.NonMeleeHits,sd.NonMeleeCrits,sd.NonMeleeMissed =
2823 string.find(recap_set[filen].Combatant[i],"%^(%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+)")
2824 end
2825 if found then
2826 for k in sd do
2827 if sd[k] and tonumber(sd[k])>0 then
2828 recap.Combatant[i].Incoming[k] = tonumber(sd[k])
2829 end
2830 end
2831 end
2832  
2833 -- process details: [name:a000b000c000]
2834 for j in string.gfind(recap_set[filen].Combatant[i],"%[.-%]") do
2835 for k in sd do sd[k] = nil end -- wipe temp buffer
2836 found,_,set_name = string.find(j,"%[(.-)%>")
2837 if found then -- new saved method
2838 recap.Combatant[i].Detail[set_name] = {}
2839 for k in detkey do
2840 _,_,sd[k] = string.find(j,detkey[k].."(%d+)")
2841 end
2842 else
2843 found,_,set_name = string.find(j,"%[(.-) %d")
2844 if found then -- old saved method
2845 recap.Combatant[i].Detail[set_name] = {}
2846 _,_,sd.HitsDmg,sd.Hits,sd.HitsMax,sd.CritsDmg,sd.Crits,sd.CritsMax,sd.CritsEvents,sd.Missed =
2847 string.find(j,"%[.+ (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+)") -- old method
2848 end
2849 end
2850 if found then
2851 for k in sd do
2852 if sd[k] and tonumber(sd[k])>0 then
2853 recap.Combatant[i].Detail[set_name][k] = tonumber(sd[k])
2854 end
2855 end
2856 end
2857  
2858 end
2859 end
2860  
2861 end
2862  
2863 end
2864  
2865 function Recap_ResetAllCombatants()
2866  
2867 local current_state = recap.Opt.State.value
2868 recap.Opt.State.value = "Stopped"
2869  
2870 recap.Combatant = {}
2871 recap_temp.IdleTimer = -1
2872 recap_temp.Last = {}
2873 recap[recap_temp.p].LastDuration = 0
2874 recap[recap_temp.p].TotalDuration = 0
2875 recap_temp.FightStart = 0
2876 recap_temp.FightEnd = 0
2877 recap_temp.ListSize = 0
2878  
2879 recap.Opt.State.value = current_state
2880 end
2881  
2882 local function Recap_LoadSelf()
2883  
2884 recap.Self = recap.Self or {}
2885 recap.Self[recap_temp.s] = recap.Self[recap_temp.s] or {}
2886  
2887 recap_temp.SelfList = {}
2888 recap_temp.SelfListSize = 1
2889 end
2890  
2891 function Recap_InitializeData()
2892  
2893 local i,j,k,l,m
2894 local temp_user = recap_temp.p
2895 local oldkeys = { ["Krieger"]="WARRIOR", ["Magier"]="MAGE", ["Schurke"]="ROGUE", ["Druide"]="DRUID",
2896 ["J\195\164ger"]="HUNTER", ["Schamane"]="SHAMAN", ["Priester"]="PRIEST", ["Hexenmeister"]="WARLOCK",
2897 ["Guerrier"]="WARRIOR", ["Voleur"]="ROGUE", ["Chasseur"]="HUNTER", ["Chaman"]="SHAMAN",
2898 ["Prêtre"]="PRIEST", ["Démoniste"]="WARLOCK", ["Familier"]="Pet" }
2899  
2900  
2901 if not recap.DataVersion then
2902 -- wipe all pre-2.6 data
2903 recap = {}
2904 recap.DataVersion = 3.2
2905 elseif recap.DataVersion < 3.0 then
2906 -- convert 2.6 to 3.0, make classes uppercase
2907 for i in recap.Combatant do
2908  
2909 if recap.Combatant[i].Faction=="Allianz" then
2910 recap.Combatant[i].Faction = "Alliance"
2911 end
2912  
2913 if recap.Combatant[i].Class then
2914 -- convert classes to english, which all locales will use for icon reference
2915 if oldkeys[recap.Combatant[i].Class] then
2916 recap.Combatant[i].Class = oldkeys[recap.Combatant[i].Class]
2917 end
2918 recap.Combatant[i].Class = string.upper(recap.Combatant[i].Class)
2919 end
2920 end
2921 recap.DataVersion = 3.0
2922 end
2923  
2924 -- if this user hasn't been made before
2925 if not recap[recap_temp.p] then
2926 recap[recap_temp.p] = {}
2927 recap[recap_temp.p].TotalDuration = 0
2928 recap[recap_temp.p].LastDuration = 0
2929 end
2930  
2931 -- if this is a different/first-time user, or if this is first run of a new version,
2932 -- save the current combatants and options and then load them based on default.
2933 -- any changes in combatant or option format must come with a version change
2934 if (recap.User ~= recap_temp.p) or recap.DataVersion<Recap_Version then
2935  
2936 -- if we have data from previous user, save them
2937 if recap.User then
2938 recap_temp.p = recap.User
2939 Recap_SaveCombatants("UserData:"..recap.User,1)
2940 Recap_SaveOpt(recap.User)
2941 recap_temp.p = temp_user
2942 end
2943 recap.User = recap_temp.p
2944  
2945 -- wipe slate, load defaults and overlay saved data ontop
2946 Recap_LoadDefaultOpt()
2947 Recap_ResetAllCombatants()
2948  
2949 -- convert data sets to new format (see readme)
2950 if recap.DataVersion < 3.2 then
2951 for i in recap_set do
2952 if recap_set[i].Combatant then
2953 j = recap_set[i].TimeStamp
2954 Recap_LoadCombatants(i,1)
2955 for k in recap_set[i].Combatant do
2956 l = (l or 0) + string.len(recap_set[i].Combatant[k])
2957 end
2958 Recap_SaveCombatants(i,1)
2959 for k in recap_set[i].Combatant do
2960 m = (m or 0) + string.len(recap_set[i].Combatant[k])
2961 end
2962 recap_set[i].TimeStamp = j
2963 end
2964 end
2965 recap.DataVersion = 3.2
2966 end
2967  
2968 Recap_LoadCombatants("UserData:"..recap_temp.p,1)
2969 Recap_LoadOpt(recap_temp.p)
2970  
2971 recap.DataVersion = Recap_Version
2972  
2973 else
2974 for i in recap.Combatant do
2975 recap_temp.Last[i] = { Start = 0, End = 0, DmgIn = 0, DmgOut = 0, MaxHit = 0, Kills = 0, Heal = 0 }
2976 end
2977 end
2978  
2979 -- remove current UserData: - it's now "live" in recap.Combatant
2980 if recap_set and recap_set["UserData:"..recap_temp.p] then
2981 recap_set["UserData:"..recap_temp.p] = nil
2982 end
2983  
2984 Recap_LoadSelf()
2985  
2986 end
2987  
2988 --[[ Context menu functions ]]
2989  
2990 function RecapMenu_OnUpdate(arg1)
2991  
2992 local i
2993  
2994 if not recap_temp.MenuTimer or MouseIsOver(RecapMenu) then
2995 recap_temp.MenuTimer = 0
2996 end
2997  
2998 recap_temp.MenuTimer = recap_temp.MenuTimer + arg1
2999 if recap_temp.MenuTimer > .2 then
3000 recap_temp.MenuTimer = 0
3001 RecapMenu:Hide()
3002 if recap_temp.SelectedEffect then
3003 for i=1,15 do
3004 getglobal("RecapSelf"..i):UnlockHighlight()
3005 end
3006 end
3007 end
3008 end
3009  
3010  
3011 --[[ Fight report functions ]]
3012  
3013 function Recap_AutoPostGetStatID(arg1)
3014  
3015 if arg1=="Damage" then
3016 return "DmgOut"
3017 elseif arg1=="Tanking" then
3018 return "DmgIn"
3019 elseif arg1=="Healing" then
3020 return "Heal"
3021 end
3022 return "DPS"
3023 end
3024  
3025 function Recap_PostFight()
3026  
3027 local print_chat = SendChatMessage
3028 local chatchan, chatnum, text
3029  
3030 if recap.Opt.SpamRows.value then
3031 Recap_PostSpamRows(Recap_AutoPostGetStatID(recap.Opt.AutoPost.Stat),"recap auto")
3032 else
3033 chatchan = recap.Opt.AutoPost.Channel
3034 _,_,chatnum = string.find(chatchan,"(%d+)")
3035 if chatnum then
3036 chatchan = "CHANNEL"
3037 end
3038 if chatchan=="Self" then
3039 print_chat = Recap_Print
3040 end
3041 text = Recap_PostSpamLine(Recap_AutoPostGetStatID(recap.Opt.AutoPost.Stat))
3042 if string.find(text,"%d") then
3043 print_chat(Recap_PostSpamLine(Recap_AutoPostGetStatID(recap.Opt.AutoPost.Stat)),chatchan,nil,chatnum)
3044 end
3045 end
3046  
3047 end
3048  
3049 function Recap_PostLeader()
3050  
3051 local print_chat = SendChatMessage
3052 local chatchan, chatnum, leader, statid, i
3053  
3054 if recap_temp.ListSize>2 then
3055 chatchan = recap.Opt.AutoPost.Channel
3056 _,_,chatnum = string.find(chatchan,"(%d+)")
3057 if chatnum then
3058 chatchan = "CHANNEL"
3059 end
3060 if chatchan=="Self" then
3061 print_chat = Recap_Print
3062 end
3063 statid = Recap_AutoPostGetStatID(recap.Opt.AutoPost.Stat)
3064  
3065 if not recap.Combatant[recap_temp.Leader] then -- in case leader reset
3066 recap_temp.Leader = nil
3067 end
3068  
3069 if not recap_temp.Leader and recap.Combatant[recap_temp.List[1].Name].Friend then
3070 recap_temp.Leader = recap_temp.List[1].Name
3071 leader = recap_temp.Leader -- spam initial leader
3072 end
3073  
3074 if recap_temp.Leader then
3075 for i in recap.Combatant do
3076 if (recap.Combatant[i]["Total"..statid] > recap.Combatant[recap_temp.Leader]["Total"..statid]) and recap.Combatant[i].Friend then
3077 leader = i
3078 end
3079 end
3080 if leader then
3081 recap_temp.Leader = leader
3082 print_chat(string.format("New leader for %s: %s with %s",recap.Opt.AutoPost.Stat,leader,Recap_FormatStat(statid,leader)),chatchan,nil,chatnum)
3083 end
3084 end
3085 end
3086 end
3087  
3088  
3089 -- returns 'text' to be spammed in autopost or linked in chat
3090 function Recap_PostSpamLine(arg1)
3091  
3092 local text,i
3093  
3094 text = recap_temp.Local.LinkRank[arg1].." for "..recap_temp.Local.LastAll[recap.Opt.View.value]..":"
3095 for i=1,recap.Opt.MaxRank.value do
3096 if i<recap_temp.ListSize and recap.Combatant[recap_temp.List[i].Name].Friend then
3097 if recap_temp.List[i][arg1]>0 then
3098 text = text.." ["..i.."."..recap_temp.List[i].Name.." "..Recap_FormatStat(arg1,i).."]"
3099 end
3100 end
3101 end
3102 return text
3103 end
3104  
3105 -- arg1 = stat to report by (DPS, DmgOut, etc)
3106 function Recap_PostSpamRows(arg1,chatchan,chatnum)
3107  
3108 local headertext = nil
3109 local print_chat = SendChatMessage
3110  
3111 if chatchan=="recap auto" then
3112 chatchan = recap.Opt.AutoPost.Channel
3113 end
3114  
3115 arg1 = string.gsub(arg1,"P$","") -- strip trailing P from % id's
3116  
3117 if not chatnum then
3118 _,_,chatnum = string.find(chatchan,"(%d+)")
3119 if chatnum then
3120 chatchan = "CHANNEL"
3121 end
3122 end
3123 if chatchan=="Self" then
3124 print_chat = Recap_Print
3125 end
3126 headertext = "__ "..recap_temp.Local.LinkRank[arg1].." for "..recap_temp.Local.LastAll[recap.Opt.View.value].." __"
3127 for i=1,recap.Opt.MaxRank.value do
3128 if i<recap_temp.ListSize and recap.Combatant[recap_temp.List[i].Name].Friend then
3129 text = i..". "..recap_temp.List[i].Name..": "..Recap_FormatStat(arg1,i)
3130 if recap_temp.List[i][arg1] > 0 then
3131 if headertext then
3132 print_chat(headertext,chatchan,nil,chatnum)
3133 headertext = nil
3134 end
3135 print_chat(text,chatchan,nil,chatnum)
3136 end
3137 end
3138 end
3139 end
3140  
3141 -- returns a formatted string for arg1 stat ("DPS" "Time" etc) for combatant arg2 (number is .List[], non-number is name)
3142 function Recap_FormatStat(arg1,arg2)
3143  
3144 local i
3145  
3146 arg1 = string.gsub(arg1,"P$","")
3147  
3148 if not tonumber(arg2) then
3149  
3150 for i=1,(recap_temp.ListSize-1) do
3151 if recap_temp.List[i].Name==arg2 then
3152 arg2 = i
3153 i = recap_temp.ListSize
3154 end
3155 end
3156 end
3157  
3158 if tonumber(arg2) then
3159  
3160 if arg1=="DPS" then
3161 return string.format("%.1f",recap_temp.List[arg2].DPS)
3162 elseif arg1=="DPSvsAll" then
3163 return string.format("%.1f",recap_temp.List[arg2].DPSvsAll)
3164 elseif arg1=="Time" then
3165 return Recap_FormatTime(recap_temp.List[arg2].Time)
3166 elseif arg1=="DmgOut" then
3167 return recap_temp.List[arg2].DmgOut.." ("..recap_temp.List[arg2].DmgOutP.."%)"
3168 elseif arg1=="DmgIn" then
3169 return recap_temp.List[arg2].DmgIn.." ("..recap_temp.List[arg2].DmgInP.."%)"
3170 elseif arg1=="Heal" then
3171 return recap_temp.List[arg2].Heal.." ("..recap_temp.List[arg2].HealP.."%)"
3172 elseif arg1=="Over" then
3173 return recap_temp.List[arg2].Over.."%"
3174 else
3175 return recap_temp.List[arg2][arg1]
3176 end
3177 end
3178  
3179 return ""
3180 end
3181  
3182  
3183 function Recap_Print(arg1)
3184 DEFAULT_CHAT_FRAME:AddMessage(tostring(arg1))
3185 end
3186  
3187 --[[ Debug ]]
3188  
3189 function Recap_DebugUnusedFilters(filter)
3190  
3191 local i,j,found
3192  
3193 for i in recap_temp[filter] do
3194 found = false
3195 for j in recap.debug_Filter do
3196 if recap_temp[filter][i].pattern==recap.debug_Filter[j].pattern then
3197 found = true
3198 end
3199 end
3200 if not found then
3201 DEFAULT_CHAT_FRAME:AddMessage(filter..": "..recap_temp[filter][i].pattern)
3202 end
3203 end
3204  
3205 end
3206  
3207 function Recap_MoveMinimize()
3208  
3209 RecapCloseButton:ClearAllPoints()
3210 RecapCloseButton:SetPoint("TOPRIGHT","RecapFrame","TOPRIGHT",-6,-6)
3211 RecapMinStatus:ClearAllPoints()
3212 RecapMinStatus:SetPoint("TOPLEFT", "RecapFrame", "TOPLEFT", 6,-7)
3213 RecapResetButton:ClearAllPoints()
3214 RecapResetButton:SetPoint("BOTTOMLEFT", "RecapFrame", "BOTTOMLEFT", 5,4)
3215 RecapMinimizeButton:ClearAllPoints()
3216  
3217 if recap.Opt.GrowLeftwards.value and not recap.Opt.GrowUpwards.value then -- topright
3218 RecapMinimizeButton:SetPoint("TOPRIGHT", "RecapFrame", "TOPRIGHT", -6, -6)
3219 RecapCloseButton:SetPoint("TOPRIGHT", "RecapMinimizeButton", "TOPLEFT", -2, 0)
3220 elseif recap.Opt.GrowLeftwards.value and recap.Opt.GrowUpwards.value then -- bottomright
3221 RecapMinimizeButton:SetPoint("BOTTOMRIGHT", "RecapFrame", "BOTTOMRIGHT", -6, 6)
3222 if recap.Opt.Minimized.value then
3223 RecapCloseButton:SetPoint("TOPRIGHT", "RecapMinimizeButton", "TOPLEFT", -2, 0)
3224 end
3225 elseif not recap.Opt.GrowLeftwards.value and not recap.Opt.GrowUpwards.value then -- topleft
3226 RecapMinimizeButton:SetPoint("TOPLEFT", "RecapFrame", "TOPLEFT", 6, -6)
3227 RecapMinStatus:SetPoint("TOPLEFT", "RecapMinimizeButton", "TOPRIGHT", 2, -1)
3228 else -- bottomleft
3229 RecapMinimizeButton:SetPoint("BOTTOMLEFT", "RecapFrame", "BOTTOMLEFT", 6, 6)
3230 RecapResetButton:SetPoint("BOTTOMLEFT", "RecapFrame", "BOTTOMLEFT", 23, 4)
3231 end
3232  
3233 if recap.Opt.Minimized.value and not recap.Opt.GrowLeftwards.value then
3234 RecapMinStatus:SetPoint("TOPLEFT", "RecapMinimizeButton", "TOPRIGHT", 2, -1)
3235 end
3236  
3237 if recap.Opt.AutoMinimize.value then
3238 RecapMinimizeButton:SetWidth(1)
3239 RecapMinimizeButton:Hide()
3240 else
3241 RecapMinimizeButton:SetWidth(16)
3242 RecapMinimizeButton:Show()
3243 end
3244  
3245 end
3246  
3247 function RecapMenu_SetCheck(id,arg1)
3248  
3249 if arg1 then
3250 getglobal("RecapMenu"..id.."_Check"):Show()
3251 else
3252 getglobal("RecapMenu"..id.."_Check"):Hide()
3253 end
3254 end
3255  
3256 function RecapMenu_OnClick()
3257  
3258 local id,index = this:GetID()
3259  
3260 if recap_temp.Menu==recap_temp.ColumnMenu or recap_temp.Menu==recap_temp.MinMenu or recap_temp.Menu==recap_temp.EffectOptMenu then
3261 index = recap_temp.Menu[id].Info -- .Info of menu item selected
3262 if recap.Opt[index] then
3263 recap.Opt[index].value = not recap.Opt[index].value
3264 getglobal("RecapOptCheck_"..recap_temp.Menu[id].Info):SetChecked(0)
3265 if recap.Opt[index].value then
3266 getglobal("RecapOptCheck_"..recap_temp.Menu[id].Info):SetChecked(1)
3267 end
3268 RecapMenu_SetCheck(id,recap.Opt[index].value)
3269 if recap.Opt.Minimized.value then
3270 Recap_Minimize()
3271 else
3272 Recap_Maximize()
3273 end
3274 elseif index=="Pin" then
3275 recap.Opt.Pinned.value = not recap.Opt.Pinned.value
3276 Recap_SetButtons()
3277 RecapMenu:Hide()
3278 end
3279 end
3280  
3281  
3282 if recap_temp.Menu==recap_temp.AddMenu or recap_temp.Menu==recap_temp.DropMenu then
3283 RecapMenu:Hide()
3284 index = recap_temp.List[recap_temp.Selected].Name -- name selected
3285  
3286 if id==1 and recap_temp.Menu==recap_temp.DropMenu and index~=recap_temp.Player then
3287 recap.Combatant[index].Friend = false
3288 elseif id==1 and index~=recap_temp.Player then
3289 recap.Combatant[index].Friend = not recap.Combatant[index].Friend
3290 elseif id==2 and recap.Opt.View.value=="All" then -- reset
3291 recap.Combatant[index] = nil
3292 Recap_CreateBlankCombatant(index)
3293 elseif id==2 and recap.Opt.View.value=="Last" then
3294 if recap.Combatant[index].WasInLast then
3295 Recap_ResetLastFight(index)
3296 end
3297 elseif id==3 and index~=recap_temp.Player then
3298 recap.Combatant[index] = nil
3299 Recap_CreateBlankCombatant(index)
3300 recap.Combatant[index].Ignore = true
3301 end
3302  
3303 Recap_SetView()
3304 end
3305  
3306 if recap_temp.Menu==recap_temp.EffectMenu then
3307 RecapMenu:Hide()
3308 for i=1,15 do
3309 getglobal("RecapSelf"..i):UnlockHighlight()
3310 end
3311 if recap_temp.SelectedEffect and recap.Self[recap_temp.s][recap_temp.SelectedEffect] then
3312 recap.Self[recap_temp.s][recap_temp.SelectedEffect] = nil
3313 recap_temp.SelectedEffect = nil
3314 Recap_SetView()
3315 end
3316 end
3317  
3318 if recap_temp.Menu==recap_temp.DetailMenu then
3319 if recap_temp.DetailsList and recap_temp.DetailsList[1][recap_temp.Menu[id].Info] then
3320 recap.Opt.PanelDetail.value = recap_temp.Menu[id].Info
3321 RecapPanel_Populate(recap_temp.List[recap_temp.Selected].Name)
3322 end
3323 RecapMenu:Hide()
3324 end
3325 end
3326  
3327 -- offset=1 to move window so it's under pointer
3328 function RecapCreateMenu(menu,offset)
3329  
3330 local i,cy,x,y,lines
3331  
3332 recap_temp.Menu = menu
3333  
3334 if recap_temp.Menu==recap_temp.ColumnMenu or recap_temp.Menu==recap_temp.MinMenu or recap_temp.Menu==recap_temp.EffectOptMenu then
3335 for i in recap_temp.Menu do
3336 if recap.Opt[recap_temp.Menu[i].Info] then
3337 recap_temp.Menu[i].Check = recap.Opt[recap_temp.Menu[i].Info].value
3338 end
3339 end
3340 end
3341  
3342 if recap_temp.Menu==recap_temp.MinMenu then
3343 recap_temp.Menu[1].Check = recap.Opt.Pinned.value
3344 end
3345  
3346 if recap_temp.Menu==recap_temp.DetailMenu then
3347 for i in recap_temp.Menu do
3348 recap_temp.Menu[i].Check = recap.Opt.PanelDetail.value==recap_temp.Menu[i].Info
3349 end
3350 end
3351  
3352 lines = min(table.getn(recap_temp.Menu),16)
3353  
3354 cy = 44 -- 12+32
3355 for i=1,lines do
3356 getglobal("RecapMenu"..i.."_Text"):SetText(recap_temp.Menu[i].Text)
3357 RecapMenu_SetCheck(i,recap_temp.Menu[i].Check)
3358 getglobal("RecapMenu"..i):Show()
3359 cy = cy + 14
3360 end
3361 for i=(lines+1),16 do
3362 getglobal("RecapMenu"..i):Hide()
3363 end
3364  
3365 RecapMenu:SetHeight(cy)
3366 RecapDropSubFrame:SetHeight(cy-32)
3367 RecapMenu:ClearAllPoints()
3368 x,y = GetCursorPosition()
3369 if recap.Opt.GrowUpwards.value and not offset then
3370 y = this:GetBottom()*UIParent:GetScale()
3371 RecapMenu:SetPoint("BOTTOMRIGHT","UIParent","BOTTOMLEFT",(x/UIParent:GetScale())+20,(y/UIParent:GetScale())-4)
3372 else
3373 y = this:GetTop()*UIParent:GetScale()
3374 RecapMenu:SetPoint("TOPRIGHT","UIParent","BOTTOMLEFT",(x/UIParent:GetScale())+20,(y/UIParent:GetScale())+(offset and 16 or 4))
3375 end
3376 RecapMenu:Show()
3377  
3378 end
3379  
3380 function RecapMenu_OnEnter()
3381 id = this:GetID()
3382 if recap_temp.Menu[id] and recap_temp.Menu[id].Info then
3383 if recap_temp.Menu==recap_temp.AddMenu or recap_temp.Menu==recap_temp.DropMenu then
3384 Recap_OnTooltip(recap_temp.Menu[id].Info,recap_temp.List[recap_temp.Selected].Name)
3385 elseif recap_temp.Menu==recap_temp.EffectMenu and recap_temp.SelectedEffect then
3386 Recap_OnTooltip(recap_temp.Menu[id].Info,string.sub(recap_temp.SelectedEffect,2))
3387 else
3388 Recap_OnTooltip(recap_temp.Menu[id].Info)
3389 end
3390 end
3391 end
3392  
3393 function RecapEffectsHeader_OnEnter()
3394 local s
3395  
3396 _,_,s = string.find(this:GetName(),"RecapHeader_(.+)")
3397 if s then
3398 Recap_OnTooltip("Header"..s)
3399 end
3400 end
3401  
3402 function RecapSelf_OnMouseUp(arg1)
3403  
3404 local index,i
3405  
3406 recap_temp.SelectedEffect = nil
3407  
3408 Recap_OnMouseUp(arg1)
3409 if arg1=="RightButton" then
3410 _,_,i = string.find(this:GetName(),"(%d+)")
3411 if i and tonumber(i) then
3412 i = tonumber(i)
3413 index = i + FauxScrollFrame_GetOffset(RecapScrollBar)
3414 if index < recap_temp.SelfListSize then
3415 this:LockHighlight()
3416 recap_temp.SelectedEffect = recap_temp.SelfList[index].EName
3417 end
3418 end
3419  
3420 RecapCreateMenu(recap_temp.EffectMenu,1)
3421 end
3422 end
3423  
3424 function RecapEffectsHeader_OnMouseUp(arg1)
3425  
3426 if arg1=="RightButton" then
3427 RecapCreateMenu(recap_temp.EffectOptMenu)
3428 end
3429 end
3430  
3431 function RecapEffectsHeader_OnClick()
3432  
3433 local idx,i
3434 local alltext,text = ""
3435 local channel,chatnumber = ChatFrameEditBox.chatType
3436 local hasdata
3437  
3438 if IsShiftKeyDown() and ChatFrameEditBox:IsVisible() then
3439  
3440 if channel=="WHISPER" then
3441 chatnumber = ChatFrameEditBox.tellTarget
3442 elseif channel=="CHANNEL" then
3443 chatnumber = ChatFrameEditBox.channelTarget
3444 end
3445  
3446 _,_,idx = string.find(tostring(this:GetName()),"RecapHeader_(.+)")
3447 if idx and idx~="EName" then
3448  
3449 alltext = (recap.Opt.SpamRows.value and "__ " or "")..recap_temp.Player.."'s "..Recap_GetTooltip("Header"..idx)..(recap.Opt.SpamRows.value and " __" or ":")
3450 for i=1,recap_temp.SelfListSize-1 do
3451 if recap_temp.SelfList[i][idx]~="0.0%" and recap_temp.SelfList[i][idx]~="--" and tostring(recap_temp.SelfList[i][idx])~="0" then
3452 if not hasdata and recap.Opt.SpamRows.value then
3453 SendChatMessage(alltext,channel,nil,chatnumber)
3454 end
3455 hasdata = true
3456 text = string.sub(recap_temp.SelfList[i].EName,2)..(string.sub(recap_temp.SelfList[i].EName,1,1)=="3" and "*" or "")..(recap.Opt.SpamRows.value and ": " or " ")..recap_temp.SelfList[i][idx]..(idx=="ETotal" and (" ("..recap_temp.SelfList[i].ETotalP..")") or "")
3457 if not recap.Opt.SpamRows.value then
3458 alltext = alltext.." ["..text.."]"
3459 else
3460 SendChatMessage(text,channel,nil,chatnumber)
3461 end
3462 end
3463 end
3464 if not recap.Opt.SpamRows.value and hasdata then
3465 Recap_InsertChat(alltext)
3466 end
3467 end
3468 end
3469 end
3470  
3471  
3472 function RecapSelf_OnClick()
3473  
3474 local id = this:GetID()
3475 local index = id + FauxScrollFrame_GetOffset(RecapScrollBar)
3476 local linkformat = recap_temp.Local.DamageDetailLink
3477 local text = ""
3478  
3479 if IsShiftKeyDown() and index<recap_temp.SelfListSize and ChatFrameEditBox:IsVisible() then
3480  
3481 if string.sub(recap_temp.SelfList[index].EName,1,1)=="3" then
3482 linkformat = recap_temp.Local.HealDetailLink
3483 end
3484 text = string.format(linkformat,recap_temp.Player,string.sub(recap_temp.SelfList[index].EName,2),recap_temp.SelfList[index].ETotal,recap_temp.SelfList[index].ETotalP )..", Max: "..recap_temp.SelfList[index].EMaxAll..((recap_temp.SelfList[index].ECritsP~="--") and (", Crit Rate: "..recap_temp.SelfList[index].ECritsP) or "")
3485 Recap_InsertChat(text," ")
3486 end
3487 end
3488  
3489  
3490 function Recap_Combat_OnEvent()
3491  
3492 if event=="CHAT_MSG_COMBAT_FRIENDLY_DEATH" or event=="CHAT_MSG_COMBAT_HOSTILE_DEATH" then
3493 Recap_DeathEvent(arg1)
3494 elseif event=="UPDATE_MOUSEOVER_UNIT" then
3495 Recap_GetUnitInfo("mouseover")
3496 elseif event=="PLAYER_TARGET_CHANGED" then
3497 Recap_GetUnitInfo("target")
3498 elseif event=="SPELLCAST_START" then
3499 if (not recap.Opt.LightData.value) and recap.Combatant[recap_temp.Player] and recap.Combatant[recap_temp.Player].Detail["1"..arg1] then
3500 if not recap.Opt.LimitFights.value then
3501 if recap.Opt.IdleFight.value then
3502 recap_temp.IdleTimer = 0
3503 end
3504 if recap.Opt.State.value=="Idle" then
3505 Recap_StartFight()
3506 end
3507 end
3508 Recap_CreateCombatant(recap_temp.Player,1) -- if this was a cast that's done damage before, start timer
3509 end
3510 elseif string.find(event,"BUFF") then
3511 Recap_HealEvent(arg1)
3512 else
3513 Recap_DamageEvent(arg1)
3514 end
3515 end
3516  
3517 function Recap_Register_CombatEvents()
3518  
3519 if not recap_temp.CombatEventsRegistered then
3520 -- register damage events
3521 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_HITS")
3522 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_MISSES")
3523 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS")
3524 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS")
3525 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES")
3526 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS")
3527 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES")
3528 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS")
3529 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES")
3530 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_PARTY_HITS")
3531 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_PARTY_MISSES")
3532 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES")
3533 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_PET_HITS")
3534 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_PET_MISSES")
3535 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS")
3536 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_SELF_MISSES")
3537 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE")
3538 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE")
3539 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE")
3540 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS")
3541 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF")
3542 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE")
3543 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE")
3544 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
3545 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE")
3546 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE")
3547 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE")
3548 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
3549 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
3550 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PET_DAMAGE")
3551 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
3552  
3553 -- register death events
3554 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLY_DEATH")
3555 RecapCombatEvents:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH")
3556  
3557 -- register healing events
3558 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF")
3559 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_PARTY_BUFF")
3560 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_BUFF")
3561 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF")
3562 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF")
3563 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF")
3564 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS")
3565 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS")
3566 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS")
3567 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS")
3568 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS")
3569 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_PET_BUFF")
3570 RecapCombatEvents:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF")
3571  
3572 RecapCombatEvents:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
3573 RecapCombatEvents:RegisterEvent("PLAYER_TARGET_CHANGED")
3574 RecapCombatEvents:RegisterEvent("SPELLCAST_START")
3575 recap_temp.CombatEventsRegistered = 1
3576 end
3577 end
3578  
3579 function Recap_Unregister_CombatEvents()
3580 if recap_temp.CombatEventsRegistered then
3581 RecapCombatEvents:UnregisterAllEvents()
3582 recap_temp.CombatEventsRegistered = nil
3583 end
3584 end