vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 ****************************************************************
3 Scrolling Combat Text 5.0
4  
5 Author: Grayhoof
6 ****************************************************************
7  
8 Official Site:
9 http://grayhoof.wowinterface.com
10  
11 ****************************************************************]]
12 SCT = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceDB-2.0", "AceConsole-2.0", "AceHook-2.0");
13  
14 --embedded libs
15 local parser = ParserLib:GetInstance("1.1")
16  
17 --Table Constants
18 SCT.COLORS_TABLE = "COLORS";
19 SCT.CRITS_TABLE = "CRITS";
20 SCT.FRAMES_TABLE = "FRAMES";
21 SCT.FRAMES_DATA_TABLE = "FRAMESDATA";
22 SCT.FRAME1 = 1;
23 SCT.FRAME2 = 2;
24 SCT.MSG = 10;
25  
26 -- local constants, use lowercase sct
27 local sct_LastHPPercent = 0;
28 local sct_LastTargetHPPercent = 0;
29 local sct_LastManaPercent = 0;
30 local sct_LastManaFull = 99999;
31  
32 local arrPowerStrings = {
33 [0] = MANA,
34 [1] = RAGE,
35 [3] = ENERGY
36 }
37  
38 local arrShadowOutline = {
39 [1] = "",
40 [2] = "OUTLINE",
41 [3] = "THICKOUTLINE"
42 }
43  
44 local arrSpellColors = {
45 [SPELL_SCHOOL0_CAP] = {r=1,g=0,b=0},
46 [SPELL_SCHOOL1_CAP] = {r=1,g=1,b=0},
47 [SPELL_SCHOOL2_CAP] = {r=1,g=.3,b=0},
48 [SPELL_SCHOOL3_CAP] = {r=.5,g=1,b=.2},
49 [SPELL_SCHOOL4_CAP] = {r=.4,g=.6,b=.9},
50 [SPELL_SCHOOL5_CAP] = {r=.4,g=.4,b=.5},
51 [SPELL_SCHOOL6_CAP] = {r=.8,g=.8,b=1},
52 }
53  
54 SCT.SpellColors = arrSpellColors;
55  
56 ----------------------
57 --Called on login
58 function SCT:OnEnable()
59 self:RegisterSelfEvents();
60 end
61  
62 ----------------------
63 -- called on standby
64 function SCT:OnDisable()
65 self:DisableAll()
66 end
67  
68 ----------------------
69 -- Disable all events
70 function SCT:DisableAll()
71 -- no more events to handle
72 parser:UnregisterAllEvents("sct")
73 self:UnregisterAllEvents()
74 end
75  
76 ----------------------
77 -- Show the Option Menu
78 function SCT:ShowMenu()
79 local loaded, message = LoadAddOn("sct_options");
80 if (loaded) then
81 PlaySound("igMainMenuOpen");
82 ShowUIPanel(SCTOptions);
83 else
84 PlaySound("TellMessage");
85 SCT:Print(SCT.LOCALS.Load_Error.." "..message);
86 end
87 end
88  
89 ----------------------
90 --Hide the Option Menu
91 function SCT:HideMenu()
92 PlaySound("igMainMenuClose");
93 HideUIPanel(SCTOptions);
94 end
95  
96 ----------------------
97 --Called when Addon loaded
98 function SCT:OnInitialize()
99  
100 --default settings
101 local default_config = self:GetDefaultConfig();
102  
103 --slash command setup
104 local main = {
105 type="group",
106 args = {
107 menu = {
108 name = "Menu", type = 'execute',
109 desc = "Display SCT Option Menu",
110 func = function()
111 self:ShowMenu();
112 end
113 },
114 reset = {
115 name = "Reset", type = 'execute',
116 desc = "Reset SCT Options to default",
117 func = function()
118 self:Reset();
119 end
120 }
121 }
122 }
123 local menu = {
124 type = 'execute',
125 desc = "Display SCT Option Menu",
126 func = function()
127 self:ShowMenu();
128 end
129 }
130 local reset = {
131 type = 'execute',
132 desc = "Reset SCT Options to default",
133 func = function()
134 self:Reset();
135 end
136 }
137 local cmd = {
138 type = 'text',
139 name = "Display",
140 usage = SCT.LOCALS.DISPLAY_USEAGE,
141 desc = "Display a message using SCT",
142 get = false,
143 set = function(x)
144 self:CmdDisplay(x);
145 end
146 }
147  
148 --hook chat frame if using event debug
149 if SCT.EventDebug then
150 for i = 1, 7, 1 do
151 self:Hook(getglobal("ChatFrame" .. i), "AddMessage")
152 end
153 end
154  
155 self:RegisterDB("SCT_CONFIG")
156 self:RegisterDefaults('profile', default_config )
157  
158 self:RegisterChatCommand({"/sct"}, main)
159 self:RegisterChatCommand({"/sctmenu"}, menu)
160 self:RegisterChatCommand({"/sctreset"}, reset)
161 self:RegisterChatCommand({"/sctdisplay"}, cmd)
162  
163 --set to profile by char by default
164 if not self.db.char.notFirstTime then
165 self.db.char.notFirstTime = true;
166 self:SetProfile("char");
167 end
168  
169 --register with other mods
170 self:RegisterOtherMods()
171  
172 -- Add my options frame to the global UI panel list
173 UIPanelWindows["SCTOptions"] = {area = "center", pushable = 0};
174  
175 --setup animations
176 self:AniInit();
177  
178 --Set Enabled State
179 if (self.db.profile["ENABLED"]) then
180 self:ToggleActive(true);
181 self:Print(SCT.LOCALS.STARTUP);
182 else
183 self:ToggleActive(false);
184 end
185  
186 end
187  
188 ----------------------
189 --Hook Function to show event
190 function SCT:AddMessage(frame, text, r, g, b, id)
191 self.hooks[frame].AddMessage.orig(frame, text.." |cff00ff00["..tostring(event).."]|r", r, g, b, id)
192 end
193  
194 ----------------------
195 --Reset everything to default
196 function SCT:Reset()
197 self:ResetDB("profile")
198 self:HideMenu();
199 self:ShowMenu();
200 self:ShowExample();
201 self:Print(SCT.LOCALS.PROFILE_NEW..AceLibrary("AceDB-2.0").CHAR_ID);
202 end
203  
204 ----------------------
205 --Get a value from player config
206 function SCT:Get(option, table)
207 if (table) then
208 return self.db.profile[table][option];
209 else
210 return self.db.profile[option];
211 end
212 end
213  
214 ----------------------
215 --Set a value in player config
216 function SCT:Set(option, value, table)
217 if (table) then
218 self.db.profile[table][option] = value;
219 else
220 self.db.profile[option] = value;
221 end
222 end
223  
224 ----------------------
225 --Display for any partial blocks
226 function SCT:DisplayBlock(blocked)
227 SCT:Display_Event("SHOWBLOCK", BLOCK.." ("..blocked..")");
228 end
229  
230 ----------------------
231 --Display for any partial absorbs
232 function SCT:DisplayAbsorb(absorbed)
233 SCT:Display_Event("SHOWABSORB", ABSORB.." ("..absorbed..")");
234 end
235  
236 ----------------------
237 -- Event Handler
238 -- this function parses events that are printed in the combat
239 -- chat window then displays the health changes
240 function SCT:OnEvent()
241 --Player Health
242 if (event == "UNIT_HEALTH") then
243 if (arg1 == "player") then
244 local warnlevel = self.db.profile["LOWHP"] / 100;
245 local HPPercent = UnitHealth("player") / UnitHealthMax("player");
246 if (HPPercent < warnlevel) and (sct_LastHPPercent >= warnlevel) and (not SCT:CheckFD("player")) then
247 if (self.db.profile["PLAYSOUND"] and self.db.profile["SHOWLOWHP"]) then
248 PlaySoundFile("Sound\\Spells\\bind2_Impact_Base.wav")
249 end
250 self:Display_Event("SHOWLOWHP", SCT.LOCALS.LowHP.." ("..UnitHealth("player")..")");
251 end
252 sct_LastHPPercent = HPPercent;
253 return;
254 end
255 return;
256  
257 --Player Mana
258 elseif (event == "UNIT_MANA") or (event == "UNIT_RAGE") or (event == "UNIT_ENERGY")then
259 if (arg1 == "player") and (UnitPowerType("player") == 0)then
260 local warnlevel = self.db.profile["LOWMANA"] / 100;
261 local ManaPercent = UnitMana("player") / UnitManaMax("player");
262 if (ManaPercent < warnlevel) and (sct_LastManaPercent >= warnlevel) and (not SCT:CheckFD("player")) then
263 if (self.db.profile["PLAYSOUND"] and self.db.profile["SHOWLOWMANA"]) then
264 PlaySoundFile("Sound\\Spells\\ShaysBell.wav");
265 end
266 SCT:Display_Event("SHOWLOWMANA", SCT.LOCALS.LowMana.." ("..UnitMana("player")..")");
267 end
268 sct_LastManaPercent = ManaPercent;
269 end
270 if (arg1 == "player") and (self.db.profile["SHOWALLPOWER"]) then
271 local ManaFull = UnitMana("player");
272 if (ManaFull > sct_LastManaFull) then
273 self:Display_Event("SHOWPOWER", "+"..ManaFull-sct_LastManaFull.." "..arrPowerStrings[UnitPowerType("player")]);
274 end
275 sct_LastManaFull = ManaFull;
276 end
277 return;
278  
279 --Power Change
280 elseif (event == "UNIT_DISPLAYPOWER") then
281 sct_LastManaFull = UnitMana("player");
282 return;
283  
284 --Player Combat
285 elseif (event =="PLAYER_REGEN_DISABLED") then
286 self:Display_Event("SHOWCOMBAT", SCT.LOCALS.Combat);
287 return;
288  
289 --Player NoCombat
290 elseif (event =="PLAYER_REGEN_ENABLED") then
291 self:Display_Event("SHOWCOMBAT", SCT.LOCALS.NoCombat);
292 return;
293  
294 --Player Combo Points
295 elseif (event == "PLAYER_COMBO_POINTS") then
296 local sct_CP = GetComboPoints();
297 if (sct_CP ~= 0) then
298 local sct_CP_Message = sct_CP.." "..SCT.LOCALS.ComboPoint;
299 if (sct_CP == 5) then
300 sct_CP_Message = sct_CP_Message.." "..SCT.LOCALS.FiveCPMessage;
301 end;
302 self:Display_Event("SHOWCOMBOPOINTS", sct_CP_Message);
303 end
304 return;
305  
306 --All other combat events
307 elseif (arg1) then
308 self:ParseCombat(arg1);
309 end
310 end
311  
312 ----------------------
313 -- Displays Parsed info based on type
314 function SCT:ParseCombat(info)
315 --self doesn't work here because of the call from ParserLib
316 local self = SCT;
317  
318 --custom search first
319 if (self.db.profile["CUSTOMEVENTS"]) and (not SCT.db.profile["LIGHTMODE"]) and (self:CustomEventSearch(arg1) == true) then
320 return;
321 end
322  
323 --Player Skill Gains Here, since its unsupported
324 if (event == "CHAT_MSG_SKILL") then
325 local target, rank = parser:Deformat(arg1, SKILL_RANK_UP);
326 if target then
327 self:Display_Event("SHOWSKILL", target..": "..rank);
328 return;
329 end
330 return;
331 end
332  
333 --if its not a ParserLib Event, then end
334 if (type(info) ~= "table") then
335 return;
336 end
337  
338 --outgoing heals, done first since its only thing blizzard events don't do
339 if (info.type == "heal" and info.victim ~= ParserLib_SELF) then
340 --heal filter
341 if (info.amount < self.db.profile["HEALFILTER"]) then return end;
342 --outgoing heals, ignore dots
343 if (info.source == ParserLib_SELF and not info.isDOT) then
344 if (self.db.profile["SHOWOVERHEAL"]) then
345 info.amount = self:GetOverheal(info.victim, info.amount);
346 end
347 self:Display_Event("SHOWSELFHEAL", info.victim..": +"..info.amount, info.isCrit);
348 end
349 return;
350 end
351  
352 --if in light mode, end here
353 if (self.db.profile["LIGHTMODE"]) then
354 return;
355 end
356  
357 -- Environmental
358 if (info.type == "environment") then
359 if (info.victim == ParserLib_SELF) then
360 if( info.damageType == "fire" or info.damageType == "lava" or info.damageType == "slime") then
361 self:Display_Event("SHOWSPELL", "-"..info.amount, nil, nil, info.amountResist );
362 else
363 self:Display_Event("SHOWHIT", "-"..info.amount);
364 end
365 if(info.amountAbsorb) then
366 self:DisplayAbsorb(info.amountAbsorb);
367 end
368 end
369  
370 --Hits (melee, spell, etc..)
371 elseif (info.type == "hit") then
372 if (info.victim == ParserLib_SELF) then
373 if (info.skill == ParserLib_MELEE) then
374 self:Display_Event("SHOWHIT", "-"..info.amount, info.isCrit);
375 else
376 self:Display_Event("SHOWSPELL", "-"..info.amount, info.isCrit, info.element, info.amountResist);
377 end
378 if( info.amountAbsorb) then
379 self:DisplayAbsorb(info.amountAbsorb);
380 end
381 if( info.amountBlock) then
382 self:DisplayBlock(info.amountBlock);
383 end
384 end
385  
386 --Miss Events
387 elseif (info.type == "miss") then
388 if (info.victim == ParserLib_SELF) then
389 if (info.missType == "miss") then
390 self:Display_Event("SHOWMISS", MISS, nil, nil, nil, nil, SCT.LOCALS.TARGET.." "..MISS);
391 elseif (info.missType == "dodge") then
392 self:Display_Event("SHOWDODGE", DODGE, nil, nil, nil, nil, YOU.." "..DODGE);
393 elseif (info.missType == "block") then
394 self:Display_Event("SHOWBLOCK", BLOCK, nil, nil, nil, nil, YOU.." "..BLOCK);
395 elseif (info.missType == "deflect") then
396 self:Display_Event("SHOWABSORB", DEFLECT, nil, nil, nil, nil, YOU.." "..DEFLECT);
397 elseif (info.missType == "immune") then
398 self:Display_Event("SHOWABSORB", IMMUNE, nil, nil, nil, nil, YOU.." "..IMMUNE);
399 elseif (info.missType == "evade") then
400 self:Display_Event("SHOWABSORB", EVADAE, nil, nil, nil, nil, YOU.." "..EVADE);
401 elseif (info.missType == "parry") then
402 self:Display_Event("SHOWPARRY", PARRY, nil, nil, nil, nil, YOU.." "..PARRY);
403 elseif (info.missType == "resist") then
404 self:Display_Event("SHOWRESIST", RESIST, nil, nil, nil, nil, YOU.." "..RESIST);
405 elseif (info.missType == "reflect") then
406 self:Display_Event("SHOWABSORB", REFLECT, nil, nil, nil, nil, YOU.." "..REFLECT);
407 elseif (info.missType == "absorb") then
408 self:Display_Event("SHOWABSORB", ABSORB, nil, nil, nil, nil, YOU.." "..ABSORB);
409 end
410 end
411  
412 --Gains
413 elseif (info.type == "gain") then
414 if (info.victim == ParserLib_SELF) and (not self.db.profile["SHOWALLPOWER"]) then
415 self:Display_Event("SHOWPOWER", "+"..info.amount.." "..info.attribute);
416 end
417  
418 --Leech
419 elseif (info.type == "leech") and (not self.db.profile["SHOWALLPOWER"]) then
420 if (info.sourceGained == ParserLib_SELF) then
421 self:Display_Event("SHOWPOWER", "+"..info.amountGained.." "..info.attributeGained);
422 end
423  
424 --buff
425 elseif (info.type == "buff") then
426 if (info.victim == ParserLib_SELF) then
427 self:Display_Event("SHOWBUFF", "["..info.skill.."]", nil, nil, nil, nil, arg1);
428 end
429  
430 --debuff
431 elseif (info.type == "debuff") then
432 if (info.victim == ParserLib_SELF) then
433 if (info.amountRank) then
434 self:Display_Event("SHOWDEBUFF", "("..info.skill.." "..info.amountRank..")", nil, nil, nil, nil, arg1);
435 else
436 self:Display_Event("SHOWDEBUFF", "("..info.skill..")", nil, nil, nil, nil, arg1);
437 end
438 end
439  
440 --healing in/out
441 elseif (info.type == "heal") then
442 --heal filter
443 if (info.amount < self.db.profile["HEALFILTER"]) then return end;
444 --self heals
445 if (info.victim == ParserLib_SELF and info.source == ParserLib_SELF) then
446 if (self.db.profile["SHOWOVERHEAL"]) then
447 info.amount = self:GetOverheal("player", info.amount);
448 end
449 self:Display_Event("SHOWHEAL", "+"..info.amount, info.isCrit, nil, nil, info.skill);
450 --incoming heals
451 elseif (info.victim == ParserLib_SELF) then
452 self:Display_Event("SHOWHEAL", "+"..info.amount, info.isCrit, nil, nil, info.source);
453 end
454 end
455 end
456  
457 ----------------------
458 --Handle Blizzard events
459 function SCT:BlizzardCombatTextEvent()
460 --Normal Events
461 if (arg1=="SPELL_ACTIVE") then
462 self:Display_Event("SHOWEXECUTE", arg2.."!");
463 elseif (arg1=="FACTION") then
464 if ( tonumber(arg3) < 0 ) then
465 self:Display_Event("SHOWREP", "-"..arg3.." "..REPUTATION.." ("..arg2..")");
466 else
467 self:Display_Event("SHOWREP", "+"..arg3.." "..REPUTATION.." ("..arg2..")");
468 end
469 elseif (arg1=="HONOR_GAINED") then
470 self:Display_Event("SHOWHONOR", "+"..arg2.." "..HONOR);
471 elseif (arg1=="AURA_END") then
472 self:Display_Event("SHOWFADE", "-["..arg2.."]",nil,nil,nil,nil,format(AURAREMOVEDSELF, arg2));
473 elseif (arg1=="AURA_END_HARMFUL") then
474 if (self.db.profile["SHOWFADE"]) then
475 self:Display_Event("SHOWDEBUFF", "-("..arg2..")",nil,nil,nil,nil,format(AURAREMOVEDSELF, arg2));
476 end
477 elseif (arg1=="EXTRA_ATTACKS") then
478 if ( tonumber(arg2) > 1 ) then
479 self:Display_Event("SHOWEXECUTE", self.LOCALS.ExtraAttack.."("..arg2..")");
480 else
481 self:Display_Event("SHOWEXECUTE", self.LOCALS.ExtraAttack);
482 end
483 end
484  
485 --if not in light mode, end here
486 if (not self.db.profile["LIGHTMODE"]) then
487 return;
488 end
489  
490 --Light Mode Event
491 if ( arg1 == "DAMAGE_CRIT" ) then
492 self:Display_Event("SHOWHIT", "-"..arg2, 1);
493 elseif ( arg1 == "DAMAGE" ) then
494 self:Display_Event("SHOWHIT", "-"..arg2);
495 elseif ( arg1 == "SPELL_DAMAGE" ) then
496 self:Display_Event("SHOWSPELL", "-"..arg2);
497 elseif ( arg1 == "AURA_START" ) then
498 self:Display_Event("SHOWBUFF", "["..arg2.."]");
499 elseif ( arg1 == "AURA_START_HARMFUL" ) then
500 self:Display_Event("SHOWDEBUFF", "("..arg2..")");
501 elseif ( arg1 == "HEAL" or arg1 == "PERIODIC_HEAL") then
502 --heal filter
503 if (tonumber(arg3) < tonumber(self.db.profile["HEALFILTER"])) then return end;
504 if ( UnitName("player") ~= arg2 ) then
505 self:Display_Event("SHOWHEAL", "+"..arg3, nil, nil, nil, arg2);
506 else
507 self:Display_Event("SHOWHEAL", "+"..arg3);
508 end
509 elseif ( arg1 == "HEAL_CRIT" ) then
510 --heal filter
511 if (tonumber(arg3) < tonumber(self.db.profile["HEALFILTER"])) then return end;
512 if ( UnitName("player") ~= arg2 ) then
513 self:Display_Event("SHOWHEAL", "+"..arg3, 1, nil, nil, arg2);
514 else
515 self:Display_Event("SHOWHEAL", "+"..arg3, 1);
516 end
517 elseif ( arg1 == "MANA" or arg1 == "RAGE" or arg1 == "ENERGY") then
518 if (not self.db.profile["SHOWALLPOWER"]) then
519 self:Display_Event("SHOWPOWER", "+"..arg2.." "..getglobal(arg1));
520 end
521 elseif ( arg1 == "MISS" or arg1 == "SPELL_MISSED") then
522 self:Display_Event("SHOWMISS", MISS, nil, nil, nil, nil, SCT.LOCALS.TARGET.." "..MISS);
523 elseif ( arg1 == "EVADE" or arg1 == "SPELL_EVADED") then
524 self:Display_Event("SHOWABSORB", EVADAE, nil, nil, nil, nil, YOU.." "..EVADE);
525 elseif ( arg1 == "DODGE" or arg1 == "SPELL_DODGED" ) then
526 self:Display_Event("SHOWDODGE", DODGE, nil, nil, nil, nil, YOU.." "..DODGE);
527 elseif ( arg1 == "PARRY" or arg1 == "SPELL_PARRIED") then
528 self:Display_Event("SHOWPARRY", PARRY, nil, nil, nil, nil, YOU.." "..PARRY);
529 elseif ( arg1 == "IMMUNE" or arg1 == "SPELL_IMMUNE") then
530 self:Display_Event("SHOWABSORB", IMMUNE, nil, nil, nil, nil, YOU.." "..IMMUNE);
531 elseif ( arg1 == "DEFLECT" or arg1 == "SPELL_DEFLECTED") then
532 self:Display_Event("SHOWABSORB", DEFLECT, nil, nil, nil, nil, YOU.." "..DEFLECT);
533 elseif ( arg1 == "SPELL_REFLECTED") then
534 self:Display_Event("SHOWABSORB", REFLECT, nil, nil, nil, nil, YOU.." "..REFLECT);
535 elseif ( arg1 == "BLOCK" or arg1 == "SPELL_BLOCKED") then
536 if ( arg3 ) then
537 if (arg1 == "SPELL_BLOCKED") then
538 self:Display_Event("SHOWSPELL", "-"..arg2);
539 else
540 self:Display_Event("SHOWHIT", "-"..arg2);
541 end
542 self:DisplayBlock(arg3)
543 else
544 self:Display_Event("SHOWBLOCK", BLOCK, nil, nil, nil, nil, YOU.." "..BLOCK);
545 end
546 elseif ( arg1 == "ABSORB" or arg1 == "SPELL_ABSORBED" ) then
547 if ( arg3 ) then
548 if (arg1 == "SPELL_ABSORBED") then
549 self:Display_Event("SHOWSPELL", "-"..arg2);
550 else
551 self:Display_Event("SHOWHIT", "-"..arg2);
552 end
553 self:DisplayAbsorb(arg3)
554 else
555 self:Display_Event("SHOWABSORB", ABSORB, nil, nil, nil, nil, YOU.." "..ABSORB);
556 end
557 elseif ( arg1 == "RESIST" or arg1 == "SPELL_RESISTED" ) then
558 if ( arg3 ) then
559 if (arg1 == "SPELL_RESISTED") then
560 self:Display_Event("SHOWSPELL", "-"..arg2, nil, nil, arg3);
561 else
562 self:Display_Event("SHOWHIT", "-"..arg2, nil, nil, arg3);
563 end
564 else
565 self:Display_Event("SHOWRESIST", RESIST, nil, nil, nil, nil, YOU.." "..RESIST);
566 end
567 end
568 end
569  
570 ----------------------
571 --Find a custom capture event message
572 function SCT:CustomEventSearch(arg1)
573 local strTempMessage, currentcolor, table, classfound, key, key2, class, value, i;
574 local carg1, carg2, carg3, carg4, carg5;
575 --cache it index order
576 if (SCT.CustomEvents == nil) then
577 SCT.CustomEvents = {};
578 for key, value in self:PairsByKeys(SCT.EventConfig) do
579 tinsert(SCT.CustomEvents, value);
580 end
581 end
582 for key, value in SCT.CustomEvents do
583 --default class found to true
584 classfound = true;
585 --check if they want to see it for this class
586 if (value.class) then
587 --if want to filter by class, default to false
588 classfound = false;
589 for key2, class in value.class do
590 if (strlower(UnitClass("player")) == strlower(class)) then
591 classfound = true;
592 break;
593 end
594 end
595 end
596 --if ok
597 if (classfound) then
598 for carg1, carg2, carg3, carg4, carg5 in string.gfind(arg1, value.search) do
599 strTempMessage = value.name;
600 --if there are capture args
601 if ((value.argcount) and (value.argcount > 0) and (value.argcount < 6)) then
602 table = {carg1, carg2, carg3, carg4, carg5}
603 --loop though each capture arg. if it exists replace the display position with it
604 for i = 1, value.argcount do
605 if (table[i]) then
606 strTempMessage, _ = string.gsub(strTempMessage, "*"..i, table[i]);
607 end
608 end
609 end
610 --get color
611 currentcolor = {r = 1.0, g = 1.0, b = 1.0};
612 if (value.r and value.g and value.b) then
613 currentcolor.r,currentcolor.g,currentcolor.b = value.r,value.g,value.b;
614 end
615 --set msg
616 if (value.ismsg) then value.ismsg = SCT.MSG end;
617 --play sound
618 if (value.sound) then PlaySound(value.sound) end;
619 --play soundwave
620 if (value.soundwave) then PlaySoundFile(value.soundwave) end;
621 --display
622 self:DisplayCustomEvent(strTempMessage, currentcolor, value.iscrit, value.ismsg, value.anitype);
623 return true;
624 end
625 end
626 end
627 return false;
628 end
629  
630 ----------------------
631 --Display for mainly combat events
632 --Mainly used for short messages
633 function SCT:Display_Event(option, msg1, crit, damagetype, resisted, target, msg2)
634 local rbgcolor, showcrit, showmsg, event;
635 --if option is on
636 if (self.db.profile[option]) then
637 --get options
638 rbgcolor = self.db.profile[self.COLORS_TABLE][option];
639 showcrit = self.db.profile[self.CRITS_TABLE][option];
640 showmsg = self.db.profile[self.FRAMES_TABLE][option] or 1;
641 --if damage type
642 if ((damagetype) and (self.db.profile["SPELLTYPE"])) then
643 msg1 = msg1.." ("..damagetype..")";
644 end
645 --if spell color
646 if ((damagetype) and (self.db.profile["SPELLCOLOR"])) then
647 rbgcolor = self.SpellColors[damagetype] or rbgcolor;
648 end
649 --if resisted
650 if ((resisted) and (self.db.profile["SHOWRESIST"])) then
651 msg1 = msg1.." ("..resisted.." "..ERR_FEIGN_DEATH_RESISTED..")";
652 end
653 --if target label
654 if ((target) and (self.db.profile["SHOWTARGETS"])) then
655 msg1 = msg1.." ("..target..")";
656 end
657 --if messages
658 if (showmsg == SCT.MSG) then
659 --if 2nd msg
660 if (msg2) then msg1 = msg2 end;
661 --display message
662 self:DisplayMessage( msg1, rbgcolor );
663 else
664 event = "event";
665 --set event type
666 if (option == "SHOWHIT" or option == "SHOWSPELL" or option == "SHOWHEAL" or option == "SHOWSELFHEAL") then
667 event = "damage";
668 end
669 --see if crit override
670 if (showcrit) then crit = 1 end;
671 --display
672 self:DisplayText(msg1, rbgcolor, crit, event, showmsg);
673 end
674 end
675 end
676  
677 ----------------------
678 --Display the Text based on message flag for custom events
679 function SCT:DisplayCustomEvent(msg1, color, iscrit, ismsg, anitype)
680 if (ismsg) then
681 self:DisplayMessage( msg1, color );
682 else
683 self:DisplayText(msg1 , color, iscrit, "event", 1, anitype);
684 end
685 end
686  
687 ----------------------
688 --Displays a message at the top of the screen
689 function SCT:DisplayMessage(msg, color)
690 SCT_MSG_FRAME:AddMessage(msg, color.r, color.g, color.b, 1);
691 end
692  
693 ----------------------
694 --Display text from a command line
695 function SCT:CmdDisplay(msg)
696 local message = nil;
697 local colors = nil;
698 --If there are not parameters, display useage
699 if string.len(msg) == 0 then
700 self:DisplayUseage();
701 --Get message anf colors if quotes used
702 elseif string.sub(msg,1,1) == "'" then
703 local location = string.find(string.sub(msg,2),"'")
704 if location and (location>1) then
705 message = string.sub(msg,2,location)
706 colors = string.sub(msg,location+1);
707 end
708 --Get message anf colors if single word used
709 else
710 local idx = string.find(msg," ");
711 if (idx) then
712 message = string.sub(msg,1,idx-1);
713 colors = string.sub(msg,idx+1);
714 else
715 message = msg;
716 end
717 end
718 --if they sent colors, grab them
719 local firsti, lasti, red, green, blue = nil;
720 if (colors ~= nil) then
721 firsti, lasti, red, green, blue = string.find (colors, "(%w+) (%w+) (%w+)");
722 end
723 local color = {r = 1.0, g = 1.0, b = 1.0};
724 --if they sent 3 colors use them, else use default white
725 if (red) and (green) and (blue) then
726 color.r,color.g,color.b = (tonumber(red)/10),(tonumber(green)/10),(tonumber(blue)/10);
727 end
728 self:DisplayText(message, color, nil, "event", 1);
729 end
730  
731 -------------------------
732 --Set the font of an object using msg vars
733 function SCT:SetMsgFont(object)
734 --set font
735 object:SetFont(SCT.LOCALS.FONTS[self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGFONT"]].path,
736 self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGSIZE"],
737 arrShadowOutline[self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGFONTSHADOW"]]);
738 --reset size of allow 3 messages
739 object:SetHeight(self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGSIZE"] * 4)
740 --Set Fade Duration
741 if (object.SetFadeDuration) then
742 object:SetFadeDuration(1);
743 end
744 end
745  
746 -------------------------
747 --Set the font of the built in damage font
748 function SCT:SetDmgFont()
749 if (SCT.db.profile["DMGFONT"]) then
750 DAMAGE_TEXT_FONT = SCT.LOCALS.FONTS[SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME1]["FONT"]].path;
751 end
752 end
753  
754 -------------------------
755 --Set the font of an object
756 function SCT:SetFontSize(object, font, textsize, fontshadow)
757 object:SetFont(SCT.LOCALS.FONTS[font].path, textsize, arrShadowOutline[fontshadow]);
758 end
759  
760 -------------------------
761 --Determine if a hunter is FD'ing
762 --Code taken from CTRA
763 function SCT:CheckFD(unit)
764 if ( UnitClass(unit) ~= SCT.LOCALS.HUNTER ) then
765 return;
766 end
767 local hasFD;
768 local num, buff = 0, UnitBuff(unit, 1);
769 while ( buff ) do
770 if ( buff == "Interface\\Icons\\Ability_Rogue_FeignDeath" ) then
771 hasFD = 1;
772 break;
773 end
774 num = num + 1;
775 buff = UnitBuff(unit, num+1);
776 end
777 if ( hasFD ) then
778 return true;
779 else
780 return false;
781 end
782 end
783  
784 -------------------------
785 --Return the unit if for a given target
786 function SCT:GetTargetUnit(target)
787 local unit;
788 if (target == "player") then
789 return "player";
790 end
791 if (target == UnitName('pet'))then
792 return "pet";
793 end
794 for i = 1, GetNumRaidMembers(), 1 do
795 if ( UnitName("raid" .. i) and UnitName("raid" .. i) == target ) then
796 return "raid"..i;
797 end
798 end
799 for i = 1, GetNumPartyMembers(), 1 do
800 if ( UnitName("party" .. i) and UnitName("party" .. i) == target ) then
801 return "party"..i;
802 end
803 end
804 end
805  
806 -------------------------
807 --Return the amount the target is overhealed
808 function SCT:GetOverheal(target, damage)
809 local unit = self:GetTargetUnit(target);
810 if unit then
811 local lost = UnitHealthMax(unit)-UnitHealth(unit);
812 local overheal = damage - lost;
813 if (overheal > 0) then
814 damage = lost.." {"..overheal.."}";
815 end
816 end
817 return damage;
818 end
819  
820 -------------------------
821 --Regsiter SCT with other mods
822 function SCT:RegisterOtherMods()
823 -- myAddOns support
824 if(myAddOnsFrame_Register) then
825 local SCTDetails = {
826 name = "sct",
827 version = SCT.Version,
828 optionsframe = "SCTOptions",
829 category = MYADDONS_CATEGORY_COMBAT
830 };
831 myAddOnsFrame_Register(SCTDetails);
832 end
833  
834 --Cosmos support
835 if ( EarthFeature_AddButton ) then
836 EarthFeature_AddButton(
837 {
838 id="SCT";
839 name=SCT.LOCALS.SCT_CB_NAME;
840 text=SCT.LOCALS.SCT_CB_NAME;
841 subtext=SCT.LOCALS.SCT_CB_SHORT_DESC;
842 helptext=SCT.LOCALS.SCT_CB_LONG_DESC;
843 icon=SCT.LOCALS.SCT_CB_ICON;
844 callback=SCT.ShowMenu;
845 }
846 );
847 elseif (Cosmos_RegisterButton) then
848 Cosmos_RegisterButton (
849 SCT.LOCALS.SCT_CB_NAME,
850 SCT.LOCALS.SCT_CB_SHORT_DESC,
851 SCT.LOCALS.SCT_CB_LONG_DESC,
852 SCT.LOCALS.SCT_CB_ICON,
853 SCT.ShowMenu,
854 function()
855 return true;
856 end
857 );
858 default_config.ENABLED = 0;
859 end
860  
861 -- Add to CTMod Control panel if available
862 if ( CT_RegisterMod ) then
863 CT_RegisterMod(SCT.LOCALS.CB_NAME, nil, 5, SCT.LOCALS.CB_ICON, SCT.LOCALS.CB_LONG_DESC, "switch", nil, SCT.ShowMenu);
864 end
865  
866 end
867  
868 -------------------------
869 --Get the default Config
870 function SCT:GetDefaultConfig()
871 local default = {
872 ["VERSION"] = SCT.Version,
873 ["ENABLED"] = true,
874 ["SHOWHIT"] = 1,
875 ["SHOWMISS"] = 1,
876 ["SHOWDODGE"] = 1,
877 ["SHOWPARRY"] = 1,
878 ["SHOWBLOCK"] = 1,
879 ["SHOWSPELL"] = 1,
880 ["SHOWHEAL"] = 1,
881 ["SHOWRESIST"] = 1,
882 ["SHOWDEBUFF"] = 1,
883 ["SHOWBUFF"] = 1,
884 ["SHOWFADE"] = false,
885 ["SHOWABSORB"] = 1,
886 ["SHOWLOWHP"] = 1,
887 ["SHOWLOWMANA"] = 1,
888 ["SHOWPOWER"] = 1,
889 ["SHOWCOMBAT"] = false,
890 ["SHOWCOMBOPOINTS"] = false,
891 ["SHOWHONOR"] = 1,
892 ["SHOWEXECUTE"] = 1,
893 ["SHOWREP"] = 1,
894 ["SHOWSELFHEAL"] = 1,
895 ["SHOWSKILL"] = 1,
896 ["SHOWTARGETS"] = 1,
897 ["SHOWSELF"] = false,
898 ["SHOWOVERHEAL"] = 1,
899 ["STICKYCRIT"] = 1,
900 ["FLASHCRIT"] = 1,
901 ["SPELLTYPE"] = false,
902 ["SPELLCOLOR"] = false,
903 ["DMGFONT"] = false,
904 ["SHOWALLPOWER"] = false,
905 ["FPSMODE"] = false,
906 ["ANIMATIONSPEED"] = 15,
907 ["MOVEMENT"] = 2,
908 ["LOWHP"] = 40,
909 ["LOWMANA"] = 40,
910 ["HEALFILTER"] = 50,
911 ["PLAYSOUND"] = 1,
912 ["CUSTOMEVENTS"] = 1,
913 ["LIGHTMODE"] = false,
914 [SCT.FRAMES_DATA_TABLE] = {
915 [SCT.FRAME1] = {
916 ["FONT"] = 1,
917 ["FONTSHADOW"] = 2,
918 ["ALPHA"] = 100,
919 ["ANITYPE"] = 1,
920 ["ANISIDETYPE"] = 1,
921 ["XOFFSET"] = 0,
922 ["YOFFSET"] = 0,
923 ["DIRECTION"] = false,
924 ["TEXTSIZE"] = 24,
925 },
926 [SCT.FRAME2] = {
927 ["FONT"] = 1,
928 ["FONTSHADOW"] = 2,
929 ["ALPHA"] = 100,
930 ["ANITYPE"] = 1,
931 ["ANISIDETYPE"] = 1,
932 ["XOFFSET"] = 0,
933 ["YOFFSET"] = -150,
934 ["DIRECTION"] = true,
935 ["TEXTSIZE"] = 24,
936 },
937 [SCT.MSG] = {
938 ["MSGFADE"] = 1.5,
939 ["MSGFONT"] = 1,
940 ["MSGFONTSHADOW"] = 2,
941 ["MSGSIZE"] = 24,
942 ["MSGYOFFSET"] = -280,
943 ["MSGXOFFSET"] = 0,
944 }
945 },
946 [SCT.COLORS_TABLE] = {
947 ["SHOWHIT"] = {r = 1.0, g = 0.0, b = 0.0},
948 ["SHOWMISS"] = {r = 0.0, g = 0.0, b = 1.0},
949 ["SHOWDODGE"] = {r = 0.0, g = 0.0, b = 1.0},
950 ["SHOWPARRY"] = {r = 0.0, g = 0.0, b = 1.0},
951 ["SHOWBLOCK"] = {r = 0.0, g = 0.0, b = 1.0},
952 ["SHOWSPELL"] = {r = 0.5, g = 0.0, b = 0.5},
953 ["SHOWHEAL"] = {r = 0.0, g = 1.0, b = 0.0},
954 ["SHOWRESIST"] = {r = 0.5, g = 0.0, b = 0.5},
955 ["SHOWDEBUFF"] = {r = 0.0, g = 0.5, b = 0.5},
956 ["SHOWABSORB"] = {r = 1.0, g = 1.0, b = 0.0},
957 ["SHOWLOWHP"] = {r = 1.0, g = 0.5, b = 0.5},
958 ["SHOWLOWMANA"] = {r = 0.5, g = 0.5, b = 1.0},
959 ["SHOWPOWER"] = {r = 1.0, g = 1.0, b = 0.0},
960 ["SHOWCOMBAT"] = {r = 1.0, g = 1.0, b = 1.0},
961 ["SHOWCOMBOPOINTS"] = {r = 1.0, g = 0.5, b = 0.0},
962 ["SHOWHONOR"] = {r = 0.5, g = 0.5, b = 0.7},
963 ["SHOWBUFF"] = {r = 0.7, g = 0.7, b = 0.0},
964 ["SHOWFADE"] = {r = 0.7, g = 0.7, b = 0.0},
965 ["SHOWEXECUTE"] = {r = 0.7, g = 0.7, b = 0.7},
966 ["SHOWREP"] = {r = 0.5, g = 0.5, b = 1},
967 ["SHOWSELFHEAL"] = {r = 0, g = 0.7, b = 0},
968 ["SHOWSKILL"] = {r = 0, g = 0, b = 0.7}
969 },
970 [SCT.CRITS_TABLE] = {
971 ["SHOWEXECUTE"] = 1,
972 ["SHOWLOWHP"] = 1,
973 ["SHOWLOWMANA"] = 1,
974 },
975 [SCT.FRAMES_TABLE] = {
976 ["SHOWHIT"] = SCT.FRAME1,
977 ["SHOWMISS"] = SCT.FRAME1,
978 ["SHOWDODGE"] = SCT.FRAME1,
979 ["SHOWPARRY"] = SCT.FRAME1,
980 ["SHOWBLOCK"] = SCT.FRAME1,
981 ["SHOWSPELL"] = SCT.FRAME1,
982 ["SHOWHEAL"] = SCT.FRAME2,
983 ["SHOWRESIST"] = SCT.FRAME1,
984 ["SHOWDEBUFF"] = SCT.FRAME1,
985 ["SHOWABSORB"] = SCT.FRAME1,
986 ["SHOWLOWHP"] = SCT.FRAME1,
987 ["SHOWLOWMANA"] = SCT.FRAME1,
988 ["SHOWPOWER"] = SCT.FRAME2,
989 ["SHOWCOMBAT"] = SCT.FRAME2,
990 ["SHOWCOMBOPOINTS"] = SCT.FRAME1,
991 ["SHOWHONOR"] = SCT.MSG,
992 ["SHOWBUFF"] = SCT.MSG,
993 ["SHOWFADE"] = SCT.FRAME1,
994 ["SHOWEXECUTE"] = SCT.FRAME1,
995 ["SHOWREP"] = SCT.MSG,
996 ["SHOWSELFHEAL"] = SCT.FRAME2 ,
997 ["SHOWSKILL"] = SCT.FRAME2
998 }
999 };
1000 return default;
1001 end
1002  
1003 -------------------------
1004 --Regsiter SCT with all events
1005 function SCT:RegisterSelfEvents()
1006  
1007 -- Register Main Events
1008 self:RegisterEvent("UNIT_HEALTH", "OnEvent");
1009 self:RegisterEvent("UNIT_MANA", "OnEvent");
1010 self:RegisterEvent("UNIT_ENERGY", "OnEvent");
1011 self:RegisterEvent("UNIT_RAGE", "OnEvent");
1012 self:RegisterEvent("UNIT_DISPLAYPOWER", "OnEvent");
1013 self:RegisterEvent("PLAYER_REGEN_ENABLED", "OnEvent");
1014 self:RegisterEvent("PLAYER_REGEN_DISABLED", "OnEvent");
1015 self:RegisterEvent("PLAYER_COMBO_POINTS", "OnEvent");
1016 self:RegisterEvent("COMBAT_TEXT_UPDATE", "BlizzardCombatTextEvent");
1017  
1018 --unsupported chat events:
1019 self:RegisterEvent("CHAT_MSG_SKILL", "OnEvent");
1020  
1021 --events need for light and normal mode for Parserlib
1022 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_SELF_BUFF", SCT.ParseCombat) ;
1023  
1024 --if in light mode, end here
1025 if (self.db.profile["LIGHTMODE"]) then
1026 return;
1027 end
1028  
1029 --events only needed in normal mode for Parserlib
1030 parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_SELF_HITS", SCT.ParseCombat) ;
1031 parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS", SCT.ParseCombat) ;
1032 parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES", SCT.ParseCombat) ;
1033 parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS", SCT.ParseCombat) ;
1034 parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES", SCT.ParseCombat) ;
1035 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_SELF_DAMAGE", SCT.ParseCombat) ;
1036 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE", SCT.ParseCombat) ;
1037 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF", SCT.ParseCombat) ;
1038 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE", SCT.ParseCombat) ;
1039 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE", SCT.ParseCombat) ;
1040 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS", SCT.ParseCombat) ;
1041 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE", SCT.ParseCombat) ;
1042 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS", SCT.ParseCombat) ;
1043 parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS", SCT.ParseCombat) ;
1044  
1045 --searchable added events
1046 local key, value
1047 for key, value in SCT.EventList do
1048 self:RegisterEvent(value, "OnEvent");
1049 end
1050 end
1051  
1052 ------------------------------
1053 ---Sort a table by its keys.
1054 ---stolen from http://www.lua.org/pil/19.3.html
1055 function SCT:PairsByKeys (t, f)
1056 local a = {}
1057 for n in pairs(t) do table.insert(a, n) end
1058 table.sort(a, f)
1059 local i = 0 -- iterator variable
1060 local iter = function () -- iterator function
1061 i = i + 1
1062 if a[i] == nil then return nil
1063 else return a[i], t[a[i]]
1064 end
1065 end
1066 return iter
1067 end
1068  
1069 ------------------------------
1070 --Create event to load up correct font
1071 --when another mod loads. Incase they try to change
1072 --the font (super inspect, etc...)
1073 SCT:RegisterEvent("ADDON_LOADED", SCT.SetDmgFont);