Skip to content

Instantly share code, notes, and snippets.

@JoeGannon
Last active August 18, 2019 09:43
Show Gist options
  • Save JoeGannon/288ac79a9edadd6b639c138f6320b865 to your computer and use it in GitHub Desktop.
Save JoeGannon/288ac79a9edadd6b639c138f6320b865 to your computer and use it in GitHub Desktop.
--[Extended Character Stats v1](https://www.curseforge.com/wow/addons/extended-character-stats)
--Client 11302
-- Empty variable for stats
local ECS_CHARACTER_STATS = nil;
-- Font for the header display
local headerFont = "GameFontNormal";
-- Font for the stat display
local statFont = "GameFontHighlightSmall";
-- Configure Frame
local ECS_STAT_PANE = CreateFrame("Frame", "ECS_StatsFrame", PaperDollItemsFrame, "BasicFrameTemplateWithInset");
ECS_STAT_PANE:SetSize(250, 420); -- Width, Height
ECS_STAT_PANE:SetPoint("RIGHT", PaperDollItemsFrame, "RIGHT", 225, 32) -- Point, relativeFrame, relativePoint, xOffset, yOffset
ECS_STAT_PANE.title = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY");
ECS_STAT_PANE.title:SetFontObject("GameFontHighlight");
ECS_STAT_PANE.title:SetPoint("CENTER", ECS_STAT_PANE.TitleBg, "CENTER", 5, 0);
ECS_STAT_PANE.title:SetText("Extended Character Stats");
-- Create Headers
ECS_STAT_PANE.SpellHeader = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", headerFont);
ECS_STAT_PANE.MeleeHeader = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", headerFont);
ECS_STAT_PANE.BaseHeader = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", headerFont);
ECS_STAT_PANE.RangedHeader = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", headerFont);
-- Create Stat Displays
ECS_STAT_PANE.SpellHit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.SpellCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.MeleeHit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.MeleeCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.DodgeChance = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.ParryChance = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.BlockChance = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.PowerRegen = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.RangedHit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.RangedCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.HolyDmg = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.HolyCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.BonusHealing = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.ShadowDmg = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.ShadowCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.NatureDmg = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.NatureCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.FrostDmg = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.FrostCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.FireDmg = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.FireCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.ArcaneDmg = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
ECS_STAT_PANE.ArcaneCrit = ECS_STAT_PANE:CreateFontString(nil, "OVERLAY", statFont);
-- Configure Event Frame
local ECS_EVENT_FRAME = CreateFrame("Frame", nil, UIParent);
-- Subscribe to events that will trigger an update
ECS_EVENT_FRAME:RegisterEvent("UNIT_AURA"); -- Triggers whenever the player gains or loses a buff/debuff
ECS_EVENT_FRAME:RegisterEvent("PLAYER_LEVEL_UP"); -- Triggers whenever the player levels up
ECS_EVENT_FRAME:RegisterEvent("PLAYER_ENTERING_WORLD"); -- Triggers whenever the player log in, zone in to a new zone or reloads the UI
ECS_EVENT_FRAME:RegisterEvent("PLAYER_EQUIPMENT_CHANGED"); -- Triggers whenever the player changes gear
ECS_EVENT_FRAME:RegisterEvent("UNIT_POWER_UPDATE"); -- Triggers whenever the player changes gear
-- Rounds every number down to 2 decimal places
local function Round(num)
mult = 10^(2);
return math.floor(num * mult + 0.5) / mult or 0;
end
-- Updates extra information about specific spell schools e.g Frost Damage/Crit
local function UpdateSpellBonus(class, yOffset)
if class == "Paladin" then
-- Holy DMG
ECS_STAT_PANE.HolyDmg:SetPoint("TOPLEFT", 20, yOffset - 15);
ECS_STAT_PANE.HolyDmg:SetText("Holy Bonus Damage: " .. ECS_CHARACTER_STATS.holyBonusDmg);
-- Holy Crit
ECS_STAT_PANE.HolyCrit:SetPoint("TOPLEFT", 20, yOffset -30);
ECS_STAT_PANE.HolyCrit:SetText("Holy Crit Chance: " .. ECS_CHARACTER_STATS.holyCrit);
-- Bonus Healing
ECS_STAT_PANE.BonusHealing:SetPoint("TOPLEFT", 20, yOffset -45);
ECS_STAT_PANE.BonusHealing:SetText("Bonus Healing: " .. ECS_CHARACTER_STATS.spellBonusHealing);
elseif class == "Priest" then
-- Holy DMG
ECS_STAT_PANE.HolyDmg:SetPoint("TOPLEFT", 20, yOffset - 15);
ECS_STAT_PANE.HolyDmg:SetText("Holy Bonus Damage: " .. ECS_CHARACTER_STATS.holyBonusDmg);
-- Holy Crit
ECS_STAT_PANE.HolyCrit:SetPoint("TOPLEFT", 20, yOffset -30);
ECS_STAT_PANE.HolyCrit:SetText("Holy Crit Chance: " .. ECS_CHARACTER_STATS.holyCrit);
-- Shadow DMG
ECS_STAT_PANE.ShadowDmg:SetPoint("TOPLEFT", 20, yOffset - 45);
ECS_STAT_PANE.ShadowDmg:SetText("Shadow Bonus Damage: " .. ECS_CHARACTER_STATS.shadowBonusDmg);
-- Shadow Crit
ECS_STAT_PANE.ShadowCrit:SetPoint("TOPLEFT", 20, yOffset -60);
ECS_STAT_PANE.ShadowCrit:SetText("Shadow Crit Chance: " .. ECS_CHARACTER_STATS.shadowCrit);
-- Bonus Healing
ECS_STAT_PANE.BonusHealing:SetPoint("TOPLEFT", 20, yOffset -75);
ECS_STAT_PANE.BonusHealing:SetText("Bonus Healing: " .. ECS_CHARACTER_STATS.spellBonusHealing);
elseif class == "Shaman" then
-- Nature DMG
ECS_STAT_PANE.NatureDmg:SetPoint("TOPLEFT", 20, yOffset -15);
ECS_STAT_PANE.NatureDmg:SetText("Nature Bonus Damage: " .. ECS_CHARACTER_STATS.natureBonusDmg);
-- Nature Crit
ECS_STAT_PANE.NatureCrit:SetPoint("TOPLEFT", 20, yOffset -30);
ECS_STAT_PANE.NatureCrit:SetText("Nature Crit Chance: " .. ECS_CHARACTER_STATS.natureCrit);
-- Frost DMG
ECS_STAT_PANE.FrostDmg:SetPoint("TOPLEFT", 20, yOffset -45);
ECS_STAT_PANE.FrostDmg:SetText("Frost Bonus Damage: " .. ECS_CHARACTER_STATS.frostBonusDmg);
-- Frost Crit
ECS_STAT_PANE.FrostCrit:SetPoint("TOPLEFT", 20, yOffset -60);
ECS_STAT_PANE.FrostCrit:SetText("Frost Crit Chance: " .. ECS_CHARACTER_STATS.frostCrit);
-- Fire DMG
ECS_STAT_PANE.FireDmg:SetPoint("TOPLEFT", 20, yOffset -75);
ECS_STAT_PANE.FireDmg:SetText("Fire Bonus Damage: " .. ECS_CHARACTER_STATS.fireBonusDmg);
-- Fire Crit
ECS_STAT_PANE.FireCrit:SetPoint("TOPLEFT", 20, yOffset -90);
ECS_STAT_PANE.FireCrit:SetText("Fire Crit Chance: " .. ECS_CHARACTER_STATS.fireCrit);
-- Bonus Healing
ECS_STAT_PANE.BonusHealing:SetPoint("TOPLEFT", 20, yOffset -105);
ECS_STAT_PANE.BonusHealing:SetText("Bonus Healing: " .. ECS_CHARACTER_STATS.spellBonusHealing);
elseif class == "Mage" then
-- Arcane DMG
ECS_STAT_PANE.ArcaneDmg:SetPoint("TOPLEFT", 20, yOffset -15);
ECS_STAT_PANE.ArcaneDmg:SetText("Arcane Bonus Damage: " .. ECS_CHARACTER_STATS.arcaneBonusDmg);
-- Arcane Crit
ECS_STAT_PANE.ArcaneCrit:SetPoint("TOPLEFT", 20, yOffset -30);
ECS_STAT_PANE.ArcaneCrit:SetText("Arcane Crit Chance: " .. ECS_CHARACTER_STATS.arcaneCrit);
-- Frost DMG
ECS_STAT_PANE.FrostDmg:SetPoint("TOPLEFT", 20, yOffset -45);
ECS_STAT_PANE.FrostDmg:SetText("Frost Bonus Damage: " .. ECS_CHARACTER_STATS.frostBonusDmg);
-- Frost Crit
ECS_STAT_PANE.FrostCrit:SetPoint("TOPLEFT", 20, yOffset -60);
ECS_STAT_PANE.FrostCrit:SetText("Frost Crit Chance: " .. ECS_CHARACTER_STATS.frostCrit);
-- Fire DMG
ECS_STAT_PANE.FireDmg:SetPoint("TOPLEFT", 20, yOffset -75);
ECS_STAT_PANE.FireDmg:SetText("Fire Bonus Damage: " .. ECS_CHARACTER_STATS.fireBonusDmg);
-- Fire Crit
ECS_STAT_PANE.FireCrit:SetPoint("TOPLEFT", 20, yOffset -90);
ECS_STAT_PANE.FireCrit:SetText("Fire Crit Chance: " .. ECS_CHARACTER_STATS.fireCrit);
elseif class == "Warlock" then
-- Fire DMG
ECS_STAT_PANE.FireDmg:SetPoint("TOPLEFT", 20, yOffset -15);
ECS_STAT_PANE.FireDmg:SetText("Fire Bonus Damage: " .. ECS_CHARACTER_STATS.fireBonusDmg);
-- Fire Crit
ECS_STAT_PANE.FireCrit:SetPoint("TOPLEFT", 20, yOffset -30);
ECS_STAT_PANE.FireCrit:SetText("Fire Crit Chance: " .. ECS_CHARACTER_STATS.fireCrit);
-- Shadow DMG
ECS_STAT_PANE.ShadowDmg:SetPoint("TOPLEFT", 20, yOffset - 45);
ECS_STAT_PANE.ShadowDmg:SetText("Shadow Bonus Damage: " .. ECS_CHARACTER_STATS.shadowBonusDmg);
-- Shadow Crit
ECS_STAT_PANE.ShadowCrit:SetPoint("TOPLEFT", 20, yOffset -60);
ECS_STAT_PANE.ShadowCrit:SetText("Shadow Crit Chance: " .. ECS_CHARACTER_STATS.shadowCrit);
elseif class == "Druid" then
-- Nature DMG
ECS_STAT_PANE.NatureDmg:SetPoint("TOPLEFT", 20, yOffset -15);
ECS_STAT_PANE.NatureDmg:SetText("Nature Bonus Damage: " .. ECS_CHARACTER_STATS.natureBonusDmg);
-- Nature Crit
ECS_STAT_PANE.NatureCrit:SetPoint("TOPLEFT", 20, yOffset -30);
ECS_STAT_PANE.NatureCrit:SetText("Nature Crit Chance: " .. ECS_CHARACTER_STATS.natureCrit);
-- Bonus Healing
ECS_STAT_PANE.BonusHealing:SetPoint("TOPLEFT", 20, yOffset -45);
ECS_STAT_PANE.BonusHealing:SetText("Bonus Healing: " .. ECS_CHARACTER_STATS.spellBonusHealing);
end
end
-- Updates all stats under the 'Defense' header
local function UpdateDefense()
-- Defense Header
ECS_STAT_PANE.BaseHeader:SetPoint("TOPLEFT", 20, -40);
ECS_STAT_PANE.BaseHeader:SetText("Defense");
-- Dodge
ECS_STAT_PANE.DodgeChance:SetPoint("TOPLEFT", 20, -55);
ECS_STAT_PANE.DodgeChance:SetText("Dodge: " .. ECS_CHARACTER_STATS.dodge);
-- Parry
ECS_STAT_PANE.ParryChance:SetPoint("TOPLEFT", 20, -70);
ECS_STAT_PANE.ParryChance:SetText("Parry: " .. ECS_CHARACTER_STATS.parry);
-- Block
ECS_STAT_PANE.BlockChance:SetPoint("TOPLEFT", 20, -85);
ECS_STAT_PANE.BlockChance:SetText("Block: " .. ECS_CHARACTER_STATS.block);
-- Resource Regen
ECS_STAT_PANE.PowerRegen:SetPoint("TOPLEFT", 20, -100);
if UnitClass("player") == "Warrior" then
ECS_STAT_PANE.PowerRegen:SetText("MP5: N/A");
elseif UnitClass("player") == "Rogue" then
ECS_STAT_PANE.PowerRegen:SetText("MP5: N/A");
else
ECS_STAT_PANE.PowerRegen:SetText("MP5: " .. ECS_CHARACTER_STATS.powerRegen);
end
end
-- Updates all stats under the 'Melee' header
local function UpdateMelee()
-- Melee Header
ECS_STAT_PANE.MeleeHeader:SetPoint("TOPLEFT", 20, -120);
ECS_STAT_PANE.MeleeHeader:SetText("Melee");
-- Hit
ECS_STAT_PANE.MeleeHit:SetPoint("TOPLEFT", 20, -135);
ECS_STAT_PANE.MeleeHit:SetText("Hit Bonus: " .. ECS_CHARACTER_STATS.hitChance);
-- Crit
ECS_STAT_PANE.MeleeCrit:SetPoint("TOPLEFT", 20, -150);
ECS_STAT_PANE.MeleeCrit:SetText("Crit Chance: " .. ECS_CHARACTER_STATS.meleeCrit);
end
-- Updates all stats under the 'Ranged' header
local function UpdateRange()
-- Ranged Header
ECS_STAT_PANE.RangedHeader:SetPoint("TOPLEFT", 20, -170);
ECS_STAT_PANE.RangedHeader:SetText("Ranged");
-- Hit
ECS_STAT_PANE.RangedHit:SetPoint("TOPLEFT", 20, -185);
ECS_STAT_PANE.RangedHit:SetText("Hit Bonus: " .. ECS_CHARACTER_STATS.hitChance);
-- Crit
ECS_STAT_PANE.RangedCrit:SetPoint("TOPLEFT", 20, -200);
ECS_STAT_PANE.RangedCrit:SetText("Crit Chance: " .. ECS_CHARACTER_STATS.rangedCrit);
end
-- Updates all stats under the 'Spell' header
local function UpdateSpell()
-- Spell Header
ECS_STAT_PANE.SpellHeader:SetPoint("TOPLEFT", 20, -220);
ECS_STAT_PANE.SpellHeader:SetText("Spell");
-- Hit
ECS_STAT_PANE.SpellHit:SetPoint("TOPLEFT", 20, -235);
ECS_STAT_PANE.SpellHit:SetText("Hit Bonus: " .. ECS_CHARACTER_STATS.hitChance);
-- Crit
ECS_STAT_PANE.SpellCrit:SetPoint("TOPLEFT", 20, -250);
ECS_STAT_PANE.SpellCrit:SetText("Crit Chance: " .. ECS_CHARACTER_STATS.spellCrit);
UpdateSpellBonus(UnitClass("player"), -250);
end
-- Toggles the display of the window
-- if the window is hidden or closed, it will be displayed
-- if the window is visible, it will be hidden
local function ToggleView(msg)
ECS_STAT_PANE:SetShown(not ECS_STAT_PANE:IsShown());
end
-- Event handler for all the subscribed events
-- Calls the update functions to update all the relevant stats
ECS_EVENT_FRAME:SetScript("OnEvent", function(self, event, ...)
-- Get updated stat data
ECS_CHARACTER_STATS = {
-- Base Stats
hitChance = Round(GetHitModifier()) .. "%",
powerRegen = Round(GetPowerRegen()),
meleeCrit = Round(GetCritChance()) .. "%",
spellCrit = Round(GetSpellCritChance()) .. "%",
rangedCrit = Round(GetRangedCritChance()) .. "%",
spellPen = Round(GetSpellPenetration()) .. "%",
-- Defense
dodge = Round(GetDodgeChance()) .. "%",
parry = Round(GetParryChance()) .. "%",
block = Round(GetBlockChance()) .. "%",
-- Bonus Spell Damage & Healing
physicalBonusDmg = Round(GetSpellBonusDamage(1)),
holyBonusDmg = Round(GetSpellBonusDamage(2)),
fireBonusDmg = Round(GetSpellBonusDamage(3)),
natureBonusDmg = Round(GetSpellBonusDamage(4)),
frostBonusDmg = Round(GetSpellBonusDamage(5)),
shadowBonusDmg = Round(GetSpellBonusDamage(6)),
arcaneBonusDmg = Round(GetSpellBonusDamage(7)),
spellBonusHealing = Round(GetSpellBonusHealing()),
-- Spell Crit
physicalCrit = Round(GetSpellCritChance(1)) .. "%",
holyCrit = Round(GetSpellCritChance(2)) .. "%",
fireCrit = Round(GetSpellCritChance(3)) .. "%",
natureCrit = Round(GetSpellCritChance(4)) .. "%",
frostCrit = Round(GetSpellCritChance(5)) .. "%",
shadowCrit = Round(GetSpellCritChance(6)) .. "%",
arcaneCrit = Round(GetSpellCritChance(7)) .. "%",
-- Pets
petSpellDmg = Round(GetPetSpellBonusDamage()),
}
-- Update the GUI
UpdateDefense();
UpdateMelee();
UpdateRange();
UpdateSpell();
end)
-- Slash Command for toggling the display
SLASH_ECS1 = "/ECS";
SlashCmdList["ECS"] = ToggleView;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment