Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Skada:AddLoadableModule("Damage", function(Skada, L)
- if Skada.db.profile.modulesBlocked.Damage then return end
- local mod = Skada:NewModule(L["Damage"])
- local dpsmod = Skada:NewModule(L["DPS"])
- local playermod = Skada:NewModule(L["Damage spell list"])
- local spellmod = Skada:NewModule(L["Damage spell details"])
- local damagedmod = Skada:NewModule(L["Damaged mobs"])
- local function getDPS(set, player)
- local totaltime = Skada:PlayerActiveTime(set, player)
- return player.damage / math.max(1,totaltime)
- end
- local function getRaidDPS(set)
- if set.time > 0 then
- return set.damage / math.max(1, set.time)
- else
- local endtime = set.endtime
- if not endtime then
- endtime = time()
- end
- return set.damage / math.max(1, endtime - set.starttime)
- end
- end
- local function log_damage(set, dmg)
- -- Get the player.
- local player = Skada:get_player(set, dmg.playerid, dmg.playername)
- if player then
- -- Subtract overkill
- -- local amount = math.max(0,dmg.amount - dmg.overkill)
- -- Or don't. Seems to be the way other meters do it.
- local amount = dmg.amount
- -- self:Print(player.name..": "..dmg.spellname.." for "..tostring(amount))
- -- Also add to set total damage.
- set.damage = set.damage + amount
- -- Add spell to player if it does not exist.
- if not player.damagespells[dmg.spellname] then
- player.damagespells[dmg.spellname] = {id = dmg.spellid, totalhits = 0, damage = 0}
- end
- -- Add to player total damage.
- player.damage = player.damage + amount
- -- Get the spell from player.
- local spell = player.damagespells[dmg.spellname]
- if not dmg.multistrike then
- spell.totalhits = spell.totalhits + 1
- if spell.max == nil or amount > spell.max then
- spell.max = amount
- end
- if (spell.min == nil or amount < spell.min) and not dmg.missed then
- spell.min = amount
- end
- end
- spell.damage = spell.damage + amount
- if dmg.multistrike then
- spell.multistrike = (spell.multistrike or 0) + 1
- elseif dmg.critical then
- spell.critical = (spell.critical or 0) + 1
- elseif dmg.missed ~= nil then
- spell[dmg.missed] = (spell[dmg.missed] or 0) + 1
- elseif dmg.glancing then
- spell.glancing = (spell.glancing or 0) + 1
- elseif dmg.crushing then
- spell.crushing = (spell.crushing or 0) + 1
- else
- spell.hit = (spell.hit or 0) + 1
- end
- -- For now, only save damaged info to current set.
- -- Saving this to Total may become a memory hog deluxe, and besides, it does not make much sense
- -- to see in Total. Why care which particular mob you damaged the most in a whole raid, for example?
- if set == Skada.current and dmg.dstname and amount > 0 then
- -- Make sure destination exists in player.
- if not player.damaged[dmg.dstname] then
- player.damaged[dmg.dstname] = 0
- end
- -- Add to destination.
- player.damaged[dmg.dstname] = player.damaged[dmg.dstname] + amount
- end
- end
- end
- local dmg = {}
- local function SpellDamage(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellId, spellName, spellSchool, samount, soverkill, sschool, sresisted, sblocked, sabsorbed, scritical, sglancing, scrushing, soffhand, smultistrike)
- -- Spell damage.
- if srcGUID ~= dstGUID then
- -- XXX WoD quick fix for Mage's Prismatic Crystal talent
- -- All damage done to the crystal is transferred, so ignore it
- -- Now with extra Legion "quick fix" for Warlock's Soul Effigy!
- if dstGUID:match("^Creature%-0%-%d+%-%d+%-%d+%-76933%-%w+$") or dstGUID:match("^Creature%-0%-%d+%-%d+%-%d+%-103679%-%w+$") then
- return
- end
- if spellId == 191259 or spellId == 190893 and srcFlags == 0x511 then
- srcGUID = UnitGUID("player")
- srcName = UnitName("player")
- end
- dmg.playerid = srcGUID
- dmg.playerflags = srcFlags
- dmg.dstname = dstName
- dmg.playername = srcName
- dmg.spellid = spellId
- dmg.spellname = spellName
- dmg.amount = samount
- dmg.overkill = soverkill
- dmg.resisted = sresisted
- dmg.blocked = sblocked
- dmg.absorbed = sabsorbed
- dmg.critical = scritical
- dmg.glancing = sglancing
- dmg.crushing = scrushing
- dmg.offhand = soffhand
- dmg.multistrike = smultistrike
- dmg.missed = nil
- Skada:FixPets(dmg)
- log_damage(Skada.current, dmg)
- log_damage(Skada.total, dmg)
- end
- end
- local function SwingDamage(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, samount, soverkill, sschool, sresisted, sblocked, sabsorbed, scritical, sglancing, scrushing, soffhand, smultistrike)
- -- White melee.
- if srcGUID ~= dstGUID then
- dmg.playerid = srcGUID
- dmg.playername = srcName
- dmg.playerflags = srcFlags
- dmg.dstname = dstName
- dmg.spellid = 6603
- dmg.spellname = L["Attack"]
- dmg.amount = samount
- dmg.overkill = soverkill
- dmg.resisted = sresisted
- dmg.blocked = sblocked
- dmg.absorbed = sabsorbed
- dmg.critical = scritical
- dmg.glancing = sglancing
- dmg.crushing = scrushing
- dmg.offhand = soffhand
- dmg.multistrike = smultistrike
- dmg.missed = nil
- Skada:FixPets(dmg)
- log_damage(Skada.current, dmg)
- log_damage(Skada.total, dmg)
- end
- end
- local function SpellAbsorbed(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
- local chk = ...
- local spellId, spellName, spellSchool, aGUID, aName, aFlags, aRaidFlags, aspellId, aspellName, aspellSchool, aAmount
- if type(chk) == "number" then
- -- Spell event
- spellId, spellName, spellSchool, aGUID, aName, aFlags, aRaidFlags, aspellId, aspellName, aspellSchool, aAmount = ...
- -- Exclude Spirit Shift damage
- if aspellId == 184553 then
- return
- end
- if aAmount then
- SpellDamage(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellId, spellName, spellSchool, aAmount)
- end
- else
- -- Swing event
- aGUID, aName, aFlags, aRaidFlags, aspellId, aspellName, aspellSchool, aAmount = ...
- -- Exclude Spirit Shift damage
- if aspellId == 184553 then
- return
- end
- if aAmount then
- SwingDamage(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, aAmount)
- end
- end
- end
- local function SwingMissed(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, missed)
- if srcGUID ~= dstGUID then
- -- Melee misses
- dmg.playerid = srcGUID
- dmg.playername = srcName
- dmg.playerflags = srcFlags
- dmg.dstname = dstName
- dmg.spellid = 6603
- dmg.spellname = L["Attack"]
- dmg.amount = 0
- dmg.overkill = 0
- dmg.resisted = nil
- dmg.blocked = nil
- dmg.absorbed = nil
- dmg.critical = nil
- dmg.glancing = nil
- dmg.crushing = nil
- dmg.offhand = nil
- dmg.multistrike = nil
- dmg.missed = missed
- Skada:FixPets(dmg)
- log_damage(Skada.current, dmg)
- log_damage(Skada.total, dmg)
- end
- end
- local function SpellMissed(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellId, spellName, spellSchool, missType)
- -- Misses
- if srcGUID ~= dstGUID then
- dmg.playerid = srcGUID
- dmg.playername = srcName
- dmg.playerflags = srcFlags
- dmg.dstname = dstName
- dmg.spellid = spellId
- dmg.spellname = spellName
- dmg.amount = 0
- dmg.overkill = 0
- dmg.resisted = nil
- dmg.blocked = nil
- dmg.absorbed = nil
- dmg.critical = nil
- dmg.glancing = nil
- dmg.crushing = nil
- dmg.offhand = nil
- dmg.multistrike = nil
- dmg.missed = missType
- Skada:FixPets(dmg)
- log_damage(Skada.current, dmg)
- log_damage(Skada.total, dmg)
- end
- end
- -- Damage overview.
- function mod:Update(win, set)
- -- Max value.
- local max = 0
- local nr = 1
- for i, player in ipairs(set.players) do
- if player.damage > 0 then
- local dps = getDPS(set, player)
- local d = win.dataset[nr] or {}
- win.dataset[nr] = d
- d.label = player.name
- d.valuetext = Skada:FormatValueText(
- Skada:FormatNumber(player.damage), self.metadata.columns.Damage,
- Skada:FormatNumber(dps), self.metadata.columns.DPS,
- string.format("%02.1f%%", player.damage / set.damage * 100), self.metadata.columns.Percent
- )
- d.value = player.damage
- d.id = player.id
- d.class = player.class
- d.role = player.role
- if player.damage > max then
- max = player.damage
- end
- nr = nr + 1
- end
- end
- win.metadata.maxvalue = max
- end
- -- Tooltip for a specific player.
- local function dps_tooltip(win, id, label, tooltip)
- local set = win:get_selected_set()
- local player = Skada:find_player(set, id)
- if player then
- local activetime = Skada:PlayerActiveTime(set, player)
- local totaltime = Skada:GetSetTime(set)
- tooltip:AddLine(player.name.." - "..L["DPS"])
- tooltip:AddDoubleLine(L["Segment time"], totaltime.."s", 255,255,255,255,255,255)
- tooltip:AddDoubleLine(L["Active time"], activetime.."s", 255,255,255,255,255,255)
- tooltip:AddDoubleLine(L["Damage done"], Skada:FormatNumber(player.damage), 255,255,255,255,255,255)
- tooltip:AddDoubleLine(Skada:FormatNumber(player.damage) .. " / " .. activetime .. ":", ("%02.1f"):format(player.damage / math.max(1,activetime)), 255,255,255,255,255,255)
- end
- end
- -- Tooltip for a specific player.
- local function player_tooltip(win, id, label, tooltip)
- local player = Skada:find_player(win:get_selected_set(), playermod.playerid)
- if player then
- local spell = player.damagespells[label]
- if spell then
- tooltip:AddLine(player.name.." - "..label)
- if spell.max and spell.min then
- tooltip:AddDoubleLine(L["Minimum hit:"], Skada:FormatNumber(spell.min), 255,255,255,255,255,255)
- tooltip:AddDoubleLine(L["Maximum hit:"], Skada:FormatNumber(spell.max), 255,255,255,255,255,255)
- end
- tooltip:AddDoubleLine(L["Average hit:"], Skada:FormatNumber(spell.damage / spell.totalhits), 255,255,255,255,255,255)
- end
- end
- end
- -- Tooltip for a specific player.
- -- This is a post-tooltip
- local function damage_tooltip(win, id, label, tooltip)
- local set = win:get_selected_set()
- local player = Skada:find_player(set, id)
- --ChatFrame4:AddMessage(("Set: %s, id: %s"):format(set, id))
- if player then
- local activetime = Skada:PlayerActiveTime(set, player)
- local totaltime = Skada:GetSetTime(set)
- tooltip:AddDoubleLine(L["Activity"], ("%02.1f%%"):format(activetime/math.max(1,totaltime)*100), 255,255,255,255,255,255)
- end
- end
- function playermod:Enter(win, id, label)
- local player = Skada:find_player(win:get_selected_set(), id)
- if player then
- playermod.playerid = id
- playermod.title = player.name..L["'s Damage"]
- end
- end
- -- Detail view of a player.
- function playermod:Update(win, set)
- -- View spells for this player.
- local player = Skada:find_player(set, self.playerid)
- local max = 0
- -- If we reset we have no data.
- if player then
- local nr = 1
- if player then
- for spellname, spell in pairs(player.damagespells) do
- local d = win.dataset[nr] or {}
- win.dataset[nr] = d
- d.label = spellname
- d.id = spellname
- local _, _, icon = GetSpellInfo(spell.id)
- d.icon = icon
- d.spellid = spell.id
- d.value = spell.damage
- d.valuetext = Skada:FormatValueText(
- Skada:FormatNumber(spell.damage), self.metadata.columns.Damage,
- string.format("%02.1f%%", spell.damage / player.damage * 100), self.metadata.columns.Percent
- )
- if spell.damage > max then
- max = spell.damage
- end
- nr = nr + 1
- end
- end
- end
- win.metadata.maxvalue = max
- end
- function damagedmod:Enter(win, id, label)
- local player = Skada:find_player(win:get_selected_set(), id)
- damagedmod.playerid = id
- damagedmod.title = (player and player.name or "Unknown")..L["'s "]..L["Damaged mobs"]
- end
- -- Player view showing damaged mobs.
- function damagedmod:Update(win, set)
- local player = Skada:find_player(set, self.playerid)
- local max = 0
- -- If we reset we have no data.
- if player then
- local nr = 1
- if player then
- for mob, amount in pairs(player.damaged) do
- local d = win.dataset[nr] or {}
- win.dataset[nr] = d
- d.label = mob
- d.id = mob
- d.value = amount
- d.valuetext = Skada:FormatValueText(
- Skada:FormatNumber(amount), self.metadata.columns.Damage,
- string.format("%02.1f%%", amount / player.damage * 100), self.metadata.columns.Percent
- )
- if amount > max then
- max = amount
- end
- nr = nr + 1
- end
- end
- end
- win.metadata.maxvalue = max
- end
- local function add_detail_bar(win, title, value)
- local nr = spellmod.nr + 1
- spellmod.nr = nr
- local d = win.dataset[nr] or {}
- win.dataset[nr] = d
- d.value = value
- d.label = title
- d.id = title
- d.valuetext = Skada:FormatValueText(
- value, mod.metadata.columns.Damage,
- string.format("%02.1f%%", value / spellmod.totalhits * 100), mod.metadata.columns.Percent
- )
- win.metadata.maxvalue = math.max(win.metadata.maxvalue, value)
- end
- function spellmod:Enter(win, id, label)
- local player = Skada:find_player(win:get_selected_set(), playermod.playerid)
- spellmod.spellname = label
- spellmod.title = player.name..L["'s "]..label
- end
- function spellmod:Update(win, set)
- local player = Skada:find_player(set,playermod.playerid)
- if player then
- local spell = player.damagespells[self.spellname]
- if spell then
- spellmod.totalhits = spell.totalhits
- spellmod.nr = 0
- win.metadata.maxvalue = 0
- if spell.hit and spell.hit > 0 then
- add_detail_bar(win, L["Hit"], spell.hit)
- end
- if spell.critical and spell.critical > 0 then
- add_detail_bar(win, L["Critical"], spell.critical)
- end
- if spell.multistrike and spell.multistrike > 0 then
- add_detail_bar(win, L["Multistrike"], spell.multistrike)
- end
- if spell.glancing and spell.glancing > 0 then
- add_detail_bar(win, L["Glancing"], spell.glancing)
- end
- if spell.crushing and spell.crushing > 0 then
- add_detail_bar(win, L["Crushing"], spell.crushing)
- end
- if spell.ABSORB and spell.ABSORB > 0 then
- add_detail_bar(win, L["Absorb"], spell.ABSORB)
- end
- if spell.BLOCK and spell.BLOCK > 0 then
- add_detail_bar(win, L["Block"], spell.BLOCK)
- end
- if spell.DEFLECT and spell.DEFLECT > 0 then
- add_detail_bar(win, L["Deflect"], spell.DEFLECT)
- end
- if spell.DODGE and spell.DODGE > 0 then
- add_detail_bar(win, L["Dodge"], spell.DODGE)
- end
- if spell.EVADE and spell.EVADE > 0 then
- add_detail_bar(win, L["Evade"], spell.EVADE)
- end
- if spell.IMMUNE and spell.IMMUNE > 0 then
- add_detail_bar(win, L["Immune"], spell.IMMUNE)
- end
- if spell.MISS and spell.MISS > 0 then
- add_detail_bar(win, L["Missed"], spell.MISS)
- end
- if spell.PARRY and spell.PARRY > 0 then
- add_detail_bar(win, L["Parry"], spell.PARRY)
- end
- if spell.REFLECT and spell.REFLECT > 0 then
- add_detail_bar(win, L["Reflect"], spell.REFLECT)
- end
- if spell.RESIST and spell.RESIST > 0 then
- add_detail_bar(win, L["Resist"], spell.RESIST)
- end
- end
- end
- end
- -- DPS-only view
- function dpsmod:GetSetSummary(set)
- return Skada:FormatNumber(getRaidDPS(set))
- end
- function dpsmod:Update(win, set)
- local max = 0
- local nr = 1
- for i, player in ipairs(set.players) do
- local dps = getDPS(set, player)
- if dps > 0 then
- local d = win.dataset[nr] or {}
- win.dataset[nr] = d
- d.label = player.name
- d.id = player.id
- d.value = dps
- d.class = player.class
- d.role = player.role
- d.valuetext = Skada:FormatNumber(dps)
- if dps > max then
- max = dps
- end
- nr = nr + 1
- end
- end
- win.metadata.maxvalue = max
- end
- function mod:OnEnable()
- dpsmod.metadata = {showspots = true, tooltip = dps_tooltip}
- playermod.metadata = {tooltip = player_tooltip, click1 = spellmod, columns = {Damage = true, Percent = true}}
- mod.metadata = {post_tooltip = damage_tooltip, showspots = true, click1 = playermod, click2 = damagedmod, columns = {Damage = true, DPS = true, Percent = true}}
- damagedmod.metadata = {columns = {Damage = true, Percent = true}}
- spellmod.metadata = {columns = {Damage = true, Percent = true}}
- Skada:RegisterForCL(SpellDamage, 'DAMAGE_SHIELD', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellDamage, 'SPELL_DAMAGE', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellAbsorbed, 'SPELL_ABSORBED', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellDamage, 'SPELL_PERIODIC_DAMAGE', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellDamage, 'SPELL_BUILDING_DAMAGE', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellDamage, 'RANGE_DAMAGE', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SwingDamage, 'SWING_DAMAGE', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SwingMissed, 'SWING_MISSED', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellMissed, 'SPELL_MISSED', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellMissed, 'SPELL_PERIODIC_MISSED', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellMissed, 'RANGE_MISSED', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:RegisterForCL(SpellMissed, 'SPELL_BUILDING_MISSED', {src_is_interesting = true, dst_is_not_interesting = true})
- Skada:AddFeed(L["Damage: Personal DPS"], function()
- if Skada.current then
- local player = Skada:find_player(Skada.current, UnitGUID("player"))
- if player then
- return Skada:FormatNumber(getDPS(Skada.current, player)).." "..L["DPS"]
- end
- end
- end)
- Skada:AddFeed(L["Damage: Raid DPS"], function()
- if Skada.current then
- return Skada:FormatNumber(getRaidDPS(Skada.current)).." "..L["RDPS"]
- end
- end)
- Skada:AddMode(self)
- end
- function mod:OnDisable()
- Skada:RemoveMode(self)
- Skada:RemoveFeed(L["Damage: Personal DPS"])
- Skada:RemoveFeed(L["Damage: Raid DPS"])
- end
- function dpsmod:OnEnable()
- Skada:AddMode(self)
- end
- function dpsmod:OnDisable()
- Skada:RemoveMode(self)
- end
- function mod:AddToTooltip(set, tooltip)
- GameTooltip:AddDoubleLine(L["DPS"], Skada:FormatNumber(getRaidDPS(set)), 1,1,1)
- end
- function mod:GetSetSummary(set)
- return Skada:FormatValueText(
- Skada:FormatNumber(set.damage), self.metadata.columns.Damage,
- Skada:FormatNumber(getRaidDPS(set)), self.metadata.columns.DPS
- )
- end
- -- Called by Skada when a new player is added to a set.
- function mod:AddPlayerAttributes(player)
- if not player.damage then
- player.damage = 0
- player.damagespells = {}
- end
- if not player.damaged then
- player.damaged = {}
- end
- end
- -- Called by Skada when a new set is created.
- function mod:AddSetAttributes(set)
- if not set.damage then
- set.damage = 0
- end
- end
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement