--[[ **************************************************************** Scrolling Combat Text Author: Grayhoof **************************************************************** Official Site: http://grayhoof.wowinterface.com ****************************************************************]] SCT = LibStub("AceAddon-3.0"):NewAddon("SCT", "AceEvent-3.0", "AceTimer-3.0", "AceConsole-3.0", "AceHook-3.0") local SCT = SCT local db SCT.title = "sct" SCT.version = GetAddOnMetadata(SCT.title, "Version") --embedded libs local media = LibStub("LibSharedMedia-3.0") --Table Constants SCT.SPELL_COLORS_TABLE = "SPELLCOLORS" 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 local last_hp_percent = 0 local last_hp_target_percent = 0 local last_mana_percent = 0 local last_mana_full = 99999 local menuloaded = false --Blizzard APi calls local GetComboPoints = GetComboPoints local UnitHealth = UnitHealth local UnitHealthMax = UnitHealthMax local UnitMana = UnitMana local UnitManaMax = UnitManaMax local UnitName = UnitName local UnitIsFriend = UnitIsFriend local UnitIsDead = UnitIsDead local UnitIsCorpse = UnitIsCorpse local UnitIsFeignDeath = UnitIsFeignDeath local UnitGUID = UnitGUID local PlaySound = PlaySound local PlaySoundFile = PlaySoundFile local GetNumRaidMembers = GetNumRaidMembers local GetNumPartyMembers = GetNumPartyMembers local GetSpellInfo = GetSpellInfo local GetRuneType = GetRuneType --LUA calls local pairs = pairs local tonumber = tonumber local strsub = strsub local strlen = strlen local gsub = gsub local string_match = string.match local string_format = string.format local string_find = string.find local string_split = string.split --combat log locals local CombatLog_Object_IsA = CombatLog_Object_IsA local skillmsg = gsub(gsub(gsub(SKILL_RANK_UP, '%d%$', ''), '%%s', '(.+)'), '%%d', '(%%d+)') local COMBATLOG_OBJECT_NONE = COMBATLOG_OBJECT_NONE local COMBATLOG_FILTER_MINE = COMBATLOG_FILTER_MINE local COMBATLOG_FILTER_MY_PET = COMBATLOG_FILTER_MY_PET local COMBATLOG_FILTER_HOSTILE = bit.bor( COMBATLOG_FILTER_HOSTILE_PLAYERS, COMBATLOG_FILTER_HOSTILE_UNITS) local COMBATLOG_FILTER_PLAYER = bit.bor( COMBATLOG_OBJECT_AFFILIATION_MASK, COMBATLOG_OBJECT_REACTION_MASK, COMBATLOG_OBJECT_TYPE_PLAYER, COMBATLOG_OBJECT_CONTROL_PLAYER) local COMBAT_EVENTS = { ["SWING_DAMAGE"] = "DAMAGE", ["RANGE_DAMAGE"] = "DAMAGE", ["SPELL_DAMAGE"] = "DAMAGE", ["SPELL_PERIODIC_DAMAGE"] = "DAMAGE", ["ENVIRONMENTAL_DAMAGE"] = "DAMAGE", ["DAMAGE_SHIELD"] = "DAMAGE", ["DAMAGE_SPLIT"] = "DAMAGE", ["SPELL_HEAL"] = "HEAL", ["SPELL_PERIODIC_HEAL"] = "HEAL", ["SWING_MISSED"] = "MISS", ["RANGE_MISSED"] = "MISS", ["SPELL_MISSED"] = "MISS", ["SPELL_PERIODIC_MISSED"] = "MISS", ["DAMAGE_SHIELD_MISSED"] = "MISS", ["SPELL_DRAIN"] = "DRAIN", ["SPELL_LEECH"] = "DRAIN", ["SPELL_PERIODIC_DRAIN"] = "DRAIN", ["SPELL_PERIODIC_LEECH"] = "DRAIN", ["SPELL_ENERGIZE"] = "POWER", ["SPELL_PERIODIC_ENERGIZE"] = "POWER", ["SPELL_INTERRUPT"] = "INTERRUPT", ["PARTY_KILL"] = "DEATH", ["UNIT_DIED"] = "DEATH", ["UNIT_DESTROYED"] = "DEATH", ["SPELL_AURA_APPLIED"] = "BUFF", ["SPELL_PERIODIC_AURA_APPLIED"] = "BUFF", ["SPELL_AURA_APPLIED_DOSE"] = "BUFF", ["SPELL_PERIODIC_AURA_APPLIED_DOSE"] = "BUFF", ["SPELL_AURA_REMOVED"] = "FADE", ["SPELL_PERIODIC_AURA_REMOVED"] = "FADE", ["SPELL_AURA_REMOVED_DOSE"] = "FADE", ["SPELL_PERIODIC_AURA_REMOVED_DOSE"] = "FADE", ["ENCHANT_APPLIED"] = "ENCHANT_APPLIED", ["ENCHANT_REMOVED"] = "ENCHANT_REMOVED", ["SPELL_SUMMON"] = "SUMMON", ["SPELL_CREATE"] = "SUMMON", ["SPELL_DISPEL"] = "DISPEL", ["SPELL_STOLEN"] = "DISPEL", ["SPELL_CAST_START"] = "CAST", ["SPELL_CAST_SUCCESS"] = "CAST", } local SCHOOL_STRINGS = { [SCHOOL_MASK_PHYSICAL] = SPELL_SCHOOL0_CAP, [SCHOOL_MASK_HOLY] = SPELL_SCHOOL1_CAP, [SCHOOL_MASK_FIRE] = SPELL_SCHOOL2_CAP, [SCHOOL_MASK_NATURE] = SPELL_SCHOOL3_CAP, [SCHOOL_MASK_FROST] = SPELL_SCHOOL4_CAP, [SCHOOL_MASK_SHADOW] = SPELL_SCHOOL5_CAP, [SCHOOL_MASK_ARCANE] = SPELL_SCHOOL6_CAP, } local POWER_STRINGS = { [SPELL_POWER_MANA] = MANA, [SPELL_POWER_RAGE] = RAGE, [SPELL_POWER_FOCUS] = FOCUS, [SPELL_POWER_ENERGY] = ENERGY, [SPELL_POWER_HAPPINESS] = HAPPINESS, [SPELL_POWER_RUNES] = RUNES, [SPELL_POWER_RUNIC_POWER] = RUNIC_POWER, [SPELL_POWER_SOUL_SHARDS] = SHARDS, [SPELL_POWER_ECLIPSE] = ECLIPSE, [SPELL_POWER_HOLY_POWER] = HOLY_POWER, } local SHADOW_STRINGS = { [1] = "", [2] = "OUTLINE", [3] = "THICKOUTLINE" } local RUNETYPE_BLOOD = 1; local RUNETYPE_UNHOLY = 2; local RUNETYPE_FROST = 3; local RUNETYPE_DEATH = 4 local RUNE_STRINGS = { [RUNETYPE_BLOOD] = {text = COMBAT_TEXT_RUNE_BLOOD, icon = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Blood", color = {r=.75,g=0,b=0}}, [RUNETYPE_UNHOLY] = {text = COMBAT_TEXT_RUNE_UNHOLY, icon = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Unholy", color = {r=.5,g=.6,b=.5}}, [RUNETYPE_FROST] = {text = COMBAT_TEXT_RUNE_FROST, icon = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Frost", color = {r=0,g=.75,b=1}}, [RUNETYPE_DEATH] = {text = TUTORIAL_TITLE25.." "..RUNES, icon = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Death", color = {r=1,g=.75,b=0}}, } ---------------------- --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 self:UnregisterAllEvents() end ---------------------- -- Show the Option Menu function SCT:ShowMenu() local loaded, message = LoadAddOn("sct_options") if (loaded) then PlaySound("igMainMenuOpen") if not menuloaded then SCT:MakeBlizzOptions() menuloaded = true else SCT:OptionsFrame_OnShow() end InterfaceOptionsFrame_OpenToCategory("SCT "..SCT.LOCALS.OPTION_MISC21.name) else PlaySound("TellMessage") SCT:Print(SCT.LOCALS.Load_Error.." "..message) end end ---------------------- --Hide the Option Menu function SCT:HideMenu() PlaySound("igMainMenuClose") HideUIPanel(SCTOptions) end local slashHandler = function(option) local self = SCT if option == "menu" then self:ShowMenu() elseif option == "reset" then self:Reset() else self:Print(self.version) self:Print("/sct menu") self:Print("/sct reset") self:Print("/sctdisplay") end end ---------------------- --Called when Addon loaded function SCT:OnInitialize() self.db = LibStub("AceDB-3.0"):New("SCT_CONFIG", self:GetDefaultConfig(), true) self.eventdb = LibStub("AceDB-3.0"):New("SCT_EVENT_CONFIG", nil, "Global") --local the profile table db = self.db.profile --set event defaults (not using a AceDB default table because how it handles nil values doesn't work well with custom events) if not self.eventdb.global.firstload or self.AlwaysLoadEvents then self.eventdb.global.firstload = true self.eventdb.global.events = {} for k,v in pairs(self.Events) do self.eventdb.global.events[k] = v end end self.EventConfig = self.eventdb.global.events self:RegisterChatCommand("sct", slashHandler) self:RegisterChatCommand("sctmenu", function() self:ShowMenu() end) self:RegisterChatCommand("sctdisplay", function(x) self:CmdDisplay(x) end) --Shared Media for key, value in pairs(SCT.LOCALS.FONTS) do media:Register("font", value.name, value.path) end --register with other mods self:RegisterOtherMods() --setup animations self:AniInit() --cache custome events self:CacheCustomEvents() --set healing flags self:SetHealingFlags() --setup Unit name plate tracking if (db["NAMEPLATES"]) then self:EnableNameplate() end end ---------------------- --Hook Function to show event function SCT:AddMessage(frame, text, r, g, b, id) self.hooks[frame].AddMessage(frame, text.." |cff00ff00["..tostring(event).."]|r", r, g, b, id) end ---------------------- --Reset everything to default function SCT:Reset() self.db:ResetProfile() self:AniInit() self:HideMenu() self:ShowMenu() self:ShowExample() self:Print(SCT.LOCALS.PROFILE_NEW..self.db:GetCurrentProfile()) end ---------------------- --Get a value from player config function SCT:Get(option, table) if (table) then return db[table][option] else return db[option] end end ---------------------- --Set a value in player config function SCT:Set(option, value, table) if (table) then db[table][option] = value else db[option] = value end end ---------------------- --Display for any partial blocks function SCT:DisplayBlock(blocked) SCT:Display_Event("SHOWBLOCK", string_format("%s (%d)",BLOCK, blocked)) end ---------------------- --Display for any partial absorbs function SCT:DisplayAbsorb(absorbed) SCT:Display_Event("SHOWABSORB", string_format("%s (%d)", ABSORB, absorbed)) end ---------------------- --Player Health function SCT:UNIT_HEALTH(event, larg1) if (larg1 == "player") then local warnlevel = db["LOWHP"] / 100 local HPPercent = UnitHealth("player") / UnitHealthMax("player") if (HPPercent < warnlevel) and (last_hp_percent >= warnlevel) and (not UnitIsFeignDeath("player")) then if (db["PLAYSOUND"] and db["SHOWLOWHP"]) then PlaySoundFile("Sound\\Spells\\bind2_Impact_Base.wav") end self:Display_Event("SHOWLOWHP", string_format("%s (%d)", SCT.LOCALS.LowHP, UnitHealth("player"))) end last_hp_percent = HPPercent return end end ---------------------- --Player Runes function SCT:RUNE_POWER_UPDATE(event, ...) if db["SHOWRUNES"] then local rune, usable = ... local crit = db[self.CRITS_TABLE]["SHOWRUNES"] local showmsg = db[self.FRAMES_TABLE]["SHOWRUNES"] or 1 rune = GetRuneType(rune) if usable and rune then if (showmsg == SCT.MSG) then self:DisplayMessage(RUNE_STRINGS[rune].text, RUNE_STRINGS[rune].color, RUNE_STRINGS[rune].icon) else self:DisplayCustomEvent(RUNE_STRINGS[rune].text, RUNE_STRINGS[rune].color, crit, showmsg, nil, RUNE_STRINGS[rune].icon) end end end end ---------------------- --Player Mana function SCT:UNIT_POWER(event, larg1) if (larg1 == "player") and (UnitPowerType("player") == 0)then local warnlevel = db["LOWMANA"] / 100 local ManaPercent = UnitMana("player") / UnitManaMax("player") if (ManaPercent < warnlevel) and (last_mana_percent >= warnlevel) and (not UnitIsFeignDeath("player")) then if (db["PLAYSOUND"] and db["SHOWLOWMANA"]) then PlaySoundFile("Sound\\Spells\\ShaysBell.wav") end SCT:Display_Event("SHOWLOWMANA", string_format("%s (%d)", SCT.LOCALS.LowMana, UnitMana("player"))) end last_mana_percent = ManaPercent end if (larg1 == "player") and (db["SHOWALLPOWER"]) then local ManaFull = UnitMana("player") if (ManaFull > last_mana_full) then self:Display_Event("SHOWPOWER", string_format("+%d %s", ManaFull-last_mana_full, POWER_STRINGS[UnitPowerType("player")])) end last_mana_full = ManaFull end end ---------------------- --Player target change function SCT:PLAYER_TARGET_CHANGED(event) if (not UnitIsFriend("target", "player") and (UnitIsDead("target")~=true) and (UnitIsCorpse("target")~=true)) then last_hp_target_percent = UnitHealth("target") else last_hp_target_percent = 100 end end ---------------------- --Power Change function SCT:UNIT_DISPLAYPOWER(event) last_mana_full = UnitMana("player") end ---------------------- --Player Combat function SCT:PLAYER_REGEN_DISABLED(event) self:Display_Event("SHOWCOMBAT", SCT.LOCALS.Combat) end ---------------------- --Player NoCombat function SCT:PLAYER_REGEN_ENABLED(event) self:Display_Event("SHOWCOMBAT", SCT.LOCALS.NoCombat) end ---------------------- --Unit Combo Points function SCT:UNIT_COMBO_POINTS(event, larg1) if (larg1 == "player") then local sct_CP = GetComboPoints('player') if (sct_CP ~= 0) then local sct_CP_Message = string_format("%d %s", 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 end end ---------------------- -- Skill Gains function SCT:CHAT_MSG_SKILL(event, larg1) local skill, rank = string_match(larg1, skillmsg) if skill then self:Display_Event("SHOWSKILL", string_format("%s: %d", skill, rank)) end end ---------------------- -- Displays Parsed info based on type function SCT:ParseCombat(arg1, timestamp, event, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, ...) local etype = COMBAT_EVENTS[event] if not etype then return end --custom search first if (db["CUSTOMEVENTS"]) and (self:CustomCombatEventSearch(etype, event, sourceName, sourceFlags, destName, destFlags, ...) == true) then return end --check for reflect damage if self.ReflectTarget and self.ReflectSkill and event == "SPELL_DAMAGE" and sourceName == destName and CombatLog_Object_IsA(destFlags, COMBATLOG_FILTER_HOSTILE) then self:ParseReflect(timestamp, event, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, ...) return end local toPlayer, fromPlayer, toPet, fromPet if (sourceName and not CombatLog_Object_IsA(sourceFlags, COMBATLOG_OBJECT_NONE) ) then fromPlayer = CombatLog_Object_IsA(sourceFlags, COMBATLOG_FILTER_MINE) fromPet = CombatLog_Object_IsA(sourceFlags, COMBATLOG_FILTER_MY_PET) end if (destName and not CombatLog_Object_IsA(destFlags, COMBATLOG_OBJECT_NONE) ) then toPlayer = CombatLog_Object_IsA(destFlags, COMBATLOG_FILTER_MINE) toPet = CombatLog_Object_IsA(destFlags, COMBATLOG_FILTER_MY_PET) end --if it was only a custom event, then end if not fromPlayer and not toPlayer and not fromPet and not toPet then return end local healtot, healamt, parent local amount, overDamage, school, resisted, blocked, absorbed, critical, glancing, crushing local spellId, spellName, spellSchool, missType, powerType, extraAmount, environmentalType, extraSpellId, extraSpellName, extraSpellSchool, auraType, overHeal local text, texture, message, inout, color ------------damage---------------- if etype == "DAMAGE" then if event == "SWING_DAMAGE" then amount, overDamage, school, resisted, blocked, absorbed, critical, glancing, crushing = select(1, ...) elseif event == "ENVIRONMENTAL_DAMAGE" then environmentalType, amount, overDamage, school, resisted, blocked, absorbed, critical, glancing, crushing = select(1, ...) else spellId, spellName, spellSchool, amount, overDamage, school, resisted, blocked, absorbed, critical, glancing, crushing = select(1, ...) texture = select(3, GetSpellInfo(spellId)) end text = tostring(amount) if toPlayer then if (amount < db["DMGFILTER"]) then return end if (crushing and db["SHOWGLANCE"]) then text = self.LOCALS.Crushchar..text..self.LOCALS.Crushchar end if (glancing and db["SHOWGLANCE"]) then text = self.LOCALS.Glancechar..text..self.LOCALS.Glancechar end if(absorbed) then self:DisplayAbsorb(absorbed) end if(blocked) then self:DisplayBlock(blocked) end if event == "SWING_DAMAGE" or event == "RANGE_DAMAGE" then self:Display_Event("SHOWHIT", "-"..text, critical) else self:Display_Event("SHOWSPELL", "-"..text, critical, SCHOOL_STRINGS[school], resisted, nil, nil, nil, spellName, texture) end end ------------buff/debuff gain---------------- elseif etype == "BUFF" then spellId, spellName, spellSchool, auraType, amount = select(1, ...) texture = select(3, GetSpellInfo(spellId)) if toPlayer then if amount and amount > 1 then self:Display_Event("SHOW"..auraType, string_format("[%s %d]", self:ShortenString(spellName), amount), nil, nil, nil, nil, nil, nil, nil, texture) else self:Display_Event("SHOW"..auraType, "["..self:ShortenString(spellName).."]", nil, nil, nil, nil, nil, nil, nil, texture) end end ------------buff/debuff lose---------------- elseif etype == "FADE" then spellId, spellName, spellSchool, auraType, amount = select(1, ...) texture = select(3, GetSpellInfo(spellId)) if toPlayer then if db["SHOWFADE"] then self:Display_Event("SHOWFADE", "-["..self:ShortenString(spellName).."]", nil, nil, nil, nil, nil, nil, nil, texture) end end ------------heals---------------- elseif etype == "HEAL" then spellId, spellName, spellSchool, amount, overHeal, absorbed, critical = select(1, ...) text = amount texture = select(3, GetSpellInfo(spellId)) healtot = tostring(amount) --heal filter if (amount < db["HEALFILTER"]) then return end if toPlayer then --self heals if toPlayer and fromPlayer then if (db["SHOWOVERHEAL"]) and overHeal > 0 then healtot = string_format("%d {%d}", amount-overHeal, overHeal) end self:Display_Event("SHOWHEAL", "+"..healtot, critical, nil, nil, self:ShortenString(spellName), nil, nil, nil, texture) --incoming heals else self:Display_Event("SHOWHEAL", "+"..healtot, critical, nil, nil, sourceName, nil, nil, spellName, texture) end --outgoing heals elseif fromPlayer then if event == "SPELL_PERIODIC_HEAL" and (not db["SHOWHOTS"]) then return end if (db["SHOWOVERHEAL"]) and overHeal > 0 then healtot = string_format("%d {%d}", amount-overHeal, overHeal) end local healtext = destName..": +"..healtot if (db["NAMEPLATES"]) then parent = self:GetNameplate(self:CleanName(destName, destFlags)) end if parent then healtext = "+"..healtot end self:Display_Event("SHOWSELFHEAL", healtext, critical, nil, nil, nil, nil, parent, spellName, texture) end ------------misses---------------- elseif etype == "MISS" then if event == "SWING_MISSED" or event == "RANGE_MISSED" then missType = select(1, ...) else spellId, spellName, spellSchool, missType = select(1, ...) texture = select(3, GetSpellInfo(spellId)) end text = _G[missType] if toPlayer then if (missType == "REFLECT") then self:Display_Event("SHOWABSORB", text.." ("..spellName..")", nil, nil, nil, nil, text.." ("..spellName..")", nil, spellName, texture) self:SetReflect(sourceName, spellName) elseif (missType == "ABSORB" or missType == "DEFLECT" or missType == "IMMUNE" or missType == "EVADE") then self:Display_Event("SHOWABSORB", text, nil, nil, nil, nil, text, nil, spellName, texture) elseif missType then self:Display_Event("SHOW"..missType, text, nil, nil, nil, nil, text, nil, spellName, texture) end end ------------leech and drains---------------- elseif etype == "DRAIN" then spellId, spellName, spellSchool, amount, powerType, extraAmount = select(1, ...) texture = select(3, GetSpellInfo(spellId)) if toPlayer then self:Display_Event("SHOWPOWER", string_format("-%d %s", amount, POWER_STRINGS[powerType]), nil, nil, nil, nil, nil, nil, spellName, texture) elseif fromPlayer and extraAmount and (not db["SHOWALLPOWER"]) then if (extraAmount < db["MANAFILTER"]) then return end self:Display_Event("SHOWPOWER", string_format("+%d %s", extraAmount, POWER_STRINGS[powerType]), nil, nil, nil, nil, nil, nil, spellName, texture) elseif fromPlayer then return --for showing your drain damage --self:Display_Event("SHOWSPELL", string_format("%d %s", extraAmount, POWER_STRINGS[powerType]), nil, nil, nil, nil, nil, nil, spellName, texture) end ------------power gains---------------- elseif etype == "POWER" then spellId, spellName, spellSchool, amount, powerType = select(1, ...) texture = select(3, GetSpellInfo(spellId)) if (amount < db["MANAFILTER"]) then return end if toPlayer and (not db["SHOWALLPOWER"]) then self:Display_Event("SHOWPOWER", string_format("+%d %s", amount, POWER_STRINGS[powerType]), nil, nil, nil, nil, nil, nil, spellName, texture) end ------------interrupts---------------- elseif etype == "INTERRUPT" then spellId, spellName, spellSchool, extraSpellId, extraSpellName, extraSpellSchool = select(1, ...) texture = select(3, GetSpellInfo(extraSpellId)) if toPlayer then self:Display_Event("SHOWINTERRUPT", self.LOCALS.Interrupted, nil, nil, nil, nil, nil, nil, extraSpellName, texture) end ------------dispels---------------- elseif etype == "DISPEL" then spellId, spellName, spellSchool, extraSpellId, extraSpellName, extraSpellSchool, auraType = select(1, ...) texture = select(3, GetSpellInfo(extraSpellId)) if fromPlayer then self:Display_Event("SHOWDISPEL", self.LOCALS.Dispel, nil, nil, nil, nil, nil, nil, extraSpellName, texture) end ------------deaths---------------- elseif etype == "DEATH" then if fromPlayer then self:Display_Event("SHOWKILLBLOW", self.LOCALS.KillingBlow) end ------------enchants---------------- elseif etype == "ENCHANT_APPLIED" then spellName = select(1, ...) self:Display_Event("SHOWBUFF", "["..self:ShortenString(spellName).."]", nil, nil, nil, nil, nil, nil, nil, texture) elseif etype == "ENCHANT_REMOVED" then if db["SHOWFADE"] then spellName = select(1, ...) self:Display_Event("SHOWBUFF", "-["..self:ShortenString(spellName).."]", nil, nil, nil, nil, nil, nil, nil, texture) end -------------anything else------------- end end ---------------------- --Handle Blizzard events function SCT:COMBAT_TEXT_UPDATE(event, larg1, larg2, larg3) --Normal Events if (larg1=="SPELL_ACTIVE") then --check for redundant display info if not self:CheckSkill(larg2.."!") then local texture = select(3, GetSpellInfo(larg2)) self:Display_Event("SHOWEXECUTE", larg2.."!", nil, nil, nil, nil, nil, nil, nil, texture) end elseif (larg1=="FACTION") then local sign = "+" if (tonumber(larg3) < 0) then sign = "" end self:Display_Event("SHOWREP", string_format("%s%d %s (%s)", sign, larg3, REPUTATION, larg2)) elseif (larg1=="HONOR_GAINED") then self:Display_Event("SHOWHONOR", string_format("+%d %s", larg2, HONOR)) elseif (larg1=="EXTRA_ATTACKS") then if ( tonumber(larg2) > 1 ) then self:Display_Event("SHOWEXECUTE", string_format("%s (%d)", self.LOCALS.ExtraAttack, larg2)) else self:Display_Event("SHOWEXECUTE", self.LOCALS.ExtraAttack) end end end ------------------------- --Set last reflection function SCT:ParseReflect(timestamp, event, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, ...) local spellId, spellName, spellSchool, amount, school, resisted, blocked, absorbed, critical, glancing, crushing = select(1, ...) local texture = select(3, GetSpellInfo(spellId)) --reflected events if (self.ReflectTarget == sourceName and sourceName == destName and self.ReflectSkill == spellName) then local parent if (db["NAMEPLATES"]) then parent = self:GetNameplate(self:CleanName(destName, destFlags)) end if SCTD then SCTD:DisplayText("SCTD_SHOWSPELL", string_format("%s: %d", REFLECT, amount), critical, SCHOOL_STRINGS[school], resisted, destName, spellName, texture, destFlags) else self:Display_Event("SHOWABSORB", string_format("%s: %d (%s)", spellName, amount, REFLECT), critical,nil,nil,nil,nil,parent,nil,texture) end self:ClearReflect() end end ------------------------- --Set last reflection function SCT:SetReflect(target, skill) self.ReflectTarget = target self.ReflectSkill = skill --clear reflection after 3 seconds. self:ScheduleTimer(self.ClearReflect, 3, self) end ------------------------- --Clear last reflection function SCT:ClearReflect() self.ReflectTarget = nil self.ReflectSkill = nil end ------------------------- --Clean server name from players names function SCT:CleanName(name, destFlags) if (CombatLog_Object_IsA(destFlags, COMBATLOG_FILTER_PLAYER)) then local rname = select(1, string_split("-", name)) return rname end return name end ---------------------- --Display for mainly combat events --Mainly used for short messages function SCT:Display_Event(option, msg1, crit, damagetype, resisted, target, msg2, parent, skill, icon) local rbgcolor, showcrit, showmsg, event --if option is on if (db[option]) then --get options rbgcolor = db[self.COLORS_TABLE][option] showcrit = db[self.CRITS_TABLE][option] showmsg = db[self.FRAMES_TABLE][option] or 1 --if skill name if ((skill) and (db["SKILLNAME"])) then msg1 = msg1.." ("..self:ShortenString(skill)..")" end --if damage type if ((damagetype) and (db["SPELLTYPE"])) then msg1 = msg1.." <"..damagetype..">" end --if spell color if ((damagetype) and (db["SPELLCOLOR"])) then rbgcolor = db[self.SPELL_COLORS_TABLE][damagetype] or rbgcolor end --if resisted if ((resisted) and (db["SHOWRESIST"])) then msg1 = string_format("%s (%d %s)", msg1, resisted, ERR_FEIGN_DEATH_RESISTED) end --if target label if ((target) and (db["SHOWTARGETS"])) then msg1 = msg1.." ("..target..")" end --If they want to tag all self events if (db["SHOWSELF"]) then msg1 = SCT.LOCALS.SelfFlag..msg1..SCT.LOCALS.SelfFlag end --if messages if (showmsg == SCT.MSG) then --if 2nd msg if (msg2) then msg1 = msg2 end --display message self:DisplayMessage( msg1, rbgcolor, icon ) 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, nil, parent, icon) end end end ---------------------- --Displays a message at the top of the screen function SCT:DisplayMessage(msg, color, icon) self:SetMsgFont(SCT_MSG_FRAME) if icon and db["ICON"] then msg = "|T"..icon..":"..(db[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGSIZE"]).."|t"..msg end 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 strlen(msg) == 0 then self:Print(SCT.LOCALS.DISPLAY_USEAGE) --Get message anf colors if quotes used elseif strsub(msg,1,1) == "'" then local location = string_find(strsub(msg,2),"'") if location and (location>1) then message = strsub(msg,2,location) colors = strsub(msg,location+1) end --Get message anf colors if single word used else local idx = string_find(msg," ") if (idx) then message = strsub(msg,1,idx-1) colors = strsub(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(media:Fetch("font", db[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGFONT"]), db[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGSIZE"], SHADOW_STRINGS[db[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGFONTSHADOW"]]) end ------------------------- --Set the font of the built in damage font function SCT:SetDmgFont() if (SCT.db.profile["DMGFONT"]) then DAMAGE_TEXT_FONT = media:Fetch("font",SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME1]["FONT"]) end end ------------------------- --Set the font of an object function SCT:SetFontSize(object, font, textsize, fontshadow) object:SetFont(media:Fetch("font",font), textsize, SHADOW_STRINGS[fontshadow]) end ------------------------- --Regsiter SCT with other mods function SCT:RegisterOtherMods() local frame = CreateFrame("FRAME", nil) frame:SetScript("OnShow",function() SCT:ShowMenu() end) frame.name = "SCT" InterfaceOptions_AddCategory(frame) InterfaceOptionsFrame:SetMovable(true) local title = InterfaceOptionsFrame:CreateTitleRegion() title:ClearAllPoints() title:SetAllPoints(InterfaceOptionsFrameHeader) end ------------------------- --Get the default Config function SCT:GetDefaultConfig() local default = { profile = { ["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, ["SHOWGLANCE"] = 1, ["SHOWOVERHEAL"] = 1, ["SHOWHOTS"] = false, ["SHOWKILLBLOW"] = 1, ["SHOWINTERRUPT"] = 1, ["SHOWDISPEL"] = 1, ["SHOWRUNES"] = 1, ["STICKYCRIT"] = 1, ["FLASHCRIT"] = 1, ["SKILLNAME"] = false, ["SPELLTYPE"] = false, ["SPELLCOLOR"] = false, ["DMGFONT"] = false, ["SHOWALLPOWER"] = false, ["FPSMODE"] = false, ["ANIMATIONSPEED"] = 15, ["MOVEMENT"] = 2, ["LOWHP"] = 40, ["LOWMANA"] = 40, ["HEALFILTER"] = 0, ["MANAFILTER"] = 0, ["DMGFILTER"] = 0, ["PLAYSOUND"] = 1, ["CUSTOMEVENTS"] = 1, ["NAMEPLATES"] = false, ["TRUNCATETYPE"] = 1, ["TRUNCATESIZE"] = 30, ["WOWHEAL"] = 1, ["ICON"] = 1, [SCT.FRAMES_DATA_TABLE] = { [SCT.FRAME1] = { ["FONT"] = "Friz Quadrata TT", ["FONTSHADOW"] = 2, ["ALPHA"] = 100, ["ANITYPE"] = 1, ["ANISIDETYPE"] = 1, ["XOFFSET"] = 0, ["YOFFSET"] = 0, ["DIRECTION"] = false, ["TEXTSIZE"] = 24, ["GAPDIST"] = 40, ["ALIGN"] = 2, ["ICONSIDE"] = 2, }, [SCT.FRAME2] = { ["FONT"] = "Friz Quadrata TT", ["FONTSHADOW"] = 2, ["ALPHA"] = 100, ["ANITYPE"] = 1, ["ANISIDETYPE"] = 1, ["XOFFSET"] = 0, ["YOFFSET"] = -150, ["DIRECTION"] = true, ["TEXTSIZE"] = 24, ["GAPDIST"] = 40, ["ALIGN"] = 2, ["ICONSIDE"] = 2, }, [SCT.MSG] = { ["MSGFADE"] = 1.5, ["MSGFONT"] = "Friz Quadrata TT", ["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}, ["SHOWKILLBLOW"] = {r = 0.7, g = 0.1, b = 0.1}, ["SHOWINTERRUPT"] = {r = 0.3, g = 0.3, b = 0.5}, ["SHOWDISPEL"] = {r = 0.8, g = 0.8, b = 1}, ["SHOWRUNES"] = {r = 0, g = 1, b = 1}, -- not used }, [SCT.SPELL_COLORS_TABLE] = { [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.CRITS_TABLE] = { ["SHOWEXECUTE"] = 1, ["SHOWLOWHP"] = 1, ["SHOWLOWMANA"] = 1, ["SHOWKILLBLOW"] = 1, ["SHOWINTERRUPT"] = 1, ["SHOWRUNES"] = 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, ["SHOWKILLBLOW"] = SCT.FRAME1, ["SHOWINTERRUPT"] = SCT.FRAME1, ["SHOWDISPEL"] = SCT.FRAME2, ["SHOWRUNES"] = SCT.FRAME1, } } } return default end ------------------------- --Regsiter SCT with all events function SCT:RegisterSelfEvents() -- Register Main Events self:RegisterEvent("UNIT_HEALTH") self:RegisterEvent("UNIT_POWER") self:RegisterEvent("UNIT_DISPLAYPOWER") self:RegisterEvent("RUNE_POWER_UPDATE"); self:RegisterEvent("PLAYER_REGEN_ENABLED") self:RegisterEvent("PLAYER_REGEN_DISABLED") self:RegisterEvent("UNIT_COMBO_POINTS") self:RegisterEvent("COMBAT_TEXT_UPDATE") self:RegisterEvent("CHAT_MSG_SKILL") self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED","ParseCombat") --Create event to load up correct font --when another mod loads. Incase they try to change --the font (super inspect, etc...) self:RegisterEvent("ADDON_LOADED", SCT.SetDmgFont) end ------------------------------ ---Shorten a spell/buff function SCT:ShortenString(strString) if strlen(strString) > db["TRUNCATESIZE"] then if (db["TRUNCATETYPE"] == 1) then return strsub(strString, 1, db["TRUNCATESIZE"]).."..." else return gsub(gsub(gsub(strString," of ","O"),"%s",""), "(%u)%l*", "%1") end else return strString end end ------------------------ --Setup Healing Flags based on Options function SCT:SetHealingFlags() local ver,build,date = GetBuildInfo() if (tonumber(build) <= 6546) then return end --set WoW Healing Flags if (SCT.db.profile["WOWHEAL"]) then SetCVar("CombatHealing", 0) else SetCVar("CombatHealing", 1) end end