vanilla-wow-addons – Rev 1
?pathlinks?
---------------
-- CONSTANTS --
---------------
-- NOTE: "DMI"s are the legacy name for quantities that DM tracks.
-- However, the term "quantity" refers to a quantity that is displayed.
-- There are more Quantities than there are DMIs.
-- Better names for these two things would be "Real" vs. "Virtual" or "Display" quantities.
DMI_DAMAGE = 1;
DMI_HEALING = 2;
DMI_DAMAGED = 3;
DMI_HEALED = 4;
DMI_REPORT_MAX = 4;
DMI_CURING = 5;
DMI_OVERHEAL = 6;
DMI_ABSHEAL = 7;
DMI_BUILTIN_MAX = 7;
DMI_MAX = 7;
-- Just legacy crap.
DMI_1 = DMI_DAMAGE;
DMI_2 = DMI_HEALING;
DMI_3 = DMI_DAMAGED;
DMI_4 = DMI_HEALED;
-- Defined Quantities.
-- These numbers index into the DM_QUANTDEFS table.
DamageMeters_Quantity_DAMAGE = 1;
DamageMeters_Quantity_HEALING = 2;
DamageMeters_Quantity_DAMAGED = 3;
DamageMeters_Quantity_HEALINGRECEIVED = 4;
DamageMeters_Quantity_CURING = 5;
DamageMeters_Quantity_OVERHEAL = 6;
DamageMeters_Quantity_ABSHEAL = 7;
DamageMeters_Quantity_DPS = 8;
DamageMeters_Quantity_HPS = 9;
DamageMeters_Quantity_DTPS = 10;
DamageMeters_Quantity_HTPS = 11;
DamageMeters_Quantity_CURINGFIGHT = 12;
DamageMeters_Quantity_OVERHEALFIGHT = 13;
DamageMeters_Quantity_ABSHEALFIGHT = 14;
DamageMeters_Quantity_TIME = 15;
DamageMeters_Quantity_NETDAMAGE = 16;
DamageMeters_Quantity_NETHEALING = 17;
DamageMeters_Quantity_DAMAGEPLUSHEALING = 18;
DamageMeters_Quantity_HEALTH = 19;
DamageMeters_Quantity_OVERHEALPERCENTAGE = 20;
-- While this is assigned here, this number is actually CALCULATED when
-- DamageMeters is loaded. (It is set to the length of DM_QUANTDEFS). This was intended to
-- allow other mods to add quantities, but who knows if its really possible.
DamageMeters_Quantity_MAX = 18;
-- These aren't actualy quantities, but rather just flags to DoReport.
DamageMeters_ReportQuantity_Total = -1;
DamageMeters_ReportQuantity_Leaders = -2;
DamageMeters_ReportQuantity_Events = -3;
-------------------------------------------------------------------------------
-- Virtual Quantity Definitions --
--[[
name - The localized string name of this quantity.
psName - [Optional] The string name of the quantity when it is per-second.
defaultColor - The default color of the frame when the quantity is visible.
dmi - [Optional] The DMI that this quantity is based on.
bUsesFightTable - True if this quantity uses the Fight table instead of the Active one.
toggleQuant - The quantity to switch to when we are toggled. (Note that toggling really means between fight/regular).
filterDefault - Default quantity filter setting.
pfnGetValue - function(playerStruct). A quantityDef can specify a function that the system is to call
to get a given player's value for this quantity.
titanAbbrev - A short string (ideally a few characters) to be shown in the titan panel for this quantity.
]]--
DM_QUANTDEFS = {};
DM_QUANTDEFS[DamageMeters_Quantity_DAMAGE] = {
name = DM_QUANTSTRING_DAMAGEDONE,
psName = nil,
defaultColor = {1.0, 0.0, 0.0, 0.8},
dmi = DMI_DAMAGE,
bUsesFightTable = false,
toggleQuant = DamageMeters_Quantity_DPS,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_DAMAGEDONE;
};
DM_QUANTDEFS[DamageMeters_Quantity_HEALING] = {
name = DM_QUANTSTRING_HEALINGDONE,
psName = nil,
defaultColor = {0.0, 1.0, 0.0, 0.8},
dmi = DMI_HEALING,
bUsesFightTable = false,
toggleQuant = DamageMeters_Quantity_HPS,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_HEALINGDONE;
};
DM_QUANTDEFS[DamageMeters_Quantity_DAMAGED] = {
name = DM_QUANTSTRING_DAMAGETAKEN,
psName = nil,
defaultColor = {1.0, 0.5, 0.0, 0.8},
dmi = DMI_DAMAGED,
bUsesFightTable = false,
toggleQuant = DamageMeters_Quantity_DTPS,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_DAMAGETAKEN;
};
DM_QUANTDEFS[DamageMeters_Quantity_HEALINGRECEIVED] = {
name = DM_QUANTSTRING_HEALINGTAKEN,
psName = nil,
defaultColor = {0.0, 0.0, 1.0, 0.8},
dmi = DMI_HEALED,
bUsesFightTable = false,
toggleQuant = DamageMeters_Quantity_HTPS,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_HEALINGTAKEN;
};
DM_QUANTDEFS[DamageMeters_Quantity_CURING] = {
name = DM_QUANTSTRING_CURING,
psName = nil,
defaultColor = {0.6, 0.7, 0.8, 0.8},
dmi = DMI_CURING,
bUsesFightTable = false,
toggleQuant = DamageMeters_Quantity_CURINGFIGHT,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_CURING;
};
DM_QUANTDEFS[DamageMeters_Quantity_OVERHEAL] = {
name = DM_QUANTSTRING_OVERHEAL,
psName = nil,
defaultColor = {1.0, 1.0, 0.0, 0.8},
dmi = DMI_OVERHEAL,
bUsesFightTable = false,
filterDefault = true,
toggleQuant = DamageMeters_Quantity_OVERHEALFIGHT,
titanAbbrev = DM_QUANTABBREV_OVERHEAL;
};
DM_QUANTDEFS[DamageMeters_Quantity_ABSHEAL] = {
name = DM_QUANTSTRING_ABSHEAL,
psName = nil,
defaultColor = {1.0, 0.0, 1.0, 0.8},
dmi = DMI_ABSHEAL,
bUsesFightTable = false,
filterDefault = false,
toggleQuant = DamageMeters_Quantity_ABSHEALFIGHT,
titanAbbrev = DM_QUANTABBREV_ABSHEAL;
};
DM_QUANTDEFS[DamageMeters_Quantity_DPS] = {
name = DM_QUANTSTRING_DAMAGEDONE_FIGHT,
psName = DM_QUANTSTRING_DAMAGEDONE_PS,
defaultColor = {0.8, 0.0, 0.0, 0.8},
dmi = DMI_DAMAGE,
bUsesFightTable = true,
toggleQuant = DamageMeters_Quantity_DAMAGE,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_DAMAGEDONE_PS;
};
DM_QUANTDEFS[DamageMeters_Quantity_HPS] = {
name = DM_QUANTSTRING_HEALINGDONE_FIGHT,
psName = DM_QUANTSTRING_HEALINGDONE_PS,
defaultColor = {0.0, 0.8, 0.0, 0.8},
dmi = DMI_HEALING,
bUsesFightTable = true,
toggleQuant = DamageMeters_Quantity_HEALING,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_HEALINGDONE_PS;
};
DM_QUANTDEFS[DamageMeters_Quantity_DTPS] = {
name = DM_QUANTSTRING_DAMAGETAKEN_FIGHT,
psName = DM_QUANTSTRING_DAMAGETAKEN_PS,
defaultColor = {1.0, 0.7, 0.2, 0.8},
dmi = DMI_DAMAGED,
bUsesFightTable = true,
toggleQuant = DamageMeters_Quantity_DAMAGED,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_DAMAGETAKEN_PS,
};
DM_QUANTDEFS[DamageMeters_Quantity_HTPS] = {
name = DM_QUANTSTRING_HEALINGTAKEN_FIGHT,
psName = DM_QUANTSTRING_HEALINGTAKEN_PS,
defaultColor = {0.0, 0.0, 0.8, 0.8},
dmi = DMI_HEALED,
bUsesFightTable = true,
toggleQuant = DamageMeters_Quantity_HEALINGRECEIVED,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_HEALINGTAKEN_PS,
};
DM_QUANTDEFS[DamageMeters_Quantity_CURINGFIGHT] = {
name = DM_QUANTSTRING_CURING_FIGHT,
psName = DM_QUANTSTRING_CURING_PS,
defaultColor = {0.4, 0.5, 0.6, 0.8},
dmi = DMI_CURING,
bUsesFightTable = true,
toggleQuant = DamageMeters_Quantity_CURING,
filterDefault = true,
titanAbbrev = DM_QUANTABBREV_CURING_PS,
};
DM_QUANTDEFS[DamageMeters_Quantity_OVERHEALFIGHT] = {
name = DM_QUANTSTRING_OVERHEAL_FIGHT,
psName = DM_QUANTSTRING_OVERHEAL_PS,
defaultColor = {0.4, 0.4, 0.0, 0.8},
dmi = DMI_OVERHEAL,
bUsesFightTable = true,
filterDefault = true,
toggleQuant = DamageMeters_Quantity_OVERHEALPERCENTAGE,
titanAbbrev = DM_QUANTABBREV_OVERHEAL_PS,
};
DM_QUANTDEFS[DamageMeters_Quantity_ABSHEALFIGHT] = {
name = DM_QUANTSTRING_ABSHEAL_FIGHT,
psName = DM_QUANTSTRING_ABSHEAL_PS,
defaultColor = {0.8, 0.0, 0.8, 0.8},
dmi = DMI_ABSHEAL,
bUsesFightTable = true,
filterDefault = false,
toggleQuant = DamageMeters_Quantity_ABSHEAL,
titanAbbrev = DM_QUANTABBREV_ABSHEAL_PS,
};
DM_QUANTDEFS[DamageMeters_Quantity_TIME] = {
name = DM_QUANTSTRING_IDLETIME,
psName = nil,
defaultColor = {0.0, 0.4, 1.0, 0.8},
dmi = nil,
bUsesFightTable = false,
filterDefault = true,
pfnGetValue = function(playerStruct) return GetTime() - playerStruct.lastTime; end,
formatString = "%.1f",
titanAbbrev = DM_QUANTABBREV_IDLETIME;
};
DM_QUANTDEFS[DamageMeters_Quantity_NETDAMAGE] = {
name = DM_QUANTSTRING_NETDAMAGE,
psName = nil,
defaultColor = {0.5, 0.0, 0.0, 0.8},
dmi = nil,
bUsesFightTable = false,
filterDefault = false,
pfnGetValue = function(playerStruct) return playerStruct.dmiData[DMI_DAMAGE].q - playerStruct.dmiData[DMI_DAMAGED].q; end,
titanAbbrev = DM_QUANTABBREV_NETDAMAGE;
};
DM_QUANTDEFS[DamageMeters_Quantity_NETHEALING] = {
name = DM_QUANTSTRING_NETHEALING,
psName = nil,
defaultColor = {0.0, 0.5, 0.0, 0.8},
dmi = nil,
bUsesFightTable = false,
filterDefault = false,
pfnGetValue = function(playerStruct) return playerStruct.dmiData[DMI_HEALING].q - playerStruct.dmiData[DMI_HEALED].q; end,
titanAbbrev = DM_QUANTABBREV_NETHEALING;
};
DM_QUANTDEFS[DamageMeters_Quantity_DAMAGEPLUSHEALING] = {
name = DM_QUANTSTRING_DAMAGEPLUSHEALING,
psName = nil,
defaultColor = {0.5, 0.5, 0.5, 0.8},
dmi = nil,
bUsesFightTable = false,
filterDefault = false,
pfnGetValue = function(playerStruct) return playerStruct.dmiData[DMI_DAMAGE].q + playerStruct.dmiData[DMI_HEALING].q; end,
titanAbbrev = DM_QUANTABBREV_DAMAGEPLUSHEALING;
};
DM_QUANTDEFS[DamageMeters_Quantity_HEALTH] = {
name = DM_QUANTSTRING_HEALTH;
psName = nil,
defaultColor = {0.5, 0.3, 0.7, 0.8},
dmi = nil,
bUsesFightTable = false,
filterDefault = false,
pfnGetValue = function(playerStruct) return playerStruct.health; end;
titanAbbrev = DM_QUANTABBREV_HEALTH;
};
DM_QUANTDEFS[DamageMeters_Quantity_OVERHEALPERCENTAGE] = {
name = DM_QUANTSTRING_OVERHEAL_PERCENTAGE,
psName = nil,
defaultColor = {0.5, 0.5, 0.7, 0.8},
dmi = nil,
bUsesFightTable = false,
filterDefault = false,
pfnGetValue = function(playerStruct) return floor(100 * DM_GetFraction(playerStruct.dmiData[DMI_OVERHEAL].q, playerStruct.dmiData[DMI_HEALING].q + playerStruct.dmiData[DMI_OVERHEAL].q)); end,
toggleQuant = DamageMeters_Quantity_OVERHEAL,
titanAbbrev = DM_QUANTABBREV_OVERHEAL_PERCENTAGE;
};
--[[
DM_QUANTDEFS[DamageMeters_Quantity_DANDERATING] = {
name = DM_QUANTSTRING_DANDERATING,
psName = nil,
defaultColor = {1.0, 0.6, 0.6, 0.8},
dmi = nil,
bUsesFightTable = false,
filterDefault = false,
pfnGetValue =
function(playerStruct)
local dmgIndex = ( DamageMeters_totalsTable[DMT_ACTIVE] ~= nil and
DamageMeters_totalsTable[DMT_ACTIVE][DMI_DAMAGE] ~= nil and
DamageMeters_totalsTable[DMT_ACTIVE][DMI_DAMAGE] > 0)
and
floor(playerStruct.dmiData[DMI_DAMAGE].q * 500.0 / DamageMeters_totalsTable[DMT_ACTIVE][DMI_DAMAGE])
or
0;
local healIndex = ( DamageMeters_totalsTable[DMT_ACTIVE] ~= nil and
DamageMeters_totalsTable[DMT_ACTIVE][DMI_HEALING] ~= nil and
DamageMeters_totalsTable[DMT_ACTIVE][DMI_HEALING] > 0)
and
floor(playerStruct.dmiData[DMI_HEALING].q * 500.0 / DamageMeters_totalsTable[DMT_ACTIVE][DMI_HEALING])
or
0;
return dmgIndex + healIndex;
end,
};
]]--
-------------
-- GLOBALS --
-------------
DamageMeters_rankTables = {};
DamageMeters_rankTables[DM_TABLE_A] = {};
DamageMeters_rankTables[DM_TABLE_B] = {};
DamageMeters_rankTables[DMT_FIGHT] = {};
DamageMeters_totalsTable = {};
DamageMeters_totalsTable[DM_TABLE_A] = {};
DamageMeters_totalsTable[DM_TABLE_B] = {};
DamageMeters_totalsTable[DMT_FIGHT] = {};
-------------------------------------------------
-- FUNCTIONS --
-------------------------------------------------
function DamageMeters_IsQuantityFight(quantity)
if (DM_QUANTDEFS[quantity]) then
return DM_QUANTDEFS[quantity].bUsesFightTable;
end
-- DMReporter can call this with plug-in quantities. In those cases the quantdefs aren't filled in.
-- This could be a problem if a plugin uses a quantity that isn't just a simple DMI.
return false;
end
function DamageMeters_IsQuantityPS(quantity, forcePSFlag)
return (DamageMeters_flags[DMFLAG_showFightAsPS] or forcePSFlag) and (DM_QUANTDEFS[quantity].bUsesFightTable);
end
function DamageMeters_GetQuantityDMI(quantity)
if (nil == quantity) then
DMPrintD("DamageMeters_GetQuantityDMI: quantity = nil");
end
return DM_QUANTDEFS[quantity].dmi;
end
-- This function is about as fast as I know how to make it. It doesn't protect
-- against invalid inputs at all.
function DamageMeters_GetQuantityValue(quantity, tableIndex, playerIndex)
local playerStruct = DamageMeters_tables[tableIndex][playerIndex];
if (DamageMeters_Quantity_TIME == DamageMeters_quantity) then
return GetTime() - playerStruct.lastTime;
else
local quantDef = DM_QUANTDEFS[quantity];
local value = 0;
if (nil ~= playerStruct) then
if (nil ~= quantDef.pfnGetValue) then
value = quantDef.pfnGetValue(playerStruct);
else
value = playerStruct.dmiData[quantDef.dmi].q;
end
if (DamageMeters_IsQuantityPS(quantity)) then
value = DamageMeters_GetCombatValuePS(value);
end
end
return value;
end
end
-- This is a slow function. Not used much, I think.
function DamageMeters_GetQuantityValueString(quantity, playerName)
local quantDef = DM_QUANTDEFS[quantity];
local tableIndex;
if (quantDef.bUsesFightTable) then
tableIndex = DMT_FIGHT;
else
tableIndex = DMT_ACTIVE;
end
local playerIndex = DamageMeters_GetPlayerIndex(playerName, tableIndex);
if (playerIndex ~= nil) then
local value = DamageMeters_GetQuantityValue(quantity, tableIndex, playerIndex);
local formatString;
if (quantDef.formatString) then
formatString = quantDef.formatString;
else
if (DamageMeters_IsQuantityPS(quantity)) then
formatString = "%0.1f";
else
formatString = "%d";
end
end
return string.format(formatString, value);
else
return "-";
end
end
function DamageMeters_GetQuantityString(quantity, forcePSFlag)
if (DamageMeters_IsQuantityPS(quantity, forcePSFlag)) then
return DM_QUANTDEFS[quantity].psName;
end
return DM_QUANTDEFS[quantity].name;
end
function DamageMeters_GetPlayerIndex(player, searchTableIndex)
if (nil == searchTableIndex) then
searchTableIndex = DMT_ACTIVE;
end
local i;
for i = 1, table.getn(DamageMeters_tables[searchTableIndex]) do
if (DamageMeters_tables[searchTableIndex][i].player == player) then
return i;
end
end
return nil;
end
DMSortTemp_sortType = 1;
DMSortTemp_quantity = 1;
DMSortTemp_dmi = 1;
-- This could be broken into two separate increasing/decreasing functions
-- for increased performance.
function DMSortFunc_Default(a,b)
local result;
if (a.dmiData[DMSortTemp_dmi].q == b.dmiData[DMSortTemp_dmi].q) then
if (DMSortTemp_sortType == DamageMeters_Sort_INCREASING) then
result = a.player > b.player;
else
result = a.player < b.player;
end
else
if (DMSortTemp_sortType == DamageMeters_Sort_INCREASING) then
result = a.dmiData[DMSortTemp_dmi].q < b.dmiData[DMSortTemp_dmi].q;
else
result = a.dmiData[DMSortTemp_dmi].q > b.dmiData[DMSortTemp_dmi].q;
end
end
return result;
end
function DMSortFunc_Alphabetical(a, b)
return a.player < b.player;
end
function DMSortFunc_Time(a, b)
local result;
if (a.lastTime == b.lastTime) then
result = a.player < b.player;
else
result = a.lastTime < b.lastTime;
end
if (DMSortTemp_sortType == DamageMeters_Sort_INCREASING) then
result = not result;
end
return result;
end
function DMSortFunc_Custom(a, b)
local valfunc = DM_QUANTDEFS[DMSortTemp_quantity].pfnGetValue;
local aValue = valfunc(a);
local bValue = valfunc(b);
local result;
if (aValue == bValue) then
if (DMSortTemp_sortType == DamageMeters_Sort_INCREASING) then
result = a.player > b.player;
else
result = a.player < b.player;
end
else
if (DMSortTemp_sortType == DamageMeters_Sort_INCREASING) then
result = aValue < bValue;
else
result = aValue > bValue;
end
end
return result;
end
-- In the case of a tie, sort alphabetically.
function DamageMeters_DoSort(tableToSort, quantity, sortType)
if (DM_Bypass["Sort"] == true) then
return;
end
if (nil == sortType) then
sortType = DamageMeters_sort;
end
DMSortTemp_sortType = sortType;
DMSortTemp_quantity = quantity;
DMSortTemp_dmi = DM_QUANTDEFS[quantity].dmi;
if (DamageMeters_Sort_ALPHABETICAL == sortType) then
table.sort(tableToSort, DMSortFunc_Alphabetical);
return;
end
if (quantity == DamageMeters_Quantity_TIME) then
table.sort(tableToSort, DMSortFunc_Time);
return;
elseif (DM_QUANTDEFS[quantity].pfnGetValue ~= nil) then
table.sort(tableToSort, DMSortFunc_Custom);
return;
else
DMSortTemp_quantity = DamageMeters_GetQuantityDMI(quantity);
table.sort(tableToSort, DMSortFunc_Default);
return;
end
end
-- No reason to believe this doesn't work but it has never been used.
--[[
function DamageMeters_BuildSortHash(sortType)
DamageMeters_tableSortHash = {};
-- Build the unsorted hash.
local quant;
for quant = 1, DamageMeters_Quantity_MAX do
DamageMeters_tableSortHash[quant] = {};
local quantTable = (DM_QUANTDEFS[quant].bUsesFightTable) and DMT_FIGHT or DMT_ACTIVE;
-- Populate the table for this quantity.
local playerIndex;
for playerIndex = 1, table.getn(DamageMeters_tables[quantTable]) do
DamageMeters_tableSortHash[quant][playerIndex] = {};
DamageMeters_tableSortHash[quant][playerIndex].playerName = DamageMeters_tables[quantTable][playerIndex].player;
DamageMeters_tableSortHash[quant][playerIndex].playerIndex = playerIndex;
DamageMeters_tableSortHash[quant][playerIndex].value = DamageMeters_GetQuantityValue(quant, quantTable, playerIndex);
end
-- Sort this quantity.
table.sort(DamageMeters_tableSortHash[quant],
function(a,b)
if (a.value == b.value or DamageMeters_Sort_ALPHABETICAL == sortType) then
return a.playerName < b.playerName;
elseif (DamageMeters_Sort_INCREASING == sortType) then
return a.value > b.value;
else -- DamageMeters_Sort_DECREASING implied.
return a.value < b.value;
end
end
);
end
end
]]--
DM_fakeTables = {};
DM_fakeTablesInitialized = false;
function DamageMeters_InitFakeTables()
for ix = 1, 2 do
DM_fakeTables[ix] = {};
for index = 1, DamageMeters_TABLE_MAX do
DM_fakeTables[ix][index] = {};
DM_fakeTables[ix][index].player = nil;
DM_fakeTables[ix][index].lastTime = -1;
DM_fakeTables[ix][index].dmiData = {};
for dmi = 1, DMI_MAX do
DM_fakeTables[ix][index].dmiData[dmi] = {};
DM_fakeTables[ix][index].dmiData[dmi].q = 0;
end
end
end
DM_fakeTablesInitialized = true;
end
-- The bRankQuantities parameter is a hack. Its only used by TitanDamageMeters.lua.
-- It will only work as expected if the tableIx isn't DMT_FIGHT already.
-- If true, this function will determine the ranks of -quantities-, not DMIs.
function DamageMeters_DetermineRanks(tableIx, bRankQuantities)
if (DM_Bypass["Determine Ranks"] == true) then
return;
end
if (not DM_fakeTablesInitialized) then
DamageMeters_InitFakeTables();
end
local index, playerStruct;
local indexMax = table.getn(DamageMeters_tables[tableIx]);
for index = 1, indexMax do
if (nil == DM_fakeTables[1][index]) then
DM_fakeTables[1][index] = {};
DM_fakeTables[1][index].dmiData = {};
for dmi = 1, DMI_MAX do
DM_fakeTables[1][index].dmiData[dmi] = {};
end
end
DM_fakeTables[1][index].player = DamageMeters_tables[tableIx][index].player;
DM_fakeTables[1][index].lastTime = DamageMeters_tables[tableIx][index].lastTime;
local dmi;
for dmi = 1, DMI_MAX do
DM_fakeTables[1][index].dmiData[dmi].q = DamageMeters_tables[tableIx][index].dmiData[dmi].q;
end
end
for index = (indexMax + 1), DamageMeters_TABLE_MAX do
DM_fakeTables[1][index] = nil;
end
if (bRankQuantities) then
local indexMax = table.getn(DamageMeters_tables[DMT_FIGHT]);
for index = 1, indexMax do
if (nil == DM_fakeTables[2][index]) then
DM_fakeTables[2][index] = {};
DM_fakeTables[2][index].dmiData = {};
for dmi = 1, DMI_MAX do
DM_fakeTables[2][index].dmiData[dmi] = {};
end
end
DM_fakeTables[2][index].player = DamageMeters_tables[DMT_FIGHT][index].player;
DM_fakeTables[2][index].lastTime = DamageMeters_tables[DMT_FIGHT][index].lastTime;
local dmi;
for dmi = 1, DMI_MAX do
DM_fakeTables[2][index].dmiData[dmi].q = DamageMeters_tables[DMT_FIGHT][index].dmiData[dmi].q;
end
end
for index = (indexMax + 1), DamageMeters_TABLE_MAX do
DM_fakeTables[2][index] = nil;
end
end
-----------
if (DM_Bypass["Determine Ranks 1"] == true) then
return;
end
local count = table.getn(DamageMeters_tables[tableIx]);
local countPS = table.getn(DamageMeters_tables[DMT_FIGHT]);
local quantity;
local max = bRankQuantities and DamageMeters_Quantity_MAX or DMI_MAX;
for quantity = 1, max do
local fakeTableToUseIndex;
local countToUse;
local tableIxToUse;
if (bRankQuantities and DamageMeters_IsQuantityPS(quantity)) then
fakeTableToUseIndex = 2;
countToUse = countPS;
tableIxToUse = DMT_FIGHT;
else
fakeTableToUseIndex = 1;
countToUse = count;
tableIxToUse = tableIx;
end
DamageMeters_DoSort(DM_fakeTables[fakeTableToUseIndex], quantity, DamageMeters_Sort_DECREASING);
-- Mark all players as unused in the rank table. We'll mark them used as we
-- need to in the next loop.
for playerName, struct in DamageMeters_rankTables[tableIxToUse] do
struct._used = false;
end
local index;
for index = 1, countToUse do
local playerName = DM_fakeTables[fakeTableToUseIndex][index].player;
if (DamageMeters_rankTables[tableIxToUse][playerName] == nil) then
DamageMeters_rankTables[tableIxToUse][playerName] = {};
end
DamageMeters_rankTables[tableIxToUse][playerName][quantity] = index;
DamageMeters_rankTables[tableIxToUse][playerName]._used = true;
end
-- Remove any players from the rank table we aren't using.
for playerName, struct in DamageMeters_rankTables[tableIxToUse] do
if (struct._used == false) then
DamageMeters_rankTables[tableIxToUse][playerName] = nil;
end
end
end
end
function DamageMeters_DetermineTotals()
--DamageMeters_totalsTable = {};
DamageMeters_DetermineTotalsForATable(DMT_ACTIVE);
DamageMeters_DetermineTotalsForATable(DMT_FIGHT);
end
function DamageMeters_DetermineTotalsForATable(tableIx)
--DamageMeters_totalsTable[tableIx] = {};
local dmi;
for dmi = 1, DMI_MAX do
DamageMeters_totalsTable[tableIx][dmi] = 0;
end
local index, info;
for index,info in DamageMeters_tables[tableIx] do
for dmi = 1, DMI_MAX do
DamageMeters_totalsTable[tableIx][dmi] = DamageMeters_totalsTable[tableIx][dmi] + info.dmiData[dmi].q;
end
end
end
function DamageMeters_DoReport(reportQuantity, destination, invert, start, count, tellTarget)
local msg;
if (destination == "BUFFER") then
DamageMeters_reportBuffer = "";
elseif (destination == "PARTY") then
if (GetNumPartyMembers() == 0) then
DMPrint(DM_ERROR_NOPARTY);
return;
end
elseif (destination == "RAID") then
if (GetNumRaidMembers() == 0) then
DMPrint(DM_ERROR_NORAID);
return;
end
end
local tableIx = DMT_ACTIVE;
if (DamageMeters_IsQuantityFight(reportQuantity)) then
tableIx = DMT_FIGHT;
end
-- Determine bounds.
local finish = start + count - 1;
if (finish > table.getn(DamageMeters_tables[tableIx])) then
finish = table.getn(DamageMeters_tables[tableIx]);
end
local step = 1;
if (invert) then
start = finish;
finish = 1;
step = -1;
end
------------
-- Header --
------------
if (reportQuantity == DamageMeters_ReportQuantity_Total) then
msg = string.format(DM_MSG_FULLREPORTHEADER1, count, table.getn(DamageMeters_tables[tableIx]));
DamageMeters_SendReportMsg(msg, destination, tellTarget);
DamageMeters_SendReportMsg(DM_MSG_FULLREPORTHEADER2, destination, tellTarget);
msg = DM_MSG_FULLREPORTHEADER3;
elseif (reportQuantity == DamageMeters_ReportQuantity_Leaders) then
local header = string.format(DM_MSG_LEADERREPORTHEADER, count, table.getn(DamageMeters_tables[tableIx]));
local q;
for q = 1, DMI_REPORT_MAX do
header = string.format("%s| %-21s", header, DM_QUANTDEFS[q].name);
end
msg = header.."\n-------------------------------------------------------------------------------------------";
elseif (reportQuantity == DamageMeters_ReportQuantity_Events) then
msg = string.format(DM_MSG_EVENTREPORTHEADER, count, table.getn(DamageMeters_tables[tableIx]));
else
msg = string.format(DM_MSG_REPORTHEADER, DamageMeters_GetQuantityString(reportQuantity), count, table.getn(DamageMeters_tables[tableIx]));
end
DamageMeters_SendReportMsg(msg, destination, tellTarget);
if (reportQuantity > 0) then
DamageMeters_DoSort(DamageMeters_tables[tableIx], reportQuantity);
end
local reportQuantityDMI = nil;
if (reportQuantity > 0) then
reportQuantityDMI = DamageMeters_GetQuantityDMI(reportQuantity);
end
-- Calculate totals.
local totalValue = 0;
local index;
local info;
local totals = {0, 0, 0, 0, 0, 0, 0};
if (reportQuantity > 0) then
if (DamageMeters_Quantity_TIME ~= reportQuantity) then
local playerIndex;
for playerIndex = 1, table.getn(DamageMeters_tables[tableIx]) do
totalValue = totalValue + DamageMeters_GetQuantityValue(reportQuantity, tableIx, playerIndex);
end
end
elseif (reportQuantity == DamageMeters_ReportQuantity_Total or
reportQuantity == DamageMeters_ReportQuantity_Leaders) then
for index,info in DamageMeters_tables[tableIx] do
totals[1] = totals[1] + info.dmiData[DMI_1].q;
totals[2] = totals[2] + info.dmiData[DMI_2].q;
totals[3] = totals[3] + info.dmiData[DMI_3].q;
totals[4] = totals[4] + info.dmiData[DMI_4].q;
totals[5] = totals[5] + info.dmiData[DMI_DAMAGE].hitCount;
totals[6] = totals[6] + info.dmiData[DMI_DAMAGE].critCount;
end
DamageMeters_DetermineRanks(tableIx);
end
---------------
-- Main Loop --
---------------
local formatStrTotalMain_A = "%-12s %7d[%2d] %7d[%2d] %7d[%2d] %7d[%2d] %7d %7d";
local formatStrTotalTotals = "%-12s %11d %11d %11d %11d %7d %7d";
-- Careful here--if there isn't a space after each | it can lock up.
local formatStrTotalMain_B = "%2d| %8d %-12s| %8d %-12s| %8d %-12s| %8d %-12s";
local formatStrLeaderTotals= " =| %-20d | %-20d | %-20d | %-20d";
local currentTime = GetTime();
local i;
local showThis;
local visibleTotal = 0;
--DMPrintD("start = "..start..", finish = "..finish..", quantity = "..reportQuantity);
if (count > 0) then
for i = start, finish, step do
local value;
msg = "";
if (reportQuantity == DamageMeters_ReportQuantity_Total) then
msg = string.format(formatStrTotalMain_A, DamageMeters_tables[tableIx][i].player,
DamageMeters_tables[tableIx][i].dmiData[DMI_1].q, DamageMeters_rankTables[tableIx][DamageMeters_tables[tableIx][i].player][1],
DamageMeters_tables[tableIx][i].dmiData[DMI_2].q, DamageMeters_rankTables[tableIx][DamageMeters_tables[tableIx][i].player][2],
DamageMeters_tables[tableIx][i].dmiData[DMI_3].q, DamageMeters_rankTables[tableIx][DamageMeters_tables[tableIx][i].player][3],
DamageMeters_tables[tableIx][i].dmiData[DMI_4].q, DamageMeters_rankTables[tableIx][DamageMeters_tables[tableIx][i].player][4],
DamageMeters_tables[tableIx][i].dmiData[DMI_DAMAGE].hitCount, DamageMeters_tables[tableIx][i].dmiData[DMI_DAMAGE].critCount);
elseif(reportQuantity == DamageMeters_ReportQuantity_Leaders) then
local leaders = {};
local leaderIndexes = {};
local qIx;
for qIx = 2, DMI_MAX do
local leaderName, rank;
for leaderName, rank in DamageMeters_rankTables[tableIx] do
--DMPrint(i.." "..leaderName.." "..rank[qIx]);
if (rank[qIx] == i) then
leaders[qIx] = leaderName;
leaderIndexes[qIx] = DamageMeters_GetPlayerIndex(leaderName);
break;
end
end
end
msg = string.format(formatStrTotalMain_B, i,
DamageMeters_tables[tableIx][i].dmiData[DMI_1].q, DamageMeters_tables[tableIx][i].player,
DamageMeters_tables[tableIx][leaderIndexes[2]].dmiData[DMI_2].q, leaders[2],
DamageMeters_tables[tableIx][leaderIndexes[3]].dmiData[DMI_3].q, leaders[3],
DamageMeters_tables[tableIx][leaderIndexes[4]].dmiData[DMI_4].q, leaders[4]);
elseif (reportQuantity == DamageMeters_ReportQuantity_Events) then
DamageMeters_DumpPlayerEvents(DamageMeters_tables[tableIx][i].player, destination, true, i, totals);
else
if (DamageMeters_Quantity_TIME == reportQuantity) then
local idleTime = currentTime - DamageMeters_tables[tableIx][i].lastTime;
msg = string.format("#%.2d: %-16s %d:%.02d", i, DamageMeters_tables[tableIx][i].player, idleTime / 60, math.mod(idleTime, 60));
else
local value = DamageMeters_GetQuantityValue(reportQuantity, tableIx, i);
-- 4/2/06: Removed this check. Was never necessary, and now that some quantitites can be
-- negative its detrimental.
--if (value > 0) then
visibleTotal = visibleTotal + value;
if (DamageMeters_IsQuantityPS(reportQuantity)) then
msg = string.format("#%.2d: %-16s %.1f", i, DamageMeters_tables[tableIx][i].player, value);
else
local percentage = (totalValue > 0) and (100 * value / totalValue) or 0;
msg = string.format("#%.2d: %.2f%% %-16s %d", i, percentage, DamageMeters_tables[tableIx][i].player, value);
end
--end
end
end
if (msg ~= "") then
DamageMeters_SendReportMsg(msg, destination, tellTarget);
end
end
end
------------
-- Totals --
------------
if (reportQuantity == DamageMeters_ReportQuantity_Total or
reportQuantity == DamageMeters_ReportQuantity_Leaders) then
if (reportQuantity == DamageMeters_ReportQuantity_Total) then
msg = string.format(formatStrTotalTotals, DM_MSG_TOTAL, totals[1], totals[2], totals[3], totals[4], totals[5], totals[6]);
else
msg = string.format(formatStrLeaderTotals, totals[1], totals[2], totals[3], totals[4], totals[5], totals[6]);
end
DamageMeters_SendReportMsg(msg, destination, tellTarget);
-- Print a list of contributors.
if (DamageMeters_flags[DMFLAG_haveContributors]) then
msg = string.format(DM_MSG_COLLECTORS, UnitName("Player"));
for contrib, unused in DamageMeters_contributorList do
msg = msg..", "..contrib;
end
DamageMeters_SendReportMsg(msg, destination, tellTarget);
end
elseif (DamageMeters_Quantity_DPS == reportQuantity) then
msg = string.format(DM_MSG_COMBATDURATION, DamageMeters_combatEndTime - DamageMeters_combatStartTime);
DamageMeters_SendReportMsg(msg, destination, tellTarget);
end
if (reportQuantity > 0) then
if (DamageMeters_Quantity_TIME == reportQuantity) then
-- No total.
elseif (DamageMeters_Quantity_DPS == reportQuantity) then
msg = string.format(DM_MSG_REPORTTOTALDPS, totalValue, visibleTotal);
DamageMeters_SendReportMsg(msg, destination, tellTarget);
else
msg = string.format(DM_MSG_REPORTTOTAL, totalValue, visibleTotal);
DamageMeters_SendReportMsg(msg, destination, tellTarget);
end
end
end
function DamageMeters_DumpPlayerEvents(player, destination, bIncludeName, index, totals, singleQuantity)
local tellTarget = nil;
local playerIndex = DamageMeters_GetPlayerIndex(player, DMT_VISIBLE);
--[[ removed when changed event system
local playerEventStruct = DamageMeters_tables[DMT_VISIBLE][playerIndex].events;
if (nil == playerEventStruct) then
-- Makes spam.
--DMPrintD("Player "..player.." not found.", nil, true);
return;
end
]]--
local prefix = "";
if (bIncludeName) then
if (index) then
str = index..": "..player..":";
else
str = player..":";
end
prefix = " ";
DamageMeters_SendReportMsg(str, destination, tellTarget);
end
if (totals == nil) then
totals = {};
local ii;
for ii = 1, table.getn(DamageMeters_tables[DMT_VISIBLE]) do
local q;
for q = 1, DMI_MAX do
if (totals[q] == nil) then
totals[q] = 0;
end
totals[q] = totals[q] + DamageMeters_tables[DMT_VISIBLE][ii].dmiData[q].q;
end
end
end
--[[ Remove firstMsg functionality. Pounds the GC.
if (DamageMeters_debugEnabled) then
if (playerIndex and DamageMeters_tables[DMT_VISIBLE][playerIndex].firstMsg and DamageMeters_tables[DMT_VISIBLE][playerIndex].firstMsg["event"]) then
local msg = "Last message: "..DamageMeters_tables[DMT_VISIBLE][playerIndex].firstMsg.event.." ("..DamageMeters_tables[DMT_VISIBLE][playerIndex].firstMsg.desc..")";
DamageMeters_SendReportMsg(msg, destination, tellTarget);
msg = " "..DamageMeters_tables[DMT_VISIBLE][playerIndex].firstMsg.fullMsg.."\n";
DamageMeters_SendReportMsg(msg, destination, tellTarget);
end
end
]]--
local headerDest = destination;
if (headerDest == "TOOLTIP") then
headerDest = "TOOLTIP_TITLE";
end
local dmi, eventStruct;
if (singleQuantity) then
dmi = DM_QUANTDEFS[singleQuantity].dmi;
if (dmi) then
eventStruct = DamageMeters_tables[DMT_VISIBLE][playerIndex].dmiData[dmi].events;
if (eventStruct) then
DamageMeters_DumpQuantityEvents(player, dmi, eventStruct, totals, headerDest, destination, tellTarget, prefix);
end
end
else
for dmi = 1, DMI_MAX do
eventStruct = DamageMeters_tables[DMT_VISIBLE][playerIndex].dmiData[dmi].events;
if (eventStruct) then
DamageMeters_DumpQuantityEvents(player, dmi, eventStruct, totals, headerDest, destination, tellTarget, prefix);
end
end
end
DamageMeters_SendReportMsg("", destination, tellTarget);
end
function DamageMeters_DumpQuantityEvents(player, dmi, eventStruct, totals, headerDest, destination, tellTarget, prefix)
if (eventStruct == nil) then
return;
end
-- Calculate total.
local total = 0;
for spell, spellStruct in eventStruct.spellTable do
-- Spells with "*" at the end are duplicates, and are not to be counted towards the total.
if (string.sub(spell, -1) ~= "*") then
total = total + spellStruct.value;
end
end
local percentageOfTotal = (totals[dmi] > 0) and (100 * total / totals[dmi]) or (0);
local rank = (DamageMeters_rankTables[DMT_ACTIVE][player] and DamageMeters_rankTables[DMT_ACTIVE][player][dmi]) and " #"..tostring(DamageMeters_rankTables[DMT_ACTIVE][player][dmi]) or "";
str = string.format("%s = %s (%.1f%%)%s", prefix..DMI_NAMES[dmi], total, percentageOfTotal, rank);
DamageMeters_SendReportMsg(str, headerDest, tellTarget);
-- Cannot sort spells, as that table is indexed by string.
if (eventStruct.dirty) then
DamageMeters_BuildSpellHash(eventStruct);
end
-- Print
for hashIndex = 1, table.getn(eventStruct.hash) do
local spell = eventStruct.hash[hashIndex].spell;
spellStruct = eventStruct.spellTable[spell];
--DMPrint("Hash "..hashIndex.." = "..spell);
local percentageOfTotal = (total > 0) and (100 * spellStruct.value / total) or (0);
local critPercentage = (spellStruct.counts[DM_HIT] > 0) and (100 * spellStruct.counts[DM_CRT] / spellStruct.counts[DM_HIT]) or 0.0;
local average = string.format("%.1f Avg", (spellStruct.counts[DM_HIT] and spellStruct.value / spellStruct.counts[DM_HIT] or 0));
str = string.format(prefix.." %s = %d (%.1f%%) %d/%d %.1f%% %s", spell, spellStruct.value, percentageOfTotal, spellStruct.counts[DM_CRT], spellStruct.counts[DM_HIT], critPercentage, average);
-- Show resistance info.
if (dmi == DMI_DAMAGED and
(spellStruct.damageType <= DM_DMGTYPE_RESISTMAX or spellStruct.resistanceSum > 0)) then
local avgResist = spellStruct.resistanceSum / spellStruct.resistanceCount;
str = string.format("%s (%d %s)", str, avgResist, DM_DMGTYPENAMES[spellStruct.damageType]);
end
DamageMeters_SendReportMsg(str, destination, tellTarget);
end
end
function DamageMeters_BuildSpellHash(eventStruct)
if (DM_Bypass["BuildSpellHash"] == true) then
return;
end
if (nil == eventStruct.hash) then
eventStruct.hash = {};
end
local hashIndex = 1;
for spell, spellStruct in eventStruct.spellTable do
eventStruct.hash[hashIndex] = {};
eventStruct.hash[hashIndex].spell = spell;
eventStruct.hash[hashIndex].value = spellStruct.value;
hashIndex = hashIndex + 1;
end
table.sort(eventStruct.hash,
function(a,b)
return a.value > b.value;
end
);
eventStruct.dirty = false;
end
Generated by GNU Enscript 1.6.5.90.