------------------------------------------------------------------------------- -- Quu Spell Alert -- A mod that alerts about spell effects. Written by Quu -- Original "Spell Alert" written by Awen ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -- Contants -- The things that make this tick ------------------------------------------------------------------------------- BINDING_HEADER_QSATITLE = "Quu Spell Alert"; QSA_VERSION = "2.5.1"; local QSA_SLASH_COMMAND = "/qsa"; -- how long alerts should be displayed local QSA_NON_CRIT_TIME = 2; local QSA_CRIT_TIME = 5; ------------------------------------------------------------------------------- -- controll variables -- these are the variables that are saved between sessions, and variables -- that enable the "controll" logic ------------------------------------------------------------------------------- -- the basics (there are stored in the savedvariables.lua QSA_SavedVars_DEFAULT = { Enabled = true; CombatOnly = true; TargetOnly = false; ShortDisplay = true; EmoteMode = true; GainMode = true; FadeMode = false; Afflictions = true; QSA_Hide = false; }; QSA_SavedVars = { }; QSA_RED = 1.0; QSA_GREEN = 0.2; QSA_BLUE = 0.2; QSA_ALPHA = 1.0; function getVar( varName) local playerName = UnitName( "player"); if (not QSA_SavedVars[playerName]) then QSA_SavedVars[playerName] = QSA_SavedVars_DEFAULT; end return QSA_SavedVars[playerName][varName]; end function setVar( varName, value) local playerName = UnitName( "player"); if (not QSA_SavedVars[playerName]) then QSA_SavedVars[playerName] = QSA_SavedVars_DEFAULT; end QSA_SavedVars[playerName][varName] = value; end function toggleVar( varName) local playerName = UnitName( "player"); if (not QSA_SavedVars[playerName]) then QSA_SavedVars[playerName] = QSA_SavedVars_DEFAULT; end QSA_SavedVars[playerName][varName] = not QSA_SavedVars[playerName][varName]; end -- this is the last caster that was captured -- used for the key binding local QSA_LastTarget; ------------------------------------------------------------------------------- -- Alert functions ------------------------------------------------------------------------------- -- print simple messages function QSA_println( Message) DEFAULT_CHAT_FRAME:AddMessage(Message, 1.0, 1.0, 1.0); end -- normal alerts function QSA_Banner(msg) QuuSpellAlertNormalFrame:AddMessage(msg, QSA_RED, QSA_GREEN, QSA_BLUE, QSA_ALPHA, QSA_NON_CRIT_TIME); end -- critical alerts function QSA_Critical(msg) QuuSpellAlertCriticalFrame:AddMessage(msg, QSA_RED, QSA_GREEN, QSA_BLUE, QSA_ALPHA, QSA_CRIT_TIME); end ------------------------------------------------------------------------------- -- the colour picking stuff (and alpha) ------------------------------------------------------------------------------- -- initial loading of the color chooser function QSA_ChooseColor() ColorPickerFrame.func = QSA_SetColor; ColorPickerFrame.hasOpacity = true; ColorPickerFrame.opacityFunc = QSA_SetOpacity; ColorPickerFrame.opacity = 1.0 - QSA_ALPHA; ColorPickerFrame:SetColorRGB(QSA_RED, QSA_GREEN, QSA_BLUE); ColorPickerFrame.previousValues = {r = QSA_RED, g = QSA_GREEN, b = QSA_BLUE, opacity = (1.0 - QSA_ALPHA)}; ColorPickerFrame.cancelFunc = QSA_CancelColor; ShowUIPanel(ColorPickerFrame); end -- this is the values as they are set function QSA_SetColor() QSA_RED, QSA_GREEN, QSA_BLUE = ColorPickerFrame:GetColorRGB(); end -- this si the opacity as they are set function QSA_SetOpacity() QSA_ALPHA = 1.0 - OpacitySliderFrame:GetValue(); end -- they changed thier minds function QSA_CancelColor() QSA_RED = ColorPickerFrame.previousValues.r; QSA_GREEN = ColorPickerFrame.previousValues.g; QSA_BLUE = ColorPickerFrame.previousValues.b; QSA_ALPHA = 1.0 - ColorPickerFrame.previousValues.opacity; end ------------------------------------------------------------------------------- -- Options box... the functions for the options dialog box ------------------------------------------------------------------------------- function QSA_OptionsOpen() if ( not QuuSpellAlertOptions:IsVisible() ) then QuuSpellAlertOptionsEnable:SetChecked(getVar("Enabled")); QuuSpellAlertOptionsCombat:SetChecked(getVar("CombatOnly")); QuuSpellAlertOptionsTarget:SetChecked(getVar("TargetOnly")); QuuSpellAlertOptionsShort:SetChecked(getVar("ShortDisplay")); QuuSpellAlertOptionsEmote:SetChecked(getVar("EmoteMode")); QuuSpellAlertOptionsGain:SetChecked(getVar("GainMode")); QuuSpellAlertOptionsFade:SetChecked(getVar("FadeMode")); QuuSpellAlertOptionsAffliction:SetChecked(getVar("Afflictions")); QuuSpellAlertOptions:Show(); else QSA_OptionsClose(); end end function QSA_OptionsClose() setVar( "Enabled", QuuSpellAlertOptionsEnable:GetChecked()); setVar( "CombatOnly", QuuSpellAlertOptionsCombat:GetChecked()); setVar( "TargetOnly", QuuSpellAlertOptionsTarget:GetChecked()); setVar( "ShortDisplay", QuuSpellAlertOptionsShort:GetChecked()); setVar( "EmoteMode", QuuSpellAlertOptionsEmote:GetChecked()); setVar( "GainMode", QuuSpellAlertOptionsGain:GetChecked()); setVar( "FadeMode", QuuSpellAlertOptionsFade:GetChecked()); setVar( "Afflictions", QuuSpellAlertOptionsAffliction:GetChecked()); QuuSpellAlertOptions:Hide(); end ------------------------------------------------------------------------------- -- the init and configuration ------------------------------------------------------------------------------- function QSA_Init() QSA_Status(); -- Register our slash command SLASH_QSA1 = QSA_SLASH_COMMAND; SlashCmdList["QSA"] = function(msg) QSA_Command(msg); end if (getVar( "QSA_Hide")) then QuuSpellAlertAnchor:Hide(); end QSA_LastTarget = nil; end function QSA_Command(msg) if( msg ) then local command = string.lower(msg); if( command == "" ) then QSA_println(QSA_SLASH_COMMAND.." ["..QSA_MACRO_STATUS.."|"..QSA_MACRO_TOGGLE.."|...]"); QSA_println(" "..QSA_MACRO_STATUS.." "..QSA_MACRO_STATUS_DESC); QSA_println(" "..QSA_MACRO_TOGGLE.." "..QSA_MACRO_TOGGLE_DESC); QSA_println(" "..QSA_MACRO_REPORT.." "..QSA_MACRO_REPORT_DESC); QSA_println(" "..QSA_MACRO_TARGET.." "..QSA_MACRO_TARGET_DESC); QSA_println(" "..QSA_MACRO_SHOW.." "..QSA_MACRO_SHOW_DESC); QSA_println(" "..QSA_MACRO_EMOTE.." "..QSA_MACRO_EMOTE_DESC); QSA_println(" "..QSA_MACRO_GAIN.." "..QSA_MACRO_GAIN_DESC); QSA_println(" "..QSA_MACRO_FADE.." "..QSA_MACRO_FADE_DESC); QSA_println(" "..QSA_MACRO_COMBAT.." "..QSA_MACRO_COMBAT_DESC); QSA_println(" "..QSA_MACRO_TRGNLY.." "..QSA_MACRO_TRGNLY_DESC); QSA_println(" "..QSA_MACRO_SHORT.." "..QSA_MACRO_SHORT_DESC); QSA_println(" "..QSA_MACRO_AFFL.." "..QSA_MACRO_AFFL_DESC); QSA_println(" "..QSA_MACRO_TEST.." "..QSA_MACRO_TEST_DESC); elseif (command == QSA_MACRO_STATUS ) then QSA_Status(); elseif (command == QSA_MACRO_TOGGLE ) then toggleVar( "Enabled"); QSA_Status(); elseif (command == QSA_MACRO_REPORT ) then toggleVar( "QSA_Report"); QSA_Status(); elseif (command == QSA_MACRO_TARGET ) then QSA_TargetLast(); elseif (command == QSA_MACRO_SHOW ) then setVar( "QSA_Hide", false) QuuSpellAlertAnchor:Show(); QuuSpellAlertTimerFrame:Show(); elseif (command == QSA_MACRO_EMOTE ) then toggleVar( "EmoteMode"); QSA_Status(); elseif (command == QSA_MACRO_GAIN ) then toggleVar( "GainMode"); QSA_Status(); elseif (command == QSA_MACRO_FADE ) then toggleVar( "FadeMode"); QSA_Status(); elseif (command == QSA_MACRO_COMBAT ) then toggleVar( "CombatOnly"); QSA_Status(); elseif (command == QSA_MACRO_TRGNLY ) then toggleVar( "TargetOnly"); QSA_Status(); elseif (command == QSA_MACRO_SHORT ) then toggleVar( "ShortDisplay"); QSA_Status(); elseif (command == QSA_MACRO_AFFL ) then toggleVar( "Afflictions"); QSA_Status(); elseif (command == QSA_MACRO_TEST ) then QSA_Test(); else QSA_println( QSA_MACRO_ERROR); end end end function QSA_Test() local enabled_temp = getVar("Enabled"); local combat_temp = getVar("CombatOnly"); local target_only = getVar("TargetOnly"); setVar( "Enabled",true); setVar( "CombatOnly",false); setVar( "TargetOnly",false); -- I am not going to localize the test strings --Running through the events local creature = "Beta Death Shaman"; local emote = " is dacing to the beat!"; QSA_Event( "CHAT_MSG_MONSTER_EMOTE", emote, creature); local casting = "Uber Flame Strike"; local buffer = string.format(SPELLCASTOTHERSTART, creature, casting); QSA_Event( "CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE", buffer, nil); local performing = "Death Coil Onion"; buffer = string.format(SPELLPERFORMOTHERSTART, creature, performing); QSA_Event( "CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE", buffer, nil); local totem = "Uber "..QSA_TOTEM; buffer = string.format(SPELLCASTGOOTHER, creature, totem); QSA_Event( "CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE", buffer, nil); local aura = "Uberness"; buffer = string.format(AURAADDEDOTHERHELPFUL, creature, aura); QSA_Event( "CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE", buffer, nil); -- and displaying some information QSA_Critical("This is the Critical Alert area"); QSA_Critical("More important stuff is here"); setVar( "TargetOnly",target_only); setVar( "CombatOnly",combat_temp); setVar( "Enabled",enabled_temp); end function QSA_TargetLast() if (QSA_LastTarget ~= nil) then TargetByName(QSA_LastTarget); end end function QSA_Status() --[[ QSA_println( "Quu Spell Alert "..QSA_VERSION); if (getVar("Enabled")) then QSA_println( QSA_STATUS_ENABLED); if (QSA_Report) then QSA_println( QSA_REPORT_ENABLED); end if (getVar("EmoteMode")) then QSA_println( QSA_EMOTE_ENABLED); end if (getVar("GainMode")) then QSA_println( QSA_GAIN_ENABLED); end if (getVar("FadeMode")) then QSA_println( QSA_FADE_ENABLED); end if (getVar("CombatOnly")) then QSA_println( QSA_COMBAT_ENABLED); end if (getVar("TargetOnly")) then QSA_println( QSA_TRGONLY_ENABLED) end if (getVar("ShortDisplay")) then QSA_println( QSA_SHORT_ENABLED) end if (getVar("Afflictions")) then QSA_println( QSA_AFFL_ENABLED) end else QSA_println( QSA_STATUS_DISBALED); end ]]-- end ------------------------------------------------------------------------------- -- the display logic -- this takes the spell and caster... and determains if we alert on it ------------------------------------------------------------------------------- function QSA_ReplaceTokens( originalString, caster, effect) return string.gsub( string.gsub( originalString, "$c", caster), "$e", effect); end -- name check function function QSA_IsInParty( Name) if (Name == UnitName("player")) then return true; elseif (Name == UnitName("pet")) then return true; elseif (Name == UnitName("party1")) then return true; elseif (Name == UnitName("party2")) then return true; elseif (Name == UnitName("party3")) then return true; elseif (Name == UnitName("party4")) then return true; elseif (Name == UnitName("partypet1")) then return true; elseif (Name == UnitName("partypet2")) then return true; elseif (Name == UnitName("partypet3")) then return true; elseif (Name == UnitName("partypet4")) then return true; else local numRaidMembers = GetNumRaidMembers(); if (numRaidMembers > 0) then -- we are in a raid for i=1, numRaidMembers do RaidName = GetRaidRosterInfo(i); if ( Name == RaidName) then return true; end if ( Name == UnitName("raidpet"..i)) then return true; end end end end return false; end -- this displays the information function QSA_Display( Creature, Effect, Msg, type, bannner) if (not getVar(type)) then return; end; -- first... do we ignore it? if (QSA_IgnoreSpells[Effect]) then return; end -- then if they are in our party... ignore it if (QSA_IsInParty(Creature)) then return; end if (getVar("TargetOnly") and (UnitExists("target"))) then if (UnitName("target") ~= Creature) then return; end end -- save the name for a targetbyname possability QSA_LastTarget = Creature; if (QSA_ImportantSpells[Effect]) then -- its important... flag it if (getVar("ShortDisplay")) then QSA_Critical( QSA_ReplaceTokens(bannner, Creature, Effect)); else QSA_Critical( Msg); end else -- its not important... put a normal display if (getVar("ShortDisplay")) then QSA_Banner( QSA_ReplaceTokens(bannner, Creature, Effect)); else QSA_Banner( Msg); end end end ------------------------------------------------------------------------------- -- event block... this listens and deals with all those pesky events ------------------------------------------------------------------------------- -- this is all the events that might trip up ones we care about -- all these doe is remove potential "pitfall" alerts... spam QSA_PreConsumerStrings = { AURAADDEDSELFHELPFUL, AURADISPELSELF, AURAREMOVEDSELF, GENERICPOWERGAIN_OTHER, GENERICPOWERGAIN_SELF, PERIODICAURAHEALOTHEROTHER, PERIODICAURAHEALOTHERSELF, PERIODICAURAHEALSELFOTHER, PERIODICAURAHEALSELFSELF, POWERGAIN_OTHER, POWERGAIN_SELF, SPELLCASTGOSELF, SPELLCASTSELFSTART, SPELLEXTRAATTACKSOTHER, SPELLEXTRAATTACKSOTHER_SINGULAR, SPELLEXTRAATTACKSSELF, SPELLEXTRAATTACKSSELF_SINGULAR, SPELLPERFORMSELFSTART, SPELLPOWERDRAINOTHEROTHER, SPELLPOWERDRAINOTHERSELF, SPELLPOWERLEECHOTHEROTHER, SPELLPOWERLEECHOTHERSELF, SPELLPOWERLEECHSELFOTHER, } -- this function converts one of the globals into a search string -- this is important so we don't have to localize them function QSA_FormatGlobalStrings( globalString) local res = globalString; -- first reformat the "global" so it can be gsubed local i; for i = 1, string.len(res) do if (string.sub(res, i, i) == "%") then if (i == 1) then res = "$"..string.sub(res, 2); else res = string.sub(res, 1, i -1).."$"..string.sub(res, i + 1); end end end res = string.gsub(res, "$s", "(.+)"); res = string.gsub(res, "$d", "(%d)"); return res; end -- this is the "big" function function QSA_Event(event, arg1, arg2) -- are we enabled if (not getVar("Enabled")) then return; end -- are we in combat if ((not UnitAffectingCombat("player")) and getVar("CombatOnly")) then return; end -- first lets check for emotes if ( (event == "CHAT_MSG_EMOTE") or -- (event == "CHAT_MSG_TEXT_EMOTE") or (event == "CHAT_MSG_MONSTER_EMOTE") ) then -- got one... process it for display QSA_Display( arg2, arg1, arg2.." "..arg1, "EmoteMode", QSA_EMOTE_BANNER); return; elseif ( (event == "CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE") or (event == "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE") or (event == "CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE") ) then -- looks like we have somethign effecting the party if (getVar("Afflictions")) then for effect in string.gfind(arg1,QSA_FormatGlobalStrings(AURAADDEDSELFHARMFUL)) do if (getVar("Afflictions")) then if (QSA_Alert_Afflictions[effect]) then QSA_Critical(arg1); end end return; end -- now we look to see if a team member is afflicted with somethign we care about for player, effect in string.gfind(arg1,QSA_FormatGlobalStrings(AURAADDEDOTHERHARMFUL)) do --AURAADDEDOTHERHARMFUL = "%s is afflicted by %s."; -- Combat log text for aura events if (QSA_Alert_Afflictions[effect]) then QSA_Critical(arg1); end return; end end else -- first remove any troublesome strings that might trip up the real ones for key, value in QSA_PreConsumerStrings do for _ in string.gfind(arg1,QSA_FormatGlobalStrings(value)) do if (QSA_Debug) then if ( not QSA_DebugArray.preConsumed) then QSA_DebugArray.preConsumed = { }; end QSA_DebugArray.preConsumed[arg1] = event; end return; end end -- now parse the different spells we listen to local mob = ""; local effect = ""; for mob, effect in string.gfind(arg1,QSA_FormatGlobalStrings(SPELLCASTOTHERSTART)) do QSA_Display( mob, effect, arg1, "Enabled", QSA_CASTING_BANNER); return; end for mob, effect in string.gfind(arg1,QSA_FormatGlobalStrings(SPELLPERFORMOTHERSTART)) do QSA_Display( mob, effect, arg1, "Enabled", QSA_CASTING_BANNER); return; end for mob, effect in string.gfind(arg1,QSA_FormatGlobalStrings(SPELLCASTGOOTHER)) do if (string.find(effect, QSA_TOTEM)) then QSA_Display( mob, effect, arg1, "Enabled", QSA_CASTING_BANNER); end return; end for effect, mob in string.gfind(arg1,QSA_FormatGlobalStrings(AURAREMOVEDOTHER)) do QSA_Display( mob, effect, arg1, "FadeMode", QSA_FADE_BANNER); return; end for mob, effect in string.gfind(arg1,QSA_FormatGlobalStrings(AURADISPELOTHER)) do QSA_Display( mob, effect, arg1, "FadeMode", QSA_FADE_BANNER); return; end for mob, effect in string.gfind(arg1,QSA_FormatGlobalStrings(AURAADDEDOTHERHELPFUL)) do QSA_Display( mob, effect, arg1, "GainMode", QSA_GAIN_BANNER); return; end -- GAIN2 is for when a mob gets a bad status ailment... -- we don't normally care about that... so only do it -- if it is an important event. for mob, effect in string.gfind(arg1,QSA_FormatGlobalStrings(AURAADDEDOTHERHARMFUL)) do if (QSA_ImportantSpells[effect]) then QSA_Display( mob, effect, arg1, "GainMode", QSA_GAIN_BANNER); end return; end end end