You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
837 lines
31 KiB
837 lines
31 KiB
local DIGITS = "%.2f";
|
|
local NO_BONUS_ALPHA = 0.5;
|
|
|
|
local Narci = Narci;
|
|
local L = Narci.L;
|
|
local FormatLargeNumbers = NarciAPI.FormatLargeNumbers;
|
|
local BreakUpLargeNumbers = BreakUpLargeNumbers;
|
|
local GetPrimaryStats = NarciAPI.GetPrimaryStats;
|
|
local format = string.format;
|
|
local floor = math.floor;
|
|
local ceil = math.ceil;
|
|
local max = math.max;
|
|
local min = math.min;
|
|
|
|
local DefaultTooltip = NarciGameTooltip; --Created in NarciAPI.lua
|
|
|
|
local C_PaperDollInfo = C_PaperDollInfo;
|
|
local UnitStat = UnitStat;
|
|
local GetCombatRating = GetCombatRating;
|
|
local GetCombatRatingBonus = GetCombatRatingBonus;
|
|
local BASE_MOVEMENT_SPEED = BASE_MOVEMENT_SPEED;
|
|
local GetSpecialization = GetSpecialization;
|
|
|
|
local function GetPrimaryStatsNum()
|
|
local _, strength = UnitStat("player", 1);
|
|
local _, agility = UnitStat("player", 2);
|
|
local _, intellect = UnitStat("player", 4);
|
|
if strength > agility and strength > intellect then
|
|
return strength;
|
|
elseif agility > strength and agility > intellect then
|
|
return agility;
|
|
elseif intellect > agility and intellect > strength then
|
|
return intellect;
|
|
end
|
|
end
|
|
|
|
local function GetAppropriateDamage(unit)
|
|
if IsRangedWeapon() then
|
|
local attackTime, minDamage, maxDamage, bonusPos, bonusNeg, percent = UnitRangedDamage(unit);
|
|
return minDamage, maxDamage, nil, nil, 0, 0, percent;
|
|
else
|
|
return UnitDamage(unit);
|
|
end
|
|
end
|
|
|
|
local function CharacterDamageFrame_OnEnter(object)
|
|
-- Main hand weapon
|
|
DefaultTooltip:SetOwner(object, "ANCHOR_NONE");
|
|
if ( object.unit == "pet" ) then
|
|
DefaultTooltip:SetText(INVTYPE_WEAPONMAINHAND_PET, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
|
|
else
|
|
DefaultTooltip:SetText(INVTYPE_WEAPONMAINHAND, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
|
|
end
|
|
DefaultTooltip:AddDoubleLine(format(STAT_FORMAT, ATTACK_SPEED_SECONDS), format("%.2F", object.attackSpeed), 1.00, 0.82, 0.00, 1.00, 0.82, 0.00);
|
|
DefaultTooltip:AddDoubleLine(format(STAT_FORMAT, DAMAGE), object.damage, 1.00, 0.82, 0.00, 1.00, 0.82, 0.00);
|
|
-- Check for offhand weapon
|
|
if ( object.offhandAttackSpeed ) then
|
|
DefaultTooltip:AddLine("\n");
|
|
DefaultTooltip:AddLine(INVTYPE_WEAPONOFFHAND, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
|
|
DefaultTooltip:AddDoubleLine(format(STAT_FORMAT, ATTACK_SPEED_SECONDS), format("%.2F", object.offhandAttackSpeed), 1.00, 0.82, 0.00, 1.00, 0.82, 0.00);
|
|
DefaultTooltip:AddDoubleLine(format(STAT_FORMAT, DAMAGE), object.offhandDamage, 1.00, 0.82, 0.00, 1.00, 0.82, 0.00);
|
|
end
|
|
|
|
DefaultTooltip:SetPoint("TOPRIGHT",object,"TOPLEFT", -4, 0);
|
|
DefaultTooltip:Show();
|
|
end
|
|
|
|
local function MovementSpeed_OnUpdate(object, elapsed)
|
|
object.t = object.t + elapsed;
|
|
if object.t > 0.1 then
|
|
object.t = 0;
|
|
else
|
|
return
|
|
end
|
|
|
|
local unit = object.unit;
|
|
local _, runSpeed, flightSpeed, swimSpeed = GetUnitSpeed(unit);
|
|
runSpeed = runSpeed/BASE_MOVEMENT_SPEED*100;
|
|
flightSpeed = flightSpeed/BASE_MOVEMENT_SPEED*100;
|
|
swimSpeed = swimSpeed/BASE_MOVEMENT_SPEED*100;
|
|
|
|
-- Determine whether to display running, flying, or swimming speed
|
|
local speed = runSpeed;
|
|
local swimming = IsSwimming(unit);
|
|
if (swimming) then
|
|
speed = swimSpeed;
|
|
elseif (IsFlying(unit)) then
|
|
speed = flightSpeed;
|
|
end
|
|
|
|
-- Hack so that your speed doesn't appear to change when jumping out of the water
|
|
if (IsFalling(unit)) then
|
|
if (object.wasSwimming) then
|
|
speed = swimSpeed;
|
|
end
|
|
else
|
|
object.wasSwimming = swimming;
|
|
end
|
|
|
|
local valueText = format("%d%%", speed+0.5);
|
|
|
|
object.Label:SetText(L["Movement Speed"]); --STAT_MOVEMENT_SPEED
|
|
object.Value:SetText(valueText);
|
|
|
|
object.speed = speed;
|
|
object.runSpeed = runSpeed;
|
|
object.flightSpeed = flightSpeed;
|
|
object.swimSpeed = swimSpeed;
|
|
end
|
|
|
|
local function MovementSpeed_OnEnter(object)
|
|
DefaultTooltip:SetOwner(object, "ANCHOR_NONE");
|
|
DefaultTooltip:SetText("|cffffffff".. STAT_MOVEMENT_SPEED .." "..format("%d%%", object.speed+0.5).."|r");
|
|
|
|
DefaultTooltip:AddLine(format(STAT_MOVEMENT_GROUND_TOOLTIP, object.runSpeed+0.5));
|
|
if (object.unit ~= "pet") then
|
|
DefaultTooltip:AddLine(format(STAT_MOVEMENT_FLIGHT_TOOLTIP, object.flightSpeed+0.5));
|
|
end
|
|
DefaultTooltip:AddLine(format(STAT_MOVEMENT_SWIM_TOOLTIP, object.swimSpeed+0.5));
|
|
DefaultTooltip:AddLine(" ");
|
|
DefaultTooltip:AddLine(format(CR_SPEED_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_SPEED)), GetCombatRatingBonus(CR_SPEED)));
|
|
|
|
DefaultTooltip:SetPoint("TOPRIGHT",object,"TOPLEFT", -4, 0)
|
|
DefaultTooltip:Show();
|
|
|
|
object.UpdateTooltip = MovementSpeed_OnEnter;
|
|
end
|
|
|
|
local function MasteryFrame_OnEnter(object)
|
|
local RadarChart = object:GetParent();
|
|
if RadarChart.SetVerticeSize then
|
|
RadarChart.SetVerticeSize(RadarChart, object, 15);
|
|
end
|
|
|
|
DefaultTooltip:SetOwner(object, "ANCHOR_NONE");
|
|
|
|
local mastery, bonusCoeff = GetMasteryEffect();
|
|
local masteryBonus = GetCombatRatingBonus(CR_MASTERY) * bonusCoeff;
|
|
|
|
local title = "|cffffffff"..STAT_MASTERY.." "..format("%.2F%%", mastery).."|r";
|
|
if (masteryBonus > 0) then
|
|
title = title.."|cffffffff".." ("..format("%.2F%%", mastery-masteryBonus).."|r"..GREEN_FONT_COLOR_CODE.."+"..format("%.2F%%", masteryBonus).."|r".."|cffffffff"..")".."|r";
|
|
end
|
|
DefaultTooltip:SetText(title);
|
|
|
|
local masteryRating = GetCombatRating(CR_MASTERY);
|
|
local primaryTalentTree = GetSpecialization();
|
|
if (primaryTalentTree) then --dragonflight
|
|
local masterySpell, masterySpell2 = GetSpecializationMasterySpells(primaryTalentTree);
|
|
if DefaultTooltip.AddSpellByID then
|
|
if (masterySpell) then
|
|
DefaultTooltip:AddSpellByID(masterySpell);
|
|
end
|
|
if (masterySpell2) then
|
|
DefaultTooltip:AddLine(" ");
|
|
DefaultTooltip:AddSpellByID(masterySpell2);
|
|
end
|
|
else
|
|
if (masterySpell) then
|
|
local tooltipInfo = CreateBaseTooltipInfo("GetSpellByID", masterySpell);
|
|
tooltipInfo.append = true;
|
|
DefaultTooltip:ProcessInfo(tooltipInfo);
|
|
end
|
|
if (masterySpell2) then
|
|
DefaultTooltip:AddLine(" ");
|
|
local tooltipInfo = CreateBaseTooltipInfo("GetSpellByID", masterySpell2);
|
|
tooltipInfo.append = true;
|
|
DefaultTooltip:ProcessInfo(tooltipInfo);
|
|
end
|
|
end
|
|
DefaultTooltip:AddLine(" ");
|
|
local tooltip = format(STAT_MASTERY_TOOLTIP, BreakUpLargeNumbers(masteryRating), masteryBonus);
|
|
if masteryBonus ~= 0 then
|
|
DefaultTooltip:AddDoubleLine(tooltip ,floor( (masteryRating / masteryBonus) * 100 + 0.5) / 100 .. " [+1%]", 1.00, 0.82, 0.00, 1.00, 0.82, 0.00);
|
|
else
|
|
DefaultTooltip:AddLine(tooltip, 1.00, 0.82, 0.00, true);
|
|
end
|
|
else
|
|
DefaultTooltip:AddLine(format(STAT_MASTERY_TOOLTIP, BreakUpLargeNumbers(masteryRating), masteryBonus), 1.00, 0.82, 0.00, true);
|
|
DefaultTooltip:AddLine(" ");
|
|
DefaultTooltip:AddLine(STAT_MASTERY_TOOLTIP_NO_TALENT_SPEC, GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b, true);
|
|
end
|
|
DefaultTooltip:SetPoint("TOPRIGHT",object,"TOPLEFT", -4, 0)
|
|
DefaultTooltip:Show();
|
|
end
|
|
|
|
local function GetEffectiveCrit()
|
|
local rating;
|
|
local spellCrit, rangedCrit, meleeCrit;
|
|
local critChance;
|
|
|
|
-- Start at 2 to skip physical damage
|
|
local holySchool = 2;
|
|
local minCrit = GetSpellCritChance(holySchool);
|
|
local spellCritTable = {};
|
|
spellCritTable[holySchool] = minCrit;
|
|
local spellCrit;
|
|
for i = (holySchool+1), MAX_SPELL_SCHOOLS do
|
|
spellCrit = GetSpellCritChance(i);
|
|
minCrit = min(minCrit, spellCrit);
|
|
spellCritTable[i] = spellCrit;
|
|
end
|
|
spellCrit = minCrit
|
|
rangedCrit = GetRangedCritChance();
|
|
meleeCrit = GetCritChance();
|
|
|
|
if (spellCrit >= rangedCrit and spellCrit >= meleeCrit) then
|
|
critChance = spellCrit;
|
|
rating = CR_CRIT_SPELL;
|
|
elseif (rangedCrit >= meleeCrit) then
|
|
critChance = rangedCrit;
|
|
rating = CR_CRIT_RANGED;
|
|
else
|
|
critChance = meleeCrit;
|
|
rating = CR_CRIT_MELEE;
|
|
end
|
|
|
|
return critChance, rating
|
|
end
|
|
|
|
Narci.GetEffectiveCrit = GetEffectiveCrit;
|
|
|
|
------------------------------------------------------------------
|
|
----The following codes are derivated from PapaerDollFrame.lua----
|
|
------------------------------------------------------------------
|
|
local UpdateFunc = {};
|
|
|
|
function UpdateFunc:Primary(object)
|
|
local unit = "player";
|
|
local PrimaryStatsName, PrimaryStatsNum = GetPrimaryStats();
|
|
object.Label:SetText(PrimaryStatsName)
|
|
object.Value:SetText(PrimaryStatsNum)
|
|
local spec = GetSpecialization();
|
|
if not spec then return; end
|
|
local role = GetSpecializationRole(spec);
|
|
local _, _, _, _, _, primaryStat = GetSpecializationInfo(spec);
|
|
if type(tonumber(primaryStat)) ~= "number" then return; end --sometimes changing zones cause Lua error
|
|
local stat, effectiveStat, posBuff, negBuff = UnitStat(unit, primaryStat);
|
|
local effectiveStatDisplay = FormatLargeNumbers(effectiveStat);
|
|
|
|
-- Set the tooltip text
|
|
local statName = _G["SPELL_STAT"..primaryStat.."_NAME"];
|
|
local tooltipText = "|cffffffff".. statName .." ";
|
|
|
|
if ( ( posBuff == 0 ) and ( negBuff == 0 ) ) then
|
|
object.tooltip = tooltipText..effectiveStatDisplay.."|r";
|
|
else
|
|
tooltipText = tooltipText..effectiveStatDisplay;
|
|
if ( posBuff > 0 or negBuff < 0 ) then
|
|
tooltipText = tooltipText.." ("..BreakUpLargeNumbers(stat - posBuff - negBuff).."|r";
|
|
end
|
|
if ( posBuff > 0 ) then
|
|
tooltipText = tooltipText.."|r"..GREEN_FONT_COLOR_CODE.."+"..BreakUpLargeNumbers(posBuff).."|r";
|
|
end
|
|
if ( negBuff < 0 ) then
|
|
tooltipText = tooltipText..RED_FONT_COLOR_CODE.." "..BreakUpLargeNumbers(negBuff).."|r";
|
|
end
|
|
if ( posBuff > 0 or negBuff < 0 ) then
|
|
tooltipText = tooltipText.."|cffffffff"..")".."|r";
|
|
end
|
|
object.tooltip = tooltipText;
|
|
|
|
-- If there are any negative buffs then show the main number in red even if there are
|
|
-- positive buffs. Otherwise show in green.
|
|
if ( negBuff < 0 and not GetPVPGearStatRules() ) then
|
|
effectiveStatDisplay = RED_FONT_COLOR_CODE..effectiveStatDisplay.."|r";
|
|
end
|
|
end
|
|
|
|
object.tooltip2 = _G["DEFAULT_STAT"..primaryStat.."_TOOLTIP"];
|
|
|
|
if ( primaryStat == LE_UNIT_STAT_AGILITY ) then
|
|
local attackPower = GetAttackPowerForStat(primaryStat, effectiveStat);
|
|
local tooltip = STAT_TOOLTIP_BONUS_AP;
|
|
if (HasAPEffectsSpellPower()) then
|
|
tooltip = STAT_TOOLTIP_BONUS_AP_SP;
|
|
end
|
|
if (not primaryStat or primaryStat == LE_UNIT_STAT_AGILITY) then
|
|
object.tooltip2 = format(tooltip, BreakUpLargeNumbers(attackPower));
|
|
if ( role == "TANK" ) then
|
|
local increasedDodgeChance = GetDodgeChanceFromAttribute();
|
|
if ( increasedDodgeChance > 0 ) then
|
|
object.tooltip2 = object.tooltip2.."|n|n"..format(CR_DODGE_BASE_STAT_TOOLTIP, increasedDodgeChance);
|
|
end
|
|
end
|
|
else
|
|
object.tooltip2 = STAT_NO_BENEFIT_TOOLTIP;
|
|
end
|
|
|
|
elseif ( primaryStat == LE_UNIT_STAT_STRENGTH ) then
|
|
local attackPower = GetAttackPowerForStat(primaryStat,effectiveStat);
|
|
if (HasAPEffectsSpellPower()) then
|
|
object.tooltip2 = STAT_TOOLTIP_BONUS_AP_SP;
|
|
end
|
|
if (not primaryStat or primaryStat == LE_UNIT_STAT_STRENGTH) then
|
|
object.tooltip2 = format(object.tooltip2, BreakUpLargeNumbers(attackPower));
|
|
if ( role == "TANK" ) then
|
|
local increasedParryChance = GetParryChanceFromAttribute();
|
|
if ( increasedParryChance > 0 ) then
|
|
object.tooltip2 = object.tooltip2.."|n|n"..format(CR_PARRY_BASE_STAT_TOOLTIP, increasedParryChance);
|
|
end
|
|
end
|
|
else
|
|
object.tooltip2 = STAT_NO_BENEFIT_TOOLTIP;
|
|
end
|
|
|
|
elseif ( primaryStat == LE_UNIT_STAT_INTELLECT ) then
|
|
if ( UnitHasMana("player") ) then
|
|
if (HasAPEffectsSpellPower()) then
|
|
object.tooltip2 = STAT_NO_BENEFIT_TOOLTIP;
|
|
else
|
|
local result, druid = HasSPEffectsAttackPower();
|
|
if (result and druid) then
|
|
object.tooltip2 = format(STAT_TOOLTIP_SP_AP_DRUID, max(0, effectiveStat), max(0, effectiveStat));
|
|
elseif (result) then
|
|
object.tooltip2 = format(STAT_TOOLTIP_BONUS_AP_SP, max(0, effectiveStat));
|
|
elseif (not primaryStat or primaryStat == LE_UNIT_STAT_INTELLECT) then
|
|
object.tooltip2 = format(object.tooltip2, max(0, effectiveStat));
|
|
else
|
|
object.tooltip2 = STAT_NO_BENEFIT_TOOLTIP;
|
|
end
|
|
end
|
|
else
|
|
object.tooltip2 = STAT_NO_BENEFIT_TOOLTIP;
|
|
end
|
|
end
|
|
end
|
|
|
|
function UpdateFunc:Stamina(object)
|
|
local statIndex = LE_UNIT_STAT_STAMINA;
|
|
local stat, effectiveStat, posBuff, negBuff = UnitStat("player", statIndex);
|
|
|
|
local effectiveStatDisplay = FormatLargeNumbers(effectiveStat);
|
|
-- Set the tooltip text
|
|
local statName = _G["SPELL_STAT"..statIndex.."_NAME"];
|
|
local tooltipText = "|cffffffff".. statName .." ";
|
|
|
|
if ( ( posBuff == 0 ) and ( negBuff == 0 ) ) then
|
|
object.tooltip = tooltipText..effectiveStatDisplay.."|r";
|
|
else
|
|
tooltipText = tooltipText..effectiveStatDisplay;
|
|
if ( posBuff > 0 or negBuff < 0 ) then
|
|
tooltipText = tooltipText.." ("..BreakUpLargeNumbers(stat - posBuff - negBuff).."|r";
|
|
end
|
|
if ( posBuff > 0 ) then
|
|
tooltipText = tooltipText.."|r"..GREEN_FONT_COLOR_CODE.."+"..BreakUpLargeNumbers(posBuff).."|r";
|
|
end
|
|
if ( negBuff < 0 ) then
|
|
tooltipText = tooltipText..RED_FONT_COLOR_CODE.." "..BreakUpLargeNumbers(negBuff).."|r";
|
|
end
|
|
if ( posBuff > 0 or negBuff < 0 ) then
|
|
tooltipText = tooltipText.."|cffffffff"..")".."|r";
|
|
end
|
|
object.tooltip = tooltipText;
|
|
|
|
-- If there are any negative buffs then show the main number in red even if there are
|
|
-- positive buffs. Otherwise show in green.
|
|
if ( negBuff < 0 and not GetPVPGearStatRules() ) then
|
|
effectiveStatDisplay = RED_FONT_COLOR_CODE..effectiveStatDisplay.."|r";
|
|
end
|
|
end
|
|
|
|
object.Label:SetText(statName)
|
|
object.Value:SetText(effectiveStat)
|
|
object.tooltip2 = _G["DEFAULT_STAT"..statIndex.."_TOOLTIP"];
|
|
object.tooltip2 = format(object.tooltip2, BreakUpLargeNumbers(((effectiveStat*UnitHPPerStamina("player")))*GetUnitMaxHealthModifier("player")));
|
|
|
|
--object:Show();
|
|
end
|
|
|
|
function UpdateFunc:Damage(object)
|
|
local unit = "player";
|
|
|
|
local speed, offhandSpeed = UnitAttackSpeed(unit);
|
|
local minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent = GetAppropriateDamage(unit);
|
|
|
|
-- remove decimal points for display values
|
|
local displayMin = max(floor(minDamage),1);
|
|
local displayMinLarge = displayMin --BreakUpLargeNumbers(displayMin);
|
|
local displayMax = max(ceil(maxDamage),1);
|
|
local displayMaxLarge = displayMax --BreakUpLargeNumbers(displayMax);
|
|
|
|
-- calculate base damage
|
|
if percent == 0 then return; end;
|
|
minDamage = (minDamage / percent) - physicalBonusPos - physicalBonusNeg;
|
|
maxDamage = (maxDamage / percent) - physicalBonusPos - physicalBonusNeg;
|
|
|
|
local baseDamage = (minDamage + maxDamage) * 0.5;
|
|
local fullDamage = (baseDamage + physicalBonusPos + physicalBonusNeg) * percent;
|
|
local totalBonus = (fullDamage - baseDamage);
|
|
-- set tooltip text with base damage
|
|
local damageTooltip = BreakUpLargeNumbers(max(floor(minDamage),1)).." - "..BreakUpLargeNumbers(max(ceil(maxDamage),1));
|
|
|
|
local colorPos = "|cffffffff";
|
|
local colorNeg = "|cffffffff";
|
|
|
|
-- epsilon check
|
|
if ( totalBonus < 0.1 and totalBonus > -0.1 ) then
|
|
totalBonus = 0.0;
|
|
end
|
|
|
|
local value;
|
|
if ( totalBonus == 0 ) then
|
|
if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then
|
|
value = displayMinLarge.." - "..displayMaxLarge;
|
|
else
|
|
value = displayMinLarge.." - "..displayMaxLarge;
|
|
end
|
|
else
|
|
-- set bonus color and display
|
|
local color;
|
|
if ( totalBonus > 0 ) then
|
|
color = colorPos;
|
|
else
|
|
color = colorNeg;
|
|
end
|
|
if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then
|
|
value = color..displayMinLarge.." - "..displayMaxLarge.."|r";
|
|
else
|
|
value = color..displayMinLarge.." - "..displayMaxLarge.."|r";
|
|
end
|
|
if ( physicalBonusPos > 0 ) then
|
|
damageTooltip = damageTooltip..colorPos.." +"..physicalBonusPos.."|r";
|
|
end
|
|
if ( physicalBonusNeg < 0 ) then
|
|
damageTooltip = damageTooltip..colorNeg.." "..physicalBonusNeg.."|r";
|
|
end
|
|
if ( percent > 1 ) then
|
|
damageTooltip = damageTooltip..colorPos.." x"..floor(percent*100+0.5).."%|r";
|
|
elseif ( percent < 1 ) then
|
|
damageTooltip = damageTooltip..colorNeg.." x"..floor(percent*100+0.5).."%|r";
|
|
end
|
|
|
|
end
|
|
|
|
object.Label:SetText(DAMAGE)
|
|
object.Value:SetText(value)
|
|
object.damage = damageTooltip;
|
|
object.attackSpeed = speed;
|
|
object.unit = unit;
|
|
|
|
-- If there's an offhand speed then add the offhand info to the tooltip
|
|
if ( offhandSpeed and minOffHandDamage and maxOffHandDamage ) then
|
|
minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg;
|
|
maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg;
|
|
|
|
local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5;
|
|
local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent;
|
|
local offhandDamageTooltip = BreakUpLargeNumbers(max(floor(minOffHandDamage),1)).." - "..BreakUpLargeNumbers(max(ceil(maxOffHandDamage),1));
|
|
if ( physicalBonusPos > 0 ) then
|
|
offhandDamageTooltip = offhandDamageTooltip..colorPos.." +"..physicalBonusPos.."|r";
|
|
end
|
|
if ( physicalBonusNeg < 0 ) then
|
|
offhandDamageTooltip = offhandDamageTooltip..colorNeg.." "..physicalBonusNeg.."|r";
|
|
end
|
|
if ( percent > 1 ) then
|
|
offhandDamageTooltip = offhandDamageTooltip..colorPos.." x"..floor(percent*100+0.5).."%|r";
|
|
elseif ( percent < 1 ) then
|
|
offhandDamageTooltip = offhandDamageTooltip..colorNeg.." x"..floor(percent*100+0.5).."%|r";
|
|
end
|
|
object.offhandDamage = offhandDamageTooltip;
|
|
object.offhandAttackSpeed = offhandSpeed;
|
|
else
|
|
object.offhandAttackSpeed = nil;
|
|
end
|
|
|
|
object:SetScript("OnEnter", CharacterDamageFrame_OnEnter);
|
|
--object:Show();
|
|
end
|
|
|
|
function UpdateFunc:AttackSpeed(object, unit)
|
|
local unit = "player"
|
|
|
|
local meleeHaste = GetMeleeHaste();
|
|
local speed, offhandSpeed = UnitAttackSpeed(unit);
|
|
|
|
local displaySpeed = floor(100*speed + 0.5)/100;
|
|
if ( offhandSpeed ) then
|
|
offhandSpeed = floor(100*offhandSpeed + 0.5)/100;
|
|
end
|
|
if ( offhandSpeed ) then
|
|
if displaySpeed ~= offhandSpeed then
|
|
displaySpeed = displaySpeed.." / ".. offhandSpeed;
|
|
else
|
|
displaySpeed = displaySpeed;
|
|
end
|
|
else
|
|
displaySpeed = displaySpeed;
|
|
end
|
|
|
|
local speedText = format(DIGITS, meleeHaste).."%"
|
|
object.Label:SetText(ATTACK_SPEED)
|
|
object.Value:SetText(displaySpeed)
|
|
|
|
object.tooltip = "|cffffffff".. ATTACK_SPEED .." "..displaySpeed.."|r";
|
|
object.tooltip2 = format(STAT_ATTACK_SPEED_BASE_TOOLTIP, format(DIGITS, meleeHaste));
|
|
|
|
--object:Show();
|
|
end
|
|
|
|
function UpdateFunc:Armor(object, unit)
|
|
local unit = "player"
|
|
|
|
local baselineArmor, effectiveArmor, armor, bonusArmor = UnitArmor(unit);
|
|
object.Label:SetText(STAT_ARMOR);
|
|
object.Value:SetText(effectiveArmor);
|
|
|
|
local armorReduction = C_PaperDollInfo.GetArmorEffectiveness(effectiveArmor, UnitEffectiveLevel(unit));
|
|
local armorReductionAgainstTarget = C_PaperDollInfo.GetArmorEffectivenessAgainstTarget(effectiveArmor);
|
|
|
|
object.tooltip = "|cffffffff".. ARMOR .." "..BreakUpLargeNumbers(effectiveArmor).."|r";
|
|
object.tooltip2 = format(STAT_ARMOR_TOOLTIP, 100*armorReduction);
|
|
if (armorReductionAgainstTarget) then
|
|
object.tooltip3 = format(STAT_ARMOR_TARGET_TOOLTIP, 100*armorReductionAgainstTarget);
|
|
else
|
|
object.tooltip3 = nil;
|
|
end
|
|
--object:Show();
|
|
end
|
|
|
|
function UpdateFunc:Reduction(object)
|
|
local unit = "player"
|
|
local baselineArmor, effectiveArmor, armor, bonusArmor = UnitArmor(unit);
|
|
|
|
local armorReduction = C_PaperDollInfo.GetArmorEffectiveness(effectiveArmor, UnitEffectiveLevel(unit)) or 0;
|
|
armorReduction = 100 * armorReduction;
|
|
local armorReductionAgainstTarget = C_PaperDollInfo.GetArmorEffectivenessAgainstTarget(effectiveArmor);
|
|
local armorReductionText = format(DIGITS, armorReduction).."%"
|
|
|
|
object.Label:SetText(L["Damage Reduction Percentage"]);
|
|
|
|
object.tooltip = "|cffffffff"..COMBAT_TEXT_SHOW_RESISTANCES_TEXT.." "..armorReductionText.."|r";
|
|
object.tooltip2 = format(STAT_ARMOR_TOOLTIP, armorReduction);
|
|
if (armorReductionAgainstTarget) then
|
|
object.tooltip3 = format(STAT_ARMOR_TARGET_TOOLTIP, 100*armorReductionAgainstTarget);
|
|
armorReduction = 100 * armorReductionAgainstTarget
|
|
else
|
|
object.tooltip3 = nil;
|
|
end
|
|
|
|
object.Value:SetText(armorReductionText);
|
|
--object:Show();
|
|
end
|
|
|
|
function UpdateFunc:Dodge(object)
|
|
local chance = GetDodgeChance();
|
|
local chanceText = format("%.2F", chance).."%"
|
|
object.Label:SetText(STAT_DODGE);
|
|
object.Value:SetText(chanceText);
|
|
|
|
object.tooltip = "|cffffffff".. DODGE_CHANCE .." "..format("%.2F", chance).."%".."|r";
|
|
object.tooltip2 = format(CR_DODGE_TOOLTIP, GetCombatRating(CR_DODGE), GetCombatRatingBonus(CR_DODGE));
|
|
--object:Show();
|
|
end
|
|
|
|
function UpdateFunc:Parry(object)
|
|
local chance = GetParryChance();
|
|
local chanceText = format("%.2F", chance).."%"
|
|
object.Label:SetText(STAT_PARRY);
|
|
object.Value:SetText(chanceText);
|
|
|
|
object.tooltip = "|cffffffff".. PARRY_CHANCE .." "..format("%.2F", chance).."%".."|r";
|
|
object.tooltip2 = format(CR_PARRY_TOOLTIP, GetCombatRating(CR_PARRY), GetCombatRatingBonus(CR_PARRY));
|
|
--object:Show();
|
|
end
|
|
|
|
function UpdateFunc:Block(object)
|
|
local unit = "player";
|
|
|
|
local chance = GetBlockChance();
|
|
local chanceText = format("%.2F", chance).."%";
|
|
|
|
local spec = GetSpecialization();
|
|
if not spec then return; end
|
|
|
|
--local role = GetSpecializationRole(spec);
|
|
if chance ~= 0 and C_PaperDollInfo.OffhandHasShield() then --role == "TANK"
|
|
object:SetLabelAndValue(STAT_BLOCK, chanceText);
|
|
else
|
|
object:SetLabelAndValue(STAT_BLOCK, "N/A", true);
|
|
end
|
|
|
|
object.tooltip = "|cffffffff".. BLOCK_CHANCE .." "..format("%.2F", chance).."%".."|r";
|
|
|
|
local shieldBlockArmor = GetShieldBlock();
|
|
local blockArmorReduction = C_PaperDollInfo.GetArmorEffectiveness(shieldBlockArmor, UnitEffectiveLevel(unit));
|
|
local blockArmorReductionAgainstTarget = C_PaperDollInfo.GetArmorEffectivenessAgainstTarget(shieldBlockArmor);
|
|
|
|
object.tooltip2 = format(CR_BLOCK_TOOLTIP, blockArmorReduction * 100);
|
|
if (blockArmorReductionAgainstTarget) then
|
|
object.tooltip3 = format(STAT_BLOCK_TARGET_TOOLTIP, blockArmorReductionAgainstTarget * 100);
|
|
else
|
|
object.tooltip3 = nil;
|
|
end
|
|
end
|
|
|
|
function UpdateFunc:Health(object, unit)
|
|
if (not unit) then
|
|
unit = "player";
|
|
end
|
|
local health = UnitHealthMax(unit);
|
|
local healthText = FormatLargeNumbers(health);
|
|
object.Label:SetText(HEALTH)
|
|
object.Value:SetText(healthText)
|
|
object.tooltip = "|cffffffff".. HEALTH .." "..healthText.."|r";
|
|
if (unit == "player") then
|
|
object.tooltip2 = STAT_HEALTH_TOOLTIP;
|
|
elseif (unit == "pet") then
|
|
object.tooltip2 = STAT_HEALTH_PET_TOOLTIP;
|
|
end
|
|
object:Show();
|
|
end
|
|
|
|
function UpdateFunc:Power(object)
|
|
local unit = "player";
|
|
local powerType, powerToken = UnitPowerType(unit);
|
|
local power = UnitPowerMax(unit) or 0;
|
|
local powerText = FormatLargeNumbers(power);
|
|
local powerName = _G[powerToken];
|
|
if (powerToken and powerName) then
|
|
object.Label:SetText(powerName)
|
|
object.Value:SetText(powerText)
|
|
object.tooltip = "|cffffffff".. powerName .." "..powerText.."|r";
|
|
object.tooltip2 = _G["STAT_"..powerToken.."_TOOLTIP"];
|
|
object:Show();
|
|
else
|
|
object:SetLabelAndValue("Resource", "N/A", true);
|
|
end
|
|
end
|
|
|
|
function UpdateFunc:Regen(object)
|
|
local powerType, powerToken = UnitPowerType("player");
|
|
local regenRate = GetPowerRegen();
|
|
local regenRateText = BreakUpLargeNumbers(regenRate);
|
|
local regenRatePerSec = format("%.2f", regenRate).."/s";
|
|
local labelText;
|
|
if powerToken == "ENERGY" then
|
|
labelText = STAT_ENERGY_REGEN;
|
|
object.tooltip2 = STAT_ENERGY_REGEN_TOOLTIP;
|
|
elseif powerToken == "RUNES" then
|
|
labelText = STAT_RUNE_REGEN;
|
|
object.tooltip2 = STAT_RUNE_REGEN_TOOLTIP;
|
|
elseif powerToken == "FOCUS" then
|
|
labelText = STAT_FOCUS_REGEN;
|
|
object.tooltip2 = STAT_FOCUS_REGEN_TOOLTIP;
|
|
elseif UnitHasMana("player") then
|
|
labelText = MANA_REGEN;
|
|
regenRate = GetManaRegen();
|
|
regenRatePerSec = tostring(floor(regenRate)).."/s";
|
|
else
|
|
local _, class = UnitClass("player");
|
|
if (class ~= "DEATHKNIGHT") then
|
|
object:SetLabelAndValue(MANA_REGEN_COMBAT, "N/A", true); --MANA_REGEN_ABBR
|
|
return;
|
|
end
|
|
local _, regenRate = GetRuneCooldown(1);
|
|
local regenRateText = (format(STAT_RUNE_REGEN_FORMAT, regenRate));
|
|
object:SetLabelAndValue(STAT_RUNE_REGEN, regenRateText);
|
|
return;
|
|
end
|
|
if labelText then
|
|
object.tooltip = "|cffffffff".. labelText .." "..regenRatePerSec.."|r";
|
|
end
|
|
object:SetLabelAndValue(labelText, regenRatePerSec);
|
|
end
|
|
|
|
function UpdateFunc:Crit(object)
|
|
if not Narci.refreshCombatRatings then return end;
|
|
local critChance, rating = GetEffectiveCrit();
|
|
|
|
object.tooltip = "|cffffffff".. STAT_CRITICAL_STRIKE .." "..format("%.2F%%", critChance).."|r";
|
|
local extraCritChance = GetCombatRatingBonus(rating);
|
|
local extraCritRating = GetCombatRating(rating);
|
|
object.tooltip4 = nil;
|
|
if (GetCritChanceProvidesParryEffect()) then
|
|
object.tooltip2 = format(CR_CRIT_PARRY_RATING_TOOLTIP, BreakUpLargeNumbers(extraCritRating), extraCritChance, GetCombatRatingBonusForCombatRatingValue(CR_PARRY, extraCritRating));
|
|
else
|
|
if extraCritChance == 0 then
|
|
object.tooltip2 = format(CR_CRIT_TOOLTIP, BreakUpLargeNumbers(extraCritRating), extraCritChance);
|
|
else
|
|
object.tooltip2 = NARCI_CRIT_TOOLTIP;
|
|
object.tooltip4 = {format(NARCI_CRIT_TOOLTIP_FORMAT, BreakUpLargeNumbers(extraCritRating), extraCritChance), floor( (extraCritRating / extraCritChance) * 100 + 0.5) / 100 .. " [+1%]"}
|
|
end
|
|
end
|
|
|
|
local PercentageText = format(DIGITS, critChance).."%"
|
|
object.Label:SetText(NARCI_CRITICAL_STRIKE); --COMBAT_RATING_NAME10
|
|
object.Value:SetText(PercentageText);
|
|
object.ValueRating:SetText(extraCritRating);
|
|
end
|
|
|
|
function UpdateFunc:Haste(object)
|
|
if not Narci.refreshCombatRatings then return end;
|
|
local unit = "player";
|
|
local haste = GetHaste();
|
|
local rating = CR_HASTE_MELEE;
|
|
local hasteFormatString;
|
|
|
|
if (haste < 0 and not GetPVPGearStatRules()) then
|
|
hasteFormatString = RED_FONT_COLOR_CODE.."%s".."|r";
|
|
else
|
|
hasteFormatString = "%s";
|
|
end
|
|
|
|
object.tooltip = "|cffffffff" .. STAT_HASTE .. " " .. format(hasteFormatString, format("%.2F%%", haste)) .. "|r";
|
|
|
|
local _, class = UnitClass(unit);
|
|
object.tooltip2 = _G["STAT_HASTE_"..class.."_TOOLTIP"];
|
|
if (not object.tooltip2) then
|
|
object.tooltip2 = STAT_HASTE_TOOLTIP;
|
|
end
|
|
|
|
local Rating = GetCombatRating(rating);
|
|
local RatingBonus = GetCombatRatingBonus(rating);
|
|
if RatingBonus == 0 then
|
|
object.tooltip2 = object.tooltip2 .. format(STAT_HASTE_BASE_TOOLTIP, BreakUpLargeNumbers(Rating), RatingBonus);
|
|
object.tooltip4 = nil;
|
|
else
|
|
object.tooltip4 = {format(NARCI_HASTE_TOOLTIP_FORMAT, BreakUpLargeNumbers(Rating), RatingBonus), floor( (Rating / RatingBonus) * 100 + 0.5) / 100 .. " [+1%]"};
|
|
end
|
|
|
|
local PercentageText = format(DIGITS, haste).."%"
|
|
object.Label:SetText(STAT_HASTE);
|
|
object.Value:SetText(PercentageText);
|
|
object.ValueRating:SetText(GetCombatRating(rating));
|
|
end
|
|
|
|
function UpdateFunc:Mastery(object)
|
|
if not Narci.refreshCombatRatings then return end;
|
|
object:SetScript("OnEnter", MasteryFrame_OnEnter);
|
|
|
|
local mastery = GetMasteryEffect();
|
|
local PercentageText = format(DIGITS, mastery).."%"
|
|
object.Label:SetText(STAT_MASTERY);
|
|
|
|
--[[
|
|
if (UnitLevel("player") < SHOW_MASTERY_LEVEL) then
|
|
object.numericValue = 0;
|
|
object.Value:SetText("N/A");
|
|
object.ValueRating:SetText("0");
|
|
object.Label:SetAlpha(NO_BONUS_ALPHA)
|
|
object.Value:SetAlpha(NO_BONUS_ALPHA)
|
|
object.ValueRating:SetAlpha(NO_BONUS_ALPHA)
|
|
return;
|
|
end
|
|
--]]
|
|
|
|
object.Value:SetText(PercentageText);
|
|
object.ValueRating:SetText(GetCombatRating(CR_MASTERY));
|
|
|
|
object.Label:SetAlpha(1)
|
|
object.Value:SetAlpha(1)
|
|
object.ValueRating:SetAlpha(1)
|
|
end
|
|
|
|
function UpdateFunc:Versatility(object)
|
|
if not Narci.refreshCombatRatings then return end;
|
|
local versatility = GetCombatRating(CR_VERSATILITY_DAMAGE_DONE);
|
|
local versatilityDamageBonus = GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_DONE) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_DONE);
|
|
local versatilityDamageTakenReduction = GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_TAKEN) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_TAKEN);
|
|
object.tooltip = "|cffffffff" .. format(VERSATILITY_TOOLTIP_FORMAT, STAT_VERSATILITY, versatilityDamageBonus, versatilityDamageTakenReduction) .. "|r";
|
|
|
|
if versatilityDamageBonus == 0 then
|
|
object.tooltip2 = format(CR_VERSATILITY_TOOLTIP, versatilityDamageBonus, versatilityDamageTakenReduction, BreakUpLargeNumbers(versatility), versatilityDamageBonus, versatilityDamageTakenReduction);
|
|
object.tooltip4 = nil;
|
|
else
|
|
object.tooltip2 = format(NARCI_VERSATILITY_TOOLTIP_FORMAT_1, versatilityDamageBonus, versatilityDamageTakenReduction);
|
|
object.tooltip4 = {format(NARCI_VERSATILITY_TOOLTIP_FORMAT_2, BreakUpLargeNumbers(versatility), versatilityDamageBonus, versatilityDamageTakenReduction) , floor( (versatility / versatilityDamageBonus) * 100 + 0.5) / 100 .. " [+1%/0.5%]"};
|
|
end
|
|
|
|
local PercentageText = format(DIGITS, versatilityDamageBonus).."%";
|
|
object.Label:SetText(STAT_VERSATILITY);
|
|
object.Value:SetText(PercentageText);
|
|
object.ValueRating:SetText(GetCombatRating(CR_VERSATILITY_DAMAGE_DONE));
|
|
end
|
|
|
|
function UpdateFunc:Leech(object)
|
|
local lifesteal = GetLifesteal();
|
|
|
|
object.tooltip = "|cffffffff" .. STAT_LIFESTEAL .. " " .. format("%.2F%%", lifesteal) .. "|r";
|
|
object.tooltip2 = format(CR_LIFESTEAL_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_LIFESTEAL)), GetCombatRatingBonus(CR_LIFESTEAL));
|
|
|
|
local PercentageText = format(DIGITS, lifesteal).."%";
|
|
object:SetLabelAndValue(STAT_LIFESTEAL, PercentageText, lifesteal == 0);
|
|
end
|
|
|
|
function UpdateFunc:Avoidance(object)
|
|
local avoidance = GetAvoidance();
|
|
|
|
object.tooltip = "|cffffffff" .. STAT_AVOIDANCE .. " " .. format("%.2F%%", avoidance) .. "|r";
|
|
object.tooltip2 = format(CR_AVOIDANCE_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_AVOIDANCE)), GetCombatRatingBonus(CR_AVOIDANCE));
|
|
|
|
local PercentageText = format(DIGITS, avoidance).."%";
|
|
object:SetLabelAndValue(STAT_AVOIDANCE, PercentageText, avoidance == 0);
|
|
end
|
|
|
|
function UpdateFunc:Speed(object)
|
|
local speed = GetSpeed();
|
|
|
|
object.tooltip = "|cffffffff" .. STAT_SPEED .. " " .. format("%.2F%%", speed) .. "|r";
|
|
object.tooltip2 = format(CR_SPEED_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_SPEED)), GetCombatRatingBonus(CR_SPEED));
|
|
|
|
local PercentageText = format(DIGITS, speed).."%";
|
|
object:SetLabelAndValue(STAT_SPEED, PercentageText, speed == 0);
|
|
end
|
|
|
|
function UpdateFunc:MovementSpeed(object)
|
|
local unit = "player";
|
|
|
|
object.wasSwimming = nil;
|
|
object.unit = unit;
|
|
object.t = 0;
|
|
MovementSpeed_OnUpdate(object, 1);
|
|
object:SetScript("OnEnter", MovementSpeed_OnEnter);
|
|
object:SetScript("OnUpdate", MovementSpeed_OnUpdate);
|
|
end
|
|
|
|
---------------------------------------------------------------------------
|
|
NarciAttributeMixin = {};
|
|
|
|
function NarciAttributeMixin:Update()
|
|
if UpdateFunc[self.token] then
|
|
UpdateFunc[self.token](nil, self);
|
|
end
|
|
end
|
|
|
|
function NarciAttributeMixin:SetLabelAndValue(label, value, grey)
|
|
self.Label:SetText(label);
|
|
self.Value:SetText(value);
|
|
if grey then
|
|
self.Label:SetTextColor(0.5, 0.5, 0.5);
|
|
self.Value:SetTextColor(0.5, 0.5, 0.5);
|
|
else
|
|
self.Label:SetTextColor(0.92, 0.92, 0.92);
|
|
self.Value:SetTextColor(0.92, 0.92, 0.92);
|
|
end
|
|
end
|