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

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