diff --git a/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.lua b/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.lua index d0ad708..933d809 100644 --- a/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.lua +++ b/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.lua @@ -1,7 +1,7 @@ if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then return end local major = "LibHealComm-4.0" -local minor = 92 +local minor = 99 assert(LibStub, format("%s requires LibStub.", major)) local HealComm = LibStub:NewLibrary(major, minor) @@ -75,18 +75,18 @@ local COMBATLOG_OBJECT_AFFILIATION_MINE = COMBATLOG_OBJECT_AFFILIATION_MINE local isTBC = WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC local spellRankTableData = { - [1] = { 774, 8936, 5185, 740, 635, 19750, 139, 2060, 596, 2061, 2054, 2050, 1064, 331, 8004, 136, 755, 689, 746, 33763, 32546 }, + [1] = { 774, 8936, 5185, 740, 635, 19750, 139, 2060, 596, 2061, 2054, 2050, 1064, 331, 8004, 136, 755, 689, 746, 33763, 32546, 37563 }, [2] = { 1058, 8938, 5186, 8918, 639, 19939, 6074, 10963, 996, 9472, 2055, 2052, 10622, 332, 8008, 3111, 3698, 699, 1159 }, [3] = { 1430, 8939, 5187, 9862, 647, 19940, 6075, 10964, 10960, 9473, 6063, 2053, 10623, 547, 8010, 3661, 3699, 709, 3267 }, [4] = { 2090, 8940, 5188, 9863, 1026, 19941, 6076, 10965, 10961, 9474, 6064, 913, 10466, 3662, 3700, 7651, 3268, 25422 }, [5] = { 2091, 8941, 5189, 1042, 19942, 6077, 22009, 25314, 25316, 10915, 939, 10467, 13542, 11693, 11699, 7926, 25423, 26983 }, [6] = { 3627, 9750, 6778, 3472, 19943, 6078, 10916, 959, 10468, 13543, 11694, 11700, 7927, 23569, 24412, 25210, 25308 }, [7] = { 8910, 9856, 8903, 10328, 10927, 10917, 8005, 13544, 11695, 10838, 27137, 25213, 25420, 27219 }, - [8] = { 9839, 9857, 9758, 10329, 10928, 10395, 10839, 23568, 24413, 25233, 27259, 27220 }, + [8] = { 9839, 9857, 9758, 10329, 10928, 10395, 10839, 23568, 24413, 25233, 27259, 27220, 27046 }, [9] = { 9840, 9858, 9888, 25292, 10929, 10396, 18608, 25235 }, [10] = { 9841, 9889, 25315, 25357, 18610, 23567, 24414, 26980, 27135 }, - [11] = { 25299, 25297, 30020, 27136, 25221, 25391 }, - [12] = { 26981, 26978, 25222, 25396 }, + [11] = { 25299, 25297, 30020, 27136, 25221, 25391, 27030 }, + [12] = { 26981, 26978, 25222, 25396, 27031 }, [13] = { 26982, 26979 }, } @@ -107,8 +107,9 @@ local BOMB_HEALS = 0x10 local ALL_HEALS = bit.bor(DIRECT_HEALS, CHANNEL_HEALS, HOT_HEALS, BOMB_HEALS) local CASTED_HEALS = bit.bor(DIRECT_HEALS, CHANNEL_HEALS) local OVERTIME_HEALS = bit.bor(HOT_HEALS, CHANNEL_HEALS) +local OVERTIME_AND_BOMB_HEALS = bit.bor(HOT_HEALS, CHANNEL_HEALS, BOMB_HEALS) -HealComm.ALL_HEALS, HealComm.CHANNEL_HEALS, HealComm.DIRECT_HEALS, HealComm.HOT_HEALS, HealComm.CASTED_HEALS, HealComm.ABSORB_SHIELDS, HealComm.ALL_DATA, HealComm.BOMB_HEALS = ALL_HEALS, CHANNEL_HEALS, DIRECT_HEALS, HOT_HEALS, CASTED_HEALS, ABSORB_SHIELDS, ALL_DATA, BOMB_HEALS +HealComm.ALL_HEALS, HealComm.OVERTIME_HEALS, HealComm.OVERTIME_AND_BOMB_HEALS, HealComm.CHANNEL_HEALS, HealComm.DIRECT_HEALS, HealComm.HOT_HEALS, HealComm.CASTED_HEALS, HealComm.ABSORB_SHIELDS, HealComm.ALL_DATA, HealComm.BOMB_HEALS = ALL_HEALS, OVERTIME_HEALS, OVERTIME_AND_BOMB_HEALS, CHANNEL_HEALS, DIRECT_HEALS, HOT_HEALS, CASTED_HEALS, ABSORB_SHIELDS, ALL_DATA, BOMB_HEALS local playerGUID, playerName, playerLevel local playerHealModifier = 1 @@ -126,7 +127,6 @@ HealComm.pendingHots = HealComm.pendingHots or {} HealComm.spellData = HealComm.spellData or {} HealComm.talentData = HealComm.talentData or {} HealComm.tempPlayerList = HealComm.tempPlayerList or {} -HealComm.spellDesc = HealComm.spellDesc or {} if( not HealComm.unitToPet ) then HealComm.unitToPet = {["player"] = "pet"} @@ -134,44 +134,10 @@ if( not HealComm.unitToPet ) then for i = 1, MAX_RAID_MEMBERS do HealComm.unitToPet["raid" .. i] = "raidpet" .. i end end -local spellDesc, spellData, hotData, tempPlayerList, pendingHeals, pendingHots = HealComm.spellDesc, HealComm.spellData, HealComm.hotData, HealComm.tempPlayerList, HealComm.pendingHeals, HealComm.pendingHots +local spellData, hotData, tempPlayerList, pendingHeals, pendingHots = HealComm.spellData, HealComm.hotData, HealComm.tempPlayerList, HealComm.pendingHeals, HealComm.pendingHots local equippedSetCache, itemSetsData, talentData = HealComm.equippedSetCache, HealComm.itemSetsData, HealComm.talentData local activeHots, activePets = HealComm.activeHots, HealComm.activePets ---[[Added to try ID indexing for spell data access -spellDesc: spell description table in format used by hotData previously -hotData: index table to bound all spell IDs to their descriptions -[spell id] = [spell description in spellDesc table] ---]] - ---Function to set all entries of table T to specified Value -local function Set (Value, T) - local set = {} - for _, l in ipairs(T) do - set[l] = Value - end - return set -end - ---Function to append content of table T2 at the end of table T1 -local function TableAppend(T1, T2) - for i,v in pairs(T2) do - table.insert(T1, i, v) - end -end - ---[[ -Function to add new spell to hot table -Data: spell description table -IDs: list of id for each rank of the spell ---]] -local function AddHot(Data, IDs) - table.insert(spellDesc, Data) - local idTable = Set(Data, IDs) - TableAppend(hotData, idTable) -end ---end - -- Figure out what they are now since a few things change based off of this local playerClass = select(2, UnitClass("player")) @@ -194,7 +160,7 @@ if( not HealComm.compressGUID ) then end rawset(tbl, guid, str) return str - end}) + end}) HealComm.decompressGUID = setmetatable({}, { __index = function(tbl, str) @@ -212,7 +178,7 @@ if( not HealComm.compressGUID ) then rawset(tbl, str, guid) return guid - end}) + end}) end local compressGUID, decompressGUID = HealComm.compressGUID, HealComm.decompressGUID @@ -457,7 +423,7 @@ function HealComm:GetNextHealAmount(guid, bitFlag, time, ignoreGUID, srcGUID) healFrom = casterGUID end - -- Channeled heals and hots, have to figure out how many times it'll tick within the given time band + -- Channeled heals and hots, have to figure out how many times it'll tick within the given time band elseif( ( pending.bitType == CHANNEL_HEALS or pending.bitType == HOT_HEALS ) ) then local secondsLeft = time and time - currentTime or endTime - currentTime local nextTick = currentTime + (secondsLeft % pending.tickInterval) @@ -733,6 +699,10 @@ end local function calculateGeneralAmount(level, amount, spellPower, spModifier, healModifier) local penalty = level > 20 and 1 or (1 - ((20 - level) * 0.0375)) + if isTBC then + -- TBC added another downrank penalty + penalty = penalty * min(1, (level + 11) / playerLevel) + end spellPower = spellPower * penalty @@ -753,43 +723,46 @@ end --[[ What the different callbacks do: + AuraHandler: Specific aura tracking needed for this class, who has Beacon up on them and such + ResetChargeData: Due to spell "queuing" you can't always rely on aura data for buffs that last one or two casts, for example Divine Favor (+100% crit, one spell) if you cast Holy Light and queue Flash of Light the library would still see they have Divine Favor and give them crits on both spells. The reset means that the flag that indicates they have the aura can be killed and if they interrupt the cast then it will call this and let you reset the flags. + What happens in terms of what the client thinks and what actually is, is something like this: + UNIT_SPELLCAST_START, Holy Light -> Divine Favor up UNIT_SPELLCAST_SUCCEEDED, Holy Light -> Divine Favor up (But it was really used) UNIT_SPELLCAST_START, Flash of Light -> Divine Favor up (It's not actually up but auras didn't update) UNIT_AURA -> Divine Favor up (Split second where it still thinks it's up) UNIT_AURA -> Divine Favor faded (Client catches up and realizes it's down) + CalculateHealing: Calculates the healing value, does all the formula calculations talent modifiers and such + CalculateHotHealing: Used specifically for calculating the heals of hots + GetHealTargets: Who the heal is going to hit, used for setting extra targets for Beacon of Light + Paladin heal or Prayer of Healing. The returns should either be: + "compressedGUID1,compressedGUID2,compressedGUID3,compressedGUID4", healthAmount Or if you need to set specific healing values for one GUID it should be "compressedGUID1,healthAmount1,compressedGUID2,healAmount2,compressedGUID3,healAmount3", -1 + The latter is for cases like Glyph of Healing Wave where you need a heal for 1,000 on A and a heal for 200 on the player for B without sending 2 events. The -1 tells the library to look in the GUId list for the heal amounts + **NOTE** Any GUID returned from GetHealTargets must be compressed through a call to compressGUID[guid] ]] local CalculateHealing, GetHealTargets, AuraHandler, CalculateHotHealing, ResetChargeData, LoadClassData -local function getBaseHealAmount(spellData, spellName, spellRank) - spellData = spellData[spellName] - local average = spellData.averages[spellRank] - if type(average) == "number" then - return average +local function getBaseHealAmount(spellData, spellName, spellID, spellRank) + if spellID == 37563 then + spellData = spellData["37563"] + else + spellData = spellData[spellName] end - local requiresLevel = spellData.levels[spellRank] - return average[min(playerLevel - requiresLevel + 1, #average)] -end - ---Function copies functionality of getBaseHealAmount but uses spellID as an argument instead of spellName -local function getBaseHealAmountBYID(spellData, spellID, spellRank) - spellData = spellData[spellID] local average = spellData.averages[spellRank] if type(average) == "number" then return average @@ -811,16 +784,9 @@ if( playerClass == "DRUID" ) then local EmpoweredRejuv = GetSpellInfo(33886) or "EmpoweredRejuv" local EmpoweredTouch = GetSpellInfo(33879) or "EmpoweredTouch" - --Regrowth - local RegrowthHot = { interval = 3, ticks = 7, coeff = isTBC and 0.7 or 0.5, levels = { 12, 18, 24, 30, 36, 42, 48, 54, 60, 65 }, - averages = { 98, 175, 259, 343, 427, 546, 686, 861, 1064, 1274}} - AddHot(RegrowthHot, {8936, 8938, 8939, 8940, 8941, 9750, 9856, 9857, 9858, 26980}) - --Rejuvenation - AddHot({ interval = 3, levels = { 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 60, 63, 69 }, - averages = { 32, 56, 116, 180, 244, 304, 388, 488, 608, 756, 888, 932, 1060 }}, - {774, 1058, 1430, 2090, 2091, 3627, 8910, 9839, 9840, 9841, 25299, 26981, 26982}) - --Revewal - AddHot({interval = 1, ticks = 7, coeff = 0.52, dhCoeff = 0.34335, levels = {64}, averages = {273}, bomb = {600}}, {33763}) + hotData[Regrowth] = { interval = 3, ticks = 7, coeff = isTBC and 0.7 or 0.5, levels = { 12, 18, 24, 30, 36, 42, 48, 54, 60, 65 }, averages = { 98, 175, 259, 343, 427, 546, 686, 861, 1064, 1274 }} + hotData[Rejuvenation] = { interval = 3, levels = { 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 60, 63, 69 }, averages = { 32, 56, 116, 180, 244, 304, 388, 488, 608, 756, 888, 932, 1060 }} + hotData[Lifebloom] = {interval = 1, ticks = 7, coeff = 0.52, dhCoeff = 0.34335, levels = {64}, averages = {273}, bomb = {600}} spellData[HealingTouch] = { levels = {1, 8, 14, 20, 26, 32, 38, 44, 50, 56, 60, 62, 69}, averages = { {avg(37, 51), avg(37, 52), avg(38, 53), avg(39, 54), avg(40, 55)}, @@ -836,7 +802,7 @@ if( playerClass == "DRUID" ) then {avg(2267, 2677), avg(2274, 2685), avg(2281, 2692), avg(2288, 2699), avg(2296, 2707), avg(2303, 2714)}, {avg(2364, 2790), avg(2371, 2798), avg(2378, 2805), avg(2386, 2813), avg(2393, 2820), avg(2401, 2827)}, {avg(2707, 3197), avg(2715, 3206)} }} - spellData[Regrowth] = {coeff = 0.5 * (2 / 3.5) , levels = RegrowthHot.levels, averages = { + spellData[Regrowth] = {coeff = 0.5 * (2 / 3.5) , levels = hotData[Regrowth].levels, averages = { {avg(84, 98), avg(85, 100), avg(87, 102), avg(89, 104), avg(91, 106), avg(93, 107)}, {avg(164, 188), avg(166, 191), avg(169, 193), avg(171, 196), avg(174, 198), avg(176, 201)}, {avg(240, 274), avg(243, 278), avg(246, 281), avg(249, 284), avg(252, 287), avg(255, 290)}, @@ -895,10 +861,9 @@ if( playerClass == "DRUID" ) then -- Calculate hot heals CalculateHotHealing = function(guid, spellID) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local healAmount = getBaseHealAmountBYID(hotData, spellID, spellRank) + local healAmount = getBaseHealAmount(hotData, spellName, spellID, spellRank) local spellPower = GetSpellBonusHealing() - local healModifier = HealComm:GetHealModifier(guid) * playerHealModifier - local spModifier = 1 + local healModifier, spModifier = playerHealModifier, 1 local bombAmount, totalTicks -- Gift of Nature @@ -923,7 +888,7 @@ if( playerClass == "DRUID" ) then end local duration = 12 - local ticks = duration / hotData[spellID].interval + local ticks = duration / hotData[spellName].interval if( equippedSetCache["Stormrage"] >= 8 ) then healAmount = healAmount + (healAmount / ticks) -- Add Tick Amount Gained by Set. @@ -940,9 +905,9 @@ if( playerClass == "DRUID" ) then healAmount = healAmount + 15 end elseif( spellName == Regrowth ) then - spellPower = spellPower * hotData[spellID].coeff * (1 + talentData[EmpoweredRejuv].current) - spellPower = spellPower / hotData[spellID].ticks - healAmount = healAmount / hotData[spellID].ticks + spellPower = spellPower * hotData[spellName].coeff * (1 + talentData[EmpoweredRejuv].current) + spellPower = spellPower / hotData[spellName].ticks + healAmount = healAmount / hotData[spellName].ticks totalTicks = 7 @@ -955,36 +920,35 @@ if( playerClass == "DRUID" ) then bombSpellPower = bombSpellPower + bloomBombIdols[playerCurrentRelic] end - local bombSpell = bombSpellPower * hotData[spellID].dhCoeff * (1 + talentData[EmpoweredRejuv].current) - bombAmount = math.ceil(calculateGeneralAmount(hotData[spellID].levels[spellRank], hotData[spellID].bomb[spellRank], bombSpell, spModifier, healModifier)) + local bombSpell = bombSpellPower * hotData[spellName].dhCoeff * (1 + talentData[EmpoweredRejuv].current) + bombAmount = math.ceil(calculateGeneralAmount(hotData[spellName].levels[spellRank], hotData[spellName].bomb[spellRank], bombSpell, spModifier, healModifier)) -- Figure out the hot tick healing - spellPower = spellPower * (hotData[spellID].coeff * (1 + talentData[EmpoweredRejuv].current)) + spellPower = spellPower * (hotData[spellName].coeff * (1 + talentData[EmpoweredRejuv].current)) -- Idol of the Emerald Queen, +47 SP per tick if( playerCurrentRelic == 27886 ) then spellPower = spellPower + 47 end - spellPower = spellPower / hotData[spellID].ticks - healAmount = healAmount / hotData[spellID].ticks + spellPower = spellPower / hotData[spellName].ticks + healAmount = healAmount / hotData[spellName].ticks -- Figure out total ticks totalTicks = 7 end - healAmount = calculateGeneralAmount(hotData[spellID].levels[spellRank], healAmount, spellPower, spModifier, healModifier) + healAmount = calculateGeneralAmount(hotData[spellName].levels[spellRank], healAmount, spellPower, spModifier, healModifier) - return HOT_HEALS, ceil(healAmount), totalTicks, hotData[spellID].interval, bombAmount + return HOT_HEALS, ceil(healAmount), totalTicks, hotData[spellName].interval, bombAmount end -- Calcualte direct and channeled heals CalculateHealing = function(guid, spellID) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local healAmount = getBaseHealAmount(spellData, spellName, spellRank) + local healAmount = getBaseHealAmount(spellData, spellName, spellID, spellRank) local spellPower = GetSpellBonusHealing() - local healModifier = HealComm:GetHealModifier(guid) * playerHealModifier - local spModifier = 1 + local healModifier, spModifier = playerHealModifier, 1 -- Gift of Nature if isTBC then @@ -997,7 +961,7 @@ if( playerClass == "DRUID" ) then -- Regrowth if( spellName == Regrowth ) then spellPower = spellPower * spellData[spellName].coeff - -- Healing Touch + -- Healing Touch elseif( spellName == HealingTouch ) then healAmount = healAmount + (spellPower * talentData[EmpoweredTouch].current) @@ -1015,7 +979,7 @@ if( playerClass == "DRUID" ) then healModifier = healModifier + 0.05 end - -- Tranquility + -- Tranquility elseif( spellName == Tranquility ) then spellPower = spellPower * spellData[spellName].coeff * (1 + talentData[EmpoweredRejuv].current) spellPower = spellPower / spellData[spellName].ticks @@ -1113,10 +1077,9 @@ if( playerClass == "PALADIN" ) then CalculateHealing = function(guid, spellID, unit) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local healAmount = getBaseHealAmount(spellData, spellName, spellRank) + local healAmount = getBaseHealAmount(spellData, spellName, spellID, spellRank) local spellPower = GetSpellBonusHealing() - local healModifier = HealComm:GetHealModifier(guid) * playerHealModifier - local spModifier = 1 + local healModifier, spModifier = playerHealModifier, 1 if isTBC then healModifier = healModifier * (1 + talentData[HealingLight].current) @@ -1175,16 +1138,12 @@ if( playerClass == "PRIEST" ) then local CureDisease = GetSpellInfo(528) local BindingHeal = GetSpellInfo(32546) or "Binding Heal" local EmpoweredHealing = GetSpellInfo(33158) or "Empowered Healing" - local Renewal = GetSpellInfo(37563) or "Renewal" -- T4 bonus + local Renewal = GetSpellInfo(37563) and "37563" -- T4 bonus - --Renew - local RenewData = {coeff = 1, interval = 3, ticks = 5, levels = {8, 14, 20, 26, 32, 38, 44, 50, 56, 60, 65, 70}, averages = { + hotData[Renew] = {coeff = 1, interval = 3, ticks = 5, levels = {8, 14, 20, 26, 32, 38, 44, 50, 56, 60, 65, 70}, averages = { 45, 100, 175, 245, 315, 400, 510, 650, 810, 970, 1010, 1110 }} - AddHot(RenewData, {139, 6074, 6075, 6076, 6077, 6078, 10927, 10928, 10929, 25315, 25221, 25222}) - --GreaterHealHot - AddHot(RenewData, {22009}) - --Renewal - AddHot({coeff = 0, interval = 3, ticks = 3, levels = {70}, averages = {150}}, {37563}) + hotData[GreaterHealHot] = hotData[Renew] + hotData[Renewal] = {coeff = 0, interval = 3, ticks = 3, levels = {70}, averages = {150}} spellData[FlashHeal] = {coeff = 1.5 / 3.5, levels = {20, 26, 32, 38, 44, 50, 56, 61, 67}, averages = { {avg(193, 237), avg(194, 239), avg(196, 241), avg(198, 243), avg(200, 245), avg(202, 247)}, @@ -1259,10 +1218,9 @@ if( playerClass == "PRIEST" ) then CalculateHotHealing = function(guid, spellID) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local healAmount = getBaseHealAmountBYID(hotData, spellID, spellRank) + local healAmount = getBaseHealAmount(hotData, spellName, spellID, spellRank) local spellPower = GetSpellBonusHealing() - local healModifier = HealComm:GetHealModifier(guid) * playerHealModifier - local spModifier = 1 + local healModifier, spModifier = playerHealModifier, 1 local totalTicks if isTBC then @@ -1281,7 +1239,7 @@ if( playerClass == "PRIEST" ) then end local duration = 15 - local ticks = hotData[spellID].ticks + local ticks = hotData[spellName].ticks if( equippedSetCache["Oracle"] >= 5 or equippedSetCache["Avatar"] >= 4 ) then healAmount = healAmount + (healAmount / ticks) -- Add Tick Amount Gained by Set. @@ -1295,17 +1253,16 @@ if( playerClass == "PRIEST" ) then healAmount = healAmount / ticks end - healAmount = calculateGeneralAmount(hotData[spellID].levels[spellRank], healAmount, spellPower, spModifier, healModifier) - return HOT_HEALS, ceil(healAmount), totalTicks, hotData[spellID].interval + healAmount = calculateGeneralAmount(hotData[spellName].levels[spellRank], healAmount, spellPower, spModifier, healModifier) + return HOT_HEALS, ceil(healAmount), totalTicks, hotData[spellName].interval end -- If only every other class was as easy as Paladins CalculateHealing = function(guid, spellID) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local healAmount = getBaseHealAmount(spellData, spellName, spellRank) + local healAmount = getBaseHealAmount(spellData, spellName, spellID, spellRank) local spellPower = GetSpellBonusHealing() - local healModifier = HealComm:GetHealModifier(guid) * playerHealModifier - local spModifier = 1 + local healModifier, spModifier = playerHealModifier, 1 if isTBC then healModifier = healModifier * (1 + talentData[SpiritualHealing].current) @@ -1318,21 +1275,21 @@ if( playerClass == "PRIEST" ) then if( equippedSetCache["Absolution"] >= 4 ) then healModifier = healModifier * 1.05 end healAmount = healAmount + (spellPower * (talentData[EmpoweredHealing].current * 2)) spellPower = spellPower * spellData[spellName].coeff - -- Flash Heal + -- Flash Heal elseif( spellName == FlashHeal ) then healAmount = healAmount + (spellPower * talentData[EmpoweredHealing].current) spellPower = spellPower * spellData[spellName].coeff - -- Binding Heal + -- Binding Heal elseif( spellName == BindingHeal ) then healAmount = healAmount + (spellPower * talentData[EmpoweredHealing].current) spellPower = spellPower * spellData[spellName].coeff - -- Prayer of Healing + -- Prayer of Healing elseif( spellName == PrayerofHealing ) then spellPower = spellPower * spellData[spellName].coeff - -- Heal + -- Heal elseif( spellName == Heal ) then spellPower = spellPower * spellData[spellName].coeff - -- Lesser Heal + -- Lesser Heal elseif( spellName == LesserHeal ) then local castTime = spellRank >= 3 and 2.5 or spellRank == 2 and 2 or 1.5 spellPower = spellPower * (castTime / 3.5) @@ -1403,10 +1360,9 @@ if( playerClass == "SHAMAN" ) then -- If only every other class was as easy as Paladins CalculateHealing = function(guid, spellID, unit) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local healAmount = getBaseHealAmount(spellData, spellName, spellRank) + local healAmount = getBaseHealAmount(spellData, spellName, spellID, spellRank) local spellPower = GetSpellBonusHealing() - local healModifier = HealComm:GetHealModifier(guid) * playerHealModifier - local spModifier = 1 + local healModifier, spModifier = playerHealModifier, 1 if isTBC then healModifier = healModifier * (1 + talentData[Purification].current) @@ -1426,7 +1382,7 @@ if( playerClass == "SHAMAN" ) then healModifier = healModifier * (1 + talentData[ImpChainHeal].current) if playerCurrentRelic == 28523 then healAmount = healAmount + 87 end - -- Heaing Wave + -- Heaing Wave elseif( spellName == HealingWave ) then local hwStacks = select(3, unitHasAura(unit, 29203)) if( hwStacks ) then @@ -1440,7 +1396,7 @@ if( playerClass == "SHAMAN" ) then spellPower = spellPower * (castTime / 3.5) - -- Lesser Healing Wave + -- Lesser Healing Wave elseif( spellName == LesserHealingWave ) then spellPower = spellPower + (playerCurrentRelic and lhwTotems[playerCurrentRelic] or 0) spellPower = spellPower * spellData[spellName].coeff @@ -1463,7 +1419,11 @@ if( playerClass == "HUNTER" ) then LoadClassData = function() local MendPet = GetSpellInfo(136) - spellData[MendPet] = { interval = 1, levels = { 12, 20, 28, 36, 44, 52, 60 }, ticks = 5, averages = {100, 190, 340, 515, 710, 945, 1225 } } + if isTBC then + hotData[MendPet] = { interval = 3, levels = { 12, 20, 28, 36, 44, 52, 60, 68 }, ticks = 5, averages = {125, 250, 450, 700, 1000, 1400, 1825, 2375 } } + else + spellData[MendPet] = { interval = 1, levels = { 12, 20, 28, 36, 44, 52, 60 }, ticks = 5, averages = {100, 190, 340, 515, 710, 945, 1225 } } + end itemSetsData["Giantstalker"] = {16851, 16849, 16850, 16845, 16848, 16852, 16846, 16847} @@ -1471,13 +1431,22 @@ if( playerClass == "HUNTER" ) then return compressGUID[UnitGUID("pet")], healAmount end - CalculateHealing = function(guid, spellID) + CalculateHotHealing = function(guid, spellID) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local amount = getBaseHealAmount(spellData, spellName, spellRank) + local amount = getBaseHealAmount(hotData, spellName, spellID, spellRank) if( equippedSetCache["Giantstalker"] >= 3 ) then amount = amount * 1.1 end - return CHANNEL_HEALS, ceil(amount / spellData[spellName].ticks), spellData[spellName].ticks, spellData[spellName].interval + return HOT_HEALS, ceil(amount / hotData[spellName].ticks), hotData[spellName].ticks, hotData[spellName].interval + end + + CalculateHealing = function(guid, spellID) + local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] + local healAmount = getBaseHealAmount(spellData, spellName, spellID, spellRank) + + if( equippedSetCache["Giantstalker"] >= 3 ) then healAmount = healAmount * 1.1 end + + return CHANNEL_HEALS, ceil(healAmount / spellData[spellName].ticks), spellData[spellName].ticks, spellData[spellName].interval end end end @@ -1499,11 +1468,11 @@ if( playerClass == "WARLOCK" ) then CalculateHealing = function(guid, spellID) local spellName, spellRank = GetSpellInfo(spellID), SpellIDToRank[spellID] - local amount = getBaseHealAmount(spellData, spellName, spellRank) + local healAmount = getBaseHealAmount(spellData, spellName, spellID, spellRank) - amount = amount * (1 + talentData[ImpHealthFunnel].current) + healAmount = healAmount * (1 + talentData[ImpHealthFunnel].current) - return CHANNEL_HEALS, ceil(amount / spellData[spellName].ticks), spellData[spellName].ticks, spellData[spellName].interval + return CHANNEL_HEALS, ceil(healAmount / spellData[spellName].ticks), spellData[spellName].ticks, spellData[spellName].interval end end end @@ -1519,6 +1488,8 @@ HealComm.currentModifiers = HealComm.currentModifiers or {} -- The only spell in the game with a name conflict is Ray of Pain from the Nagrand Void Walkers HealComm.healingModifiers = HealComm.healingModifiers or { [28776] = 0.10, -- Necrotic Poison + [36693] = 0.55, -- Necrotic Poison + [46296] = 0.25, -- Necrotic Poison [19716] = 0.25, -- Gehennas' Curse [13737] = 0.50, -- Mortal Strike [15708] = 0.50, -- Mortal Strike @@ -1526,12 +1497,58 @@ HealComm.healingModifiers = HealComm.healingModifiers or { [17547] = 0.50, -- Mortal Strike [19643] = 0.50, -- Mortal Strike [24573] = 0.50, -- Mortal Strike + [27580] = 0.50, -- Mortal Strike + [29572] = 0.50, -- Mortal Strike + [31911] = 0.50, -- Mortal Strike + [32736] = 0.50, -- Mortal Strike + [35054] = 0.50, -- Mortal Strike + [37335] = 0.50, -- Mortal Strike + [39171] = 0.50, -- Mortal Strike + [40220] = 0.50, -- Mortal Strike + [44268] = 0.50, -- Mortal Strike [12294] = 0.50, -- Mortal Strike (Rank 1) [21551] = 0.50, -- Mortal Strike (Rank 2) [21552] = 0.50, -- Mortal Strike (Rank 3) [21553] = 0.50, -- Mortal Strike (Rank 4) + [25248] = 0.50, -- Mortal Strike (Rank 5) + [30330] = 0.50, -- Mortal Strike (Rank 6) + [43441] = 0.50, -- Mortal Strike + [30843] = 0.00, -- Enfeeble + [19434] = 0.50, -- Aimed Shot (Rank 1) + [20900] = 0.50, -- Aimed Shot (Rank 2) + [20901] = 0.50, -- Aimed Shot (Rank 3) + [20902] = 0.50, -- Aimed Shot (Rank 4) + [20903] = 0.50, -- Aimed Shot (Rank 5) + [20904] = 0.50, -- Aimed Shot (Rank 6) + [27065] = 0.50, -- Aimed Shot (Rank 7) + [34625] = 0.25, -- Demolish + [35189] = 0.50, -- Solar Strike + [32315] = 0.50, -- Soul Strike + [32378] = 0.50, -- Filet + [36917] = 0.50, -- Magma-Thrower's Curse + [44534] = 0.50, -- Wretched Strike + [34366] = 0.75, -- Ebon Poison + [36023] = 0.50, -- Deathblow + [36054] = 0.50, -- Deathblow + [45885] = 0.50, -- Shadow Spike + [41292] = 0.00, -- Aura of Suffering + [40599] = 0.50, -- Arcing Smash + [9035] = 0.80, -- Hex of Weakness (Rank 1) + [19281] = 0.80, -- Hex of Weakness (Rank 2) + [19282] = 0.80, -- Hex of Weakness (Rank 3) + [19283] = 0.80, -- Hex of Weakness (Rank 4) + [19284] = 0.80, -- Hex of Weakness (Rank 5) + [25470] = 0.80, -- Hex of Weakness (Rank 6) + [34073] = 0.85, -- Curse of the Bleeding Hollow + [31306] = 0.25, -- Carrion Swarm + [44475] = 0.25, -- Magic Dampening Field [23169] = 0.50, -- Brood Affliction: Green [22859] = 0.50, -- Mortal Cleave + [38572] = 0.50, -- Mortal Cleave + [39595] = 0.50, -- Mortal Cleave + [45996] = 0.00, -- Darkness + [41350] = 2.00, -- Aura of Desire + [28176] = 1.20, -- Fel Armor [7068] = 0.25, -- Veil of Shadow [17820] = 0.25, -- Veil of Shadow [22687] = 0.25, -- Veil of Shadow @@ -1540,14 +1557,33 @@ HealComm.healingModifiers = HealComm.healingModifiers or { [28440] = 0.25, -- Veil of Shadow [13583] = 0.50, -- Curse of the Deadwood [23230] = 0.50, -- Blood Fury + [31977] = 1.50, -- Curse of Infinity } HealComm.healingStackMods = HealComm.healingStackMods or { -- Mortal Wound [25646] = function(stacks) return 1 - stacks * 0.10 end, [28467] = function(stacks) return 1 - stacks * 0.10 end, + [30641] = function(stacks) return 1 - stacks * 0.05 end, + [31464] = function(stacks) return 1 - stacks * 0.10 end, + [36814] = function(stacks) return 1 - stacks * 0.10 end, + [38770] = function(stacks) return 1 - stacks * 0.05 end, + -- Dark Touched + [45347] = function(stacks) return 1 - stacks * 0.05 end, + -- Nether Portal - Dominance + [30423] = function(stacks) return 1 - stacks * 0.01 end, + -- Focused Will + [45242] = function(stacks) return 1 + stacks * 0.10 end, } +if isTBC then + HealComm.healingStackMods[13218] = function(stacks) return 1 - stacks * 0.10 end -- Wound Poison (Rank 1) + HealComm.healingStackMods[13222] = function(stacks) return 1 - stacks * 0.10 end -- Wound Poison (Rank 2) + HealComm.healingStackMods[13223] = function(stacks) return 1 - stacks * 0.10 end -- Wound Poison (Rank 3) + HealComm.healingStackMods[13224] = function(stacks) return 1 - stacks * 0.10 end -- Wound Poison (Rank 4) + HealComm.healingStackMods[27189] = function(stacks) return 1 - stacks * 0.10 end -- Wound Poison (Rank 5) +end + local healingStackMods = HealComm.healingStackMods local healingModifiers, currentModifiers = HealComm.healingModifiers, HealComm.currentModifiers @@ -1564,7 +1600,7 @@ end -- Keep track of where all the data should be going local instanceType local function updateDistributionChannel() - if( instanceType == "pvp" ) then + if( instanceType == "pvp" or instanceType == "arena" ) then distribution = "INSTANCE_CHAT" elseif( IsInRaid() ) then distribution = "RAID" @@ -1659,6 +1695,35 @@ function HealComm:UNIT_AURA(unit) playerIncrease = playerIncrease * 1.20 end + local npsStacks = select(3, unitHasAura("player", 30422)) -- Nether Portal - Serenity + if npsStacks then + playerIncrease = playerIncrease * (1 + npsStacks * 0.05) + end + + if unitHasAura("player", 41406) then -- Dementia: +5% + playerIncrease = playerIncrease * 1.05 + end + + if unitHasAura("player", 41409) then -- Dementia: -5% + playerDecrease = playerDecrease * 0.95 + end + + if unitHasAura("player", 32346) then -- Stolen Soul + playerDecrease = playerDecrease * 0.50 + end + + if unitHasAura("player", 40099) then -- Vile Slime + playerDecrease = playerDecrease * 0.50 + end + + if unitHasAura("player", 38246) then -- Vile Sludge + playerDecrease = playerDecrease * 0.50 + end + + if unitHasAura("player", 45573) then -- Vile Sludge + playerDecrease = playerDecrease * 0.50 + end + playerHealModifier = playerIncrease * playerDecrease end @@ -1972,7 +2037,7 @@ local function parseHealDelayed(casterGUID, startTimeRelative, endTimeRelative, if( pending.bitType == DIRECT_HEALS ) then pending.startTime = startTime pending.endTime = endTime - -- Channel heal + -- Channel heal elseif( pending.bitType == CHANNEL_HEALS ) then pending.startTime = startTime pending.endTime = endTime @@ -1997,7 +2062,7 @@ end function HealComm:CHAT_MSG_ADDON(prefix, message, channel, sender) if( prefix ~= COMM_PREFIX or channel ~= distribution ) then return end - local commType, extraArg, spellID, arg1, arg2, arg3, arg4 = strsplit(":", message) + local commType, extraArg, spellID, arg1, arg2, arg3, arg4, arg5, arg6 = strsplit(":", message) local casterGUID = UnitGUID(Ambiguate(sender, "none")) spellID = tonumber(spellID) @@ -2006,24 +2071,24 @@ function HealComm:CHAT_MSG_ADDON(prefix, message, channel, sender) -- New direct heal - D:<extra>:<spellID>:<amount>:target1,target2... if( commType == "D" and arg1 and arg2 ) then parseDirectHeal(casterGUID, spellID, tonumber(arg1), tonumber(extraArg), strsplit(",", arg2)) - -- New channel heal - C:<extra>:<spellID>:<amount>:<totalTicks>:target1,target2... + -- New channel heal - C:<extra>:<spellID>:<amount>:<totalTicks>:target1,target2... elseif( commType == "C" and arg1 and arg3 ) then parseChannelHeal(casterGUID, spellID, tonumber(arg1), tonumber(arg2), strsplit(",", arg3)) - -- New hot with a "bomb" component - B:<totalTicks>:<spellID>:<bombAmount>:target1,target2:<amount>:<isMulti>:<tickInterval>:target1,target2... + -- New hot with a "bomb" component - B:<totalTicks>:<spellID>:<bombAmount>:target1,target2:<amount>:<isMulti>:<tickInterval>:target1,target2... elseif( commType == "B" and arg1 and arg6 ) then parseHotHeal(casterGUID, false, spellID, tonumber(arg3), tonumber(extraArg), tonumber(arg5), string.split(",", arg6)) parseHotBomb(casterGUID, false, spellID, tonumber(arg1), string.split(",", arg2)) - -- New hot - H:<totalTicks>:<spellID>:<amount>:<isMulti>:<tickInterval>:target1,target2... + -- New hot - H:<totalTicks>:<spellID>:<amount>:<isMulti>:<tickInterval>:target1,target2... elseif( commType == "H" and arg1 and arg4 ) then parseHotHeal(casterGUID, false, spellID, tonumber(arg1), tonumber(extraArg), tonumber(arg3), strsplit(",", arg4)) - -- New updated heal somehow before ending - U:<totalTicks>:<spellID>:<amount>:<tickInterval>:target1,target2... + -- New updated heal somehow before ending - U:<totalTicks>:<spellID>:<amount>:<tickInterval>:target1,target2... elseif( commType == "U" and arg1 and arg3 ) then parseHotHeal(casterGUID, true, spellID, tonumber(arg1), tonumber(extraArg), tonumber(arg2), strsplit(",", arg3)) - -- New updated bomb hot - UB:<totalTicks>:<spellID>:<bombAmount>:target1,target2:<amount>:<tickInterval>:target1,target2... - elseif( commtype == "UB" and arg1 and arg5 ) then + -- New updated bomb hot - UB:<totalTicks>:<spellID>:<bombAmount>:target1,target2:<amount>:<tickInterval>:target1,target2... + elseif( commType == "UB" and arg1 and arg5 ) then parseHotHeal(casterGUID, true, spellID, tonumber(arg3), tonumber(extraArg), tonumber(arg4), string.split(",", arg5)) parseHotBomb(casterGUID, true, spellID, tonumber(arg1), string.split(",", arg2)) - -- Heal stopped - S:<extra>:<spellID>:<ended early: 0/1>:target1,target2... + -- Heal stopped - S:<extra>:<spellID>:<ended early: 0/1>:target1,target2... elseif( commType == "S" or commType == "HS" ) then local interrupted = arg1 == "1" and true or false local checkType = commType == "HS" and "id" or "name" @@ -2058,7 +2123,7 @@ HealComm.bucketFrame:SetScript("OnUpdate", function(self, elapsed) -- This shouldn't happen, on the offhand chance it does then don't bother sending an event if( #(data) == 0 or not data.spellID or not data.spellName ) then wipe(data) - -- We're doing a bucket for a tick heal like Tranquility or Wild Growth + -- We're doing a bucket for a tick heal like Tranquility or Wild Growth elseif( data.type == "tick" ) then local pending = pendingHots[casterGUID] and pendingHots[casterGUID][data.spellName] if( pending and pending.bitType ) then @@ -2067,7 +2132,7 @@ HealComm.bucketFrame:SetScript("OnUpdate", function(self, elapsed) end wipe(data) - -- We're doing a bucket for a cast thats a multi-target heal like Wild Growth or Prayer of Healing + -- We're doing a bucket for a cast thats a multi-target heal like Wild Growth or Prayer of Healing elseif( data.type == "heal" ) then local bitType, amount, totalTicks, tickInterval, _ = CalculateHotHealing(data[1], data.spellID) if( bitType ) then @@ -2140,9 +2205,9 @@ function HealComm:COMBAT_LOG_EVENT_UNFILTERED(...) end end - -- New hot was applied + -- New hot was applied elseif( ( eventType == "SPELL_AURA_APPLIED" or eventType == "SPELL_AURA_REFRESH" or eventType == "SPELL_AURA_APPLIED_DOSE" ) and bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == COMBATLOG_OBJECT_AFFILIATION_MINE ) then - if( hotData[spellID] ) then + if( hotData[spellName] ) then -- Single target so we can just send it off now thankfully local bitType, amount, totalTicks, tickInterval, bombAmount = CalculateHotHealing(destGUID, spellID) if( bitType ) then @@ -2179,7 +2244,7 @@ function HealComm:COMBAT_LOG_EVENT_UNFILTERED(...) end end end - -- Single stack of a hot was removed, this only applies when going from 2 -> 1, when it goes from 1 -> 0 it fires SPELL_AURA_REMOVED + -- Single stack of a hot was removed, this only applies when going from 2 -> 1, when it goes from 1 -> 0 it fires SPELL_AURA_REMOVED elseif( eventType == "SPELL_AURA_REMOVED_DOSE" and bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == COMBATLOG_OBJECT_AFFILIATION_MINE ) then local pending = sourceGUID and pendingHeals[sourceGUID] and pendingHeals[sourceGUID][spellID] if( pending and pending.bitType ) then @@ -2202,12 +2267,12 @@ function HealComm:COMBAT_LOG_EVENT_UNFILTERED(...) sendMessage(string.format("U:%s:%d:%d:%d:%s", spellID, amount, pending.totalTicks, pending.tickInterval, compressGUID[destGUID])) end end - -- Aura faded + -- Aura faded elseif( eventType == "SPELL_AURA_REMOVED" and bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == COMBATLOG_OBJECT_AFFILIATION_MINE ) then if compressGUID[destGUID] then -- Hot faded that we cast local pending = pendingHots[playerGUID] and pendingHots[playerGUID][spellName] - if hotData[spellID] then + if hotData[spellName] then parseHealEnd(sourceGUID, pending, "id", spellID, false, compressGUID[destGUID]) sendMessage(format("HS::%d::%s", spellID, compressGUID[destGUID])) elseif spellData[spellName] and spellData[spellName]._isChanneled then @@ -2247,7 +2312,7 @@ function HealComm:UNIT_SPELLCAST_SENT(unit, targetName, castGUID, spellID) local spellName = GetSpellInfo(spellID) if(unit ~= "player") then return end - if hotData[spellID] or spellData[spellName] then + if hotData[spellName] or spellData[spellName] then targetName = targetName or UnitName("player") castTarget = gsub(targetName, "(.-)%-(.*)$", "%1") @@ -2283,7 +2348,7 @@ function HealComm:UNIT_SPELLCAST_START(unit, cast, spellID) local castGUID = castGUIDs[spellID] local castUnit = guidToUnit[castGUID] - if isTBC and not castUnit and spellID == 32546 and castGUID == UnitGUID("target") then + if isTBC and not castUnit and spellID == 32546 and castGUID == UnitGUID("target") then -- Binding Heal castGUID = UnitGUID("player") castUnit = "player" end @@ -2310,6 +2375,16 @@ end HealComm.UNIT_SPELLCAST_CHANNEL_START = HealComm.UNIT_SPELLCAST_START local spellCastSucceeded = {} +local function hasNS() + local i=1 + repeat + local spellID = select(10, UnitBuff("player", i)) + if spellID == 17116 or spellID == 16188 then + return true + end + i = i + 1 + until not spellID +end function HealComm:UNIT_SPELLCAST_SUCCEEDED(unit, cast, spellID) if( unit ~= "player") then return end @@ -2319,12 +2394,12 @@ function HealComm:UNIT_SPELLCAST_SUCCEEDED(unit, cast, spellID) hasDivineFavor = true end - if spellData[spellName] and not spellData[spellName]._isChanneled then + if spellData[spellName] and not spellData[spellName]._isChanneled and not hasNS() then hasDivineFavor = nil parseHealEnd(playerGUID, nil, "name", spellID, false) sendMessage(format("S::%d:0", spellID or 0)) spellCastSucceeded[spellID] = true - elseif spellID == 20473 or spellID == 20929 or spellID == 20930 then -- Holy Shock + elseif spellName == GetSpellInfo(20473) then -- Holy Shock hasDivineFavor = nil end end @@ -2366,7 +2441,7 @@ function HealComm:UNIT_SPELLCAST_DELAYED(unit, castGUID, spellID) parseHealDelayed(casterGUID, startTimeRelative, endTimeRelative, spellID) sendMessage(format("F::%d:%.3f:%.3f", spellID, startTimeRelative, endTimeRelative)) end - -- Channel heal delayed + -- Channel heal delayed elseif( pendingHeals[casterGUID][spellName].bitType == CHANNEL_HEALS ) then local startTime, endTime = select(4, ChannelInfo()) if( startTime and endTime ) then @@ -2453,7 +2528,7 @@ function HealComm:CastSpell(arg, unit) -- If the spell is waiting for a target and it's a spell action button then we know that the GUID has to be mouseover or a key binding cast. if( unit and UnitCanAssist("player", unit) ) then setCastData(4, UnitName(unit), UnitGUID(unit)) - -- No unit, or it's a unit we can't assist + -- No unit, or it's a unit we can't assist elseif( not SpellIsTargeting() ) then if( UnitCanAssist("player", "target") ) then setCastData(4, UnitName("target"), UnitGUID("target")) @@ -2570,6 +2645,8 @@ function HealComm:UNIT_PET(unit) if activeGUID and activeGUID ~= petGUID then removeAllRecords(activeGUID) + rawset(self.compressGUID, activeGUID, nil) + rawset(self.decompressGUID, "p-"..strsub(UnitGUID(unit),8), nil) guidToUnit[activeGUID] = nil guidToGroup[activeGUID] = nil activePets[unit] = nil @@ -2643,7 +2720,6 @@ function HealComm:OnInitialize() wipe(hotData) wipe(itemSetsData) wipe(talentData) - wipe(spellDesc) -- Load all of the classes formulas and such if LoadClassData then @@ -2653,8 +2729,11 @@ function HealComm:OnInitialize() do local FirstAid = GetSpellInfo(746) - spellData[FirstAid] = { ticks = {6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 10}, interval = 1, averages = { - 66, 114, 161, 301, 400, 640, 800, 1104, 1360, 2000} } + spellData[FirstAid] = { + ticks = {6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8}, + interval = 1, + averages = {66, 114, 161, 301, 400, 640, 800, 1104, 1360, 2000, 2800, 3400} + } local _GetHealTargets = GetHealTargets @@ -2783,4 +2862,4 @@ if( not IsLoggedIn() ) then HealComm.eventFrame:RegisterEvent("PLAYER_LOGIN") else HealComm:PLAYER_LOGIN() -end \ No newline at end of file +end diff --git a/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.xml b/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.xml index 730fcb3..6342b2d 100644 --- a/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.xml +++ b/oUF/libs/LibHealComm-4.0/LibHealComm-4.0.xml @@ -2,4 +2,4 @@ ..\FrameXML\UI.xsd"> <Script file="ChatThrottleLib.lua"/> <Script file="LibHealComm-4.0.lua"/> -</Ui> \ No newline at end of file +</Ui>