--[[
-- Blizzard Combat Log
-- by Alexander Yoshi
--
-- This is a prototype combat log designed to serve the
-- majority of needs for WoW players. The new and improved
-- combat log event formatting should allow for the community
-- to develop even better combat logs in the future.
--
-- Thanks to:
-- Chris Heald & Xinhuan - Code Optimization Support
--
--]]
-- Version
-- Constant -- Incrementing this number will erase saved filter settings!!
COMBATLOG_FILTER_VERSION = 4.3;
-- Saved Variable
Blizzard_CombatLog_Filter_Version = 0;
-- Define the log
COMBATLOG = ChatFrame2;
-- BUFF / DEBUFF
AURA_TYPE_BUFF = "BUFF";
AURA_TYPE_DEBUFF = "DEBUFF"
-- Message Limit
COMBATLOG_LIMIT_PER_FRAME = 1;
COMBATLOG_HIGHLIGHT_MULTIPLIER = 1.5;
-- Default Colors
COMBATLOG_DEFAULT_COLORS = {
-- Unit names
unitColoring = {
[COMBATLOG_FILTER_MINE] = {a=1.0,r=0.70,g=0.70,b=0.70}; --{a=1.0,r=0.14,g=1.00,b=0.15};
[COMBATLOG_FILTER_MY_PET] = {a=1.0,r=0.70,g=0.70,b=0.70}; --{a=1.0,r=0.14,g=0.80,b=0.15};
[COMBATLOG_FILTER_FRIENDLY_UNITS] = {a=1.0,r=0.34,g=0.64,b=1.00};
[COMBATLOG_FILTER_HOSTILE_UNITS] = {a=1.0,r=0.75,g=0.05,b=0.05};
[COMBATLOG_FILTER_HOSTILE_PLAYERS] = {a=1.0,r=0.75,g=0.05,b=0.05};
[COMBATLOG_FILTER_NEUTRAL_UNITS] = {a=1.0,r=0.75,g=0.05,b=0.05}; -- {a=1.0,r=0.80,g=0.80,b=0.14};
[COMBATLOG_FILTER_UNKNOWN_UNITS] = {a=1.0,r=0.75,g=0.75,b=0.75};
};
-- School coloring
schoolColoring = {
[SCHOOL_MASK_NONE] = {a=1.0,r=1.00,g=1.00,b=1.00};
[SCHOOL_MASK_PHYSICAL] = {a=1.0,r=1.00,g=1.00,b=0.00};
[SCHOOL_MASK_HOLY] = {a=1.0,r=1.00,g=0.90,b=0.50};
[SCHOOL_MASK_FIRE] = {a=1.0,r=1.00,g=0.50,b=0.00};
[SCHOOL_MASK_NATURE] = {a=1.0,r=0.30,g=1.00,b=0.30};
[SCHOOL_MASK_FROST] = {a=1.0,r=0.50,g=1.00,b=1.00};
[SCHOOL_MASK_SHADOW] = {a=1.0,r=0.50,g=0.50,b=1.00};
[SCHOOL_MASK_ARCANE] = {a=1.0,r=1.00,g=0.50,b=1.00};
};
-- Defaults
defaults = {
spell = {a=1.0,r=1.00,g=1.00,b=1.00};
damage = {a=1.0,r=1.00,g=1.00,b=0.00};
};
-- Line coloring
eventColoring = {
};
-- Highlighted events
highlightedEvents = {
["PARTY_KILL"] = true;
};
};
COMBATLOG_DEFAULT_SETTINGS = {
-- Settings
fullText = false;
textMode = TEXT_MODE_A;
timestamp = false;
timestampFormat = TEXT_MODE_A_TIMESTAMP;
unitColoring = false;
sourceColoring = true;
destColoring = true;
lineColoring = true;
lineHighlighting = true;
abilityColoring = false;
abilityActorColoring = false;
abilitySchoolColoring = false;
abilityHighlighting = true;
actionColoring = false;
actionActorColoring = false;
actionHighlighting = false;
amountColoring = false;
amountActorColoring = false;
amountSchoolColoring = false;
amountHighlighting = true;
schoolNameColoring = false;
schoolNameActorColoring = false;
schoolNameHighlighting = true;
noMeleeSwingColoring = false;
missColoring = true;
braces = false;
unitBraces = true;
sourceBraces = true;
destBraces = true;
spellBraces = false;
itemBraces = true;
showHistory = true;
lineColorPriority = 1; -- 1 = source->dest->event, 2 = dest->source->event, 3 = event->source->dest
unitIcons = true;
hideBuffs = true;
hideDebuffs = true;
--unitTokens = true;
};
--
-- Combat Log Icons
--
COMBATLOG_ICON_RAIDTARGET1 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_1.blp:0|t";
COMBATLOG_ICON_RAIDTARGET2 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_2.blp:0|t";
COMBATLOG_ICON_RAIDTARGET3 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_3.blp:0|t";
COMBATLOG_ICON_RAIDTARGET4 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_4.blp:0|t";
COMBATLOG_ICON_RAIDTARGET5 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_5.blp:0|t";
COMBATLOG_ICON_RAIDTARGET6 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_6.blp:0|t";
COMBATLOG_ICON_RAIDTARGET7 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_7.blp:0|t";
COMBATLOG_ICON_RAIDTARGET8 = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_8.blp:0|t";
--
-- Default Event List
--
COMBATLOG_EVENT_LIST = {
["ENVIRONMENTAL_DAMAGE"] = true,
["SWING_DAMAGE"] = true,
["SWING_MISSED"] = true,
["RANGE_DAMAGE"] = true,
["RANGE_MISSED"] = true,
["SPELL_CAST_START"] = false,
["SPELL_CAST_SUCCESS"] = false,
["SPELL_CAST_FAILED"] = false,
["SPELL_MISSED"] = true,
["SPELL_DAMAGE"] = true,
["SPELL_HEAL"] = true,
["SPELL_ENERGIZE"] = true,
["SPELL_DRAIN"] = true,
["SPELL_LEECH"] = true,
["SPELL_SUMMON"] = true,
["SPELL_RESURRECT"] = true,
["SPELL_CREATE"] = true,
["SPELL_INSTAKILL"] = true,
["SPELL_INTERRUPT"] = true,
["SPELL_EXTRA_ATTACKS"] = true,
["SPELL_DURABILITY_DAMAGE"] = false,
["SPELL_DURABILITY_DAMAGE_ALL"] = false,
["SPELL_AURA_APPLIED"] = false,
["SPELL_AURA_APPLIED_DOSE"] = false,
["SPELL_AURA_REMOVED"] = false,
["SPELL_AURA_REMOVED_DOSE"] = false,
["SPELL_AURA_BROKEN"] = false,
["SPELL_AURA_BROKEN_SPELL"] = false,
["SPELL_AURA_REFRESH"] = false,
["SPELL_DISPEL"] = true,
["SPELL_STOLEN"] = true,
["ENCHANT_APPLIED"] = true,
["ENCHANT_REMOVED"] = true,
["SPELL_PERIODIC_MISSED"] = true,
["SPELL_PERIODIC_DAMAGE"] = true,
["SPELL_PERIODIC_HEAL"] = true,
["SPELL_PERIODIC_ENERGIZE"] = true,
["SPELL_PERIODIC_DRAIN"] = true,
["SPELL_PERIODIC_LEECH"] = true,
["SPELL_DISPEL_FAILED"] = true,
["DAMAGE_SHIELD"] = false,
["DAMAGE_SHIELD_MISSED"] = false,
["DAMAGE_SPLIT"] = false,
["PARTY_KILL"] = true,
["UNIT_DIED"] = true,
["UNIT_DESTROYED"] = true,
["SPELL_BUILDING_DAMAGE"] = true,
["SPELL_BUILDING_HEAL"] = true,
["UNIT_DISSIPATES"] = true,
};
COMBATLOG_FLAG_LIST = {
[COMBATLOG_FILTER_MINE] = true,
[COMBATLOG_FILTER_MY_PET] = true,
[COMBATLOG_FILTER_FRIENDLY_UNITS] = true,
[COMBATLOG_FILTER_HOSTILE_UNITS] = true,
[COMBATLOG_FILTER_HOSTILE_PLAYERS] = true,
[COMBATLOG_FILTER_NEUTRAL_UNITS] = true,
[COMBATLOG_FILTER_UNKNOWN_UNITS] = true,
};
EVENT_TEMPLATE_FORMATS = {
["SPELL_AURA_BROKEN_SPELL"] = TEXT_MODE_A_STRING_3,
["SPELL_CAST_START"] = TEXT_MODE_A_STRING_2,
["SPELL_CAST_SUCCESS"] = TEXT_MODE_A_STRING_2
};
--
-- Creates an empty filter
--
function Blizzard_CombatLog_InitializeFilters( settings )
settings.filters =
{
[1] = {
eventList = {};
};
};
end
--
-- Generates a new event list from the COMBATLOG_EVENT_LIST global
--
-- I wish there was a better way built in to do this.
--
-- Returns:
-- An array, indexed by the events, with a value of true
--
function Blizzard_CombatLog_GenerateFullEventList ( )
local eventList = {}
for event, v in pairs ( COMBATLOG_EVENT_LIST ) do
eventList[event] = true;
end
return eventList;
end
function Blizzard_CombatLog_GenerateFullFlagList(flag)
local flagList = {};
for k, v in pairs(COMBATLOG_FLAG_LIST) do
if ( flag ) then
flagList[k] = true
else
flagList[k] = false;
end
end
return flagList;
end
--
-- Default CombatLog Filter
-- This table is used to create new CombatLog filters
--
DEFAULT_COMBATLOG_FILTER_TEMPLATE = {
-- Descriptive Information
hasQuickButton = true;
quickButtonDisplay = {
solo = true;
party = true;
raid = true;
};
-- Default Color and Formatting Options
settings = CopyTable(COMBATLOG_DEFAULT_SETTINGS);
-- Coloring
colors = CopyTable(COMBATLOG_DEFAULT_COLORS);
-- The actual client filters
filters = {
[1] = {
eventList = Blizzard_CombatLog_GenerateFullEventList();
sourceFlags = {
[COMBATLOG_FILTER_MINE] = true,
[COMBATLOG_FILTER_MY_PET] = true;
};
destFlags = nil;
};
[2] = {
eventList = Blizzard_CombatLog_GenerateFullEventList();
sourceFlags = nil;
destFlags = {
[COMBATLOG_FILTER_MINE] = true,
[COMBATLOG_FILTER_MY_PET] = true;
};
};
};
};
local CombatLogUpdateFrame = CreateFrame("Frame", "CombatLogUpdateFrame", UIParent)
local _G = getfenv(0)
local bit_bor = _G.bit.bor
local bit_band = _G.bit.band
local tinsert = _G.tinsert
local tremove = _G.tremove
local math_floor = _G.math.floor
local format = _G.format
local gsub = _G.gsub
local strsub = _G.strsub
-- Make all the constants upvalues. This prevents the global environment lookup + table lookup each time we use one (and they're used a lot)
local COMBATLOG_OBJECT_AFFILIATION_MINE = COMBATLOG_OBJECT_AFFILIATION_MINE
local COMBATLOG_OBJECT_AFFILIATION_PARTY = COMBATLOG_OBJECT_AFFILIATION_PARTY
local COMBATLOG_OBJECT_AFFILIATION_RAID = COMBATLOG_OBJECT_AFFILIATION_RAID
local COMBATLOG_OBJECT_AFFILIATION_OUTSIDER = COMBATLOG_OBJECT_AFFILIATION_OUTSIDER
local COMBATLOG_OBJECT_AFFILIATION_MASK = COMBATLOG_OBJECT_AFFILIATION_MASK
local COMBATLOG_OBJECT_REACTION_FRIENDLY = COMBATLOG_OBJECT_REACTION_FRIENDLY
local COMBATLOG_OBJECT_REACTION_NEUTRAL = COMBATLOG_OBJECT_REACTION_NEUTRAL
local COMBATLOG_OBJECT_REACTION_HOSTILE = COMBATLOG_OBJECT_REACTION_HOSTILE
local COMBATLOG_OBJECT_REACTION_MASK = COMBATLOG_OBJECT_REACTION_MASK
local COMBATLOG_OBJECT_CONTROL_PLAYER = COMBATLOG_OBJECT_CONTROL_PLAYER
local COMBATLOG_OBJECT_CONTROL_NPC = COMBATLOG_OBJECT_CONTROL_NPC
local COMBATLOG_OBJECT_CONTROL_MASK = COMBATLOG_OBJECT_CONTROL_MASK
local COMBATLOG_OBJECT_TYPE_PLAYER = COMBATLOG_OBJECT_TYPE_PLAYER
local COMBATLOG_OBJECT_TYPE_NPC = COMBATLOG_OBJECT_TYPE_NPC
local COMBATLOG_OBJECT_TYPE_PET = COMBATLOG_OBJECT_TYPE_PET
local COMBATLOG_OBJECT_TYPE_GUARDIAN = COMBATLOG_OBJECT_TYPE_GUARDIAN
local COMBATLOG_OBJECT_TYPE_OBJECT = COMBATLOG_OBJECT_TYPE_OBJECT
local COMBATLOG_OBJECT_TYPE_MASK = COMBATLOG_OBJECT_TYPE_MASK
local COMBATLOG_OBJECT_TARGET = COMBATLOG_OBJECT_TARGET
local COMBATLOG_OBJECT_FOCUS = COMBATLOG_OBJECT_FOCUS
local COMBATLOG_OBJECT_MAINTANK = COMBATLOG_OBJECT_MAINTANK
local COMBATLOG_OBJECT_MAINASSIST = COMBATLOG_OBJECT_MAINASSIST
local COMBATLOG_OBJECT_RAIDTARGET1 = COMBATLOG_OBJECT_RAIDTARGET1
local COMBATLOG_OBJECT_RAIDTARGET2 = COMBATLOG_OBJECT_RAIDTARGET2
local COMBATLOG_OBJECT_RAIDTARGET3 = COMBATLOG_OBJECT_RAIDTARGET3
local COMBATLOG_OBJECT_RAIDTARGET4 = COMBATLOG_OBJECT_RAIDTARGET4
local COMBATLOG_OBJECT_RAIDTARGET5 = COMBATLOG_OBJECT_RAIDTARGET5
local COMBATLOG_OBJECT_RAIDTARGET6 = COMBATLOG_OBJECT_RAIDTARGET6
local COMBATLOG_OBJECT_RAIDTARGET7 = COMBATLOG_OBJECT_RAIDTARGET7
local COMBATLOG_OBJECT_RAIDTARGET8 = COMBATLOG_OBJECT_RAIDTARGET8
local COMBATLOG_OBJECT_NONE = COMBATLOG_OBJECT_NONE
local COMBATLOG_OBJECT_SPECIAL_MASK = COMBATLOG_OBJECT_SPECIAL_MASK
local COMBATLOG_FILTER_ME = COMBATLOG_FILTER_ME
local COMBATLOG_FILTER_MINE = COMBATLOG_FILTER_MINE
local COMBATLOG_FILTER_MY_PET = COMBATLOG_FILTER_MY_PET
local COMBATLOG_FILTER_FRIENDLY_UNITS = COMBATLOG_FILTER_FRIENDLY_UNITS
local COMBATLOG_FILTER_HOSTILE_UNITS = COMBATLOG_FILTER_HOSTILE_UNITS
local COMBATLOG_FILTER_HOSTILE_PLAYERS = COMBATLOG_FILTER_HOSTILE_PLAYERS
local COMBATLOG_FILTER_NEUTRAL_UNITS = COMBATLOG_FILTER_NEUTRAL_UNITS
local COMBATLOG_FILTER_UNKNOWN_UNITS = COMBATLOG_FILTER_UNKNOWN_UNITS
local COMBATLOG_FILTER_EVERYTHING = COMBATLOG_FILTER_EVERYTHING
local COMBATLOG = COMBATLOG
local AURA_TYPE_BUFF = AURA_TYPE_BUFF
local AURA_TYPE_DEBUFF = AURA_TYPE_DEBUFF
local SPELL_POWER_MANA = SPELL_POWER_MANA
local SPELL_POWER_RAGE = SPELL_POWER_RAGE
local SPELL_POWER_FOCUS = SPELL_POWER_FOCUS
local SPELL_POWER_ENERGY = SPELL_POWER_ENERGY
local SPELL_POWER_RUNES = SPELL_POWER_RUNES
local SPELL_POWER_RUNIC_POWER = SPELL_POWER_RUNIC_POWER
local SPELL_POWER_SOUL_SHARDS = SPELL_POWER_SOUL_SHARDS;
local SPELL_POWER_ECLIPSE = SPELL_POWER_ECLIPSE;
local SPELL_POWER_HOLY_POWER = SPELL_POWER_HOLY_POWER;
local SPELL_POWER_ALTERNATE_POWER = SPELL_POWER_ALTERNATE_POWER;
local SPELL_POWER_BURNING_EMBERS = SPELL_POWER_BURNING_EMBERS;
local SCHOOL_MASK_NONE = SCHOOL_MASK_NONE
local SCHOOL_MASK_PHYSICAL = SCHOOL_MASK_PHYSICAL
local SCHOOL_MASK_HOLY = SCHOOL_MASK_HOLY
local SCHOOL_MASK_FIRE = SCHOOL_MASK_FIRE
local SCHOOL_MASK_NATURE = SCHOOL_MASK_NATURE
local SCHOOL_MASK_FROST = SCHOOL_MASK_FROST
local SCHOOL_MASK_SHADOW = SCHOOL_MASK_SHADOW
local SCHOOL_MASK_ARCANE = SCHOOL_MASK_ARCANE
local COMBATLOG_LIMIT_PER_FRAME = COMBATLOG_LIMIT_PER_FRAME
local COMBATLOG_HIGHLIGHT_MULTIPLIER = COMBATLOG_HIGHLIGHT_MULTIPLIER
local COMBATLOG_DEFAULT_COLORS = COMBATLOG_DEFAULT_COLORS
local COMBATLOG_DEFAULT_SETTINGS = COMBATLOG_DEFAULT_SETTINGS
local COMBATLOG_ICON_RAIDTARGET1 = COMBATLOG_ICON_RAIDTARGET1
local COMBATLOG_ICON_RAIDTARGET2 = COMBATLOG_ICON_RAIDTARGET2
local COMBATLOG_ICON_RAIDTARGET3 = COMBATLOG_ICON_RAIDTARGET3
local COMBATLOG_ICON_RAIDTARGET4 = COMBATLOG_ICON_RAIDTARGET4
local COMBATLOG_ICON_RAIDTARGET5 = COMBATLOG_ICON_RAIDTARGET5
local COMBATLOG_ICON_RAIDTARGET6 = COMBATLOG_ICON_RAIDTARGET6
local COMBATLOG_ICON_RAIDTARGET7 = COMBATLOG_ICON_RAIDTARGET7
local COMBATLOG_ICON_RAIDTARGET8 = COMBATLOG_ICON_RAIDTARGET8
local COMBATLOG_EVENT_LIST = COMBATLOG_EVENT_LIST
local CombatLog_OnEvent -- for later
local CombatLog_Object_IsA = CombatLog_Object_IsA
-- Create a dummy CombatLogQuickButtonFrame for line 803 of FloatingChatFrame.lua. It causes inappropriate show/hide behavior. Instead, we'll use our own frame display handling.
-- If there are more than 2 combat log frames, then the CombatLogQuickButtonFrame gets tied to the last frame tab's visibility status. Yuck! Let's just instead tie it to the combat log's tab.
local CombatLogQuickButtonFrame, CombatLogQuickButtonFrameProgressBar, CombatLogQuickButtonFrameTexture
_G.CombatLogQuickButtonFrame = CreateFrame("Frame", "CombatLogQuickButtonFrame", UIParent)
local Blizzard_CombatLog_Update_QuickButtons
local Blizzard_CombatLog_PreviousSettings
--
-- Persistant Variables
--
--
-- Default Filters
--
Blizzard_CombatLog_Filter_Defaults = {
-- All of the filters
filters = {
[1] = {
-- Descriptive Information
name = QUICKBUTTON_NAME_MY_ACTIONS;
hasQuickButton = true;
quickButtonName = QUICKBUTTON_NAME_MY_ACTIONS;
quickButtonDisplay = {
solo = true;
party = true;
raid = true;
};
tooltip = QUICKBUTTON_NAME_MY_ACTIONS_TOOLTIP;
-- Default Color and Formatting Options
settings = CopyTable(COMBATLOG_DEFAULT_SETTINGS);
-- Coloring
colors = CopyTable(COMBATLOG_DEFAULT_COLORS);
-- The actual client filters
filters = {
[1] = {
eventList = {
["ENVIRONMENTAL_DAMAGE"] = false,
["SWING_DAMAGE"] = true,
["SWING_MISSED"] = false,
["RANGE_DAMAGE"] = true,
["RANGE_MISSED"] = false,
--["SPELL_CAST_START"] = true,
--["SPELL_CAST_SUCCESS"] = true,
--["SPELL_CAST_FAILED"] = true,
["SPELL_MISSED"] = false,
["SPELL_DAMAGE"] = true,
["SPELL_HEAL"] = true,
["SPELL_ENERGIZE"] = false,
["SPELL_DRAIN"] = false,
["SPELL_LEECH"] = false,
["SPELL_INSTAKILL"] = false,
["SPELL_INTERRUPT"] = false,
["SPELL_EXTRA_ATTACKS"] = false,
--["SPELL_DURABILITY_DAMAGE"] = true,
--["SPELL_DURABILITY_DAMAGE_ALL"] = true,
["SPELL_AURA_APPLIED"] = false,
["SPELL_AURA_APPLIED_DOSE"] = false,
["SPELL_AURA_REMOVED"] = false,
["SPELL_AURA_REMOVED_DOSE"] = false,
["SPELL_AURA_BROKEN"] = false,
["SPELL_AURA_BROKEN_SPELL"] = false,
["SPELL_AURA_REFRESH"] = false,
["SPELL_DISPEL"] = false,
["SPELL_STOLEN"] = false,
["ENCHANT_APPLIED"] = false,
["ENCHANT_REMOVED"] = false,
["SPELL_PERIODIC_MISSED"] = false,
["SPELL_PERIODIC_DAMAGE"] = true,
["SPELL_PERIODIC_HEAL"] = true,
["SPELL_PERIODIC_ENERGIZE"] = false,
["SPELL_PERIODIC_DRAIN"] = false,
["SPELL_PERIODIC_LEECH"] = false,
["SPELL_DISPEL_FAILED"] = false,
--["DAMAGE_SHIELD"] = true,
--["DAMAGE_SHIELD_MISSED"] = true,
["DAMAGE_SPLIT"] = true,
["PARTY_KILL"] = true,
["UNIT_DIED"] = false,
["UNIT_DESTROYED"] = true,
["UNIT_DISSIPATES"] = true
};
sourceFlags = {
[COMBATLOG_FILTER_MINE] = true
};
destFlags = nil;
};
[2] = {
eventList = {
--["ENVIRONMENTAL_DAMAGE"] = true,
["SWING_DAMAGE"] = true,
["SWING_MISSED"] = true,
["RANGE_DAMAGE"] = true,
["RANGE_MISSED"] = true,
--["SPELL_CAST_START"] = true,
--["SPELL_CAST_SUCCESS"] = true,
--["SPELL_CAST_FAILED"] = true,
["SPELL_MISSED"] = true,
["SPELL_DAMAGE"] = true,
["SPELL_HEAL"] = true,
["SPELL_ENERGIZE"] = true,
["SPELL_DRAIN"] = true,
["SPELL_LEECH"] = true,
["SPELL_INSTAKILL"] = true,
["SPELL_INTERRUPT"] = true,
["SPELL_EXTRA_ATTACKS"] = true,
--["SPELL_DURABILITY_DAMAGE"] = true,
--["SPELL_DURABILITY_DAMAGE_ALL"] = true,
--["SPELL_AURA_APPLIED"] = true,
--["SPELL_AURA_APPLIED_DOSE"] = true,
--["SPELL_AURA_REMOVED"] = true,
--["SPELL_AURA_REMOVED_DOSE"] = true,
["SPELL_DISPEL"] = true,
["SPELL_STOLEN"] = true,
["ENCHANT_APPLIED"] = true,
["ENCHANT_REMOVED"] = true,
--["SPELL_PERIODIC_MISSED"] = true,
--["SPELL_PERIODIC_DAMAGE"] = true,
--["SPELL_PERIODIC_HEAL"] = true,
--["SPELL_PERIODIC_ENERGIZE"] = true,
--["SPELL_PERIODIC_DRAIN"] = true,
--["SPELL_PERIODIC_LEECH"] = true,
["SPELL_DISPEL_FAILED"] = true,
--["DAMAGE_SHIELD"] = true,
--["DAMAGE_SHIELD_MISSED"] = true,
["DAMAGE_SPLIT"] = true,
["PARTY_KILL"] = true,
["UNIT_DIED"] = true,
["UNIT_DESTROYED"] = true,
["UNIT_DISSIPATES"] = true
};
sourceFlags = nil;
destFlags = {
[COMBATLOG_FILTER_MINE] = false,
[COMBATLOG_FILTER_MY_PET] = false;
};
};
};
};
[2] = {
-- Descriptive Information
name = QUICKBUTTON_NAME_ME;
hasQuickButton = true;
quickButtonName = QUICKBUTTON_NAME_ME;
quickButtonDisplay = {
solo = true;
party = true;
raid = true;
};
tooltip = QUICKBUTTON_NAME_ME_TOOLTIP;
-- Settings
settings = CopyTable(COMBATLOG_DEFAULT_SETTINGS);
-- Coloring
colors = CopyTable(COMBATLOG_DEFAULT_COLORS);
-- The actual client filters
filters = {
[1] = {
eventList = {
["ENVIRONMENTAL_DAMAGE"] = true,
["SWING_DAMAGE"] = true,
["RANGE_DAMAGE"] = true,
["SPELL_DAMAGE"] = true,
["SPELL_HEAL"] = true,
["SPELL_PERIODIC_DAMAGE"] = true,
["SPELL_PERIODIC_HEAL"] = true,
["DAMAGE_SPLIT"] = true,
["UNIT_DIED"] = true,
["UNIT_DESTROYED"] = true,
["UNIT_DISSIPATES"] = true
};
sourceFlags = Blizzard_CombatLog_GenerateFullFlagList(false);
destFlags = nil;
};
[2] = {
eventList = Blizzard_CombatLog_GenerateFullEventList();
sourceFlags = nil;
destFlags = {
[COMBATLOG_FILTER_MINE] = true,
[COMBATLOG_FILTER_MY_PET] = false;
};
};
};
};
};
-- Current Filter
currentFilter = 1;
};
Blizzard_CombatLog_Filters = Blizzard_CombatLog_Filter_Defaults;
-- Combat Log Filter Resetting Code
--
-- args:
-- config - the configuration array we are about to apply
--
function Blizzard_CombatLog_ApplyFilters(config)
if ( not config ) then
return;
end
CombatLogResetFilter()
-- Loop over all associated filters
local eventList;
for k,v in pairs(config.filters) do
local eList
-- Only use the first filter's eventList because for some reason each filter that the player can see actually
-- has two filters, one for source flags and one for dest flags (??), even though only the eventList for the source
-- flags is updated properly
eventList = config.filters[1].eventList;
if ( eventList ) then
for k2,v2 in pairs(eventList) do
if ( v2 == true ) then
-- The true comparison is because check boxes whose parent is unchecked will be non-false but not "true"
eList = eList and (eList .. "," .. k2) or k2
end
end
end
local sourceFlags, destFlags;
if ( v.sourceFlags ) then
sourceFlags = 0;
for k2, v2 in pairs(v.sourceFlags) do
-- Support for GUIDs
if ( type (k2) == "string" ) then
sourceFlags = k2;
break;
end
-- Otherwise OR bits
if ( v2 ) then
sourceFlags = bit_bor(sourceFlags, k2);
end
end
end
if ( v.destFlags ) then
destFlags = 0;
for k2, v2 in pairs(v.destFlags) do
-- Support for GUIDs
if ( type (k2) == "string" ) then
destFlags = k2;
break;
end
-- Otherwise OR bits
if ( v2 ) then
destFlags = bit_bor(destFlags, k2);
end
end
end
if ( type(sourceFlags) == "string" and destFlags == 0 ) then
destFlags = nil;
end
if ( type(destFlags) == "string" and sourceFlags == 0 ) then
sourceFlags = nil;
end
-- This is a HACK!!! Need filters to be able to accept empty or zero sourceFlags or destFlags
if ( sourceFlags == 0 or destFlags == 0 ) then
CombatLogAddFilter("", COMBATLOG_FILTER_MINE, nil);
else
CombatLogAddFilter(eList, sourceFlags, destFlags);
end
end
end
--
-- Combat Log Repopulation Code
--
-- Message Limit
COMBATLOG_MESSAGE_LIMIT = 300;
--
-- Repopulate the combat log with message history
--
function Blizzard_CombatLog_Refilter()
local count = CombatLogGetNumEntries();
COMBATLOG:SetMaxLines(COMBATLOG_MESSAGE_LIMIT);
-- count should be between 1 and COMBATLOG_MESSAGE_LIMIT
count = max(1, min(count, COMBATLOG_MESSAGE_LIMIT));
CombatLogSetCurrentEntry(0);
-- Clear the combat log
COMBATLOG:Clear();
-- Moved setting the max value here, since we don't really need to reset the max every frame, do we?
-- We can't add events while refiltering (:AddFilter short circuits) so this should be safe optimization.
CombatLogQuickButtonFrameProgressBar:SetMinMaxValues(0, count);
CombatLogQuickButtonFrameProgressBar:SetValue(0);
CombatLogQuickButtonFrameProgressBar:Show();
-- Enable the distributed frame
CombatLogUpdateFrame.refiltering = true;
CombatLogUpdateFrame:SetScript("OnUpdate", Blizzard_CombatLog_RefilterUpdate)
Blizzard_CombatLog_RefilterUpdate()
end
--
-- This is a single frame "step" in the refiltering process
--
function Blizzard_CombatLog_RefilterUpdate()
local valid = CombatLogGetCurrentEntry(); -- CombatLogAdvanceEntry(0);
-- Clear the combat log
local total = 0;
while (valid and total < COMBATLOG_LIMIT_PER_FRAME) do
-- Log to the window
local text, r, g, b, a = CombatLog_OnEvent(Blizzard_CombatLog_CurrentSettings, CombatLogGetCurrentEntry());
-- NOTE: be sure to pass in nil for the color id or the color id may override the r, g, b values for this message
if ( text ) then
COMBATLOG:AddMessage( text, r, g, b, nil, true );
end
-- count can be
-- positive to advance from oldest to newest
-- negative to advance from newest to oldest
valid = CombatLogAdvanceEntry(-1)
total = total + 1;
end
-- Show filtering progress bar
CombatLogQuickButtonFrameProgressBar:SetValue(CombatLogQuickButtonFrameProgressBar:GetValue() + total);
if ( not valid or (CombatLogQuickButtonFrameProgressBar:GetValue() >= COMBATLOG_MESSAGE_LIMIT) ) then
CombatLogUpdateFrame.refiltering = false
CombatLogUpdateFrame:SetScript("OnUpdate", nil)
CombatLogQuickButtonFrameProgressBar:Hide();
end
end
--
-- Checks for an event over all filters
--
function Blizzard_CombatLog_HasEvent ( settings, ... )
-- If this actually happens, we have data corruption issues.
if ( not settings.filters ) then
settings.filters = {}
end
for _, filter in pairs (settings.filters) do
if ( filter.eventList ) then
for i = 1, select("#", ...) do
local event = select(i, ...)
if ( filter.eventList[event] == true ) then
return true
end
end
end
end
end
--
-- Checks for an event over all filters
--
function Blizzard_CombatLog_EnableEvent ( settings, ... )
-- If this actually happens, we have data corruption issues.
if ( not settings.filters ) then
settings.filters = Blizzard_CombatLog_InitializeFilters( settings );
end
for _, filter in pairs (settings.filters) do
if ( not filter.eventList ) then
filter.eventList = {};
end
for i = 1, select("#", ...) do
filter.eventList[select(i, ...)] = true;
end
end
end
--
-- Checks for an event over all filters
--
function Blizzard_CombatLog_DisableEvent ( settings, ... )
-- If this actually happens, we have data corruption issues.
if ( not settings.filters ) then
settings.filters = {}
end
for _, filter in pairs (settings.filters) do
if ( filter.eventList ) then
for i = 1, select("#", ...) do
filter.eventList[select(i, ...)] = false;
end
end
end
end
--
-- Creates the action menu popup
--
do
local eventType
local actionMenu = {
[1] = {
text = "string.format(BLIZZARD_COMBAT_LOG_MENU_SPELL_HIDE, eventType)",
func = function () Blizzard_CombatLog_SpellMenuClick ("HIDE", nil, nil, eventType); end;
},
};
function Blizzard_CombatLog_CreateActionMenu(eventType_arg)
-- Update upvalues
eventType = eventType_arg
actionMenu[1].text = string.format(BLIZZARD_COMBAT_LOG_MENU_SPELL_HIDE, eventType_arg);
return actionMenu
end
end
--
-- Creates the spell menu popup
--
do
local spellName, spellId, eventType
local spellMenu = {
[1] = {
text = "string.format(BLIZZARD_COMBAT_LOG_MENU_SPELL_LINK, spellName)",
func = function () Blizzard_CombatLog_SpellMenuClick ("LINK", spellName, spellId, eventType); end;
},
};
local spellMenu2 = {
[2] = {
text = "string.format(BLIZZARD_COMBAT_LOG_MENU_SPELL_HIDE, eventType)",
func = function () Blizzard_CombatLog_SpellMenuClick ("HIDE", spellName, spellId, eventType); end;
},
[3] = {
text = "------------------";
disabled = true;
},
};
function Blizzard_CombatLog_CreateSpellMenu(spellName_arg, spellId_arg, eventType_arg)
-- Update upvalues
spellName, spellId, eventType = spellName_arg, spellId_arg, eventType_arg;
-- Update menu text and filters
spellMenu[1].text = string.format(BLIZZARD_COMBAT_LOG_MENU_SPELL_LINK, spellName);
if ( eventType ) then
spellMenu2[2].text = string.format(BLIZZARD_COMBAT_LOG_MENU_SPELL_HIDE, eventType);
-- Copy the table references over
spellMenu[2] = spellMenu2[2];
if ( DEBUG ) then
spellMenu[3] = spellMenu2[3];
-- These 2 calls update the menus in their respective do-end blocks
spellMenu[4] = Blizzard_CombatLog_FormattingMenu(Blizzard_CombatLog_Filters.currentFilter);
spellMenu[5] = Blizzard_CombatLog_MessageTypesMenu(Blizzard_CombatLog_Filters.currentFilter);
end
else
-- Remove the table references, they are still stored in their various closures
spellMenu[2] = nil;
spellMenu[3] = nil;
spellMenu[4] = nil;
spellMenu[5] = nil;
end
return spellMenu;
end
end
--
-- Temporary Menu
--
do
-- This big table currently only has one upvalue: Blizzard_CombatLog_CurrentSettings
local messageTypesMenu = {
text = "Message Types";
hasArrow = true;
menuList = {
[1] = {
text = "Melee";
hasArrow = true;
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SWING_DAMAGE", "SWING_MISSED"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SWING_DAMAGE", "SWING_MISSED" );
end;
menuList = {
[1] = {
text = "Damage";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SWING_DAMAGE");end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SWING_DAMAGE" );
end;
};
[2] = {
text = "Failure";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SWING_MISSED"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SWING_MISSED" );
end;
};
};
};
[2] = {
text = "Ranged";
hasArrow = true;
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "RANGE_DAMAGE", "RANGE_MISSED"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "RANGED_DAMAGE", "RANGED_MISSED" );
end;
menuList = {
[1] = {
text = "Damage";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "RANGE_DAMAGE"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "RANGE_DAMAGE" );
end;
};
[2] = {
text = "Failure";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "RANGE_MISSED"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "RANGE_MISSED" );
end;
};
};
};
[3] = {
text = "Spells";
hasArrow = true;
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_DAMAGE", "SPELL_MISSED", "SPELL_HEAL", "SPELL_ENERGIZE", "SPELL_DRAIN", "SPELL_LEECH", "SPELL_INTERRUPT", "SPELL_EXTRA_ATTACKS", "SPELL_CAST_START", "SPELL_CAST_SUCCESS", "SPELL_CAST_FAILED", "SPELL_INSTAKILL", "SPELL_DURABILITY_DAMAGE" ); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_DAMAGE", "SPELL_MISSED", "SPELL_HEAL", "SPELL_ENERGIZE", "SPELL_DRAIN", "SPELL_LEECH", "SPELL_INTERRUPT", "SPELL_EXTRA_ATTACKS", "SPELL_CAST_START", "SPELL_CAST_SUCCESS", "SPELL_CAST_FAILED", "SPELL_INSTAKILL", "SPELL_DURABILITY_DAMAGE" );
end;
menuList = {
[1] = {
text = "Damage";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_DAMAGE"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_DAMAGE" );
end;
};
[2] = {
text = "Failure";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_MISSED"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_MISSED" );
end;
};
[3] = {
text = "Heals";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_HEAL"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_HEAL" );
end;
};
[4] = {
text = "Power Gains";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_ENERGIZE"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_ENERGIZE" );
end;
};
[4] = {
text = "Drains";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_DRAIN", "SPELL_LEECH"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_DRAIN", "SPELL_LEECH" );
end;
};
[5] = {
text = "Interrupts";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_INTERRUPT"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_INTERRUPT" );
end;
};
[6] = {
text = "Extra Attacks";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_EXTRA_ATTACKS"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_EXTRA_ATTACKS" );
end;
};
[7] = {
text = "Casting";
hasArrow = true;
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_CAST_START", "SPELL_CAST_SUCCESS", "SPELL_CAST_FAILED"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_CAST_START", "SPELL_CAST_SUCCESS", "SPELL_CAST_FAILED");
end;
menuList = {
[1] = {
text = "Start";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_CAST_START"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_CAST_START" );
end;
};
[2] = {
text = "Success";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_CAST_SUCCESS"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_CAST_SUCCESS" );
end;
};
[3] = {
text = "Failed";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_CAST_FAILED"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_CAST_FAILED" );
end;
};
};
};
[8] = {
text = "Special";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_INSTAKILL", "SPELL_DURABILITY_DAMAGE"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_INSTAKILL", "SPELL_DURABILITY_DAMAGE" );
end;
};
};
};
[4] = {
text = "Auras";
hasArrow = true;
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_AURA_APPLIED", "SPELL_AURA_BROKEN", "SPELL_AURA_REFRESH", "SPELL_AURA_BROKEN_SPELL", "SPELL_AURA_APPLIED_DOSE", "SPELL_AURA_REMOVED", "SPELL_AURA_REMOVED_DOSE", "SPELL_DISPEL", "SPELL_STOLEN", "ENCHANT_APPLIED", "ENCHANT_REMOVED" ); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_AURA_APPLIED", "SPELL_AURA_BROKEN", "SPELL_AURA_REFRESH", "SPELL_AURA_BROKEN_SPELL", "SPELL_AURA_APPLIED_DOSE", "SPELL_AURA_REMOVED", "SPELL_AURA_REMOVED_DOSE", "SPELL_DISPEL", "SPELL_STOLEN", "ENCHANT_APPLIED", "ENCHANT_REMOVED" );
end;
menuList = {
[1] = {
text = "Applied";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_AURA_APPLIED", "SPELL_AURA_BROKEN", "SPELL_AURA_REFRESH", "SPELL_AURA_BROKEN_SPELL", "SPELL_AURA_APPLIED_DOSE"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_AURA_APPLIED", "SPELL_AURA_BROKEN", "SPELL_AURA_REFRESH", "SPELL_AURA_BROKEN_SPELL", "SPELL_AURA_APPLIED_DOSE", "ENCHANT_APPLIED" );
end;
};
[2] = {
text = "Removed";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_AURA_REMOVED", "SPELL_AURA_REMOVED_DOSE", "ENCHANT_REMOVED" ); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_AURA_REMOVED", "SPELL_AURA_REMOVED_DOSE" );
end;
};
[3] = {
text = "Dispelled";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_DISPEL"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_DISPEL" );
end;
};
[4] = {
text = "Stolen";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_STOLEN"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_STOLEN" );
end;
};
};
};
[5] = {
text = "Periodics";
hasArrow = true;
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_PERIODIC_DAMAGE", "SPELL_PERIODIC_MISSED", "SPELL_PERIODIC_DRAIN", "SPELL_PERIODIC_ENERGIZE", "SPELL_PERIODIC_HEAL", "SPELL_PERIODIC_LEECH" ); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_PERIODIC_DAMAGE", "SPELL_PERIODIC_MISSED", "SPELL_PERIODIC_DRAIN", "SPELL_PERIODIC_ENERGIZE", "SPELL_PERIODIC_HEAL", "SPELL_PERIODIC_LEECH" );
end;
menuList = {
[1] = {
text = "Damage";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_PERIODIC_DAMAGE"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_PERIODIC_DAMAGE" );
end;
};
[2] = {
text = "Failure";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_PERIODIC_MISSED" ); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_PERIODIC_MISSED" );
end;
};
[3] = {
text = "Heals";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_PERIODIC_HEAL"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_PERIODIC_HEAL" );
end;
};
[4] = {
text = "Other";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "SPELL_PERIODIC_DRAIN", "SPELL_PERIODIC_ENERGIZE", "SPELL_PERIODIC_LEECH"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "SPELL_PERIODIC_DRAIN", "SPELL_PERIODIC_ENERGIZE", "SPELL_PERIODIC_LEECH" );
end;
};
};
};
[6] = {
text = "Other";
hasArrow = true;
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "PARTY_KILL", "UNIT_DIED", "UNIT_DESTROYED", "UNIT_DISSIPATES", "DAMAGE_SPLIT", "ENVIRONMENTAL_DAMAGE" ); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "PARTY_KILL", "UNIT_DIED", "UNIT_DESTROYED", "UNIT_DISSIPATES", "DAMAGE_SPLIT", "ENVIRONMENTAL_DAMAGE" );
end;
menuList = {
[1] = {
text = "Kills";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "PARTY_KILL"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "PARTY_KILL" );
end;
};
[2] = {
text = "Deaths";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "UNIT_DIED", "UNIT_DESTROYED", "UNIT_DISSIPATES"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "UNIT_DIED", "UNIT_DESTROYED", "UNIT_DISSIPATES" );
end;
};
[3] = {
text = "Damage Split";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "DAMAGE_SPLIT"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "DAMAGE_SPLIT" );
end;
};
[4] = {
text = "Environmental Damage";
checked = function() return Blizzard_CombatLog_HasEvent (Blizzard_CombatLog_CurrentSettings, "ENVIRONMENTAL_DAMAGE"); end;
keepShownOnClick = true;
func = function ( self, arg1, arg2, checked )
Blizzard_CombatLog_MenuHelper ( checked, "ENVIRONMENTAL_DAMAGE" );
end;
};
};
};
};
};
-- functions I see do pass in arguments, update upvalues as necessary.
function Blizzard_CombatLog_MessageTypesMenu()
return messageTypesMenu;
end
end
--
-- Temporary Menu
--
do
local filterId
local filter
local currentFilter
local formattingMenu = {
text = "Formatting";
hasArrow = true;
menuList = {
{
text = "Full Text";
checked = function() return filter.fullText; end;
func = function(self, arg1, arg2, checked)
filter.fullText = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Timestamp";
checked = function() return filter.timestamp; end;
func = function(self, arg1, arg2, checked)
filter.timestamp = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Unit Name Coloring";
checked = function() return filter.unitColoring; end;
func = function(self, arg1, arg2, checked)
filter.unitColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Line Coloring";
checked = function() return filter.lineColoring; end;
func = function(self, arg1, arg2, checked)
filter.lineColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Line Highlighting";
checked = function() return filter.lineHighlighting; end;
func = function(self, arg1, arg2, checked)
filter.lineHighlighting = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Ability Coloring";
checked = function() return filter.abilityColoring; end;
func = function(self, arg1, arg2, checked)
filter.abilityColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Ability-by-School Coloring";
checked = function() return filter.abilitySchoolColoring; end;
--disabled = not filter.abilityColoring;
func = function(self, arg1, arg2, checked)
filter.abilitySchoolColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Ability-by-Actor Coloring";
checked = function() return filter.abilityActorColoring; end;
func = function(self, arg1, arg2, checked)
filter.abilityActorColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Ability Highlighting";
checked = function() return filter.abilityHighlighting; end;
func = function(self, arg1, arg2, checked)
filter.abilityHighlighting = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Action Coloring";
checked = function() return filter.actionColoring; end;
func = function(self, arg1, arg2, checked)
filter.actionColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Action-by-School Coloring";
checked = function() return filter.actionSchoolColoring; end;
func = function(self, arg1, arg2, checked)
filter.actionSchoolColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Action-by-Actor Coloring";
checked = function() return filter.actionActorColoring; end;
--disabled = not filter.abilityColoring;
func = function(self, arg1, arg2, checked)
filter.actionActorColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Action Highlighting";
checked = function() return filter.actionHighlighting; end;
--disabled = not filter.abilityColoring;
func = function(self, arg1, arg2, checked)
filter.actionHighlighting = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Damage Coloring";
checked = function() return filter.amountColoring; end;
func = function(self, arg1, arg2, checked)
filter.amountColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Damage-by-School Coloring";
checked = function() return filter.amountSchoolColoring; end;
--disabled = not filter.amountColoring;
func = function(self, arg1, arg2, checked)
filter.amountSchoolColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Damage-by-Actor Coloring";
checked = function() return filter.amountActorColoring; end;
--disabled = not filter.amountColoring;
func = function(self, arg1, arg2, checked)
filter.amountActorColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Damage Highlighting";
checked = function() return filter.amountHighlighting; end;
func = function(self, arg1, arg2, checked)
filter.amountHighlighting = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Color School Names";
checked = function() return filter.schoolNameColoring; end;
func = function(self, arg1, arg2, checked)
filter.schoolNameColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "School Name Highlighting";
checked = function() return filter.schoolNameHighlighting; end;
func = function(self, arg1, arg2, checked)
filter.schoolNameHighlighting = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "White Swing Rule";
checked = function() return filter.noMeleeSwingColoring; end;
func = function(self, arg1, arg2, checked)
filter.noMeleeSwingColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Misses Colored Rule";
checked = function() return filter.missColoring; end;
func = function(self, arg1, arg2, checked)
filter.missColoring = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Braces";
checked = function() return filter.braces; end;
func = function(self, arg1, arg2, checked)
filter.braces = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
},
{
text = "Refiltering";
checked = function() return filter.showHistory; end;
func = function(self, arg1, arg2, checked)
filter.showHistory = checked;
Blizzard_CombatLog_QuickButton_OnClick(currentFilter)
end;
keepShownOnClick = true;
tooltipTitle = "Refiltering";
tooltipText = "This clears the chat frame and refills it with the last 500 events.";
},
};
};
function Blizzard_CombatLog_FormattingMenu(filterId_arg)
-- Update upvalues
filterId = filterId_arg;
filter = Blizzard_CombatLog_Filters.filters[filterId].settings;
currentFilter = Blizzard_CombatLog_Filters.currentFilter;
return formattingMenu;
end
end
--
-- Menu Option Helper Function
--
function Blizzard_CombatLog_MenuHelper ( checked, ... )
if ( not checked ) then
Blizzard_CombatLog_DisableEvent (Blizzard_CombatLog_CurrentSettings, ...);
else
Blizzard_CombatLog_EnableEvent (Blizzard_CombatLog_CurrentSettings, ...);
end
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
if ( Blizzard_CombatLog_CurrentSettings.settings.showHistory ) then
Blizzard_CombatLog_Refilter();
end
end;
--
-- Blizzard_CombatLog_CreateTabMenu
--
-- Creates a context sensitive menu based on the current quick button
--
-- args:
-- settingsIndex - the filter settings to use
--
do
local filterId
local unitName, unitGUID, special
local tabMenu = {
[1] = {
text = BLIZZARD_COMBAT_LOG_MENU_EVERYTHING;
func = function () Blizzard_CombatLog_UnitMenuClick ("EVERYTHING", unitName, unitGUID, special); end;
},
[2] = {
text = BLIZZARD_COMBAT_LOG_MENU_SAVE;
func = function () Blizzard_CombatLog_UnitMenuClick ("SAVE", unitName, unitGUID, special); end;
},
[3] = {
text = BLIZZARD_COMBAT_LOG_MENU_RESET;
func = function () Blizzard_CombatLog_UnitMenuClick ("RESET", unitName, unitGUID, special); end;
},
[4] = {
text = "--------- Temporary Adjustments ---------";
disabled = true;
},
};
function Blizzard_CombatLog_CreateTabMenu ( filterId_arg )
-- Update upvalues
filterId = filterId_arg
-- Update menus
tabMenu[2].disabled = (Blizzard_CombatLog_PreviousSettings == Blizzard_CombatLog_CurrentSettings)
tabMenu[5] = Blizzard_CombatLog_FormattingMenu(filterId);
tabMenu[6] = Blizzard_CombatLog_MessageTypesMenu(filterId);
return tabMenu;
end
end
--
-- Temporary Menu
--
do
function Blizzard_CombatLog_CreateUnitMenu(unitName, unitGUID, special)
local displayName = unitName;
if ( (unitGUID == UnitGUID("player")) and (_G["COMBAT_LOG_UNIT_YOU_ENABLED"] == "1") ) then
displayName = UNIT_YOU;
end
local unitMenu = {
[1] = {
text = string.format(BLIZZARD_COMBAT_LOG_MENU_BOTH, displayName); -- Dummy text
func = function () Blizzard_CombatLog_UnitMenuClick ("BOTH", unitName, unitGUID, special); end;
},
[2] = {
text = string.format(BLIZZARD_COMBAT_LOG_MENU_INCOMING, displayName);
func = function () Blizzard_CombatLog_UnitMenuClick ("INCOMING", unitName, unitGUID, special); end;
},
[3] = {
text = string.format(BLIZZARD_COMBAT_LOG_MENU_OUTGOING, displayName);
func = function () Blizzard_CombatLog_UnitMenuClick ("OUTGOING", unitName, unitGUID, special); end;
},
[4] = {
text = "------------------";
disabled = true;
},
[5] = {
text = BLIZZARD_COMBAT_LOG_MENU_EVERYTHING;
func = function () Blizzard_CombatLog_UnitMenuClick ("EVERYTHING", unitName, unitGUID, special); end;
},
[6] = {
text = BLIZZARD_COMBAT_LOG_MENU_SAVE;
func = function () Blizzard_CombatLog_UnitMenuClick ("SAVE", unitName, unitGUID, special); end;
disabled = not CanCreateFilters();
},
[7] = {
text = BLIZZARD_COMBAT_LOG_MENU_RESET;
func = function () Blizzard_CombatLog_UnitMenuClick ("RESET", unitName, unitGUID, special); end;
},
};
--[[
-- These 2 calls update the menus in their respective do-end blocks
unitMenu[9] = Blizzard_CombatLog_FormattingMenu(Blizzard_CombatLog_Filters.currentFilter);
unitMenu[10] = Blizzard_CombatLog_MessageTypesMenu(Blizzard_CombatLog_Filters.currentFilter);
]]
if ( unitGUID ~= UnitGUID("player") ) then
table.insert(unitMenu, 4, {
text = string.format(BLIZZARD_COMBAT_LOG_MENU_OUTGOING_ME, displayName);
func = function () Blizzard_CombatLog_UnitMenuClick ("OUTGOING_ME", unitName, unitGUID, special); end;
} );
end
return unitMenu
end
end
-- Create additional filter dropdown list
do
local menu = {};
function Blizzard_CombatLog_CreateFilterMenu()
local count = 1;
for index, value in pairs(menu) do
if ( not value ) then
value = {};
else
for k, v in pairs(value) do
value[k] = nil;
end
end
end
local selectedIndex = Blizzard_CombatLog_Filters.currentFilter;
local checked;
for index, value in ipairs(Blizzard_CombatLog_Filters.filters) do
if ( not value.onQuickBar ) then
if ( not menu[count] ) then
menu[count] = {};
end
menu[count].text = value.name;
menu[count].func = function () Blizzard_CombatLog_QuickButton_OnClick(index); end;
if ( selectedIndex == index ) then
checked = 1;
else
checked = nil;
end
menu[count].checked = checked;
count = count+1;
end
end
return menu;
end
end
--
-- Handle mini menu clicks
--
-- args:
-- event - "EVERYTHING" | "RESET" | "INCOMING" | "OUTGOING" | "BOTH"
-- unitName - string for the units name
-- unitGUID - unique global unit ID for the specific unit
-- special - bit code for special filters, such as raid targets
--
function Blizzard_CombatLog_UnitMenuClick(event, unitName, unitGUID, unitFlags)
-- ChatFrame1:AddMessage("Event: "..event.." N: "..tostring(unitName).." GUID: "..tostring(unitGUID).." Flags: "..tostring(unitFlags));
--
-- This code was for the context menus to support different formatting criteria
--
-- -- Apply the correct settings.
-- if ( Blizzard_CombatLog_Filters.contextMenu[event] ) then
-- Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.contextMenu[event]
-- end
-- I'm not sure if we really want this feature for live
if ( event == "REVERT" ) then
local temp = Blizzard_CombatLog_CurrentSettings;
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_PreviousSettings;
Blizzard_CombatLog_PreviousSettings = temp;
temp = nil;
-- Apply the old filters
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
elseif ( event == "SAVE" ) then
local dialog = StaticPopup_Show("COPY_COMBAT_FILTER");
dialog.data = Blizzard_CombatLog_CurrentSettings;
return;
elseif ( event == "RESET" ) then
Blizzard_CombatLog_PreviousSettings = Blizzard_CombatLog_CurrentSettings;
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.filters[Blizzard_CombatLog_Filters.currentFilter];
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
else
-- Copy the current settings
Blizzard_CombatLog_PreviousSettings = Blizzard_CombatLog_CurrentSettings;
Blizzard_CombatLog_CurrentSettings = {};
for k,v in pairs( Blizzard_CombatLog_PreviousSettings ) do
Blizzard_CombatLog_CurrentSettings[k] = v;
end
-- Erase the filter criteria
Blizzard_CombatLog_CurrentSettings.filters = {}; -- We want to be careful not to destroy the active data, so the user can reset
if ( event == "EVERYTHING" ) then
-- Reset all filtering.
CombatLogResetFilter()
--Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.contextMenu[event];
CombatLogAddFilter(nil, nil, nil)
tinsert ( Blizzard_CombatLog_CurrentSettings.filters, {} );
end
if ( event == "INCOMING" or event == "BOTH" ) then
if ( unitFlags ) then
tinsert ( Blizzard_CombatLog_CurrentSettings.filters, { destFlags = { [unitFlags] = true; } } );
else
tinsert ( Blizzard_CombatLog_CurrentSettings.filters, { destFlags = { [unitGUID] = true; } } );
end
end
if ( event == "OUTGOING" or event == "BOTH" ) then
if ( unitFlags ) then
tinsert ( Blizzard_CombatLog_CurrentSettings.filters, { sourceFlags = { [unitFlags] = true; } } );
else
tinsert ( Blizzard_CombatLog_CurrentSettings.filters, { sourceFlags = { [unitGUID] = true; } } );
end
end
if ( event == "OUTGOING_ME" ) then
if ( unitFlags ) then
tinsert ( Blizzard_CombatLog_CurrentSettings.filters, { sourceFlags = { [unitFlags] = true; }; destFlags = { [COMBATLOG_FILTER_MINE] = true; } } );
else
tinsert ( Blizzard_CombatLog_CurrentSettings.filters, { sourceFlags = { [unitGUID] = true; }; destFlags = { [COMBATLOG_FILTER_MINE] = true; } } );
end
end
-- If the context menu is not resetting, then we need to create an event list,
-- So that right click removal works when the user right clicks
--
-- Fill the event list
local fullEventList = Blizzard_CombatLog_GenerateFullEventList();
-- Insert to the active data
for k,v in pairs (Blizzard_CombatLog_CurrentSettings.filters) do
v.eventList = fullEventList;
end
-- Apply the generated filters
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
-- Let the system know that this filter is temporary and unhighlight any quick buttons
Blizzard_CombatLog_CurrentSettings.isTemp = true;
Blizzard_CombatLog_Update_QuickButtons()
end
-- Reset the combat log text box! (Grats!)
Blizzard_CombatLog_Refilter();
end
--
-- Shows a simplified version of the menu if you right click on the quick button
--
-- This function isn't used anywhere yet. The QuickButtons doesn't have a event handler for right click yet.
function Blizzard_CombatLog_QuickButtonRightClick(event, filterId)
-- I'm not sure if we really want this feature for live
if ( event == "REVERT" ) then
local temp = Blizzard_CombatLog_CurrentSettings;
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_PreviousSettings;
Blizzard_CombatLog_PreviousSettings = temp;
temp = nil;
-- Apply the old filters
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
elseif ( event == "RESET" ) then
Blizzard_CombatLog_PreviousSettings = Blizzard_CombatLog_CurrentSettings;
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.filters[filterId];
--CombatLogAddFilter(nil, nil, COMBATLOG_FILTER_MINE)
--CombatLogAddFilter(nil, COMBATLOG_FILTER_MINE, nil)
else
-- Copy the current settings
Blizzard_CombatLog_PreviousSettings = Blizzard_CombatLog_CurrentSettings;
Blizzard_CombatLog_CurrentSettings = {};
for k,v in pairs( Blizzard_CombatLog_Filters.filters[filterId] ) do
Blizzard_CombatLog_CurrentSettings[k] = v;
end
-- Erase the filter criteria
Blizzard_CombatLog_CurrentSettings.filters = {}; -- We want to be careful not to destroy the active data, so the user can reset
if ( event == "EVERYTHING" ) then
CombatLogAddFilter(nil, nil, nil)
table.insert ( Blizzard_CombatLog_CurrentSettings.filters, {} );
end
-- If the context menu is not resetting, then we need to create an event list,
-- So that right click removal works when the user right clicks
--
-- Fill the event list
local fullEventList = Blizzard_CombatLog_GenerateFullEventList();
-- Insert to the active data
for k,v in pairs (Blizzard_CombatLog_CurrentSettings.filters) do
v.eventList = fullEventList;
end
-- Apply the generated filters
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
end
-- Reset the combat log text box! (Grats!)
Blizzard_CombatLog_Refilter();
end
--
-- Handle spell mini menu clicks
-- args:
-- action - "HIDE" | "LINK"
-- spellName - Spell or ability's name
-- spellId - Spell or ability's id (100, 520, 30000, etc)
-- event - the event type that generated this message
--
function Blizzard_CombatLog_SpellMenuClick(action, spellName, spellId, eventType)
if ( action == "HIDE" ) then
for k,v in pairs (Blizzard_CombatLog_CurrentSettings.filters) do
if ( type (v.eventList) ~= "table" ) then
v.eventList = Blizzard_CombatLog_GenerateFullEventList();
end
v.eventList[eventType] = false;
end
elseif ( action == "LINK" ) then
if ( ChatEdit_GetActiveWindow() ) then
ChatEdit_InsertLink(GetSpellLink(spellId));
else
ChatFrame_OpenChat(GetSpellLink(spellId));
end
return;
end
-- Apply the newly reconstituted filters
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
-- Reset the combat log text box! (Grats!)
Blizzard_CombatLog_Refilter();
end
--
-- Temporary Settings
--
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.filters[1];
Blizzard_CombatLog_PreviousSettings = Blizzard_CombatLog_CurrentSettings;
local Blizzard_CombatLog_UnitTokens = {};
--[[
-- Converts 4 floats into FF code
--
--]]
local function CombatLog_Color_FloatToText(r,g,b,a)
if ( type(r) == "table" ) then
r, g, b, a = r.r, r.g, r.b, r.a;
end
a = min(1, a or 1) * 255
r = min(1, r) * 255
g = min(1, g) * 255
b = min(1, b) * 255
-- local fmt = "%.2x";
return ("%.2x%.2x%.2x%.2x"):format(math_floor(a), math_floor(r), math_floor(g), math_floor(b))
end
_G.CombatLog_Color_FloatToText = CombatLog_Color_FloatToText
--
-- Gets the appropriate color for an event type
--
-- If this needs to return a new table per event (ie, the table gets modified), then just replace the "defaultColorArray" in the function with
-- a new table creation.
local defaultColorArray = {a=1.0,r=0.5,g=0.5,b=0.5}
local function CombatLog_Color_ColorArrayByEventType( event )
return Blizzard_CombatLog_CurrentSettings.colors.eventColoring[event] or defaultColorArray
end
_G.CombatLog_Color_ColorArrayByEventType = CombatLog_Color_ColorArrayByEventType
--
-- Gets the appropriate color for a unit type
--
local function CombatLog_Color_ColorArrayByUnitType(unitFlags, settings)
local array = nil;
if ( not settings ) then
settings = Blizzard_CombatLog_CurrentSettings;
end
for mask,colorArray in pairs( settings.colors.unitColoring ) do
if ( CombatLog_Object_IsA (unitFlags, mask) )then
array = colorArray;
break;
end
end
return array or defaultColorArray
end
_G.CombatLog_Color_ColorArrayByUnitType = CombatLog_Color_ColorArrayByUnitType
--
-- Gets the appropriate color for a spell school
--
local function CombatLog_Color_ColorArrayBySchool(school, settings)
if ( not settings ) then
settings = Blizzard_CombatLog_CurrentSettings;
end
if ( not school ) then
return settings.colors.schoolColoring.default;
end
return settings.colors.schoolColoring[school] or settings.colors.defaults.spell;
end
_G.CombatLog_Color_ColorArrayBySchool = CombatLog_Color_ColorArrayBySchool
--
-- Gets the appropriate color for a spell school
--
local highlightColorTable = {}
local function CombatLog_Color_HighlightColorArray(colorArray)
highlightColorTable.r = colorArray.r * COMBATLOG_HIGHLIGHT_MULTIPLIER;
highlightColorTable.g = colorArray.g * COMBATLOG_HIGHLIGHT_MULTIPLIER;
highlightColorTable.b = colorArray.b * COMBATLOG_HIGHLIGHT_MULTIPLIER;
highlightColorTable.a = colorArray.a;
return highlightColorTable
end
_G.CombatLog_Color_HighlightColorArray = CombatLog_Color_HighlightColorArray
--
-- Returns a string associated with a numeric power type
--
local function CombatLog_String_PowerType(powerType, amount, alternatePowerType)
if ( not powerType ) then
return "";
elseif ( powerType == SPELL_POWER_MANA ) then
return MANA;
elseif ( powerType == SPELL_POWER_RAGE ) then
return RAGE;
elseif ( powerType == SPELL_POWER_ENERGY ) then
return ENERGY;
elseif ( powerType == SPELL_POWER_FOCUS ) then
return FOCUS;
elseif ( powerType == SPELL_POWER_RUNES ) then
return RUNES;
elseif ( powerType == SPELL_POWER_RUNIC_POWER ) then
return RUNIC_POWER;
elseif ( powerType == SPELL_POWER_SOUL_SHARDS ) then
return SOUL_SHARDS;
elseif ( powerType == SPELL_POWER_ECLIPSE ) then
if amount and amount > 0 then
return BALANCE_POSITIVE_ENERGY;
else
return BALANCE_NEGATIVE_ENERGY;
end
elseif ( powerType == SPELL_POWER_HOLY_POWER ) then
return HOLY_POWER;
elseif ( powerType == SPELL_POWER_CHI ) then
return CHI_POWER; -- "Chi"
elseif ( powerType == SPELL_POWER_BURNING_EMBERS ) then
return BURNING_EMBERS_POWER;
elseif ( powerType == SPELL_POWER_SHADOW_ORBS ) then
return SHADOW_ORBS_POWER;
elseif ( powerType == SPELL_POWER_ALTERNATE_POWER and alternatePowerType ) then
local costName = select(12, GetAlternatePowerInfoByID(alternatePowerType));
return costName; --costName could be nil if we didn't get the alternatePowerType for some reason (e.g. target out of AOI)
end
end
_G.CombatLog_String_PowerType = CombatLog_String_PowerType
local function CombatLog_String_SchoolString(school)
if ( not school or school == SCHOOL_MASK_NONE ) then
return STRING_SCHOOL_UNKNOWN;
end
local schoolString = SchoolStringTable[school];
return schoolString or STRING_SCHOOL_UNKNOWN
end
_G.CombatLog_String_SchoolString = CombatLog_String_SchoolString
local function CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill )
local resultStr;
-- Result String formatting
local useOverhealing = overhealing and overhealing > 0;
local useOverkill = overkill and overkill > 0;
local useAbsorbed = absorbed and absorbed > 0;
if ( resisted or blocked or critical or glancing or crushing or useOverhealing or useOverkill or useAbsorbed) then
resultStr = nil;
if ( resisted ) then
if ( resisted < 0 ) then --Its really a vulnerability
resultStr = format(TEXT_MODE_A_STRING_RESULT_VULNERABILITY, -resisted);
else
resultStr = format(TEXT_MODE_A_STRING_RESULT_RESIST, resisted);
end
end
if ( blocked ) then
if ( resultStr ) then
resultStr = resultStr.." "..format(TEXT_MODE_A_STRING_RESULT_BLOCK, blocked);
else
resultStr = format(TEXT_MODE_A_STRING_RESULT_BLOCK, blocked);
end
end
if ( useAbsorbed ) then
if ( resultStr ) then
resultStr = resultStr.." "..format(TEXT_MODE_A_STRING_RESULT_ABSORB, absorbed);
else
resultStr = format(TEXT_MODE_A_STRING_RESULT_ABSORB, absorbed);
end
end
if ( glancing ) then
if ( resultStr ) then
resultStr = resultStr.." "..TEXT_MODE_A_STRING_RESULT_GLANCING;
else
resultStr = TEXT_MODE_A_STRING_RESULT_GLANCING;
end
end
if ( crushing ) then
if ( resultStr ) then
resultStr = resultStr.." "..TEXT_MODE_A_STRING_RESULT_CRUSHING;
else
resultStr = TEXT_MODE_A_STRING_RESULT_CRUSHING;
end
end
if ( useOverhealing ) then
if ( resultStr ) then
resultStr = resultStr.." "..format(TEXT_MODE_A_STRING_RESULT_OVERHEALING, overhealing);
else
resultStr = format(TEXT_MODE_A_STRING_RESULT_OVERHEALING, overhealing);
end
end
if ( useOverkill ) then
if ( resultStr ) then
resultStr = resultStr.." "..format(TEXT_MODE_A_STRING_RESULT_OVERKILLING, overkill);
else
resultStr = format(TEXT_MODE_A_STRING_RESULT_OVERKILLING, overkill);
end
end
if ( critical ) then
local critString = TEXT_MODE_A_STRING_RESULT_CRITICAL;
if ( spellId ) then
critString = TEXT_MODE_A_STRING_RESULT_CRITICAL_SPELL;
end
if ( resultStr ) then
resultStr = resultStr.." "..critString;
else
resultStr = critString;
end
end
end
return resultStr;
end
_G.CombatLog_String_DamageResultString = CombatLog_String_DamageResultString
--
-- Get the appropriate raid icon for a unit
--
local function CombatLog_String_GetIcon ( unitFlags, direction )
-- Check for an appropriate icon for this unit
local raidTarget = bit_band(unitFlags, COMBATLOG_OBJECT_RAIDTARGET_MASK);
if ( raidTarget == 0 ) then
return "";
end
local iconString = "";
local icon = nil;
local iconBit = 0;
if ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET1 ) then
icon = COMBATLOG_ICON_RAIDTARGET1;
iconBit = COMBATLOG_OBJECT_RAIDTARGET1;
elseif ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET2 ) then
icon = COMBATLOG_ICON_RAIDTARGET2;
iconBit = COMBATLOG_OBJECT_RAIDTARGET2;
elseif ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET3 ) then
icon = COMBATLOG_ICON_RAIDTARGET3;
iconBit = COMBATLOG_OBJECT_RAIDTARGET3;
elseif ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET4 ) then
icon = COMBATLOG_ICON_RAIDTARGET4;
iconBit = COMBATLOG_OBJECT_RAIDTARGET4;
elseif ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET5 ) then
icon = COMBATLOG_ICON_RAIDTARGET5;
iconBit = COMBATLOG_OBJECT_RAIDTARGET5;
elseif ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET6 ) then
icon = COMBATLOG_ICON_RAIDTARGET6;
iconBit = COMBATLOG_OBJECT_RAIDTARGET6;
elseif ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET7 ) then
icon = COMBATLOG_ICON_RAIDTARGET7;
iconBit = COMBATLOG_OBJECT_RAIDTARGET7;
elseif ( raidTarget == COMBATLOG_OBJECT_RAIDTARGET8 ) then
icon = COMBATLOG_ICON_RAIDTARGET8;
iconBit = COMBATLOG_OBJECT_RAIDTARGET8;
end
-- Insert the Raid Icon if it exists
if ( icon ) then
--
-- Insert a hyperlink for that icon
if ( direction == "source" ) then
iconString = format(TEXT_MODE_A_STRING_SOURCE_ICON, iconBit, icon);
else
iconString = format(TEXT_MODE_A_STRING_DEST_ICON, iconBit, icon);
end
end
return iconString;
end
_G.CombatLog_String_GetIcon = CombatLog_String_GetIcon
--
-- Obtains the appropriate unit token for a GUID
--
local function CombatLog_String_GetToken (unitGUID, unitName, unitFlags)
--
-- Code to display Defias Pillager (A), Defias Pillager (B), etc
--
--[[
local newName = TEXT_MODE_A_STRING_TOKEN_UNIT;
-- Use the local cache if possible
if ( Blizzard_CombatLog_UnitTokens[unitGUID] ) then
-- For unique creatures, hide the token
if ( Blizzard_CombatLog_UnitTokens[unitGUID] == unitName ) then
return unitName;
end
newName = gsub ( newName, "$token", Blizzard_CombatLog_UnitTokens[unitGUID] );
newName = gsub ( newName, "$unitName", unitName );
else
if ( not Blizzard_CombatLog_UnitTokens[unitName] or Blizzard_CombatLog_UnitTokens[unitName] > 26*26) then
Blizzard_CombatLog_UnitTokens[unitName] = 1;
Blizzard_CombatLog_UnitTokens[unitGUID] = unitName;
newName = unitName;
else
Blizzard_CombatLog_UnitTokens[unitName] = Blizzard_CombatLog_UnitTokens[unitName] + 1;
if ( Blizzard_CombatLog_UnitTokens[unitName] > 26 ) then
Blizzard_CombatLog_UnitTokens[unitGUID] =
string.char ( TEXT_MODE_A_STRING_TOKEN_BASE + math.floor(Blizzard_CombatLog_UnitTokens[unitName] / 26) )..
string.char ( TEXT_MODE_A_STRING_TOKEN_BASE + math.fmod(Blizzard_CombatLog_UnitTokens[unitName], 26) );
else
Blizzard_CombatLog_UnitTokens[unitGUID] = string.char ( TEXT_MODE_A_STRING_TOKEN_BASE + math.fmod(Blizzard_CombatLog_UnitTokens[unitName], 26) );
end
newName = gsub ( newName, "$token", Blizzard_CombatLog_UnitTokens[unitGUID] );
newName = gsub ( newName, "$unitName", unitName );
end
end
]]
-- Shortcut since the above block is commented out.
-- newName = unitName;
return unitName;
end
_G.CombatLog_String_GetToken = CombatLog_String_GetToken
--
-- Gets the appropriate color for a unit type
--
--
local function CombatLog_Color_ColorStringByUnitType(unitFlags)
local colorArray = CombatLog_Color_ColorArrayByUnitType(unitFlags);
return CombatLog_Color_FloatToText(colorArray.r, colorArray.g, colorArray.b, colorArray.a )
end
_G.CombatLog_Color_ColorStringByUnitType = CombatLog_Color_ColorStringByUnitType
--[[
-- Gets the appropriate color for a school
--
--]]
local function CombatLog_Color_ColorStringBySchool(school)
local colorArray = CombatLog_Color_ColorArrayBySchool(school);
return CombatLog_Color_FloatToText(colorArray.r, colorArray.g, colorArray.b, colorArray.a )
end
_G.CombatLog_Color_ColorStringBySchool = CombatLog_Color_ColorStringBySchool
--
-- Gets the appropriate color for an event type
--
--
local function CombatLog_Color_ColorStringByEventType(unitFlags)
local colorArray = CombatLog_Color_ColorArrayByEventType(unitFlags);
return CombatLog_Color_FloatToText(colorArray.r, colorArray.g, colorArray.b, colorArray.a )
end
_G.CombatLog_Color_ColorStringByEventType = CombatLog_Color_ColorStringByEventType
--[[
-- Handles events and dumps them to the specified frame.
--]]
-- Add settings as an arg
local defaultCombatLogLineColor = { a = 1.00, r = 1.00, g = 1.00, b = 1.00 };
function CombatLog_OnEvent(filterSettings, timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, ...)
-- [environmentalDamageType]
-- [spellName, spellRank, spellSchool]
-- [damage, school, [resisted, blocked, absorbed, crit, glancing, crushing]]
-- Upvalue this, we're gonna use it a lot
local settings = filterSettings.settings;
local lineColor = defaultCombatLogLineColor;
local sourceColor, destColor = nil, nil;
local braceColor = "FFFFFFFF";
local abilityColor = "FFFFFF00";
-- Processing variables
local textMode = settings.textMode;
local timestampEnabled = settings.timestamp;
local hideBuffs = settings.hideBuffs;
local hideDebuffs = settings.hideDebuffs;
local sourceEnabled = true;
local falseSource = false;
local destEnabled = true;
local spellEnabled = true;
local actionEnabled = true;
local valueEnabled = true;
local valueTypeEnabled = true;
local resultEnabled = true;
local powerTypeEnabled = true;
local itemEnabled = false;
local extraSpellEnabled = false;
local valueIsItem = false;
local schoolEnabled = true;
local withPoints = false;
local forceDestPossessive = false;
-- Get the initial string
local schoolString;
local resultStr;
local formatString = TEXT_MODE_A_STRING_1;
if ( EVENT_TEMPLATE_FORMATS[event] ) then
formatString = EVENT_TEMPLATE_FORMATS[event];
end
-- Replacements to do:
-- * Src, Dest, Action, Spell, Amount, Result
-- Spell standard order
local spellId, spellName, spellSchool;
local extraSpellId, extraSpellName, extraSpellSchool;
-- For Melee/Ranged swings and enchants
local nameIsNotSpell, extraNameIsNotSpell;
-- Damage standard order
local amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, overhealing;
-- Miss argument order
local missType, isOffHand, amountMissed;
-- Aura arguments
local auraType; -- BUFF or DEBUFF
-- Enchant arguments
local itemId, itemName;
-- Special Spell values
local valueType = 1; -- 1 = School, 2 = Power Type
local extraAmount; -- Used for Drains and Leeches
local powerType; -- Used for energizes, drains and leeches
local alternatePowerType; -- Used for energizes, drains and leeches
local environmentalType; -- Used for environmental damage
local message; -- Used for server spell messages
local originalEvent = event; -- Used for spell links
local remainingPoints; --Used for absorbs with the correct flag set (like Power Word: Shield)
-- Generic disabling stuff
if ( not sourceName or CombatLog_Object_IsA(sourceFlags, COMBATLOG_OBJECT_NONE) ) then
sourceEnabled = false;
end
if ( not destName or CombatLog_Object_IsA(destFlags, COMBATLOG_OBJECT_NONE) ) then
destEnabled = false;
end
local subVal = strsub(event, 1, 5)
-- Swings
if ( subVal == "SWING" ) then
spellName = ACTION_SWING;
nameIsNotSpell = true;
end
-- Break out the arguments into variable
if ( event == "SWING_DAMAGE" ) then
-- Damage standard
amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...;
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
if ( not resultStr ) then
resultEnabled = false;
end
if ( overkill > 0 ) then
amount = amount - overkill;
end
elseif ( event == "SWING_MISSED" ) then
spellName = ACTION_SWING;
-- Miss type
missType, isOffHand, amountMissed = ...;
-- Result String
if( missType == "RESIST" or missType == "BLOCK" or missType == "ABSORB" ) then
resultStr = format(_G["TEXT_MODE_A_STRING_RESULT_"..missType], amountMissed);
else
resultStr = _G["ACTION_SWING_MISSED_"..missType];
end
-- Miss Type
if ( settings.fullText and missType ) then
event = format("%s_%s", event, missType);
end
-- Disable appropriate sections
nameIsNotSpell = true;
valueEnabled = false;
resultEnabled = true;
elseif ( subVal == "SPELL" ) then -- Spell standard arguments
spellId, spellName, spellSchool = ...;
if ( event == "SPELL_DAMAGE" or event == "SPELL_BUILDING_DAMAGE") then
-- Damage standard
amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = select(4, ...);
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
if ( not resultStr ) then
resultEnabled = false
end
if ( overkill > 0 ) then
amount = amount - overkill;
end
elseif ( event == "SPELL_MISSED" ) then
-- Miss type
missType, isOffHand, amountMissed = select(4, ...);
resultEnabled = true;
-- Result String
if( missType == "RESIST" or missType == "BLOCK" or missType == "ABSORB" ) then
if ( amountMissed ~= 0 ) then
resultStr = format(_G["TEXT_MODE_A_STRING_RESULT_"..missType], amountMissed);
else
resultEnabled = false;
end
else
resultStr = _G["ACTION_SWING_MISSED_"..missType];
end
-- Miss Event
if ( missType ) then
event = format("%s_%s", event, missType);
end
-- Disable appropriate sections
valueEnabled = false;
elseif ( event == "SPELL_HEAL" or event == "SPELL_BUILDING_HEAL") then
-- Did the heal crit?
amount, overhealing, absorbed, critical = select(4, ...);
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
if ( not resultStr ) then
resultEnabled = false
end
-- Temporary Spell School Hack
school = spellSchool;
-- Disable appropriate sections
valueEnabled = true;
valueTypeEnabled = true;
amount = amount - overhealing;
elseif ( event == "SPELL_ENERGIZE" ) then
-- Set value type to be a power type
valueType = 2;
-- Did the heal crit?
amount, powerType, alternatePowerType = select(4, ...);
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
if ( not resultStr ) then
resultEnabled = false
end
-- Disable appropriate sections
valueEnabled = true;
valueTypeEnabled = true;
elseif ( strsub(event, 1, 14) == "SPELL_PERIODIC" ) then
if ( event == "SPELL_PERIODIC_MISSED" ) then
-- Miss type
missType = select(4, ...);
-- Result String
if ( missType == "ABSORB" ) then
resultStr = CombatLog_String_DamageResultString( resisted, blocked, select(5,...), critical, glancing, crushing, overhealing, textMode, spellId, overkill );
else
resultStr = _G["ACTION_SPELL_PERIODIC_MISSED_"..missType];
end
-- Miss Event
if ( settings.fullText and missType ) then
event = format("%s_%s", event, missType);
end
-- Disable appropriate sections
valueEnabled = false;
resultEnabled = true;
elseif ( event == "SPELL_PERIODIC_DAMAGE" ) then
-- Damage standard
amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = select(4, ...);
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
-- Disable appropriate sections
if ( not resultStr ) then
resultEnabled = false
end
if ( overkill > 0 ) then
amount = amount - overkill;
end
elseif ( event == "SPELL_PERIODIC_HEAL" ) then
-- Did the heal crit?
amount, overhealing, absorbed, critical = select(4, ...);
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
if ( not resultStr ) then
resultEnabled = false
end
-- Temporary Spell School Hack
school = spellSchool;
-- Disable appropriate sections
valueEnabled = true;
valueTypeEnabled = true;
amount = amount - overhealing;
elseif ( event == "SPELL_PERIODIC_DRAIN" ) then
-- Special attacks
amount, powerType, extraAmount, alternatePowerType = select(4, ...);
-- Set value type to be a power type
valueType = 2;
-- Result String
--resultStr = _G[textModeString .. "RESULT"];
--resultStr = gsub(resultStr,"$resultString", _G["ACTION_"..event.."_RESULT"]);
-- Disable appropriate sections
if ( not resultStr ) then
resultEnabled = false
end
valueEnabled = true;
schoolEnabled = false;
elseif ( event == "SPELL_PERIODIC_LEECH" ) then
-- Special attacks
amount, powerType, extraAmount, alternatePowerType = select(4, ...);
-- Set value type to be a power type
valueType = 2;
-- Result String
resultStr = format(_G["ACTION_SPELL_PERIODIC_LEECH_RESULT"], nil, nil, nil, nil, nil, nil, nil, CombatLog_String_PowerType(powerType, amount, alternatePowerType), nil, extraAmount) --"($extraAmount $powerType Gained)"
-- Disable appropriate sections
if ( not resultStr ) then
resultEnabled = false
end
valueEnabled = true;
schoolEnabled = false;
elseif ( event == "SPELL_PERIODIC_ENERGIZE" ) then
-- Set value type to be a power type
valueType = 2;
-- Did the heal crit?
amount, powerType, alternatePowerType = select(4, ...);
-- Parse the result string
--resultStr = _G[textModeString .. "RESULT"];
--resultStr = gsub(resultStr,"$resultString", _G["ACTION_"..event.."_RESULT"]);
if ( not resultStr ) then
resultEnabled = false
end
-- Disable appropriate sections
valueEnabled = true;
valueTypeEnabled = true;
end
elseif ( event == "SPELL_CAST_START" ) then -- Spellcast
if ( not destName ) then
destEnabled = false;
end
if ( not sourceName and not settings.fullText ) then
sourceName = COMBATLOG_UNKNOWN_UNIT;
sourceEnabled = true;
falseSource = true;
end
-- Disable appropriate types
resultEnabled = false;
valueEnabled = false;
elseif ( event == "SPELL_CAST_SUCCESS" ) then
if ( not destName ) then
destEnabled = false;
end
if ( not sourceName and not settings.fullText ) then
sourceName = COMBATLOG_UNKNOWN_UNIT;
sourceEnabled = true;
falseSource = true;
end
-- Disable appropriate types
resultEnabled = false;
valueEnabled = false;
elseif ( event == "SPELL_CAST_FAILED" ) then
if ( not destName ) then
destEnabled = false;
end
-- Miss reason
missType = select(4, ...);
-- Result String
resultStr = format("(%s)", missType);
--resultStr = gsub(_G[textModeString .. "RESULT"],"$resultString", missType);
-- Disable appropriate sections
valueEnabled = false;
destEnabled = false;
if ( not resultStr ) then
resultEnabled = false;
end
elseif ( event == "SPELL_DRAIN" ) then -- Special Spell effects
-- Special attacks
amount, powerType, extraAmount, alternatePowerType = select(4, ...);
-- Set value type to be a power type
valueType = 2;
-- Disable appropriate sections
if ( not resultStr ) then
resultEnabled = false;
end
valueEnabled = true;
schoolEnabled = false;
elseif ( event == "SPELL_LEECH" ) then
-- Special attacks
amount, powerType, extraAmount, alternatePowerType = select(4, ...);
-- Set value type to be a power type
valueType = 2;
-- Result String
resultStr = format(_G["ACTION_SPELL_LEECH_RESULT"], nil, nil, nil, nil, nil, nil, nil, CombatLog_String_PowerType(powerType, amount, alternatePowerType), nil, extraAmount)
-- Disable appropriate sections
if ( not resultStr ) then
resultEnabled = false;
end
valueEnabled = true;
schoolEnabled = false;
elseif ( event == "SPELL_INTERRUPT" ) then
-- Spell interrupted
extraSpellId, extraSpellName, extraSpellSchool = select(4, ...);
-- Replace the value token with a spell token
if ( extraSpellId ) then
extraSpellEnabled = true;
end
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
valueTypeEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_EXTRA_ATTACKS" ) then
-- Special attacks
amount = select(4, ...);
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = true;
valueTypeEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_SUMMON" ) then
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_RESURRECT" ) then
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_CREATE" ) then
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_INSTAKILL" ) then
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_DURABILITY_DAMAGE" ) then
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_DURABILITY_DAMAGE_ALL" ) then
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
schoolEnabled = false;
elseif ( event == "SPELL_DISPEL_FAILED" ) then
-- Extra Spell standard
extraSpellId, extraSpellName, extraSpellSchool = select(4, ...);
-- Replace the value token with a spell token
if ( extraSpellId ) then
extraSpellEnabled = true;
end
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
elseif ( event == "SPELL_DISPEL" or event == "SPELL_STOLEN" ) then
-- Extra Spell standard, Aura standard
extraSpellId, extraSpellName, extraSpellSchool, auraType = select(4, ...);
-- Event Type
event = format("%s_%s", event, auraType);
-- Replace the value token with a spell token
if ( extraSpellId ) then
extraSpellEnabled = true;
valueEnabled = true;
else
valueEnabled = false;
end
-- Disable appropriate sections
resultEnabled = false;
elseif ( event == "SPELL_AURA_BROKEN" or event == "SPELL_AURA_BROKEN_SPELL") then
-- Extra Spell standard, Aura standard
if(event == "SPELL_AURA_BROKEN") then
auraType = select(4, ...);
else
extraSpellId, extraSpellName, extraSpellSchool, auraType = select(4, ...);
end
-- Abort if buff/debuff is not set to true
if ( hideBuffs and auraType == AURA_TYPE_BUFF ) then
return;
elseif ( hideDebuffs and auraType == AURA_TYPE_DEBUFF ) then
return;
end
-- Event Type
event = format("%s_%s", event, auraType);
-- Replace the value token with a spell token
if ( extraSpellId ) then
extraSpellEnabled = true;
valueEnabled = true;
else
forceDestPossessive = true;
valueEnabled = false;
end
resultEnabled = false;
elseif ( event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REMOVED" or event == "SPELL_AURA_REFRESH") then -- Aura Events
-- Aura standard
auraType, remainingPoints = select(4, ...);
-- Abort if buff/debuff is not set to true
if ( hideBuffs and auraType == AURA_TYPE_BUFF ) then
return;
elseif ( hideDebuffs and auraType == AURA_TYPE_DEBUFF ) then
return;
end
formatString = TEXT_MODE_A_STRING_1;
-- Event Type
event = format("%s_%s", event, auraType);
if ( remainingPoints and settings.fullText ) then
withPoints = true;
end
resultEnabled = false;
valueEnabled = false;
elseif ( event == "SPELL_AURA_APPLIED_DOSE" or event == "SPELL_AURA_REMOVED_DOSE" ) then
-- Aura standard
auraType, amount = select(4, ...);
-- Abort if buff/debuff is not set to true
if ( hideBuffs and auraType == AURA_TYPE_BUFF ) then
return;
elseif ( hideDebuffs and auraType == AURA_TYPE_DEBUFF ) then
return;
end
-- Event Type
event = format("%s_%s", event, auraType);
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = true;
valueTypeEnabled = false;
end
elseif ( subVal == "RANGE" ) then
--spellName = ACTION_RANGED;
--nameIsNotSpell = true;
-- Shots are spells, technically
spellId, spellName, spellSchool = ...;
if ( event == "RANGE_DAMAGE" ) then
-- Damage standard
amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = select(4, ...);
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
if ( not resultStr ) then
resultEnabled = false
end
-- Disable appropriate sections
nameIsNotSpell = true;
if ( overkill > 0 ) then
amount = amount - overkill;
end
elseif ( event == "RANGE_MISSED" ) then
spellName = ACTION_RANGED;
-- Miss type
missType, isOffHand, amountMissed = select(4,...);
-- Result String
if( missType == "RESIST" or missType == "BLOCK" or missType == "ABSORB" ) then
resultStr = format(_G["TEXT_MODE_A_STRING_RESULT_"..missType], amountMissed);
else
resultStr = _G["ACTION_RANGE_MISSED_"..missType];
end
-- Miss Type
if ( settings.fullText and missType ) then
event = format("%s_%s", event, missType);
end
-- Disable appropriate sections
nameIsNotSpell = true;
valueEnabled = false;
resultEnabled = true;
end
elseif ( event == "DAMAGE_SHIELD" ) then -- Damage Shields
-- Spell standard, Damage standard
spellId, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...;
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
-- Disable appropriate sections
if ( not resultStr ) then
resultEnabled = false
end
if ( overkill > 0 ) then
amount = amount - overkill;
end
elseif ( event == "DAMAGE_SHIELD_MISSED" ) then
-- Spell standard, Miss type
spellId, spellName, spellSchool, missType = ...;
-- Result String
resultStr = _G["ACTION_DAMAGE_SHIELD_MISSED_"..missType];
-- Miss Event
if ( settings.fullText and missType ) then
event = format("%s_%s", event, missType);
end
-- Disable appropriate sections
valueEnabled = false;
if ( not resultStr ) then
resultEnabled = false;
end
elseif ( event == "PARTY_KILL" ) then -- Unique Events
-- Disable appropriate sections
resultEnabled = false;
valueEnabled = false;
spellEnabled = false;
elseif ( event == "ENCHANT_APPLIED" ) then
-- Get the enchant name, item id and item name
spellName, itemId, itemName = ...;
nameIsNotSpell = true;
-- Disable appropriate sections
valueIsItem = true;
itemEnabled = true;
resultEnabled = false;
elseif ( event == "ENCHANT_REMOVED" ) then
-- Get the enchant name, item id and item name
spellName, itemId, itemName = ...;
nameIsNotSpell = true;
-- Disable appropriate sections
valueIsItem = true;
itemEnabled = true;
resultEnabled = false;
sourceEnabled = false;
elseif ( event == "UNIT_DIED" or event == "UNIT_DESTROYED" or event == "UNIT_DISSIPATES" ) then
-- Swap Source with Dest
sourceName = destName;
sourceGUID = destGUID;
sourceFlags = destFlags;
-- Disable appropriate sections
resultEnabled = false;
sourceEnabled = true;
destEnabled = false;
spellEnabled = false;
valueEnabled = false;
elseif ( event == "ENVIRONMENTAL_DAMAGE" ) then
--Environemental Type, Damage standard
environmentalType, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...
environmentalType = string.upper(environmentalType);
-- Miss Event
spellName = _G["ACTION_ENVIRONMENTAL_DAMAGE_"..environmentalType];
spellSchool = school;
nameIsNotSpell = true;
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
-- Environmental Event
if ( settings.fullText and environmentalType ) then
event = "ENVIRONMENTAL_DAMAGE_"..environmentalType;
end
if ( not resultStr ) then
resultEnabled = false;
end
if ( overkill > 0 ) then
amount = amount - overkill;
end
elseif ( event == "DAMAGE_SPLIT" ) then
-- Spell Standard Arguments, Damage standard
spellId, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...;
-- Parse the result string
resultStr = CombatLog_String_DamageResultString( resisted, blocked, absorbed, critical, glancing, crushing, overhealing, textMode, spellId, overkill );
if ( not resultStr ) then
resultEnabled = false
end
if ( overkill > 0 ) then
amount = amount - overkill;
end
end
-- Throw away all of the assembled strings and just grab a premade one
if ( settings.fullText ) then
local formatStringEvent;
if (withPoints) then
formatStringEvent = format("ACTION_%s_WITH_POINTS_FULL_TEXT", event);
else
formatStringEvent = format("ACTION_%s_FULL_TEXT", event);
end
-- Get the base string
if ( _G[formatStringEvent] ) then
formatString = _G[formatStringEvent];
end
-- Set any special cases
if ( not sourceEnabled ) then
formatStringEvent = formatStringEvent.."_NO_SOURCE";
end
if ( not destEnabled ) then
formatStringEvent = formatStringEvent.."_NO_DEST";
end
if (event=="DAMAGE_SPLIT" and resultStr) then
if (amount == 0) then
formatStringEvent = "ACTION_DAMAGE_SPLIT_ABSORBED_FULL_TEXT";
else
formatStringEvent = "ACTION_DAMAGE_SPLIT_RESULT_FULL_TEXT";
end
end
-- Get the special cased string
if ( _G[formatStringEvent] ) then
formatString = _G[formatStringEvent];
end
sourceEnabled = true;
destEnabled = true;
spellEnabled = true;
valueEnabled = true;
end
-- Actor name construction.
--
local sourceNameStr = "";
local destNameStr = "";
local sourceIcon = "";
local destIcon = "";
local spellNameStr = spellName;
local extraSpellNameStr = extraSpellName;
local itemNameStr = itemName;
local actionEvent = "ACTION_"..event;
local actionStr = _G[actionEvent];
local timestampStr = timestamp;
local powerTypeString = "";
-- If this ever succeeds, the event string is missing.
--
if ( not actionStr ) then
actionStr = event;
end
-- Initialize the strings now
sourceNameStr, destNameStr = sourceName, destName;
-- Special changes for localization when not in full text mode
if ( not settings.fullText and COMBAT_LOG_UNIT_YOU_ENABLED == "1" ) then
-- Replace your name with "You";
if ( sourceName and CombatLog_Object_IsA(sourceFlags, COMBATLOG_FILTER_MINE) ) then
sourceNameStr = UNIT_YOU_SOURCE;
end
if ( destName and CombatLog_Object_IsA(destFlags, COMBATLOG_FILTER_MINE) ) then
destNameStr = UNIT_YOU_DEST;
end
-- Apply the possessive form to the source
if ( sourceName and spellName and _G[actionEvent.."_POSSESSIVE"] == "1" ) then
if ( sourceName and CombatLog_Object_IsA(sourceFlags, COMBATLOG_FILTER_MINE) ) then
sourceNameStr = UNIT_YOU_SOURCE_POSSESSIVE;
end
end
-- Apply the possessive form to the source
if ( destName and ( extraSpellName or itemName ) ) then
if ( destName and CombatLog_Object_IsA(destFlags, COMBATLOG_FILTER_MINE) ) then
destNameStr = UNIT_YOU_DEST_POSSESSIVE;
end
end
-- If its full text mode
else
-- Apply the possessive form to the source
if ( sourceName and spellName and _G[actionEvent.."_POSSESSIVE"] == "1" ) then
sourceNameStr = format(TEXT_MODE_A_STRING_POSSESSIVE, sourceNameStr);
end
-- Apply the possessive form to the dest if the dest has a spell
if ( ( extraSpellName or forceDestPossessive or itemName ) and destName ) then
destNameStr = format(TEXT_MODE_A_STRING_POSSESSIVE, destNameStr);
end
end
-- Unit Tokens
if ( settings.unitTokens ) then
-- Apply the possessive form to the source
if ( sourceName ) then
sourceName = CombatLog_String_GetToken(sourceGUID, sourceName, sourceFlags);
end
if ( destName ) then
destName = CombatLog_String_GetToken(destGUID, destName, destFlags);
end
end
-- Unit Icons
if ( settings.unitIcons ) then
if ( sourceName ) then
sourceIcon = CombatLog_String_GetIcon(sourceRaidFlags, "source");
end
if ( destName ) then
destIcon = CombatLog_String_GetIcon(destRaidFlags, "dest");
end
end
-- Get the source color
if ( sourceName ) then
sourceColor = CombatLog_Color_ColorStringByUnitType( sourceFlags );
end
-- Get the dest color
if ( destName ) then
destColor = CombatLog_Color_ColorStringByUnitType( destFlags );
end
-- Whole line coloring
if ( settings.lineColoring ) then
if ( settings.lineColorPriority == 3 or ( not sourceName and not destName) ) then
lineColor = CombatLog_Color_ColorArrayByEventType( event, filterSettings );
else
if ( ( settings.lineColorPriority == 1 and sourceName ) or not destName ) then
lineColor = CombatLog_Color_ColorArrayByUnitType( sourceFlags, filterSettings );
elseif ( ( settings.lineColorPriority == 2 and destName ) ) then
lineColor = CombatLog_Color_ColorArrayByUnitType( destFlags, filterSettings );
else
lineColor = CombatLog_Color_ColorArrayByUnitType( sourceFlags, filterSettings );
end
end
end
-- Power Type
if ( powerType ) then
powerTypeString = CombatLog_String_PowerType(powerType, amount, alternatePowerType);
if powerTypeString == BALANCE_NEGATIVE_ENERGY then
amount = abs(amount);
end
end
-- Only replace if there's an amount
if ( amount ) then
local amountColor;
-- Color amount numbers
if ( settings.amountColoring ) then
-- To make white swings white
if ( settings.noMeleeSwingColoring and school == SCHOOL_MASK_PHYSICAL and not spellId ) then
-- Do nothing
elseif ( settings.amountActorColoring ) then
if ( sourceName ) then
amountColor = CombatLog_Color_ColorArrayByUnitType( sourceFlags, filterSettings );
elseif ( destName ) then
amountColor = CombatLog_Color_ColorArrayByUnitType( destFlags, filterSettings );
end
elseif ( settings.amountSchoolColoring ) then
amountColor = CombatLog_Color_ColorArrayBySchool(school, filterSettings);
else
amountColor = filterSettings.colors.defaults.damage;
end
end
-- Highlighting
if ( settings.amountHighlighting ) then
local colorArray;
if ( not amountColor ) then
colorArray = lineColor;
else
colorArray = amountColor;
end
amountColor = CombatLog_Color_HighlightColorArray (colorArray);
end
if ( amountColor ) then
amountColor = CombatLog_Color_FloatToText(amountColor);
amount = format("|c%s%s|r", amountColor, amount);
end
schoolString = CombatLog_String_SchoolString(school);
local schoolNameColor = nil;
-- Color school names
if ( settings.schoolNameColoring ) then
if ( settings.noMeleeSwingColoring and school == SCHOOL_MASK_PHYSICAL and not spellId ) then
elseif ( settings.schoolNameActorColoring ) then
if ( sourceName ) then
schoolNameColor = CombatLog_Color_ColorArrayByUnitType( sourceFlags, filterSettings );
elseif ( destName ) then
schoolNameColor = CombatLog_Color_ColorArrayByUnitType( destFlags, filterSettings );
end
else
schoolNameColor = CombatLog_Color_ColorArrayBySchool( school, filterSettings );
end
end
-- Highlighting
if ( settings.schoolNameHighlighting ) then
local colorArray;
if ( not schoolNameColor ) then
colorArray = lineColor;
else
colorArray = schoolNameColor;
end
schoolNameColor = CombatLog_Color_HighlightColorArray (colorArray);
end
if ( schoolNameColor ) then
schoolNameColor = CombatLog_Color_FloatToText(schoolNameColor);
schoolString = format("|c%s%s|r", schoolNameColor, schoolString);
end
end
-- Color source names
if ( settings.unitColoring ) then
if ( sourceName and settings.sourceColoring ) then
sourceNameStr = format("|c%s%s|r", sourceColor, sourceNameStr);
end
if ( destName and settings.destColoring ) then
destNameStr = format("|c%s%s|r", destColor, destNameStr);
end
end
-- If there's an action (always)
if ( actionStr ) then
local actionColor = nil;
-- Color ability names
if ( settings.actionColoring ) then
if ( settings.actionActorColoring ) then
if ( sourceName ) then
actionColor = CombatLog_Color_ColorArrayByUnitType( sourceFlags, filterSettings );
elseif ( destName ) then
actionColor = CombatLog_Color_ColorArrayByUnitType( destFlags, filterSettings );
end
elseif ( settings.actionSchoolColoring and spellSchool ) then
actionColor = CombatLog_Color_ColorArrayBySchool( spellSchool, filterSettings );
else
actionColor = CombatLog_Color_ColorArrayByEventType(event);
end
-- Special option to only color "Miss" if there's no damage
elseif ( settings.missColoring ) then
if ( event ~= "SWING_DAMAGE" and
event ~= "RANGE_DAMAGE" and
event ~= "SPELL_DAMAGE" and
event ~= "SPELL_PERIODIC_DAMAGE" ) then
local actionColor = nil;
if ( settings.actionActorColoring ) then
actionColor = CombatLog_Color_ColorArrayByUnitType( sourceFlags, filterSettings );
elseif ( settings.actionSchoolColoring ) then
actionColor = CombatLog_Color_ColorArrayBySchool( spellSchool, filterSettings );
else
actionColor = CombatLog_Color_ColorArrayByEventType(event);
end
end
end
-- Highlighting
if ( settings.actionHighlighting ) then
local colorArray;
if ( not actionColor ) then
colorArray = lineColor;
else
colorArray = actionColor;
end
actionColor = CombatLog_Color_HighlightColorArray (colorArray);
end
if ( actionColor ) then
actionColor = CombatLog_Color_FloatToText(actionColor);
actionStr = format("|c%s%s|r", actionColor, actionStr);
end
end
-- If there's a spell name
if ( spellName ) then
local abilityColor = nil;
-- Color ability names
if ( settings.abilityColoring ) then
if ( settings.abilityActorColoring ) then
abilityColor = CombatLog_Color_ColorArrayByUnitType( sourceFlags, filterSettings );
elseif ( settings.abilitySchoolColoring ) then
abilityColor = CombatLog_Color_ColorArrayBySchool( spellSchool, filterSettings );
else
if ( spellSchool ) then
abilityColor = filterSettings.colors.defaults.spell;
end
end
end
-- Highlight this color
if ( settings.abilityHighlighting ) then
local colorArray;
if ( not abilityColor ) then
colorArray = lineColor;
else
colorArray = abilityColor;
end
abilityColor = CombatLog_Color_HighlightColorArray (colorArray);
end
if ( abilityColor ) then
abilityColor = CombatLog_Color_FloatToText(abilityColor);
if ( itemId ) then
spellNameStr = spellName;
else
spellNameStr = format("|c%s%s|r", abilityColor, spellName);
end
end
end
-- If there's a spell name
if ( extraSpellName ) then
local abilityColor = nil;
-- Color ability names
if ( settings.abilityColoring ) then
if ( settings.abilitySchoolColoring ) then
abilityColor = CombatLog_Color_ColorArrayBySchool( extraSpellSchool, filterSettings );
else
if ( extraSpellSchool ) then
abilityColor = CombatLog_Color_ColorArrayBySchool( SCHOOL_MASK_HOLY, filterSettings );
else
abilityColor = CombatLog_Color_ColorArrayBySchool( nil, filterSettings );
end
end
end
-- Highlight this color
if ( settings.abilityHighlighting ) then
local colorArray;
if ( not abilityColor ) then
colorArray = lineColor;
else
colorArray = abilityColor;
end
abilityColor = CombatLog_Color_HighlightColorArray (colorArray);
end
if ( abilityColor ) then
abilityColor = CombatLog_Color_FloatToText(abilityColor);
extraSpellNameStr = format("|c%s%s|r", abilityColor, extraSpellName);
end
end
-- Whole line highlighting
if ( settings.lineHighlighting ) then
if ( filterSettings.colors.highlightedEvents[event] ) then
lineColor = CombatLog_Color_HighlightColorArray (lineColor);
end
end
-- Build braces
if ( settings.braces ) then
-- Unit specific braces
if ( settings.unitBraces ) then
if ( sourceName and settings.sourceBraces ) then
sourceNameStr = format(TEXT_MODE_A_STRING_BRACE_UNIT, braceColor, sourceNameStr, braceColor);
end
if ( destName and settings.destBraces ) then
destNameStr = format(TEXT_MODE_A_STRING_BRACE_UNIT, braceColor, destNameStr, braceColor);
end
end
-- Spell name braces
if ( spellName and settings.spellBraces ) then
if ( not itemId ) then
spellNameStr = format(TEXT_MODE_A_STRING_BRACE_SPELL, braceColor, spellNameStr, braceColor);
end
end
if ( extraSpellName and settings.spellBraces ) then
extraSpellNameStr = format(TEXT_MODE_A_STRING_BRACE_SPELL, braceColor, extraSpellNameStr, braceColor);
end
-- Build item braces
if ( itemName and settings.itemBraces ) then
itemNameStr = format(TEXT_MODE_A_STRING_BRACE_ITEM, braceColor, itemNameStr, braceColor);
end
end
local sourceString = "";
local spellString = "";
local actionString = "";
local destString = "";
local valueString = "";
local resultString = "";
local remainingPointsString = "";
if ( sourceEnabled and sourceName and falseSource ) then
sourceString = sourceName;
elseif ( sourceEnabled and sourceName ) then
sourceString = format(TEXT_MODE_A_STRING_SOURCE_UNIT, sourceIcon, sourceGUID, sourceName, sourceNameStr);
end
if ( spellName ) then
if ( nameIsNotSpell ) then
spellString = format(TEXT_MODE_A_STRING_ACTION, originalEvent, spellNameStr);
else
spellString = format(TEXT_MODE_A_STRING_SPELL, spellId, originalEvent, spellNameStr, spellId);
end
end
if ( actionString ) then
actionString = format(TEXT_MODE_A_STRING_ACTION, originalEvent, actionStr);
end
if ( destEnabled and destName ) then
destString = format(TEXT_MODE_A_STRING_DEST_UNIT, destIcon, destGUID, destName, destNameStr);
end
if ( valueEnabled ) then
if ( extraSpellEnabled and extraSpellNameStr ) then
if ( extraNameIsNotSpell ) then
valueString = extraSpellNameStr;
else
valueString = format(TEXT_MODE_A_STRING_SPELL_EXTRA, extraSpellId, originalEvent, extraSpellNameStr, spellId);
end
elseif ( valueIsItem and itemNameStr ) then
valueString = format(TEXT_MODE_A_STRING_ITEM, itemId, itemNameStr);
elseif ( amount ) then
if ( valueTypeEnabled ) then
if ( valueType == 1 and schoolString ) then
valueString = format(TEXT_MODE_A_STRING_VALUE_SCHOOL, amount, schoolString);
elseif ( valueType == 2 and powerTypeString ) then
valueString = format(TEXT_MODE_A_STRING_VALUE_TYPE, amount, powerTypeString);
end
end
if ( valueString == "" ) then
valueString = amount;
end
end
end
if ( resultEnabled and resultStr ) then
resultString = resultStr;
end
if ( not schoolString ) then
schoolString = "";
end
if ( not powerTypeString ) then
powerTypeString = "";
end
if ( not amount ) then
amount = "";
end
if ( not extraAmount) then
extraAmount = "";
end
if ( sourceString == "" and not hideCaster ) then
sourceString = UNKNOWN;
end
if ( destEnabled and destString == "" ) then
destString = UNKNOWN;
end
if ( remainingPoints ) then
remainingPointsString = format(TEXT_MODE_A_STRING_REMAINING_POINTS, remainingPoints);
end
local finalString = format(formatString, sourceString, spellString, actionString, destString, valueString, resultString, schoolString, powerTypeString, amount, extraAmount, remainingPointsString);
finalString = gsub(finalString, " [ ]+", " " ); -- extra white spaces
finalString = gsub(finalString, " ([.,])", "%1" ); -- spaces before periods or comma
finalString = gsub(finalString, "^([ .,]+)", "" ); -- spaces, period or comma at the beginning of a line
if ( timestampEnabled and timestamp ) then
-- Replace the timestamp
finalString = format(TEXT_MODE_A_STRING_TIMESTAMP, date(settings.timestampFormat, timestamp), finalString);
end
-- NOTE: be sure to pass back nil for the color id or the color id may override the r, g, b values for this message line
return finalString, lineColor.r, lineColor.g, lineColor.b;
end
_G.CombatLog_OnEvent = CombatLog_OnEvent
-- Process the event and add it to the combat log
function CombatLog_AddEvent(...)
if ( DEBUG == true ) then
local info = ChatTypeInfo["COMBAT_MISC_INFO"];
local timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags = ...
local message = format("%s, %s, %s, 0x%x, %s, %s, 0x%x",
--date("%H:%M:%S", timestamp),
event,
srcGUID, srcName or "nil", srcFlags,
dstGUID, dstName or "nil", dstFlags);
for i = 9, select("#", ...) do
message = message..", "..(select(i, ...) or "nil");
end
ChatFrame1:AddMessage(message, info.r, info.g, info.b);
end
-- Add the messages
local text, r, g, b, a = CombatLog_OnEvent(Blizzard_CombatLog_CurrentSettings, ... );
if ( text ) then
COMBATLOG:AddMessage(text, r, g, b, a);
end
end
--
-- Overrides for the combat log
--
-- Save the original event handler
local original_OnEvent = COMBATLOG:GetScript("OnEvent");
COMBATLOG:SetScript("OnEvent",
function(self, event, ...)
if ( event == "COMBAT_LOG_EVENT" ) then
CombatLog_AddEvent(...);
return;
elseif ( event == "COMBAT_LOG_EVENT_UNFILTERED") then
--[[
local timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags = select(1, ...);
local message = string.format("%s, %s, %s, 0x%x, %s, %s, 0x%x",
--date("%H:%M:%S", timestamp),
event,
srcGUID, srcName or "nil", srcFlags,
dstGUID, dstName or "nil", dstFlags);
for i = 9, select("#", ...) do
message = message..", "..(select(i, ...) or "nil");
end
ChatFrame1:AddMessage(message);
--COMBATLOG:AddMessage(message);
]]
return;
else
original_OnEvent(self, event, ...);
end
end
);
--COMBATLOG:RegisterEvent("COMBAT_LOG_EVENT");
--COMBATLOG:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
--[[
_G[COMBATLOG:GetName().."Tab"]:SetScript("OnDragStart",
function(self, event, ...)
local chatFrame = _G["ChatFrame"..this:GetID()];
if ( chatFrame == DEFAULT_CHAT_FRAME ) then
if (chatFrame.isLocked) then
return;
end
chatFrame:StartMoving();
MOVING_CHATFRAME = chatFrame;
return;
elseif ( chatFrame.isDocked ) then
FCF_UnDockFrame(chatFrame);
FCF_SetLocked(chatFrame, nil);
local chatTab = _G[chatFrame:GetName().."Tab"];
local x,y = chatTab:GetCenter();
if ( x and y ) then
x = x - (chatTab:GetWidth()/2);
y = y - (chatTab:GetHeight()/2);
chatTab:ClearAllPoints();
chatFrame:ClearAllPoints();
chatFrame:SetPoint("TOPLEFT", "UIParent", "BOTTOMLEFT", x, y - CombatLogQuickButtonFrame:GetHeight());
end
FCF_SetTabPosition(chatFrame, 0);
chatFrame:StartMoving();
MOVING_CHATFRAME = chatFrame;
end
SELECTED_CHAT_FRAME = chatFrame;
end
);
]]--
--
-- XML Function Overrides Part 2
--
--
-- Attach the Combat Log Button Frame to the Combat Log
--
-- On Event
function Blizzard_CombatLog_QuickButtonFrame_OnEvent(self, event, ...)
local arg1 = ...;
if ( event == "ADDON_LOADED" ) then
if ( arg1 == "Blizzard_CombatLog" ) then
Blizzard_CombatLog_Filters = _G.Blizzard_CombatLog_Filters or Blizzard_CombatLog_Filters
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.filters[1];
_G.Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_CurrentSettings;
Blizzard_CombatLog_QuickButton_OnClick( Blizzard_CombatLog_Filters.currentFilter );
Blizzard_CombatLog_Refilter();
for k,v in pairs (Blizzard_CombatLog_UnitTokens) do
Blizzard_CombatLog_UnitTokens[k] = nil;
end
Blizzard_CombatLog_Update_QuickButtons();
--Hide the quick button frame if chatframe1 is selected and the combat log is docked
if ( COMBATLOG.isDocked and SELECTED_CHAT_FRAME == ChatFrame1 ) then
self:Hide();
end
end
end
end
-- BUG: Since we're futzing with the frame height, the combat log tab fades out on hover while other tabs remain faded in. This bug is in the stock version, as well.
local function Blizzard_CombatLog_AdjustCombatLogHeight()
-- This prevents improper positioning of the frame due to the scale not yet being set.
-- This whole method of resizing the frame and extending the background to preserve visual continuity really screws with repositioning after
-- a reload. I'm not sure it's going to work well in the long run.
local uiScale = tonumber(GetCVar("uiScale"));
--if UIParent:GetScale() ~= uiScale then return end
local quickButtonHeight = CombatLogQuickButtonFrame:GetHeight();
if ( COMBATLOG.isDocked ) then
local oldPoint,relativeTo,relativePoint,xOfs,yOfs;
for i=1, COMBATLOG:GetNumPoints() do
oldPoint,relativeTo,relativePoint,xOfs,yOfs = COMBATLOG:GetPoint(i);
if ( oldPoint == "TOPLEFT" ) then
break;
end
end
COMBATLOG:SetPoint("TOPLEFT", relativeTo, relativePoint, xOfs/uiScale, -quickButtonHeight);
end
local yOffset = (3 + quickButtonHeight*uiScale) / uiScale;
local xOffset = 2 / uiScale;
local combatLogBackground = _G[COMBATLOG:GetName().."Background"];
combatLogBackground:SetPoint("TOPLEFT", COMBATLOG, "TOPLEFT", -xOffset, yOffset);
combatLogBackground:SetPoint("TOPRIGHT", COMBATLOG, "TOPRIGHT", xOffset, yOffset);
end
-- On Load
local hooksSet = false
function Blizzard_CombatLog_QuickButtonFrame_OnLoad(self)
self:RegisterEvent("ADDON_LOADED");
-- We're using the _Custom suffix to get around the show/hide bug in FloatingChatFrame.lua.
-- Once the fading is removed from FloatingChatFrame.lua these can do back to the non-custom values, and the dummy frame creation should be removed.
CombatLogQuickButtonFrame = _G.CombatLogQuickButtonFrame_Custom
CombatLogQuickButtonFrameProgressBar = _G.CombatLogQuickButtonFrame_CustomProgressBar
CombatLogQuickButtonFrameTexture = _G.CombatLogQuickButtonFrame_CustomTexture
-- Parent it to the tab so that we just inherit the tab's alpha. No need to do special fading for it.
CombatLogQuickButtonFrame:SetParent(COMBATLOG:GetName() .. "Tab");
CombatLogQuickButtonFrame:ClearAllPoints();
CombatLogQuickButtonFrame:SetPoint("BOTTOMLEFT", COMBATLOG, "TOPLEFT");
CombatLogQuickButtonFrame:SetPoint("BOTTOMRIGHT", COMBATLOG, "TOPRIGHT");
CombatLogQuickButtonFrameProgressBar:Hide();
-- Hook the frame's hide/show events so we can hide/show the quick buttons as appropriate.
local show, hide = COMBATLOG:GetScript("OnShow"), COMBATLOG:GetScript("OnHide")
COMBATLOG:SetScript("OnShow", function(self)
CombatLogQuickButtonFrame_Custom:Show()
--Blizzard_CombatLog_AdjustCombatLogHeight()
COMBATLOG:RegisterEvent("COMBAT_LOG_EVENT");
-- select a filter for the user only the first time it's shown
if ( not self.loaded ) then
Blizzard_CombatLog_QuickButton_OnClick(Blizzard_CombatLog_Filters.currentFilter);
self.loaded = true;
end
return show and show(self)
end)
COMBATLOG:SetScript("OnHide", function(self)
CombatLogQuickButtonFrame_Custom:Hide()
-- Blizzard_CombatLog_AdjustCombatLogHeight()
COMBATLOG:UnregisterEvent("COMBAT_LOG_EVENT");
return hide and hide(self)
end)
if ( COMBATLOG:IsShown() ) then
COMBATLOG:RegisterEvent("COMBAT_LOG_EVENT");
end
FCF_SetButtonSide(COMBATLOG, COMBATLOG.buttonSide, true);
end
local oldFCF_DockUpdate = FCF_DockUpdate;
FCF_DockUpdate = function()
oldFCF_DockUpdate();
Blizzard_CombatLog_AdjustCombatLogHeight();
end
--
-- Combat Log Global Functions
--
--[[
--
-- Returns the correct {} code for the combat log bit
--
-- args:
-- bit - a bit exactly equal to a raid target icon.
--]]
local function Blizzard_CombatLog_BitToBraceCode(bit)
if ( bit == COMBATLOG_OBJECT_RAIDTARGET1 ) then
return "{"..strlower(RAID_TARGET_1).."}";
elseif ( bit == COMBATLOG_OBJECT_RAIDTARGET2 ) then
return "{"..strlower(RAID_TARGET_2).."}";
elseif ( bit == COMBATLOG_OBJECT_RAIDTARGET3 ) then
return "{"..strlower(RAID_TARGET_3).."}";
elseif ( bit == COMBATLOG_OBJECT_RAIDTARGET4 ) then
return "{"..strlower(RAID_TARGET_4).."}";
elseif ( bit == COMBATLOG_OBJECT_RAIDTARGET5 ) then
return "{"..strlower(RAID_TARGET_5).."}";
elseif ( bit == COMBATLOG_OBJECT_RAIDTARGET6 ) then
return "{"..strlower(RAID_TARGET_6).."}";
elseif ( bit == COMBATLOG_OBJECT_RAIDTARGET7 ) then
return "{"..strlower(RAID_TARGET_7).."}";
elseif ( bit == COMBATLOG_OBJECT_RAIDTARGET8 ) then
return "{"..strlower(RAID_TARGET_8).."}";
end
return "";
end
-- Override Hyperlink Handlers
-- The SetItemRef() function hook is to be moved out into the core FrameXML.
-- It is currently in the Constants.lua stub file to simulate being moved out to the core.
--
-- The reason is because Blizzard_CombatLog is a LoD addon and can be replaced by the user
-- If the functionality of these new unit/icon/spell/action links is not in the core FrameXML
-- file in ItemRef.lua, then every combat log addon that replaces Blizzard_CombatLog must
-- provide the same functionality.
-- Players may also get all sorts of errors on trying to click on these new linktypes before
-- Blizzard_CombatLog gets loaded.
-- Override Hyperlink Handlers
-- This entire function hook should/must be directly integrated into ItemRef.lua
-- The reason is because Blizzard_CombatLog is a LoD addon and can be replaced by the user
-- If the functionality of these new unit/icon/spell/action links is not in the core FrameXML
-- file in ItemRef.lua, then every combat log addon that replaces Blizzard_CombatLog must
-- provide the same functionality.
-- Players may also get all sorts of errors on trying to click on these new linktypes before
-- Blizzard_CombatLog gets loaded.
local oldSetItemRef = SetItemRef;
function SetItemRef(link, text, button, chatFrame)
if ( strsub(link, 1, 4) == "unit") then
local _, guid, name = strsplit(":", link);
if ( IsModifiedClick("CHATLINK") ) then
ChatEdit_InsertLink (name);
return;
elseif( button == "RightButton") then
-- Show Popup Menu
EasyMenu(Blizzard_CombatLog_CreateUnitMenu(name, guid), CombatLogDropDown, "cursor", nil, nil, "MENU");
return;
end
elseif ( strsub(link, 1, 4) == "icon") then
local _, bit, direction = strsplit(":", link);
local texture = string.gsub(text,".*|h(.*)|h.*","%1");
-- Show Popup Menu
if( button == "RightButton") then
-- need to fix this to be actual texture
EasyMenu(Blizzard_CombatLog_CreateUnitMenu(Blizzard_CombatLog_BitToBraceCode(tonumber(bit)), nil, tonumber(bit)), CombatLogDropDown, "cursor", nil, nil, "MENU");
elseif ( IsModifiedClick("CHATLINK") ) then
ChatEdit_InsertLink (Blizzard_CombatLog_BitToBraceCode(tonumber(bit)));
end
return;
elseif ( strsub(link, 1,5) == "spell" ) then
local _, spellId, event = strsplit(":", link);
spellId = tonumber (spellId);
if ( IsModifiedClick("CHATLINK") ) then
if ( spellId > 0 ) then
if ( ChatEdit_InsertLink(GetSpellLink(spellId)) ) then
return;
end
else
return;
end
-- Show Popup Menu
elseif( button == "RightButton" and event ) then
EasyMenu(Blizzard_CombatLog_CreateSpellMenu(text, spellId, event), CombatLogDropDown, "cursor", nil, nil, "MENU");
return;
end
elseif ( strsub(link, 1,6) == "action" ) then
local _, event = strsplit(":", link);
-- Show Popup Menu
if( button == "RightButton") then
EasyMenu(Blizzard_CombatLog_CreateActionMenu(event), CombatLogDropDown, "cursor", nil, nil, "MENU");
end
return;
elseif ( strsub(link, 1, 4) == "item") then
if ( IsModifiedClick("CHATLINK") ) then
local name, link = GetItemInfo(text);
ChatEdit_InsertLink (link);
return;
end
end
oldSetItemRef(link, text, button, chatFrame);
end
function Blizzard_CombatLog_Update_QuickButtons()
local baseName = "CombatLogQuickButtonFrame";
local buttonName, button, textWidth;
local buttonIndex = 1;
-- subtract the width of the dropdown button
local clogleft, clogright = COMBATLOG:GetRight(), COMBATLOG:GetLeft();
local maxWidth;
if ( clogleft and clogright ) then
maxWidth = (COMBATLOG:GetRight()-COMBATLOG:GetLeft())-31; --Hacky hacky because GetWidth goes crazy when it is docked
else
maxWidth = COMBATLOG:GetWidth() - 31;
end
local totalWidth = 0;
local padding = 13;
local showMoreQuickButtons = true;
for index, filter in ipairs(_G.Blizzard_CombatLog_Filters.filters) do
buttonName = baseName.."Button"..buttonIndex;
button = _G[buttonName];
if ( ShowQuickButton(filter) and showMoreQuickButtons ) then
if ( not button ) then
button = CreateFrame("BUTTON", buttonName, CombatLogQuickButtonFrame, "CombatLogQuickButtonTemplate");
end
button:SetText(filter.name);
textWidth = button:GetTextWidth();
totalWidth = totalWidth + textWidth + padding;
if ( totalWidth <= maxWidth ) then
button:SetWidth(textWidth+padding);
button:SetID(index);
button:Show();
button.tooltip = filter.tooltip;
if ( buttonIndex > 1 ) then
button:SetPoint("LEFT", _G[baseName.."Button"..buttonIndex-1], "RIGHT", 3, 0);
else
button:SetPoint("LEFT", CombatLogQuickButtonFrame, "LEFT", 3, 0);
end
if ( Blizzard_CombatLog_Filters.currentFilter == index and (Blizzard_CombatLog_CurrentSettings and not Blizzard_CombatLog_CurrentSettings.isTemp) ) then
button:LockHighlight();
else
button:UnlockHighlight();
end
filter.onQuickBar = true;
else
-- Don't show anymore buttons if the maxwidth has been exceeded
showMoreQuickButtons = false;
button:Hide();
filter.onQuickBar = false;
end
buttonIndex = buttonIndex + 1;
else
filter.onQuickBar = false;
if ( button ) then
button:Hide();
end
end
end
-- Hide remaining buttons
repeat
button = _G[baseName.."Button"..buttonIndex];
if ( button ) then
button:Hide();
end
buttonIndex = buttonIndex+1;
until not button;
end
_G.Blizzard_CombatLog_Update_QuickButtons = Blizzard_CombatLog_Update_QuickButtons
function Blizzard_CombatLog_QuickButton_OnClick(id)
Blizzard_CombatLog_Filters.currentFilter = id;
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.filters[Blizzard_CombatLog_Filters.currentFilter];
Blizzard_CombatLog_ApplyFilters(Blizzard_CombatLog_CurrentSettings);
if ( Blizzard_CombatLog_CurrentSettings.settings.showHistory ) then
Blizzard_CombatLog_Refilter();
end
Blizzard_CombatLog_Update_QuickButtons();
PlaySound("UChatScrollButton");
end
function ShowQuickButton(filter)
if ( filter.hasQuickButton ) then
if ( IsInRaid() ) then
return filter.quickButtonDisplay.raid;
elseif ( IsInGroup() ) then
return filter.quickButtonDisplay.party;
else
return filter.quickButtonDisplay.solo;
end
else
return false;
end;
end
function Blizzard_CombatLog_RefreshGlobalLinks()
-- Have to do this because Blizzard_CombatLog_Filters is a reference to the _G.Blizzard_CombatLog_Filters
Blizzard_CombatLog_CurrentSettings = Blizzard_CombatLog_Filters.filters[Blizzard_CombatLog_Filters.currentFilter];
end