vanilla-wow-addons – Rev 1
?pathlinks?
--[[
****************************************************************
Scrolling Combat Text 5.0
Author: Grayhoof
****************************************************************
Official Site:
http://grayhoof.wowinterface.com
****************************************************************]]
SCT = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceDB-2.0", "AceConsole-2.0", "AceHook-2.0");
--embedded libs
local parser = ParserLib:GetInstance("1.1")
--Table Constants
SCT.COLORS_TABLE = "COLORS";
SCT.CRITS_TABLE = "CRITS";
SCT.FRAMES_TABLE = "FRAMES";
SCT.FRAMES_DATA_TABLE = "FRAMESDATA";
SCT.FRAME1 = 1;
SCT.FRAME2 = 2;
SCT.MSG = 10;
-- local constants, use lowercase sct
local sct_LastHPPercent = 0;
local sct_LastTargetHPPercent = 0;
local sct_LastManaPercent = 0;
local sct_LastManaFull = 99999;
local arrPowerStrings = {
[0] = MANA,
[1] = RAGE,
[3] = ENERGY
}
local arrShadowOutline = {
[1] = "",
[2] = "OUTLINE",
[3] = "THICKOUTLINE"
}
local arrSpellColors = {
[SPELL_SCHOOL0_CAP] = {r=1,g=0,b=0},
[SPELL_SCHOOL1_CAP] = {r=1,g=1,b=0},
[SPELL_SCHOOL2_CAP] = {r=1,g=.3,b=0},
[SPELL_SCHOOL3_CAP] = {r=.5,g=1,b=.2},
[SPELL_SCHOOL4_CAP] = {r=.4,g=.6,b=.9},
[SPELL_SCHOOL5_CAP] = {r=.4,g=.4,b=.5},
[SPELL_SCHOOL6_CAP] = {r=.8,g=.8,b=1},
}
SCT.SpellColors = arrSpellColors;
----------------------
--Called on login
function SCT:OnEnable()
self:RegisterSelfEvents();
end
----------------------
-- called on standby
function SCT:OnDisable()
self:DisableAll()
end
----------------------
-- Disable all events
function SCT:DisableAll()
-- no more events to handle
parser:UnregisterAllEvents("sct")
self:UnregisterAllEvents()
end
----------------------
-- Show the Option Menu
function SCT:ShowMenu()
local loaded, message = LoadAddOn("sct_options");
if (loaded) then
PlaySound("igMainMenuOpen");
ShowUIPanel(SCTOptions);
else
PlaySound("TellMessage");
SCT:Print(SCT.LOCALS.Load_Error.." "..message);
end
end
----------------------
--Hide the Option Menu
function SCT:HideMenu()
PlaySound("igMainMenuClose");
HideUIPanel(SCTOptions);
end
----------------------
--Called when Addon loaded
function SCT:OnInitialize()
--default settings
local default_config = self:GetDefaultConfig();
--slash command setup
local main = {
type="group",
args = {
menu = {
name = "Menu", type = 'execute',
desc = "Display SCT Option Menu",
func = function()
self:ShowMenu();
end
},
reset = {
name = "Reset", type = 'execute',
desc = "Reset SCT Options to default",
func = function()
self:Reset();
end
}
}
}
local menu = {
type = 'execute',
desc = "Display SCT Option Menu",
func = function()
self:ShowMenu();
end
}
local reset = {
type = 'execute',
desc = "Reset SCT Options to default",
func = function()
self:Reset();
end
}
local cmd = {
type = 'text',
name = "Display",
usage = SCT.LOCALS.DISPLAY_USEAGE,
desc = "Display a message using SCT",
get = false,
set = function(x)
self:CmdDisplay(x);
end
}
--hook chat frame if using event debug
if SCT.EventDebug then
for i = 1, 7, 1 do
self:Hook(getglobal("ChatFrame" .. i), "AddMessage")
end
end
self:RegisterDB("SCT_CONFIG")
self:RegisterDefaults('profile', default_config )
self:RegisterChatCommand({"/sct"}, main)
self:RegisterChatCommand({"/sctmenu"}, menu)
self:RegisterChatCommand({"/sctreset"}, reset)
self:RegisterChatCommand({"/sctdisplay"}, cmd)
--set to profile by char by default
if not self.db.char.notFirstTime then
self.db.char.notFirstTime = true;
self:SetProfile("char");
end
--register with other mods
self:RegisterOtherMods()
-- Add my options frame to the global UI panel list
UIPanelWindows["SCTOptions"] = {area = "center", pushable = 0};
--setup animations
self:AniInit();
--Set Enabled State
if (self.db.profile["ENABLED"]) then
self:ToggleActive(true);
self:Print(SCT.LOCALS.STARTUP);
else
self:ToggleActive(false);
end
end
----------------------
--Hook Function to show event
function SCT:AddMessage(frame, text, r, g, b, id)
self.hooks[frame].AddMessage.orig(frame, text.." |cff00ff00["..tostring(event).."]|r", r, g, b, id)
end
----------------------
--Reset everything to default
function SCT:Reset()
self:ResetDB("profile")
self:HideMenu();
self:ShowMenu();
self:ShowExample();
self:Print(SCT.LOCALS.PROFILE_NEW..AceLibrary("AceDB-2.0").CHAR_ID);
end
----------------------
--Get a value from player config
function SCT:Get(option, table)
if (table) then
return self.db.profile[table][option];
else
return self.db.profile[option];
end
end
----------------------
--Set a value in player config
function SCT:Set(option, value, table)
if (table) then
self.db.profile[table][option] = value;
else
self.db.profile[option] = value;
end
end
----------------------
--Display for any partial blocks
function SCT:DisplayBlock(blocked)
SCT:Display_Event("SHOWBLOCK", BLOCK.." ("..blocked..")");
end
----------------------
--Display for any partial absorbs
function SCT:DisplayAbsorb(absorbed)
SCT:Display_Event("SHOWABSORB", ABSORB.." ("..absorbed..")");
end
----------------------
-- Event Handler
-- this function parses events that are printed in the combat
-- chat window then displays the health changes
function SCT:OnEvent()
--Player Health
if (event == "UNIT_HEALTH") then
if (arg1 == "player") then
local warnlevel = self.db.profile["LOWHP"] / 100;
local HPPercent = UnitHealth("player") / UnitHealthMax("player");
if (HPPercent < warnlevel) and (sct_LastHPPercent >= warnlevel) and (not SCT:CheckFD("player")) then
if (self.db.profile["PLAYSOUND"] and self.db.profile["SHOWLOWHP"]) then
PlaySoundFile("Sound\\Spells\\bind2_Impact_Base.wav")
end
self:Display_Event("SHOWLOWHP", SCT.LOCALS.LowHP.." ("..UnitHealth("player")..")");
end
sct_LastHPPercent = HPPercent;
return;
end
return;
--Player Mana
elseif (event == "UNIT_MANA") or (event == "UNIT_RAGE") or (event == "UNIT_ENERGY")then
if (arg1 == "player") and (UnitPowerType("player") == 0)then
local warnlevel = self.db.profile["LOWMANA"] / 100;
local ManaPercent = UnitMana("player") / UnitManaMax("player");
if (ManaPercent < warnlevel) and (sct_LastManaPercent >= warnlevel) and (not SCT:CheckFD("player")) then
if (self.db.profile["PLAYSOUND"] and self.db.profile["SHOWLOWMANA"]) then
PlaySoundFile("Sound\\Spells\\ShaysBell.wav");
end
SCT:Display_Event("SHOWLOWMANA", SCT.LOCALS.LowMana.." ("..UnitMana("player")..")");
end
sct_LastManaPercent = ManaPercent;
end
if (arg1 == "player") and (self.db.profile["SHOWALLPOWER"]) then
local ManaFull = UnitMana("player");
if (ManaFull > sct_LastManaFull) then
self:Display_Event("SHOWPOWER", "+"..ManaFull-sct_LastManaFull.." "..arrPowerStrings[UnitPowerType("player")]);
end
sct_LastManaFull = ManaFull;
end
return;
--Power Change
elseif (event == "UNIT_DISPLAYPOWER") then
sct_LastManaFull = UnitMana("player");
return;
--Player Combat
elseif (event =="PLAYER_REGEN_DISABLED") then
self:Display_Event("SHOWCOMBAT", SCT.LOCALS.Combat);
return;
--Player NoCombat
elseif (event =="PLAYER_REGEN_ENABLED") then
self:Display_Event("SHOWCOMBAT", SCT.LOCALS.NoCombat);
return;
--Player Combo Points
elseif (event == "PLAYER_COMBO_POINTS") then
local sct_CP = GetComboPoints();
if (sct_CP ~= 0) then
local sct_CP_Message = sct_CP.." "..SCT.LOCALS.ComboPoint;
if (sct_CP == 5) then
sct_CP_Message = sct_CP_Message.." "..SCT.LOCALS.FiveCPMessage;
end;
self:Display_Event("SHOWCOMBOPOINTS", sct_CP_Message);
end
return;
--All other combat events
elseif (arg1) then
self:ParseCombat(arg1);
end
end
----------------------
-- Displays Parsed info based on type
function SCT:ParseCombat(info)
--self doesn't work here because of the call from ParserLib
local self = SCT;
--custom search first
if (self.db.profile["CUSTOMEVENTS"]) and (not SCT.db.profile["LIGHTMODE"]) and (self:CustomEventSearch(arg1) == true) then
return;
end
--Player Skill Gains Here, since its unsupported
if (event == "CHAT_MSG_SKILL") then
local target, rank = parser:Deformat(arg1, SKILL_RANK_UP);
if target then
self:Display_Event("SHOWSKILL", target..": "..rank);
return;
end
return;
end
--if its not a ParserLib Event, then end
if (type(info) ~= "table") then
return;
end
--outgoing heals, done first since its only thing blizzard events don't do
if (info.type == "heal" and info.victim ~= ParserLib_SELF) then
--heal filter
if (info.amount < self.db.profile["HEALFILTER"]) then return end;
--outgoing heals, ignore dots
if (info.source == ParserLib_SELF and not info.isDOT) then
if (self.db.profile["SHOWOVERHEAL"]) then
info.amount = self:GetOverheal(info.victim, info.amount);
end
self:Display_Event("SHOWSELFHEAL", info.victim..": +"..info.amount, info.isCrit);
end
return;
end
--if in light mode, end here
if (self.db.profile["LIGHTMODE"]) then
return;
end
-- Environmental
if (info.type == "environment") then
if (info.victim == ParserLib_SELF) then
if( info.damageType == "fire" or info.damageType == "lava" or info.damageType == "slime") then
self:Display_Event("SHOWSPELL", "-"..info.amount, nil, nil, info.amountResist );
else
self:Display_Event("SHOWHIT", "-"..info.amount);
end
if(info.amountAbsorb) then
self:DisplayAbsorb(info.amountAbsorb);
end
end
--Hits (melee, spell, etc..)
elseif (info.type == "hit") then
if (info.victim == ParserLib_SELF) then
if (info.skill == ParserLib_MELEE) then
self:Display_Event("SHOWHIT", "-"..info.amount, info.isCrit);
else
self:Display_Event("SHOWSPELL", "-"..info.amount, info.isCrit, info.element, info.amountResist);
end
if( info.amountAbsorb) then
self:DisplayAbsorb(info.amountAbsorb);
end
if( info.amountBlock) then
self:DisplayBlock(info.amountBlock);
end
end
--Miss Events
elseif (info.type == "miss") then
if (info.victim == ParserLib_SELF) then
if (info.missType == "miss") then
self:Display_Event("SHOWMISS", MISS, nil, nil, nil, nil, SCT.LOCALS.TARGET.." "..MISS);
elseif (info.missType == "dodge") then
self:Display_Event("SHOWDODGE", DODGE, nil, nil, nil, nil, YOU.." "..DODGE);
elseif (info.missType == "block") then
self:Display_Event("SHOWBLOCK", BLOCK, nil, nil, nil, nil, YOU.." "..BLOCK);
elseif (info.missType == "deflect") then
self:Display_Event("SHOWABSORB", DEFLECT, nil, nil, nil, nil, YOU.." "..DEFLECT);
elseif (info.missType == "immune") then
self:Display_Event("SHOWABSORB", IMMUNE, nil, nil, nil, nil, YOU.." "..IMMUNE);
elseif (info.missType == "evade") then
self:Display_Event("SHOWABSORB", EVADAE, nil, nil, nil, nil, YOU.." "..EVADE);
elseif (info.missType == "parry") then
self:Display_Event("SHOWPARRY", PARRY, nil, nil, nil, nil, YOU.." "..PARRY);
elseif (info.missType == "resist") then
self:Display_Event("SHOWRESIST", RESIST, nil, nil, nil, nil, YOU.." "..RESIST);
elseif (info.missType == "reflect") then
self:Display_Event("SHOWABSORB", REFLECT, nil, nil, nil, nil, YOU.." "..REFLECT);
elseif (info.missType == "absorb") then
self:Display_Event("SHOWABSORB", ABSORB, nil, nil, nil, nil, YOU.." "..ABSORB);
end
end
--Gains
elseif (info.type == "gain") then
if (info.victim == ParserLib_SELF) and (not self.db.profile["SHOWALLPOWER"]) then
self:Display_Event("SHOWPOWER", "+"..info.amount.." "..info.attribute);
end
--Leech
elseif (info.type == "leech") and (not self.db.profile["SHOWALLPOWER"]) then
if (info.sourceGained == ParserLib_SELF) then
self:Display_Event("SHOWPOWER", "+"..info.amountGained.." "..info.attributeGained);
end
--buff
elseif (info.type == "buff") then
if (info.victim == ParserLib_SELF) then
self:Display_Event("SHOWBUFF", "["..info.skill.."]", nil, nil, nil, nil, arg1);
end
--debuff
elseif (info.type == "debuff") then
if (info.victim == ParserLib_SELF) then
if (info.amountRank) then
self:Display_Event("SHOWDEBUFF", "("..info.skill.." "..info.amountRank..")", nil, nil, nil, nil, arg1);
else
self:Display_Event("SHOWDEBUFF", "("..info.skill..")", nil, nil, nil, nil, arg1);
end
end
--healing in/out
elseif (info.type == "heal") then
--heal filter
if (info.amount < self.db.profile["HEALFILTER"]) then return end;
--self heals
if (info.victim == ParserLib_SELF and info.source == ParserLib_SELF) then
if (self.db.profile["SHOWOVERHEAL"]) then
info.amount = self:GetOverheal("player", info.amount);
end
self:Display_Event("SHOWHEAL", "+"..info.amount, info.isCrit, nil, nil, info.skill);
--incoming heals
elseif (info.victim == ParserLib_SELF) then
self:Display_Event("SHOWHEAL", "+"..info.amount, info.isCrit, nil, nil, info.source);
end
end
end
----------------------
--Handle Blizzard events
function SCT:BlizzardCombatTextEvent()
--Normal Events
if (arg1=="SPELL_ACTIVE") then
self:Display_Event("SHOWEXECUTE", arg2.."!");
elseif (arg1=="FACTION") then
if ( tonumber(arg3) < 0 ) then
self:Display_Event("SHOWREP", "-"..arg3.." "..REPUTATION.." ("..arg2..")");
else
self:Display_Event("SHOWREP", "+"..arg3.." "..REPUTATION.." ("..arg2..")");
end
elseif (arg1=="HONOR_GAINED") then
self:Display_Event("SHOWHONOR", "+"..arg2.." "..HONOR);
elseif (arg1=="AURA_END") then
self:Display_Event("SHOWFADE", "-["..arg2.."]",nil,nil,nil,nil,format(AURAREMOVEDSELF, arg2));
elseif (arg1=="AURA_END_HARMFUL") then
if (self.db.profile["SHOWFADE"]) then
self:Display_Event("SHOWDEBUFF", "-("..arg2..")",nil,nil,nil,nil,format(AURAREMOVEDSELF, arg2));
end
elseif (arg1=="EXTRA_ATTACKS") then
if ( tonumber(arg2) > 1 ) then
self:Display_Event("SHOWEXECUTE", self.LOCALS.ExtraAttack.."("..arg2..")");
else
self:Display_Event("SHOWEXECUTE", self.LOCALS.ExtraAttack);
end
end
--if not in light mode, end here
if (not self.db.profile["LIGHTMODE"]) then
return;
end
--Light Mode Event
if ( arg1 == "DAMAGE_CRIT" ) then
self:Display_Event("SHOWHIT", "-"..arg2, 1);
elseif ( arg1 == "DAMAGE" ) then
self:Display_Event("SHOWHIT", "-"..arg2);
elseif ( arg1 == "SPELL_DAMAGE" ) then
self:Display_Event("SHOWSPELL", "-"..arg2);
elseif ( arg1 == "AURA_START" ) then
self:Display_Event("SHOWBUFF", "["..arg2.."]");
elseif ( arg1 == "AURA_START_HARMFUL" ) then
self:Display_Event("SHOWDEBUFF", "("..arg2..")");
elseif ( arg1 == "HEAL" or arg1 == "PERIODIC_HEAL") then
--heal filter
if (tonumber(arg3) < tonumber(self.db.profile["HEALFILTER"])) then return end;
if ( UnitName("player") ~= arg2 ) then
self:Display_Event("SHOWHEAL", "+"..arg3, nil, nil, nil, arg2);
else
self:Display_Event("SHOWHEAL", "+"..arg3);
end
elseif ( arg1 == "HEAL_CRIT" ) then
--heal filter
if (tonumber(arg3) < tonumber(self.db.profile["HEALFILTER"])) then return end;
if ( UnitName("player") ~= arg2 ) then
self:Display_Event("SHOWHEAL", "+"..arg3, 1, nil, nil, arg2);
else
self:Display_Event("SHOWHEAL", "+"..arg3, 1);
end
elseif ( arg1 == "MANA" or arg1 == "RAGE" or arg1 == "ENERGY") then
if (not self.db.profile["SHOWALLPOWER"]) then
self:Display_Event("SHOWPOWER", "+"..arg2.." "..getglobal(arg1));
end
elseif ( arg1 == "MISS" or arg1 == "SPELL_MISSED") then
self:Display_Event("SHOWMISS", MISS, nil, nil, nil, nil, SCT.LOCALS.TARGET.." "..MISS);
elseif ( arg1 == "EVADE" or arg1 == "SPELL_EVADED") then
self:Display_Event("SHOWABSORB", EVADAE, nil, nil, nil, nil, YOU.." "..EVADE);
elseif ( arg1 == "DODGE" or arg1 == "SPELL_DODGED" ) then
self:Display_Event("SHOWDODGE", DODGE, nil, nil, nil, nil, YOU.." "..DODGE);
elseif ( arg1 == "PARRY" or arg1 == "SPELL_PARRIED") then
self:Display_Event("SHOWPARRY", PARRY, nil, nil, nil, nil, YOU.." "..PARRY);
elseif ( arg1 == "IMMUNE" or arg1 == "SPELL_IMMUNE") then
self:Display_Event("SHOWABSORB", IMMUNE, nil, nil, nil, nil, YOU.." "..IMMUNE);
elseif ( arg1 == "DEFLECT" or arg1 == "SPELL_DEFLECTED") then
self:Display_Event("SHOWABSORB", DEFLECT, nil, nil, nil, nil, YOU.." "..DEFLECT);
elseif ( arg1 == "SPELL_REFLECTED") then
self:Display_Event("SHOWABSORB", REFLECT, nil, nil, nil, nil, YOU.." "..REFLECT);
elseif ( arg1 == "BLOCK" or arg1 == "SPELL_BLOCKED") then
if ( arg3 ) then
if (arg1 == "SPELL_BLOCKED") then
self:Display_Event("SHOWSPELL", "-"..arg2);
else
self:Display_Event("SHOWHIT", "-"..arg2);
end
self:DisplayBlock(arg3)
else
self:Display_Event("SHOWBLOCK", BLOCK, nil, nil, nil, nil, YOU.." "..BLOCK);
end
elseif ( arg1 == "ABSORB" or arg1 == "SPELL_ABSORBED" ) then
if ( arg3 ) then
if (arg1 == "SPELL_ABSORBED") then
self:Display_Event("SHOWSPELL", "-"..arg2);
else
self:Display_Event("SHOWHIT", "-"..arg2);
end
self:DisplayAbsorb(arg3)
else
self:Display_Event("SHOWABSORB", ABSORB, nil, nil, nil, nil, YOU.." "..ABSORB);
end
elseif ( arg1 == "RESIST" or arg1 == "SPELL_RESISTED" ) then
if ( arg3 ) then
if (arg1 == "SPELL_RESISTED") then
self:Display_Event("SHOWSPELL", "-"..arg2, nil, nil, arg3);
else
self:Display_Event("SHOWHIT", "-"..arg2, nil, nil, arg3);
end
else
self:Display_Event("SHOWRESIST", RESIST, nil, nil, nil, nil, YOU.." "..RESIST);
end
end
end
----------------------
--Find a custom capture event message
function SCT:CustomEventSearch(arg1)
local strTempMessage, currentcolor, table, classfound, key, key2, class, value, i;
local carg1, carg2, carg3, carg4, carg5;
--cache it index order
if (SCT.CustomEvents == nil) then
SCT.CustomEvents = {};
for key, value in self:PairsByKeys(SCT.EventConfig) do
tinsert(SCT.CustomEvents, value);
end
end
for key, value in SCT.CustomEvents do
--default class found to true
classfound = true;
--check if they want to see it for this class
if (value.class) then
--if want to filter by class, default to false
classfound = false;
for key2, class in value.class do
if (strlower(UnitClass("player")) == strlower(class)) then
classfound = true;
break;
end
end
end
--if ok
if (classfound) then
for carg1, carg2, carg3, carg4, carg5 in string.gfind(arg1, value.search) do
strTempMessage = value.name;
--if there are capture args
if ((value.argcount) and (value.argcount > 0) and (value.argcount < 6)) then
table = {carg1, carg2, carg3, carg4, carg5}
--loop though each capture arg. if it exists replace the display position with it
for i = 1, value.argcount do
if (table[i]) then
strTempMessage, _ = string.gsub(strTempMessage, "*"..i, table[i]);
end
end
end
--get color
currentcolor = {r = 1.0, g = 1.0, b = 1.0};
if (value.r and value.g and value.b) then
currentcolor.r,currentcolor.g,currentcolor.b = value.r,value.g,value.b;
end
--set msg
if (value.ismsg) then value.ismsg = SCT.MSG end;
--play sound
if (value.sound) then PlaySound(value.sound) end;
--play soundwave
if (value.soundwave) then PlaySoundFile(value.soundwave) end;
--display
self:DisplayCustomEvent(strTempMessage, currentcolor, value.iscrit, value.ismsg, value.anitype);
return true;
end
end
end
return false;
end
----------------------
--Display for mainly combat events
--Mainly used for short messages
function SCT:Display_Event(option, msg1, crit, damagetype, resisted, target, msg2)
local rbgcolor, showcrit, showmsg, event;
--if option is on
if (self.db.profile[option]) then
--get options
rbgcolor = self.db.profile[self.COLORS_TABLE][option];
showcrit = self.db.profile[self.CRITS_TABLE][option];
showmsg = self.db.profile[self.FRAMES_TABLE][option] or 1;
--if damage type
if ((damagetype) and (self.db.profile["SPELLTYPE"])) then
msg1 = msg1.." ("..damagetype..")";
end
--if spell color
if ((damagetype) and (self.db.profile["SPELLCOLOR"])) then
rbgcolor = self.SpellColors[damagetype] or rbgcolor;
end
--if resisted
if ((resisted) and (self.db.profile["SHOWRESIST"])) then
msg1 = msg1.." ("..resisted.." "..ERR_FEIGN_DEATH_RESISTED..")";
end
--if target label
if ((target) and (self.db.profile["SHOWTARGETS"])) then
msg1 = msg1.." ("..target..")";
end
--if messages
if (showmsg == SCT.MSG) then
--if 2nd msg
if (msg2) then msg1 = msg2 end;
--display message
self:DisplayMessage( msg1, rbgcolor );
else
event = "event";
--set event type
if (option == "SHOWHIT" or option == "SHOWSPELL" or option == "SHOWHEAL" or option == "SHOWSELFHEAL") then
event = "damage";
end
--see if crit override
if (showcrit) then crit = 1 end;
--display
self:DisplayText(msg1, rbgcolor, crit, event, showmsg);
end
end
end
----------------------
--Display the Text based on message flag for custom events
function SCT:DisplayCustomEvent(msg1, color, iscrit, ismsg, anitype)
if (ismsg) then
self:DisplayMessage( msg1, color );
else
self:DisplayText(msg1 , color, iscrit, "event", 1, anitype);
end
end
----------------------
--Displays a message at the top of the screen
function SCT:DisplayMessage(msg, color)
SCT_MSG_FRAME:AddMessage(msg, color.r, color.g, color.b, 1);
end
----------------------
--Display text from a command line
function SCT:CmdDisplay(msg)
local message = nil;
local colors = nil;
--If there are not parameters, display useage
if string.len(msg) == 0 then
self:DisplayUseage();
--Get message anf colors if quotes used
elseif string.sub(msg,1,1) == "'" then
local location = string.find(string.sub(msg,2),"'")
if location and (location>1) then
message = string.sub(msg,2,location)
colors = string.sub(msg,location+1);
end
--Get message anf colors if single word used
else
local idx = string.find(msg," ");
if (idx) then
message = string.sub(msg,1,idx-1);
colors = string.sub(msg,idx+1);
else
message = msg;
end
end
--if they sent colors, grab them
local firsti, lasti, red, green, blue = nil;
if (colors ~= nil) then
firsti, lasti, red, green, blue = string.find (colors, "(%w+) (%w+) (%w+)");
end
local color = {r = 1.0, g = 1.0, b = 1.0};
--if they sent 3 colors use them, else use default white
if (red) and (green) and (blue) then
color.r,color.g,color.b = (tonumber(red)/10),(tonumber(green)/10),(tonumber(blue)/10);
end
self:DisplayText(message, color, nil, "event", 1);
end
-------------------------
--Set the font of an object using msg vars
function SCT:SetMsgFont(object)
--set font
object:SetFont(SCT.LOCALS.FONTS[self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGFONT"]].path,
self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGSIZE"],
arrShadowOutline[self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGFONTSHADOW"]]);
--reset size of allow 3 messages
object:SetHeight(self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGSIZE"] * 4)
--Set Fade Duration
if (object.SetFadeDuration) then
object:SetFadeDuration(1);
end
end
-------------------------
--Set the font of the built in damage font
function SCT:SetDmgFont()
if (SCT.db.profile["DMGFONT"]) then
DAMAGE_TEXT_FONT = SCT.LOCALS.FONTS[SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME1]["FONT"]].path;
end
end
-------------------------
--Set the font of an object
function SCT:SetFontSize(object, font, textsize, fontshadow)
object:SetFont(SCT.LOCALS.FONTS[font].path, textsize, arrShadowOutline[fontshadow]);
end
-------------------------
--Determine if a hunter is FD'ing
--Code taken from CTRA
function SCT:CheckFD(unit)
if ( UnitClass(unit) ~= SCT.LOCALS.HUNTER ) then
return;
end
local hasFD;
local num, buff = 0, UnitBuff(unit, 1);
while ( buff ) do
if ( buff == "Interface\\Icons\\Ability_Rogue_FeignDeath" ) then
hasFD = 1;
break;
end
num = num + 1;
buff = UnitBuff(unit, num+1);
end
if ( hasFD ) then
return true;
else
return false;
end
end
-------------------------
--Return the unit if for a given target
function SCT:GetTargetUnit(target)
local unit;
if (target == "player") then
return "player";
end
if (target == UnitName('pet'))then
return "pet";
end
for i = 1, GetNumRaidMembers(), 1 do
if ( UnitName("raid" .. i) and UnitName("raid" .. i) == target ) then
return "raid"..i;
end
end
for i = 1, GetNumPartyMembers(), 1 do
if ( UnitName("party" .. i) and UnitName("party" .. i) == target ) then
return "party"..i;
end
end
end
-------------------------
--Return the amount the target is overhealed
function SCT:GetOverheal(target, damage)
local unit = self:GetTargetUnit(target);
if unit then
local lost = UnitHealthMax(unit)-UnitHealth(unit);
local overheal = damage - lost;
if (overheal > 0) then
damage = lost.." {"..overheal.."}";
end
end
return damage;
end
-------------------------
--Regsiter SCT with other mods
function SCT:RegisterOtherMods()
-- myAddOns support
if(myAddOnsFrame_Register) then
local SCTDetails = {
name = "sct",
version = SCT.Version,
optionsframe = "SCTOptions",
category = MYADDONS_CATEGORY_COMBAT
};
myAddOnsFrame_Register(SCTDetails);
end
--Cosmos support
if ( EarthFeature_AddButton ) then
EarthFeature_AddButton(
{
id="SCT";
name=SCT.LOCALS.SCT_CB_NAME;
text=SCT.LOCALS.SCT_CB_NAME;
subtext=SCT.LOCALS.SCT_CB_SHORT_DESC;
helptext=SCT.LOCALS.SCT_CB_LONG_DESC;
icon=SCT.LOCALS.SCT_CB_ICON;
callback=SCT.ShowMenu;
}
);
elseif (Cosmos_RegisterButton) then
Cosmos_RegisterButton (
SCT.LOCALS.SCT_CB_NAME,
SCT.LOCALS.SCT_CB_SHORT_DESC,
SCT.LOCALS.SCT_CB_LONG_DESC,
SCT.LOCALS.SCT_CB_ICON,
SCT.ShowMenu,
function()
return true;
end
);
default_config.ENABLED = 0;
end
-- Add to CTMod Control panel if available
if ( CT_RegisterMod ) then
CT_RegisterMod(SCT.LOCALS.CB_NAME, nil, 5, SCT.LOCALS.CB_ICON, SCT.LOCALS.CB_LONG_DESC, "switch", nil, SCT.ShowMenu);
end
end
-------------------------
--Get the default Config
function SCT:GetDefaultConfig()
local default = {
["VERSION"] = SCT.Version,
["ENABLED"] = true,
["SHOWHIT"] = 1,
["SHOWMISS"] = 1,
["SHOWDODGE"] = 1,
["SHOWPARRY"] = 1,
["SHOWBLOCK"] = 1,
["SHOWSPELL"] = 1,
["SHOWHEAL"] = 1,
["SHOWRESIST"] = 1,
["SHOWDEBUFF"] = 1,
["SHOWBUFF"] = 1,
["SHOWFADE"] = false,
["SHOWABSORB"] = 1,
["SHOWLOWHP"] = 1,
["SHOWLOWMANA"] = 1,
["SHOWPOWER"] = 1,
["SHOWCOMBAT"] = false,
["SHOWCOMBOPOINTS"] = false,
["SHOWHONOR"] = 1,
["SHOWEXECUTE"] = 1,
["SHOWREP"] = 1,
["SHOWSELFHEAL"] = 1,
["SHOWSKILL"] = 1,
["SHOWTARGETS"] = 1,
["SHOWSELF"] = false,
["SHOWOVERHEAL"] = 1,
["STICKYCRIT"] = 1,
["FLASHCRIT"] = 1,
["SPELLTYPE"] = false,
["SPELLCOLOR"] = false,
["DMGFONT"] = false,
["SHOWALLPOWER"] = false,
["FPSMODE"] = false,
["ANIMATIONSPEED"] = 15,
["MOVEMENT"] = 2,
["LOWHP"] = 40,
["LOWMANA"] = 40,
["HEALFILTER"] = 50,
["PLAYSOUND"] = 1,
["CUSTOMEVENTS"] = 1,
["LIGHTMODE"] = false,
[SCT.FRAMES_DATA_TABLE] = {
[SCT.FRAME1] = {
["FONT"] = 1,
["FONTSHADOW"] = 2,
["ALPHA"] = 100,
["ANITYPE"] = 1,
["ANISIDETYPE"] = 1,
["XOFFSET"] = 0,
["YOFFSET"] = 0,
["DIRECTION"] = false,
["TEXTSIZE"] = 24,
},
[SCT.FRAME2] = {
["FONT"] = 1,
["FONTSHADOW"] = 2,
["ALPHA"] = 100,
["ANITYPE"] = 1,
["ANISIDETYPE"] = 1,
["XOFFSET"] = 0,
["YOFFSET"] = -150,
["DIRECTION"] = true,
["TEXTSIZE"] = 24,
},
[SCT.MSG] = {
["MSGFADE"] = 1.5,
["MSGFONT"] = 1,
["MSGFONTSHADOW"] = 2,
["MSGSIZE"] = 24,
["MSGYOFFSET"] = -280,
["MSGXOFFSET"] = 0,
}
},
[SCT.COLORS_TABLE] = {
["SHOWHIT"] = {r = 1.0, g = 0.0, b = 0.0},
["SHOWMISS"] = {r = 0.0, g = 0.0, b = 1.0},
["SHOWDODGE"] = {r = 0.0, g = 0.0, b = 1.0},
["SHOWPARRY"] = {r = 0.0, g = 0.0, b = 1.0},
["SHOWBLOCK"] = {r = 0.0, g = 0.0, b = 1.0},
["SHOWSPELL"] = {r = 0.5, g = 0.0, b = 0.5},
["SHOWHEAL"] = {r = 0.0, g = 1.0, b = 0.0},
["SHOWRESIST"] = {r = 0.5, g = 0.0, b = 0.5},
["SHOWDEBUFF"] = {r = 0.0, g = 0.5, b = 0.5},
["SHOWABSORB"] = {r = 1.0, g = 1.0, b = 0.0},
["SHOWLOWHP"] = {r = 1.0, g = 0.5, b = 0.5},
["SHOWLOWMANA"] = {r = 0.5, g = 0.5, b = 1.0},
["SHOWPOWER"] = {r = 1.0, g = 1.0, b = 0.0},
["SHOWCOMBAT"] = {r = 1.0, g = 1.0, b = 1.0},
["SHOWCOMBOPOINTS"] = {r = 1.0, g = 0.5, b = 0.0},
["SHOWHONOR"] = {r = 0.5, g = 0.5, b = 0.7},
["SHOWBUFF"] = {r = 0.7, g = 0.7, b = 0.0},
["SHOWFADE"] = {r = 0.7, g = 0.7, b = 0.0},
["SHOWEXECUTE"] = {r = 0.7, g = 0.7, b = 0.7},
["SHOWREP"] = {r = 0.5, g = 0.5, b = 1},
["SHOWSELFHEAL"] = {r = 0, g = 0.7, b = 0},
["SHOWSKILL"] = {r = 0, g = 0, b = 0.7}
},
[SCT.CRITS_TABLE] = {
["SHOWEXECUTE"] = 1,
["SHOWLOWHP"] = 1,
["SHOWLOWMANA"] = 1,
},
[SCT.FRAMES_TABLE] = {
["SHOWHIT"] = SCT.FRAME1,
["SHOWMISS"] = SCT.FRAME1,
["SHOWDODGE"] = SCT.FRAME1,
["SHOWPARRY"] = SCT.FRAME1,
["SHOWBLOCK"] = SCT.FRAME1,
["SHOWSPELL"] = SCT.FRAME1,
["SHOWHEAL"] = SCT.FRAME2,
["SHOWRESIST"] = SCT.FRAME1,
["SHOWDEBUFF"] = SCT.FRAME1,
["SHOWABSORB"] = SCT.FRAME1,
["SHOWLOWHP"] = SCT.FRAME1,
["SHOWLOWMANA"] = SCT.FRAME1,
["SHOWPOWER"] = SCT.FRAME2,
["SHOWCOMBAT"] = SCT.FRAME2,
["SHOWCOMBOPOINTS"] = SCT.FRAME1,
["SHOWHONOR"] = SCT.MSG,
["SHOWBUFF"] = SCT.MSG,
["SHOWFADE"] = SCT.FRAME1,
["SHOWEXECUTE"] = SCT.FRAME1,
["SHOWREP"] = SCT.MSG,
["SHOWSELFHEAL"] = SCT.FRAME2 ,
["SHOWSKILL"] = SCT.FRAME2
}
};
return default;
end
-------------------------
--Regsiter SCT with all events
function SCT:RegisterSelfEvents()
-- Register Main Events
self:RegisterEvent("UNIT_HEALTH", "OnEvent");
self:RegisterEvent("UNIT_MANA", "OnEvent");
self:RegisterEvent("UNIT_ENERGY", "OnEvent");
self:RegisterEvent("UNIT_RAGE", "OnEvent");
self:RegisterEvent("UNIT_DISPLAYPOWER", "OnEvent");
self:RegisterEvent("PLAYER_REGEN_ENABLED", "OnEvent");
self:RegisterEvent("PLAYER_REGEN_DISABLED", "OnEvent");
self:RegisterEvent("PLAYER_COMBO_POINTS", "OnEvent");
self:RegisterEvent("COMBAT_TEXT_UPDATE", "BlizzardCombatTextEvent");
--unsupported chat events:
self:RegisterEvent("CHAT_MSG_SKILL", "OnEvent");
--events need for light and normal mode for Parserlib
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_SELF_BUFF", SCT.ParseCombat) ;
--if in light mode, end here
if (self.db.profile["LIGHTMODE"]) then
return;
end
--events only needed in normal mode for Parserlib
parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_SELF_HITS", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_SELF_DAMAGE", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS", SCT.ParseCombat) ;
parser:RegisterEvent("sct", "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS", SCT.ParseCombat) ;
--searchable added events
local key, value
for key, value in SCT.EventList do
self:RegisterEvent(value, "OnEvent");
end
end
------------------------------
---Sort a table by its keys.
---stolen from http://www.lua.org/pil/19.3.html
function SCT:PairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
------------------------------
--Create event to load up correct font
--when another mod loads. Incase they try to change
--the font (super inspect, etc...)
SCT:RegisterEvent("ADDON_LOADED", SCT.SetDmgFont);