From 7ab6a4f56487effdfd63231325c74458f08dbb16 Mon Sep 17 00:00:00 2001 From: Spit <110714733+Otari98@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:08:30 +0300 Subject: [PATCH 01/39] Bunch of fixes and polish Replaced buggy ranged weapon slot check with more consistent one Added mana regen check (for non mana classes sets to N/A) Added total avoidance line in Defenses tab Added weapon skill in Ranged and Melee tabs Every stat now have a proper tooltip (fixed old ones, added many new ones) --- BetterCharacterStats.lua | 2700 ++++++++++++++++++++++++-------------- Localization.lua | 393 +++--- helper.lua | 4 +- 3 files changed, 1907 insertions(+), 1190 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index fb0adee..cad968a 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -1,1016 +1,1684 @@ -BCS = BCS or {} -BCSConfig = BCSConfig or {} - -local L, IndexLeft, IndexRight -L = BCS.L - -BCS.PLAYERSTAT_DROPDOWN_OPTIONS = { - "PLAYERSTAT_BASE_STATS", - "PLAYERSTAT_MELEE_COMBAT", - "PLAYERSTAT_RANGED_COMBAT", - "PLAYERSTAT_SPELL_COMBAT", - "PLAYERSTAT_SPELL_SCHOOLS", - "PLAYERSTAT_DEFENSES", -} - -BCS.MELEEHIT = { - ["ROGUE"] = { - 5, -- pvp - 8, -- yellow cap - 24.6, -- white cap - }, -} - -BCS.SPELLHIT = { - -- soon(tm) -} - -BCS.PaperDollFrame = PaperDollFrame - -BCS.Debug = false -BCS.DebugStack = {} - -function BCS:DebugTrace(start, limit) - BCS.Debug = nil - local length = getn(BCS.DebugStack) - if not start then start = 1 end - if start > length then start = length end - if not limit then limit = start + 30 end - - BCS:Print("length: " .. length) - BCS:Print("start: " .. start) - BCS:Print("limit: " .. limit) - - for i = start, length, 1 do - BCS:Print("[" .. i .. "] Event: " .. BCS.DebugStack[i].E) - BCS:Print(format( - "[%d] `- Arguments: %s, %s, %s, %s, %s", - i, - BCS.DebugStack[i].arg1, - BCS.DebugStack[i].arg2, - BCS.DebugStack[i].arg3, - BCS.DebugStack[i].arg4, - BCS.DebugStack[i].arg5 - )) - if i >= limit then i = length end - end - -end - -function BCS:Print(message) - ChatFrame2:AddMessage("[BCS] " .. message, 0.63, 0.86, 1.0) -end - -function BCS:OnLoad() - CharacterAttributesFrame:Hide() - PaperDollFrame:UnregisterEvent('UNIT_DAMAGE') - PaperDollFrame:UnregisterEvent('PLAYER_DAMAGE_DONE_MODS') - PaperDollFrame:UnregisterEvent('UNIT_ATTACK_SPEED') - PaperDollFrame:UnregisterEvent('UNIT_RANGEDDAMAGE') - PaperDollFrame:UnregisterEvent('UNIT_ATTACK') - PaperDollFrame:UnregisterEvent('UNIT_STATS') - PaperDollFrame:UnregisterEvent('UNIT_ATTACK_POWER') - PaperDollFrame:UnregisterEvent('UNIT_RANGED_ATTACK_POWER') - - self.Frame = BCSFrame - self.needUpdate = nil - - self.Frame:RegisterEvent("ADDON_LOADED") - self.Frame:RegisterEvent("UNIT_INVENTORY_CHANGED") -- fires when equipment changes - self.Frame:RegisterEvent("CHARACTER_POINTS_CHANGED") -- fires when learning talent - self.Frame:RegisterEvent("PLAYER_AURAS_CHANGED") -- buffs/warrior stances - - local _, classFileName = UnitClass("Player") - self.playerClass = strupper(classFileName) -end - -function BCS:OnEvent() - --[[if BCS.Debug then - local t = { - E = event, - arg1 = arg1 or "nil", - arg2 = arg2 or "nil", - arg3 = arg3 or "nil", - arg4 = arg4 or "nil", - arg5 = arg5 or "nil", - } - tinsert(BCS.DebugStack, t) - end]] - - if - event == "PLAYER_AURAS_CHANGED" or - event == "CHARACTER_POINTS_CHANGED" - then - if BCS.PaperDollFrame:IsVisible() then - BCS:UpdateStats() - else - BCS.needUpdate = true - end - elseif event == "UNIT_INVENTORY_CHANGED" and arg1 == "player" then - if BCS.PaperDollFrame:IsVisible() then - BCS:UpdateStats() - else - BCS.needUpdate = true - end - elseif event == "ADDON_LOADED" and arg1 == "BetterCharacterStats" then - IndexLeft = BCSConfig["DropdownLeft"] or BCS.PLAYERSTAT_DROPDOWN_OPTIONS[1] - IndexRight = BCSConfig["DropdownRight"] or BCS.PLAYERSTAT_DROPDOWN_OPTIONS[2] - - UIDropDownMenu_SetSelectedValue(PlayerStatFrameLeftDropDown, IndexLeft) - UIDropDownMenu_SetSelectedValue(PlayerStatFrameRightDropDown, IndexRight) - end -end - -function BCS:OnShow() - if BCS.needUpdate then - BCS.needUpdate = nil - BCS:UpdateStats() - end -end - --- debugging / profiling ---local avgV = {} ---local avg = 0 -function BCS:UpdateStats() - --[[if BCS.Debug then - local e = event or "nil" - BCS:Print("Update due to " .. e) - end - local beginTime = debugprofilestop()]] - - BCS:UpdatePaperdollStats("PlayerStatFrameLeft", IndexLeft) - BCS:UpdatePaperdollStats("PlayerStatFrameRight", IndexRight) - - --[[local timeUsed = debugprofilestop()-beginTime - table.insert(avgV, timeUsed) - avg = 0 - - for i,v in ipairs(avgV) do - avg = avg + v - end - avg = avg / getn(avgV) - - BCS:Print(format("Average: %d (%d results), Exact: %d", avg, getn(avgV), timeUsed))]] -end - -function BCS:SetStat(statFrame, statIndex) - local label = getglobal(statFrame:GetName().."Label") - local text = getglobal(statFrame:GetName().."StatText") - local stat - local effectiveStat - local posBuff - local negBuff - local statIndexTable = { - "STRENGTH", - "AGILITY", - "STAMINA", - "INTELLECT", - "SPIRIT", - } - - statFrame:SetScript("OnEnter", function() - PaperDollStatTooltip("player", statIndexTable[statIndex]) - end) - - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - - label:SetText(TEXT(getglobal("SPELL_STAT"..(statIndex-1).."_NAME"))..":") - stat, effectiveStat, posBuff, negBuff = UnitStat("player", statIndex) - - -- Set the tooltip text - local tooltipText = HIGHLIGHT_FONT_COLOR_CODE..getglobal("SPELL_STAT"..(statIndex-1).."_NAME").." " - - if ( ( posBuff == 0 ) and ( negBuff == 0 ) ) then - text:SetText(effectiveStat) - statFrame.tooltip = tooltipText..effectiveStat..FONT_COLOR_CODE_CLOSE - else - tooltipText = tooltipText..effectiveStat - if ( posBuff > 0 or negBuff < 0 ) then - tooltipText = tooltipText.." ("..(stat - posBuff - negBuff)..FONT_COLOR_CODE_CLOSE - end - if ( posBuff > 0 ) then - tooltipText = tooltipText..FONT_COLOR_CODE_CLOSE..GREEN_FONT_COLOR_CODE.."+"..posBuff..FONT_COLOR_CODE_CLOSE - end - if ( negBuff < 0 ) then - tooltipText = tooltipText..RED_FONT_COLOR_CODE.." "..negBuff..FONT_COLOR_CODE_CLOSE - end - if ( posBuff > 0 or negBuff < 0 ) then - tooltipText = tooltipText..HIGHLIGHT_FONT_COLOR_CODE..")"..FONT_COLOR_CODE_CLOSE - end - statFrame.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 ) then - text:SetText(RED_FONT_COLOR_CODE..effectiveStat..FONT_COLOR_CODE_CLOSE) - else - text:SetText(GREEN_FONT_COLOR_CODE..effectiveStat..FONT_COLOR_CODE_CLOSE) - end - end -end - -function BCS:SetArmor(statFrame) - - local base, effectiveArmor, armor, posBuff, negBuff = UnitArmor("player") - local totalBufs = posBuff + negBuff - local frame = statFrame - local label = getglobal(frame:GetName() .. "Label") - local text = getglobal(frame:GetName() .. "StatText") - - PaperDollFormatStat(ARMOR, base, posBuff, negBuff, frame, text) - label:SetText(TEXT(ARMOR_COLON)) - - local playerLevel = UnitLevel("player") - local armorReduction = effectiveArmor/((85 * playerLevel) + 400) - armorReduction = 100 * (armorReduction/(armorReduction + 1)) - - frame.tooltipSubtext = format(ARMOR_TOOLTIP, playerLevel, armorReduction) - - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - -end - -function BCS:SetDamage(statFrame) - local label = getglobal(statFrame:GetName() .. "Label") - label:SetText(TEXT(DAMAGE_COLON)) - local damageText = getglobal(statFrame:GetName() .. "StatText") - local damageFrame = statFrame - - damageFrame:SetScript("OnEnter", CharacterDamageFrame_OnEnter) - damageFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - - local speed, offhandSpeed = UnitAttackSpeed("player") - - local minDamage - local maxDamage - local minOffHandDamage - local maxOffHandDamage - local physicalBonusPos - local physicalBonusNeg - local percent - minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent = UnitDamage("player") - local displayMin = max(floor(minDamage),1) - local displayMax = max(ceil(maxDamage),1) - - 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) - local damagePerSecond = (max(fullDamage,1) / speed) - local damageTooltip = max(floor(minDamage),1).." - "..max(ceil(maxDamage),1) - - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - if ( totalBonus == 0 ) then - if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then - damageText:SetText(displayMin.." - "..displayMax) - else - damageText:SetText(displayMin.."-"..displayMax) - end - else - - local color - if ( totalBonus > 0 ) then - color = colorPos - else - color = colorNeg - end - if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then - damageText:SetText(color..displayMin.." - "..displayMax.."|r") - else - damageText:SetText(color..displayMin.."-"..displayMax.."|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 - damageFrame.damage = damageTooltip - damageFrame.attackSpeed = speed - damageFrame.dps = damagePerSecond - - -- If there's an offhand speed then add the offhand info to the tooltip - if ( offhandSpeed ) then - minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg - maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg - - local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5 - local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent - local offhandDamagePerSecond = (max(offhandFullDamage,1) / offhandSpeed) - local offhandDamageTooltip = max(floor(minOffHandDamage),1).." - "..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 - damageFrame.offhandDamage = offhandDamageTooltip - damageFrame.offhandAttackSpeed = offhandSpeed - damageFrame.offhandDps = offhandDamagePerSecond - else - damageFrame.offhandAttackSpeed = nil - end - -end - -function BCS:SetAttackSpeed(statFrame) - local speed, offhandSpeed = UnitAttackSpeed("player") - speed = format("%.2f", speed) - if ( offhandSpeed ) then - offhandSpeed = format("%.2f", offhandSpeed) - end - local text - if ( offhandSpeed ) then - text = speed.." / "..offhandSpeed - else - text = speed - end - - local label = getglobal(statFrame:GetName() .. "Label") - local value = getglobal(statFrame:GetName() .. "StatText") - - label:SetText(TEXT(SPEED)..":") - value:SetText(text) - - --[[statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..format(PAPERDOLLFRAME_TOOLTIP_FORMAT, ATTACK_SPEED).." "..text..FONT_COLOR_CODE_CLOSE; - statFrame.tooltip2 = format(CR_HASTE_RATING_TOOLTIP, GetCombatRating(CR_HASTE_MELEE), GetCombatRatingBonus(CR_HASTE_MELEE));]] - - statFrame:Show() -end - -function BCS:SetAttackPower(statFrame) - local base, posBuff, negBuff = UnitAttackPower("player") - - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(TEXT(ATTACK_POWER_COLON)) - - PaperDollFormatStat(MELEE_ATTACK_POWER, base, posBuff, negBuff, frame, text) - frame.tooltipSubtext = format(MELEE_ATTACK_POWER_TOOLTIP, max((base+posBuff+negBuff), 0)/ATTACK_POWER_MAGIC_NUMBER) -end - -function BCS:SetSpellPower(statFrame, school) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - - if school then - label:SetText(L["SPELL_SCHOOL_"..strupper(school)]) - local base = BCS:GetSpellPower() - local fromSchool = BCS:GetSpellPower(school) - local output = base + fromSchool - - if fromSchool > 0 then - output = colorPos .. output .. "|r" - end - - text:SetText(output) - else - local power, secondaryPower, secondaryName = BCS:GetSpellPower() - - label:SetText(L.SPELL_POWER_COLON) - text:SetText(power+secondaryPower) - - if secondaryPower > 0 then - frame.tooltip = format(L.SPELL_POWER_SECONDARY_TOOLTIP, (power+secondaryPower), power, secondaryPower, secondaryName) - - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - end - - end -end - -function BCS:SetRating(statFrame, ratingType) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(L.MELEE_HIT_RATING_COLON) - - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - - if ratingType == "MELEE" then - local rating = BCS:GetHitRating() - if BCS.MELEEHIT[BCS.playerClass] then - if rating < BCS.MELEEHIT[BCS.playerClass][1] then - rating = colorNeg .. rating .. "%|r" - elseif rating >= BCS.MELEEHIT[BCS.playerClass][2] then - rating = colorPos .. rating .. "%|r" - else - rating = rating .. "%" - end - else - rating = rating .. "%" - end - text:SetText(rating) - - frame.tooltip = L.MELEE_HIT_TOOLTIP - if L[BCS.playerClass .. "_MELEE_HIT_TOOLTIP"] then - frame.tooltipSubtext = L[BCS.playerClass .. "_MELEE_HIT_TOOLTIP"] - end - elseif ratingType == "RANGED" then - local rating = BCS:GetRangedHitRating() - if BCS.MELEEHIT[BCS.playerClass] then - if rating < BCS.MELEEHIT[BCS.playerClass][1] then - rating = colorNeg .. rating .. "%|r" - elseif rating >= BCS.MELEEHIT[BCS.playerClass][2] then - rating = colorPos .. rating .. "%|r" - else - rating = rating .. "%" - end - else - rating = rating .. "%" - end - text:SetText(rating) - - frame.tooltip = L.MELEE_HIT_TOOLTIP - if L[BCS.playerClass .. "_MELEE_HIT_TOOLTIP"] then - frame.tooltipSubtext = L[BCS.playerClass .. "_MELEE_HIT_TOOLTIP"] - end - elseif ratingType == "SPELL" then - local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow = BCS:GetSpellHitRating() - --[[if BCS.SPELLHIT[BCS.playerClass] then - if spell_hit < BCS.SPELLHIT[BCS.playerClass][1] then - spell_hit = colorNeg .. spell_hit .. "%|r" - elseif spell_hit >= BCS.SPELLHIT[BCS.playerClass][2] then - spell_hit = colorPos .. spell_hit .. "%|r" - else - spell_hit = spell_hit .. "%" - end - else - spell_hit = spell_hit .. "%" - end]] - - if spell_hit_fire > 0 or spell_hit_frost > 0 or spell_hit_arcane > 0 or spell_hit_shadow > 0 then - -- got spell hit from talents - local spell_hit_other, spell_hit_other_type - - spell_hit_other = 0 - spell_hit_other_type = "" - - if spell_hit_fire > spell_hit_other then - spell_hit_other = spell_hit_fire - spell_hit_other_type = L.SPELL_SCHOOL_FIRE - end - if spell_hit_frost > spell_hit_other then - spell_hit_other = spell_hit_frost - spell_hit_other_type = L.SPELL_SCHOOL_FROST - end - if spell_hit_arcane > spell_hit_other then - spell_hit_other = spell_hit_arcane - spell_hit_other_type = L.SPELL_SCHOOL_ARCANE - end - if spell_hit_shadow > spell_hit_other then - spell_hit_other = spell_hit_shadow - spell_hit_other_type = L.SPELL_SCHOOL_SHADOW - end - - frame.tooltip = format(L.SPELL_HIT_SECONDARY_TOOLTIP, spell_hit+spell_hit_other, spell_hit, spell_hit_other, spell_hit_other_type) - text:SetText(spell_hit+spell_hit_other.."%") - else - frame.tooltip = L.SPELL_HIT_TOOLTIP - text:SetText(spell_hit.."%") - end - - -- class specific tooltip - if L[BCS.playerClass .. "_SPELL_HIT_TOOLTIP"] then - frame.tooltipSubtext = L[BCS.playerClass .. "_SPELL_HIT_TOOLTIP"] - end - end - - if frame.tooltip then - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - end - -end - -function BCS:SetMeleeCritChance(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(L.MELEE_CRIT_COLON) - text:SetText(format("%.2f%%", BCS:GetCritChance())) -end - -function BCS:SetSpellCritChance(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(L.SPELL_CRIT_COLON) - text:SetText(format("%.2f%%", BCS:GetSpellCritChance())) -end - -function BCS:SetRangedCritChance(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(L.RANGED_CRIT_COLON) - text:SetText(format("%.2f%%", BCS:GetRangedCritChance())) -end - -function BCS:SetHealing(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - local power,_,_,dmg = BCS:GetSpellPower() - local heal = BCS:GetHealingPower() - - power = power-dmg - - label:SetText(L.HEAL_POWER_COLON) - text:SetText(power+heal) - - frame.tooltip = format(L.SPELL_HEALING_POWER_TOOLTIP, (power+heal), power, heal) - - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -end - -function BCS:SetManaRegen(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - local base, casting, mp5 = BCS:GetManaRegen() - local mp2 = mp5*0.4 - local totalRegen = base + mp2 - local totalRegenWhileCasting = (casting/100)*base + mp2 - - label:SetText(L.MANA_REGEN_COLON) - text:SetText(format("%d |cffBF40BF(%d)|r", totalRegen, totalRegenWhileCasting)) - - frame.tooltip = format(L.SPELL_MANA_REGEN_TOOLTIP, totalRegen, totalRegenWhileCasting, base, casting, mp5, mp2) - - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -end - -function BCS:SetDodge(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(L.DODGE_COLON) - text:SetText(format("%.2f%%", GetDodgeChance())) -end - -function BCS:SetParry(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(L.PARRY_COLON) - text:SetText(format("%.2f%%", GetParryChance())) -end - -function BCS:SetBlock(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(L.BLOCK_COLON) - text:SetText(format("%.2f%%", GetBlockChance())) -end - -function BCS:SetDefense(statFrame) - local base, modifier = UnitDefense("player") - - local frame = statFrame - local label = getglobal(statFrame:GetName() .. "Label") - local text = getglobal(statFrame:GetName() .. "StatText") - - label:SetText(TEXT(DEFENSE_COLON)) - - local posBuff = 0 - local negBuff = 0 - if ( modifier > 0 ) then - posBuff = modifier - elseif ( modifier < 0 ) then - negBuff = modifier - end - PaperDollFormatStat(DEFENSE_COLON, base, posBuff, negBuff, frame, text) -end - -function BCS:SetRangedDamage(statFrame) - local label = getglobal(statFrame:GetName() .. "Label") - local damageText = getglobal(statFrame:GetName() .. "StatText") - local damageFrame = statFrame - - label:SetText(TEXT(DAMAGE_COLON)) - - damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) - damageFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - - -- If no ranged attack then set to n/a - if ( PaperDollFrame.noRanged ) then - damageText:SetText(NOT_APPLICABLE) - damageFrame.damage = nil - return - end - - local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") - local displayMin = max(floor(minDamage),1) - local displayMax = max(ceil(maxDamage),1) - - 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) - local damagePerSecond = (max(fullDamage,1) / rangedAttackSpeed) - local tooltip = max(floor(minDamage),1).." - "..max(ceil(maxDamage),1) - - if ( totalBonus == 0 ) then - if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then - damageText:SetText(displayMin.." - "..displayMax) - else - damageText:SetText(displayMin.."-"..displayMax) - end - else - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - local color - if ( totalBonus > 0 ) then - color = colorPos - else - color = colorNeg - end - if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then - damageText:SetText(color..displayMin.." - "..displayMax.."|r") - else - damageText:SetText(color..displayMin.."-"..displayMax.."|r") - end - if ( physicalBonusPos > 0 ) then - tooltip = tooltip..colorPos.." +"..physicalBonusPos.."|r" - end - if ( physicalBonusNeg < 0 ) then - tooltip = tooltip..colorNeg.." "..physicalBonusNeg.."|r" - end - if ( percent > 1 ) then - tooltip = tooltip..colorPos.." x"..floor(percent*100+0.5).."%|r" - elseif ( percent < 1 ) then - tooltip = tooltip..colorNeg.." x"..floor(percent*100+0.5).."%|r" - end - damageFrame.tooltip = tooltip.." "..format(TEXT(DPS_TEMPLATE), damagePerSecond) - end - damageFrame.attackSpeed = rangedAttackSpeed - damageFrame.damage = tooltip - damageFrame.dps = damagePerSecond -end - -function BCS:SetRangedAttackSpeed(startFrame) - local label = getglobal(startFrame:GetName() .. "Label") - local damageText = getglobal(startFrame:GetName() .. "StatText") - local damageFrame = startFrame - - label:SetText(TEXT(SPEED)..":") - - -- If no ranged attack then set to n/a - if ( PaperDollFrame.noRanged ) then - damageText:SetText(NOT_APPLICABLE) - damageFrame.damage = nil - return - end - - local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") - local displayMin = max(floor(minDamage),1) - local displayMax = max(ceil(maxDamage),1) - - 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) - local damagePerSecond = (max(fullDamage,1) / rangedAttackSpeed) - local tooltip = max(floor(minDamage),1).." - "..max(ceil(maxDamage),1) - - if ( totalBonus == 0 ) then - if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then - damageText:SetText(displayMin.." - "..displayMax) - else - damageText:SetText(displayMin.."-"..displayMax) - end - else - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - local color - if ( totalBonus > 0 ) then - color = colorPos - else - color = colorNeg - end - if ( ( displayMin < 100 ) and ( displayMax < 100 ) ) then - damageText:SetText(color..displayMin.." - "..displayMax.."|r") - else - damageText:SetText(color..displayMin.."-"..displayMax.."|r") - end - if ( physicalBonusPos > 0 ) then - tooltip = tooltip..colorPos.." +"..physicalBonusPos.."|r" - end - if ( physicalBonusNeg < 0 ) then - tooltip = tooltip..colorNeg.." "..physicalBonusNeg.."|r" - end - if ( percent > 1 ) then - tooltip = tooltip..colorPos.." x"..floor(percent*100+0.5).."%|r" - elseif ( percent < 1 ) then - tooltip = tooltip..colorNeg.." x"..floor(percent*100+0.5).."%|r" - end - damageFrame.tooltip = tooltip.." "..format(TEXT(DPS_TEMPLATE), damagePerSecond) - end - - damageText:SetText(format("%.2f", rangedAttackSpeed)) - - damageFrame.attackSpeed = rangedAttackSpeed - damageFrame.damage = tooltip - damageFrame.dps = damagePerSecond -end - -function BCS:SetRangedAttackPower(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - - label:SetText(TEXT(ATTACK_POWER_COLON)) - - -- If no ranged attack then set to n/a - if ( PaperDollFrame.noRanged ) then - text:SetText(NOT_APPLICABLE) - frame.tooltip = nil - return - end - if ( HasWandEquipped() ) then - text:SetText("--") - frame.tooltip = nil - return - end - - local base, posBuff, negBuff = UnitRangedAttackPower("player") - PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, frame, text) - frame.tooltipSubtext = format(RANGED_ATTACK_POWER_TOOLTIP, base/ATTACK_POWER_MAGIC_NUMBER) -end - -function BCS:UpdatePaperdollStats(prefix, index) - local stat1 = getglobal(prefix..1) - local stat2 = getglobal(prefix..2) - local stat3 = getglobal(prefix..3) - local stat4 = getglobal(prefix..4) - local stat5 = getglobal(prefix..5) - local stat6 = getglobal(prefix..6) - - stat1:SetScript("OnEnter", nil) - stat2:SetScript("OnEnter", nil) - stat3:SetScript("OnEnter", nil) - stat4:SetScript("OnEnter", nil) - stat4:SetScript("OnEnter", nil) - stat5:SetScript("OnEnter", nil) - stat6:SetScript("OnEnter", nil) - - stat1.tooltip = nil - stat2.tooltip = nil - stat3.tooltip = nil - stat4.tooltip = nil - stat4.tooltip = nil - stat5.tooltip = nil - stat6.tooltip = nil - - stat4:Show() - stat5:Show() - stat6:Show() - - if ( index == "PLAYERSTAT_BASE_STATS" ) then - BCS:SetStat(stat1, 1) - BCS:SetStat(stat2, 2) - BCS:SetStat(stat3, 3) - BCS:SetStat(stat4, 4) - BCS:SetStat(stat5, 5) - BCS:SetArmor(stat6) - elseif ( index == "PLAYERSTAT_MELEE_COMBAT" ) then - BCS:SetDamage(stat1) - BCS:SetAttackSpeed(stat2) - BCS:SetAttackPower(stat3) - BCS:SetRating(stat4, "MELEE") - BCS:SetMeleeCritChance(stat5) - stat6:Hide() - elseif ( index == "PLAYERSTAT_RANGED_COMBAT" ) then - BCS:SetRangedDamage(stat1) - BCS:SetRangedAttackSpeed(stat2) - BCS:SetRangedAttackPower(stat3) - BCS:SetRating(stat4, "RANGED") - BCS:SetRangedCritChance(stat5) - stat6:Hide() - elseif ( index == "PLAYERSTAT_SPELL_COMBAT" ) then - BCS:SetSpellPower(stat1) - BCS:SetRating(stat2, "SPELL") - BCS:SetSpellCritChance(stat3) - BCS:SetHealing(stat4) - BCS:SetManaRegen(stat5) - stat6:Hide() - elseif ( index == "PLAYERSTAT_SPELL_SCHOOLS" ) then - BCS:SetSpellPower(stat1, "Arcane") - BCS:SetSpellPower(stat2, "Fire") - BCS:SetSpellPower(stat3, "Frost") - BCS:SetSpellPower(stat4, "Holy") - BCS:SetSpellPower(stat5, "Nature") - BCS:SetSpellPower(stat6, "Shadow") - elseif ( index == "PLAYERSTAT_DEFENSES" ) then - BCS:SetArmor(stat1) - BCS:SetDefense(stat2) - BCS:SetDodge(stat3) - BCS:SetParry(stat4) - BCS:SetBlock(stat5) - stat6:Hide() - end -end - -local function PlayerStatFrameLeftDropDown_OnClick() - UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) - IndexLeft = this.value - BCSConfig["DropdownLeft"] = IndexLeft - BCS:UpdatePaperdollStats("PlayerStatFrameLeft", this.value) -end - -local function PlayerStatFrameRightDropDown_OnClick() - UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) - IndexRight = this.value - BCSConfig["DropdownRight"] = IndexRight - BCS:UpdatePaperdollStats("PlayerStatFrameRight", this.value) -end - -local function PlayerStatFrameLeftDropDown_Initialize() - local info = {} - local checked = nil - for i=1, getn(BCS.PLAYERSTAT_DROPDOWN_OPTIONS) do - info.text = BCS.L[BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i]] - info.func = PlayerStatFrameLeftDropDown_OnClick - info.value = BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i] - info.checked = checked - info.owner = UIDROPDOWNMENU_OPEN_MENU - UIDropDownMenu_AddButton(info) - end -end - -local function PlayerStatFrameRightDropDown_Initialize() - local info = {} - local checked = nil - for i=1, getn(BCS.PLAYERSTAT_DROPDOWN_OPTIONS) do - info.text = BCS.L[BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i]] - info.func = PlayerStatFrameRightDropDown_OnClick - info.value = BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i] - info.checked = checked - info.owner = UIDROPDOWNMENU_OPEN_MENU - UIDropDownMenu_AddButton(info) - end -end - -function PlayerStatFrameLeftDropDown_OnLoad() - RaiseFrameLevel(this) - RaiseFrameLevel(getglobal(this:GetName() .. "Button")) - UIDropDownMenu_Initialize(this, PlayerStatFrameLeftDropDown_Initialize) - UIDropDownMenu_SetWidth(99, this) - UIDropDownMenu_JustifyText("LEFT") -end - -function PlayerStatFrameRightDropDown_OnLoad() - RaiseFrameLevel(this) - RaiseFrameLevel(getglobal(this:GetName() .. "Button")) - UIDropDownMenu_Initialize(this, PlayerStatFrameRightDropDown_Initialize) - UIDropDownMenu_SetWidth(99, this) - UIDropDownMenu_JustifyText("LEFT") -end - ---pfUI.api.strsplit -function hcstrsplit(delimiter, subject) - if not subject then return nil end - local delimiter, fields = delimiter or ":", {} - local pattern = string.format("([^%s]+)", delimiter) - string.gsub(subject, pattern, function(c) fields[table.getn(fields)+1] = c end) - return unpack(fields) -end - ---Update announcing code taken from pfUI -local major, minor, fix = hcstrsplit(".", tostring(GetAddOnMetadata("BetterCharacterStats", "Version"))) - -local alreadyshown = false -local localversion = tonumber(major*10000 + minor*100 + fix) -local remoteversion = tonumber(bcsupdateavailable) or 0 -local loginchannels = { "BATTLEGROUND", "RAID", "GUILD", "PARTY" } -local groupchannels = { "BATTLEGROUND", "RAID", "PARTY" } - -bcsupdater = CreateFrame("Frame") -bcsupdater:RegisterEvent("CHAT_MSG_ADDON") -bcsupdater:RegisterEvent("PLAYER_ENTERING_WORLD") -bcsupdater:RegisterEvent("PARTY_MEMBERS_CHANGED") -bcsupdater:SetScript("OnEvent", function() - if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then - local v, remoteversion = hcstrsplit(":", arg2) - local remoteversion = tonumber(remoteversion) - if v == "VERSION" and remoteversion then - if remoteversion > localversion then - bcsupdateavailable = remoteversion - if not alreadyshown then - DEFAULT_CHAT_FRAME:AddMessage("|cffffffffBetterCharacterStats|r New version available! https://github.com/Lexiebean/BetterCharacterStats") - alreadyshown = true - end - end - end - --This is a little check that I can use to see if people are actually using the addon. - if v == "PING?" then - for _, chan in pairs(loginchannels) do - SendAddonMessage("bcs", "PONG!:"..GetAddOnMetadata("BetterCharacterStats", "Version"), chan) - end - end - if v == "PONG!" then - --print(arg1 .." "..arg2.." "..arg3.." "..arg4) - end - end - - if event == "PARTY_MEMBERS_CHANGED" then - local groupsize = GetNumRaidMembers() > 0 and GetNumRaidMembers() or GetNumPartyMembers() > 0 and GetNumPartyMembers() or 0 - if ( this.group or 0 ) < groupsize then - for _, chan in pairs(groupchannels) do - SendAddonMessage("bcs", "VERSION:" .. localversion, chan) - end - end - this.group = groupsize - end - - if event == "PLAYER_ENTERING_WORLD" then - if not alreadyshown and localversion < remoteversion then - DEFAULT_CHAT_FRAME:AddMessage("|cffffffffBetterCharacterStats|r New version available! https://github.com/Lexiebean/BetterCharacterStats") - bcsupdateavailable = localversion - alreadyshown = true - end - - for _, chan in pairs(loginchannels) do - SendAddonMessage("bcs", "VERSION:" .. localversion, chan) - end - end - end) \ No newline at end of file +BCS = BCS or {} +BCSConfig = BCSConfig or {} + +local L, IndexLeft, IndexRight +L = BCS.L + +BCS.PLAYERSTAT_DROPDOWN_OPTIONS = { + "PLAYERSTAT_BASE_STATS", + "PLAYERSTAT_MELEE_COMBAT", + --"PLAYERSTAT_MELEE_BOSS", + "PLAYERSTAT_RANGED_COMBAT", + "PLAYERSTAT_SPELL_COMBAT", + "PLAYERSTAT_SPELL_SCHOOLS", + "PLAYERSTAT_DEFENSES", +} + +BCS.MELEEHIT = { + ["ROGUE"] = { + 5, -- pvp + 8, -- yellow cap + 24.6, -- white cap + }, +} + +BCS.SPELLHIT = { + -- soon(tm) +} + +BCS.PaperDollFrame = PaperDollFrame + +BCS.Debug = false +BCS.DebugStack = {} + +function BCS:DebugTrace(start, limit) + BCS.Debug = nil + local length = getn(BCS.DebugStack) + if not start then + start = 1 + end + if start > length then + start = length + end + if not limit then + limit = start + 30 + end + + BCS:Print("length: " .. length) + BCS:Print("start: " .. start) + BCS:Print("limit: " .. limit) + + for i = start, length, 1 do + BCS:Print("[" .. i .. "] Event: " .. BCS.DebugStack[i].E) + BCS:Print(format( + "[%d] `- Arguments: %s, %s, %s, %s, %s", + i, + BCS.DebugStack[i].arg1, + BCS.DebugStack[i].arg2, + BCS.DebugStack[i].arg3, + BCS.DebugStack[i].arg4, + BCS.DebugStack[i].arg5 + )) + if i >= limit then + i = length + end + end + +end + +function BCS:Print(message) + ChatFrame2:AddMessage("[BCS] " .. message, 0.63, 0.86, 1.0) +end + +function BCS:OnLoad() + CharacterAttributesFrame:Hide() + PaperDollFrame:UnregisterEvent('UNIT_DAMAGE') + PaperDollFrame:UnregisterEvent('PLAYER_DAMAGE_DONE_MODS') + PaperDollFrame:UnregisterEvent('UNIT_ATTACK_SPEED') + PaperDollFrame:UnregisterEvent('UNIT_RANGEDDAMAGE') + PaperDollFrame:UnregisterEvent('UNIT_ATTACK') + PaperDollFrame:UnregisterEvent('UNIT_STATS') + PaperDollFrame:UnregisterEvent('UNIT_ATTACK_POWER') + PaperDollFrame:UnregisterEvent('UNIT_RANGED_ATTACK_POWER') + + self.Frame = BCSFrame + self.needUpdate = nil + + self.Frame:RegisterEvent("ADDON_LOADED") + self.Frame:RegisterEvent("UNIT_INVENTORY_CHANGED") -- fires when equipment changes + self.Frame:RegisterEvent("CHARACTER_POINTS_CHANGED") -- fires when learning talent + self.Frame:RegisterEvent("PLAYER_AURAS_CHANGED") -- buffs/warrior stances + + local _, classFileName = UnitClass("Player") + self.playerClass = strupper(classFileName) +end + +function BCS:OnEvent() + --[[if BCS.Debug then + local t = { + E = event, + arg1 = arg1 or "nil", + arg2 = arg2 or "nil", + arg3 = arg3 or "nil", + arg4 = arg4 or "nil", + arg5 = arg5 or "nil", + } + tinsert(BCS.DebugStack, t) + end]] + + if + event == "PLAYER_AURAS_CHANGED" or + event == "CHARACTER_POINTS_CHANGED" + then + if BCS.PaperDollFrame:IsVisible() then + BCS:UpdateStats() + else + BCS.needUpdate = true + end + elseif event == "UNIT_INVENTORY_CHANGED" and arg1 == "player" then + if BCS.PaperDollFrame:IsVisible() then + BCS:UpdateStats() + else + BCS.needUpdate = true + end + elseif event == "ADDON_LOADED" and arg1 == "BetterCharacterStats" then + IndexLeft = BCSConfig["DropdownLeft"] or BCS.PLAYERSTAT_DROPDOWN_OPTIONS[1] + IndexRight = BCSConfig["DropdownRight"] or BCS.PLAYERSTAT_DROPDOWN_OPTIONS[2] + + UIDropDownMenu_SetSelectedValue(PlayerStatFrameLeftDropDown, IndexLeft) + UIDropDownMenu_SetSelectedValue(PlayerStatFrameRightDropDown, IndexRight) + end +end + +function BCS:OnShow() + if BCS.needUpdate then + BCS.needUpdate = nil + BCS:UpdateStats() + end +end + +-- debugging / profiling +--local avgV = {} +--local avg = 0 +function BCS:UpdateStats() + --[[if BCS.Debug then + local e = event or "nil" + BCS:Print("Update due to " .. e) + end + local beginTime = debugprofilestop()]] + + BCS:UpdatePaperdollStats("PlayerStatFrameLeft", IndexLeft) + BCS:UpdatePaperdollStats("PlayerStatFrameRight", IndexRight) + + --[[local timeUsed = debugprofilestop()-beginTime + table.insert(avgV, timeUsed) + avg = 0 + + for i,v in ipairs(avgV) do + avg = avg + v + end + avg = avg / getn(avgV) + + BCS:Print(format("Average: %d (%d results), Exact: %d", avg, getn(avgV), timeUsed))]] +end + +function BCS:SetStat(statFrame, statIndex) + local label = getglobal(statFrame:GetName() .. "Label") + local text = getglobal(statFrame:GetName() .. "StatText") + local stat + local effectiveStat + local posBuff + local negBuff + local statIndexTable = { + "STRENGTH", + "AGILITY", + "STAMINA", + "INTELLECT", + "SPIRIT", + } + + statFrame:SetScript("OnEnter", function() + PaperDollStatTooltip("player", statIndexTable[statIndex]) + end) + + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + + label:SetText(TEXT(getglobal("SPELL_STAT" .. (statIndex - 1) .. "_NAME")) .. ":") + stat, effectiveStat, posBuff, negBuff = UnitStat("player", statIndex) + + -- Set the tooltip text + local tooltipText = HIGHLIGHT_FONT_COLOR_CODE .. getglobal("SPELL_STAT" .. (statIndex - 1) .. "_NAME") .. " " + + if ((posBuff == 0) and (negBuff == 0)) then + text:SetText(effectiveStat) + statFrame.tooltip = tooltipText .. effectiveStat .. FONT_COLOR_CODE_CLOSE + else + tooltipText = tooltipText .. effectiveStat + if (posBuff > 0 or negBuff < 0) then + tooltipText = tooltipText .. " (" .. (stat - posBuff - negBuff) .. FONT_COLOR_CODE_CLOSE + end + if (posBuff > 0) then + tooltipText = tooltipText .. FONT_COLOR_CODE_CLOSE .. GREEN_FONT_COLOR_CODE .. "+" .. posBuff .. FONT_COLOR_CODE_CLOSE + end + if (negBuff < 0) then + tooltipText = tooltipText .. RED_FONT_COLOR_CODE .. " " .. negBuff .. FONT_COLOR_CODE_CLOSE + end + if (posBuff > 0 or negBuff < 0) then + tooltipText = tooltipText .. HIGHLIGHT_FONT_COLOR_CODE .. ")" .. FONT_COLOR_CODE_CLOSE + end + statFrame.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) then + text:SetText(RED_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) + else + text:SetText(GREEN_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) + end + end +end + +function BCS:SetArmor(statFrame) + + local base, effectiveArmor, armor, posBuff, negBuff = UnitArmor("player") + local totalBufs = posBuff + negBuff + local frame = statFrame + local label = getglobal(frame:GetName() .. "Label") + local text = getglobal(frame:GetName() .. "StatText") + + PaperDollFormatStat(ARMOR, base, posBuff, negBuff, frame, text) + label:SetText(TEXT(ARMOR_COLON)) + + local playerLevel = UnitLevel("player") + local armorReduction = effectiveArmor / ((85 * playerLevel) + 400) + armorReduction = 100 * (armorReduction / (armorReduction + 1)) + + frame.tooltipSubtext = format(ARMOR_TOOLTIP, playerLevel, armorReduction) + + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:GetSlotItemId(slot) + local _, _, id = string.find(GetInventoryItemLink("player", GetInventorySlotInfo(slot)) or "", "item:(%d+):%d+:%d+:%d+"); + if id then + return tonumber(id) + else + return 0 + end +end + +function BCS:GetGlovesItemId() + return BCS:GetSlotItemId("HandsSlot") +end + +function BCS:GetHeadItemId() + return BCS:GetSlotItemId("HeadSlot") +end + +function BCS:GetNeckItemId() + return BCS:GetSlotItemId("NeckSlot") +end + +function BCS:GetWaistItemId() + return BCS:GetSlotItemId("WaistSlot") +end + +function BCS:GetShoulderItemId() + return BCS:GetSlotItemId("ShoulderSlot") +end + +function BCS:GetChestItemId() + return BCS:GetSlotItemId("ChestSlot") +end + +function BCS:GetLegsItemId() + return BCS:GetSlotItemId("LegsSlot") +end + +function BCS:GetFeetItemId() + return BCS:GetSlotItemId("FeetSlot") +end + +function BCS:GetMainHandItemId() + return BCS:GetSlotItemId("MainHandSlot") +end + +function BCS:GetOffHandItemId() + return BCS:GetSlotItemId("SecondaryHandSlot") +end + +function BCS:GetWeaponSkill(skillName) + -- loop through skills + local skillIndex = 1 + while true do + local name, isHeader, isExpanded, skillRank, numTempPoints, skillModifier, + skillMaxRank, isAbandonable, stepCost, rankCost, minLevel, skillCostType, + skillDescription = GetSkillLineInfo(skillIndex) + if not name then + return 0 + end + + if name == skillName then + return skillRank + skillModifier + end + + skillIndex = skillIndex + 1 + end +end + +function BCS:GetWeaponSkillForWeaponType(weaponType) + if weaponType == "Daggers" then + return BCS:GetWeaponSkill("Daggers") + elseif weaponType == "One-Handed Swords" then + return BCS:GetWeaponSkill("Swords") + elseif weaponType == "Two-Handed Swords" then + return BCS:GetWeaponSkill("Two-Handed Swords") + elseif weaponType == "One-Handed Axes" then + return BCS:GetWeaponSkill("Axes") + elseif weaponType == "Two-Handed Axes" then + return BCS:GetWeaponSkill("Two-Handed Axes") + elseif weaponType == "One-Handed Maces" then + return BCS:GetWeaponSkill("Maces") + elseif weaponType == "Two-Handed Maces" then + return BCS:GetWeaponSkill("Two-Handed Maces") + elseif weaponType == "Fist Weapons" then + return BCS:GetWeaponSkill("Unarmed") + elseif weaponType == "Bows" then + return BCS:GetWeaponSkill("Bows") + elseif weaponType == "Crossbows" then + return BCS:GetWeaponSkill("Crossbows") + elseif weaponType == "Guns" then + return BCS:GetWeaponSkill("Guns") + elseif weaponType == "Thrown" then + return BCS:GetWeaponSkill("Thrown") + elseif weaponType == "Wands" then + return BCS:GetWeaponSkill("Wands") + end + + return 0 +end + +function BCS:GetItemInfoForSlot(slot) + local _, _, id = string.find(GetInventoryItemLink("player", GetInventorySlotInfo(slot)) or "", "(item:%d+:%d+:%d+:%d+)"); + if not id then + return + end + + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(id); + + return itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice; +end + +function BCS:GetMHWeaponSkill() + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("MainHandSlot") + + return BCS:GetWeaponSkillForWeaponType(itemType) +end + +function BCS:GetOHWeaponSkill() + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("SecondaryHandSlot") + + return BCS:GetWeaponSkillForWeaponType(itemType) +end + +function BCS:GetRangedWeaponSkill() + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("RangedSlot") + + return BCS:GetWeaponSkillForWeaponType(itemType) +end + +function BCS:GetMissChanceRaw(wepSkill) + local diff = wepSkill - 315 + local miss = 5 + + if diff < -10 then + miss = miss - diff * 0.2; + else + miss = miss - diff * 0.1; + end + + local hitChance = BCS:GetHitRating() + -- if skill diff < -10 then subtract one from +hit, if there is any +hit + if (diff < -10) and (hitChance > 0) then + hitChance = hitChance - 1 + end + miss = miss - hitChance + + return miss +end + +function BCS:GetMissChance(wepSkill) + return max(0, min(BCS:GetMissChanceRaw(wepSkill),60)) +end + +function BCS:GetDualWieldMissChance(wepSkill) + return max(0,min(BCS:GetMissChanceRaw(wepSkill)+19,60)) +end + +function BCS:GetGlanceChance(wepSkill) + return 10 + 15 * 2; +end + +function BCS:GetGlanceReduction(wepSkill) + local diff = 315 - wepSkill; + local low = math.max(math.min(1.3 - 0.05 * diff, 0.91), 0.01); + local high = math.max(math.min(1.2 - 0.03 * diff, 0.99), 0.2); + return 100 * ((high - low) / 2 + low); +end + +function BCS:GetDodgeChance(wepSkill) + return math.max(5 + (315 - wepSkill) * 0.1, 0); +end + +function BCS:GetDualWieldCritCap(wepSkill) + return 100 - self:GetDualWieldMissChance(wepSkill) - self:GetGlanceChance(wepSkill) - self:GetDodgeChance(wepSkill); +end + +function BCS:GetCritCap(wepSkill) + return 100 - self:GetMissChance(wepSkill) - self:GetGlanceChance(wepSkill) - self:GetDodgeChance(wepSkill); +end + +function BCS:SetDamage(statFrame) + local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(TEXT(DAMAGE_COLON)) + local damageText = getglobal(statFrame:GetName() .. "StatText") + local damageFrame = statFrame + + damageFrame:SetScript("OnEnter", CharacterDamageFrame_OnEnter) + damageFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + + local speed, offhandSpeed = UnitAttackSpeed("player") + + local minDamage + local maxDamage + local minOffHandDamage + local maxOffHandDamage + local physicalBonusPos + local physicalBonusNeg + local percent + minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent = UnitDamage("player") + local displayMin = max(floor(minDamage), 1) + local displayMax = max(ceil(maxDamage), 1) + + 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) + local damagePerSecond = (max(fullDamage, 1) / speed) + local damageTooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) + + local colorPos = "|cff20ff20" + local colorNeg = "|cffff2020" + if (totalBonus == 0) then + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(displayMin .. " - " .. displayMax) + else + damageText:SetText(displayMin .. "-" .. displayMax) + end + else + + local color + if (totalBonus > 0) then + color = colorPos + else + color = colorNeg + end + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") + else + damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|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 + damageFrame.damage = damageTooltip + damageFrame.attackSpeed = speed + damageFrame.dps = damagePerSecond + + -- If there's an offhand speed then add the offhand info to the tooltip + if (offhandSpeed) then + minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg + maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg + + local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5 + local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent + local offhandDamagePerSecond = (max(offhandFullDamage, 1) / offhandSpeed) + local offhandDamageTooltip = max(floor(minOffHandDamage), 1) .. " - " .. 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 + damageFrame.offhandDamage = offhandDamageTooltip + damageFrame.offhandAttackSpeed = offhandSpeed + damageFrame.offhandDps = offhandDamagePerSecond + else + damageFrame.offhandAttackSpeed = nil + end + +end + +function BCS:SetAttackSpeed(statFrame) + + local damageText = getglobal(statFrame:GetName() .. "StatText") + local damageFrame = statFrame + local speed, offhandSpeed = UnitAttackSpeed("player") + speed = format("%.2f", speed) + if (offhandSpeed) then + offhandSpeed = format("%.2f", offhandSpeed) + end + local text + if (offhandSpeed) then + text = speed .. " | " .. offhandSpeed + else + text = speed + end + + local minDamage + local maxDamage + local minOffHandDamage + local maxOffHandDamage + local physicalBonusPos + local physicalBonusNeg + local percent + minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent = UnitDamage("player") + local displayMin = max(floor(minDamage), 1) + local displayMax = max(ceil(maxDamage), 1) + + 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) + local damagePerSecond = (max(fullDamage, 1) / speed) + local damageTooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) + + local colorPos = "|cff20ff20" + local colorNeg = "|cffff2020" + if (totalBonus == 0) then + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(displayMin .. " - " .. displayMax) + else + damageText:SetText(displayMin .. "-" .. displayMax) + end + else + + local color + if (totalBonus > 0) then + color = colorPos + else + color = colorNeg + end + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") + else + damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|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 + damageFrame.damage = damageTooltip + damageFrame.attackSpeed = speed + damageFrame.dps = damagePerSecond + + -- If there's an offhand speed then add the offhand info to the tooltip + if (offhandSpeed) then + minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg + maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg + + local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5 + local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent + local offhandDamagePerSecond = (max(offhandFullDamage, 1) / offhandSpeed) + local offhandDamageTooltip = max(floor(minOffHandDamage), 1) .. " - " .. 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 + damageFrame.offhandDamage = offhandDamageTooltip + damageFrame.offhandAttackSpeed = offhandSpeed + damageFrame.offhandDps = offhandDamagePerSecond + else + damageFrame.offhandAttackSpeed = nil + end + local label = getglobal(statFrame:GetName() .. "Label") + local value = getglobal(statFrame:GetName() .. "StatText") + label:SetText(TEXT(SPEED) .. ":") + value:SetText(text) + --statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE; + --statFrame.tooltip = format(CR_HASTE_RATING_TOOLTIP, GetCombatRating(CR_HASTE_MELEE), GetCombatRatingBonus(CR_HASTE_MELEE)); + statFrame:SetScript("OnEnter", CharacterDamageFrame_OnEnter) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetAttackPower(statFrame) + local base, posBuff, negBuff = UnitAttackPower("player") + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + local tooltipText = HIGHLIGHT_FONT_COLOR_CODE .. MELEE_ATTACK_POWER .. " " + local effectiveStat = base + posBuff + negBuff + if ((posBuff == 0) and (negBuff == 0)) then + text:SetText(effectiveStat) + statFrame.tooltip = tooltipText .. base .. FONT_COLOR_CODE_CLOSE + else + tooltipText = tooltipText .. effectiveStat + if (posBuff > 0 or negBuff < 0) then + tooltipText = tooltipText .. " (" .. (base - posBuff - negBuff) .. FONT_COLOR_CODE_CLOSE + end + if (posBuff > 0) then + tooltipText = tooltipText .. FONT_COLOR_CODE_CLOSE .. GREEN_FONT_COLOR_CODE .. "+" .. posBuff .. FONT_COLOR_CODE_CLOSE + end + if (negBuff < 0) then + tooltipText = tooltipText .. RED_FONT_COLOR_CODE .. " " .. negBuff .. FONT_COLOR_CODE_CLOSE + end + if (posBuff > 0 or negBuff < 0) then + tooltipText = tooltipText .. HIGHLIGHT_FONT_COLOR_CODE .. ")" .. FONT_COLOR_CODE_CLOSE + end + statFrame.tooltip = tooltipText + + if (negBuff < 0) then + text:SetText(RED_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) + else + text:SetText(GREEN_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) + end + end + label:SetText(TEXT(ATTACK_POWER_COLON)) + PaperDollFormatStat(MELEE_ATTACK_POWER, base, posBuff, negBuff, frame, text) + frame.tooltipSubtext= format(MELEE_ATTACK_POWER_TOOLTIP, max((base + posBuff + negBuff), 0) / ATTACK_POWER_MAGIC_NUMBER) + if frame.tooltip then + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + end +end + +function BCS:SetSpellPower(statFrame, school) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + local colorPos = "|cff20ff20" + local colorNeg = "|cffff2020" + + if school then + label:SetText(L["SPELL_SCHOOL_" .. strupper(school)]) + local base = BCS:GetSpellPower() + local fromSchool = BCS:GetSpellPower(school) + local output = base + fromSchool + + if fromSchool > 0 then + output = colorPos .. output .. "|r" + end + + text:SetText(output) + + frame.tooltip = format(L.SPELL_SCHOOL_TOOLTIP , school) + frame.tooltipSubtext = format(L.SPELL_SCHOOL_TOOLTIP_SUB, strlower(school)) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + else + local power, secondaryPower, secondaryName = BCS:GetSpellPower() + + label:SetText(L.SPELL_POWER_COLON) + text:SetText(power + secondaryPower) + + if secondaryPower ~= 0 then + frame.tooltip = format(L.SPELL_POWER_SECONDARY_TOOLTIP, (power + secondaryPower), power, secondaryPower, secondaryName) + frame.tooltipSubtext = format(L.SPELL_POWER_SECONDARY_TOOLTIP_SUB) + else + frame.tooltip = format(L.SPELL_POWER_TOOLTIP, power) + frame.tooltipSubtext = format(L.SPELL_POWER_TOOLTIP_SUB) + end + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + end +end + +function BCS:SetRating(statFrame, ratingType) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.MELEE_HIT_RATING_COLON) + + local colorPos = "|cff20ff20" + local colorNeg = "|cffff2020" + + if ratingType == "MELEE" then + local rating = BCS:GetHitRating() + if BCS.MELEEHIT[BCS.playerClass] then + if rating < BCS.MELEEHIT[BCS.playerClass][1] then + rating = colorNeg .. rating .. "%|r" + elseif rating >= BCS.MELEEHIT[BCS.playerClass][2] then + rating = colorPos .. rating .. "%|r" + else + rating = rating .. "%" + end + else + rating = rating .. "%" + end + text:SetText(rating) + + frame.tooltip = (L.MELEE_HIT_TOOLTIP) + frame.tooltipSubtext = format(L.MELEE_HIT_TOOLTIP_SUB) + + elseif ratingType == "RANGED" then + local rating = BCS:GetRangedHitRating() + if BCS.MELEEHIT[BCS.playerClass] then + if rating < BCS.MELEEHIT[BCS.playerClass][1] then + rating = colorNeg .. rating .. "%|r" + elseif rating >= BCS.MELEEHIT[BCS.playerClass][2] then + rating = colorPos .. rating .. "%|r" + else + rating = rating .. "%" + end + else + rating = rating .. "%" + end + text:SetText(rating) + + frame.tooltip = (L.MELEE_HIT_TOOLTIP) + frame.tooltipSubtext = format(L.MELEE_HIT_TOOLTIP_SUB) + + elseif ratingType == "SPELL" then + local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow = BCS:GetSpellHitRating() + --[[if BCS.SPELLHIT[BCS.playerClass] then + if spell_hit < BCS.SPELLHIT[BCS.playerClass][1] then + spell_hit = colorNeg .. spell_hit .. "%|r" + elseif spell_hit >= BCS.SPELLHIT[BCS.playerClass][2] then + spell_hit = colorPos .. spell_hit .. "%|r" + else + spell_hit = spell_hit .. "%" + end + else + spell_hit = spell_hit .. "%" + end]] + + if spell_hit_fire > 0 or spell_hit_frost > 0 or spell_hit_arcane > 0 or spell_hit_shadow > 0 then + -- got spell hit from talents + local spell_hit_other, spell_hit_other_type + + spell_hit_other = 0 + spell_hit_other_type = "" + + if spell_hit_fire > spell_hit_other then + spell_hit_other = spell_hit_fire + spell_hit_other_type = L.SPELL_SCHOOL_FIRE + end + if spell_hit_frost > spell_hit_other then + spell_hit_other = spell_hit_frost + spell_hit_other_type = L.SPELL_SCHOOL_FROST + end + if spell_hit_arcane > spell_hit_other then + spell_hit_other = spell_hit_arcane + spell_hit_other_type = L.SPELL_SCHOOL_ARCANE + end + if spell_hit_shadow > spell_hit_other then + spell_hit_other = spell_hit_shadow + spell_hit_other_type = L.SPELL_SCHOOL_SHADOW + end + + frame.tooltip = format(L.SPELL_HIT_SECONDARY_TOOLTIP, spell_hit + spell_hit_other, spell_hit, spell_hit_other, spell_hit_other_type) + text:SetText(spell_hit + spell_hit_other .. "%") + else + frame.tooltip = L.SPELL_HIT_TOOLTIP + text:SetText(spell_hit .. "%") + end + frame.tooltipSubtext = format(L.SPELL_HIT_TOOLTIP_SUB) + end + + if frame.tooltip then + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + end + +end + +function BCS:SetMeleeCritChance(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.MELEE_CRIT_COLON) + text:SetText(format("%.2f%%", BCS:GetCritChance())) + + statFrame.tooltip = (L.MELEE_CRIT_TOOLTIP) + statFrame.tooltipSubtext = (L.MELEE_CRIT_TOOLTIP_SUB) + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetWeaponSkill(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.WEAPON_SKILL_COLON) + if OffhandHasWeapon() == 1 then + text:SetText(format("%d |%d", BCS:GetMHWeaponSkill(), BCS:GetOHWeaponSkill())) + else + text:SetText(format("%d", BCS:GetMHWeaponSkill())) + end + statFrame.tooltip = format(L.MELEE_WEAPON_SKILL_TOOLTIP) + statFrame.tooltipSubtext = format(L.MELEE_WEAPON_SKILL_TOOLTIP_SUB) + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetRangedWeaponSkill(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + local _,class = UnitClass("player") + label:SetText(L.WEAPON_SKILL_COLON) + -- If no ranged attack then set to n/a + if not (GetInventoryItemLink("player",18)) or + ((class == "PALADIN") + or(class == "DRUID") + or(class == "SHAMAN")) + then + text:SetText(NOT_APPLICABLE) + return + end + text:SetText(format("%d", BCS:GetRangedWeaponSkill())) + statFrame.tooltip = format(L.RANGED_WEAPON_SKILL_TOOLTIP) + statFrame.tooltipSubtext = format(L.RANGED_WEAPON_SKILL_TOOLTIP_SUB) + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetMissChance(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.MISS_CHANCE_COLON) + + local mh_miss = BCS:GetMissChance(BCS:GetMHWeaponSkill()) + + if OffhandHasWeapon() == 1 then + text:SetText(format("%.1f%%|%.1f%%", + BCS:GetDualWieldMissChance(BCS:GetMHWeaponSkill()), + BCS:GetDualWieldMissChance(BCS:GetOHWeaponSkill()))) + else + text:SetText(format("%.1f%%", mh_miss)) + end + + frame.tooltip = format(L.MELEE_HIT_VS_BOSS_TOOLTIP, mh_miss) + + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetGlanceReduction(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.GLANCE_REDUCTION_COLON) + + if OffhandHasWeapon() == 1 then + text:SetText(format("%d%% |%d%%", + BCS:GetGlanceReduction(BCS:GetMHWeaponSkill()), + BCS:GetGlanceReduction(BCS:GetOHWeaponSkill()))) + else + text:SetText(format("%d%%", BCS:GetGlanceReduction(BCS:GetMHWeaponSkill()))) + end + statFrame.tooltip = L.GLANCE_TOOLTIP + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetDodgeChance(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.DODGE_CHANCE_COLON) + + if OffhandHasWeapon() == 1 then + text:SetText(format("%.1f%% |%.1f%%", + BCS:GetDodgeChance(BCS:GetMHWeaponSkill()), + BCS:GetDodgeChance(BCS:GetOHWeaponSkill()))) + else + text:SetText(format("%.1f%%", BCS:GetDodgeChance(BCS:GetMHWeaponSkill()))) + end + statFrame.tooltip = L.DODGE_CHANCE_TOOLTIP + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetCritCap(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.CRIT_CAP_COLON) + if OffhandHasWeapon() == 1 then + text:SetText(format("%.1f%%|%.1f%%", + BCS:GetDualWieldCritCap(BCS:GetMHWeaponSkill()), + BCS:GetDualWieldCritCap(BCS:GetOHWeaponSkill()))) + else + text:SetText(format("%.1f%%", BCS:GetCritCap(BCS:GetMHWeaponSkill()))) + end + statFrame.tooltip = L.CRIT_CAP_TOOLTIP + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetBossCrit(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.BOSS_CRIT_COLON) + + local critChance = BCS:GetCritChance() - 3 -- 3 % crit reduction vs lvl 63 + if OffhandHasWeapon() == 1 then + text:SetText(format("%.1f%%|%.1f%%", + math.min(critChance, BCS:GetDualWieldCritCap(BCS:GetMHWeaponSkill())), + math.min(critChance, BCS:GetDualWieldCritCap(BCS:GetOHWeaponSkill())) + )) + else + text:SetText(format("%.1f%%", math.min(critChance, BCS:GetCritCap(BCS:GetMHWeaponSkill())))) + end + statFrame.tooltip = L.EFFECTIVE_CRIT_TOOLTIP + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetSpellCritChance(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.SPELL_CRIT_COLON) + text:SetText(format("%.2f%%", BCS:GetSpellCritChance())) + frame.tooltip = format(L.SPELL_CRIT_TOOLTIP) + frame.tooltipSubtext = format(L.SPELL_CRIT_TOOLTIP_SUB) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetRangedCritChance(statFrame) + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.RANGED_CRIT_COLON) + text:SetText(format("%.2f%%", BCS:GetRangedCritChance())) + + statFrame.tooltip = (L.MELEE_CRIT_TOOLTIP) + statFrame.tooltipSubtext = (L.MELEE_CRIT_TOOLTIP_SUB) + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetHealing(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + local power, _, _, dmg = BCS:GetSpellPower() + local heal = BCS:GetHealingPower() + power = power - dmg + label:SetText(L.HEAL_POWER_COLON) + text:SetText(power + heal) + if heal ~= 0 then + frame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (power + heal), power, heal) + else + frame.tooltip = format(L.SPELL_HEALING_POWER_TOOLTIP, (power + heal)) + end + frame.tooltipSubtext = format(L.SPELL_HEALING_POWER_TOOLTIP_SUB) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetManaRegen(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + local base, casting, mp5 = BCS:GetManaRegen() + local mp2 = mp5 * 0.4 + local totalRegen = base + mp2 + local totalRegenWhileCasting = (casting / 100) * base + mp2 + local _,class = UnitClass("player") + label:SetText(L.MANA_REGEN_COLON) + + -- if not a mana user or druid set to N/A + if (UnitPowerType("player") ~= 0 and not(class=="DRUID"))then + text:SetText(NOT_APPLICABLE) + frame.tooltip = nil + else + text:SetText(format("%d |cffBF40BF(%d)|r", totalRegen, totalRegenWhileCasting)) + frame.tooltip = format(L.SPELL_MANA_REGEN_TOOLTIP, totalRegen, totalRegenWhileCasting) + frame.tooltipSubtext = format(L.SPELL_MANA_REGEN_TOOLTIP_SUB, base, casting, mp5, mp2) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + end +end + +function BCS:SetDodge(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.DODGE_COLON) + text:SetText(format("%.2f%%", GetDodgeChance())) + + frame.tooltip = format(L.PLAYER_DODGE_TOOLTIP) + frame.tooltipSubtext = format(L.PLAYER_DODGE_TOOLTIP_SUB) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetParry(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.PARRY_COLON) + text:SetText(format("%.2f%%", GetParryChance())) + + frame.tooltip = format(L.PLAYER_PARRY_TOOLTIP) + frame.tooltipSubtext = format(L.PLAYER_PARRY_TOOLTIP_SUB) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetBlock(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.BLOCK_COLON) + text:SetText(format("%.2f%%", GetBlockChance())) + + frame.tooltip = format(L.PLAYER_BLOCK_TOOLTIP) + frame.tooltipSubtext = format(L.PLAYER_BLOCK_TOOLTIP_SUB) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end +function BCS:SetTotalAvoidance(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + + label:SetText(L.TOTAL_COLON) + text:SetText(format("%.2f%%", (GetBlockChance() + GetParryChance() + GetDodgeChance()))) + + frame.tooltip = format(L.TOTAL_AVOIDANCE_TOOLTIP) + frame.tooltipSubtext = format(L.TOTAL_AVOIDANCE_TOOLTIP_SUB) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetDefense(statFrame) + local base, modifier = UnitDefense("player") + + local frame = statFrame + local label = getglobal(statFrame:GetName() .. "Label") + local text = getglobal(statFrame:GetName() .. "StatText") + + label:SetText(TEXT(DEFENSE_COLON)) + + local posBuff = 0 + local negBuff = 0 + if (modifier > 0) then + posBuff = modifier + elseif (modifier < 0) then + negBuff = modifier + end + PaperDollFormatStat(DEFENSE_COLON, base, posBuff, negBuff, frame, text) + frame.tooltip = format(L.DEFENSE_TOOLTIP) + frame.tooltipSubtext = format(L.DEFENSE_TOOLTIP_SUB) + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +function BCS:SetRangedDamage(statFrame) + local label = getglobal(statFrame:GetName() .. "Label") + local damageText = getglobal(statFrame:GetName() .. "StatText") + local damageFrame = statFrame + local _,class = UnitClass("player") + label:SetText(TEXT(DAMAGE_COLON)) + + damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) + damageFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + + -- If no ranged attack then set to n/a + if not (GetInventoryItemLink("player",18)) or + ((class == "PALADIN") + or(class == "DRUID") + or(class == "SHAMAN")) + then + damageText:SetText(NOT_APPLICABLE) + damageFrame.damage = nil + return + end + + local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") + local displayMin = max(floor(minDamage), 1) + local displayMax = max(ceil(maxDamage), 1) + + 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) + local damagePerSecond = (max(fullDamage, 1) / rangedAttackSpeed) + local tooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) + + if (totalBonus == 0) then + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(displayMin .. " - " .. displayMax) + else + damageText:SetText(displayMin .. "-" .. displayMax) + end + else + local colorPos = "|cff20ff20" + local colorNeg = "|cffff2020" + local color + if (totalBonus > 0) then + color = colorPos + else + color = colorNeg + end + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") + else + damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|r") + end + if (physicalBonusPos > 0) then + tooltip = tooltip .. colorPos .. " +" .. physicalBonusPos .. "|r" + end + if (physicalBonusNeg < 0) then + tooltip = tooltip .. colorNeg .. " " .. physicalBonusNeg .. "|r" + end + if (percent > 1) then + tooltip = tooltip .. colorPos .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + elseif (percent < 1) then + tooltip = tooltip .. colorNeg .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + end + damageFrame.tooltip = tooltip .. " " .. format(TEXT(DPS_TEMPLATE), damagePerSecond) + end + damageFrame.attackSpeed = rangedAttackSpeed + damageFrame.damage = tooltip + damageFrame.dps = damagePerSecond +end + +function BCS:SetRangedAttackSpeed(startFrame) + local label = getglobal(startFrame:GetName() .. "Label") + local damageText = getglobal(startFrame:GetName() .. "StatText") + local damageFrame = startFrame + local _,class = UnitClass("player") + label:SetText(TEXT(SPEED) .. ":") + damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) + damageFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + -- If no ranged attack then set to n/a + if not (GetInventoryItemLink("player",18)) or + ((class == "PALADIN") + or(class == "DRUID") + or(class == "SHAMAN")) + then + damageText:SetText(NOT_APPLICABLE) + damageFrame.damage = nil + return + end + + local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") + local displayMin = max(floor(minDamage), 1) + local displayMax = max(ceil(maxDamage), 1) + + 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) + local damagePerSecond = (max(fullDamage, 1) / rangedAttackSpeed) + local tooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) + + if (totalBonus == 0) then + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(displayMin .. " - " .. displayMax) + else + damageText:SetText(displayMin .. "-" .. displayMax) + end + else + local colorPos = "|cff20ff20" + local colorNeg = "|cffff2020" + local color + if (totalBonus > 0) then + color = colorPos + else + color = colorNeg + end + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") + else + damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|r") + end + if (physicalBonusPos > 0) then + tooltip = tooltip .. colorPos .. " +" .. physicalBonusPos .. "|r" + end + if (physicalBonusNeg < 0) then + tooltip = tooltip .. colorNeg .. " " .. physicalBonusNeg .. "|r" + end + if (percent > 1) then + tooltip = tooltip .. colorPos .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + elseif (percent < 1) then + tooltip = tooltip .. colorNeg .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + end + damageFrame.tooltip = tooltip .. " " .. format(TEXT(DPS_TEMPLATE), damagePerSecond) + end + + damageText:SetText(format("%.2f", rangedAttackSpeed)) + + damageFrame.attackSpeed = rangedAttackSpeed + damageFrame.damage = tooltip + damageFrame.dps = damagePerSecond +end + +function BCS:SetRangedAttackPower(statFrame) + local frame = statFrame + local text = getglobal(statFrame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + local _,class = UnitClass("player") + label:SetText(TEXT(ATTACK_POWER_COLON)) + + -- If no ranged attack then set to n/a + if not (GetInventoryItemLink("player",18)) or + ((class == "PALADIN") + or(class == "DRUID") + or(class == "SHAMAN")) + then + text:SetText(NOT_APPLICABLE) + frame.tooltip = nil + return + end + + local base, posBuff, negBuff = UnitRangedAttackPower("player") + PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, frame, text) + frame.tooltipSubtext = format(RANGED_ATTACK_POWER_TOOLTIP, base / ATTACK_POWER_MAGIC_NUMBER) + + local tooltipText = HIGHLIGHT_FONT_COLOR_CODE .. RANGED_ATTACK_POWER .. " " + local effectiveStat = base + posBuff + negBuff + if ((posBuff == 0) and (negBuff == 0)) then + text:SetText(effectiveStat) + statFrame.tooltip = tooltipText .. base .. FONT_COLOR_CODE_CLOSE + else + tooltipText = tooltipText .. effectiveStat + if (posBuff > 0 or negBuff < 0) then + tooltipText = tooltipText .. " (" .. (base - posBuff - negBuff) .. FONT_COLOR_CODE_CLOSE + end + if (posBuff > 0) then + tooltipText = tooltipText .. FONT_COLOR_CODE_CLOSE .. GREEN_FONT_COLOR_CODE .. "+" .. posBuff .. FONT_COLOR_CODE_CLOSE + end + if (negBuff < 0) then + tooltipText = tooltipText .. RED_FONT_COLOR_CODE .. " " .. negBuff .. FONT_COLOR_CODE_CLOSE + end + if (posBuff > 0 or negBuff < 0) then + tooltipText = tooltipText .. HIGHLIGHT_FONT_COLOR_CODE .. ")" .. FONT_COLOR_CODE_CLOSE + end + statFrame.tooltip = tooltipText + + if (negBuff < 0) then + text:SetText(RED_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) + else + text:SetText(GREEN_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) + end + end + label:SetText(TEXT(ATTACK_POWER_COLON)) + PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, frame, text) + frame.tooltipSubtext= format(RANGED_ATTACK_POWER_TOOLTIP, max((base + posBuff + negBuff), 0) / ATTACK_POWER_MAGIC_NUMBER) + if frame.tooltip then + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + end + +end + +function BCS:UpdatePaperdollStats(prefix, index) + local stat1 = getglobal(prefix .. 1) + local stat2 = getglobal(prefix .. 2) + local stat3 = getglobal(prefix .. 3) + local stat4 = getglobal(prefix .. 4) + local stat5 = getglobal(prefix .. 5) + local stat6 = getglobal(prefix .. 6) + + stat1:SetScript("OnEnter", nil) + stat2:SetScript("OnEnter", nil) + stat3:SetScript("OnEnter", nil) + stat4:SetScript("OnEnter", nil) + stat4:SetScript("OnEnter", nil) + stat5:SetScript("OnEnter", nil) + stat6:SetScript("OnEnter", nil) + + stat1.tooltip = nil + stat2.tooltip = nil + stat3.tooltip = nil + stat4.tooltip = nil + stat4.tooltip = nil + stat5.tooltip = nil + stat6.tooltip = nil + + stat4:Show() + stat5:Show() + stat6:Show() + + if (index == "PLAYERSTAT_BASE_STATS") then + BCS:SetStat(stat1, 1) + BCS:SetStat(stat2, 2) + BCS:SetStat(stat3, 3) + BCS:SetStat(stat4, 4) + BCS:SetStat(stat5, 5) + BCS:SetArmor(stat6) + elseif (index == "PLAYERSTAT_MELEE_COMBAT") then + BCS:SetWeaponSkill(stat1) + BCS:SetDamage(stat2) + BCS:SetAttackSpeed(stat3) + BCS:SetAttackPower(stat4) + BCS:SetRating(stat5, "MELEE") + BCS:SetMeleeCritChance(stat6) + elseif (index == "PLAYERSTAT_MELEE_BOSS") then + BCS:SetWeaponSkill(stat1) + BCS:SetMissChance(stat2) + BCS:SetDodgeChance(stat3) + BCS:SetGlanceReduction(stat4) + BCS:SetCritCap(stat5) + BCS:SetBossCrit(stat6) + elseif (index == "PLAYERSTAT_RANGED_COMBAT") then + BCS:SetRangedWeaponSkill(stat1) + BCS:SetRangedDamage(stat2) + BCS:SetRangedAttackSpeed(stat3) + BCS:SetRangedAttackPower(stat4) + BCS:SetRating(stat5, "RANGED") + BCS:SetRangedCritChance(stat6) + elseif (index == "PLAYERSTAT_SPELL_COMBAT") then + BCS:SetSpellPower(stat1) + BCS:SetRating(stat2, "SPELL") + BCS:SetSpellCritChance(stat3) + BCS:SetHealing(stat4) + BCS:SetManaRegen(stat5) + stat6:Hide() + elseif (index == "PLAYERSTAT_SPELL_SCHOOLS") then + BCS:SetSpellPower(stat1, "Arcane") + BCS:SetSpellPower(stat2, "Fire") + BCS:SetSpellPower(stat3, "Frost") + BCS:SetSpellPower(stat4, "Holy") + BCS:SetSpellPower(stat5, "Nature") + BCS:SetSpellPower(stat6, "Shadow") + elseif (index == "PLAYERSTAT_DEFENSES") then + BCS:SetArmor(stat1) + BCS:SetDefense(stat2) + BCS:SetDodge(stat3) + BCS:SetParry(stat4) + BCS:SetBlock(stat5) + BCS:SetTotalAvoidance(stat6) + end +end + +local function PlayerStatFrameLeftDropDown_OnClick() + UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) + IndexLeft = this.value + BCSConfig["DropdownLeft"] = IndexLeft + BCS:UpdatePaperdollStats("PlayerStatFrameLeft", this.value) +end + +local function PlayerStatFrameRightDropDown_OnClick() + UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) + IndexRight = this.value + BCSConfig["DropdownRight"] = IndexRight + BCS:UpdatePaperdollStats("PlayerStatFrameRight", this.value) +end + +local function PlayerStatFrameLeftDropDown_Initialize() + local info = {} + local checked = nil + for i = 1, getn(BCS.PLAYERSTAT_DROPDOWN_OPTIONS) do + info.text = BCS.L[BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i]] + info.func = PlayerStatFrameLeftDropDown_OnClick + info.value = BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i] + info.checked = checked + info.owner = UIDROPDOWNMENU_OPEN_MENU + UIDropDownMenu_AddButton(info) + end +end + +local function PlayerStatFrameRightDropDown_Initialize() + local info = {} + local checked = nil + for i = 1, getn(BCS.PLAYERSTAT_DROPDOWN_OPTIONS) do + info.text = BCS.L[BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i]] + info.func = PlayerStatFrameRightDropDown_OnClick + info.value = BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i] + info.checked = checked + info.owner = UIDROPDOWNMENU_OPEN_MENU + UIDropDownMenu_AddButton(info) + end +end + +function PlayerStatFrameLeftDropDown_OnLoad() + RaiseFrameLevel(this) + RaiseFrameLevel(getglobal(this:GetName() .. "Button")) + UIDropDownMenu_Initialize(this, PlayerStatFrameLeftDropDown_Initialize) + UIDropDownMenu_SetWidth(99, this) + UIDropDownMenu_JustifyText("LEFT") +end + +function PlayerStatFrameRightDropDown_OnLoad() + RaiseFrameLevel(this) + RaiseFrameLevel(getglobal(this:GetName() .. "Button")) + UIDropDownMenu_Initialize(this, PlayerStatFrameRightDropDown_Initialize) + UIDropDownMenu_SetWidth(99, this) + UIDropDownMenu_JustifyText("LEFT") +end + +--pfUI.api.strsplit +function hcstrsplit(delimiter, subject) + if not subject then + return nil + end + local delimiter, fields = delimiter or ":", {} + local pattern = string.format("([^%s]+)", delimiter) + string.gsub(subject, pattern, function(c) + fields[table.getn(fields) + 1] = c + end) + return unpack(fields) +end + +--Update announcing code taken from pfUI +local major, minor, fix = hcstrsplit(".", tostring(GetAddOnMetadata("BetterCharacterStats", "Version"))) + +local alreadyshown = false +local localversion = tonumber(major * 10000 + minor * 100 + fix) +local remoteversion = tonumber(bcsupdateavailable) or 0 +local loginchannels = { "BATTLEGROUND", "RAID", "GUILD", "PARTY" } +local groupchannels = { "BATTLEGROUND", "RAID", "PARTY" } + +bcsupdater = CreateFrame("Frame") +bcsupdater:RegisterEvent("CHAT_MSG_ADDON") +bcsupdater:RegisterEvent("PLAYER_ENTERING_WORLD") +bcsupdater:RegisterEvent("PARTY_MEMBERS_CHANGED") +bcsupdater:SetScript("OnEvent", function() + if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then + local v, remoteversion = hcstrsplit(":", arg2) + local remoteversion = tonumber(remoteversion) + if v == "VERSION" and remoteversion then + if remoteversion > localversion then + bcsupdateavailable = remoteversion + if not alreadyshown then + DEFAULT_CHAT_FRAME:AddMessage("|cffffffffBetterCharacterStats|r New version available! https://github.com/Lexiebean/BetterCharacterStats") + alreadyshown = true + end + end + end + --This is a little check that I can use to see if people are actually using the addon. + if v == "PING?" then + for _, chan in pairs(loginchannels) do + SendAddonMessage("bcs", "PONG!:" .. GetAddOnMetadata("BetterCharacterStats", "Version"), chan) + end + end + if v == "PONG!" then + --print(arg1 .." "..arg2.." "..arg3.." "..arg4) + end + end + + if event == "PARTY_MEMBERS_CHANGED" then + local groupsize = GetNumRaidMembers() > 0 and GetNumRaidMembers() or GetNumPartyMembers() > 0 and GetNumPartyMembers() or 0 + if (this.group or 0) < groupsize then + for _, chan in pairs(groupchannels) do + SendAddonMessage("bcs", "VERSION:" .. localversion, chan) + end + end + this.group = groupsize + end + + if event == "PLAYER_ENTERING_WORLD" then + if not alreadyshown and localversion < remoteversion then + DEFAULT_CHAT_FRAME:AddMessage("|cffffffffBetterCharacterStats|r New version available! https://github.com/Lexiebean/BetterCharacterStats") + bcsupdateavailable = localversion + alreadyshown = true + end + + for _, chan in pairs(loginchannels) do + SendAddonMessage("bcs", "VERSION:" .. localversion, chan) + end + end +end) diff --git a/Localization.lua b/Localization.lua index 115faf7..e765196 100644 --- a/Localization.lua +++ b/Localization.lua @@ -1,172 +1,221 @@ -BCS = BCS or {} - -BCS["L"] = { - - ["([%d.]+)%% chance to crit"] = "([%d.]+)%% chance to crit", - - ["^Set: Improves your chance to hit by (%d)%%."] = "^Set: Improves your chance to hit by (%d)%%.", - ["^Set: Improves your chance to get a critical strike with spells by (%d)%%."] = "^Set: Improves your chance to get a critical strike with spells by (%d)%%.", - ["^Set: Improves your chance to hit with spells by (%d)%%."] = "^Set: Improves your chance to hit with spells by (%d)%%.", - ["^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%."] = "^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%.", - ["^Set: Increases healing done by spells and effects by up to (%d+)%."] = "^Set: Increases healing done by spells and effects by up to (%d+)%.", - ["^Set: Allows (%d+)%% of your Mana regeneration to continue while casting."] = "^Set: Allows (%d+)%% of your Mana regeneration to continue while casting.", - - ["Equip: Improves your chance to hit by (%d)%%."] = "Equip: Improves your chance to hit by (%d)%%.", - ["Equip: Improves your chance to get a critical strike with spells by (%d)%%."] = "Equip: Improves your chance to get a critical strike with spells by (%d)%%.", - ["Equip: Improves your chance to hit with spells by (%d)%%."] = "Equip: Improves your chance to hit with spells by (%d)%%.", - - ["Increases your chance to hit with melee weapons by (%d)%%."] = "Increases your chance to hit with melee weapons by (%d)%%.", - ["Increases your critical strike chance with ranged weapons by (%d)%%."] = "Increases your critical strike chance with ranged weapons by (%d)%%.", - ["Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%."] = "Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%.", - ["Increases your critical strike chance with all attacks by (%d)%%."] = "Increases your critical strike chance with all attacks by (%d)%%.", - ["Increases spell damage and healing by up to (%d+)%% of your total Spirit."] = "Increases spell damage and healing by up to (%d+)%% of your total Spirit.", - ["Allows (%d+)%% of your Mana regeneration to continue while casting."] = "Allows (%d+)%% of your Mana regeneration to continue while casting.", - ["Reduces the chance that the opponent can resist your Frost and Fire spells by (%d)%%."] = "Reduces the chance that the opponent can resist your Frost and Fire spells by (%d)%%.", - ["Reduces the chance that the opponent can resist your Arcane spells by (%d+)%%."] = "Reduces the chance that the opponent can resist your Arcane spells by (%d+)%%.", - ["Reduces your target's chance to resist your Shadow spells by (%d+)%%."] = "Reduces your target's chance to resist your Shadow spells by (%d+)%%.", - - ["Equip: Increases damage done by Arcane spells and effects by up to (%d+)."] = "Equip: Increases damage done by Arcane spells and effects by up to (%d+).", - ["Equip: Increases damage done by Fire spells and effects by up to (%d+)."] = "Equip: Increases damage done by Fire spells and effects by up to (%d+).", - ["Equip: Increases damage done by Frost spells and effects by up to (%d+)."] = "Equip: Increases damage done by Frost spells and effects by up to (%d+).", - ["Equip: Increases damage done by Holy spells and effects by up to (%d+)."] = "Equip: Increases damage done by Holy spells and effects by up to (%d+).", - ["Equip: Increases damage done by Nature spells and effects by up to (%d+)."] = "Equip: Increases damage done by Nature spells and effects by up to (%d+).", - ["Equip: Increases damage done by Shadow spells and effects by up to (%d+)."] = "Equip: Increases damage done by Shadow spells and effects by up to (%d+).", - - ["Shadow Damage %+(%d+)"] = "Shadow Damage %+(%d+)", - ["Spell Damage %+(%d+)"] = "Spell Damage %+(%d+)", - ["Fire Damage %+(%d+)"] = "Fire Damage %+(%d+)", - ["Frost Damage %+(%d+)"] = "Frost Damage %+(%d+)", - ["Healing Spells %+(%d+)"] = "Healing Spells %+(%d+)", - ["^Healing %+(%d+) and %d+ mana per 5 sec."] = "^Healing %+(%d+) and %d+ mana per 5 sec.", - - ["Equip: Restores (%d+) mana per 5 sec."] = "Equip: Restores (%d+) mana per 5 sec.", - ["+(%d)%% Hit"] = "+(%d)%% Hit", - - -- Random Bonuses // https://wow.gamepedia.com/index.php?title=SuffixId&oldid=204406 - ["^%+(%d+) Damage and Healing Spells"] = "^%+(%d+) Damage and Healing Spells", - ["^%+(%d+) Arcane Spell Damage"] = "^%+(%d+) Arcane Spell Damage", - ["^%+(%d+) Fire Spell Damage"] = "^%+(%d+) Fire Spell Damage", - ["^%+(%d+) Frost Spell Damage"] = "^%+(%d+) Frost Spell Damage", - ["^%+(%d+) Holy Spell Damage"] = "^%+(%d+) Holy Spell Damage", - ["^%+(%d+) Nature Spell Damage"] = "^%+(%d+) Nature Spell Damage", - ["^%+(%d+) Shadow Spell Damage"] = "^%+(%d+) Shadow Spell Damage", - ["^%+(%d+) mana every 5 sec."] = "^%+(%d+) mana every 5 sec.", - ["Restores (%d+) mana every 1 sec."] = "Restores (%d+) mana every 1 sec.", - ["(%d+)%% of your Mana regeneration continuing while casting."] = "(%d+)%% of your Mana regeneration continuing while casting.", - - - -- Mana Oils - ["^Brilliant Mana Oil %((%d+) min%"] = "^Brilliant Mana Oil %((%d+) min%", - ["^Lesser Mana Oil ((%d+) min)"] = "^Lesser Mana Oil ((%d+) min)", - ["^Minor Mana Oil ((%d+) min)"] = "^Minor Mana Oil ((%d+) min)", - - -- snowflakes ZG enchants - ["/Hit %+(%d+)"] = "/Hit %+(%d+)", - ["/Spell Hit %+(%d+)"] = "/Spell Hit %+(%d+)", - ["^Mana Regen %+(%d+)"] = "^Mana Regen %+(%d+)", - ["^Healing %+%d+ and (%d+) mana per 5 sec."] = "^Healing %+%d+ and (%d+) mana per 5 sec.", - ["^%+(%d+) Healing Spells"] = "^%+(%d+) Healing Spells", - ["^%+(%d+) Spell Damage and Healing"] = "^%+(%d+) Spell Damage and Healing", - - -- Mana Oils - ["^Brilliant Mana Oil %((%d+) min%"] = "^Brilliant Mana Oil %((%d+) min%", - - ["Equip: Increases damage and healing done by magical spells and effects by up to (%d+)."] = "Equip: Increases damage and healing done by magical spells and effects by up to (%d+).", - ["Equip: Increases healing done by spells and effects by up to (%d+)."] = "Equip: Increases healing done by spells and effects by up to (%d+).", - - -- auras - ["Chance to hit increased by (%d)%%."] = "Chance to hit increased by (%d)%%.", - ["Magical damage dealt is increased by up to (%d+)."] = "Magical damage dealt is increased by up to (%d+).", - ["Healing done by magical spells is increased by up to (%d+)."] = "Healing done by magical spells is increased by up to (%d+).", - ["Increases healing done by magical spells by up to (%d+) for 3600 sec."] = "Increases healing done by magical spells by up to (%d+) for 3600 sec.", - ["Healing increased by up to (%d+)."] = "Healing increased by up to (%d+).", - ["Healing spells increased by up to (%d+)."] = "Healing spells increased by up to (%d+).", - ["Chance to hit reduced by (%d+)%%."] = "Chance to hit reduced by (%d+)%%.", - ["Chance to hit decreased by (%d+)%% and %d+ Nature damage every %d+ sec."] = "Chance to hit decreased by (%d+)%% and %d+ Nature damage every %d+ sec.", - ["Lowered chance to hit."] = "Lowered chance to hit.", -- 5917 Fumble (25%) - ["Increases hitpoints by 300. 15%% haste to melee attacks. (%d+) mana regen every 5 seconds."] = "Increases hitpoints by 300. 15%% haste to melee attacks. (%d+) mana regen every 5 seconds.", - ["Restores (%d+) mana per 5 sec."] = "Restores (%d+) mana per 5 sec.", - ["Regenerating (%d+) Mana every 5 seconds."] = "Regenerating (%d+) Mana every 5 seconds.", - ["Regenerate (%d+) mana per 5 sec."] = "Regenerate (%d+) mana per 5 sec.", - ["Mana Regeneration increased by (%d+) every 5 seconds."] = "Mana Regeneration increased by (%d+) every 5 seconds.", - ["Improves your chance to hit by (%d+)%%."] = "Improves your chance to hit by (%d+)%%.", - ["Chance for a critical hit with a spell increased by (%d+)%%."] = "Chance for a critical hit with a spell increased by (%d+)%%.", - ["While active, target's critical hit chance with spells and attacks increases by 10%%."] = "While active, target's critical hit chance with spells and attacks increases by 10%%.", - ["Increases attack power by %d+ and chance to hit by (%d+)%%."] = "Increases attack power by %d+ and chance to hit by (%d+)%%.", - ["Holy spell critical hit chance increased by (%d+)%%."] = "Holy spell critical hit chance increased by (%d+)%%.", - ["Destruction spell critical hit chance increased by (%d+)%%."] = "Destruction spell critical hit chance increased by (%d+)%%.", - ["Arcane spell critical hit chance increased by (%d+)%%.\r\nArcane spell critical hit damage increased by (%d+)%%."] = "Arcane spell critical hit chance increased by (%d+)%%.\r\nArcane spell critical hit damage increased by (%d+)%%.", - ["Spell hit chance increased by (%d+)%%."] = "Spell hit chance increased by (%d+)%%.", - - ["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."] = "Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+.", - ["Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%."] = "Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%.", - ["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."] = "Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration.", - ["Holy spell critical hit chance increased by (%d+)%%."] = "Holy spell critical hit chance increased by (%d+)%%.", - ["Destruction spell critical hit chance increased by (%d+)%%."] = "Destruction spell critical hit chance increased by (%d+)%%.", - ["Critical strike chance with spells and melee attacks increased by (%d+)%%."] = "Critical strike chance with spells and melee attacks increased by (%d+)%%.", - - - ["MELEE_HIT_TOOLTIP"] = [[|cffffffffHit|r - Result of an attack made with - melee or ranged weapons.]], - - ["SPELL_HIT_TOOLTIP"] = [[|cffffffffHit|r - Result of an attack made with - spells.]], - - ["SPELL_HIT_SECONDARY_TOOLTIP"] = [[|cffffffffHit %d%% (%d%%|cff20ff20+%d%% %s|r|cffffffff)|r - Result of an attack made with - spells.]], - - ["SPELL_POWER_TOOLTIP"] = [[|cffffffffSpell Power %d|r - Increases damage done by spells and effects.]], - - ["SPELL_POWER_SECONDARY_TOOLTIP"] = [[|cffffffffSpell Power %d (%d|cff20ff20+%d %s|r|cffffffff)|r - Increases damage done by spells and effects.]], - - ["SPELL_HEALING_POWER_TOOLTIP"] = [[|cffffffffHealing Power %d (%d|cff20ff20+%d|r|cffffffff)|r - Increases healing done by spells and effects.]], - - ["SPELL_MANA_REGEN_TOOLTIP"] = [[|cffffffffMana regen: %d |cffBF40BF(%d)|r - Mana regen when not casting and |cffBF40BF(while casting)|r. - Mana regenerates every 2 seconds and the amount - is dependent on your total spirit and MP5. - Spirit Regen: |cff7DF9FF%d|r - %%Regen while casting: |cffBF40BF%d%%|r - MP5 Regen: |cff20ff20%d|r - MP5 Regen (2s): |cff20ff20%d|r]], - - ["ROGUE_MELEE_HIT_TOOLTIP"] = [[ -+5% hit to always hit enemy players. -+8% hit to always hit with your special abilities against a raid boss. -+24.6% hit to always hit a raid boss.]], - - PLAYERSTAT_BASE_STATS = "Base Stats", - PLAYERSTAT_DEFENSES = "Defenses", - PLAYERSTAT_MELEE_COMBAT = "Melee", - PLAYERSTAT_RANGED_COMBAT = "Ranged", - PLAYERSTAT_SPELL_COMBAT = "Spell", - PLAYERSTAT_SPELL_SCHOOLS = "Schools", - - MELEE_HIT_RATING_COLON = "Hit Rating:", - RANGED_HIT_RATING_COLON = "Hit Rating:", - SPELL_HIT_RATING_COLON = "Hit Rating:", - MELEE_CRIT_COLON = "Crit Chance:", - RANGED_CRIT_COLON = "Crit Chance:", - SPELL_CRIT_COLON = "Crit Chance:", - MANA_REGEN_COLON = "Mana regen:", - HEAL_POWER_COLON = "Healing:", - DODGE_COLON = DODGE .. ":", - PARRY_COLON = PARRY .. ":", - BLOCK_COLON = BLOCK .. ":", - - SPELL_POWER_COLON = "Power:", - - SPELL_SCHOOL_ARCANE = "Arcane", - SPELL_SCHOOL_FIRE = "Fire", - SPELL_SCHOOL_FROST = "Frost", - SPELL_SCHOOL_HOLY = "Holy", - SPELL_SCHOOL_NATURE = "Nature", - SPELL_SCHOOL_SHADOW = "Shadow", - -} \ No newline at end of file +BCS = BCS or {} + +BCS["L"] = { + + ["([%d.]+)%% chance to crit"] = "([%d.]+)%% chance to crit", + + ["^Set: Improves your chance to hit by (%d)%%."] = "^Set: Improves your chance to hit by (%d)%%.", + ["^Set: Improves your chance to get a critical strike with spells by (%d)%%."] = "^Set: Improves your chance to get a critical strike with spells by (%d)%%.", + ["^Set: Improves your chance to hit with spells by (%d)%%."] = "^Set: Improves your chance to hit with spells by (%d)%%.", + ["^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%."] = "^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%.", + ["^Set: Increases healing done by spells and effects by up to (%d+)%."] = "^Set: Increases healing done by spells and effects by up to (%d+)%.", + ["^Set: Allows (%d+)%% of your Mana regeneration to continue while casting."] = "^Set: Allows (%d+)%% of your Mana regeneration to continue while casting.", + + ["Equip: Improves your chance to hit by (%d)%%."] = "Equip: Improves your chance to hit by (%d)%%.", + ["Equip: Improves your chance to get a critical strike with spells by (%d)%%."] = "Equip: Improves your chance to get a critical strike with spells by (%d)%%.", + ["Equip: Improves your chance to hit with spells by (%d)%%."] = "Equip: Improves your chance to hit with spells by (%d)%%.", + + ["Increases your chance to hit with melee weapons by (%d)%%."] = "Increases your chance to hit with melee weapons by (%d)%%.", + ["Increases your critical strike chance with ranged weapons by (%d)%%."] = "Increases your critical strike chance with ranged weapons by (%d)%%.", + ["Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%."] = "Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%.", + ["Increases your critical strike chance with all attacks by (%d)%%."] = "Increases your critical strike chance with all attacks by (%d)%%.", + ["Increases spell damage and healing by up to (%d+)%% of your total Spirit."] = "Increases spell damage and healing by up to (%d+)%% of your total Spirit.", + ["Allows (%d+)%% of your Mana regeneration to continue while casting."] = "Allows (%d+)%% of your Mana regeneration to continue while casting.", + ["Reduces the chance that the opponent can resist your Frost and Fire spells by (%d)%%."] = "Reduces the chance that the opponent can resist your Frost and Fire spells by (%d)%%.", + ["Reduces the chance that the opponent can resist your Arcane spells by (%d+)%%."] = "Reduces the chance that the opponent can resist your Arcane spells by (%d+)%%.", + ["Reduces your target's chance to resist your Shadow spells by (%d+)%%."] = "Reduces your target's chance to resist your Shadow spells by (%d+)%%.", + + ["Equip: Increases damage done by Arcane spells and effects by up to (%d+)."] = "Equip: Increases damage done by Arcane spells and effects by up to (%d+).", + ["Equip: Increases damage done by Fire spells and effects by up to (%d+)."] = "Equip: Increases damage done by Fire spells and effects by up to (%d+).", + ["Equip: Increases damage done by Frost spells and effects by up to (%d+)."] = "Equip: Increases damage done by Frost spells and effects by up to (%d+).", + ["Equip: Increases damage done by Holy spells and effects by up to (%d+)."] = "Equip: Increases damage done by Holy spells and effects by up to (%d+).", + ["Equip: Increases damage done by Nature spells and effects by up to (%d+)."] = "Equip: Increases damage done by Nature spells and effects by up to (%d+).", + ["Equip: Increases damage done by Shadow spells and effects by up to (%d+)."] = "Equip: Increases damage done by Shadow spells and effects by up to (%d+).", + + ["Shadow Damage %+(%d+)"] = "Shadow Damage %+(%d+)", + ["Spell Damage %+(%d+)"] = "Spell Damage %+(%d+)", + ["Fire Damage %+(%d+)"] = "Fire Damage %+(%d+)", + ["Frost Damage %+(%d+)"] = "Frost Damage %+(%d+)", + ["Healing Spells %+(%d+)"] = "Healing Spells %+(%d+)", + ["^Healing %+(%d+) and %d+ mana per 5 sec."] = "^Healing %+(%d+) and %d+ mana per 5 sec.", + + ["Equip: Restores (%d+) mana per 5 sec."] = "Equip: Restores (%d+) mana per 5 sec.", + ["+(%d)%% Hit"] = "+(%d)%% Hit", + + -- Random Bonuses // https://wow.gamepedia.com/index.php?title=SuffixId&oldid=204406 + ["^%+(%d+) Damage and Healing Spells"] = "^%+(%d+) Damage and Healing Spells", + ["^%+(%d+) Arcane Spell Damage"] = "^%+(%d+) Arcane Spell Damage", + ["^%+(%d+) Fire Spell Damage"] = "^%+(%d+) Fire Spell Damage", + ["^%+(%d+) Frost Spell Damage"] = "^%+(%d+) Frost Spell Damage", + ["^%+(%d+) Holy Spell Damage"] = "^%+(%d+) Holy Spell Damage", + ["^%+(%d+) Nature Spell Damage"] = "^%+(%d+) Nature Spell Damage", + ["^%+(%d+) Shadow Spell Damage"] = "^%+(%d+) Shadow Spell Damage", + ["^%+(%d+) mana every 5 sec."] = "^%+(%d+) mana every 5 sec.", + ["Restores (%d+) mana every 1 sec."] = "Restores (%d+) mana every 1 sec.", + ["(%d+)%% of your Mana regeneration continuing while casting."] = "(%d+)%% of your Mana regeneration continuing while casting.", + + -- Mana Oils + ["^Brilliant Mana Oil %((%d+) min%"] = "^Brilliant Mana Oil %((%d+) min%", + ["^Lesser Mana Oil ((%d+) min)"] = "^Lesser Mana Oil ((%d+) min)", + ["^Minor Mana Oil ((%d+) min)"] = "^Minor Mana Oil ((%d+) min)", + + -- snowflakes ZG enchants + ["/Hit %+(%d+)"] = "/Hit %+(%d+)", + ["/Spell Hit %+(%d+)"] = "/Spell Hit %+(%d+)", + ["^Mana Regen %+(%d+)"] = "^Mana Regen %+(%d+)", + ["^Healing %+%d+ and (%d+) mana per 5 sec."] = "^Healing %+%d+ and (%d+) mana per 5 sec.", + ["^%+(%d+) Healing Spells"] = "^%+(%d+) Healing Spells", + ["^%+(%d+) Spell Damage and Healing"] = "^%+(%d+) Spell Damage and Healing", + + ["Equip: Increases damage and healing done by magical spells and effects by up to (%d+)."] = "Equip: Increases damage and healing done by magical spells and effects by up to (%d+).", + ["Equip: Increases healing done by spells and effects by up to (%d+)."] = "Equip: Increases healing done by spells and effects by up to (%d+).", + + -- auras + ["Chance to hit increased by (%d)%%."] = "Chance to hit increased by (%d)%%.", + ["Magical damage dealt is increased by up to (%d+)."] = "Magical damage dealt is increased by up to (%d+).", + ["Healing done by magical spells is increased by up to (%d+)."] = "Healing done by magical spells is increased by up to (%d+).", + ["Increases healing done by magical spells by up to (%d+) for 3600 sec."] = "Increases healing done by magical spells by up to (%d+) for 3600 sec.", + ["Healing increased by up to (%d+)."] = "Healing increased by up to (%d+).", + ["Healing spells increased by up to (%d+)."] = "Healing spells increased by up to (%d+).", + ["Chance to hit reduced by (%d+)%%."] = "Chance to hit reduced by (%d+)%%.", + ["Chance to hit decreased by (%d+)%% and %d+ Nature damage every %d+ sec."] = "Chance to hit decreased by (%d+)%% and %d+ Nature damage every %d+ sec.", + ["Lowered chance to hit."] = "Lowered chance to hit.", -- 5917 Fumble (25%) + ["Increases hitpoints by 300. 15%% haste to melee attacks. (%d+) mana regen every 5 seconds."] = "Increases hitpoints by 300. 15%% haste to melee attacks. (%d+) mana regen every 5 seconds.", + ["Restores (%d+) mana per 5 sec."] = "Restores (%d+) mana per 5 sec.", + ["Regenerating (%d+) Mana every 5 seconds."] = "Regenerating (%d+) Mana every 5 seconds.", + ["Regenerate (%d+) mana per 5 sec."] = "Regenerate (%d+) mana per 5 sec.", + ["Mana Regeneration increased by (%d+) every 5 seconds."] = "Mana Regeneration increased by (%d+) every 5 seconds.", + ["Improves your chance to hit by (%d+)%%."] = "Improves your chance to hit by (%d+)%%.", + ["Chance for a critical hit with a spell increased by (%d+)%%."] = "Chance for a critical hit with a spell increased by (%d+)%%.", + ["While active, target's critical hit chance with spells and attacks increases by 10%%."] = "While active, target's critical hit chance with spells and attacks increases by 10%%.", + ["Increases attack power by %d+ and chance to hit by (%d+)%%."] = "Increases attack power by %d+ and chance to hit by (%d+)%%.", + ["Holy spell critical hit chance increased by (%d+)%%."] = "Holy spell critical hit chance increased by (%d+)%%.", + ["Destruction spell critical hit chance increased by (%d+)%%."] = "Destruction spell critical hit chance increased by (%d+)%%.", + ["Arcane spell critical hit chance increased by (%d+)%%.\r\nArcane spell critical hit damage increased by (%d+)%%."] = "Arcane spell critical hit chance increased by (%d+)%%.\r\nArcane spell critical hit damage increased by (%d+)%%.", + ["Spell hit chance increased by (%d+)%%."] = "Spell hit chance increased by (%d+)%%.", + + ["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."] = "Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+.", + ["Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%."] = "Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%.", + ["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."] = "Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration.", + ["Critical strike chance with spells and melee attacks increased by (%d+)%%."] = "Critical strike chance with spells and melee attacks increased by (%d+)%%.", + + + ["DEFENSE_TOOLTIP"] = [[|cffffffffDefense Skill|r]], + ["DEFENSE_TOOLTIP_SUB"] = [[Highier defense makes you harder to hit and makes monsters less likely to land a crushing blow.]], + + ["PLAYER_DODGE_TOOLTIP"] = [[|cffffffffDodge|r]], + ["PLAYER_DODGE_TOOLTIP_SUB"] = [[Your chance to dodge enemy melee attacks. + Players can not dodge attacks from behind.]], + + ["PLAYER_PARRY_TOOLTIP"] = [[|cffffffffParry|r]], + ["PLAYER_PARRY_TOOLTIP_SUB"] = [[Your chance to parry enemy melee attacks. + Players and monsters can not parry attacks from behind.]], + + ["PLAYER_BLOCK_TOOLTIP"] = [[|cffffffffBlock|r]], + ["PLAYER_BLOCK_TOOLTIP_SUB"] = [[Your chance to block enemy physical attacks with a shield. + Players and monsters can not block attacks from behind.]], + + ["TOTAL_AVOIDANCE_TOOLTIP"] = [[|cffffffffAvoidance|r]], + ["TOTAL_AVOIDANCE_TOOLTIP_SUB"] = [[Your combined chance to dodge, parry and block enemy physical attacks.]], + + + ["MELEE_HIT_TOOLTIP"] = [[|cffffffffHit|r]], + ["MELEE_HIT_TOOLTIP_SUB"] = [[Increases chance to hit with melee attacks and ranged weapons.]], + + ["MELEE_CRIT_TOOLTIP"] = [[|cffffffffCrit|r]], + ["MELEE_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with melee attacks or ranged weapons.]], + + ["MELEE_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffMelee Weapon Skill|r]], + ["MELEE_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss and increases damage of your glancing blows, while using melee weapons. + A glancing blow deals reduced damage and can not crit.]], + + ["RANGED_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffRanged Weapon Skill|r]], + ["RANGED_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss with a ranged weapon.]], + + + ["SPELL_HIT_TOOLTIP"] = [[|cffffffffSpell Hit|r]], + ["SPELL_HIT_SECONDARY_TOOLTIP"] = [[|cffffffffSpell Hit%d%% (%d%%|cff20ff20+%d%% %s|r|cffffffff)|rIncreases chance to land a spell.]], + ["SPELL_HIT_TOOLTIP_SUB"] = [[Increases chance to land a harmful spell.]], + + ["SPELL_CRIT_TOOLTIP"] = [[|cffffffffSpell Crit|r]], + ["SPELL_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with spells.]], + + ["SPELL_POWER_TOOLTIP"] = [[|cffffffffSpell Power %d|r]], + ["SPELL_POWER_TOOLTIP_SUB"] = [[Increases damage done by spells and effects.]], + ["SPELL_POWER_SECONDARY_TOOLTIP"] = [[|cffffffffSpell Power %d (%d|cff20ff20+%d %s|r|cffffffff)|r]], + ["SPELL_POWER_SECONDARY_TOOLTIP_SUB"] = [[Increases damage done by spells and effects.]], + + ["SPELL_SCHOOL_TOOLTIP"] = [[|cffffffff%s Spell Power|r]], + ["SPELL_SCHOOL_TOOLTIP_SUB"] = [[Increases damage done by %s spells and effects.]], + + ["SPELL_HEALING_POWER_TOOLTIP"] = [[|cffffffffHealing Power %d|r]], + ["SPELL_HEALING_POWER_SECONDARY_TOOLTIP"] = [[|cffffffffHealing Power %d (%d|cff20ff20+%d|r|cffffffff)|r]], + ["SPELL_HEALING_POWER_TOOLTIP_SUB"] = [[Increases healing done by spells and effects.]], + + ["SPELL_MANA_REGEN_TOOLTIP"] = [[|cffffffffMana regen: %d |cffBF40BF(%d)|r]], + ["SPELL_MANA_REGEN_TOOLTIP_SUB"] = [[Mana regen when not casting and |cffBF40BF(while casting)|r. + Mana regenerates every 2 seconds and the amount is dependent on your total spirit and MP5. + Spirit Regen: |cff7DF9FF%d|r + Regen while casting: |cffBF40BF%d%%|r + MP5 Regen: |cff20ff20%d|r + MP5 Regen (2s): |cff20ff20%d|r]], + + -- unused + ["ROGUE_MELEE_HIT_TOOLTIP"] = [[ + +5% hit to always hit enemy players. + +8% hit to always hit with your special abilities against a raid boss. + +24.6% hit to always hit a raid boss.]], + + ["DODGE_CHANCE_TOOLTIP"] = [[|cffffffffDodge Chance|r + Boss level creatures have a + highier chance to dodge your attacks.]], + ["GLANCE_TOOLTIP"] = [[|cffffffffGlancing Blow Damage|r + A glancing blow deals reduced damage + and can not crit.]], + ["CRIT_CAP_TOOLTIP"] = [[|cffffffffCrit Cap|r + Highiest possible crit chance you can achieve + for white hits, while attacking boss from behind.]], + ["EFFECTIVE_CRIT_TOOLTIP"] = [[|cffffffffEffective Crit Chance|r + You have less crit vs bosses.]], + ["MELEE_HIT_VS_BOSS_TOOLTIP"] = [[|cffffffffSpecial Miss|r + Special ability miss chance: |cffffffff%.1f%%|r]], + ------ + + PLAYERSTAT_BASE_STATS = "Base Stats", + PLAYERSTAT_DEFENSES = "Defenses", + PLAYERSTAT_MELEE_COMBAT = "Melee", + PLAYERSTAT_MELEE_BOSS = "Melee vs Boss", + PLAYERSTAT_RANGED_COMBAT = "Ranged", + PLAYERSTAT_SPELL_COMBAT = "Spell", + PLAYERSTAT_SPELL_SCHOOLS = "Schools", + WEAPON_SKILL_COLON = "Skill:", + MELEE_HIT_RATING_COLON = "Hit Rating:", + RANGED_HIT_RATING_COLON = "Hit Rating:", + SPELL_HIT_RATING_COLON = "Hit Rating:", + MELEE_CRIT_COLON = "Crit Chance:", + RANGED_CRIT_COLON = "Crit Chance:", + SPELL_CRIT_COLON = "Crit Chance:", + MANA_REGEN_COLON = "Mana regen:", + HEAL_POWER_COLON = "Healing:", + DODGE_COLON = DODGE .. ":", + PARRY_COLON = PARRY .. ":", + BLOCK_COLON = BLOCK .. ":", + TOTAL_COLON = "Total:", + SPELL_POWER_COLON = "Power:", + SPELL_SCHOOL_ARCANE = "Arcane", + SPELL_SCHOOL_FIRE = "Fire", + SPELL_SCHOOL_FROST = "Frost", + SPELL_SCHOOL_HOLY = "Holy", + SPELL_SCHOOL_NATURE = "Nature", + SPELL_SCHOOL_SHADOW = "Shadow", + + -- unused + MISS_CHANCE_COLON = "Miss:", + DODGE_CHANCE_COLON = "Dodge:", + GLANCE_REDUCTION_COLON = "Glance:", + CRIT_CAP_COLON = "Cap:", + BOSS_CRIT_COLON = "E.Crit:", + + + +} diff --git a/helper.lua b/helper.lua index 2bb87c0..29215a7 100644 --- a/helper.lua +++ b/helper.lua @@ -364,7 +364,7 @@ function BCS:GetSpellHitRating() -- Paladin & Shaman -- Precision & Nature's Guidance - _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee attacks and spells by (%d+)%%.") + _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee weapons and spells by (%d+)%%.") local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) if value and rank > 0 then hit = hit + tonumber(value) @@ -1155,4 +1155,4 @@ function BCS:GetManaRegen() casting = 100 end return base, casting, mp5 -end \ No newline at end of file +end From 2095f8264905459878d2d93c660ea5674f3702a7 Mon Sep 17 00:00:00 2001 From: Spit <110714733+Otari98@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:37:56 +0300 Subject: [PATCH 02/39] Danonzo food buff + new spell crit formula --- helper.lua | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/helper.lua b/helper.lua index 29215a7..33b5bd1 100644 --- a/helper.lua +++ b/helper.lua @@ -548,6 +548,22 @@ function BCS:GetSpellCritChance() local _, intelect = UnitStat("player", 4) local _, class = UnitClass("player") + -- values from vmangos core + local playerLevel = UnitLevel("player") + if class == "MAGE" then + spellCrit = 3.7 + intelect / (14.77 + .65 * playerLevel) + elseif class == "WARLOCK" then + spellCrit = 3.18 + intelect / (11.30 + .82 * playerLevel) + elseif class == "PRIEST" then + spellCrit = 2.97 + intelect / (10.03 + .82 * playerLevel) + elseif class == "DRUID" then + spellCrit = 3.33 + intelect / (12.41 + .79 * playerLevel) + elseif class == "SHAMAN" then + spellCrit = 3.54 + intelect / (11.51 + .8 * playerLevel) + elseif class == "PALADIN" then + spellCrit = 3.7 + intelect / (14.77 + .65 * playerLevel) + end + --[[ -- values from theorycraft / http://wow.allakhazam.com/forum.html?forum=21&mid=1157230638252681707 if class == "MAGE" then spellCrit = 0.2 + (intelect / 59.5) @@ -562,7 +578,7 @@ function BCS:GetSpellCritChance() elseif class == "PALADIN" then spellCrit = intelect / 29.5 end - + --]] local MAX_INVENTORY_SLOTS = 19 for slot=0, MAX_INVENTORY_SLOTS do @@ -865,6 +881,12 @@ function BCS:GetSpellPower(school) spellPower = spellPower + tonumber(spellPowerFromAura) damagePower = damagePower + tonumber(spellPowerFromAura) end + + _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell Damage increased by (%d+)") + if spellPowerFromAura then + spellPower = spellPower + tonumber(spellPowerFromAura) + damagePower = damagePower + tonumber(spellPowerFromAura) + end local secondaryPower = 0 local secondaryPowerName = "" From a37dfe1e934ad44512393fffd4e045f94094791c Mon Sep 17 00:00:00 2001 From: Spit <110714733+Otari98@users.noreply.github.com> Date: Sat, 31 Aug 2024 19:20:56 +0300 Subject: [PATCH 03/39] Removed colored hit rating for rogues --- BetterCharacterStats.lua | 39 ++------------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index cad968a..badbe45 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -14,18 +14,6 @@ BCS.PLAYERSTAT_DROPDOWN_OPTIONS = { "PLAYERSTAT_DEFENSES", } -BCS.MELEEHIT = { - ["ROGUE"] = { - 5, -- pvp - 8, -- yellow cap - 24.6, -- white cap - }, -} - -BCS.SPELLHIT = { - -- soon(tm) -} - BCS.PaperDollFrame = PaperDollFrame BCS.Debug = false @@ -756,22 +744,9 @@ function BCS:SetRating(statFrame, ratingType) label:SetText(L.MELEE_HIT_RATING_COLON) - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - if ratingType == "MELEE" then local rating = BCS:GetHitRating() - if BCS.MELEEHIT[BCS.playerClass] then - if rating < BCS.MELEEHIT[BCS.playerClass][1] then - rating = colorNeg .. rating .. "%|r" - elseif rating >= BCS.MELEEHIT[BCS.playerClass][2] then - rating = colorPos .. rating .. "%|r" - else - rating = rating .. "%" - end - else - rating = rating .. "%" - end + rating = rating .. "%" text:SetText(rating) frame.tooltip = (L.MELEE_HIT_TOOLTIP) @@ -779,17 +754,7 @@ function BCS:SetRating(statFrame, ratingType) elseif ratingType == "RANGED" then local rating = BCS:GetRangedHitRating() - if BCS.MELEEHIT[BCS.playerClass] then - if rating < BCS.MELEEHIT[BCS.playerClass][1] then - rating = colorNeg .. rating .. "%|r" - elseif rating >= BCS.MELEEHIT[BCS.playerClass][2] then - rating = colorPos .. rating .. "%|r" - else - rating = rating .. "%" - end - else - rating = rating .. "%" - end + rating = rating .. "%" text:SetText(rating) frame.tooltip = (L.MELEE_HIT_TOOLTIP) From 53934b576dd215cffce13fed89c63a7535e12d11 Mon Sep 17 00:00:00 2001 From: Spit <110714733+Otari98@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:21:22 +0300 Subject: [PATCH 04/39] Cleanup --- BetterCharacterStats.lua | 195 +-------------------------------------- Localization.lua | 41 +------- helper.lua | 2 +- 3 files changed, 6 insertions(+), 232 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index badbe45..8980c78 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -7,7 +7,6 @@ L = BCS.L BCS.PLAYERSTAT_DROPDOWN_OPTIONS = { "PLAYERSTAT_BASE_STATS", "PLAYERSTAT_MELEE_COMBAT", - --"PLAYERSTAT_MELEE_BOSS", "PLAYERSTAT_RANGED_COMBAT", "PLAYERSTAT_SPELL_COMBAT", "PLAYERSTAT_SPELL_SCHOOLS", @@ -235,7 +234,7 @@ function BCS:SetArmor(statFrame) GameTooltip:Hide() end) end - +--Weapon Skill code taken from https://github.com/pepopo978/BetterCharacterStats function BCS:GetSlotItemId(slot) local _, _, id = string.find(GetInventoryItemLink("player", GetInventorySlotInfo(slot)) or "", "item:(%d+):%d+:%d+:%d+"); if id then @@ -370,57 +369,6 @@ function BCS:GetRangedWeaponSkill() return BCS:GetWeaponSkillForWeaponType(itemType) end -function BCS:GetMissChanceRaw(wepSkill) - local diff = wepSkill - 315 - local miss = 5 - - if diff < -10 then - miss = miss - diff * 0.2; - else - miss = miss - diff * 0.1; - end - - local hitChance = BCS:GetHitRating() - -- if skill diff < -10 then subtract one from +hit, if there is any +hit - if (diff < -10) and (hitChance > 0) then - hitChance = hitChance - 1 - end - miss = miss - hitChance - - return miss -end - -function BCS:GetMissChance(wepSkill) - return max(0, min(BCS:GetMissChanceRaw(wepSkill),60)) -end - -function BCS:GetDualWieldMissChance(wepSkill) - return max(0,min(BCS:GetMissChanceRaw(wepSkill)+19,60)) -end - -function BCS:GetGlanceChance(wepSkill) - return 10 + 15 * 2; -end - -function BCS:GetGlanceReduction(wepSkill) - local diff = 315 - wepSkill; - local low = math.max(math.min(1.3 - 0.05 * diff, 0.91), 0.01); - local high = math.max(math.min(1.2 - 0.03 * diff, 0.99), 0.2); - return 100 * ((high - low) / 2 + low); -end - -function BCS:GetDodgeChance(wepSkill) - return math.max(5 + (315 - wepSkill) * 0.1, 0); -end - -function BCS:GetDualWieldCritCap(wepSkill) - return 100 - self:GetDualWieldMissChance(wepSkill) - self:GetGlanceChance(wepSkill) - self:GetDodgeChance(wepSkill); -end - -function BCS:GetCritCap(wepSkill) - return 100 - self:GetMissChance(wepSkill) - self:GetGlanceChance(wepSkill) - self:GetDodgeChance(wepSkill); -end - function BCS:SetDamage(statFrame) local label = getglobal(statFrame:GetName() .. "Label") label:SetText(TEXT(DAMAGE_COLON)) @@ -625,8 +573,6 @@ function BCS:SetAttackSpeed(statFrame) local value = getglobal(statFrame:GetName() .. "StatText") label:SetText(TEXT(SPEED) .. ":") value:SetText(text) - --statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE; - --statFrame.tooltip = format(CR_HASTE_RATING_TOOLTIP, GetCombatRating(CR_HASTE_MELEE), GetCombatRatingBonus(CR_HASTE_MELEE)); statFrame:SetScript("OnEnter", CharacterDamageFrame_OnEnter) statFrame:SetScript("OnLeave", function() GameTooltip:Hide() @@ -762,17 +708,6 @@ function BCS:SetRating(statFrame, ratingType) elseif ratingType == "SPELL" then local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow = BCS:GetSpellHitRating() - --[[if BCS.SPELLHIT[BCS.playerClass] then - if spell_hit < BCS.SPELLHIT[BCS.playerClass][1] then - spell_hit = colorNeg .. spell_hit .. "%|r" - elseif spell_hit >= BCS.SPELLHIT[BCS.playerClass][2] then - spell_hit = colorPos .. spell_hit .. "%|r" - else - spell_hit = spell_hit .. "%" - end - else - spell_hit = spell_hit .. "%" - end]] if spell_hit_fire > 0 or spell_hit_frost > 0 or spell_hit_arcane > 0 or spell_hit_shadow > 0 then -- got spell hit from talents @@ -891,127 +826,6 @@ function BCS:SetRangedWeaponSkill(statFrame) end) end -function BCS:SetMissChance(statFrame) - local frame = statFrame - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - label:SetText(L.MISS_CHANCE_COLON) - - local mh_miss = BCS:GetMissChance(BCS:GetMHWeaponSkill()) - - if OffhandHasWeapon() == 1 then - text:SetText(format("%.1f%%|%.1f%%", - BCS:GetDualWieldMissChance(BCS:GetMHWeaponSkill()), - BCS:GetDualWieldMissChance(BCS:GetOHWeaponSkill()))) - else - text:SetText(format("%.1f%%", mh_miss)) - end - - frame.tooltip = format(L.MELEE_HIT_VS_BOSS_TOOLTIP, mh_miss) - - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -end - -function BCS:SetGlanceReduction(statFrame) - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - label:SetText(L.GLANCE_REDUCTION_COLON) - - if OffhandHasWeapon() == 1 then - text:SetText(format("%d%% |%d%%", - BCS:GetGlanceReduction(BCS:GetMHWeaponSkill()), - BCS:GetGlanceReduction(BCS:GetOHWeaponSkill()))) - else - text:SetText(format("%d%%", BCS:GetGlanceReduction(BCS:GetMHWeaponSkill()))) - end - statFrame.tooltip = L.GLANCE_TOOLTIP - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -end - -function BCS:SetDodgeChance(statFrame) - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - label:SetText(L.DODGE_CHANCE_COLON) - - if OffhandHasWeapon() == 1 then - text:SetText(format("%.1f%% |%.1f%%", - BCS:GetDodgeChance(BCS:GetMHWeaponSkill()), - BCS:GetDodgeChance(BCS:GetOHWeaponSkill()))) - else - text:SetText(format("%.1f%%", BCS:GetDodgeChance(BCS:GetMHWeaponSkill()))) - end - statFrame.tooltip = L.DODGE_CHANCE_TOOLTIP - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -end - -function BCS:SetCritCap(statFrame) - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - label:SetText(L.CRIT_CAP_COLON) - if OffhandHasWeapon() == 1 then - text:SetText(format("%.1f%%|%.1f%%", - BCS:GetDualWieldCritCap(BCS:GetMHWeaponSkill()), - BCS:GetDualWieldCritCap(BCS:GetOHWeaponSkill()))) - else - text:SetText(format("%.1f%%", BCS:GetCritCap(BCS:GetMHWeaponSkill()))) - end - statFrame.tooltip = L.CRIT_CAP_TOOLTIP - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -end - -function BCS:SetBossCrit(statFrame) - local text = getglobal(statFrame:GetName() .. "StatText") - local label = getglobal(statFrame:GetName() .. "Label") - label:SetText(L.BOSS_CRIT_COLON) - - local critChance = BCS:GetCritChance() - 3 -- 3 % crit reduction vs lvl 63 - if OffhandHasWeapon() == 1 then - text:SetText(format("%.1f%%|%.1f%%", - math.min(critChance, BCS:GetDualWieldCritCap(BCS:GetMHWeaponSkill())), - math.min(critChance, BCS:GetDualWieldCritCap(BCS:GetOHWeaponSkill())) - )) - else - text:SetText(format("%.1f%%", math.min(critChance, BCS:GetCritCap(BCS:GetMHWeaponSkill())))) - end - statFrame.tooltip = L.EFFECTIVE_CRIT_TOOLTIP - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -end - function BCS:SetSpellCritChance(statFrame) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") @@ -1481,13 +1295,6 @@ function BCS:UpdatePaperdollStats(prefix, index) BCS:SetAttackPower(stat4) BCS:SetRating(stat5, "MELEE") BCS:SetMeleeCritChance(stat6) - elseif (index == "PLAYERSTAT_MELEE_BOSS") then - BCS:SetWeaponSkill(stat1) - BCS:SetMissChance(stat2) - BCS:SetDodgeChance(stat3) - BCS:SetGlanceReduction(stat4) - BCS:SetCritCap(stat5) - BCS:SetBossCrit(stat6) elseif (index == "PLAYERSTAT_RANGED_COMBAT") then BCS:SetRangedWeaponSkill(stat1) BCS:SetRangedDamage(stat2) diff --git a/Localization.lua b/Localization.lua index e765196..e111885 100644 --- a/Localization.lua +++ b/Localization.lua @@ -99,7 +99,7 @@ BCS["L"] = { ["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."] = "Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration.", ["Critical strike chance with spells and melee attacks increased by (%d+)%%."] = "Critical strike chance with spells and melee attacks increased by (%d+)%%.", - + --defense ["DEFENSE_TOOLTIP"] = [[|cffffffffDefense Skill|r]], ["DEFENSE_TOOLTIP_SUB"] = [[Highier defense makes you harder to hit and makes monsters less likely to land a crushing blow.]], @@ -118,7 +118,7 @@ BCS["L"] = { ["TOTAL_AVOIDANCE_TOOLTIP"] = [[|cffffffffAvoidance|r]], ["TOTAL_AVOIDANCE_TOOLTIP_SUB"] = [[Your combined chance to dodge, parry and block enemy physical attacks.]], - + --physical ["MELEE_HIT_TOOLTIP"] = [[|cffffffffHit|r]], ["MELEE_HIT_TOOLTIP_SUB"] = [[Increases chance to hit with melee attacks and ranged weapons.]], @@ -126,13 +126,12 @@ BCS["L"] = { ["MELEE_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with melee attacks or ranged weapons.]], ["MELEE_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffMelee Weapon Skill|r]], - ["MELEE_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss and increases damage of your glancing blows, while using melee weapons. - A glancing blow deals reduced damage and can not crit.]], + ["MELEE_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss and increases damage of your glancing blows, while using melee weapons.]], ["RANGED_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffRanged Weapon Skill|r]], ["RANGED_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss with a ranged weapon.]], - + --spells ["SPELL_HIT_TOOLTIP"] = [[|cffffffffSpell Hit|r]], ["SPELL_HIT_SECONDARY_TOOLTIP"] = [[|cffffffffSpell Hit%d%% (%d%%|cff20ff20+%d%% %s|r|cffffffff)|rIncreases chance to land a spell.]], ["SPELL_HIT_TOOLTIP_SUB"] = [[Increases chance to land a harmful spell.]], @@ -160,31 +159,9 @@ BCS["L"] = { MP5 Regen: |cff20ff20%d|r MP5 Regen (2s): |cff20ff20%d|r]], - -- unused - ["ROGUE_MELEE_HIT_TOOLTIP"] = [[ - +5% hit to always hit enemy players. - +8% hit to always hit with your special abilities against a raid boss. - +24.6% hit to always hit a raid boss.]], - - ["DODGE_CHANCE_TOOLTIP"] = [[|cffffffffDodge Chance|r - Boss level creatures have a - highier chance to dodge your attacks.]], - ["GLANCE_TOOLTIP"] = [[|cffffffffGlancing Blow Damage|r - A glancing blow deals reduced damage - and can not crit.]], - ["CRIT_CAP_TOOLTIP"] = [[|cffffffffCrit Cap|r - Highiest possible crit chance you can achieve - for white hits, while attacking boss from behind.]], - ["EFFECTIVE_CRIT_TOOLTIP"] = [[|cffffffffEffective Crit Chance|r - You have less crit vs bosses.]], - ["MELEE_HIT_VS_BOSS_TOOLTIP"] = [[|cffffffffSpecial Miss|r - Special ability miss chance: |cffffffff%.1f%%|r]], - ------ - PLAYERSTAT_BASE_STATS = "Base Stats", PLAYERSTAT_DEFENSES = "Defenses", PLAYERSTAT_MELEE_COMBAT = "Melee", - PLAYERSTAT_MELEE_BOSS = "Melee vs Boss", PLAYERSTAT_RANGED_COMBAT = "Ranged", PLAYERSTAT_SPELL_COMBAT = "Spell", PLAYERSTAT_SPELL_SCHOOLS = "Schools", @@ -208,14 +185,4 @@ BCS["L"] = { SPELL_SCHOOL_HOLY = "Holy", SPELL_SCHOOL_NATURE = "Nature", SPELL_SCHOOL_SHADOW = "Shadow", - - -- unused - MISS_CHANCE_COLON = "Miss:", - DODGE_CHANCE_COLON = "Dodge:", - GLANCE_REDUCTION_COLON = "Glance:", - CRIT_CAP_COLON = "Cap:", - BOSS_CRIT_COLON = "E.Crit:", - - - } diff --git a/helper.lua b/helper.lua index 33b5bd1..f9d7699 100644 --- a/helper.lua +++ b/helper.lua @@ -881,7 +881,7 @@ function BCS:GetSpellPower(school) spellPower = spellPower + tonumber(spellPowerFromAura) damagePower = damagePower + tonumber(spellPowerFromAura) end - + --turtle wow spell power food _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell Damage increased by (%d+)") if spellPowerFromAura then spellPower = spellPower + tonumber(spellPowerFromAura) From 3447230f579e0b9e7fbdcf3c74d5dbe670745788 Mon Sep 17 00:00:00 2001 From: Spit <110714733+Otari98@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:20:32 +0300 Subject: [PATCH 05/39] Added missing weapon skills --- BetterCharacterStats.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 8980c78..d50290c 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -318,6 +318,10 @@ function BCS:GetWeaponSkillForWeaponType(weaponType) return BCS:GetWeaponSkill("Maces") elseif weaponType == "Two-Handed Maces" then return BCS:GetWeaponSkill("Two-Handed Maces") + elseif weaponType == "Staves" then + return BCS:GetWeaponSkill("Staves") + elseif weaponType == "Polearms" then + return BCS:GetWeaponSkill("Polearms") elseif weaponType == "Fist Weapons" then return BCS:GetWeaponSkill("Unarmed") elseif weaponType == "Bows" then @@ -332,7 +336,7 @@ function BCS:GetWeaponSkillForWeaponType(weaponType) return BCS:GetWeaponSkill("Wands") end - return 0 + return BCS:GetWeaponSkill("Unarmed") end function BCS:GetItemInfoForSlot(slot) From 1f8d5295acc3f90990415da0714c6747d63193f4 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sat, 5 Oct 2024 12:59:08 +0300 Subject: [PATCH 06/39] circumvent twow bug include set bonuses from transmogged gear --- helper.lua | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/helper.lua b/helper.lua index f9d7699..783526e 100644 --- a/helper.lua +++ b/helper.lua @@ -77,8 +77,10 @@ function BCS:GetHitRating(hitOnly) hit_debuff = 0; for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) + local hasItem = GetInventoryItemLink('player', slot) if hasItem then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + BCS_Tooltip:SetHyperlink(eqItemLink) local MAX_LINES = BCS_Tooltip:NumLines() local SET_NAME = nil @@ -279,9 +281,10 @@ function BCS:GetSpellHitRating() -- scan gear local MAX_INVENTORY_SLOTS = 19 for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) - + local hasItem = GetInventoryItemLink('player', slot) if hasItem then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + BCS_Tooltip:SetHyperlink(eqItemLink) local SET_NAME local MAX_LINES = BCS_Tooltip:NumLines() @@ -582,9 +585,10 @@ function BCS:GetSpellCritChance() local MAX_INVENTORY_SLOTS = 19 for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) - + local hasItem = GetInventoryItemLink('player', slot) if hasItem then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + BCS_Tooltip:SetHyperlink(eqItemLink) local SET_NAME = nil for line=1, BCS_Tooltip:NumLines() do @@ -712,9 +716,10 @@ function BCS:GetSpellPower(school) -- scan gear for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) - + local hasItem = GetInventoryItemLink('player', slot) if hasItem then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + BCS_Tooltip:SetHyperlink(eqItemLink) local SET_NAME for line=1, BCS_Tooltip:NumLines() do @@ -926,9 +931,10 @@ function BCS:GetHealingPower() local MAX_INVENTORY_SLOTS = 19 for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) - + local hasItem = GetInventoryItemLink('player', slot) if hasItem then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + BCS_Tooltip:SetHyperlink(eqItemLink) local SET_NAME for line=1, BCS_Tooltip:NumLines() do @@ -1047,9 +1053,10 @@ function BCS:GetManaRegen() local MAX_INVENTORY_SLOTS = 19 for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) - + local hasItem = GetInventoryItemLink('player', slot) if hasItem then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + BCS_Tooltip:SetHyperlink(eqItemLink) local SET_NAME for line=1, BCS_Tooltip:NumLines() do From 69f8980e506d07c54b6048645b1d9c893e6986b8 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Mon, 7 Oct 2024 13:40:35 +0300 Subject: [PATCH 07/39] big update Added support for improved shadowform, mage armor Fixed ranged crit based on vmangos values Added support for tree of life and brilliance (unfortunately only counts from your own buff...for now) Update on gaining skills Bug fixes --- BetterCharacterStats.lua | 76 ++++++++--- Localization.lua | 38 +++--- helper.lua | 270 +++++++++++++++++++++++---------------- 3 files changed, 238 insertions(+), 146 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index d50290c..2700d71 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -75,7 +75,7 @@ function BCS:OnLoad() self.Frame:RegisterEvent("UNIT_INVENTORY_CHANGED") -- fires when equipment changes self.Frame:RegisterEvent("CHARACTER_POINTS_CHANGED") -- fires when learning talent self.Frame:RegisterEvent("PLAYER_AURAS_CHANGED") -- buffs/warrior stances - + self.Frame:RegisterEvent("CHAT_MSG_SKILL") --gaining weapon skill local _, classFileName = UnitClass("Player") self.playerClass = strupper(classFileName) end @@ -94,8 +94,9 @@ function BCS:OnEvent() end]] if - event == "PLAYER_AURAS_CHANGED" or - event == "CHARACTER_POINTS_CHANGED" + event == "PLAYER_AURAS_CHANGED" + or event == "CHARACTER_POINTS_CHANGED" + or event == "CHAT_MSG_SKILL" then if BCS.PaperDollFrame:IsVisible() then BCS:UpdateStats() @@ -691,7 +692,7 @@ function BCS:SetRating(statFrame, ratingType) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - + local _,class = UnitClass("player") label:SetText(L.MELEE_HIT_RATING_COLON) if ratingType == "MELEE" then @@ -705,10 +706,19 @@ function BCS:SetRating(statFrame, ratingType) elseif ratingType == "RANGED" then local rating = BCS:GetRangedHitRating() rating = rating .. "%" + -- If no ranged attack then set to n/a + if not (GetInventoryItemLink("player",18)) or + ((class == "PALADIN") + or(class == "DRUID") + or(class == "SHAMAN")) + then + text:SetText(NOT_APPLICABLE) + return + end text:SetText(rating) - frame.tooltip = (L.MELEE_HIT_TOOLTIP) - frame.tooltipSubtext = format(L.MELEE_HIT_TOOLTIP_SUB) + frame.tooltip = (L.RANGED_HIT_TOOLTIP) + frame.tooltipSubtext = format(L.RANGED_HIT_TOOLTIP_SUB) elseif ratingType == "SPELL" then local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow = BCS:GetSpellHitRating() @@ -853,12 +863,31 @@ end function BCS:SetRangedCritChance(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - + local crit = BCS:GetRangedCritChance() + local skill = BCS:GetRangedWeaponSkill() + local _, class = UnitClass("player") + local level = UnitLevel("player") + -- apply skill difference modifier + local skillDiff = skill - (level*5) + if (skill >= (level*5)) then + crit = crit + (skillDiff * 0.04) + else + crit = crit + (skillDiff * 0.2) + end + if crit < 0 then crit = 0 end label:SetText(L.RANGED_CRIT_COLON) - text:SetText(format("%.2f%%", BCS:GetRangedCritChance())) - - statFrame.tooltip = (L.MELEE_CRIT_TOOLTIP) - statFrame.tooltipSubtext = (L.MELEE_CRIT_TOOLTIP_SUB) + text:SetText(format("%.2f%%", crit)) + -- If no ranged attack then set to n/a + if not (GetInventoryItemLink("player",18)) + or((class == "PALADIN") + or(class == "DRUID") + or(class == "SHAMAN")) + then + text:SetText(NOT_APPLICABLE) + return + end + statFrame.tooltip = (L.RANGED_CRIT_TOOLTIP) + statFrame.tooltipSubtext = (L.RANGED_CRIT_TOOLTIP_SUB) statFrame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) @@ -876,14 +905,16 @@ function BCS:SetHealing(statFrame) local label = getglobal(statFrame:GetName() .. "Label") local power, _, _, dmg = BCS:GetSpellPower() - local heal = BCS:GetHealingPower() + local heal, treebonus = BCS:GetHealingPower() power = power - dmg + local total = power + heal + if treebonus then total = total + treebonus end label:SetText(L.HEAL_POWER_COLON) - text:SetText(power + heal) + text:SetText(format("%.f",total)) if heal ~= 0 then - frame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (power + heal), power, heal) + frame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (total), power, heal) else - frame.tooltip = format(L.SPELL_HEALING_POWER_TOOLTIP, (power + heal)) + frame.tooltip = format(L.SPELL_HEALING_POWER_TOOLTIP, (total)) end frame.tooltipSubtext = format(L.SPELL_HEALING_POWER_TOOLTIP_SUB) frame:SetScript("OnEnter", function() @@ -902,9 +933,10 @@ function BCS:SetManaRegen(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - local base, casting, mp5 = BCS:GetManaRegen() + local base, casting, mp5, brilliance = BCS:GetManaRegen() local mp2 = mp5 * 0.4 local totalRegen = base + mp2 + if brilliance then totalRegen = totalRegen + brilliance end local totalRegenWhileCasting = (casting / 100) * base + mp2 local _,class = UnitClass("player") label:SetText(L.MANA_REGEN_COLON) @@ -914,7 +946,7 @@ function BCS:SetManaRegen(statFrame) text:SetText(NOT_APPLICABLE) frame.tooltip = nil else - text:SetText(format("%d |cffBF40BF(%d)|r", totalRegen, totalRegenWhileCasting)) + text:SetText(format("%.0f (%.0f)", totalRegen, totalRegenWhileCasting)) frame.tooltip = format(L.SPELL_MANA_REGEN_TOOLTIP, totalRegen, totalRegenWhileCasting) frame.tooltipSubtext = format(L.SPELL_MANA_REGEN_TOOLTIP_SUB, base, casting, mp5, mp2) frame:SetScript("OnEnter", function() @@ -1208,7 +1240,11 @@ function BCS:SetRangedAttackPower(statFrame) frame.tooltip = nil return end - + if ( HasWandEquipped() ) then + text:SetText("--"); + frame.tooltip = nil; + return; + end local base, posBuff, negBuff = UnitRangedAttackPower("player") PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, frame, text) frame.tooltipSubtext = format(RANGED_ATTACK_POWER_TOOLTIP, base / ATTACK_POWER_MAGIC_NUMBER) @@ -1385,7 +1421,7 @@ function PlayerStatFrameRightDropDown_OnLoad() UIDropDownMenu_SetWidth(99, this) UIDropDownMenu_JustifyText("LEFT") end - +--[[ --pfUI.api.strsplit function hcstrsplit(delimiter, subject) if not subject then @@ -1457,4 +1493,4 @@ bcsupdater:SetScript("OnEvent", function() SendAddonMessage("bcs", "VERSION:" .. localversion, chan) end end -end) +end)]] diff --git a/Localization.lua b/Localization.lua index e111885..408aee7 100644 --- a/Localization.lua +++ b/Localization.lua @@ -10,11 +10,12 @@ BCS["L"] = { ["^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%."] = "^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%.", ["^Set: Increases healing done by spells and effects by up to (%d+)%."] = "^Set: Increases healing done by spells and effects by up to (%d+)%.", ["^Set: Allows (%d+)%% of your Mana regeneration to continue while casting."] = "^Set: Allows (%d+)%% of your Mana regeneration to continue while casting.", + ["^Set: Improves your chance to get a critical strike by (%d)%%."] = "^Set: Improves your chance to get a critical strike by (%d)%%.", ["Equip: Improves your chance to hit by (%d)%%."] = "Equip: Improves your chance to hit by (%d)%%.", ["Equip: Improves your chance to get a critical strike with spells by (%d)%%."] = "Equip: Improves your chance to get a critical strike with spells by (%d)%%.", ["Equip: Improves your chance to hit with spells by (%d)%%."] = "Equip: Improves your chance to hit with spells by (%d)%%.", - + ["Equip: Improves your chance to get a critical strike by (%d)%%."] = "Equip: Improves your chance to get a critical strike by (%d)%%.", ["Increases your chance to hit with melee weapons by (%d)%%."] = "Increases your chance to hit with melee weapons by (%d)%%.", ["Increases your critical strike chance with ranged weapons by (%d)%%."] = "Increases your critical strike chance with ranged weapons by (%d)%%.", ["Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%."] = "Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%.", @@ -53,6 +54,7 @@ BCS["L"] = { ["^%+(%d+) mana every 5 sec."] = "^%+(%d+) mana every 5 sec.", ["Restores (%d+) mana every 1 sec."] = "Restores (%d+) mana every 1 sec.", ["(%d+)%% of your Mana regeneration continuing while casting."] = "(%d+)%% of your Mana regeneration continuing while casting.", + ["(%d+)%% of your mana regeneration to continue while casting."] = "(%d+)%% of your mana regeneration to continue while casting.", -- Mana Oils ["^Brilliant Mana Oil %((%d+) min%"] = "^Brilliant Mana Oil %((%d+) min%", @@ -87,13 +89,13 @@ BCS["L"] = { ["Mana Regeneration increased by (%d+) every 5 seconds."] = "Mana Regeneration increased by (%d+) every 5 seconds.", ["Improves your chance to hit by (%d+)%%."] = "Improves your chance to hit by (%d+)%%.", ["Chance for a critical hit with a spell increased by (%d+)%%."] = "Chance for a critical hit with a spell increased by (%d+)%%.", - ["While active, target's critical hit chance with spells and attacks increases by 10%%."] = "While active, target's critical hit chance with spells and attacks increases by 10%%.", + ["While active, target's critical hit chance with spells and attacks increases by 10%%."] = "While active, target's critical hit chance with spells and attacks increases by 10%%.",--?? ["Increases attack power by %d+ and chance to hit by (%d+)%%."] = "Increases attack power by %d+ and chance to hit by (%d+)%%.", ["Holy spell critical hit chance increased by (%d+)%%."] = "Holy spell critical hit chance increased by (%d+)%%.", ["Destruction spell critical hit chance increased by (%d+)%%."] = "Destruction spell critical hit chance increased by (%d+)%%.", ["Arcane spell critical hit chance increased by (%d+)%%.\r\nArcane spell critical hit damage increased by (%d+)%%."] = "Arcane spell critical hit chance increased by (%d+)%%.\r\nArcane spell critical hit damage increased by (%d+)%%.", ["Spell hit chance increased by (%d+)%%."] = "Spell hit chance increased by (%d+)%%.", - + ["Agility increased by 25, Critical hit chance increases by (%d)%%."] = "Agility increased by 25, Critical hit chance increases by (%d)%%.", ["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."] = "Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+.", ["Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%."] = "Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%.", ["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."] = "Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration.", @@ -118,18 +120,20 @@ BCS["L"] = { ["TOTAL_AVOIDANCE_TOOLTIP"] = [[|cffffffffAvoidance|r]], ["TOTAL_AVOIDANCE_TOOLTIP_SUB"] = [[Your combined chance to dodge, parry and block enemy physical attacks.]], - --physical - ["MELEE_HIT_TOOLTIP"] = [[|cffffffffHit|r]], - ["MELEE_HIT_TOOLTIP_SUB"] = [[Increases chance to hit with melee attacks and ranged weapons.]], - - ["MELEE_CRIT_TOOLTIP"] = [[|cffffffffCrit|r]], - ["MELEE_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with melee attacks or ranged weapons.]], - + --melee + ["MELEE_HIT_TOOLTIP"] = [[|cffffffffMelee Hit|r]], + ["MELEE_HIT_TOOLTIP_SUB"] = [[Increases chance to hit with melee attacks.]], + ["MELEE_CRIT_TOOLTIP"] = [[|cffffffffMelee Crit|r]], + ["MELEE_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with melee attacks.]], ["MELEE_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffMelee Weapon Skill|r]], ["MELEE_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss and increases damage of your glancing blows, while using melee weapons.]], - + --ranged ["RANGED_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffRanged Weapon Skill|r]], ["RANGED_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss with a ranged weapon.]], + ["RANGED_CRIT_TOOLTIP"] = [[|cffffffffRanged Crit|r]], + ["RANGED_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with ranged weapons.]], + ["RANGED_HIT_TOOLTIP"] = [[|cffffffffRanged Hit|r]], + ["RANGED_HIT_TOOLTIP_SUB"] = [[Increases chance to hit with ranged weapons.]], --spells ["SPELL_HIT_TOOLTIP"] = [[|cffffffffSpell Hit|r]], @@ -151,13 +155,13 @@ BCS["L"] = { ["SPELL_HEALING_POWER_SECONDARY_TOOLTIP"] = [[|cffffffffHealing Power %d (%d|cff20ff20+%d|r|cffffffff)|r]], ["SPELL_HEALING_POWER_TOOLTIP_SUB"] = [[Increases healing done by spells and effects.]], - ["SPELL_MANA_REGEN_TOOLTIP"] = [[|cffffffffMana regen: %d |cffBF40BF(%d)|r]], - ["SPELL_MANA_REGEN_TOOLTIP_SUB"] = [[Mana regen when not casting and |cffBF40BF(while casting)|r. + ["SPELL_MANA_REGEN_TOOLTIP"] = [[|cffffffffMana regen: %d |cffffffff(%d)|r]], + ["SPELL_MANA_REGEN_TOOLTIP_SUB"] = [[Mana regen when not casting and (while casting). Mana regenerates every 2 seconds and the amount is dependent on your total spirit and MP5. - Spirit Regen: |cff7DF9FF%d|r - Regen while casting: |cffBF40BF%d%%|r - MP5 Regen: |cff20ff20%d|r - MP5 Regen (2s): |cff20ff20%d|r]], + Spirit Regen: |cffffffff%d|r + Regen while casting: |cffffffff%d%%|r + MP5 Regen: |cffffffff%d|r + MP5 Regen (2s): |cffffffff%d|r]], PLAYERSTAT_BASE_STATS = "Base Stats", PLAYERSTAT_DEFENSES = "Defenses", diff --git a/helper.lua b/helper.lua index 783526e..ea44d1d 100644 --- a/helper.lua +++ b/helper.lua @@ -75,7 +75,7 @@ function BCS:GetHitRating(hitOnly) local hit = 0; local MAX_INVENTORY_SLOTS = 19; hit_debuff = 0; - + --scan gear for slot=0, MAX_INVENTORY_SLOTS do local hasItem = GetInventoryItemLink('player', slot) if hasItem then @@ -173,7 +173,7 @@ function BCS:GetHitRating(hitOnly) return hit end end - + --scan talents for tab=1, MAX_TABS do local MAX_TALENTS = GetNumTalents(tab) @@ -336,7 +336,7 @@ function BCS:GetSpellHitRating() if value and rank > 0 then hit_fire = hit_fire + tonumber(value) hit_frost = hit_frost + tonumber(value) - line = MAX_LINES + break end -- Arcane Focus @@ -344,7 +344,7 @@ function BCS:GetSpellHitRating() local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) if value and rank > 0 then hit_arcane = hit_arcane + tonumber(value) - line = MAX_LINES + break end -- Priest @@ -353,7 +353,7 @@ function BCS:GetSpellHitRating() local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) if value and rank > 0 then hit_shadow = hit_shadow + tonumber(value) - line = MAX_LINES + break end -- Druid @@ -362,7 +362,7 @@ function BCS:GetSpellHitRating() local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) if value and rank > 0 then hit = hit + tonumber(value) - line = MAX_LINES + break end -- Paladin & Shaman @@ -371,7 +371,7 @@ function BCS:GetSpellHitRating() local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) if value and rank > 0 then hit = hit + tonumber(value) - line = MAX_LINES + break end end end @@ -392,58 +392,7 @@ local Cache_GetCritChance_SpellID, Cache_GetCritChance_BookType, Cache_GetCritCh local Cache_GetCritChance_Tab, Cache_GetCritChance_Talent function BCS:GetCritChance() local crit = 0 - local _, class = UnitClass('player') - - if class == 'HUNTER' then - - local MAX_TABS = GetNumTalentTabs() - -- speedup - if Cache_GetCritChance_Tab and Cache_GetCritChance_Talent then - BCS_Tooltip:SetTalent(Cache_GetCritChance_Tab, Cache_GetCritChance_Talent) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with all attacks by (%d)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(Cache_GetCritChance_Tab, Cache_GetCritChance_Talent) - if value and rank > 0 then - crit = crit + tonumber(value) - line = MAX_LINES - end - end - end - else - for tab=1, MAX_TABS do - local MAX_TALENTS = GetNumTalents(tab) - for talent=1, MAX_TALENTS do - BCS_Tooltip:SetTalent(tab, talent); - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with all attacks by (%d)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - crit = crit + tonumber(value) - - Cache_GetCritChance_Tab = tab - Cache_GetCritChance_Talent = talent - - line = MAX_LINES - talent = MAX_TALENTS - tab = MAX_TABS - end - end - end - - end - end - end - - end - + -- speedup if Cache_GetCritChance_SpellID and Cache_GetCritChance_BookType and Cache_GetCritChance_Line then @@ -458,7 +407,7 @@ function BCS:GetCritChance() return crit end - + --scan spellbook local MAX_TABS = GetNumSpellTabs() for tab=1, MAX_TABS do @@ -495,11 +444,26 @@ function BCS:GetCritChance() return crit end -local Cache_GetRangedCritChance_Tab, Cache_GetRangedCritChance_Talent, Cache_GetRangedCritChance_Line +--local Cache_GetRangedCritChance_Tab, Cache_GetRangedCritChance_Talent, Cache_GetRangedCritChance_Line function BCS:GetRangedCritChance() - local crit = BCS:GetCritChance() - - if Cache_GetRangedCritChance_Tab and Cache_GetRangedCritChance_Talent and Cache_GetRangedCritChance_Line then + -- values from vmangos core + local crit = 0 + local _, class = UnitClass("player") + local _, agility = UnitStat("player", 2) + local level = UnitLevel("player") + local vallvl1 = 0 + local vallvl60 = 0 + local classrate = 0 + if class == "MAGE" then vallvl1 = 12.9 vallvl60 = 20 + elseif class == "ROGUE" then vallvl1 = 2.2 vallvl60 = 29 + elseif class == "HUNTER" then vallvl1 = 3.5 vallvl60 = 53 + elseif class == "PRIEST" then vallvl1 = 11 vallvl60 = 20 + elseif class == "WARLOCK" then vallvl1 = 8.4 vallvl60 = 20 + elseif class == "WARRIOR" then vallvl1 = 3.9 vallvl60 = 20 + else return crit end + classrate = vallvl1 * (60 - level) / 59 + vallvl60 * (level - 1) / 59 + crit = agility / classrate + --[[if Cache_GetRangedCritChance_Tab and Cache_GetRangedCritChance_Talent and Cache_GetRangedCritChance_Line then BCS_Tooltip:SetTalent(Cache_GetRangedCritChance_Tab, Cache_GetRangedCritChance_Talent) local left = getglobal(BCS_Prefix .. "TextLeft" .. Cache_GetRangedCritChance_Line) @@ -509,11 +473,15 @@ function BCS:GetRangedCritChance() if value and rank > 0 then crit = crit + tonumber(value) end + _,_, value = strfind(left(GetText()), L["Increases your critical strike chance with all attacks by (%d)%%."]) + if value and rank > 0 then + crit = crit + tonumber(value) + end end - + return crit - end - + end]] + --scan talents local MAX_TABS = GetNumTalentTabs() for tab=1, MAX_TABS do @@ -530,17 +498,73 @@ function BCS:GetRangedCritChance() local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) if value and rank > 0 then crit = crit + tonumber(value) - - line = MAX_LINES - talent = MAX_TALENTS - tab = MAX_TABS + break + end + _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with all attacks by (%d)%%."]) + if value and rank > 0 then + crit = crit + tonumber(value) + break end end end end end - + --scan gear + local Crit_Set_Bonus = {} + local MAX_INVENTORY_SLOTS = 19 + for slot=0, MAX_INVENTORY_SLOTS do + local hasItem = GetInventoryItemLink('player', slot) + if hasItem then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + BCS_Tooltip:SetHyperlink(eqItemLink) + local SET_NAME + local MAX_LINES = BCS_Tooltip:NumLines() + + for line=1, MAX_LINES do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to get a critical strike by (%d)%%."]) + if value then + crit = crit + tonumber(value) + end + + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to get a critical strike by (%d)%%."]) + if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then + tinsert(Crit_Set_Bonus, SET_NAME) + crit = crit + tonumber(value) + end + end + end + + end + end + --buffs + --ony head + local critFromAura = BCS:GetPlayerAura(L["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."]) + if critFromAura then + crit = crit + 5 + end + --mongoose + _, _, critFromAura = BCS:GetPlayerAura(L["Agility increased by 25, Critical hit chance increases by (%d)%%."]) + if critFromAura then + crit = crit + tonumber(critFromAura) + end + --songflower + _, _, critFromAura = BCS:GetPlayerAura(L["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."]) + if critFromAura then + crit = crit + tonumber(critFromAura) + end + if class == "MAGE" then crit = crit + 3.2 + elseif class == "PRIEST" then crit = crit + 3 + elseif class == "WARLOCK" then crit = crit + 2 + end + return crit end @@ -582,6 +606,7 @@ function BCS:GetSpellCritChance() spellCrit = intelect / 29.5 end --]] + --scan gear local MAX_INVENTORY_SLOTS = 19 for slot=0, MAX_INVENTORY_SLOTS do @@ -639,7 +664,7 @@ function BCS:GetSpellCritChance() if critFromAura then spellCrit = spellCrit + tonumber(critFromAura) end - _, _, critFromAura = BCS:GetPlayerAura(L["While active, target's critical hit chance with spells and attacks increases by 10%%."]) + _, _, critFromAura = BCS:GetPlayerAura(L["While active, target's critical hit chance with spells and attacks increases by 10%%."])--SoD spell? 23964 if critFromAura then spellCrit = spellCrit + 10 end @@ -669,7 +694,7 @@ function BCS:GetSpellPower(school) if not L["Equip: Increases damage done by "..school.." spells and effects by up to (%d+)."] then return -1 end local spellPower = 0; local MAX_INVENTORY_SLOTS = 19 - + --scan gear for slot=0, MAX_INVENTORY_SLOTS do local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) @@ -852,9 +877,7 @@ function BCS:GetSpellPower(school) spellPower = spellPower + floor(((tonumber(value) / 100) * effectiveStat)) -- nothing more is currenlty supported, break out of the loops - line = MAX_LINES - talent = MAX_TALENTS - tab = MAX_TABS + break end end end @@ -929,7 +952,7 @@ function BCS:GetHealingPower() local healPower = 0; local healPower_Set_Bonus = {} local MAX_INVENTORY_SLOTS = 19 - + --scan gear for slot=0, MAX_INVENTORY_SLOTS do local hasItem = GetInventoryItemLink('player', slot) if hasItem then @@ -986,6 +1009,13 @@ function BCS:GetHealingPower() if healPowerFromAura then healPower = healPower + tonumber(healPowerFromAura) end + --Tree of Life (unfortunately only from self) + local found = BCS:GetPlayerAura("Tree of Life Form") and BCS:GetPlayerAura("Tree of Life Aura") + local _, spirit = UnitStat("player", 5) + local treebonus = nil + if found then + treebonus = spirit * 0.2 + end --Sweet Surprise _, _, healPowerFromAura = BCS:GetPlayerAura(L["Increases healing done by magical spells by up to (%d+) for 3600 sec."]) if healPowerFromAura then @@ -1016,7 +1046,7 @@ function BCS:GetHealingPower() healPower = healPower + tonumber(healPowerFromAura) end - return healPower + return healPower, treebonus end local function GetRegenMPPerSpirit() @@ -1051,7 +1081,7 @@ function BCS:GetManaRegen() local mp5 = 0 local mp5_Set_Bonus = {} local MAX_INVENTORY_SLOTS = 19 - + --scan gear for slot=0, MAX_INVENTORY_SLOTS do local hasItem = GetInventoryItemLink('player', slot) if hasItem then @@ -1114,31 +1144,16 @@ function BCS:GetManaRegen() end end - -- scan talents - local MAX_TABS = GetNumTalentTabs() - - for tab=1, MAX_TABS do - local MAX_TALENTS = GetNumTalents(tab) - - for talent=1, MAX_TALENTS do - BCS_Tooltip:SetTalent(tab, talent) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - -- Priest (Meditation) / Druid (Reflection) - local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - casting = casting + tonumber(value) - end - end + -- improved Shadowform + for i = 1, MAX_SKILLLINE_TABS do + local name, texture, offset, numSpells = GetSpellTabInfo(i); + for s = offset + 1, offset + numSpells do + local spell, rank = GetSpellName(s, BOOKTYPE_SPELL); + if spell == "Improved Shadowform" and BCS:GetPlayerAura("Shadowform") then + casting = casting + 15 end - end end - -- buffs -- Warchief's Blessing local _, _, mp5FromAura = BCS:GetPlayerAura(L["Increases hitpoints by 300. 15%% haste to melee attacks. (%d+) mana regen every 5 seconds."]) @@ -1170,18 +1185,55 @@ function BCS:GetManaRegen() if mp5FromAura then mp5 = mp5 + tonumber(mp5FromAura)*5 -- had to multiply by 5 the mp5FromAura because the item is a sec per tick end - --Aura of the blue dragon - _, _, castingFromAura = BCS:GetPlayerAura(L["(%d+)%% of your Mana regeneration continuing while casting."]) - if mp5FromAura then - casting = casting + tonumber(castingFromAura) - end --Power of the Guardian - _, _, castingFromAura = BCS:GetPlayerAura("Restores (%d+) mana per 5 seconds.") + _, _, mp5FromAura = BCS:GetPlayerAura("Restores (%d+) mana per 5 seconds.") if mp5FromAura then mp5 = mp5 + tonumber(mp5FromAura) end + --Aura of the blue dragon + local _, _, castingFromAura = BCS:GetPlayerAura(L["(%d+)%% of your Mana regeneration continuing while casting."]) + if castingFromAura then + casting = casting + tonumber(castingFromAura) + end + --Mage Armor + _, _, castingFromAura = BCS:GetPlayerAura(L["(%d+)%% of your mana regeneration to continue while casting."]) + if castingFromAura then + casting = casting + tonumber(castingFromAura) + end + + -- scan talents + local MAX_TABS = GetNumTalentTabs() + local brilliance = nil + for tab=1, MAX_TABS do + local MAX_TALENTS = GetNumTalents(tab) + + for talent=1, MAX_TALENTS do + BCS_Tooltip:SetTalent(tab, talent) + local MAX_LINES = BCS_Tooltip:NumLines() + + for line=1, MAX_LINES do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) + local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + if value and rank > 0 then + casting = casting + tonumber(value) + break + end + -- Brilliance Aura (unfortunately only from self) + local haveTalent = strfind(left:GetText(), "Brilliance Aura") + if haveTalent and rank > 0 and BCS:GetPlayerAura("Brilliance Aura") then + brilliance = (base + (mp5 * 0.4)) * 0.15 + end + end + end + + end + end if casting > 100 then casting = 100 end - return base, casting, mp5 + + return base, casting, mp5, brilliance end From 76b577895834809c0848b0bcc8a1e2e025567e99 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Tue, 8 Oct 2024 16:58:34 +0300 Subject: [PATCH 08/39] support for auras from other people Proper Tree of life Aura and Brilliance Aura support --- BetterCharacterStats.lua | 133 ++++++-- BetterCharacterStats.toc | 3 +- ChatThrottleLib/ChatThrottleLib.lua | 464 ++++++++++++++++++++++++++++ helper.lua | 4 +- 4 files changed, 570 insertions(+), 34 deletions(-) create mode 100644 ChatThrottleLib/ChatThrottleLib.lua diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 2700d71..f4f7f8d 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -3,7 +3,9 @@ BCSConfig = BCSConfig or {} local L, IndexLeft, IndexRight L = BCS.L - +--aura bonuses from other players; +--[1] - Tree of Life; [2] - Brilliance +local aura = { .0, .0 } BCS.PLAYERSTAT_DROPDOWN_OPTIONS = { "PLAYERSTAT_BASE_STATS", "PLAYERSTAT_MELEE_COMBAT", @@ -76,6 +78,7 @@ function BCS:OnLoad() self.Frame:RegisterEvent("CHARACTER_POINTS_CHANGED") -- fires when learning talent self.Frame:RegisterEvent("PLAYER_AURAS_CHANGED") -- buffs/warrior stances self.Frame:RegisterEvent("CHAT_MSG_SKILL") --gaining weapon skill + self.Frame:RegisterEvent("CHAT_MSG_ADDON") local _, classFileName = UnitClass("Player") self.playerClass = strupper(classFileName) end @@ -92,12 +95,47 @@ function BCS:OnEvent() } tinsert(BCS.DebugStack, t) end]] - - if - event == "PLAYER_AURAS_CHANGED" - or event == "CHARACTER_POINTS_CHANGED" - or event == "CHAT_MSG_SKILL" - then + if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then + local type, player, amount = hcstrsplit(",", arg2) + if type and player and amount then + if player ~= UnitName("player") then + amount = tonumber(amount) + if type =="TREE" then + --BCS:Print("got tree response amount="..amount) + if amount >= aura[1] then + aura[1] = amount + if BCS.PaperDollFrame:IsVisible() then + BCS:UpdateStats() + else + BCS.needUpdate = true + end + end + elseif type == "BRILLIANCE" then + --BCS:Print("got mage response amount="..amount) + if amount >= aura[2] then + aura[2] = amount + if BCS.PaperDollFrame:IsVisible() then + BCS:UpdateStats() + else + BCS.needUpdate = true + end + end + end + end + end + elseif event == "PLAYER_AURAS_CHANGED" then + if not BCS:GetPlayerAura("Tree of Life Aura") then + aura[1] = 0 + end + if not BCS:GetPlayerAura("Brilliance Aura") then + aura[2] = 0 + end + if BCS.PaperDollFrame:IsVisible() then + BCS:UpdateStats() + else + BCS.needUpdate = true + end + elseif event == "CHARACTER_POINTS_CHANGED" or event == "CHAT_MSG_SKILL" then if BCS.PaperDollFrame:IsVisible() then BCS:UpdateStats() else @@ -117,7 +155,41 @@ function BCS:OnEvent() UIDropDownMenu_SetSelectedValue(PlayerStatFrameRightDropDown, IndexRight) end end - +--sending messages +local sender = CreateFrame("Frame", "BCSsender") +sender:RegisterEvent("PLAYER_AURAS_CHANGED") +sender:RegisterEvent("CHAT_MSG_ADDON") +sender:SetScript("OnEvent", function() + if not (UnitInParty("player") or UnitInRaid("player")) then return end + if event then + local player = UnitName("player") + if event == "PLAYER_AURAS_CHANGED" then + if BCS:GetPlayerAura("Tree of Life Aura") then + ChatThrottleLib:SendAddonMessage("BULK","bcs", "TREE"..","..player, "PARTY") + --BCS:Print("sent tree request") + end + if BCS:GetPlayerAura("Brilliance Aura") then + ChatThrottleLib:SendAddonMessage("BULK","bcs", "BRILLIANCE"..","..player, "PARTY") + --BCS:Print("sent mage request") + end + end + if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then + local type, name, amount = hcstrsplit(",", arg2) + if name ~= player then + local _, treebonus = BCS:GetHealingPower() + local _, _, _, brilliance = BCS:GetManaRegen() + if not amount and type == "TREE" and treebonus then + ChatThrottleLib:SendAddonMessage("BULK","bcs", "TREE"..","..player..","..treebonus, "PARTY") + --BCS:Print("sent tree response, amount="..treebonus) + end + if not amount and type == "BRILLIANCE" and brilliance then + ChatThrottleLib:SendAddonMessage("BULK","bcs", "BRILLIANCE"..","..player..","..brilliance, "PARTY") + --BCS:Print("sent mage response, amount="..brilliance) + end + end + end + end +end) function BCS:OnShow() if BCS.needUpdate then BCS.needUpdate = nil @@ -638,7 +710,7 @@ function BCS:SetSpellPower(statFrame, school) local label = getglobal(statFrame:GetName() .. "Label") local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" + --local colorNeg = "|cffff2020" if school then label:SetText(L["SPELL_SCHOOL_" .. strupper(school)]) @@ -654,15 +726,6 @@ function BCS:SetSpellPower(statFrame, school) frame.tooltip = format(L.SPELL_SCHOOL_TOOLTIP , school) frame.tooltipSubtext = format(L.SPELL_SCHOOL_TOOLTIP_SUB, strlower(school)) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) else local power, secondaryPower, secondaryName = BCS:GetSpellPower() @@ -676,16 +739,16 @@ function BCS:SetSpellPower(statFrame, school) frame.tooltip = format(L.SPELL_POWER_TOOLTIP, power) frame.tooltipSubtext = format(L.SPELL_POWER_TOOLTIP_SUB) end - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) end + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) end function BCS:SetRating(statFrame, ratingType) @@ -908,7 +971,11 @@ function BCS:SetHealing(statFrame) local heal, treebonus = BCS:GetHealingPower() power = power - dmg local total = power + heal - if treebonus then total = total + treebonus end + if treebonus and aura[1] <= treebonus then + total = total + treebonus + elseif (not treebonus and aura[1] > 0) or (treebonus and aura[1] > treebonus) then + total = total + aura[1] + end label:SetText(L.HEAL_POWER_COLON) text:SetText(format("%.f",total)) if heal ~= 0 then @@ -936,7 +1003,11 @@ function BCS:SetManaRegen(statFrame) local base, casting, mp5, brilliance = BCS:GetManaRegen() local mp2 = mp5 * 0.4 local totalRegen = base + mp2 - if brilliance then totalRegen = totalRegen + brilliance end + if brilliance and aura[2] <= brilliance then + totalRegen = totalRegen + brilliance + elseif (not brilliance and aura[2] > 0) or (brilliance and aura[2] > brilliance) then + totalRegen = totalRegen + aura[2] + end local totalRegenWhileCasting = (casting / 100) * base + mp2 local _,class = UnitClass("player") label:SetText(L.MANA_REGEN_COLON) @@ -1421,7 +1492,7 @@ function PlayerStatFrameRightDropDown_OnLoad() UIDropDownMenu_SetWidth(99, this) UIDropDownMenu_JustifyText("LEFT") end ---[[ + --pfUI.api.strsplit function hcstrsplit(delimiter, subject) if not subject then @@ -1434,7 +1505,7 @@ function hcstrsplit(delimiter, subject) end) return unpack(fields) end - +--[[ --Update announcing code taken from pfUI local major, minor, fix = hcstrsplit(".", tostring(GetAddOnMetadata("BetterCharacterStats", "Version"))) diff --git a/BetterCharacterStats.toc b/BetterCharacterStats.toc index 8eaba5f..3303f3e 100644 --- a/BetterCharacterStats.toc +++ b/BetterCharacterStats.toc @@ -4,4 +4,5 @@ ## Version: 1.12.5 ## SavedVariablesPerCharacter: BCSConfig bcsupdateavailable -BetterCharacterStats.xml \ No newline at end of file +BetterCharacterStats.xml +ChatThrottleLib\ChatThrottleLib.lua \ No newline at end of file diff --git a/ChatThrottleLib/ChatThrottleLib.lua b/ChatThrottleLib/ChatThrottleLib.lua new file mode 100644 index 0000000..04efd9b --- /dev/null +++ b/ChatThrottleLib/ChatThrottleLib.lua @@ -0,0 +1,464 @@ +-- +-- ChatThrottleLib by Mikk +-- +-- Manages AddOn chat output to keep player from getting kicked off. +-- +-- ChatThrottleLib.SendChatMessage/.SendAddonMessage functions that accept +-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage. +-- +-- Priorities get an equal share of available bandwidth when fully loaded. +-- Communication channels are separated on extension+chattype+destination and +-- get round-robinned. (Destination only matters for whispers and channels, +-- obviously) +-- +-- Will install hooks for SendChatMessage and SendAdd[Oo]nMessage to measure +-- bandwidth bypassing the library and use less bandwidth itself. +-- +-- +-- Fully embeddable library. Just copy this file into your addon directory, +-- add it to the .toc, and it's done. +-- +-- Can run as a standalone addon also, but, really, just embed it! :-) +-- + +local CTL_VERSION = 13 + +local MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800. +local MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff + +local BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now. + +local MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value + +if(ChatThrottleLib and ChatThrottleLib.version>=CTL_VERSION) then + -- There's already a newer (or same) version loaded. Buh-bye. + return; +end + + + +if(not ChatThrottleLib) then + ChatThrottleLib = {} +end + +local ChatThrottleLib = ChatThrottleLib +local strlen = strlen +local setmetatable = setmetatable +local getn = getn +local tremove = tremove +local tinsert = tinsert +local tostring = tostring +local GetTime = GetTime +local format = format + +ChatThrottleLib.version=CTL_VERSION; + + +----------------------------------------------------------------------- +-- Double-linked ring implementation + +local Ring = {} +local RingMeta = { __index=Ring } + +function Ring:New() + local ret = {} + setmetatable(ret, RingMeta) + return ret; +end + +function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position) + if(self.pos) then + obj.prev = self.pos.prev; + obj.prev.next = obj; + obj.next = self.pos; + obj.next.prev = obj; + else + obj.next = obj; + obj.prev = obj; + self.pos = obj; + end +end + +function Ring:Remove(obj) + obj.next.prev = obj.prev; + obj.prev.next = obj.next; + if(self.pos == obj) then + self.pos = obj.next; + if(self.pos == obj) then + self.pos = nil; + end + end +end + + + +----------------------------------------------------------------------- +-- Recycling bin for pipes (kept in a linked list because that's +-- how they're worked with in the rotating rings; just reusing members) + +ChatThrottleLib.PipeBin = { count=0 } + +function ChatThrottleLib.PipeBin:Put(pipe) + for i=getn(pipe),1,-1 do + tremove(pipe, i); + end + pipe.prev = nil; + pipe.next = self.list; + self.list = pipe; + self.count = self.count+1; +end + +function ChatThrottleLib.PipeBin:Get() + if(self.list) then + local ret = self.list; + self.list = ret.next; + ret.next=nil; + self.count = self.count - 1; + return ret; + end + return {}; +end + +function ChatThrottleLib.PipeBin:Tidy() + if(self.count < 25) then + return; + end + + if(self.count > 100) then + n=self.count-90; + else + n=10; + end + for i=2,n do + self.list = self.list.next; + end + local delme = self.list; + self.list = self.list.next; + delme.next = nil; +end + + + + +----------------------------------------------------------------------- +-- Recycling bin for messages + +ChatThrottleLib.MsgBin = {} + +function ChatThrottleLib.MsgBin:Put(msg) + msg.text = nil; + tinsert(self, msg); +end + +function ChatThrottleLib.MsgBin:Get() + local ret = tremove(self, getn(self)); + if(ret) then return ret; end + return {}; +end + +function ChatThrottleLib.MsgBin:Tidy() + if(getn(self)<50) then + return; + end + if(getn(self)>150) then -- "can't happen" but ... + for n=getn(self),120,-1 do + tremove(self,n); + end + else + for n=getn(self),getn(self)-20,-1 do + tremove(self,n); + end + end +end + + +----------------------------------------------------------------------- +-- ChatThrottleLib:Init +-- Initialize queues, set up frame for OnUpdate, etc + + +function ChatThrottleLib:Init() + + -- Set up queues + if(not self.Prio) then + self.Prio = {} + self.Prio["ALERT"] = { ByName={}, Ring = Ring:New(), avail=0 }; + self.Prio["NORMAL"] = { ByName={}, Ring = Ring:New(), avail=0 }; + self.Prio["BULK"] = { ByName={}, Ring = Ring:New(), avail=0 }; + end + + -- v4: total send counters per priority + for _,Prio in pairs(self.Prio) do + Prio.nTotalSent = Prio.nTotalSent or 0; + end + + self.avail = self.avail or 0; -- v5 + self.nTotalSent = self.nTotalSent or 0; -- v5 + + + -- Set up a frame to get OnUpdate events + if(not self.Frame) then + self.Frame = CreateFrame("Frame"); + self.Frame:Hide(); + end + self.Frame.Show = self.Frame.Show; -- cache for speed + self.Frame.Hide = self.Frame.Hide; -- cache for speed + self.Frame:SetScript("OnUpdate", self.OnUpdate); + self.Frame:SetScript("OnEvent", self.OnEvent); -- v11: Monitor P_E_W so we can throttle hard for a few seconds + self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD"); + self.OnUpdateDelay=0; + self.LastAvailUpdate=GetTime(); + self.HardThrottlingBeginTime=GetTime(); -- v11: Throttle hard for a few seconds after startup + + -- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7) + if(not self.ORIG_SendChatMessage) then + --SendChatMessage + self.ORIG_SendChatMessage = SendChatMessage; + SendChatMessage = function(a1,a2,a3,a4) return ChatThrottleLib.Hook_SendChatMessage(a1,a2,a3,a4); end + --SendAdd[Oo]nMessage + if(SendAddonMessage or SendAddOnMessage) then -- v10: don't pretend like it doesn't exist if it doesn't! + self.ORIG_SendAddonMessage = SendAddonMessage or SendAddOnMessage; + SendAddonMessage = function(a1,a2,a3) return ChatThrottleLib.Hook_SendAddonMessage(a1,a2,a3); end + if(SendAddOnMessage) then -- in case Slouken changes his mind... + SendAddOnMessage = SendAddonMessage; + end + end + end + self.nBypass = 0; +end + + +----------------------------------------------------------------------- +-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage +function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination) + local self = ChatThrottleLib; + local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(destination or "")) + 40; + self.avail = self.avail - size; + self.nBypass = self.nBypass + size; + return self.ORIG_SendChatMessage(text, chattype, language, destination); +end +function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype) + local self = ChatThrottleLib; + local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(prefix or "")) + 40; + self.avail = self.avail - size; + self.nBypass = self.nBypass + size; + return self.ORIG_SendAddonMessage(prefix, text, chattype); +end + + + +----------------------------------------------------------------------- +-- ChatThrottleLib:UpdateAvail +-- Update self.avail with how much bandwidth is currently available + +function ChatThrottleLib:UpdateAvail() + local now = GetTime(); + local newavail = MAX_CPS * (now-self.LastAvailUpdate); + + if(now - self.HardThrottlingBeginTime < 5) then + -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then + self.avail = min(self.avail + (newavail*0.1), MAX_CPS*0.5); + elseif(GetFramerate()ring.pos[1].nSize) do + local msg = tremove(Prio.Ring.pos, 1); + if(not Prio.Ring.pos[1]) then + local pipe = Prio.Ring.pos; + Prio.Ring:Remove(pipe); + Prio.ByName[pipe.name] = nil; + self.PipeBin:Put(pipe); + else + Prio.Ring.pos = Prio.Ring.pos.next; + end + Prio.avail = Prio.avail - msg.nSize; + msg.f(msg[1], msg[2], msg[3], msg[4]); + Prio.nTotalSent = Prio.nTotalSent + msg.nSize; + self.MsgBin:Put(msg); + end +end + + +function ChatThrottleLib.OnEvent() + -- v11: We know that the rate limiter is touchy after login. Assume that it's touch after zoning, too. + self = ChatThrottleLib; + if(event == "PLAYER_ENTERING_WORLD") then + self.HardThrottlingBeginTime=GetTime(); -- Throttle hard for a few seconds after zoning + self.avail = 0; + end +end + + +function ChatThrottleLib.OnUpdate() + self = ChatThrottleLib; + + self.OnUpdateDelay = self.OnUpdateDelay + arg1; + if(self.OnUpdateDelay < 0.08) then + return; + end + self.OnUpdateDelay = 0; + + self:UpdateAvail(); + + if(self.avail<0) then + return; -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu. + end + + -- See how many of or priorities have queued messages + local n=0; + for prioname,Prio in pairs(self.Prio) do + if(Prio.Ring.pos or Prio.avail<0) then + n=n+1; + end + end + + -- Anything queued still? + if(n<1) then + -- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing + for prioname,Prio in pairs(self.Prio) do + self.avail = self.avail + Prio.avail; + Prio.avail = 0; + end + self.bQueueing = false; + self.Frame:Hide(); + return; + end + + -- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues + local avail= self.avail/n; + self.avail = 0; + + for prioname,Prio in pairs(self.Prio) do + if(Prio.Ring.pos or Prio.avail<0) then + Prio.avail = Prio.avail + avail; + if(Prio.Ring.pos and Prio.avail>Prio.Ring.pos[1].nSize) then + self:Despool(Prio); + end + end + end + + -- Expire recycled tables if needed + self.MsgBin:Tidy(); + self.PipeBin:Tidy(); +end + + + + +----------------------------------------------------------------------- +-- Spooling logic + + +function ChatThrottleLib:Enqueue(prioname, pipename, msg) + local Prio = self.Prio[prioname]; + local pipe = Prio.ByName[pipename]; + if(not pipe) then + self.Frame:Show(); + pipe = self.PipeBin:Get(); + pipe.name = pipename; + Prio.ByName[pipename] = pipe; + Prio.Ring:Add(pipe); + end + + tinsert(pipe, msg); + + self.bQueueing = true; +end + + + +function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination) + if(not (self and prio and text and self.Prio[prio] ) ) then + error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix" or nil, "text"[, "chattype"[, "language"[, "destination"]]]', 2); + end + + prefix = prefix or tostring(this); -- each frame gets its own queue if prefix is not given + + local nSize = strlen(text) + MSG_OVERHEAD; + + -- Check if there's room in the global available bandwidth gauge to send directly + if(not self.bQueueing and nSize < self:UpdateAvail()) then + self.avail = self.avail - nSize; + self.ORIG_SendChatMessage(text, chattype, language, destination); + self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize; + return; + end + + -- Message needs to be queued + msg=self.MsgBin:Get(); + msg.f=self.ORIG_SendChatMessage + msg[1]=text; + msg[2]=chattype or "SAY"; + msg[3]=language; + msg[4]=destination; + msg.n = 4 + msg.nSize = nSize; + + self:Enqueue(prio, format("%s/%s/%s", prefix, chattype, destination or ""), msg); +end + + +function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype) + if(not (self and prio and prefix and text and chattype and self.Prio[prio] ) ) then + error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype")', 0); + end + + local nSize = strlen(prefix) + 1 + strlen(text) + MSG_OVERHEAD; + + -- Check if there's room in the global available bandwidth gauge to send directly + if(not self.bQueueing and nSize < self:UpdateAvail()) then + self.avail = self.avail - nSize; + self.ORIG_SendAddonMessage(prefix, text, chattype); + self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize; + return; + end + + -- Message needs to be queued + msg=self.MsgBin:Get(); + msg.f=self.ORIG_SendAddonMessage; + msg[1]=prefix; + msg[2]=text; + msg[3]=chattype; + msg.n = 3 + msg.nSize = nSize; + + self:Enqueue(prio, format("%s/%s", prefix, chattype), msg); +end + + + + +----------------------------------------------------------------------- +-- Get the ball rolling! + +ChatThrottleLib:Init(); + +--[[ WoWBench debugging snippet +if(WOWB_VER) then + local function SayTimer() + print("SAY: "..GetTime().." "..arg1); + end + ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer); + ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY"); +end +]] + + diff --git a/helper.lua b/helper.lua index ea44d1d..654c419 100644 --- a/helper.lua +++ b/helper.lua @@ -1009,7 +1009,7 @@ function BCS:GetHealingPower() if healPowerFromAura then healPower = healPower + tonumber(healPowerFromAura) end - --Tree of Life (unfortunately only from self) + --Tree of Life (own) local found = BCS:GetPlayerAura("Tree of Life Form") and BCS:GetPlayerAura("Tree of Life Aura") local _, spirit = UnitStat("player", 5) local treebonus = nil @@ -1221,7 +1221,7 @@ function BCS:GetManaRegen() casting = casting + tonumber(value) break end - -- Brilliance Aura (unfortunately only from self) + -- Brilliance Aura (own) local haveTalent = strfind(left:GetText(), "Brilliance Aura") if haveTalent and rank > 0 and BCS:GetPlayerAura("Brilliance Aura") then brilliance = (base + (mp5 * 0.4)) * 0.15 From 96dc7a49bb808d153aa64d301d04fbc06e046066 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Thu, 10 Oct 2024 20:32:25 +0300 Subject: [PATCH 09/39] bug fix fixed bug with 0 stats showing sometimes --- BetterCharacterStats.lua | 94 +++++++++++++--------------------------- helper.lua | 44 +++++++++---------- 2 files changed, 52 insertions(+), 86 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index f4f7f8d..2644cc0 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -755,7 +755,6 @@ function BCS:SetRating(statFrame, ratingType) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - local _,class = UnitClass("player") label:SetText(L.MELEE_HIT_RATING_COLON) if ratingType == "MELEE" then @@ -767,17 +766,13 @@ function BCS:SetRating(statFrame, ratingType) frame.tooltipSubtext = format(L.MELEE_HIT_TOOLTIP_SUB) elseif ratingType == "RANGED" then - local rating = BCS:GetRangedHitRating() - rating = rating .. "%" - -- If no ranged attack then set to n/a - if not (GetInventoryItemLink("player",18)) or - ((class == "PALADIN") - or(class == "DRUID") - or(class == "SHAMAN")) - then + -- If no ranged attack then set to n/a + if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then text:SetText(NOT_APPLICABLE) return end + local rating = BCS:GetRangedHitRating() + rating = rating .. "%" text:SetText(rating) frame.tooltip = (L.RANGED_HIT_TOOLTIP) @@ -878,14 +873,9 @@ end function BCS:SetRangedWeaponSkill(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - local _,class = UnitClass("player") label:SetText(L.WEAPON_SKILL_COLON) -- If no ranged attack then set to n/a - if not (GetInventoryItemLink("player",18)) or - ((class == "PALADIN") - or(class == "DRUID") - or(class == "SHAMAN")) - then + if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then text:SetText(NOT_APPLICABLE) return end @@ -926,9 +916,14 @@ end function BCS:SetRangedCritChance(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.RANGED_CRIT_COLON) + -- If no ranged attack then set to n/a + if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then + text:SetText(NOT_APPLICABLE) + return + end local crit = BCS:GetRangedCritChance() local skill = BCS:GetRangedWeaponSkill() - local _, class = UnitClass("player") local level = UnitLevel("player") -- apply skill difference modifier local skillDiff = skill - (level*5) @@ -938,17 +933,7 @@ function BCS:SetRangedCritChance(statFrame) crit = crit + (skillDiff * 0.2) end if crit < 0 then crit = 0 end - label:SetText(L.RANGED_CRIT_COLON) text:SetText(format("%.2f%%", crit)) - -- If no ranged attack then set to n/a - if not (GetInventoryItemLink("player",18)) - or((class == "PALADIN") - or(class == "DRUID") - or(class == "SHAMAN")) - then - text:SetText(NOT_APPLICABLE) - return - end statFrame.tooltip = (L.RANGED_CRIT_TOOLTIP) statFrame.tooltipSubtext = (L.RANGED_CRIT_TOOLTIP_SUB) statFrame:SetScript("OnEnter", function() @@ -999,7 +984,13 @@ function BCS:SetManaRegen(statFrame) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - + label:SetText(L.MANA_REGEN_COLON) + -- if not a mana user and not a druid set to N/A + local _,class = UnitClass("player") + if (UnitPowerType("player") ~= 0 and not(class=="DRUID"))then + text:SetText(NOT_APPLICABLE) + frame.tooltip = nil + else local base, casting, mp5, brilliance = BCS:GetManaRegen() local mp2 = mp5 * 0.4 local totalRegen = base + mp2 @@ -1009,14 +1000,7 @@ function BCS:SetManaRegen(statFrame) totalRegen = totalRegen + aura[2] end local totalRegenWhileCasting = (casting / 100) * base + mp2 - local _,class = UnitClass("player") - label:SetText(L.MANA_REGEN_COLON) - - -- if not a mana user or druid set to N/A - if (UnitPowerType("player") ~= 0 and not(class=="DRUID"))then - text:SetText(NOT_APPLICABLE) - frame.tooltip = nil - else + text:SetText(format("%.0f (%.0f)", totalRegen, totalRegenWhileCasting)) frame.tooltip = format(L.SPELL_MANA_REGEN_TOOLTIP, totalRegen, totalRegenWhileCasting) frame.tooltipSubtext = format(L.SPELL_MANA_REGEN_TOOLTIP_SUB, base, casting, mp5, mp2) @@ -1149,24 +1133,17 @@ function BCS:SetRangedDamage(statFrame) local label = getglobal(statFrame:GetName() .. "Label") local damageText = getglobal(statFrame:GetName() .. "StatText") local damageFrame = statFrame - local _,class = UnitClass("player") label:SetText(TEXT(DAMAGE_COLON)) - - damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) - damageFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - -- If no ranged attack then set to n/a - if not (GetInventoryItemLink("player",18)) or - ((class == "PALADIN") - or(class == "DRUID") - or(class == "SHAMAN")) - then + if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then damageText:SetText(NOT_APPLICABLE) damageFrame.damage = nil return end + damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) + damageFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") local displayMin = max(floor(minDamage), 1) @@ -1223,22 +1200,17 @@ function BCS:SetRangedAttackSpeed(startFrame) local label = getglobal(startFrame:GetName() .. "Label") local damageText = getglobal(startFrame:GetName() .. "StatText") local damageFrame = startFrame - local _,class = UnitClass("player") label:SetText(TEXT(SPEED) .. ":") - damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) - damageFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) -- If no ranged attack then set to n/a - if not (GetInventoryItemLink("player",18)) or - ((class == "PALADIN") - or(class == "DRUID") - or(class == "SHAMAN")) - then + if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then damageText:SetText(NOT_APPLICABLE) damageFrame.damage = nil return end + damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) + damageFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") local displayMin = max(floor(minDamage), 1) @@ -1298,15 +1270,9 @@ function BCS:SetRangedAttackPower(statFrame) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - local _,class = UnitClass("player") label:SetText(TEXT(ATTACK_POWER_COLON)) - -- If no ranged attack then set to n/a - if not (GetInventoryItemLink("player",18)) or - ((class == "PALADIN") - or(class == "DRUID") - or(class == "SHAMAN")) - then + if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then text:SetText(NOT_APPLICABLE) frame.tooltip = nil return diff --git a/helper.lua b/helper.lua index 654c419..2bd190b 100644 --- a/helper.lua +++ b/helper.lua @@ -76,11 +76,11 @@ function BCS:GetHitRating(hitOnly) local MAX_INVENTORY_SLOTS = 19; hit_debuff = 0; --scan gear - for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = GetInventoryItemLink('player', slot) + for slot=1, MAX_INVENTORY_SLOTS do + local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) if hasItem then local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - BCS_Tooltip:SetHyperlink(eqItemLink) + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end local MAX_LINES = BCS_Tooltip:NumLines() local SET_NAME = nil @@ -280,11 +280,11 @@ function BCS:GetSpellHitRating() -- scan gear local MAX_INVENTORY_SLOTS = 19 - for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = GetInventoryItemLink('player', slot) + for slot=1, MAX_INVENTORY_SLOTS do + local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) if hasItem then local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - BCS_Tooltip:SetHyperlink(eqItemLink) + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end local SET_NAME local MAX_LINES = BCS_Tooltip:NumLines() @@ -513,11 +513,11 @@ function BCS:GetRangedCritChance() --scan gear local Crit_Set_Bonus = {} local MAX_INVENTORY_SLOTS = 19 - for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = GetInventoryItemLink('player', slot) + for slot=1, MAX_INVENTORY_SLOTS do + local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) if hasItem then local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - BCS_Tooltip:SetHyperlink(eqItemLink) + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end local SET_NAME local MAX_LINES = BCS_Tooltip:NumLines() @@ -609,11 +609,11 @@ function BCS:GetSpellCritChance() --scan gear local MAX_INVENTORY_SLOTS = 19 - for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = GetInventoryItemLink('player', slot) + for slot=1, MAX_INVENTORY_SLOTS do + local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) if hasItem then local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - BCS_Tooltip:SetHyperlink(eqItemLink) + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end local SET_NAME = nil for line=1, BCS_Tooltip:NumLines() do @@ -695,7 +695,7 @@ function BCS:GetSpellPower(school) local spellPower = 0; local MAX_INVENTORY_SLOTS = 19 --scan gear - for slot=0, MAX_INVENTORY_SLOTS do + for slot=1, MAX_INVENTORY_SLOTS do local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) if hasItem then @@ -740,11 +740,11 @@ function BCS:GetSpellPower(school) local SpellPower_Set_Bonus = {} -- scan gear - for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = GetInventoryItemLink('player', slot) + for slot=1, MAX_INVENTORY_SLOTS do + local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) if hasItem then local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - BCS_Tooltip:SetHyperlink(eqItemLink) + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end local SET_NAME for line=1, BCS_Tooltip:NumLines() do @@ -953,11 +953,11 @@ function BCS:GetHealingPower() local healPower_Set_Bonus = {} local MAX_INVENTORY_SLOTS = 19 --scan gear - for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = GetInventoryItemLink('player', slot) + for slot=1, MAX_INVENTORY_SLOTS do + local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) if hasItem then local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - BCS_Tooltip:SetHyperlink(eqItemLink) + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end local SET_NAME for line=1, BCS_Tooltip:NumLines() do @@ -1082,11 +1082,11 @@ function BCS:GetManaRegen() local mp5_Set_Bonus = {} local MAX_INVENTORY_SLOTS = 19 --scan gear - for slot=0, MAX_INVENTORY_SLOTS do - local hasItem = GetInventoryItemLink('player', slot) + for slot=1, MAX_INVENTORY_SLOTS do + local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) if hasItem then local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - BCS_Tooltip:SetHyperlink(eqItemLink) + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end local SET_NAME for line=1, BCS_Tooltip:NumLines() do From adeacc0530f1c92f0dd1594b91b56f69b0b1005f Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sat, 12 Oct 2024 11:38:44 +0300 Subject: [PATCH 10/39] performance boost added cache to avoid scanning stuff that shouldnt be scanned on each event included miss chance in total avoidance calculation --- BetterCharacterStats.lua | 202 ++-- BetterCharacterStats.toc | 2 +- Localization.lua | 2 +- helper.lua | 1902 +++++++++++++++++++------------------- 4 files changed, 1024 insertions(+), 1084 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 2644cc0..93dfb82 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -79,10 +79,8 @@ function BCS:OnLoad() self.Frame:RegisterEvent("PLAYER_AURAS_CHANGED") -- buffs/warrior stances self.Frame:RegisterEvent("CHAT_MSG_SKILL") --gaining weapon skill self.Frame:RegisterEvent("CHAT_MSG_ADDON") - local _, classFileName = UnitClass("Player") - self.playerClass = strupper(classFileName) end - +-- Scan stuff depending on event, but make sure to scan everything when addon is loaded function BCS:OnEvent() --[[if BCS.Debug then local t = { @@ -96,6 +94,7 @@ function BCS:OnEvent() tinsert(BCS.DebugStack, t) end]] if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then + BCS.needScanAuras = true local type, player, amount = hcstrsplit(",", arg2) if type and player and amount then if player ~= UnitName("player") then @@ -124,6 +123,7 @@ function BCS:OnEvent() end end elseif event == "PLAYER_AURAS_CHANGED" then + BCS.needScanAuras = true if not BCS:GetPlayerAura("Tree of Life Aura") then aura[1] = 0 end @@ -135,19 +135,35 @@ function BCS:OnEvent() else BCS.needUpdate = true end - elseif event == "CHARACTER_POINTS_CHANGED" or event == "CHAT_MSG_SKILL" then + elseif event == "CHARACTER_POINTS_CHANGED" then + BCS.needScanTalents = true + if BCS.PaperDollFrame:IsVisible() then + BCS:UpdateStats() + else + BCS.needUpdate = true + end + elseif event == "CHAT_MSG_SKILL" then + BCS.needScanSkills = true if BCS.PaperDollFrame:IsVisible() then BCS:UpdateStats() else BCS.needUpdate = true end elseif event == "UNIT_INVENTORY_CHANGED" and arg1 == "player" then + BCS.needScanGear = true + BCS.needScanSkills = true if BCS.PaperDollFrame:IsVisible() then BCS:UpdateStats() else BCS.needUpdate = true end elseif event == "ADDON_LOADED" and arg1 == "BetterCharacterStats" then + BCSFrame:UnregisterEvent("ADDON_LOADED") + BCS.needScanGear = true + BCS.needScanTalents = true + BCS.needScanAuras = true + BCS.needScanSkills = true + IndexLeft = BCSConfig["DropdownLeft"] or BCS.PLAYERSTAT_DROPDOWN_OPTIONS[1] IndexRight = BCSConfig["DropdownRight"] or BCS.PLAYERSTAT_DROPDOWN_OPTIONS[2] @@ -190,6 +206,7 @@ sender:SetScript("OnEvent", function() end end end) + function BCS:OnShow() if BCS.needUpdate then BCS.needUpdate = nil @@ -209,7 +226,10 @@ function BCS:UpdateStats() BCS:UpdatePaperdollStats("PlayerStatFrameLeft", IndexLeft) BCS:UpdatePaperdollStats("PlayerStatFrameRight", IndexRight) - + BCS.needScanGear = false + BCS.needScanTalents = false + BCS.needScanAuras = false + BCS.needScanSkills = false --[[local timeUsed = debugprofilestop()-beginTime table.insert(avgV, timeUsed) avg = 0 @@ -307,144 +327,6 @@ function BCS:SetArmor(statFrame) GameTooltip:Hide() end) end ---Weapon Skill code taken from https://github.com/pepopo978/BetterCharacterStats -function BCS:GetSlotItemId(slot) - local _, _, id = string.find(GetInventoryItemLink("player", GetInventorySlotInfo(slot)) or "", "item:(%d+):%d+:%d+:%d+"); - if id then - return tonumber(id) - else - return 0 - end -end - -function BCS:GetGlovesItemId() - return BCS:GetSlotItemId("HandsSlot") -end - -function BCS:GetHeadItemId() - return BCS:GetSlotItemId("HeadSlot") -end - -function BCS:GetNeckItemId() - return BCS:GetSlotItemId("NeckSlot") -end - -function BCS:GetWaistItemId() - return BCS:GetSlotItemId("WaistSlot") -end - -function BCS:GetShoulderItemId() - return BCS:GetSlotItemId("ShoulderSlot") -end - -function BCS:GetChestItemId() - return BCS:GetSlotItemId("ChestSlot") -end - -function BCS:GetLegsItemId() - return BCS:GetSlotItemId("LegsSlot") -end - -function BCS:GetFeetItemId() - return BCS:GetSlotItemId("FeetSlot") -end - -function BCS:GetMainHandItemId() - return BCS:GetSlotItemId("MainHandSlot") -end - -function BCS:GetOffHandItemId() - return BCS:GetSlotItemId("SecondaryHandSlot") -end - -function BCS:GetWeaponSkill(skillName) - -- loop through skills - local skillIndex = 1 - while true do - local name, isHeader, isExpanded, skillRank, numTempPoints, skillModifier, - skillMaxRank, isAbandonable, stepCost, rankCost, minLevel, skillCostType, - skillDescription = GetSkillLineInfo(skillIndex) - if not name then - return 0 - end - - if name == skillName then - return skillRank + skillModifier - end - - skillIndex = skillIndex + 1 - end -end - -function BCS:GetWeaponSkillForWeaponType(weaponType) - if weaponType == "Daggers" then - return BCS:GetWeaponSkill("Daggers") - elseif weaponType == "One-Handed Swords" then - return BCS:GetWeaponSkill("Swords") - elseif weaponType == "Two-Handed Swords" then - return BCS:GetWeaponSkill("Two-Handed Swords") - elseif weaponType == "One-Handed Axes" then - return BCS:GetWeaponSkill("Axes") - elseif weaponType == "Two-Handed Axes" then - return BCS:GetWeaponSkill("Two-Handed Axes") - elseif weaponType == "One-Handed Maces" then - return BCS:GetWeaponSkill("Maces") - elseif weaponType == "Two-Handed Maces" then - return BCS:GetWeaponSkill("Two-Handed Maces") - elseif weaponType == "Staves" then - return BCS:GetWeaponSkill("Staves") - elseif weaponType == "Polearms" then - return BCS:GetWeaponSkill("Polearms") - elseif weaponType == "Fist Weapons" then - return BCS:GetWeaponSkill("Unarmed") - elseif weaponType == "Bows" then - return BCS:GetWeaponSkill("Bows") - elseif weaponType == "Crossbows" then - return BCS:GetWeaponSkill("Crossbows") - elseif weaponType == "Guns" then - return BCS:GetWeaponSkill("Guns") - elseif weaponType == "Thrown" then - return BCS:GetWeaponSkill("Thrown") - elseif weaponType == "Wands" then - return BCS:GetWeaponSkill("Wands") - end - - return BCS:GetWeaponSkill("Unarmed") -end - -function BCS:GetItemInfoForSlot(slot) - local _, _, id = string.find(GetInventoryItemLink("player", GetInventorySlotInfo(slot)) or "", "(item:%d+:%d+:%d+:%d+)"); - if not id then - return - end - - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(id); - - return itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice; -end - -function BCS:GetMHWeaponSkill() - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("MainHandSlot") - - return BCS:GetWeaponSkillForWeaponType(itemType) -end - -function BCS:GetOHWeaponSkill() - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("SecondaryHandSlot") - - return BCS:GetWeaponSkillForWeaponType(itemType) -end - -function BCS:GetRangedWeaponSkill() - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("RangedSlot") - - return BCS:GetWeaponSkillForWeaponType(itemType) -end function BCS:SetDamage(statFrame) local label = getglobal(statFrame:GetName() .. "Label") @@ -730,7 +612,11 @@ function BCS:SetSpellPower(statFrame, school) local power, secondaryPower, secondaryName = BCS:GetSpellPower() label:SetText(L.SPELL_POWER_COLON) - text:SetText(power + secondaryPower) + if secondaryPower > 0 then + text:SetText(colorPos..power + secondaryPower) + else + text:SetText(power + secondaryPower) + end if secondaryPower ~= 0 then frame.tooltip = format(L.SPELL_POWER_SECONDARY_TOOLTIP, (power + secondaryPower), power, secondaryPower, secondaryName) @@ -1082,9 +968,17 @@ function BCS:SetTotalAvoidance(statFrame) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - + -- apply skill modifier + local base, mod = UnitDefense("player") + local skillDiff = base + mod - UnitLevel("player") * 5 + local missChance = 5 + skillDiff * 0.04 + + local total = missChance + (GetBlockChance() + GetParryChance() + GetDodgeChance()) + if total > 100 then total = 100 end + if total < 0 then total = 0 end + label:SetText(L.TOTAL_COLON) - text:SetText(format("%.2f%%", (GetBlockChance() + GetParryChance() + GetDodgeChance()))) + text:SetText(format("%.2f%%", total)) frame.tooltip = format(L.TOTAL_AVOIDANCE_TOOLTIP) frame.tooltipSubtext = format(L.TOTAL_AVOIDANCE_TOOLTIP_SUB) @@ -1404,17 +1298,33 @@ function BCS:UpdatePaperdollStats(prefix, index) end local function PlayerStatFrameLeftDropDown_OnClick() + BCS.needScanGear = true + BCS.needScanTalents = true + BCS.needScanAuras = true + BCS.needScanSkills = true UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) IndexLeft = this.value BCSConfig["DropdownLeft"] = IndexLeft BCS:UpdatePaperdollStats("PlayerStatFrameLeft", this.value) + BCS.needScanGear = false + BCS.needScanTalents = false + BCS.needScanAuras = false + BCS.needScanSkills = false end local function PlayerStatFrameRightDropDown_OnClick() + BCS.needScanGear = true + BCS.needScanTalents = true + BCS.needScanAuras = true + BCS.needScanSkills = true UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) IndexRight = this.value BCSConfig["DropdownRight"] = IndexRight BCS:UpdatePaperdollStats("PlayerStatFrameRight", this.value) + BCS.needScanGear = false + BCS.needScanTalents = false + BCS.needScanAuras = false + BCS.needScanSkills = false end local function PlayerStatFrameLeftDropDown_Initialize() diff --git a/BetterCharacterStats.toc b/BetterCharacterStats.toc index 3303f3e..77180cd 100644 --- a/BetterCharacterStats.toc +++ b/BetterCharacterStats.toc @@ -2,7 +2,7 @@ ## Title: BetterCharacterStats ## Author: moh, Bennylava, |cffbe5effLexie|r ## Version: 1.12.5 -## SavedVariablesPerCharacter: BCSConfig bcsupdateavailable +## SavedVariablesPerCharacter: BCSConfig bcsupdateavailable BCScache BetterCharacterStats.xml ChatThrottleLib\ChatThrottleLib.lua \ No newline at end of file diff --git a/Localization.lua b/Localization.lua index 408aee7..29644be 100644 --- a/Localization.lua +++ b/Localization.lua @@ -118,7 +118,7 @@ BCS["L"] = { Players and monsters can not block attacks from behind.]], ["TOTAL_AVOIDANCE_TOOLTIP"] = [[|cffffffffAvoidance|r]], - ["TOTAL_AVOIDANCE_TOOLTIP_SUB"] = [[Your combined chance to dodge, parry and block enemy physical attacks.]], + ["TOTAL_AVOIDANCE_TOOLTIP_SUB"] = [[Your total chance to avoid enemy physical attacks.]], --melee ["MELEE_HIT_TOOLTIP"] = [[|cffffffffMelee Hit|r]], diff --git a/helper.lua b/helper.lua index 2bd190b..2570109 100644 --- a/helper.lua +++ b/helper.lua @@ -20,7 +20,66 @@ local function tContains(table, item) end return nil end - +--cache; +--[1] - gear; [2] - talents; [3] - buffs +BCScache = BCScache or { + ["gear"] = { + damage_and_healing = 0, + arcane = 0, + fire = 0, + frost = 0, + holy = 0, + nature = 0, + shadow = 0, + healing = 0, + mp5 = 0, + casting = 0, + spell_hit = 0, + spell_crit = 0, + hit = 0, + ranged_hit = 0, + ranged_crit = 0 + }, + ["talents"] = { + damage_and_healing = 0, + healing = 0, + spell_hit = 0, + spell_hit_fire = 0, + spell_hit_frost = 0, + spell_hit_arcane = 0, + spell_hit_shadow = 0, + spell_crit = 0, + casting = 0, + mp5 = 0, + hit = 0, + ranged_hit = 0, + ranged_crit = 0 + }, + ["auras"] = { + damage_and_healing = 0, + only_damage = 0, -- +dmg to all schools, comes from buffs only currently, needed to calculate healing + arcane = 0, + fire = 0, + frost = 0, + holy = 0, + nature = 0, + shadow = 0, + healing = 0, + mp5 = 0, + casting = 0, + spell_hit = 0, + spell_crit = 0, + hit = 0, + ranged_hit = 0, + ranged_crit = 0, + hit_debuff = 0 + }, + ["skills"] = { + mh = 0, + oh = 0, + ranged = 0 + } +} function BCS:GetPlayerAura(searchText, auraType) if not auraType then -- buffs @@ -30,9 +89,7 @@ function BCS:GetPlayerAura(searchText, auraType) local index = GetPlayerBuff(i, 'HELPFUL') if index > -1 then BCS_Tooltip:SetPlayerBuff(index) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do + for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then if left:GetText() == "Power of the Guardian" and searchText == "Power of the Guardian Crit" then @@ -52,9 +109,7 @@ function BCS:GetPlayerAura(searchText, auraType) local index = GetPlayerBuff(i, auraType) if index > -1 then BCS_Tooltip:SetPlayerBuff(index) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do + for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then local value = {strfind(left:GetText(), searchText)} @@ -68,176 +123,121 @@ function BCS:GetPlayerAura(searchText, auraType) end end -local Cache_GetHitRating_Tab, Cache_GetHitRating_Talent -local hit_debuff = 0 function BCS:GetHitRating(hitOnly) local Hit_Set_Bonus = {} - local hit = 0; - local MAX_INVENTORY_SLOTS = 19; - hit_debuff = 0; - --scan gear - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) - if hasItem then - local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end - local MAX_LINES = BCS_Tooltip:NumLines() - local SET_NAME = nil - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to hit by (%d)%%."]) - if value then - hit = hit + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["/Hit %+(%d+)"]) - if value then - hit = hit + tonumber(value) - end - _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") - if value then - SET_NAME = value - end - _,_, value = strfind(left:GetText(), L["^Set: Improves your chance to hit by (%d)%%."]) - if value and SET_NAME and not tContains(Hit_Set_Bonus, SET_NAME) then - tinsert(Hit_Set_Bonus, SET_NAME) - hit = hit + tonumber(value) - line = MAX_LINES + local hit = 0 + + if BCS.needScanGear then + BCScache["gear"].hit = 0 + --scan gear + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME = nil + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to hit by (%d)%%."]) + if value then + BCScache["gear"].hit = BCScache["gear"].hit + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["/Hit %+(%d+)"]) + if value then + BCScache["gear"].hit = BCScache["gear"].hit + tonumber(value) + end + + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _,_, value = strfind(left:GetText(), L["^Set: Improves your chance to hit by (%d)%%."]) + if value and SET_NAME and not tContains(Hit_Set_Bonus, SET_NAME) then + tinsert(Hit_Set_Bonus, SET_NAME) + BCScache["gear"].hit = BCScache["gear"].hit + tonumber(value) + break + end end end end - end end - -- buffs - local _, _, hitFromAura = BCS:GetPlayerAura(L["Chance to hit increased by (%d)%%."]) - if hitFromAura then - hit = hit + tonumber(hitFromAura) - end - _, _, hitFromAura = BCS:GetPlayerAura(L["Improves your chance to hit by (%d+)%%."]) - if hitFromAura then - hit = hit + tonumber(hitFromAura) - end - _, _, hitFromAura = BCS:GetPlayerAura(L["Increases attack power by %d+ and chance to hit by (%d+)%%."]) - if hitFromAura then - hit = hit + tonumber(hitFromAura) - end - -- debuffs - _, _, hitFromAura = BCS:GetPlayerAura(L["Chance to hit reduced by (%d+)%%."], 'HARMFUL') - if hitFromAura then - hit_debuff = hit_debuff + tonumber(hitFromAura) - end - _, _, hitFromAura = BCS:GetPlayerAura(L["Chance to hit decreased by (%d+)%% and %d+ Nature damage every %d+ sec."], 'HARMFUL') - if hitFromAura then - hit_debuff = hit_debuff + tonumber(hitFromAura) - end - hitFromAura = BCS:GetPlayerAura(L["Lowered chance to hit."], 'HARMFUL') - if hitFromAura then - hit_debuff = hit_debuff + 25 - end - - local MAX_TABS = GetNumTalentTabs() - -- speedup - if Cache_GetHitRating_Tab and Cache_GetHitRating_Talent then - BCS_Tooltip:SetTalent(Cache_GetHitRating_Tab, Cache_GetHitRating_Talent) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - -- rogues - local _,_, value = strfind(left:GetText(), L["Increases your chance to hit with melee weapons by (%d)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(Cache_GetHitRating_Tab, Cache_GetHitRating_Talent) - if value and rank > 0 then - hit = hit + tonumber(value) - line = MAX_LINES - end - - -- hunters - _,_, value = strfind(left:GetText(), L["Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%."]) - name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(Cache_GetHitRating_Tab, Cache_GetHitRating_Talent) - if value and rank > 0 then - hit = hit + tonumber(value) - line = MAX_LINES - end - end + if BCS.needScanAuras then + BCScache["auras"].hit = 0 + BCScache["auras"].hit_debuff = 0 + -- buffs + local _, _, hitFromAura = BCS:GetPlayerAura(L["Chance to hit increased by (%d)%%."]) + if hitFromAura then + BCScache["auras"].hit = BCScache["auras"].hit + tonumber(hitFromAura) end - - if not hitOnly then - hit = hit - hit_debuff - if hit < 0 then hit = 0 end - return hit - else - return hit + _, _, hitFromAura = BCS:GetPlayerAura(L["Improves your chance to hit by (%d+)%%."]) + if hitFromAura then + BCScache["auras"].hit = BCScache["auras"].hit + tonumber(hitFromAura) + end + _, _, hitFromAura = BCS:GetPlayerAura(L["Increases attack power by %d+ and chance to hit by (%d+)%%."]) + if hitFromAura then + BCScache["auras"].hit = BCScache["auras"].hit + tonumber(hitFromAura) + end + -- debuffs + _, _, hitFromAura = BCS:GetPlayerAura(L["Chance to hit reduced by (%d+)%%."], 'HARMFUL') + if hitFromAura then + BCScache["auras"].hit_debuff = BCScache["auras"].hit_debuff + tonumber(hitFromAura) + end + _, _, hitFromAura = BCS:GetPlayerAura(L["Chance to hit decreased by (%d+)%% and %d+ Nature damage every %d+ sec."], 'HARMFUL') + if hitFromAura then + BCScache["auras"].hit_debuff = BCScache["auras"].hit_debuff + tonumber(hitFromAura) + end + hitFromAura = BCS:GetPlayerAura(L["Lowered chance to hit."], 'HARMFUL') + if hitFromAura then + BCScache["auras"].hit_debuff = BCScache["auras"].hit_debuff + 25 end end - --scan talents - for tab=1, MAX_TABS do - local MAX_TALENTS = GetNumTalents(tab) - - for talent=1, MAX_TALENTS do - BCS_Tooltip:SetTalent(tab, talent); - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - -- rogues - local _,_, value = strfind(left:GetText(), L["Increases your chance to hit with melee weapons by (%d)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit = hit + tonumber(value) - - Cache_GetHitRating_Tab = tab - Cache_GetHitRating_Talent = talent - - line = MAX_LINES - talent = MAX_TALENTS - tab = MAX_TABS - end - - -- hunters - _,_, value = strfind(left:GetText(), L["Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%."]) - name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit = hit + tonumber(value) - - Cache_GetHitRating_Tab = tab - Cache_GetHitRating_Talent = talent - - line = MAX_LINES - talent = MAX_TALENTS - tab = MAX_TABS - end - - -- Druid - -- Natural Weapons - _,_, value = strfind(left:GetText(), "Also increases chance to hit with melee attacks and spells by (%d+)%%.") - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit = hit + tonumber(value) - line = MAX_LINES - end - - -- Paladin & Shaman - -- Precision & Nature's Guidance - _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee attacks and spells by (%d+)%%.") - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit = hit + tonumber(value) - line = MAX_LINES + + if BCS.needScanTalents then + BCScache["talents"].hit = 0 + --scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Rogue + local _,_, value = strfind(left:GetText(), L["Increases your chance to hit with melee weapons by (%d)%%."]) + if value and rank > 0 then + BCScache["talents"].hit = BCScache["talents"].hit + tonumber(value) + break + end + -- Hunter + _,_, value = strfind(left:GetText(), L["Increases hit chance by (%d)%% and increases the chance movement impairing effects will be resisted by an additional %d+%%."]) + if value and rank > 0 then + BCScache["talents"].hit = BCScache["talents"].hit + tonumber(value) + break + end + -- Druid + -- Natural Weapons + _,_, value = strfind(left:GetText(), "Also increases chance to hit with melee attacks and spells by (%d+)%%.") + if value and rank > 0 then + BCScache["talents"].hit = BCScache["talents"].hit + tonumber(value) + break + end + -- Paladin & Shaman + -- Precision & Nature's Guidance + _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee attacks and spells by (%d+)%%.") + if value and rank > 0 then + BCScache["talents"].hit = BCScache["talents"].hit + tonumber(value) + break + end end - - end + end end - end end - + hit = BCScache["talents"].hit + BCScache["gear"].hit + BCScache["auras"].hit if not hitOnly then - hit = hit - hit_debuff + hit = hit - BCScache["auras"].hit_debuff if hit < 0 then hit = 0 end -- Dust Cloud OP return hit else @@ -246,26 +246,22 @@ function BCS:GetHitRating(hitOnly) end function BCS:GetRangedHitRating() - local melee_hit = BCS:GetHitRating(true) - local ranged_hit = melee_hit - local debuff = hit_debuff - - local hasItem = BCS_Tooltip:SetInventoryItem("player", 18) -- ranged enchant - if hasItem then - local MAX_LINES = BCS_Tooltip:NumLines() - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["+(%d)%% Hit"]) - if value then - ranged_hit = ranged_hit + tonumber(value) - line = MAX_LINES + if BCS.needScanGear then + BCScache["gear"].ranged_hit = 0 + if BCS_Tooltip:SetInventoryItem("player", 18) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["+(%d)%% Hit"]) + if value then + BCScache["gear"].ranged_hit = BCScache["gear"].ranged_hit + tonumber(value) + break + end end end end end - - ranged_hit = ranged_hit - debuff + local ranged_hit = BCS:GetHitRating(true) + BCScache["gear"].ranged_hit - BCScache["auras"].hit_debuff if ranged_hit < 0 then ranged_hit = 0 end return ranged_hit end @@ -277,180 +273,140 @@ function BCS:GetSpellHitRating() local hit_arcane = 0 local hit_shadow = 0 local hit_Set_Bonus = {} - - -- scan gear - local MAX_INVENTORY_SLOTS = 19 - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) - if hasItem then - local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end - local SET_NAME - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to hit with spells by (%d)%%."]) - if value then - hit = hit + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["/Spell Hit %+(%d+)"]) - if value then - hit = hit + tonumber(value) - end - - _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") - if value then - SET_NAME = value - end - _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to hit with spells by (%d)%%."]) - if value and SET_NAME and not tContains(hit_Set_Bonus, SET_NAME) then - tinsert(hit_Set_Bonus, SET_NAME) - hit = hit + tonumber(value) + if BCS.needScanGear then + BCScache["gear"].spell_hit = 0 + -- scan gear + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to hit with spells by (%d)%%."]) + if value then + BCScache["gear"].spell_hit = BCScache["gear"].spell_hit + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["/Spell Hit %+(%d+)"]) + if value then + BCScache["gear"].spell_hit = BCScache["gear"].spell_hit + tonumber(value) + end + + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to hit with spells by (%d)%%."]) + if value and SET_NAME and not tContains(hit_Set_Bonus, SET_NAME) then + tinsert(hit_Set_Bonus, SET_NAME) + BCScache["gear"].spell_hit = BCScache["gear"].spell_hit + tonumber(value) + end end end end - end end - - -- scan talents - local MAX_TABS = GetNumTalentTabs() - - for tab=1, MAX_TABS do - local MAX_TALENTS = GetNumTalents(tab) - - for talent=1, MAX_TALENTS do - BCS_Tooltip:SetTalent(tab, talent) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - -- Mage - -- Elemental Precision - local _,_, value = strfind(left:GetText(), L["Reduces the chance that the opponent can resist your Frost and Fire spells by (%d)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit_fire = hit_fire + tonumber(value) - hit_frost = hit_frost + tonumber(value) - break - end - - -- Arcane Focus - _,_, value = strfind(left:GetText(), L["Reduces the chance that the opponent can resist your Arcane spells by (%d+)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit_arcane = hit_arcane + tonumber(value) - break - end - - -- Priest - -- Shadow Focus - _,_, value = strfind(left:GetText(), L["Reduces your target's chance to resist your Shadow spells by (%d+)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit_shadow = hit_shadow + tonumber(value) - break - end - - -- Druid - -- Natural Weapons - _,_, value = strfind(left:GetText(), "Also increases chance to hit with melee attacks and spells by (%d+)%%.") - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit = hit + tonumber(value) - break - end - - -- Paladin & Shaman - -- Precision & Nature's Guidance - _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee weapons and spells by (%d+)%%.") - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - hit = hit + tonumber(value) - break + if BCS.needScanTalents then + BCScache["talents"].spell_hit = 0 + BCScache["talents"].spell_hit_fire = 0 + BCScache["talents"].spell_hit_frost = 0 + BCScache["talents"].spell_hit_arcane = 0 + BCScache["talents"].spell_hit_shadow = 0 + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Mage + -- Elemental Precision + local _,_, value = strfind(left:GetText(), L["Reduces the chance that the opponent can resist your Frost and Fire spells by (%d)%%."]) + if value and rank > 0 then + BCScache["talents"].spell_hit_fire = BCScache["talents"].spell_hit_fire + tonumber(value) + BCScache["talents"].spell_hit_frost = BCScache["talents"].spell_hit_frost + tonumber(value) + break + end + -- Arcane Focus + _,_, value = strfind(left:GetText(), L["Reduces the chance that the opponent can resist your Arcane spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].spell_hit_arcane = BCScache["talents"].spell_hit_arcane + tonumber(value) + break + end + -- Priest + -- Shadow Focus + _,_, value = strfind(left:GetText(), L["Reduces your target's chance to resist your Shadow spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].spell_hit_shadow = BCScache["talents"].spell_hit_shadow + tonumber(value) + break + end + -- Druid + -- Natural Weapons + _,_, value = strfind(left:GetText(), "Also increases chance to hit with melee attacks and spells by (%d+)%%.") + if value and rank > 0 then + BCScache["talents"].spell_hit = BCScache["talents"].spell_hit + tonumber(value) + break + end + -- Paladin & Shaman + -- Precision & Nature's Guidance + _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee weapons and spells by (%d+)%%.") + if value and rank > 0 then + BCScache["talents"].spell_hit = BCScache["talents"].spell_hit + tonumber(value) + break + end end - end + end end - end end - -- buffs - local _, _, hitFromAura = BCS:GetPlayerAura(L["Spell hit chance increased by (%d+)%%."]) - if hitFromAura then - hit = hit + tonumber(hitFromAura) + if BCS.needScanAuras then + BCScache["auras"].spell_hit = 0 + local _, _, hitFromAura = BCS:GetPlayerAura(L["Spell hit chance increased by (%d+)%%."]) + if hitFromAura then + BCScache["auras"].spell_hit = BCScache["auras"].spell_hit + tonumber(hitFromAura) + end end - + hit = BCScache["gear"].spell_hit + BCScache["talents"].spell_hit + BCScache["auras"].spell_hit + hit_fire = BCScache["talents"].spell_hit_fire + hit_frost = BCScache["talents"].spell_hit_frost + hit_arcane = BCScache["talents"].spell_hit_arcane + hit_shadow = BCScache["talents"].spell_hit_shadow return hit, hit_fire, hit_frost, hit_arcane, hit_shadow end -local Cache_GetCritChance_SpellID, Cache_GetCritChance_BookType, Cache_GetCritChance_Line -local Cache_GetCritChance_Tab, Cache_GetCritChance_Talent -function BCS:GetCritChance() +function BCS:GetCritChance() -- so easy lol, wish i could say same about other stuff local crit = 0 - - -- speedup - if Cache_GetCritChance_SpellID and Cache_GetCritChance_BookType and Cache_GetCritChance_Line then - - BCS_Tooltip:SetSpell(Cache_GetCritChance_SpellID, Cache_GetCritChance_BookType) - local left = getglobal(BCS_Prefix .. "TextLeft" .. Cache_GetCritChance_Line) - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["([%d.]+)%% chance to crit"]) - if value then - crit = crit + tonumber(value) - end - end - - return crit - end --scan spellbook - local MAX_TABS = GetNumSpellTabs() - - for tab=1, MAX_TABS do + for tab=1, GetNumSpellTabs() do local name, texture, offset, numSpells = GetSpellTabInfo(tab) - for spell=1, numSpells do local currentPage = ceil(spell/SPELLS_PER_PAGE) local SpellID = spell + offset + ( SPELLS_PER_PAGE * (currentPage - 1)) - BCS_Tooltip:SetSpell(SpellID, BOOKTYPE_SPELL) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do + for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then local _,_, value = strfind(left:GetText(), L["([%d.]+)%% chance to crit"]) if value then crit = crit + tonumber(value) - - Cache_GetCritChance_SpellID = SpellID - Cache_GetCritChance_BookType = BOOKTYPE_SPELL - Cache_GetCritChance_Line = line - - line = MAX_LINES - spell = numSpells - tab = MAX_TABS + break end end end - end end - + return crit end ---local Cache_GetRangedCritChance_Tab, Cache_GetRangedCritChance_Talent, Cache_GetRangedCritChance_Line function BCS:GetRangedCritChance() -- values from vmangos core local crit = 0 local _, class = UnitClass("player") local _, agility = UnitStat("player", 2) - local level = UnitLevel("player") local vallvl1 = 0 local vallvl60 = 0 local classrate = 0 @@ -461,110 +417,89 @@ function BCS:GetRangedCritChance() elseif class == "WARLOCK" then vallvl1 = 8.4 vallvl60 = 20 elseif class == "WARRIOR" then vallvl1 = 3.9 vallvl60 = 20 else return crit end - classrate = vallvl1 * (60 - level) / 59 + vallvl60 * (level - 1) / 59 + classrate = vallvl1 * (60 - UnitLevel("player")) / 59 + vallvl60 * (UnitLevel("player") - 1) / 59 crit = agility / classrate - --[[if Cache_GetRangedCritChance_Tab and Cache_GetRangedCritChance_Talent and Cache_GetRangedCritChance_Line then - BCS_Tooltip:SetTalent(Cache_GetRangedCritChance_Tab, Cache_GetRangedCritChance_Talent) - local left = getglobal(BCS_Prefix .. "TextLeft" .. Cache_GetRangedCritChance_Line) - - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with ranged weapons by (%d)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(Cache_GetRangedCritChance_Tab, Cache_GetRangedCritChance_Talent) - if value and rank > 0 then - crit = crit + tonumber(value) - end - _,_, value = strfind(left(GetText()), L["Increases your critical strike chance with all attacks by (%d)%%."]) - if value and rank > 0 then - crit = crit + tonumber(value) - end - end - - return crit - end]] - --scan talents - local MAX_TABS = GetNumTalentTabs() - - for tab=1, MAX_TABS do - local MAX_TALENTS = GetNumTalents(tab) - - for talent=1, MAX_TALENTS do - BCS_Tooltip:SetTalent(tab, talent); - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with ranged weapons by (%d)%%."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - crit = crit + tonumber(value) - break - end - _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with all attacks by (%d)%%."]) - if value and rank > 0 then - crit = crit + tonumber(value) - break + if BCS.needScanTalents then + BCScache["talents"].ranged_crit = 0 + --scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with ranged weapons by (%d)%%."]) + if value and rank > 0 then + BCScache["talents"].ranged_crit = BCScache["talents"].ranged_crit + tonumber(value) + break + end + _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with all attacks by (%d)%%."]) + if value and rank > 0 then + BCScache["talents"].ranged_crit = BCScache["talents"].ranged_crit + tonumber(value) + break + end end end end - end end - --scan gear - local Crit_Set_Bonus = {} - local MAX_INVENTORY_SLOTS = 19 - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) - if hasItem then - local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end - local SET_NAME - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to get a critical strike by (%d)%%."]) - if value then - crit = crit + tonumber(value) - end - - _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") - if value then - SET_NAME = value - end - _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to get a critical strike by (%d)%%."]) - if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then - tinsert(Crit_Set_Bonus, SET_NAME) - crit = crit + tonumber(value) + + if BCS.needScanGear then + BCScache["gear"].ranged_crit = 0 + --scan gear + local Crit_Set_Bonus = {} + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to get a critical strike by (%d)%%."]) + if value then + BCScache["gear"].ranged_crit = BCScache["gear"].ranged_crit + tonumber(value) + end + + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to get a critical strike by (%d)%%."]) + if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then + tinsert(Crit_Set_Bonus, SET_NAME) + BCScache["gear"].ranged_crit = BCScache["gear"].ranged_crit + tonumber(value) + end end end end - end end - --buffs - --ony head - local critFromAura = BCS:GetPlayerAura(L["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."]) - if critFromAura then - crit = crit + 5 - end - --mongoose - _, _, critFromAura = BCS:GetPlayerAura(L["Agility increased by 25, Critical hit chance increases by (%d)%%."]) - if critFromAura then - crit = crit + tonumber(critFromAura) - end - --songflower - _, _, critFromAura = BCS:GetPlayerAura(L["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."]) - if critFromAura then - crit = crit + tonumber(critFromAura) + if BCS.needScanAuras then + BCScache["auras"].ranged_crit = 0 + --buffs + --ony head + local critFromAura = BCS:GetPlayerAura(L["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."]) + if critFromAura then + BCScache["auras"].ranged_crit = BCScache["auras"].ranged_crit + 5 + end + --mongoose + _, _, critFromAura = BCS:GetPlayerAura(L["Agility increased by 25, Critical hit chance increases by (%d)%%."]) + if critFromAura then + BCScache["auras"].ranged_crit = BCScache["auras"].ranged_crit + tonumber(critFromAura) + end + --songflower + _, _, critFromAura = BCS:GetPlayerAura(L["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."]) + if critFromAura then + BCScache["auras"].ranged_crit = BCScache["auras"].ranged_crit + tonumber(critFromAura) + end end if class == "MAGE" then crit = crit + 3.2 elseif class == "PRIEST" then crit = crit + 3 elseif class == "WARLOCK" then crit = crit + 2 end - + crit = crit + BCScache["gear"].ranged_crit + BCScache["talents"].ranged_crit + BCScache["auras"].ranged_crit return crit end @@ -572,378 +507,373 @@ function BCS:GetSpellCritChance() -- school crit: most likely never local Crit_Set_Bonus = {} local spellCrit = 0; - local _, intelect = UnitStat("player", 4) + local _, intellect = UnitStat("player", 4) local _, class = UnitClass("player") -- values from vmangos core local playerLevel = UnitLevel("player") if class == "MAGE" then - spellCrit = 3.7 + intelect / (14.77 + .65 * playerLevel) - elseif class == "WARLOCK" then - spellCrit = 3.18 + intelect / (11.30 + .82 * playerLevel) - elseif class == "PRIEST" then - spellCrit = 2.97 + intelect / (10.03 + .82 * playerLevel) - elseif class == "DRUID" then - spellCrit = 3.33 + intelect / (12.41 + .79 * playerLevel) - elseif class == "SHAMAN" then - spellCrit = 3.54 + intelect / (11.51 + .8 * playerLevel) - elseif class == "PALADIN" then - spellCrit = 3.7 + intelect / (14.77 + .65 * playerLevel) - end - --[[ - -- values from theorycraft / http://wow.allakhazam.com/forum.html?forum=21&mid=1157230638252681707 - if class == "MAGE" then - spellCrit = 0.2 + (intelect / 59.5) + spellCrit = 3.7 + intellect / (14.77 + .65 * playerLevel) elseif class == "WARLOCK" then - spellCrit = 1.7 + (intelect / 60.6) + spellCrit = 3.18 + intellect / (11.30 + .82 * playerLevel) elseif class == "PRIEST" then - spellCrit = 0.8 + (intelect / 59.56) + spellCrit = 2.97 + intellect / (10.03 + .82 * playerLevel) elseif class == "DRUID" then - spellCrit = 1.8 + (intelect / 60) + spellCrit = 3.33 + intellect / (12.41 + .79 * playerLevel) elseif class == "SHAMAN" then - spellCrit = 1.8 + (intelect / 59.2) + spellCrit = 3.54 + intellect / (11.51 + .8 * playerLevel) elseif class == "PALADIN" then - spellCrit = intelect / 29.5 + spellCrit = 3.7 + intellect / (14.77 + .65 * playerLevel) end - --]] - --scan gear - local MAX_INVENTORY_SLOTS = 19 - - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) - if hasItem then - local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end - local SET_NAME = nil - - for line=1, BCS_Tooltip:NumLines() do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if BCS.needScanGear then + BCScache["gear"].spell_crit = 0 + --scan gear + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME = nil + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to get a critical strike with spells by (%d)%%."]) + if value then + BCScache["gear"].spell_crit = BCScache["gear"].spell_crit + tonumber(value) + end - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Equip: Improves your chance to get a critical strike with spells by (%d)%%."]) - if value then - spellCrit = spellCrit + tonumber(value) + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to get a critical strike with spells by (%d)%%."]) + if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then + tinsert(Crit_Set_Bonus, SET_NAME) + BCScache["gear"].spell_crit = BCScache["gear"].spell_crit + tonumber(value) + end + _,_, value = strfind(left:GetText(), "(%d)%% Spell Critical Strike") + if value then + BCScache["gear"].spell_crit = BCScache["gear"].spell_crit + tonumber(value) + end end - - _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") - if value then - SET_NAME = value - end - - _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to get a critical strike with spells by (%d)%%."]) - if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then - tinsert(Crit_Set_Bonus, SET_NAME) - spellCrit = spellCrit + tonumber(value) - end - - local _,_, value = strfind(left:GetText(), "(%d)%% Spell Critical Strike") - if value then - spellCrit = spellCrit + tonumber(value) - end - end end end - - end - - -- buffs - local _, _, critFromAura = BCS:GetPlayerAura(L["Chance for a critical hit with a spell increased by (%d+)%%."]) - if critFromAura then - spellCrit = spellCrit + tonumber(critFromAura) - end - _, _, critFromAura = BCS:GetPlayerAura("(Moonkin Aura)") - if critFromAura then - spellCrit = spellCrit + 3 - end - _, _, critFromAura = BCS:GetPlayerAura("Power of the Guardian Crit") - if critFromAura then - spellCrit = spellCrit + tonumber(critFromAura) end - _, _, critFromAura = BCS:GetPlayerAura("Chance to get a critical strike with spells is increased by (%d+)%%") - if critFromAura then - spellCrit = spellCrit + tonumber(critFromAura) - end - _, _, critFromAura = BCS:GetPlayerAura(L["While active, target's critical hit chance with spells and attacks increases by 10%%."])--SoD spell? 23964 - if critFromAura then - spellCrit = spellCrit + 10 - end - _, _, critFromAura = BCS:GetPlayerAura(L["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."]) - if critFromAura then - spellCrit = spellCrit + tonumber(critFromAura) - end - critFromAura = BCS:GetPlayerAura(L["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."]) - if critFromAura then - spellCrit = spellCrit + 10 - end - _, _, critFromAura = BCS:GetPlayerAura(L["Critical strike chance with spells and melee attacks increased by (%d+)%%."]) - if critFromAura then - spellCrit = spellCrit + tonumber(critFromAura) - end - -- debuffs - _, _, _, critFromAura = BCS:GetPlayerAura(L["Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%."], 'HARMFUL') - if critFromAura then - spellCrit = spellCrit - tonumber(critFromAura) + + if BCS.needScanAuras then + BCScache["auras"].spell_crit = 0 + -- buffs + local _, _, critFromAura = BCS:GetPlayerAura(L["Chance for a critical hit with a spell increased by (%d+)%%."]) + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) + end + _, _, critFromAura = BCS:GetPlayerAura("(Moonkin Aura)") + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + 3 + end + _, _, critFromAura = BCS:GetPlayerAura("Power of the Guardian Crit") + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) + end + _, _, critFromAura = BCS:GetPlayerAura("Chance to get a critical strike with spells is increased by (%d+)%%") + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) + end + _, _, critFromAura = BCS:GetPlayerAura(L["While active, target's critical hit chance with spells and attacks increases by 10%%."])--SoD spell? 23964 + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + 10 + end + _, _, critFromAura = BCS:GetPlayerAura(L["Increases chance for a melee, ranged, or spell critical by (%d+)%% and all attributes by %d+."]) + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) + end + critFromAura = BCS:GetPlayerAura(L["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."]) + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + 10 + end + _, _, critFromAura = BCS:GetPlayerAura(L["Critical strike chance with spells and melee attacks increased by (%d+)%%."]) + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) + end + -- debuffs + _, _, _, critFromAura = BCS:GetPlayerAura(L["Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%."], 'HARMFUL') + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit - tonumber(critFromAura) + end end + spellCrit = spellCrit + BCScache["gear"].spell_crit + BCScache["auras"].spell_crit + return spellCrit end function BCS:GetSpellPower(school) if school then - if not L["Equip: Increases damage done by "..school.." spells and effects by up to (%d+)."] then return -1 end local spellPower = 0; - local MAX_INVENTORY_SLOTS = 19 --scan gear - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem("player", slot) - - if hasItem then - for line=1, BCS_Tooltip:NumLines() do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by "..school.." spells and effects by up to (%d+)."]) - if value then - spellPower = spellPower + tonumber(value) - end - if L[school.." Damage %+(%d+)"] then - _,_, value = strfind(left:GetText(), L[school.." Damage %+(%d+)"]) + if BCS.needScanGear then + if school == "Arcane" then BCScache["gear"].arcane = 0 + elseif school == "Fire" then BCScache["gear"].fire = 0 + elseif school == "Frost" then BCScache["gear"].frost = 0 + elseif school == "Holy" then BCScache["gear"].holy = 0 + elseif school == "Nature" then BCScache["gear"].nature = 0 + elseif school == "Shadow" then BCScache["gear"].shadow = 0 + end + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem("player", slot) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by "..school.." spells and effects by up to (%d+)."]) if value then spellPower = spellPower + tonumber(value) end - end - if L["^%+(%d+) "..school.." Spell Damage"] then - _,_, value = strfind(left:GetText(), L["^%+(%d+) "..school.." Spell Damage"]) - if value then - spellPower = spellPower + tonumber(value) + if L[school.." Damage %+(%d+)"] then + _,_, value = strfind(left:GetText(), L[school.." Damage %+(%d+)"]) + if value then + spellPower = spellPower + tonumber(value) + end + end + if L["^%+(%d+) "..school.." Spell Damage"] then + _,_, value = strfind(left:GetText(), L["^%+(%d+) "..school.." Spell Damage"]) + if value then + spellPower = spellPower + tonumber(value) + end end end end end end - + if school == "Arcane" then BCScache["gear"].arcane = spellPower + elseif school == "Fire" then BCScache["gear"].fire = spellPower + elseif school == "Frost" then BCScache["gear"].frost = spellPower + elseif school == "Holy" then BCScache["gear"].holy = spellPower + elseif school == "Nature" then BCScache["gear"].nature = spellPower + elseif school == "Shadow" then BCScache["gear"].shadow = spellPower + end + else + if school == "Arcane" then spellPower = BCScache["gear"].arcane + elseif school == "Fire" then spellPower = BCScache["gear"].fire + elseif school == "Frost" then spellPower = BCScache["gear"].frost + elseif school == "Holy" then spellPower = BCScache["gear"].holy + elseif school == "Nature" then spellPower = BCScache["gear"].nature + elseif school == "Shadow" then spellPower = BCScache["gear"].shadow + end end - + return spellPower else - local spellPower = 0; - local arcanePower = 0; - local firePower = 0; - local frostPower = 0; - local holyPower = 0; - local naturePower = 0; - local shadowPower = 0; - local damagePower = 0; - local MAX_INVENTORY_SLOTS = 19 - + local spellPower = 0 + local damagePower = 0 local SpellPower_Set_Bonus = {} - - -- scan gear - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) - if hasItem then - local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end - local SET_NAME - - for line=1, BCS_Tooltip:NumLines() do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Equip: Increases damage and healing done by magical spells and effects by up to (%d+)."]) - if value then - spellPower = spellPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to (%d+)") - if value then - spellPower = spellPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["Spell Damage %+(%d+)"]) - if value then - spellPower = spellPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Spell Damage and Healing"]) - if value then - spellPower = spellPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Damage and Healing Spells"]) - if value then - spellPower = spellPower + tonumber(value) - end - - _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Arcane spells and effects by up to (%d+)."]) - if value then - arcanePower = arcanePower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Arcane Spell Damage"]) - if value then - arcanePower = arcanePower + tonumber(value) - end - - _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Fire spells and effects by up to (%d+)."]) - if value then - firePower = firePower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["Fire Damage %+(%d+)"]) - if value then - firePower = firePower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Fire Spell Damage"]) - if value then - firePower = firePower + tonumber(value) - end - - _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Frost spells and effects by up to (%d+)."]) - if value then - frostPower = frostPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["Frost Damage %+(%d+)"]) - if value then - frostPower = frostPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Frost Spell Damage"]) - if value then - frostPower = frostPower + tonumber(value) - end - - _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Holy spells and effects by up to (%d+)."]) - if value then - holyPower = holyPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Holy Spell Damage"]) - if value then - holyPower = holyPower + tonumber(value) - end - - _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Nature spells and effects by up to (%d+)."]) - if value then - naturePower = naturePower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Nature Spell Damage"]) - if value then - naturePower = naturePower + tonumber(value) - end - - _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Shadow spells and effects by up to (%d+)."]) - if value then - shadowPower = shadowPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["Shadow Damage %+(%d+)"]) - if value then - shadowPower = shadowPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Shadow Spell Damage"]) - if value then - shadowPower = shadowPower + tonumber(value) - end - - _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") - if value then - SET_NAME = value - end + if BCS.needScanGear then + BCScache["gear"].damage_and_healing = 0 + BCScache["gear"].arcane = 0 + BCScache["gear"].fire = 0 + BCScache["gear"].frost = 0 + BCScache["gear"].holy = 0 + BCScache["gear"].nature = 0 + BCScache["gear"].shadow = 0 + -- scan gear + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Increases damage and healing done by magical spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to (%d+)") + if value then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["Spell Damage %+(%d+)"]) + if value then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Spell Damage and Healing"]) + if value then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Damage and Healing Spells"]) + if value then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + end + + _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Arcane spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].arcane = BCScache["gear"].arcane + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Arcane Spell Damage"]) + if value then + BCScache["gear"].arcane = BCScache["gear"].arcane + tonumber(value) + end + + _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Fire spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].fire = BCScache["gear"].fire + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["Fire Damage %+(%d+)"]) + if value then + BCScache["gear"].fire = BCScache["gear"].fire + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Fire Spell Damage"]) + if value then + BCScache["gear"].fire = BCScache["gear"].fire + tonumber(value) + end + + _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Frost spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].frost = BCScache["gear"].frost + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["Frost Damage %+(%d+)"]) + if value then + BCScache["gear"].frost = BCScache["gear"].frost + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Frost Spell Damage"]) + if value then + BCScache["gear"].frost = BCScache["gear"].frost + tonumber(value) + end + + _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Holy spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].holy = BCScache["gear"].holy + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Holy Spell Damage"]) + if value then + BCScache["gear"].holy = BCScache["gear"].holy + tonumber(value) + end + + _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Nature spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].nature = BCScache["gear"].nature + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Nature Spell Damage"]) + if value then + BCScache["gear"].nature = BCScache["gear"].nature + tonumber(value) + end + + _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Shadow spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].shadow = BCScache["gear"].shadow + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["Shadow Damage %+(%d+)"]) + if value then + BCScache["gear"].shadow = BCScache["gear"].shadow + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Shadow Spell Damage"]) + if value then + BCScache["gear"].shadow = BCScache["gear"].shadow + tonumber(value) + end + + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end - _, _, value = strfind(left:GetText(), L["^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%."]) - if value and SET_NAME and not tContains(SpellPower_Set_Bonus, SET_NAME) then - tinsert(SpellPower_Set_Bonus, SET_NAME) - spellPower = spellPower + tonumber(value) + _, _, value = strfind(left:GetText(), L["^Set: Increases damage and healing done by magical spells and effects by up to (%d+)%."]) + if value and SET_NAME and not tContains(SpellPower_Set_Bonus, SET_NAME) then + tinsert(SpellPower_Set_Bonus, SET_NAME) + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + end end - end end end - end - - -- scan talents - local MAX_TABS = GetNumTalentTabs() - - for tab=1, MAX_TABS do - local MAX_TALENTS = GetNumTalents(tab) - - for talent=1, MAX_TALENTS do - BCS_Tooltip:SetTalent(tab, talent) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - -- Priest - -- Spiritual Guidance - local _,_, value = strfind(left:GetText(), L["Increases spell damage and healing by up to (%d+)%% of your total Spirit."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - local stat, effectiveStat = UnitStat("player", 5) - spellPower = spellPower + floor(((tonumber(value) / 100) * effectiveStat)) - - -- nothing more is currenlty supported, break out of the loops - break + + if BCS.needScanTalents then + BCScache["talents"].damage_and_healing = 0 + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Priest + -- Spiritual Guidance + local _,_, value = strfind(left:GetText(), L["Increases spell damage and healing by up to (%d+)%% of your total Spirit."]) + if value and rank > 0 then + local stat, spirit = UnitStat("player", 5) + BCScache["talents"].damage_and_healing = BCScache["talents"].damage_and_healing + floor(((tonumber(value) / 100) * spirit)) + break + end end - end + end end - end end - - -- buffs - local _, _, spellPowerFromAura = BCS:GetPlayerAura(L["Magical damage dealt is increased by up to (%d+)."]) - if spellPowerFromAura then - spellPower = spellPower + tonumber(spellPowerFromAura) - damagePower = damagePower + tonumber(spellPowerFromAura) - end - - _, _, spellPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") - if spellPowerFromAura then - spellPower = spellPower + tonumber(spellPowerFromAura) - damagePower = damagePower + tonumber(spellPowerFromAura) - end - - _, _, spellPowerFromAura = BCS:GetPlayerAura("Magical damage dealt by spells and abilities is increased by up to (%d+)") - if spellPowerFromAura then - spellPower = spellPower + tonumber(spellPowerFromAura) - damagePower = damagePower + tonumber(spellPowerFromAura) - end - - _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell damage is increased by up to (%d+)") - if spellPowerFromAura then - spellPower = spellPower + tonumber(spellPowerFromAura) - damagePower = damagePower + tonumber(spellPowerFromAura) - end - --turtle wow spell power food - _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell Damage increased by (%d+)") - if spellPowerFromAura then - spellPower = spellPower + tonumber(spellPowerFromAura) - damagePower = damagePower + tonumber(spellPowerFromAura) - end - + if BCS.needScanAuras then + BCScache["auras"].damage_and_healing = 0 + BCScache["auras"].only_damage = 0 + -- buffs + local _, _, spellPowerFromAura = BCS:GetPlayerAura(L["Magical damage dealt is increased by up to (%d+)."]) + if spellPowerFromAura then + BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) + BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) + end + + _, _, spellPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") + if spellPowerFromAura then + BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) + BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) + end + + _, _, spellPowerFromAura = BCS:GetPlayerAura("Magical damage dealt by spells and abilities is increased by up to (%d+)") + if spellPowerFromAura then + BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) + BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) + end + + _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell damage is increased by up to (%d+)") + if spellPowerFromAura then + BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) + BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) + end + --turtle wow spell power food + _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell Damage increased by (%d+)") + if spellPowerFromAura then + BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) + BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) + end + end local secondaryPower = 0 local secondaryPowerName = "" - - if arcanePower > secondaryPower then - secondaryPower = arcanePower + + if BCScache["gear"].arcane > secondaryPower then + secondaryPower = BCScache["gear"].arcane secondaryPowerName = L.SPELL_SCHOOL_ARCANE end - if firePower > secondaryPower then - secondaryPower = firePower + if BCScache["gear"].fire > secondaryPower then + secondaryPower = BCScache["gear"].fire secondaryPowerName = L.SPELL_SCHOOL_FIRE end - if frostPower > secondaryPower then - secondaryPower = frostPower + if BCScache["gear"].frost > secondaryPower then + secondaryPower = BCScache["gear"].frost secondaryPowerName = L.SPELL_SCHOOL_FROST end - if holyPower > secondaryPower then - secondaryPower = holyPower + if BCScache["gear"].holy > secondaryPower then + secondaryPower = BCScache["gear"].holy secondaryPowerName = L.SPELL_SCHOOL_HOLY end - if naturePower > secondaryPower then - secondaryPower = naturePower + if BCScache["gear"].nature > secondaryPower then + secondaryPower = BCScache["gear"].nature secondaryPowerName = L.SPELL_SCHOOL_NATURE end - if shadowPower > secondaryPower then - secondaryPower = shadowPower + if BCScache["gear"].shadow > secondaryPower then + secondaryPower = BCScache["gear"].shadow secondaryPowerName = L.SPELL_SCHOOL_SHADOW end - + + spellPower = BCScache["gear"].damage_and_healing + BCScache["talents"].damage_and_healing + BCScache["auras"].damage_and_healing + damagePower = BCScache["auras"].only_damage + return spellPower, secondaryPower, secondaryPowerName, damagePower end end @@ -951,110 +881,112 @@ end function BCS:GetHealingPower() local healPower = 0; local healPower_Set_Bonus = {} - local MAX_INVENTORY_SLOTS = 19 - --scan gear - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) - if hasItem then - local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end - local SET_NAME - - for line=1, BCS_Tooltip:NumLines() do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["Equip: Increases healing done by spells and effects by up to (%d+)."]) - if value then - healPower = healPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to 120 and your healing by up to (300).") - if value then - healPower = healPower + tonumber(value) - 120 - end - _,_, value = strfind(left:GetText(), L["Healing Spells %+(%d+)"]) - if value then - healPower = healPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^Healing %+(%d+) and %d+ mana per 5 sec."]) - if value then - healPower = healPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) Healing Spells"]) - if value then - healPower = healPower + tonumber(value) - end - _,_, value = strfind(left:GetText(), "^Brilliant Mana Oil %((%d+) min%)") - if value then - healPower = healPower + 25 - end - - _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") - if value then - SET_NAME = value - end - _, _, value = strfind(left:GetText(), L["^Set: Increases healing done by spells and effects by up to (%d+)%."]) - if value and SET_NAME and not tContains(healPower_Set_Bonus, SET_NAME) then - tinsert(healPower_Set_Bonus, SET_NAME) - healPower = healPower + tonumber(value) + if BCS.needScanGear then + BCScache["gear"].healing = 0 + --scan gear + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["Equip: Increases healing done by spells and effects by up to (%d+)."]) + if value then + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to 120 and your healing by up to (300).") + if value then + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) - 120 + end + _,_, value = strfind(left:GetText(), L["Healing Spells %+(%d+)"]) + if value then + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^Healing %+(%d+) and %d+ mana per 5 sec."]) + if value then + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) Healing Spells"]) + if value then + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), "^Brilliant Mana Oil %((%d+) min%)") + if value then + BCScache["gear"].healing = BCScache["gear"].healing + 25 + end + + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _, _, value = strfind(left:GetText(), L["^Set: Increases healing done by spells and effects by up to (%d+)%."]) + if value and SET_NAME and not tContains(healPower_Set_Bonus, SET_NAME) then + tinsert(healPower_Set_Bonus, SET_NAME) + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) + end end end end end - end -- buffs - local _, _, healPowerFromAura = BCS:GetPlayerAura(L["Healing done by magical spells is increased by up to (%d+)."]) - if healPowerFromAura then - healPower = healPower + tonumber(healPowerFromAura) - end - --Tree of Life (own) - local found = BCS:GetPlayerAura("Tree of Life Form") and BCS:GetPlayerAura("Tree of Life Aura") - local _, spirit = UnitStat("player", 5) local treebonus = nil - if found then - treebonus = spirit * 0.2 - end - --Sweet Surprise - _, _, healPowerFromAura = BCS:GetPlayerAura(L["Increases healing done by magical spells by up to (%d+) for 3600 sec."]) - if healPowerFromAura then - healPower = healPower + tonumber(healPowerFromAura) - end - --Unstable Power - _, _, healPowerFromAura = BCS:GetPlayerAura(L["Healing increased by up to (%d+)."]) - if healPowerFromAura then - healPower = healPower + tonumber(healPowerFromAura) - end - --The Eye of the Dead - _, _, healPowerFromAura = BCS:GetPlayerAura(L["Healing spells increased by up to (%d+)."]) - if healPowerFromAura then - healPower = healPower + tonumber(healPowerFromAura) - end - --Power of the Guardian - _, _, healPowerFromAura = BCS:GetPlayerAura("Increases healing done by magical spells and effects by up to (%d+).") - if healPowerFromAura then - healPower = healPower + tonumber(healPowerFromAura) - end - _, _, healPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") - if healPowerFromAura then - healPower = healPower + tonumber(healPowerFromAura) - end - --Dreamshard Elixir - _, _, healPowerFromAura = BCS:GetPlayerAura("Healing done is increased by up to (%d+)") - if healPowerFromAura then - healPower = healPower + tonumber(healPowerFromAura) + if BCS.needScanAuras then + BCScache["auras"].healing = 0 + local _, _, healPowerFromAura = BCS:GetPlayerAura(L["Healing done by magical spells is increased by up to (%d+)."]) + if healPowerFromAura then + BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) + end + --Tree of Life (own) + local found = BCS:GetPlayerAura("Tree of Life Form") and BCS:GetPlayerAura("Tree of Life Aura") + local _, spirit = UnitStat("player", 5) + if found then + treebonus = spirit * 0.2 + end + --Sweet Surprise + _, _, healPowerFromAura = BCS:GetPlayerAura(L["Increases healing done by magical spells by up to (%d+) for 3600 sec."]) + if healPowerFromAura then + BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) + end + --Unstable Power + _, _, healPowerFromAura = BCS:GetPlayerAura(L["Healing increased by up to (%d+)."]) + if healPowerFromAura then + BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) + end + --The Eye of the Dead + _, _, healPowerFromAura = BCS:GetPlayerAura(L["Healing spells increased by up to (%d+)."]) + if healPowerFromAura then + BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) + end + --Power of the Guardian + _, _, healPowerFromAura = BCS:GetPlayerAura("Increases healing done by magical spells and effects by up to (%d+).") + if healPowerFromAura then + BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) + end + _, _, healPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") + if healPowerFromAura then + BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) + end + --Dreamshard Elixir + _, _, healPowerFromAura = BCS:GetPlayerAura("Healing done is increased by up to (%d+)") + if healPowerFromAura then + BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) + end end - + + healPower = BCScache["gear"].healing + BCScache["auras"].healing + return healPower, treebonus end local function GetRegenMPPerSpirit() local addvalue = 0 - local stat, Spirit, posBuff, negBuff = UnitStat("player", 5) local lClass, class = UnitClass("player") - + if class == "DRUID" then addvalue = (Spirit / 5 + 15) elseif class == "HUNTER" then @@ -1069,9 +1001,8 @@ local function GetRegenMPPerSpirit() addvalue = (Spirit / 5 + 17) elseif class == "WARLOCK" then addvalue = (Spirit / 5 + 15) - else - return addvalue end + return addvalue end @@ -1080,160 +1011,259 @@ function BCS:GetManaRegen() local casting = 0 local mp5 = 0 local mp5_Set_Bonus = {} - local MAX_INVENTORY_SLOTS = 19 - --scan gear - for slot=1, MAX_INVENTORY_SLOTS do - local hasItem = BCS_Tooltip:SetInventoryItem('player', slot) - if hasItem then - local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") - if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end - local SET_NAME + if BCS.needScanGear then + BCScache["gear"].mp5 = 0 + BCScache["gear"].casting = 0 + --scan gear + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), L["^Mana Regen %+(%d+)"]) + if value then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["Equip: Restores (%d+) mana per 5 sec."]) + if value and not strfind(left:GetText(), "to all party members") then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^Healing %+%d+ and (%d+) mana per 5 sec."]) + if value then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["^%+(%d+) mana every 5 sec."]) + if value then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + tonumber(value) + end + _,_, value = strfind(left:GetText(), "^Brilliant Mana Oil %((%d+) min%)") + if value then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + 12 + end + _,_, value = strfind(left:GetText(), "^Lesser Mana Oil %((%d+) min%)") + if value then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + 8 + end + _,_, value = strfind(left:GetText(), "^Minor Mana Oil %((%d+) min%)") + if value then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + 4 + end + _,_, value = strfind(left:GetText(), "^Equip: Allows (%d+)%% of your Mana regeneration to continue while casting.") + if value then + BCScache["gear"].casting = BCScache["gear"].casting + tonumber(value) + end - for line=1, BCS_Tooltip:NumLines() do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - - if left:GetText() then - local _,_, value = strfind(left:GetText(), L["^Mana Regen %+(%d+)"]) - if value then - mp5 = mp5 + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["Equip: Restores (%d+) mana per 5 sec."]) - if value and not strfind(left:GetText(), "to all party members") then - mp5 = mp5 + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^Healing %+%d+ and (%d+) mana per 5 sec."]) - if value then - mp5 = mp5 + tonumber(value) - end - _,_, value = strfind(left:GetText(), L["^%+(%d+) mana every 5 sec."]) - if value then - mp5 = mp5 + tonumber(value) - end - _,_, value = strfind(left:GetText(), "^Brilliant Mana Oil %((%d+) min%)") - if value then - mp5 = mp5 + 12 - end - _,_, value = strfind(left:GetText(), "^Lesser Mana Oil %((%d+) min%)") - if value then - mp5 = mp5 + 8 - end - _,_, value = strfind(left:GetText(), "^Minor Mana Oil %((%d+) min%)") - if value then - mp5 = mp5 + 4 - end - _,_, value = strfind(left:GetText(), "^Equip: Allows (%d+)%% of your Mana regeneration to continue while casting.") - if value then - casting = casting + tonumber(value) - end - _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") - if value then - SET_NAME = value - end - _,_, value = strfind(left:GetText(), L["^Set: Allows (%d+)%% of your Mana regeneration to continue while casting."]) - if value and SET_NAME and not tContains(mp5_Set_Bonus, SET_NAME) then - tinsert(mp5_Set_Bonus, SET_NAME) - casting = casting + tonumber(value) - end - _,_, value = strfind(left:GetText(), "^Set: Restores (%d+) mana per 5 sec.") - if value and SET_NAME and not tContains(mp5_Set_Bonus, SET_NAME) then - tinsert(mp5_Set_Bonus, SET_NAME) - mp5 = mp5 + tonumber(value) + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _,_, value = strfind(left:GetText(), L["^Set: Allows (%d+)%% of your Mana regeneration to continue while casting."]) + if value and SET_NAME and not tContains(mp5_Set_Bonus, SET_NAME) then + tinsert(mp5_Set_Bonus, SET_NAME) + BCScache["gear"].casting = BCScache["gear"].casting + tonumber(value) + end + _,_, value = strfind(left:GetText(), "^Set: Restores (%d+) mana per 5 sec.") + if value and SET_NAME and not tContains(mp5_Set_Bonus, SET_NAME) then + tinsert(mp5_Set_Bonus, SET_NAME) + BCScache["gear"].mp5 = BCScache["gear"].mp5 + tonumber(value) + end end end end end end - - -- improved Shadowform - for i = 1, MAX_SKILLLINE_TABS do - local name, texture, offset, numSpells = GetSpellTabInfo(i); - for s = offset + 1, offset + numSpells do - local spell, rank = GetSpellName(s, BOOKTYPE_SPELL); - if spell == "Improved Shadowform" and BCS:GetPlayerAura("Shadowform") then - casting = casting + 15 + + -- buffs + if BCS.needScanAuras then + BCScache["auras"].casting = 0 + BCScache["auras"].mp5 = 0 + -- improved Shadowform + for i = 1, MAX_SKILLLINE_TABS do + local name, texture, offset, numSpells = GetSpellTabInfo(i); + for s = offset + 1, offset + numSpells do + local spell = GetSpellName(s, BOOKTYPE_SPELL); + if spell == "Improved Shadowform" and BCS:GetPlayerAura("Shadowform") then + BCScache["auras"].casting = BCScache["auras"].casting + 15 + end end end + -- Warchief's Blessing + local _, _, mp5FromAura = BCS:GetPlayerAura(L["Increases hitpoints by 300. 15%% haste to melee attacks. (%d+) mana regen every 5 seconds."]) + if mp5FromAura then + BCScache["auras"].mp5 = BCScache["auras"].mp5 + 10 + end + --Epiphany + _, _, mp5FromAura = BCS:GetPlayerAura(L["Restores (%d+) mana per 5 sec."]) + if mp5FromAura then + BCScache["auras"].mp5 = BCScache["auras"].mp5 + tonumber(mp5FromAura) + end + --Nightfin Soup + _, _, mp5FromAura = BCS:GetPlayerAura(L["Regenerating (%d+) Mana every 5 seconds."]) + if mp5FromAura then + BCScache["auras"].mp5 = BCScache["auras"].mp5 + tonumber(mp5FromAura)*2.5 -- had to double the mp5FromAura because the item is a true mp5 tick + end + --Mageblood Potion + _, _, mp5FromAura = BCS:GetPlayerAura(L["Regenerate (%d+) mana per 5 sec."]) + if mp5FromAura then + BCScache["auras"].mp5 = BCScache["auras"].mp5 + tonumber(mp5FromAura) + end + --Fizzy Energy Drink and Sagefin + _, _, mp5FromAura = BCS:GetPlayerAura(L["Mana Regeneration increased by (%d+) every 5 seconds."]) + if mp5FromAura then + BCScache["auras"].mp5 = BCScache["auras"].mp5 + tonumber(mp5FromAura)*2.5 + end + --Second Wind + _, _, mp5FromAura = BCS:GetPlayerAura(L["Restores (%d+) mana every 1 sec."]) + if mp5FromAura then + BCScache["auras"].mp5 = BCScache["auras"].mp5 + tonumber(mp5FromAura)*5 -- had to multiply by 5 the mp5FromAura because the item is a sec per tick + end + --Power of the Guardian + _, _, mp5FromAura = BCS:GetPlayerAura("Restores (%d+) mana per 5 seconds.") + if mp5FromAura then + BCScache["auras"].mp5 = BCScache["auras"].mp5 + tonumber(mp5FromAura) + end + --Aura of the blue dragon + local _, _, castingFromAura = BCS:GetPlayerAura(L["(%d+)%% of your Mana regeneration continuing while casting."]) + if castingFromAura then + BCScache["auras"].casting = BCScache["auras"].casting + tonumber(castingFromAura) + end + --Mage Armor + _, _, castingFromAura = BCS:GetPlayerAura(L["(%d+)%% of your mana regeneration to continue while casting."]) + if castingFromAura then + BCScache["auras"].casting = BCScache["auras"].casting + tonumber(castingFromAura) + end end - -- buffs - -- Warchief's Blessing - local _, _, mp5FromAura = BCS:GetPlayerAura(L["Increases hitpoints by 300. 15%% haste to melee attacks. (%d+) mana regen every 5 seconds."]) - if mp5FromAura then - mp5 = mp5 + 10 - end - --Epiphany - _, _, mp5FromAura = BCS:GetPlayerAura(L["Restores (%d+) mana per 5 sec."]) - if mp5FromAura then - mp5 = mp5 + tonumber(mp5FromAura) - end - --Nightfin Soup - _, _, mp5FromAura = BCS:GetPlayerAura(L["Regenerating (%d+) Mana every 5 seconds."]) - if mp5FromAura then - mp5 = mp5 + tonumber(mp5FromAura)*2.5 -- had to double the mp5FromAura because the item is a true mp5 tick - end - --Mageblood Potion - _, _, mp5FromAura = BCS:GetPlayerAura(L["Regenerate (%d+) mana per 5 sec."]) - if mp5FromAura then - mp5 = mp5 + tonumber(mp5FromAura) - end - --Fizzy Energy Drink and Sagefin - _, _, mp5FromAura = BCS:GetPlayerAura(L["Mana Regeneration increased by (%d+) every 5 seconds."]) - if mp5FromAura then - mp5 = mp5 + tonumber(mp5FromAura)*2.5 - end - --Second Wind - _, _, mp5FromAura = BCS:GetPlayerAura(L["Restores (%d+) mana every 1 sec."]) - if mp5FromAura then - mp5 = mp5 + tonumber(mp5FromAura)*5 -- had to multiply by 5 the mp5FromAura because the item is a sec per tick - end - --Power of the Guardian - _, _, mp5FromAura = BCS:GetPlayerAura("Restores (%d+) mana per 5 seconds.") - if mp5FromAura then - mp5 = mp5 + tonumber(mp5FromAura) - end - --Aura of the blue dragon - local _, _, castingFromAura = BCS:GetPlayerAura(L["(%d+)%% of your Mana regeneration continuing while casting."]) - if castingFromAura then - casting = casting + tonumber(castingFromAura) - end - --Mage Armor - _, _, castingFromAura = BCS:GetPlayerAura(L["(%d+)%% of your mana regeneration to continue while casting."]) - if castingFromAura then - casting = casting + tonumber(castingFromAura) - end - + + mp5 = BCScache["auras"].mp5 + BCScache["gear"].mp5 + -- scan talents - local MAX_TABS = GetNumTalentTabs() local brilliance = nil - for tab=1, MAX_TABS do - local MAX_TALENTS = GetNumTalents(tab) - - for talent=1, MAX_TALENTS do - BCS_Tooltip:SetTalent(tab, talent) - local MAX_LINES = BCS_Tooltip:NumLines() - - for line=1, MAX_LINES do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) - local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - if value and rank > 0 then - casting = casting + tonumber(value) - break - end - -- Brilliance Aura (own) - local haveTalent = strfind(left:GetText(), "Brilliance Aura") - if haveTalent and rank > 0 and BCS:GetPlayerAura("Brilliance Aura") then - brilliance = (base + (mp5 * 0.4)) * 0.15 + if BCS.needScanTalents then + BCScache["talents"].casting = 0 + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) + local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) + if value and rank > 0 then + BCScache["talents"].casting = BCScache["talents"].casting + tonumber(value) + break + end + -- Brilliance Aura (own) + if strfind(left:GetText(), "Brilliance Aura") and rank > 0 and BCS:GetPlayerAura("Brilliance Aura") then + brilliance = (base + (mp5 * 0.4)) * 0.15 + end end end end - end end + + casting = BCScache["auras"].casting + BCScache["talents"].casting + BCScache["gear"].casting + if casting > 100 then casting = 100 end - + return base, casting, mp5, brilliance end + +--Weapon Skill code adapted from https://github.com/pepopo978/BetterCharacterStats +function BCS:GetWeaponSkill(skillName) + -- loop through skills + local skillIndex = 1 + while true do + local name, isHeader, isExpanded, skillRank, numTempPoints, skillModifier, + skillMaxRank, isAbandonable, stepCost, rankCost, minLevel, skillCostType, + skillDescription = GetSkillLineInfo(skillIndex) + if not name then + return 0 + end + + if name == skillName then + return skillRank + skillModifier + end + + skillIndex = skillIndex + 1 + end +end + +function BCS:GetWeaponSkillForWeaponType(weaponType) + if weaponType == "Daggers" then + return BCS:GetWeaponSkill("Daggers") + elseif weaponType == "One-Handed Swords" then + return BCS:GetWeaponSkill("Swords") + elseif weaponType == "Two-Handed Swords" then + return BCS:GetWeaponSkill("Two-Handed Swords") + elseif weaponType == "One-Handed Axes" then + return BCS:GetWeaponSkill("Axes") + elseif weaponType == "Two-Handed Axes" then + return BCS:GetWeaponSkill("Two-Handed Axes") + elseif weaponType == "One-Handed Maces" then + return BCS:GetWeaponSkill("Maces") + elseif weaponType == "Two-Handed Maces" then + return BCS:GetWeaponSkill("Two-Handed Maces") + elseif weaponType == "Staves" then + return BCS:GetWeaponSkill("Staves") + elseif weaponType == "Polearms" then + return BCS:GetWeaponSkill("Polearms") + elseif weaponType == "Fist Weapons" then + return BCS:GetWeaponSkill("Unarmed") + elseif weaponType == "Bows" then + return BCS:GetWeaponSkill("Bows") + elseif weaponType == "Crossbows" then + return BCS:GetWeaponSkill("Crossbows") + elseif weaponType == "Guns" then + return BCS:GetWeaponSkill("Guns") + elseif weaponType == "Thrown" then + return BCS:GetWeaponSkill("Thrown") + elseif weaponType == "Wands" then + return BCS:GetWeaponSkill("Wands") + end + -- no weapon equipped + return BCS:GetWeaponSkill("Unarmed") +end + +function BCS:GetItemInfoForSlot(slot) + local _, _, id = string.find(GetInventoryItemLink("player", GetInventorySlotInfo(slot)) or "", "(item:%d+:%d+:%d+:%d+)"); + if not id then + return + end + + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(id); + + return itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice; +end + +function BCS:GetMHWeaponSkill() + if not BCS.needScanSkills then return BCScache["skills"].mh end + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("MainHandSlot") + BCScache["skills"].mh = BCS:GetWeaponSkillForWeaponType(itemType) + return BCScache["skills"].mh +end + +function BCS:GetOHWeaponSkill() + if not BCS.needScanSkills then return BCScache["skills"].oh end + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("SecondaryHandSlot") + BCScache["skills"].oh = BCS:GetWeaponSkillForWeaponType(itemType) + return BCScache["skills"].oh +end + +function BCS:GetRangedWeaponSkill() + if not BCS.needScanSkills then return BCScache["skills"].ranged end + local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, + itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("RangedSlot") + BCScache["skills"].ranged = BCS:GetWeaponSkillForWeaponType(itemType) + return BCScache["skills"].ranged +end From cc0c4de08c794b48627bd0e84c72ece27bbe49f0 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Mon, 14 Oct 2024 10:45:19 +0300 Subject: [PATCH 11/39] spell hit and crit reworked now tooltip will change if you have talents or auras that increase spell hit / crit --- BetterCharacterStats.lua | 142 +++++++++---- BetterCharacterStats.toc | 4 +- Localization.lua | 40 +++- helper.lua | 428 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 561 insertions(+), 53 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 93dfb82..a9a7941 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -78,7 +78,7 @@ function BCS:OnLoad() self.Frame:RegisterEvent("CHARACTER_POINTS_CHANGED") -- fires when learning talent self.Frame:RegisterEvent("PLAYER_AURAS_CHANGED") -- buffs/warrior stances self.Frame:RegisterEvent("CHAT_MSG_SKILL") --gaining weapon skill - self.Frame:RegisterEvent("CHAT_MSG_ADDON") + self.Frame:RegisterEvent("CHAT_MSG_ADDON") --needed to recieve aura bonuses from other people end -- Scan stuff depending on event, but make sure to scan everything when addon is loaded function BCS:OnEvent() @@ -642,15 +642,12 @@ function BCS:SetRating(statFrame, ratingType) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") label:SetText(L.MELEE_HIT_RATING_COLON) - if ratingType == "MELEE" then local rating = BCS:GetHitRating() rating = rating .. "%" text:SetText(rating) - frame.tooltip = (L.MELEE_HIT_TOOLTIP) frame.tooltipSubtext = format(L.MELEE_HIT_TOOLTIP_SUB) - elseif ratingType == "RANGED" then -- If no ranged attack then set to n/a if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then @@ -660,47 +657,38 @@ function BCS:SetRating(statFrame, ratingType) local rating = BCS:GetRangedHitRating() rating = rating .. "%" text:SetText(rating) - frame.tooltip = (L.RANGED_HIT_TOOLTIP) frame.tooltipSubtext = format(L.RANGED_HIT_TOOLTIP_SUB) - elseif ratingType == "SPELL" then local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow = BCS:GetSpellHitRating() - - if spell_hit_fire > 0 or spell_hit_frost > 0 or spell_hit_arcane > 0 or spell_hit_shadow > 0 then - -- got spell hit from talents - local spell_hit_other, spell_hit_other_type - - spell_hit_other = 0 - spell_hit_other_type = "" - - if spell_hit_fire > spell_hit_other then - spell_hit_other = spell_hit_fire - spell_hit_other_type = L.SPELL_SCHOOL_FIRE - end - if spell_hit_frost > spell_hit_other then - spell_hit_other = spell_hit_frost - spell_hit_other_type = L.SPELL_SCHOOL_FROST - end - if spell_hit_arcane > spell_hit_other then - spell_hit_other = spell_hit_arcane - spell_hit_other_type = L.SPELL_SCHOOL_ARCANE - end - if spell_hit_shadow > spell_hit_other then - spell_hit_other = spell_hit_shadow - spell_hit_other_type = L.SPELL_SCHOOL_SHADOW - end - - frame.tooltip = format(L.SPELL_HIT_SECONDARY_TOOLTIP, spell_hit + spell_hit_other, spell_hit, spell_hit_other, spell_hit_other_type) - text:SetText(spell_hit + spell_hit_other .. "%") - else - frame.tooltip = L.SPELL_HIT_TOOLTIP - text:SetText(spell_hit .. "%") - end + frame.tooltip = format(L.SPELL_HIT_TOOLTIP) + text:SetText(spell_hit .. "%") frame.tooltipSubtext = format(L.SPELL_HIT_TOOLTIP_SUB) + if frame.tooltip then + frame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + if spell_hit_fire > 0 then + GameTooltip:AddLine(format(L.SPELL_SCHOOL_FIRE.." spells: %.f%%", spell_hit + spell_hit_fire)) + end + if spell_hit_frost > 0 then + GameTooltip:AddLine(format(L.SPELL_SCHOOL_FROST.." spells: %.f%%", spell_hit + spell_hit_frost)) + end + if spell_hit_arcane > 0 then + GameTooltip:AddLine(format(L.SPELL_SCHOOL_ARCANE.." spells: %.f%%", spell_hit + spell_hit_arcane)) + end + if spell_hit_shadow > 0 then + GameTooltip:AddLine(format(L.SPELL_SCHOOL_SHADOW.." spells: %.f%%", spell_hit + spell_hit_shadow)) + end + GameTooltip:Show() + end) + frame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + end end - - if frame.tooltip then + if frame.tooltip and ratingType ~= "SPELL" then frame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) @@ -711,7 +699,6 @@ function BCS:SetRating(statFrame, ratingType) GameTooltip:Hide() end) end - end function BCS:SetMeleeCritChance(statFrame) @@ -783,15 +770,86 @@ function BCS:SetSpellCritChance(statFrame) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - + local _, class = UnitClass("player") label:SetText(L.SPELL_CRIT_COLON) - text:SetText(format("%.2f%%", BCS:GetSpellCritChance())) + + local generic = BCS:GetSpellCritChance() + local spell1, spell2, spell3, spell4, spell5, spell6 = BCS:GetSpellCritFromClass(class) + + text:SetText(format("%.2f%%", generic)) frame.tooltip = format(L.SPELL_CRIT_TOOLTIP) frame.tooltipSubtext = format(L.SPELL_CRIT_TOOLTIP_SUB) frame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + local total1 = generic + spell1 + local total2 = generic + spell2 + local total3 = generic + spell3 + local total4 = generic + spell4 + local total5 = generic + spell5 + local total6 = generic + spell6 + if total1 > 100 then total1 = 100 end + if total2 > 100 then total2 = 100 end + if total3 > 100 then total3 = 100 end + if total4 > 100 then total4 = 100 end + if total5 > 100 then total5 = 100 end + if total6 > 100 then total6 = 100 end + if class == "DRUID" then + if spell1 > 0 then + GameTooltip:AddLine(format("Moonfire: %.2f%%", total1)) end + if spell2 > 0 then + GameTooltip:AddLine(format("Regrowth: %.2f%%", total2)) end + elseif class == "PALADIN" then + if spell1 > 0 then + GameTooltip:AddLine(format("Holy spells: %.2f%%", total1)) end + if spell2 > 0 then + GameTooltip:AddLine(format("Holy Light: %.2f%%", total2)) end + if spell3 > 0 then + GameTooltip:AddLine(format("Flash of Light: %.2f%%", total3)) end + if spell4 > 0 then + GameTooltip:AddLine(format("Holy Shock: %.2f%%", total4)) end + elseif class == "WARLOCK" then + if spell1 > 0 then + GameTooltip:AddLine(format("Destruction spells: %.2f%%", total1)) end + if spell2 > 0 then + GameTooltip:AddLine(format("Searing Pain: %.2f%%", total2)) end + elseif class == "PRIEST" then + if spell1 > 0 then + GameTooltip:AddLine(format("Healing spells: %.2f%%", total1)) end + if spell2 > 0 then + GameTooltip:AddLine(format("Prayer of Healing: %.2f%%", total2)) end + if spell3 > 0 then + GameTooltip:AddLine(format("Offensive spells: %.2f%%", total3)) end + if spell4 > 0 then + GameTooltip:AddLine(format("Smite: %.2f%%", total4)) end + if spell5 > 0 then + GameTooltip:AddLine(format("Holy Fire: %.2f%%", total5)) end + elseif class == "MAGE" then + if spell1 > 0 then + GameTooltip:AddLine(format("Arcane spells: %.2f%%", total1)) end + if spell2 > 0 then + GameTooltip:AddLine(format("Fire spells: %.2f%%", total2)) end + if spell3 > 0 then + GameTooltip:AddLine(format("Fire Blast: %.2f%%", total3)) end + if spell4 > 0 then + GameTooltip:AddLine(format("Scorch: %.2f%%", total4)) end + if spell5 > 0 then + GameTooltip:AddLine(format("Flamestrike: %.2f%%", total5)) end + if spell6 > 0 then + GameTooltip:AddLine(format("Frozen targets: %.2f%%", total6)) end + elseif class == "SHAMAN" then + if spell1 > 0 then + GameTooltip:AddLine(format("Lightning Bolt: %.2f%%", total1)) end + if spell2 > 0 then + GameTooltip:AddLine(format("Chain Lightning: %.2f%%", total2)) end + if spell3 > 0 then + GameTooltip:AddLine(format("Lightning Shield: %.2f%%", total3)) end + if spell4 > 0 then + GameTooltip:AddLine(format("Fire and Frost spells: %.2f%%", total4)) end + if spell5 > 0 then + GameTooltip:AddLine(format("Healing spells: %.2f%%", total5)) end + end GameTooltip:Show() end) frame:SetScript("OnLeave", function() diff --git a/BetterCharacterStats.toc b/BetterCharacterStats.toc index 77180cd..ada335f 100644 --- a/BetterCharacterStats.toc +++ b/BetterCharacterStats.toc @@ -1,7 +1,7 @@ ## Interface: 11200 ## Title: BetterCharacterStats -## Author: moh, Bennylava, |cffbe5effLexie|r -## Version: 1.12.5 +## Author: moh, Bennylava, |cffbe5effLexie|r, Spit, Pepopo +## Version: 1.12.6 ## SavedVariablesPerCharacter: BCSConfig bcsupdateavailable BCScache BetterCharacterStats.xml diff --git a/Localization.lua b/Localization.lua index 29644be..971539f 100644 --- a/Localization.lua +++ b/Localization.lua @@ -101,9 +101,33 @@ BCS["L"] = { ["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."] = "Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration.", ["Critical strike chance with spells and melee attacks increased by (%d+)%%."] = "Critical strike chance with spells and melee attacks increased by (%d+)%%.", + -- druid + ["Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%."] = "Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%.", + ["Increases the critical effect chance of your Regrowth spell by (%d+)%%."] = "Increases the critical effect chance of your Regrowth spell by (%d+)%%.", + -- paladin + ["Increases the critical effect chance of your Holy spells by (%d+)%%."] = "Increases the critical effect chance of your Holy spells by (%d+)%%.", -- same for priest + ["When activated, gives your next Flash of Light, Holy Light or Holy Shock spell a (%d+)%% critical effect chance."] = "When activated, gives your next Flash of Light, Holy Light or Holy Shock spell a (%d+)%% critical effect chance.", + -- shaman + ["Increases the critical strike chance of your Lightning Bolt and Chain Lightning spells by an additional (%d+)%%."] = "Increases the critical strike chance of your Lightning Bolt and Chain Lightning spells by an additional (%d+)%%.", + ["Increases the critical effect chance of your healing and lightning spells by (%d+)%%."] = "Increases the critical effect chance of your healing and lightning spells by (%d+)%%.", + -- warlock + ["Increases the critical strike chance of your Destruction spells by (%d+)%%."] = "Increases the critical strike chance of your Destruction spells by (%d+)%%.", + ["Increases the critical strike chance of your Searing Pain spell by (%d+)%%."] = "Increases the critical strike chance of your Searing Pain spell by (%d+)%%.", + -- mage + ["Increases the critical strike chance of your Arcane Explosion and Arcane Missiles spells by an additional (%d+)%%."] = "Increases the critical strike chance of your Arcane Explosion and Arcane Missiles spells by an additional (%d+)%%.", + ["Increases the critical strike chance of your Fire Blast and Scorch spells by (%d+)%%."] = "Increases the critical strike chance of your Fire Blast and Scorch spells by (%d+)%%.", + ["Increases the critical strike chance of your Flamestrike spell by (%d+)%%."] = "Increases the critical strike chance of your Flamestrike spell by (%d+)%%.", + ["Increases the critical strike chance of your Fire spells by (%d+)%%."] = "Increases the critical strike chance of your Fire spells by (%d+)%%.", + ["Increases the critical strike chance of all your spells against frozen targets by (%d+)%%."] = "Increases the critical strike chance of all your spells against frozen targets by (%d+)%%.", + ["Increases your spell damage and critical srike chance by (%d+)%%."] = "Increases your spell damage and critical srike chance by (%d+)%%.", + ["Increases critical strike chance from Fire damage spells by (%d+)%%."] = "Increases critical strike chance from Fire damage spells by (%d+)%%.", + -- priest + ["Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%."] = "Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%.", + ["^Set: Improves your chance to get a critical strike with Holy spells by (%d)%%."] = "^Set: Improves your chance to get a critical strike with Holy spells by (%d)%%.", + ["^Set: Increases your chance of a critical hit with Prayer of Healing by (%d+)%%."] = "^Set: Increases your chance of a critical hit with Prayer of Healing by (%d+)%%.", --defense ["DEFENSE_TOOLTIP"] = [[|cffffffffDefense Skill|r]], - ["DEFENSE_TOOLTIP_SUB"] = [[Highier defense makes you harder to hit and makes monsters less likely to land a crushing blow.]], + ["DEFENSE_TOOLTIP_SUB"] = [[Higher defense makes you harder to hit and makes monsters less likely to land a crushing blow.]], ["PLAYER_DODGE_TOOLTIP"] = [[|cffffffffDodge|r]], ["PLAYER_DODGE_TOOLTIP_SUB"] = [[Your chance to dodge enemy melee attacks. @@ -126,10 +150,10 @@ BCS["L"] = { ["MELEE_CRIT_TOOLTIP"] = [[|cffffffffMelee Crit|r]], ["MELEE_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with melee attacks.]], ["MELEE_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffMelee Weapon Skill|r]], - ["MELEE_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss and increases damage of your glancing blows, while using melee weapons.]], + ["MELEE_WEAPON_SKILL_TOOLTIP_SUB"] = [[Higher weapon skill reduces your chance to miss and increases damage of your glancing blows, while using melee weapons.]], --ranged ["RANGED_WEAPON_SKILL_TOOLTIP"] = [[|cffffffffRanged Weapon Skill|r]], - ["RANGED_WEAPON_SKILL_TOOLTIP_SUB"] = [[Highier weapon skill reduces your chance to miss with a ranged weapon.]], + ["RANGED_WEAPON_SKILL_TOOLTIP_SUB"] = [[Higher weapon skill reduces your chance to miss with a ranged weapon.]], ["RANGED_CRIT_TOOLTIP"] = [[|cffffffffRanged Crit|r]], ["RANGED_CRIT_TOOLTIP_SUB"] = [[Your chance to land a critical strike with ranged weapons.]], ["RANGED_HIT_TOOLTIP"] = [[|cffffffffRanged Hit|r]], @@ -137,7 +161,7 @@ BCS["L"] = { --spells ["SPELL_HIT_TOOLTIP"] = [[|cffffffffSpell Hit|r]], - ["SPELL_HIT_SECONDARY_TOOLTIP"] = [[|cffffffffSpell Hit%d%% (%d%%|cff20ff20+%d%% %s|r|cffffffff)|rIncreases chance to land a spell.]], + ["SPELL_HIT_SECONDARY_TOOLTIP"] = [[|cffffffffSpell Hit (%d%%|cff20ff20+%d%% %s|r|cffffffff)|r]], ["SPELL_HIT_TOOLTIP_SUB"] = [[Increases chance to land a harmful spell.]], ["SPELL_CRIT_TOOLTIP"] = [[|cffffffffSpell Crit|r]], @@ -158,10 +182,10 @@ BCS["L"] = { ["SPELL_MANA_REGEN_TOOLTIP"] = [[|cffffffffMana regen: %d |cffffffff(%d)|r]], ["SPELL_MANA_REGEN_TOOLTIP_SUB"] = [[Mana regen when not casting and (while casting). Mana regenerates every 2 seconds and the amount is dependent on your total spirit and MP5. - Spirit Regen: |cffffffff%d|r - Regen while casting: |cffffffff%d%%|r - MP5 Regen: |cffffffff%d|r - MP5 Regen (2s): |cffffffff%d|r]], + Spirit Regen: %d + Regen while casting: %d%% + MP5 Regen: %d + MP5 Regen (2s): %d]], PLAYERSTAT_BASE_STATS = "Base Stats", PLAYERSTAT_DEFENSES = "Defenses", diff --git a/helper.lua b/helper.lua index 2570109..0f88441 100644 --- a/helper.lua +++ b/helper.lua @@ -602,11 +602,437 @@ function BCS:GetSpellCritChance() end end - spellCrit = spellCrit + BCScache["gear"].spell_crit + BCScache["auras"].spell_crit + -- scan talents + if BCS.needScanTalents then + BCScache["talents"].spell_crit = 0 + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Arcane Instability + local _,_, value = strfind(left:GetText(), L["Increases your spell damage and critical srike chance by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].spell_crit = BCScache["talents"].spell_crit + tonumber(value) + break + end + end + end + end + end + end + + spellCrit = spellCrit + BCScache["talents"].spell_crit + BCScache["gear"].spell_crit + BCScache["auras"].spell_crit return spellCrit end +function BCS:GetSpellCritFromClass(class) + if not class then return 0, 0, 0, 0, 0, 0 end + --[[ + Warlock: + Devastation: + 1/2/3/4/5 % + Shadowbolt + Immolate + Searing Pain + Soulfire + Hellfire ? + Rain of Fire ? + Shadowburn + is there more? + Improved Searing Pain: + 2/4/6/8/10 % + Searing Pain + Mage: + Arcane Impact: + 2/4/6 % + Arcane Explosion + Arcane Missiles + Incinerate: + 2/4 % -? + Fireblast + Scorch + Improved Flamestrike: + 5/10/15 % + Flamestrike + Critical Mass: + 2/4/6 % + Fireball + Fireblast + Scorch + Flamestrike + Pyroblast + Blast Wave + Combustion: + +10% +20% +30% fire spell crit and so on untill 3 fire spell crits; DOES have stacks; + Shatter: + "Increases the critical strike chance of all your spells against frozen targets by (%d+)%%." + + to all spells agains FROZEN target + Paladin: + Holy power: + 1/2/3/4/5 % + Holy Light + Flash of Light + Holy Shock + Lay on Hands ? + Divine Favor: 100% while active + Holy Light + Flash of Light + Holy Shock + Druid: + Improved Moonfire: + 2/4/6/8/10 % + Moonfire + Improved Regrowth: + 10/20/30/40/50 % + Regrowth + Shaman: + Call of Thunder: + 1/2/4/6 % ? + Lightning Bolt + Chain Lightning + Tidal Mastery: + 1/2/3/4/5 % + Lightning Bolt + Chain Lightning + Lesser Healing Wave + Healing Wave + Chain Heal + Lightning shield + Stormstrike ? + (baseline?) Elemental Mastery: 100% while active (fire, frost, nature damage spells) + Lightning Bolt + Chain Lightning + Earth Shock + Flame Shock + Frost Shock + Fire Nova + Priest: + Force of Will: + 1/2/3/4/5 % + Smite + Holy Fire + Mind Blast + Pain Spike + Mana Burn + Holy Nova + Holy Specialization: + 1/2/3/4/5 % + Lesser Heal + Heal + Flash Heal + Greater Heal + Prayer of Healing + Smite + Desperate Prayer + ]] + if class == "PALADIN" then + --scan talents + if BCS.needScanTalents or BCS.needScanAuras then + BCScache["talents"].paladin_holy_spells = 0 + BCScache["talents"].paladin_holy_light = 0 + BCScache["talents"].paladin_flash = 0 + BCScache["talents"].paladin_shock = 0 + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Holy Power + local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].paladin_holy_spells = BCScache["talents"].paladin_holy_spells + tonumber(value) + break + end + end + end + end + end + end + if BCS.needScanAuras then + BCScache["talents"].paladin_holy_light = 0 + BCScache["talents"].paladin_flash = 0 + BCScache["talents"].paladin_shock = 0 + -- Buffs + -- Divine Favor + if BCS:GetPlayerAura("Divine Favor") then + BCScache["talents"].paladin_holy_light = 100 + BCScache["talents"].paladin_flash = 100 + BCScache["talents"].paladin_shock = 100 + end + end + return BCScache["talents"].paladin_holy_spells, + BCScache["talents"].paladin_holy_light, + BCScache["talents"].paladin_flash, + BCScache["talents"].paladin_shock, 0, 0 + elseif class == "DRUID" then + --scan talents + if BCS.needScanTalents then + BCScache["talents"].druid_moonfire = 0 + BCScache["talents"].druid_regrowth = 0 + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Improved Moonfire + local _,_, value = strfind(left:GetText(), L["Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].druid_moonfire = BCScache["talents"].druid_moonfire + tonumber(value) + break + end + -- Improved Regrowth + _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Regrowth spell by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].druid_regrowth = BCScache["talents"].druid_regrowth + tonumber(value) + break + end + end + end + end + end + end + + return BCScache["talents"].druid_moonfire, + BCScache["talents"].druid_regrowth, 0, 0, 0, 0 + elseif class == "WARLOCK" then + --scan talents + if BCS.needScanTalents then + BCScache["talents"].warlock_destruction_spells = 0 + BCScache["talents"].warlock_searing_pain = 0 + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Devastation + local _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Destruction spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].warlock_destruction_spells = BCScache["talents"].warlock_destruction_spells + tonumber(value) + BCScache["talents"].warlock_searing_pain = BCScache["talents"].warlock_searing_pain + tonumber(value) + break + end + -- Improved Searing Pain + _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Searing Pain spell by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].warlock_searing_pain = BCScache["talents"].warlock_searing_pain + tonumber(value) + break + end + end + end + end + end + end + + return BCScache["talents"].warlock_destruction_spells, + BCScache["talents"].warlock_searing_pain, 0, 0, 0, 0 + elseif class == "MAGE" then + --scan talents + if BCS.needScanTalents or BCS.needScanAuras then + BCScache["talents"].mage_arcane_spells = 0 + BCScache["talents"].mage_fire_spells = 0 + BCScache["talents"].mage_fireblast = 0 + BCScache["talents"].mage_scorch = 0 + BCScache["talents"].mage_flamestrike = 0 + BCScache["talents"].mage_frozen = 0 + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Arcane Impact + local _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Arcane Explosion and Arcane Missiles spells by an additional (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].mage_arcane_spells = BCScache["talents"].mage_arcane_spells + tonumber(value) + break + end + -- Incinerate + _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Fire Blast and Scorch spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].mage_fireblast = BCScache["talents"].mage_fireblast + tonumber(value) + BCScache["talents"].mage_scorch = BCScache["talents"].mage_scorch + tonumber(value) + break + end + -- Improved Flamestrike + _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Flamestrike spell by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].mage_flamestrike = BCScache["talents"].mage_flamestrike + tonumber(value) + break + end + -- Critical Mass + _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Fire spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].mage_fire_spells = BCScache["talents"].mage_fire_spells + tonumber(value) + BCScache["talents"].mage_fireblast = BCScache["talents"].mage_fireblast + tonumber(value) + BCScache["talents"].mage_flamestrike = BCScache["talents"].mage_flamestrike + tonumber(value) + BCScache["talents"].mage_scorch = BCScache["talents"].mage_scorch + tonumber(value) + break + end + -- Shatter + _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of all your spells against frozen targets by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].mage_frozen = BCScache["talents"].mage_frozen + tonumber(value) + break + end + end + end + end + end + -- Buffs + local _, _, value = BCS:GetPlayerAura(L["Increases critical strike chance from Fire damage spells by (%d+)%%."]) + -- Combustion + if value then + BCScache["talents"].mage_fire_spells = BCScache["talents"].mage_fire_spells + value + BCScache["talents"].mage_fireblast = BCScache["talents"].mage_fireblast + value + BCScache["talents"].mage_flamestrike = BCScache["talents"].mage_flamestrike + value + BCScache["talents"].mage_scorch = BCScache["talents"].mage_scorch + value + end + end + return BCScache["talents"].mage_arcane_spells, + BCScache["talents"].mage_fire_spells, + BCScache["talents"].mage_fireblast, + BCScache["talents"].mage_scorch, + BCScache["talents"].mage_flamestrike, + BCScache["talents"].mage_frozen + elseif class == "PRIEST" then + if BCS.needScanTalents then + BCScache["talents"].priest_healing_spells = 0 + BCScache["talents"].priest_offensive_spells = 0 + BCScache["talents"].priest_smite = 0 + BCScache["talents"].priest_holy_fire = 0 + BCScache["talents"].priest_prayer = 0 + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Holy Specialization + local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].priest_healing_spells = BCScache["talents"].priest_healing_spells + tonumber(value) + BCScache["talents"].priest_smite = BCScache["talents"].priest_smite + tonumber(value) + BCScache["talents"].priest_holy_fire = BCScache["talents"].priest_holy_fire + tonumber(value) + break + end + -- Force of Will + _,_, value = strfind(left:GetText(), L["Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%."]) + if value and rank > 0 then + BCScache["talents"].priest_offensive_spells = BCScache["talents"].priest_offensive_spells + tonumber(value) + BCScache["talents"].priest_smite = BCScache["talents"].priest_smite + tonumber(value) + BCScache["talents"].priest_holy_fire = BCScache["talents"].priest_holy_fire + tonumber(value) + break + end + end + end + end + end + end + -- scan gear + if BCS.needScanGear then + -- t1 set gives + 2 crit to holy and 25 to prayer of healing + BCScache["gear"].priest_healing_spells = 0 + BCScache["gear"].priest_smite = 0 + BCScache["gear"].priest_holy_fire = 0 + BCScache["gear"].priest_prayer = 0 + local Crit_Set_Bonus = {} + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + local SET_NAME = nil + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") + if value then + SET_NAME = value + end + _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to get a critical strike with Holy spells by (%d)%%."]) + if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then + tinsert(Crit_Set_Bonus, SET_NAME) + BCScache["gear"].priest_healing_spells = BCScache["gear"].priest_healing_spells + tonumber(value) + BCScache["gear"].priest_smite = BCScache["gear"].priest_smite + tonumber(value) + BCScache["gear"].priest_holy_fire = BCScache["gear"].priest_holy_fire + tonumber(value) + end + _, _, value = strfind(left:GetText(), L["^Set: Increases your chance of a critical hit with Prayer of Healing by (%d+)%%."]) + if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then + tinsert(Crit_Set_Bonus, SET_NAME) + BCScache["gear"].priest_prayer = BCScache["gear"].priest_prayer + tonumber(value) + end + end + end + end + end + end + local healingSpells, smite, holyFire, prayer + healingSpells = BCScache["talents"].priest_healing_spells + BCScache["gear"].priest_healing_spells + smite = BCScache["talents"].priest_smite + BCScache["gear"].priest_smite + holyFire = BCScache["talents"].priest_holy_fire + BCScache["gear"].priest_holy_fire + prayer = BCScache["talents"].priest_prayer + BCScache["gear"].priest_prayer + return healingSpells, prayer, BCScache["talents"].priest_offensive_spells, smite, holyFire, 0 + elseif class == "SHAMAN" then + if BCS.needScanTalents then + BCScache["talents"].shaman_lightning_bolt = 0 + BCScache["talents"].shaman_chain_lightning = 0 + BCScache["talents"].shaman_lightning_shield = 0 + BCScache["talents"].shaman_firefrost_spells = 0 + BCScache["talents"].shaman_healing_spells = 0 + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Call of Thunder + local _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Lightning Bolt and Chain Lightning spells by an additional (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].shaman_lightning_bolt = BCScache["talents"].shaman_lightning_bolt + tonumber(value) + BCScache["talents"].shaman_chain_lightning = BCScache["talents"].shaman_chain_lightning + tonumber(value) + break + end + -- Tidal Mastery + _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your healing and lightning spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].shaman_lightning_bolt = BCScache["talents"].shaman_lightning_bolt + tonumber(value) + BCScache["talents"].shaman_chain_lightning = BCScache["talents"].shaman_chain_lightning + tonumber(value) + BCScache["talents"].shaman_lightning_shield = BCScache["talents"].shaman_lightning_shield + tonumber(value) + BCScache["talents"].shaman_healing_spells = BCScache["talents"].shaman_healing_spells + tonumber(value) + break + end + end + end + end + end + end + -- buffs + if BCS.needScanAuras then + BCScache["auras"].shaman_lightning_bolt = 0 + BCScache["auras"].shaman_chain_lightning = 0 + BCScache["auras"].shaman_firefrost_spells = 0 + local hasAura = BCS:GetPlayerAura("Elemental Mastery") + if hasAura then + BCScache["auras"].shaman_lightning_bolt = 100 + BCScache["auras"].shaman_chain_lightning = 100 + BCScache["auras"].shaman_firefrost_spells = 100 + end + end + local lightningBolt = BCScache["auras"].shaman_lightning_bolt + BCScache["talents"].shaman_lightning_bolt + local chainLightning = BCScache["auras"].shaman_chain_lightning + BCScache["talents"].shaman_chain_lightning + return lightningBolt, chainLightning, + BCScache["talents"].shaman_lightning_shield, + BCScache["auras"].shaman_firefrost_spells, + BCScache["talents"].shaman_healing_spells, 0 + else + return 0, 0, 0, 0, 0, 0 + end +end + function BCS:GetSpellPower(school) if school then local spellPower = 0; From 97f56b721f6fa2427030fa9aedca64a0ebedfe8f Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Mon, 14 Oct 2024 11:55:35 +0300 Subject: [PATCH 12/39] bug fix fixed paladin talent Precision not being counted in spell hit added warlock Suppression talent --- BetterCharacterStats.lua | 60 ++++++++++++++++++++++++---------------- Localization.lua | 1 + helper.lua | 17 +++++++++--- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index a9a7941..00ec20c 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -641,6 +641,7 @@ function BCS:SetRating(statFrame, ratingType) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + local _, class = UnitClass("player") label:SetText(L.MELEE_HIT_RATING_COLON) if ratingType == "MELEE" then local rating = BCS:GetHitRating() @@ -679,7 +680,11 @@ function BCS:SetRating(statFrame, ratingType) GameTooltip:AddLine(format(L.SPELL_SCHOOL_ARCANE.." spells: %.f%%", spell_hit + spell_hit_arcane)) end if spell_hit_shadow > 0 then - GameTooltip:AddLine(format(L.SPELL_SCHOOL_SHADOW.." spells: %.f%%", spell_hit + spell_hit_shadow)) + if class == "WARLOCK" then + GameTooltip:AddLine(format("Affliction spells: %.f%%", spell_hit + spell_hit_shadow)) + else + GameTooltip:AddLine(format(L.SPELL_SCHOOL_SHADOW.." spells: %.f%%", spell_hit + spell_hit_shadow)) + end end GameTooltip:Show() end) @@ -775,26 +780,35 @@ function BCS:SetSpellCritChance(statFrame) local generic = BCS:GetSpellCritChance() local spell1, spell2, spell3, spell4, spell5, spell6 = BCS:GetSpellCritFromClass(class) + local total1 = generic + spell1 + local total2 = generic + spell2 + local total3 = generic + spell3 + local total4 = generic + spell4 + local total5 = generic + spell5 + local total6 = generic + spell6 + if total1 > 100 then total1 = 100 end + if total2 > 100 then total2 = 100 end + if total3 > 100 then total3 = 100 end + if total4 > 100 then total4 = 100 end + if total5 > 100 then total5 = 100 end + if total6 > 100 then total6 = 100 end text:SetText(format("%.2f%%", generic)) + if class == "WARLOCK" and spell1 > 0 then -- warlock spells that can crit are all destruction so just add this to generic + text:SetText(format("%.2f%%", generic + spell1)) + elseif class == "PRIEST" and spell3 > 0 and spell1 > 0 then -- if priest have both talents add lowest to generic cos there will be no more spells left that can crit + if spell1 < spell3 then + text:SetText(format("%.2f%%", generic + spell1)) + elseif spell1 >= spell3 then + text:SetText(format("%.2f%%", generic + spell3)) + end + end frame.tooltip = format(L.SPELL_CRIT_TOOLTIP) frame.tooltipSubtext = format(L.SPELL_CRIT_TOOLTIP_SUB) frame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - local total1 = generic + spell1 - local total2 = generic + spell2 - local total3 = generic + spell3 - local total4 = generic + spell4 - local total5 = generic + spell5 - local total6 = generic + spell6 - if total1 > 100 then total1 = 100 end - if total2 > 100 then total2 = 100 end - if total3 > 100 then total3 = 100 end - if total4 > 100 then total4 = 100 end - if total5 > 100 then total5 = 100 end - if total6 > 100 then total6 = 100 end if class == "DRUID" then if spell1 > 0 then GameTooltip:AddLine(format("Moonfire: %.2f%%", total1)) end @@ -810,31 +824,29 @@ function BCS:SetSpellCritChance(statFrame) if spell4 > 0 then GameTooltip:AddLine(format("Holy Shock: %.2f%%", total4)) end elseif class == "WARLOCK" then - if spell1 > 0 then - GameTooltip:AddLine(format("Destruction spells: %.2f%%", total1)) end - if spell2 > 0 then + if spell2 > 0 and spell2 ~= spell1 then GameTooltip:AddLine(format("Searing Pain: %.2f%%", total2)) end - elseif class == "PRIEST" then + elseif class == "PRIEST" then -- dont show specific spells if they have same chance as offensive/healing spells if spell1 > 0 then GameTooltip:AddLine(format("Healing spells: %.2f%%", total1)) end - if spell2 > 0 then + if spell2 > 0 and spell2 ~= spell1 then GameTooltip:AddLine(format("Prayer of Healing: %.2f%%", total2)) end if spell3 > 0 then GameTooltip:AddLine(format("Offensive spells: %.2f%%", total3)) end - if spell4 > 0 then + if spell4 > 0 and spell4 ~= spell3 then GameTooltip:AddLine(format("Smite: %.2f%%", total4)) end - if spell5 > 0 then + if spell5 > 0 and spell5 ~= spell3 then GameTooltip:AddLine(format("Holy Fire: %.2f%%", total5)) end - elseif class == "MAGE" then + elseif class == "MAGE" then -- dont show specific spells if they have same chance as fire spells if spell1 > 0 then GameTooltip:AddLine(format("Arcane spells: %.2f%%", total1)) end if spell2 > 0 then GameTooltip:AddLine(format("Fire spells: %.2f%%", total2)) end - if spell3 > 0 then + if spell3 > 0 and spell3 ~= spell2 then GameTooltip:AddLine(format("Fire Blast: %.2f%%", total3)) end - if spell4 > 0 then + if spell4 > 0 and spell4 ~= spell2 then GameTooltip:AddLine(format("Scorch: %.2f%%", total4)) end - if spell5 > 0 then + if spell5 > 0 and spell5 ~= spell2 then GameTooltip:AddLine(format("Flamestrike: %.2f%%", total5)) end if spell6 > 0 then GameTooltip:AddLine(format("Frozen targets: %.2f%%", total6)) end diff --git a/Localization.lua b/Localization.lua index 971539f..6468eea 100644 --- a/Localization.lua +++ b/Localization.lua @@ -113,6 +113,7 @@ BCS["L"] = { -- warlock ["Increases the critical strike chance of your Destruction spells by (%d+)%%."] = "Increases the critical strike chance of your Destruction spells by (%d+)%%.", ["Increases the critical strike chance of your Searing Pain spell by (%d+)%%."] = "Increases the critical strike chance of your Searing Pain spell by (%d+)%%.", + ["Reduces the chance for enemies to resist your Affliction spells by (%d+)%%."] = "Reduces the chance for enemies to resist your Affliction spells by (%d+)%%.", -- mage ["Increases the critical strike chance of your Arcane Explosion and Arcane Missiles spells by an additional (%d+)%%."] = "Increases the critical strike chance of your Arcane Explosion and Arcane Missiles spells by an additional (%d+)%%.", ["Increases the critical strike chance of your Fire Blast and Scorch spells by (%d+)%%."] = "Increases the critical strike chance of your Fire Blast and Scorch spells by (%d+)%%.", diff --git a/helper.lua b/helper.lua index 0f88441..dcec460 100644 --- a/helper.lua +++ b/helper.lua @@ -351,11 +351,18 @@ function BCS:GetSpellHitRating() end -- Paladin & Shaman -- Precision & Nature's Guidance - _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee weapons and spells by (%d+)%%.") + _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee attacks and spells by (%d+)%%.") if value and rank > 0 then BCScache["talents"].spell_hit = BCScache["talents"].spell_hit + tonumber(value) break end + -- Warlock + -- Suppression + _,_, value = strfind(left:GetText(), L["Reduces the chance for enemies to resist your Affliction spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].spell_hit_shadow = BCScache["talents"].spell_hit_shadow + tonumber(value) + break + end end end end @@ -832,7 +839,7 @@ function BCS:GetSpellCritFromClass(class) BCScache["talents"].mage_fireblast = 0 BCScache["talents"].mage_scorch = 0 BCScache["talents"].mage_flamestrike = 0 - BCScache["talents"].mage_frozen = 0 + BCScache["talents"].mage_shatter = 0 -- scan talents for tab=1, GetNumTalentTabs() do for talent=1, GetNumTalents(tab) do @@ -872,7 +879,7 @@ function BCS:GetSpellCritFromClass(class) -- Shatter _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of all your spells against frozen targets by (%d+)%%."]) if value and rank > 0 then - BCScache["talents"].mage_frozen = BCScache["talents"].mage_frozen + tonumber(value) + BCScache["talents"].mage_shatter = BCScache["talents"].mage_shatter + tonumber(value) break end end @@ -894,7 +901,7 @@ function BCS:GetSpellCritFromClass(class) BCScache["talents"].mage_fireblast, BCScache["talents"].mage_scorch, BCScache["talents"].mage_flamestrike, - BCScache["talents"].mage_frozen + BCScache["talents"].mage_shatter elseif class == "PRIEST" then if BCS.needScanTalents then BCScache["talents"].priest_healing_spells = 0 @@ -969,10 +976,12 @@ function BCS:GetSpellCritFromClass(class) end end local healingSpells, smite, holyFire, prayer + healingSpells = BCScache["talents"].priest_healing_spells + BCScache["gear"].priest_healing_spells smite = BCScache["talents"].priest_smite + BCScache["gear"].priest_smite holyFire = BCScache["talents"].priest_holy_fire + BCScache["gear"].priest_holy_fire prayer = BCScache["talents"].priest_prayer + BCScache["gear"].priest_prayer + return healingSpells, prayer, BCScache["talents"].priest_offensive_spells, smite, holyFire, 0 elseif class == "SHAMAN" then if BCS.needScanTalents then From e58dbf723ddbee044d0c35067ff547e7cda5be42 Mon Sep 17 00:00:00 2001 From: Spit <110714733+Otari98@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:17:37 +0300 Subject: [PATCH 13/39] Update README.md --- README.md | 51 ++++++++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 8e36f63..4764c73 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,20 @@ -BetterCharacterStats - a World of Warcraft (1.12.1) AddOn -=================================================== - -![preview](https://raw.githubusercontent.com/yutsuku/BetterCharacterStats/gh-pages/images/BetterCharacterStats.png) - -Installation: - -Put "BetterCharacterStats" folder into ".../World of Warcraft/Interface/AddOns/". -Create AddOns folder if necessary - -After Installation directory tree should look like the following - - World of Warcraft - `- Interface - `- AddOns - `- BetterCharacterStats - |- README.md - |- BetterCharacterStats.lua - |- BetterCharacterStats.toc - |- BetterCharacterStats.xml - |- helper.lua - `- Localization.lua - -Features: -- Displays character statistics in one place (just like the character tab in Burning Crusade). - -Known Issues: -- May be lacking things related to spell hit/spell crit. - -Thanks to: -- All people who keeps reporting to me that some things are missing or are broken. \ No newline at end of file +# BetterCharacterStats for Turtle WoW +This addon shows your character stats that are not present in default UI.
+This version is designed specifically for TurtleWoW and its custom changes. +## Features + - Base stats: strength, agility, stamina, intellect, spirit, armor + - Melee/Ranged: weapon skill, damage, attack speed, attack power, hit, crit + - Spells: spell power, spell hit, crit, healing power, mana regeneration + - Schools: your spell power for each school of magic + - Defenses: armor, defense skill, dodge, parry, block, avoidance +## Preview +![preview1](https://github.com/user-attachments/assets/d342aed0-812c-40f9-a4d4-9b33eb48caa3) + +## Installation +1. Click Code -> Download ZIP +2. Extract ZIP file into you Interface/AddOnns folder, remove ``-main`` +3. Restart the game +## Feedback +If you find any bugs, inaccuracies, typos or just want to suggest something, open an [issue](https://github.com/Otari98/BetterCharacterStats/issues) on GitHub +## Thanks to original author and all contributors +moh, Bennylava, Lexie, Spit, Pepopo From d9fa8a35c6b0434e28383445d1058fe79a43e2c5 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Mon, 14 Oct 2024 13:18:52 +0300 Subject: [PATCH 14/39] update school spell power tooltip --- BetterCharacterStats.lua | 6 +++++- Localization.lua | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 00ec20c..e19de7a 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -606,7 +606,11 @@ function BCS:SetSpellPower(statFrame, school) text:SetText(output) - frame.tooltip = format(L.SPELL_SCHOOL_TOOLTIP , school) + if fromSchool > 0 then + frame.tooltip = format(L.SPELL_SCHOOL_SECONDARY_TOOLTIP , school, base + fromSchool, base, fromSchool) + else + frame.tooltip = format(L.SPELL_SCHOOL_TOOLTIP , school, base) + end frame.tooltipSubtext = format(L.SPELL_SCHOOL_TOOLTIP_SUB, strlower(school)) else local power, secondaryPower, secondaryName = BCS:GetSpellPower() diff --git a/Localization.lua b/Localization.lua index 6468eea..87d530f 100644 --- a/Localization.lua +++ b/Localization.lua @@ -173,7 +173,8 @@ BCS["L"] = { ["SPELL_POWER_SECONDARY_TOOLTIP"] = [[|cffffffffSpell Power %d (%d|cff20ff20+%d %s|r|cffffffff)|r]], ["SPELL_POWER_SECONDARY_TOOLTIP_SUB"] = [[Increases damage done by spells and effects.]], - ["SPELL_SCHOOL_TOOLTIP"] = [[|cffffffff%s Spell Power|r]], + ["SPELL_SCHOOL_TOOLTIP"] = [[|cffffffff%s Spell Power %s|r]], + ["SPELL_SCHOOL_SECONDARY_TOOLTIP"] = [[|cffffffff%s Spell Power %d (%d|cff20ff20+%d|r|cffffffff)|r]], ["SPELL_SCHOOL_TOOLTIP_SUB"] = [[Increases damage done by %s spells and effects.]], ["SPELL_HEALING_POWER_TOOLTIP"] = [[|cffffffffHealing Power %d|r]], From 9d4578869c82df0ba3f9d12d4eae6412e7baf731 Mon Sep 17 00:00:00 2001 From: Spit <110714733+Otari98@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:30:20 +0300 Subject: [PATCH 15/39] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4764c73..ebcce4e 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ This version is designed specifically for TurtleWoW and its custom changes. ## Installation 1. Click Code -> Download ZIP -2. Extract ZIP file into you Interface/AddOnns folder, remove ``-main`` +2. Extract ZIP file into your Interface/AddOnns folder, remove ``-main`` 3. Restart the game ## Feedback If you find any bugs, inaccuracies, typos or just want to suggest something, open an [issue](https://github.com/Otari98/BetterCharacterStats/issues) on GitHub ## Thanks to original author and all contributors -moh, Bennylava, Lexie, Spit, Pepopo +Moh, Bennylava, Lexie, Spit, Pepopo From 5d5dd2f037ddfafb176370ae77bf40f359d508c2 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 30 Oct 2024 02:06:29 +0300 Subject: [PATCH 16/39] minor fix ranged crit from leader of the pack aura and spell crit from moonkin aura with idol --- BetterCharacterStats.lua | 8 +++--- Localization.lua | 3 +- helper.lua | 60 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index e19de7a..4e79acc 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -641,7 +641,7 @@ function BCS:SetSpellPower(statFrame, school) end) end -function BCS:SetRating(statFrame, ratingType) +function BCS:SetHitRating(statFrame, ratingType) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") @@ -1338,18 +1338,18 @@ function BCS:UpdatePaperdollStats(prefix, index) BCS:SetDamage(stat2) BCS:SetAttackSpeed(stat3) BCS:SetAttackPower(stat4) - BCS:SetRating(stat5, "MELEE") + BCS:SetHitRating(stat5, "MELEE") BCS:SetMeleeCritChance(stat6) elseif (index == "PLAYERSTAT_RANGED_COMBAT") then BCS:SetRangedWeaponSkill(stat1) BCS:SetRangedDamage(stat2) BCS:SetRangedAttackSpeed(stat3) BCS:SetRangedAttackPower(stat4) - BCS:SetRating(stat5, "RANGED") + BCS:SetHitRating(stat5, "RANGED") BCS:SetRangedCritChance(stat6) elseif (index == "PLAYERSTAT_SPELL_COMBAT") then BCS:SetSpellPower(stat1) - BCS:SetRating(stat2, "SPELL") + BCS:SetHitRating(stat2, "SPELL") BCS:SetSpellCritChance(stat3) BCS:SetHealing(stat4) BCS:SetManaRegen(stat5) diff --git a/Localization.lua b/Localization.lua index 87d530f..0f7a7ef 100644 --- a/Localization.lua +++ b/Localization.lua @@ -100,7 +100,8 @@ BCS["L"] = { ["Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%."] = "Melee critical-hit chance reduced by (%d+)%%.\r\nSpell critical-hit chance reduced by (%d+)%%.", ["Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration."] = "Increases critical chance of spells by 10%%, melee and ranged by 5%% and grants 140 attack power. 120 minute duration.", ["Critical strike chance with spells and melee attacks increased by (%d+)%%."] = "Critical strike chance with spells and melee attacks increased by (%d+)%%.", - + ["Increases ranged and melee critical chance by (%d+)%%."] = "Increases ranged and melee critical chance by (%d+)%%.", + ["Equip: Increases the critical chance provided by Leader of the Pack and Moonkin Aura by (%d)%%."] = "Equip: Increases the critical chance provided by Leader of the Pack and Moonkin Aura by (%d)%%.", -- druid ["Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%."] = "Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%.", ["Increases the critical effect chance of your Regrowth spell by (%d+)%%."] = "Increases the critical effect chance of your Regrowth spell by (%d+)%%.", diff --git a/helper.lua b/helper.lua index dcec460..edfc538 100644 --- a/helper.lua +++ b/helper.lua @@ -384,7 +384,7 @@ function BCS:GetSpellHitRating() return hit, hit_fire, hit_frost, hit_arcane, hit_shadow end -function BCS:GetCritChance() -- so easy lol, wish i could say same about other stuff +function BCS:GetCritChance() local crit = 0 --scan spellbook for tab=1, GetNumSpellTabs() do @@ -501,6 +501,29 @@ function BCS:GetRangedCritChance() if critFromAura then BCScache["auras"].ranged_crit = BCScache["auras"].ranged_crit + tonumber(critFromAura) end + --leader of the pack + _, _, critFromAura = BCS:GetPlayerAura(L["Increases ranged and melee critical chance by (%d+)%%."]) + if critFromAura then + BCScache["auras"].ranged_crit = BCScache["auras"].ranged_crit + tonumber(critFromAura) + --check if druid is shapeshifted and have Idol of the Moonfang equipped + for i=1, GetNumPartyMembers() do + local _, partyClass = UnitClass("party"..i) + if partyClass == "DRUID" then + if BCS_Tooltip:SetInventoryItem("party"..i, 18) and UnitCreatureType("party"..i) == "Beast" then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + _, _, critFromAura = strfind(left:GetText(), L["Equip: Increases the critical chance provided by Leader of the Pack and Moonkin Aura by (%d)%%."]) + if critFromAura then + BCScache["auras"].ranged_crit = BCScache["auras"].ranged_crit + tonumber(critFromAura) + break + end + end + end + end + end + end + end end if class == "MAGE" then crit = crit + 3.2 elseif class == "PRIEST" then crit = crit + 3 @@ -511,7 +534,6 @@ function BCS:GetRangedCritChance() end function BCS:GetSpellCritChance() - -- school crit: most likely never local Crit_Set_Bonus = {} local spellCrit = 0; local _, intellect = UnitStat("player", 4) @@ -577,6 +599,40 @@ function BCS:GetSpellCritChance() _, _, critFromAura = BCS:GetPlayerAura("(Moonkin Aura)") if critFromAura then BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + 3 + if BCS:GetPlayerAura("Moonkin Form") and BCS_Tooltip:SetInventoryItem("player", 18) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + _, _, critFromAura = strfind(left:GetText(), L["Equip: Increases the critical chance provided by Leader of the Pack and Moonkin Aura by (%d)%%."]) + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) + end + end + end + else + --check if druid is shapeshifted and have Idol of the Moonfang equipped + for i=1, GetNumPartyMembers() do + local _, partyClass = UnitClass("party"..i) + if partyClass == "DRUID" then + if BCS_Tooltip:SetInventoryItem("party"..i, 18) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + _, _, critFromAura = strfind(left:GetText(), L["Equip: Increases the critical chance provided by Leader of the Pack and Moonkin Aura by (%d)%%."]) + if critFromAura then + for buff = 1, 32 do + if UnitBuff("party"..i, buff) and UnitBuff("party"..i, buff) == "Interface\\Icons\\Spell_Nature_ForceOfNature" then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) + break + end + end + end + end + end + end + end + end + end end _, _, critFromAura = BCS:GetPlayerAura("Power of the Guardian Crit") if critFromAura then From b8ea44dec15210936a752615881e088f25ce3ee3 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Mon, 4 Nov 2024 19:50:17 +0300 Subject: [PATCH 17/39] 1.17.2 update some stuff might be missing, or changed later --- BetterCharacterStats.lua | 13 +++-- Localization.lua | 11 ++-- helper.lua | 117 ++++++++++++++++++++++++++++----------- 3 files changed, 100 insertions(+), 41 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 4e79acc..9192661 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -665,7 +665,7 @@ function BCS:SetHitRating(statFrame, ratingType) frame.tooltip = (L.RANGED_HIT_TOOLTIP) frame.tooltipSubtext = format(L.RANGED_HIT_TOOLTIP_SUB) elseif ratingType == "SPELL" then - local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow = BCS:GetSpellHitRating() + local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow, spell_hit_holy = BCS:GetSpellHitRating() frame.tooltip = format(L.SPELL_HIT_TOOLTIP) text:SetText(spell_hit .. "%") frame.tooltipSubtext = format(L.SPELL_HIT_TOOLTIP_SUB) @@ -690,6 +690,9 @@ function BCS:SetHitRating(statFrame, ratingType) GameTooltip:AddLine(format(L.SPELL_SCHOOL_SHADOW.." spells: %.f%%", spell_hit + spell_hit_shadow)) end end + if spell_hit_holy > 0 then + GameTooltip:AddLine(format(L.SPELL_SCHOOL_HOLY.." and Discipline spells: %.f%%", spell_hit + spell_hit_holy)) + end GameTooltip:Show() end) frame:SetScript("OnLeave", function() @@ -820,13 +823,11 @@ function BCS:SetSpellCritChance(statFrame) GameTooltip:AddLine(format("Regrowth: %.2f%%", total2)) end elseif class == "PALADIN" then if spell1 > 0 then - GameTooltip:AddLine(format("Holy spells: %.2f%%", total1)) end + GameTooltip:AddLine(format("Holy Light: %.2f%%", total1)) end if spell2 > 0 then - GameTooltip:AddLine(format("Holy Light: %.2f%%", total2)) end + GameTooltip:AddLine(format("Flash of Light: %.2f%%", total2)) end if spell3 > 0 then - GameTooltip:AddLine(format("Flash of Light: %.2f%%", total3)) end - if spell4 > 0 then - GameTooltip:AddLine(format("Holy Shock: %.2f%%", total4)) end + GameTooltip:AddLine(format("Holy Shock: %.2f%%", total3)) end elseif class == "WARLOCK" then if spell2 > 0 and spell2 ~= spell1 then GameTooltip:AddLine(format("Searing Pain: %.2f%%", total2)) end diff --git a/Localization.lua b/Localization.lua index 0f7a7ef..96a13aa 100644 --- a/Localization.lua +++ b/Localization.lua @@ -41,7 +41,7 @@ BCS["L"] = { ["^Healing %+(%d+) and %d+ mana per 5 sec."] = "^Healing %+(%d+) and %d+ mana per 5 sec.", ["Equip: Restores (%d+) mana per 5 sec."] = "Equip: Restores (%d+) mana per 5 sec.", - ["+(%d)%% Hit"] = "+(%d)%% Hit", + ["+(%d)%% Ranged Hit"] = "+(%d)%% Ranged Hit", -- Random Bonuses // https://wow.gamepedia.com/index.php?title=SuffixId&oldid=204406 ["^%+(%d+) Damage and Healing Spells"] = "^%+(%d+) Damage and Healing Spells", @@ -106,8 +106,9 @@ BCS["L"] = { ["Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%."] = "Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%.", ["Increases the critical effect chance of your Regrowth spell by (%d+)%%."] = "Increases the critical effect chance of your Regrowth spell by (%d+)%%.", -- paladin - ["Increases the critical effect chance of your Holy spells by (%d+)%%."] = "Increases the critical effect chance of your Holy spells by (%d+)%%.", -- same for priest - ["When activated, gives your next Flash of Light, Holy Light or Holy Shock spell a (%d+)%% critical effect chance."] = "When activated, gives your next Flash of Light, Holy Light or Holy Shock spell a (%d+)%% critical effect chance.", + ["Increases your healing power by (%d+)%% of your Armor."] = "Increases your healing power by (%d+)%% of your Armor.", + ["Increases the critical effect chance of your Holy Light and Flash of Light by (%d+)%%."] = "Increases the critical effect chance of your Holy Light and Flash of Light by (%d+)%%.", + ["Improves your chance to get a critical strike with Holy Shock by (%d+)%%."] = "Improves your chance to get a critical strike with Holy Shock by (%d+)%%.", -- shaman ["Increases the critical strike chance of your Lightning Bolt and Chain Lightning spells by an additional (%d+)%%."] = "Increases the critical strike chance of your Lightning Bolt and Chain Lightning spells by an additional (%d+)%%.", ["Increases the critical effect chance of your healing and lightning spells by (%d+)%%."] = "Increases the critical effect chance of your healing and lightning spells by (%d+)%%.", @@ -124,7 +125,9 @@ BCS["L"] = { ["Increases your spell damage and critical srike chance by (%d+)%%."] = "Increases your spell damage and critical srike chance by (%d+)%%.", ["Increases critical strike chance from Fire damage spells by (%d+)%%."] = "Increases critical strike chance from Fire damage spells by (%d+)%%.", -- priest - ["Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%."] = "Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%.", + ["Reduces the chance for enemies to resist your Holy and Discipline spells by (%d+)%%."] = "Reduces the chance for enemies to resist your Holy and Discipline spells by (%d+)%%.", + ["Increases the critical effect chance of your Holy and Discipline spells by (%d+)%%."] = "Increases the critical effect chance of your Holy and Discipline spells by (%d+)%%.", + ["Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%"] = "Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%", ["^Set: Improves your chance to get a critical strike with Holy spells by (%d)%%."] = "^Set: Improves your chance to get a critical strike with Holy spells by (%d)%%.", ["^Set: Increases your chance of a critical hit with Prayer of Healing by (%d+)%%."] = "^Set: Increases your chance of a critical hit with Prayer of Healing by (%d+)%%.", --defense diff --git a/helper.lua b/helper.lua index edfc538..99d76db 100644 --- a/helper.lua +++ b/helper.lua @@ -48,6 +48,7 @@ BCScache = BCScache or { spell_hit_frost = 0, spell_hit_arcane = 0, spell_hit_shadow = 0, + spell_hit_holy = 0, spell_crit = 0, casting = 0, mp5 = 0, @@ -223,13 +224,20 @@ function BCS:GetHitRating(hitOnly) BCScache["talents"].hit = BCScache["talents"].hit + tonumber(value) break end - -- Paladin & Shaman - -- Precision & Nature's Guidance + -- Paladin + -- Precision _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee attacks and spells by (%d+)%%.") if value and rank > 0 then BCScache["talents"].hit = BCScache["talents"].hit + tonumber(value) break end + -- Shaman + -- Elemental Devastation + _,_, value = strfind(left:GetText(), "Increases your chance to hit with spells and melee attacks by (%d+)%%") + if value and rank > 0 then + BCScache["talents"].hit = BCScache["talents"].hit + tonumber(value) + break + end end end end @@ -252,7 +260,7 @@ function BCS:GetRangedHitRating() for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local _,_, value = strfind(left:GetText(), L["+(%d)%% Hit"]) + local _,_, value = strfind(left:GetText(), L["+(%d)%% Ranged Hit"]) if value then BCScache["gear"].ranged_hit = BCScache["gear"].ranged_hit + tonumber(value) break @@ -272,6 +280,7 @@ function BCS:GetSpellHitRating() local hit_frost = 0 local hit_arcane = 0 local hit_shadow = 0 + local hit_holy = 0 local hit_Set_Bonus = {} if BCS.needScanGear then BCScache["gear"].spell_hit = 0 @@ -313,6 +322,7 @@ function BCS:GetSpellHitRating() BCScache["talents"].spell_hit_frost = 0 BCScache["talents"].spell_hit_arcane = 0 BCScache["talents"].spell_hit_shadow = 0 + BCScache["talents"].spell_hit_holy = 0 -- scan talents for tab=1, GetNumTalentTabs() do for talent=1, GetNumTalents(tab) do @@ -336,6 +346,12 @@ function BCS:GetSpellHitRating() break end -- Priest + -- Piercing Light + _,_, value = strfind(left:GetText(), L["Reduces the chance for enemies to resist your Holy and Discipline spells by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].spell_hit_holy = BCScache["talents"].spell_hit_holy + tonumber(value) + break + end -- Shadow Focus _,_, value = strfind(left:GetText(), L["Reduces your target's chance to resist your Shadow spells by (%d+)%%."]) if value and rank > 0 then @@ -349,13 +365,20 @@ function BCS:GetSpellHitRating() BCScache["talents"].spell_hit = BCScache["talents"].spell_hit + tonumber(value) break end - -- Paladin & Shaman - -- Precision & Nature's Guidance + -- Paladin + -- Precision _,_, value = strfind(left:GetText(), "Increases your chance to hit with melee attacks and spells by (%d+)%%.") if value and rank > 0 then BCScache["talents"].spell_hit = BCScache["talents"].spell_hit + tonumber(value) break end + -- Shaman + -- Elemental Devastation + _,_, value = strfind(left:GetText(), "Increases your chance to hit with spells and melee attacks by (%d+)%%") + if value and rank > 0 then + BCScache["talents"].spell_hit = BCScache["talents"].spell_hit + tonumber(value) + break + end -- Warlock -- Suppression _,_, value = strfind(left:GetText(), L["Reduces the chance for enemies to resist your Affliction spells by (%d+)%%."]) @@ -381,7 +404,8 @@ function BCS:GetSpellHitRating() hit_frost = BCScache["talents"].spell_hit_frost hit_arcane = BCScache["talents"].spell_hit_arcane hit_shadow = BCScache["talents"].spell_hit_shadow - return hit, hit_fire, hit_frost, hit_arcane, hit_shadow + hit_holy = BCScache["talents"].spell_hit_holy + return hit, hit_fire, hit_frost, hit_arcane, hit_shadow, hit_holy end function BCS:GetCritChance() @@ -634,6 +658,10 @@ function BCS:GetSpellCritChance() end end end + _, _, critFromAura = BCS:GetPlayerAura("Inner Focus") + if critFromAura then + BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + 25 + end _, _, critFromAura = BCS:GetPlayerAura("Power of the Guardian Crit") if critFromAura then BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + tonumber(critFromAura) @@ -782,7 +810,6 @@ function BCS:GetSpellCritFromClass(class) if class == "PALADIN" then --scan talents if BCS.needScanTalents or BCS.needScanAuras then - BCScache["talents"].paladin_holy_spells = 0 BCScache["talents"].paladin_holy_light = 0 BCScache["talents"].paladin_flash = 0 BCScache["talents"].paladin_shock = 0 @@ -794,9 +821,16 @@ function BCS:GetSpellCritFromClass(class) if left:GetText() then local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) -- Holy Power - local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy spells by (%d+)%%."]) + local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy Light and Flash of Light by (%d+)%%."]) + if value and rank > 0 then + BCScache["talents"].paladin_holy_light = BCScache["talents"].paladin_holy_light + tonumber(value) + BCScache["talents"].paladin_flash = BCScache["talents"].paladin_flash + tonumber(value) + break + end + -- Divine Favor + _,_, value = strfind(left:GetText(), L["Improves your chance to get a critical strike with Holy Shock by (%d+)%%."]) if value and rank > 0 then - BCScache["talents"].paladin_holy_spells = BCScache["talents"].paladin_holy_spells + tonumber(value) + BCScache["talents"].paladin_shock = BCScache["talents"].paladin_shock + tonumber(value) break end end @@ -804,22 +838,10 @@ function BCS:GetSpellCritFromClass(class) end end end - if BCS.needScanAuras then - BCScache["talents"].paladin_holy_light = 0 - BCScache["talents"].paladin_flash = 0 - BCScache["talents"].paladin_shock = 0 - -- Buffs - -- Divine Favor - if BCS:GetPlayerAura("Divine Favor") then - BCScache["talents"].paladin_holy_light = 100 - BCScache["talents"].paladin_flash = 100 - BCScache["talents"].paladin_shock = 100 - end - end - return BCScache["talents"].paladin_holy_spells, - BCScache["talents"].paladin_holy_light, + + return BCScache["talents"].paladin_holy_light, BCScache["talents"].paladin_flash, - BCScache["talents"].paladin_shock, 0, 0 + BCScache["talents"].paladin_shock, 0, 0, 0 elseif class == "DRUID" then --scan talents if BCS.needScanTalents then @@ -973,8 +995,8 @@ function BCS:GetSpellCritFromClass(class) local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - -- Holy Specialization - local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy spells by (%d+)%%."]) + -- Divinity + local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy and Discipline spells by (%d+)%%."]) if value and rank > 0 then BCScache["talents"].priest_healing_spells = BCScache["talents"].priest_healing_spells + tonumber(value) BCScache["talents"].priest_smite = BCScache["talents"].priest_smite + tonumber(value) @@ -982,7 +1004,7 @@ function BCS:GetSpellCritFromClass(class) break end -- Force of Will - _,_, value = strfind(left:GetText(), L["Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%."]) + _,_, value = strfind(left:GetText(), L["Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%"]) if value and rank > 0 then BCScache["talents"].priest_offensive_spells = BCScache["talents"].priest_offensive_spells + tonumber(value) BCScache["talents"].priest_smite = BCScache["talents"].priest_smite + tonumber(value) @@ -1369,9 +1391,34 @@ function BCS:GetSpellPower(school) end end +local ironClad = nil function BCS:GetHealingPower() local healPower = 0; local healPower_Set_Bonus = {} + --talents + if BCS.needScanTalents then + BCScache["talents"].healing = 0 + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Paladin + -- Ironclad + local _,_, value = strfind(left:GetText(), L["Increases your healing power by (%d+)%% of your Armor."]) + if value and rank > 0 then + local _, effectiveArmor = UnitArmor("player") + BCScache["talents"].healing = BCScache["talents"].healing + floor(((tonumber(value) / 100) * effectiveArmor)) + ironClad = tonumber(value) + break + end + end + end + end + end + end if BCS.needScanGear then BCScache["gear"].healing = 0 --scan gear @@ -1407,7 +1454,11 @@ function BCS:GetHealingPower() if value then BCScache["gear"].healing = BCScache["gear"].healing + 25 end - + _,_, value = strfind(left:GetText(), "Healing %+(%d+)") + if value then + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) + end + _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") if value then SET_NAME = value @@ -1421,8 +1472,12 @@ function BCS:GetHealingPower() end end end + if ironClad ~= nil then + BCScache["talents"].healing = 0 + local _, effectiveArmor = UnitArmor("player") + BCScache["talents"].healing = floor(((ironClad / 100) * effectiveArmor)) + end end - -- buffs local treebonus = nil if BCS.needScanAuras then @@ -1468,7 +1523,7 @@ function BCS:GetHealingPower() end end - healPower = BCScache["gear"].healing + BCScache["auras"].healing + healPower = BCScache["gear"].healing + BCScache["auras"].healing + BCScache["talents"].healing return healPower, treebonus end @@ -1641,7 +1696,7 @@ function BCS:GetManaRegen() local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) + -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) / Shaman (Improved Water Shield) local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) if value and rank > 0 then BCScache["talents"].casting = BCScache["talents"].casting + tonumber(value) From 6369a628cdfeeae8db427f9b0e4e810a7c2c51a6 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Tue, 5 Nov 2024 12:11:34 +0300 Subject: [PATCH 18/39] bug fix fixed ironclad pala talent and inconsistent numbers on tooltip --- BetterCharacterStats.lua | 4 ++-- helper.lua | 13 +++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 9192661..0be61a1 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -923,7 +923,7 @@ function BCS:SetHealing(statFrame) total = total + aura[1] end label:SetText(L.HEAL_POWER_COLON) - text:SetText(format("%.f",total)) + text:SetText(format("%d",total)) if heal ~= 0 then frame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (total), power, heal) else @@ -962,7 +962,7 @@ function BCS:SetManaRegen(statFrame) end local totalRegenWhileCasting = (casting / 100) * base + mp2 - text:SetText(format("%.0f (%.0f)", totalRegen, totalRegenWhileCasting)) + text:SetText(format("%d (%d)", totalRegen, totalRegenWhileCasting)) frame.tooltip = format(L.SPELL_MANA_REGEN_TOOLTIP, totalRegen, totalRegenWhileCasting) frame.tooltipSubtext = format(L.SPELL_MANA_REGEN_TOOLTIP_SUB, base, casting, mp5, mp2) frame:SetScript("OnEnter", function() diff --git a/helper.lua b/helper.lua index 99d76db..3cd0748 100644 --- a/helper.lua +++ b/helper.lua @@ -1409,8 +1409,6 @@ function BCS:GetHealingPower() -- Ironclad local _,_, value = strfind(left:GetText(), L["Increases your healing power by (%d+)%% of your Armor."]) if value and rank > 0 then - local _, effectiveArmor = UnitArmor("player") - BCScache["talents"].healing = BCScache["talents"].healing + floor(((tonumber(value) / 100) * effectiveArmor)) ironClad = tonumber(value) break end @@ -1472,11 +1470,6 @@ function BCS:GetHealingPower() end end end - if ironClad ~= nil then - BCScache["talents"].healing = 0 - local _, effectiveArmor = UnitArmor("player") - BCScache["talents"].healing = floor(((ironClad / 100) * effectiveArmor)) - end end -- buffs local treebonus = nil @@ -1522,7 +1515,11 @@ function BCS:GetHealingPower() BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) end end - + if ironClad ~= nil then + BCScache["talents"].healing = 0 + local _, effectiveArmor = UnitArmor("player") + BCScache["talents"].healing = floor(((ironClad / 100) * effectiveArmor)) + end healPower = BCScache["gear"].healing + BCScache["auras"].healing + BCScache["talents"].healing return healPower, treebonus From 9223b51be14de1691328613384e0af5cd3884201 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 6 Nov 2024 13:19:24 +0300 Subject: [PATCH 19/39] inner fire, ironclad, water shield Changed Ironclad to calculate from gear armor only Added Improved Mana Shield Added Inner Fire Got rid of Brilliance Aura since its no longer a thing --- BetterCharacterStats.lua | 48 +++++----------------- helper.lua | 89 +++++++++++++++++++++++++++------------- 2 files changed, 71 insertions(+), 66 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 0be61a1..7dcc26e 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -3,9 +3,10 @@ BCSConfig = BCSConfig or {} local L, IndexLeft, IndexRight L = BCS.L ---aura bonuses from other players; ---[1] - Tree of Life; [2] - Brilliance -local aura = { .0, .0 } + +-- Tree of Life aura bonus from other players, your own is calculated in GetHealingPower() +local aura = .0 + BCS.PLAYERSTAT_DROPDOWN_OPTIONS = { "PLAYERSTAT_BASE_STATS", "PLAYERSTAT_MELEE_COMBAT", @@ -101,18 +102,8 @@ function BCS:OnEvent() amount = tonumber(amount) if type =="TREE" then --BCS:Print("got tree response amount="..amount) - if amount >= aura[1] then - aura[1] = amount - if BCS.PaperDollFrame:IsVisible() then - BCS:UpdateStats() - else - BCS.needUpdate = true - end - end - elseif type == "BRILLIANCE" then - --BCS:Print("got mage response amount="..amount) - if amount >= aura[2] then - aura[2] = amount + if amount >= aura then + aura = amount if BCS.PaperDollFrame:IsVisible() then BCS:UpdateStats() else @@ -125,10 +116,7 @@ function BCS:OnEvent() elseif event == "PLAYER_AURAS_CHANGED" then BCS.needScanAuras = true if not BCS:GetPlayerAura("Tree of Life Aura") then - aura[1] = 0 - end - if not BCS:GetPlayerAura("Brilliance Aura") then - aura[2] = 0 + aura = 0 end if BCS.PaperDollFrame:IsVisible() then BCS:UpdateStats() @@ -184,24 +172,15 @@ sender:SetScript("OnEvent", function() ChatThrottleLib:SendAddonMessage("BULK","bcs", "TREE"..","..player, "PARTY") --BCS:Print("sent tree request") end - if BCS:GetPlayerAura("Brilliance Aura") then - ChatThrottleLib:SendAddonMessage("BULK","bcs", "BRILLIANCE"..","..player, "PARTY") - --BCS:Print("sent mage request") - end end if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then local type, name, amount = hcstrsplit(",", arg2) if name ~= player then local _, treebonus = BCS:GetHealingPower() - local _, _, _, brilliance = BCS:GetManaRegen() if not amount and type == "TREE" and treebonus then ChatThrottleLib:SendAddonMessage("BULK","bcs", "TREE"..","..player..","..treebonus, "PARTY") --BCS:Print("sent tree response, amount="..treebonus) end - if not amount and type == "BRILLIANCE" and brilliance then - ChatThrottleLib:SendAddonMessage("BULK","bcs", "BRILLIANCE"..","..player..","..brilliance, "PARTY") - --BCS:Print("sent mage response, amount="..brilliance) - end end end end @@ -917,10 +896,10 @@ function BCS:SetHealing(statFrame) local heal, treebonus = BCS:GetHealingPower() power = power - dmg local total = power + heal - if treebonus and aura[1] <= treebonus then + if treebonus and aura <= treebonus then total = total + treebonus - elseif (not treebonus and aura[1] > 0) or (treebonus and aura[1] > treebonus) then - total = total + aura[1] + elseif (not treebonus and aura > 0) or (treebonus and aura > treebonus) then + total = total + aura end label:SetText(L.HEAL_POWER_COLON) text:SetText(format("%d",total)) @@ -952,14 +931,9 @@ function BCS:SetManaRegen(statFrame) text:SetText(NOT_APPLICABLE) frame.tooltip = nil else - local base, casting, mp5, brilliance = BCS:GetManaRegen() + local base, casting, mp5 = BCS:GetManaRegen() local mp2 = mp5 * 0.4 local totalRegen = base + mp2 - if brilliance and aura[2] <= brilliance then - totalRegen = totalRegen + brilliance - elseif (not brilliance and aura[2] > 0) or (brilliance and aura[2] > brilliance) then - totalRegen = totalRegen + aura[2] - end local totalRegenWhileCasting = (casting / 100) * base + mp2 text:SetText(format("%d (%d)", totalRegen, totalRegenWhileCasting)) diff --git a/helper.lua b/helper.lua index 3cd0748..494f243 100644 --- a/helper.lua +++ b/helper.lua @@ -1120,6 +1120,7 @@ function BCS:GetSpellCritFromClass(class) end end +local impInnerFire = nil function BCS:GetSpellPower(school) if school then local spellPower = 0; @@ -1317,6 +1318,14 @@ function BCS:GetSpellPower(school) BCScache["talents"].damage_and_healing = BCScache["talents"].damage_and_healing + floor(((tonumber(value) / 100) * spirit)) break end + -- Improved Inner Fire + _,_, value = strfind(left:GetText(), "Increases the effects of your Inner Fire spell by (%d+)%%.") + if value and rank > 0 then + impInnerFire = tonumber(value) + break + else + impInnerFire = nil + end end end end @@ -1355,6 +1364,16 @@ function BCS:GetSpellPower(school) BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end + --Inner Fire + _, _, spellPowerFromAura = BCS:GetPlayerAura("Increased damage done by magical spells and effects by (%d+).") + if spellPowerFromAura then + spellPowerFromAura = tonumber(spellPowerFromAura) + if impInnerFire then + spellPowerFromAura = floor((spellPowerFromAura * (impInnerFire/100)) + (spellPowerFromAura)) + end + BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + spellPowerFromAura + BCScache["auras"].only_damage = BCScache["auras"].only_damage + spellPowerFromAura + end end local secondaryPower = 0 local secondaryPowerName = "" @@ -1411,6 +1430,8 @@ function BCS:GetHealingPower() if value and rank > 0 then ironClad = tonumber(value) break + else + ironClad = nil end end end @@ -1517,8 +1538,10 @@ function BCS:GetHealingPower() end if ironClad ~= nil then BCScache["talents"].healing = 0 - local _, effectiveArmor = UnitArmor("player") - BCScache["talents"].healing = floor(((ironClad / 100) * effectiveArmor)) + local base = UnitArmor("player") + local _, agility = UnitStat("player", 2) + local armorFromGear = base - (agility * 2) + BCScache["talents"].healing = floor(((ironClad / 100) * armorFromGear)) end healPower = BCScache["gear"].healing + BCScache["auras"].healing + BCScache["talents"].healing @@ -1549,11 +1572,38 @@ local function GetRegenMPPerSpirit() return addvalue end +local waterShield = nil function BCS:GetManaRegen() local base = GetRegenMPPerSpirit() local casting = 0 local mp5 = 0 local mp5_Set_Bonus = {} + + -- scan talents + if BCS.needScanTalents then + BCScache["talents"].casting = 0 + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) / Shaman (Improved Water Shield) + local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) + if value and rank > 0 then + BCScache["talents"].casting = BCScache["talents"].casting + tonumber(value) + waterShield = rank + break + else + waterShield = nil + end + end + end + end + end + end + if BCS.needScanGear then BCScache["gear"].mp5 = 0 BCScache["gear"].casting = 0 @@ -1678,44 +1728,25 @@ function BCS:GetManaRegen() if castingFromAura then BCScache["auras"].casting = BCScache["auras"].casting + tonumber(castingFromAura) end - end - - mp5 = BCScache["auras"].mp5 + BCScache["gear"].mp5 - - -- scan talents - local brilliance = nil - if BCS.needScanTalents then - BCScache["talents"].casting = 0 - for tab=1, GetNumTalentTabs() do - for talent=1, GetNumTalents(tab) do - BCS_Tooltip:SetTalent(tab, talent) - for line=1, BCS_Tooltip:NumLines() do - local left = getglobal(BCS_Prefix .. "TextLeft" .. line) - if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) - -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) / Shaman (Improved Water Shield) - local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) - if value and rank > 0 then - BCScache["talents"].casting = BCScache["talents"].casting + tonumber(value) - break - end - -- Brilliance Aura (own) - if strfind(left:GetText(), "Brilliance Aura") and rank > 0 and BCS:GetPlayerAura("Brilliance Aura") then - brilliance = (base + (mp5 * 0.4)) * 0.15 - end - end + --Improved Water Shield + if waterShield ~= nil then + for i = 1, 32 do + local icon, stacks = UnitBuff("player", i) + if icon and stacks and icon == "Interface\\Icons\\Ability_Shaman_WaterShield" then + BCScache["auras"].casting = BCScache["auras"].casting + (tonumber(stacks) * waterShield) end end end end casting = BCScache["auras"].casting + BCScache["talents"].casting + BCScache["gear"].casting + mp5 = BCScache["auras"].mp5 + BCScache["gear"].mp5 if casting > 100 then casting = 100 end - return base, casting, mp5, brilliance + return base, casting, mp5 end --Weapon Skill code adapted from https://github.com/pepopo978/BetterCharacterStats From 020221c34bad5a2edcae93ccb74d3eaf93289179 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 6 Nov 2024 13:59:55 +0300 Subject: [PATCH 20/39] undo mistake --- helper.lua | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/helper.lua b/helper.lua index 494f243..2e4eb73 100644 --- a/helper.lua +++ b/helper.lua @@ -1301,6 +1301,7 @@ function BCS:GetSpellPower(school) end if BCS.needScanTalents then + impInnerFire = nil BCScache["talents"].damage_and_healing = 0 -- scan talents for tab=1, GetNumTalentTabs() do @@ -1323,8 +1324,6 @@ function BCS:GetSpellPower(school) if value and rank > 0 then impInnerFire = tonumber(value) break - else - impInnerFire = nil end end end @@ -1416,6 +1415,7 @@ function BCS:GetHealingPower() local healPower_Set_Bonus = {} --talents if BCS.needScanTalents then + ironClad = nil BCScache["talents"].healing = 0 for tab=1, GetNumTalentTabs() do for talent=1, GetNumTalents(tab) do @@ -1430,8 +1430,6 @@ function BCS:GetHealingPower() if value and rank > 0 then ironClad = tonumber(value) break - else - ironClad = nil end end end @@ -1581,6 +1579,7 @@ function BCS:GetManaRegen() -- scan talents if BCS.needScanTalents then + waterShield = nil BCScache["talents"].casting = 0 for tab=1, GetNumTalentTabs() do for talent=1, GetNumTalents(tab) do @@ -1595,8 +1594,6 @@ function BCS:GetManaRegen() BCScache["talents"].casting = BCScache["talents"].casting + tonumber(value) waterShield = rank break - else - waterShield = nil end end end From 72129a1d656316f6933597eb77f79b7ff8ea41a7 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 6 Nov 2024 14:11:19 +0300 Subject: [PATCH 21/39] inner focus --- helper.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper.lua b/helper.lua index 2e4eb73..c80657d 100644 --- a/helper.lua +++ b/helper.lua @@ -658,7 +658,7 @@ function BCS:GetSpellCritChance() end end end - _, _, critFromAura = BCS:GetPlayerAura("Inner Focus") + critFromAura = BCS:GetPlayerAura("Inner Focus") if critFromAura then BCScache["auras"].spell_crit = BCScache["auras"].spell_crit + 25 end From c4b70071fa991402e72e7b5c5b50a6709da531c0 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Fri, 8 Nov 2024 16:36:46 +0300 Subject: [PATCH 22/39] block value + some other stuff added block value on block tooltip added ranged crit only items added spell damage enchants --- BetterCharacterStats.lua | 6 ++- helper.lua | 95 +++++++++++++++++++++++++++++++++++----- 2 files changed, 89 insertions(+), 12 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 7dcc26e..581c779 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -997,9 +997,10 @@ function BCS:SetBlock(statFrame) local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + local blockChance = GetBlockChance() label:SetText(L.BLOCK_COLON) - text:SetText(format("%.2f%%", GetBlockChance())) + text:SetText(format("%.2f%%", blockChance )) frame.tooltip = format(L.PLAYER_BLOCK_TOOLTIP) frame.tooltipSubtext = format(L.PLAYER_BLOCK_TOOLTIP_SUB) @@ -1007,6 +1008,9 @@ function BCS:SetBlock(statFrame) GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + if blockChance > 0 then + GameTooltip:AddLine("Block Value: "..BCS:GetBlockValue()) + end GameTooltip:Show() end) frame:SetScript("OnLeave", function() diff --git a/helper.lua b/helper.lua index c80657d..6d7bb58 100644 --- a/helper.lua +++ b/helper.lua @@ -492,6 +492,10 @@ function BCS:GetRangedCritChance() if value then BCScache["gear"].ranged_crit = BCScache["gear"].ranged_crit + tonumber(value) end + _,_, value = strfind(left:GetText(), "Equip: Improves your chance to get a critical strike with missile weapons by (%d)%%.") + if value then + BCScache["gear"].ranged_crit = BCScache["gear"].ranged_crit + tonumber(value) + end _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") if value then @@ -1142,17 +1146,13 @@ function BCS:GetSpellPower(school) if value then spellPower = spellPower + tonumber(value) end - if L[school.." Damage %+(%d+)"] then - _,_, value = strfind(left:GetText(), L[school.." Damage %+(%d+)"]) - if value then - spellPower = spellPower + tonumber(value) - end + _,_, value = strfind(left:GetText(), school.." Damage %+(%d+)") + if value then + spellPower = spellPower + tonumber(value) end - if L["^%+(%d+) "..school.." Spell Damage"] then - _,_, value = strfind(left:GetText(), L["^%+(%d+) "..school.." Spell Damage"]) - if value then - spellPower = spellPower + tonumber(value) - end + _,_, value = strfind(left:GetText(), "^%+(%d+) "..school.." Spell Damage") + if value then + spellPower = spellPower + tonumber(value) end end end @@ -1270,7 +1270,11 @@ function BCS:GetSpellPower(school) if value then BCScache["gear"].nature = BCScache["gear"].nature + tonumber(value) end - + _,_, value = strfind(left:GetText(), "Nature Damage %+(%d+)") + if value then + BCScache["gear"].nature = BCScache["gear"].nature + tonumber(value) + end + _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Shadow spells and effects by up to (%d+)."]) if value then BCScache["gear"].shadow = BCScache["gear"].shadow + tonumber(value) @@ -1838,3 +1842,72 @@ function BCS:GetRangedWeaponSkill() BCScache["skills"].ranged = BCS:GetWeaponSkillForWeaponType(itemType) return BCScache["skills"].ranged end + +--https://us.forums.blizzard.com/en/wow/t/block-value-formula/283718/18 +function BCS:GetBlockValue() + local blockValue = 0 + local _, strength = UnitStat("player", 1) + local mod = 0 + -- scan gear + for slot=1, 19 do + if BCS_Tooltip:SetInventoryItem('player', slot) then + local _, _, eqItemLink = strfind(GetInventoryItemLink('player', slot), "(item:%d+:%d+:%d+:%d+)") + if eqItemLink then BCS_Tooltip:ClearLines() BCS_Tooltip:SetHyperlink(eqItemLink) end + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local _,_, value = strfind(left:GetText(), "(%d+) Block") + if value then + blockValue = blockValue + tonumber(value) + end + _,_, value = strfind(left:GetText(), "Equip: Increases the block value of your shield by (%d+).") + if value then + blockValue = blockValue + tonumber(value) + end + _,_, value = strfind(left:GetText(), "Block Value %+(%d+)") + if value then + blockValue = blockValue + tonumber(value) + end + end + end + end + end + -- scan talents + for tab=1, GetNumTalentTabs() do + for talent=1, GetNumTalents(tab) do + BCS_Tooltip:SetTalent(tab, talent) + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + --warrior/paladin + local _,_, value = strfind(left:GetText(), "amount of damage absorbed by your shield by (%d+)%%") + if value and rank > 0 then + mod = mod + tonumber(value) + break + end + --shaman + _,_, value = strfind(left:GetText(), "increases the amount blocked by (%d+)%%") + if value and rank > 0 then + mod = mod + tonumber(value) + break + end + end + end + end + end + -- buffs + --Glyph of Deflection + local _, _, value = BCS:GetPlayerAura("Block value increased by (%d+).") + if value then + blockValue = blockValue + tonumber(value) + end + + mod = mod/100 + blockValue = blockValue + (strength/20 - 1) + blockValue = floor(blockValue + blockValue * mod) + + if blockValue < 0 then blockValue = 0 end + + return blockValue +end \ No newline at end of file From 9f561c6c94f1184132d2ecdc407aab74bc38f18b Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sat, 9 Nov 2024 03:07:07 +0300 Subject: [PATCH 23/39] mana oils/ wizard oils --- helper.lua | 107 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 23 deletions(-) diff --git a/helper.lua b/helper.lua index 6d7bb58..75a260d 100644 --- a/helper.lua +++ b/helper.lua @@ -20,8 +20,7 @@ local function tContains(table, item) end return nil end ---cache; ---[1] - gear; [2] - talents; [3] - buffs + BCScache = BCScache or { ["gear"] = { damage_and_healing = 0, @@ -58,7 +57,7 @@ BCScache = BCScache or { }, ["auras"] = { damage_and_healing = 0, - only_damage = 0, -- +dmg to all schools, comes from buffs only currently, needed to calculate healing + only_damage = 0, -- +dmg to all schools, needed to calculate healing arcane = 0, fire = 0, frost = 0, @@ -615,6 +614,17 @@ function BCS:GetSpellCritChance() end end end + if BCS_Tooltip:SetInventoryItem("player", 16) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local found = strfind(left:GetText(), "Brilliant Wizard Oil") + if found then + BCScache["gear"].spell_crit = BCScache["gear"].spell_crit + 1 + end + end + end + end end if BCS.needScanAuras then @@ -1182,6 +1192,7 @@ function BCS:GetSpellPower(school) local SpellPower_Set_Bonus = {} if BCS.needScanGear then BCScache["gear"].damage_and_healing = 0 + BCScache["gear"].only_damage = 0 BCScache["gear"].arcane = 0 BCScache["gear"].fire = 0 BCScache["gear"].frost = 0 @@ -1208,6 +1219,7 @@ function BCS:GetSpellPower(school) _,_, value = strfind(left:GetText(), L["Spell Damage %+(%d+)"]) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) end _,_, value = strfind(left:GetText(), L["^%+(%d+) Spell Damage and Healing"]) if value then @@ -1302,6 +1314,38 @@ function BCS:GetSpellPower(school) end end end + -- SetHyperLink doesnt show temporary enhancements, have to use SetInventoryItem + if BCS_Tooltip:SetInventoryItem("player", 16) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local found = strfind(left:GetText(), "Brilliant Wizard Oil") + if found then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 36 + BCScache["gear"].only_damage = BCScache["gear"].only_damage + 36 + break + end + found = strfind(left:GetText(), "Lesser Wizard Oil") + if found then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 16 + BCScache["gear"].only_damage = BCScache["gear"].only_damage + 16 + break + end + found = strfind(left:GetText(), "Minor Wizard Oil") + if found then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 8 + BCScache["gear"].only_damage = BCScache["gear"].only_damage + 8 + break + end + found = strfind(left:GetText(), "Wizard Oil") + if found then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 24 + BCScache["gear"].only_damage = BCScache["gear"].only_damage + 24 + break + end + end + end + end end if BCS.needScanTalents then @@ -1347,7 +1391,6 @@ function BCS:GetSpellPower(school) _, _, spellPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") if spellPowerFromAura then BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) - BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end _, _, spellPowerFromAura = BCS:GetPlayerAura("Magical damage dealt by spells and abilities is increased by up to (%d+)") @@ -1407,7 +1450,7 @@ function BCS:GetSpellPower(school) end spellPower = BCScache["gear"].damage_and_healing + BCScache["talents"].damage_and_healing + BCScache["auras"].damage_and_healing - damagePower = BCScache["auras"].only_damage + damagePower = BCScache["auras"].only_damage + BCScache["gear"].only_damage return spellPower, secondaryPower, secondaryPowerName, damagePower end @@ -1455,9 +1498,10 @@ function BCS:GetHealingPower() if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end - _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to 120 and your healing by up to (300).") + -- Atiesh (druid/priest) + _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to %d+ and your healing by up to (%d+).") if value then - BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) - 120 + BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end _,_, value = strfind(left:GetText(), L["Healing Spells %+(%d+)"]) if value then @@ -1471,10 +1515,7 @@ function BCS:GetHealingPower() if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end - _,_, value = strfind(left:GetText(), "^Brilliant Mana Oil %((%d+) min%)") - if value then - BCScache["gear"].healing = BCScache["gear"].healing + 25 - end + -- Jewelcrafting _,_, value = strfind(left:GetText(), "Healing %+(%d+)") if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) @@ -1493,6 +1534,18 @@ function BCS:GetHealingPower() end end end + -- SetHyperLink doesnt show temporary enhancements, have to use SetInventoryItem + if BCS_Tooltip:SetInventoryItem("player", 16) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local found = strfind(left:GetText(), "Brilliant Mana Oil") + if found then + BCScache["gear"].healing = BCScache["gear"].healing + 25 + end + end + end + end end -- buffs local treebonus = nil @@ -1633,18 +1686,6 @@ function BCS:GetManaRegen() if value then BCScache["gear"].mp5 = BCScache["gear"].mp5 + tonumber(value) end - _,_, value = strfind(left:GetText(), "^Brilliant Mana Oil %((%d+) min%)") - if value then - BCScache["gear"].mp5 = BCScache["gear"].mp5 + 12 - end - _,_, value = strfind(left:GetText(), "^Lesser Mana Oil %((%d+) min%)") - if value then - BCScache["gear"].mp5 = BCScache["gear"].mp5 + 8 - end - _,_, value = strfind(left:GetText(), "^Minor Mana Oil %((%d+) min%)") - if value then - BCScache["gear"].mp5 = BCScache["gear"].mp5 + 4 - end _,_, value = strfind(left:GetText(), "^Equip: Allows (%d+)%% of your Mana regeneration to continue while casting.") if value then BCScache["gear"].casting = BCScache["gear"].casting + tonumber(value) @@ -1668,6 +1709,26 @@ function BCS:GetManaRegen() end end end + -- SetHyperLink doesnt show temporary enhancements, have to use SetInventoryItem + if BCS_Tooltip:SetInventoryItem("player", 16) then + for line=1, BCS_Tooltip:NumLines() do + local left = getglobal(BCS_Prefix .. "TextLeft" .. line) + if left:GetText() then + local found = strfind(left:GetText(), "Brilliant Mana Oil") + if found then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + 12 + end + found = strfind(left:GetText(), "Lesser Mana Oil") + if found then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + 8 + end + found = strfind(left:GetText(), "Minor Mana Oil") + if found then + BCScache["gear"].mp5 = BCScache["gear"].mp5 + 4 + end + end + end + end end -- buffs From 3db97863afa70a112f04a0b7502b66cf9b37b99b Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sat, 9 Nov 2024 13:13:57 +0300 Subject: [PATCH 24/39] temporary fix for ranged crit had to disable due to a bug --- BetterCharacterStats.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 581c779..9f902b7 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -866,12 +866,12 @@ function BCS:SetRangedCritChance(statFrame) local skill = BCS:GetRangedWeaponSkill() local level = UnitLevel("player") -- apply skill difference modifier - local skillDiff = skill - (level*5) + --[[local skillDiff = skill - (level*5) if (skill >= (level*5)) then crit = crit + (skillDiff * 0.04) else crit = crit + (skillDiff * 0.2) - end + end]] if crit < 0 then crit = 0 end text:SetText(format("%.2f%%", crit)) statFrame.tooltip = (L.RANGED_CRIT_TOOLTIP) From e12ebd8abfc37a5d82aba9376c87ce9d6637c371 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 13 Nov 2024 17:13:05 +0300 Subject: [PATCH 25/39] Update helper.lua +12 healing fix --- helper.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper.lua b/helper.lua index 75a260d..9fb204f 100644 --- a/helper.lua +++ b/helper.lua @@ -1219,7 +1219,7 @@ function BCS:GetSpellPower(school) _,_, value = strfind(left:GetText(), L["Spell Damage %+(%d+)"]) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) - BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) + --BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) end _,_, value = strfind(left:GetText(), L["^%+(%d+) Spell Damage and Healing"]) if value then From 87aad90e2c77a4217423ce7cc21aff79393b4dad Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sat, 16 Nov 2024 18:44:43 +0300 Subject: [PATCH 26/39] spell power/healing increased readability --- BetterCharacterStats.lua | 26 ++++++++++------- helper.lua | 63 ++++++++++++++++++++++++---------------- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 9f902b7..0a2b11a 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -592,20 +592,21 @@ function BCS:SetSpellPower(statFrame, school) end frame.tooltipSubtext = format(L.SPELL_SCHOOL_TOOLTIP_SUB, strlower(school)) else - local power, secondaryPower, secondaryName = BCS:GetSpellPower() + local damageAndHealing, secondaryPower, secondaryName, damageOnly = BCS:GetSpellPower() + local total = damageAndHealing + damageOnly label:SetText(L.SPELL_POWER_COLON) if secondaryPower > 0 then - text:SetText(colorPos..power + secondaryPower) + text:SetText(colorPos..total + secondaryPower) else - text:SetText(power + secondaryPower) + text:SetText(total + secondaryPower) end if secondaryPower ~= 0 then - frame.tooltip = format(L.SPELL_POWER_SECONDARY_TOOLTIP, (power + secondaryPower), power, secondaryPower, secondaryName) + frame.tooltip = format(L.SPELL_POWER_SECONDARY_TOOLTIP, (total + secondaryPower), total, secondaryPower, secondaryName) frame.tooltipSubtext = format(L.SPELL_POWER_SECONDARY_TOOLTIP_SUB) else - frame.tooltip = format(L.SPELL_POWER_TOOLTIP, power) + frame.tooltip = format(L.SPELL_POWER_TOOLTIP, total) frame.tooltipSubtext = format(L.SPELL_POWER_TOOLTIP_SUB) end end @@ -892,22 +893,25 @@ function BCS:SetHealing(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - local power, _, _, dmg = BCS:GetSpellPower() - local heal, treebonus = BCS:GetHealingPower() - power = power - dmg - local total = power + heal + local damageAndHealing = BCS:GetSpellPower() + local healingOnly, treebonus = BCS:GetHealingPower() + local total = damageAndHealing + healingOnly + if treebonus and aura <= treebonus then total = total + treebonus elseif (not treebonus and aura > 0) or (treebonus and aura > treebonus) then total = total + aura end + label:SetText(L.HEAL_POWER_COLON) text:SetText(format("%d",total)) - if heal ~= 0 then - frame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (total), power, heal) + + if healingOnly ~= 0 then + frame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (total), damageAndHealing, healingOnly) else frame.tooltip = format(L.SPELL_HEALING_POWER_TOOLTIP, (total)) end + frame.tooltipSubtext = format(L.SPELL_HEALING_POWER_TOOLTIP_SUB) frame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_RIGHT") diff --git a/helper.lua b/helper.lua index 9fb204f..53ed445 100644 --- a/helper.lua +++ b/helper.lua @@ -1187,8 +1187,8 @@ function BCS:GetSpellPower(school) return spellPower else - local spellPower = 0 - local damagePower = 0 + local damageAndHealing = 0 + local damageOnly = 0 local SpellPower_Set_Bonus = {} if BCS.needScanGear then BCScache["gear"].damage_and_healing = 0 @@ -1208,23 +1208,32 @@ function BCS:GetSpellPower(school) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then + -- generic bonus on most gear local _,_, value = strfind(left:GetText(), L["Equip: Increases damage and healing done by magical spells and effects by up to (%d+)."]) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) end - _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to (%d+)") + -- Atiesh (druid/priest) + _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to (%d+) and your healing by up to %d+.") if value then - BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) end - _,_, value = strfind(left:GetText(), L["Spell Damage %+(%d+)"]) + -- Arcanum of Focus (Head/Legs enchant) + _,_, value = strfind(left:GetText(), "Healing and Spell Damage %+(%d+)") if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) - --BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) end + -- Zandalar Signet of Mojo (Shoulder enchant) _,_, value = strfind(left:GetText(), L["^%+(%d+) Spell Damage and Healing"]) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) end + -- Power of the Scourge (Shoulder enchant) + _,_, value = strfind(left:GetText(), "Spell Damage %+(%d+) and %+%d+%% Spell Critical Strike") + if value then + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) + end + -- Enchanted Armor Kit (Leatherworking) _,_, value = strfind(left:GetText(), L["^%+(%d+) Damage and Healing Spells"]) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) @@ -1321,25 +1330,21 @@ function BCS:GetSpellPower(school) if left:GetText() then local found = strfind(left:GetText(), "Brilliant Wizard Oil") if found then - BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 36 BCScache["gear"].only_damage = BCScache["gear"].only_damage + 36 break end found = strfind(left:GetText(), "Lesser Wizard Oil") if found then - BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 16 BCScache["gear"].only_damage = BCScache["gear"].only_damage + 16 break end found = strfind(left:GetText(), "Minor Wizard Oil") if found then - BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 8 BCScache["gear"].only_damage = BCScache["gear"].only_damage + 8 break end found = strfind(left:GetText(), "Wizard Oil") if found then - BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 24 BCScache["gear"].only_damage = BCScache["gear"].only_damage + 24 break end @@ -1384,30 +1389,23 @@ function BCS:GetSpellPower(school) -- buffs local _, _, spellPowerFromAura = BCS:GetPlayerAura(L["Magical damage dealt is increased by up to (%d+)."]) if spellPowerFromAura then - BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end - _, _, spellPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") if spellPowerFromAura then BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) end - _, _, spellPowerFromAura = BCS:GetPlayerAura("Magical damage dealt by spells and abilities is increased by up to (%d+)") if spellPowerFromAura then - BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end - _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell damage is increased by up to (%d+)") if spellPowerFromAura then - BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end - --turtle wow spell power food + -- Danonzo's Tel'Abim Delight _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell Damage increased by (%d+)") if spellPowerFromAura then - BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end --Inner Fire @@ -1417,7 +1415,6 @@ function BCS:GetSpellPower(school) if impInnerFire then spellPowerFromAura = floor((spellPowerFromAura * (impInnerFire/100)) + (spellPowerFromAura)) end - BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + spellPowerFromAura BCScache["auras"].only_damage = BCScache["auras"].only_damage + spellPowerFromAura end end @@ -1449,14 +1446,15 @@ function BCS:GetSpellPower(school) secondaryPowerName = L.SPELL_SCHOOL_SHADOW end - spellPower = BCScache["gear"].damage_and_healing + BCScache["talents"].damage_and_healing + BCScache["auras"].damage_and_healing - damagePower = BCScache["auras"].only_damage + BCScache["gear"].only_damage + damageAndHealing = BCScache["gear"].damage_and_healing + BCScache["talents"].damage_and_healing + BCScache["auras"].damage_and_healing + damageOnly = BCScache["auras"].only_damage + BCScache["gear"].only_damage - return spellPower, secondaryPower, secondaryPowerName, damagePower + return damageAndHealing, secondaryPower, secondaryPowerName, damageOnly end end local ironClad = nil +--this is stuff that gives ONLY healing, we count stuff that gives both damage and healing in GetSpellPower function BCS:GetHealingPower() local healPower = 0; local healPower_Set_Bonus = {} @@ -1503,23 +1501,29 @@ function BCS:GetHealingPower() if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end + -- Enchant Weapon/Gloves/Bracers - Healing Power _,_, value = strfind(left:GetText(), L["Healing Spells %+(%d+)"]) if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end + -- Resilience of the Scourge (Shoulder enchant) _,_, value = strfind(left:GetText(), L["^Healing %+(%d+) and %d+ mana per 5 sec."]) if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end + -- Zandalar Signet of Serenity (Shoulder enchant) _,_, value = strfind(left:GetText(), L["^%+(%d+) Healing Spells"]) if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end - -- Jewelcrafting + -- Beautiful Diamond Gemstone (Jewelcrafting) _,_, value = strfind(left:GetText(), "Healing %+(%d+)") if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end + -- Enchanted Armor Kit (Leatherwotking) + -- Arcanum of Focus (Head/Legs enchant) + -- already included in GetSpellPower _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") if value then @@ -1581,10 +1585,14 @@ function BCS:GetHealingPower() if healPowerFromAura then BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) end - _, _, healPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") + + -- ? + -- already included in GetSpellPower + --[[_, _, healPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") if healPowerFromAura then BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) - end + end]] + --Dreamshard Elixir _, _, healPowerFromAura = BCS:GetPlayerAura("Healing done is increased by up to (%d+)") if healPowerFromAura then @@ -1790,6 +1798,11 @@ function BCS:GetManaRegen() if castingFromAura then BCScache["auras"].casting = BCScache["auras"].casting + tonumber(castingFromAura) end + --Sylvan Blessing + _, _, castingFromAura = BCS:GetPlayerAura("Allows (%d+)%% of mana regeneration while casting.") + if castingFromAura then + BCScache["auras"].casting = BCScache["auras"].casting + tonumber(castingFromAura) + end --Improved Water Shield if waterShield ~= nil then for i = 1, 32 do From e1df99e57f4ffc850916cfb2772418b5aad9d481 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 20 Nov 2024 00:20:29 +0300 Subject: [PATCH 27/39] enhancing totems support --- helper.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/helper.lua b/helper.lua index 53ed445..1ae0494 100644 --- a/helper.lua +++ b/helper.lua @@ -1961,11 +1961,18 @@ function BCS:GetBlockValue() break end --shaman + --shield specialization _,_, value = strfind(left:GetText(), "increases the amount blocked by (%d+)%%") if value and rank > 0 then mod = mod + tonumber(value) break end + --enhancing totems + _,_, value = strfind(left:GetText(), "increases block amount by (%d+)%%") + if value and rank > 0 then + mod = mod + tonumber(value) + break + end end end end From c9b0d739474961bbe7b342152878f5728838831c Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 20 Nov 2024 03:30:09 +0300 Subject: [PATCH 28/39] priest crit fix --- BetterCharacterStats.lua | 92 +++++++++++++++++++++++++++------------- helper.lua | 33 +++++--------- 2 files changed, 72 insertions(+), 53 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 0a2b11a..7fb7bb8 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -783,10 +783,10 @@ function BCS:SetSpellCritChance(statFrame) text:SetText(format("%.2f%%", generic)) if class == "WARLOCK" and spell1 > 0 then -- warlock spells that can crit are all destruction so just add this to generic text:SetText(format("%.2f%%", generic + spell1)) - elseif class == "PRIEST" and spell3 > 0 and spell1 > 0 then -- if priest have both talents add lowest to generic cos there will be no more spells left that can crit - if spell1 < spell3 then - text:SetText(format("%.2f%%", generic + spell1)) - elseif spell1 >= spell3 then + elseif class == "PRIEST" and spell3 > 0 and spell2 > 0 then -- if priest have both talents add lowest to generic cos there will be no more spells left that can crit + if spell2 < spell3 then + text:SetText(format("%.2f%%", generic + spell2)) + elseif spell2 >= spell3 then text:SetText(format("%.2f%%", generic + spell3)) end end @@ -796,56 +796,88 @@ function BCS:SetSpellCritChance(statFrame) GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + if class == "DRUID" then if spell1 > 0 then - GameTooltip:AddLine(format("Moonfire: %.2f%%", total1)) end + GameTooltip:AddLine(format("Moonfire: %.2f%%", total1)) + end if spell2 > 0 then - GameTooltip:AddLine(format("Regrowth: %.2f%%", total2)) end + GameTooltip:AddLine(format("Regrowth: %.2f%%", total2)) + end + elseif class == "PALADIN" then if spell1 > 0 then - GameTooltip:AddLine(format("Holy Light: %.2f%%", total1)) end + GameTooltip:AddLine(format("Holy Light: %.2f%%", total1)) + end if spell2 > 0 then - GameTooltip:AddLine(format("Flash of Light: %.2f%%", total2)) end + GameTooltip:AddLine(format("Flash of Light: %.2f%%", total2)) + end if spell3 > 0 then - GameTooltip:AddLine(format("Holy Shock: %.2f%%", total3)) end + GameTooltip:AddLine(format("Holy Shock: %.2f%%", total3)) + end + elseif class == "WARLOCK" then if spell2 > 0 and spell2 ~= spell1 then - GameTooltip:AddLine(format("Searing Pain: %.2f%%", total2)) end - elseif class == "PRIEST" then -- dont show specific spells if they have same chance as offensive/healing spells + GameTooltip:AddLine(format("Searing Pain: %.2f%%", total2)) + end + + elseif class == "PRIEST" then -- all healing spells are holy, change tooltip if player have both talents if spell1 > 0 then - GameTooltip:AddLine(format("Healing spells: %.2f%%", total1)) end - if spell2 > 0 and spell2 ~= spell1 then - GameTooltip:AddLine(format("Prayer of Healing: %.2f%%", total2)) end + if spell3 > 0 then + GameTooltip:AddLine(format("Healing spells: %.2f%%", total1)) + end + GameTooltip:AddLine(format("Holy spells: %.2f%%", total1 + spell3)) + end + if spell2 > 0 then + GameTooltip:AddLine(format("Discipline spells: %.2f%%", total2 + spell3)) + end if spell3 > 0 then - GameTooltip:AddLine(format("Offensive spells: %.2f%%", total3)) end - if spell4 > 0 and spell4 ~= spell3 then - GameTooltip:AddLine(format("Smite: %.2f%%", total4)) end - if spell5 > 0 and spell5 ~= spell3 then - GameTooltip:AddLine(format("Holy Fire: %.2f%%", total5)) end + if spell2 > 0 then + GameTooltip:AddLine(format("Shadow spells: %.2f%%", total3)) + else + GameTooltip:AddLine(format("Offensive spells: %.2f%%", total3)) + end + end + if spell4 > 0 then + GameTooltip:AddLine(format("Prayer of Healing: %.2f%%", total4 + spell1)) + end + elseif class == "MAGE" then -- dont show specific spells if they have same chance as fire spells if spell1 > 0 then - GameTooltip:AddLine(format("Arcane spells: %.2f%%", total1)) end + GameTooltip:AddLine(format("Arcane spells: %.2f%%", total1)) + end if spell2 > 0 then - GameTooltip:AddLine(format("Fire spells: %.2f%%", total2)) end + GameTooltip:AddLine(format("Fire spells: %.2f%%", total2)) + end if spell3 > 0 and spell3 ~= spell2 then - GameTooltip:AddLine(format("Fire Blast: %.2f%%", total3)) end + GameTooltip:AddLine(format("Fire Blast: %.2f%%", total3)) + end if spell4 > 0 and spell4 ~= spell2 then - GameTooltip:AddLine(format("Scorch: %.2f%%", total4)) end + GameTooltip:AddLine(format("Scorch: %.2f%%", total4)) + end if spell5 > 0 and spell5 ~= spell2 then - GameTooltip:AddLine(format("Flamestrike: %.2f%%", total5)) end + GameTooltip:AddLine(format("Flamestrike: %.2f%%", total5)) + end if spell6 > 0 then - GameTooltip:AddLine(format("Frozen targets: %.2f%%", total6)) end + GameTooltip:AddLine(format("Frozen targets: %.2f%%", total6)) + end + elseif class == "SHAMAN" then if spell1 > 0 then - GameTooltip:AddLine(format("Lightning Bolt: %.2f%%", total1)) end + GameTooltip:AddLine(format("Lightning Bolt: %.2f%%", total1)) + end if spell2 > 0 then - GameTooltip:AddLine(format("Chain Lightning: %.2f%%", total2)) end + GameTooltip:AddLine(format("Chain Lightning: %.2f%%", total2)) + end if spell3 > 0 then - GameTooltip:AddLine(format("Lightning Shield: %.2f%%", total3)) end + GameTooltip:AddLine(format("Lightning Shield: %.2f%%", total3)) + end if spell4 > 0 then - GameTooltip:AddLine(format("Fire and Frost spells: %.2f%%", total4)) end + GameTooltip:AddLine(format("Fire and Frost spells: %.2f%%", total4)) + end if spell5 > 0 then - GameTooltip:AddLine(format("Healing spells: %.2f%%", total5)) end + GameTooltip:AddLine(format("Healing spells: %.2f%%", total5)) + end end GameTooltip:Show() end) diff --git a/helper.lua b/helper.lua index 1ae0494..c0096e2 100644 --- a/helper.lua +++ b/helper.lua @@ -996,11 +996,9 @@ function BCS:GetSpellCritFromClass(class) BCScache["talents"].mage_shatter elseif class == "PRIEST" then if BCS.needScanTalents then - BCScache["talents"].priest_healing_spells = 0 + BCScache["talents"].priest_holy_spells = 0 + BCScache["talents"].priest_discipline_spells = 0 BCScache["talents"].priest_offensive_spells = 0 - BCScache["talents"].priest_smite = 0 - BCScache["talents"].priest_holy_fire = 0 - BCScache["talents"].priest_prayer = 0 -- scan talents for tab=1, GetNumTalentTabs() do for talent=1, GetNumTalents(tab) do @@ -1012,17 +1010,14 @@ function BCS:GetSpellCritFromClass(class) -- Divinity local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy and Discipline spells by (%d+)%%."]) if value and rank > 0 then - BCScache["talents"].priest_healing_spells = BCScache["talents"].priest_healing_spells + tonumber(value) - BCScache["talents"].priest_smite = BCScache["talents"].priest_smite + tonumber(value) - BCScache["talents"].priest_holy_fire = BCScache["talents"].priest_holy_fire + tonumber(value) + BCScache["talents"].priest_holy_spells = BCScache["talents"].priest_holy_spells + tonumber(value) + BCScache["talents"].priest_discipline_spells = BCScache["talents"].priest_discipline_spells + tonumber(value) break end -- Force of Will - _,_, value = strfind(left:GetText(), L["Increases your spell damage by %d+%% and the critical strike chance of your offensive spells by (%d)%%"]) + _,_, value = strfind(left:GetText(), "Increases your spell damage and the critical strike chance of your offensive spells by (%d+)%%") if value and rank > 0 then BCScache["talents"].priest_offensive_spells = BCScache["talents"].priest_offensive_spells + tonumber(value) - BCScache["talents"].priest_smite = BCScache["talents"].priest_smite + tonumber(value) - BCScache["talents"].priest_holy_fire = BCScache["talents"].priest_holy_fire + tonumber(value) break end end @@ -1032,10 +1027,8 @@ function BCS:GetSpellCritFromClass(class) end -- scan gear if BCS.needScanGear then - -- t1 set gives + 2 crit to holy and 25 to prayer of healing - BCScache["gear"].priest_healing_spells = 0 - BCScache["gear"].priest_smite = 0 - BCScache["gear"].priest_holy_fire = 0 + -- t1 set gives + 2% crit to holy and 25% to prayer of healing + BCScache["gear"].priest_holy_spells = 0 BCScache["gear"].priest_prayer = 0 local Crit_Set_Bonus = {} for slot=1, 19 do @@ -1053,9 +1046,7 @@ function BCS:GetSpellCritFromClass(class) _, _, value = strfind(left:GetText(), L["^Set: Improves your chance to get a critical strike with Holy spells by (%d)%%."]) if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then tinsert(Crit_Set_Bonus, SET_NAME) - BCScache["gear"].priest_healing_spells = BCScache["gear"].priest_healing_spells + tonumber(value) - BCScache["gear"].priest_smite = BCScache["gear"].priest_smite + tonumber(value) - BCScache["gear"].priest_holy_fire = BCScache["gear"].priest_holy_fire + tonumber(value) + BCScache["gear"].priest_holy_spells = BCScache["gear"].priest_holy_spells + tonumber(value) end _, _, value = strfind(left:GetText(), L["^Set: Increases your chance of a critical hit with Prayer of Healing by (%d+)%%."]) if value and SET_NAME and not tContains(Crit_Set_Bonus, SET_NAME) then @@ -1067,14 +1058,10 @@ function BCS:GetSpellCritFromClass(class) end end end - local healingSpells, smite, holyFire, prayer - healingSpells = BCScache["talents"].priest_healing_spells + BCScache["gear"].priest_healing_spells - smite = BCScache["talents"].priest_smite + BCScache["gear"].priest_smite - holyFire = BCScache["talents"].priest_holy_fire + BCScache["gear"].priest_holy_fire - prayer = BCScache["talents"].priest_prayer + BCScache["gear"].priest_prayer + local holySpells = BCScache["talents"].priest_holy_spells + BCScache["gear"].priest_holy_spells - return healingSpells, prayer, BCScache["talents"].priest_offensive_spells, smite, holyFire, 0 + return holySpells, BCScache["talents"].priest_discipline_spells, BCScache["talents"].priest_offensive_spells, BCScache["gear"].priest_prayer, 0, 0 elseif class == "SHAMAN" then if BCS.needScanTalents then BCScache["talents"].shaman_lightning_bolt = 0 From e70f92f30be19aebcf373579f93c0ea675fc8323 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 20 Nov 2024 14:09:18 +0300 Subject: [PATCH 29/39] spell power enchant --- helper.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/helper.lua b/helper.lua index c0096e2..bed261f 100644 --- a/helper.lua +++ b/helper.lua @@ -1200,6 +1200,11 @@ function BCS:GetSpellPower(school) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) end + -- Spell Power enchant + _,_, value = strfind(left:GetText(), "Spell Damage %+(%d+)") + if value then + BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) + end -- Atiesh (druid/priest) _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to (%d+) and your healing by up to %d+.") if value then From f8157857e7a082972a28b78d16997a9e6cfd8a9c Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 20 Nov 2024 17:12:32 +0300 Subject: [PATCH 30/39] spell damage enchant fix --- helper.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/helper.lua b/helper.lua index bed261f..740a7ff 100644 --- a/helper.lua +++ b/helper.lua @@ -1201,9 +1201,10 @@ function BCS:GetSpellPower(school) BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) end -- Spell Power enchant + -- apparently gives healing too _,_, value = strfind(left:GetText(), "Spell Damage %+(%d+)") if value then - BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) end -- Atiesh (druid/priest) _,_, value = strfind(left:GetText(), "Equip: Increases your spell damage by up to (%d+) and your healing by up to %d+.") @@ -1320,24 +1321,25 @@ function BCS:GetSpellPower(school) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then + -- apparently gives healing too local found = strfind(left:GetText(), "Brilliant Wizard Oil") if found then - BCScache["gear"].only_damage = BCScache["gear"].only_damage + 36 + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 36 break end found = strfind(left:GetText(), "Lesser Wizard Oil") if found then - BCScache["gear"].only_damage = BCScache["gear"].only_damage + 16 + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 16 break end found = strfind(left:GetText(), "Minor Wizard Oil") if found then - BCScache["gear"].only_damage = BCScache["gear"].only_damage + 8 + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 8 break end found = strfind(left:GetText(), "Wizard Oil") if found then - BCScache["gear"].only_damage = BCScache["gear"].only_damage + 24 + BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + 24 break end end @@ -1387,10 +1389,12 @@ function BCS:GetSpellPower(school) if spellPowerFromAura then BCScache["auras"].damage_and_healing = BCScache["auras"].damage_and_healing + tonumber(spellPowerFromAura) end + -- Dreamtonic/Arcane Elixir _, _, spellPowerFromAura = BCS:GetPlayerAura("Magical damage dealt by spells and abilities is increased by up to (%d+)") if spellPowerFromAura then BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end + -- Dreamshard Elixir _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell damage is increased by up to (%d+)") if spellPowerFromAura then BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) From 46b42e8e27728b670e153f984044de4efcc73847 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Wed, 20 Nov 2024 20:27:51 +0300 Subject: [PATCH 31/39] bug fixes with spell power and healing --- BetterCharacterStats.lua | 13 ++++++++++--- helper.lua | 32 +++++++++++--------------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 7fb7bb8..05e2244 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -926,7 +926,7 @@ function BCS:SetHealing(statFrame) local label = getglobal(statFrame:GetName() .. "Label") local damageAndHealing = BCS:GetSpellPower() - local healingOnly, treebonus = BCS:GetHealingPower() + local healingOnly, treebonus, ironclad = BCS:GetHealingPower() local total = damageAndHealing + healingOnly if treebonus and aura <= treebonus then @@ -949,6 +949,9 @@ function BCS:SetHealing(statFrame) GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + if ironclad > 0 then + GameTooltip:AddLine(format("Healing power from Ironclad: %d", ironclad)) + end GameTooltip:Show() end) frame:SetScript("OnLeave", function() @@ -1425,7 +1428,9 @@ local function PlayerStatFrameLeftDropDown_Initialize() info.value = BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i] info.checked = checked info.owner = UIDROPDOWNMENU_OPEN_MENU - UIDropDownMenu_AddButton(info) + if not (UnitHasRelicSlot("player") and info.value == "PLAYERSTAT_RANGED_COMBAT") then + UIDropDownMenu_AddButton(info) + end end end @@ -1438,7 +1443,9 @@ local function PlayerStatFrameRightDropDown_Initialize() info.value = BCS.PLAYERSTAT_DROPDOWN_OPTIONS[i] info.checked = checked info.owner = UIDROPDOWNMENU_OPEN_MENU - UIDropDownMenu_AddButton(info) + if not (UnitHasRelicSlot("player") and info.value == "PLAYERSTAT_RANGED_COMBAT") then + UIDropDownMenu_AddButton(info) + end end end diff --git a/helper.lua b/helper.lua index 740a7ff..b2678e4 100644 --- a/helper.lua +++ b/helper.lua @@ -1200,8 +1200,9 @@ function BCS:GetSpellPower(school) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) end - -- Spell Power enchant - -- apparently gives healing too + -- Spell Power (weapon/bracer enchant) apparently gives healing too + -- Arcanum of Focus (Head/Legs enchant) + -- Power of the Scourge (Shoulder enchant) _,_, value = strfind(left:GetText(), "Spell Damage %+(%d+)") if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) @@ -1211,27 +1212,16 @@ function BCS:GetSpellPower(school) if value then BCScache["gear"].only_damage = BCScache["gear"].only_damage + tonumber(value) end - -- Arcanum of Focus (Head/Legs enchant) - _,_, value = strfind(left:GetText(), "Healing and Spell Damage %+(%d+)") - if value then - BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) - end -- Zandalar Signet of Mojo (Shoulder enchant) _,_, value = strfind(left:GetText(), L["^%+(%d+) Spell Damage and Healing"]) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) end - -- Power of the Scourge (Shoulder enchant) - _,_, value = strfind(left:GetText(), "Spell Damage %+(%d+) and %+%d+%% Spell Critical Strike") - if value then - BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) - end -- Enchanted Armor Kit (Leatherworking) _,_, value = strfind(left:GetText(), L["^%+(%d+) Damage and Healing Spells"]) if value then BCScache["gear"].damage_and_healing = BCScache["gear"].damage_and_healing + tonumber(value) - end - + end _,_, value = strfind(left:GetText(), L["Equip: Increases damage done by Arcane spells and effects by up to (%d+)."]) if value then BCScache["gear"].arcane = BCScache["gear"].arcane + tonumber(value) @@ -1502,17 +1492,13 @@ function BCS:GetHealingPower() if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end - -- Resilience of the Scourge (Shoulder enchant) - _,_, value = strfind(left:GetText(), L["^Healing %+(%d+) and %d+ mana per 5 sec."]) - if value then - BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) - end -- Zandalar Signet of Serenity (Shoulder enchant) _,_, value = strfind(left:GetText(), L["^%+(%d+) Healing Spells"]) if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) end -- Beautiful Diamond Gemstone (Jewelcrafting) + -- Resilience of the Scourge (Shoulder enchant) _,_, value = strfind(left:GetText(), "Healing %+(%d+)") if value then BCScache["gear"].healing = BCScache["gear"].healing + tonumber(value) @@ -1604,7 +1590,7 @@ function BCS:GetHealingPower() end healPower = BCScache["gear"].healing + BCScache["auras"].healing + BCScache["talents"].healing - return healPower, treebonus + return healPower, treebonus, BCScache["talents"].healing end local function GetRegenMPPerSpirit() @@ -1914,6 +1900,7 @@ function BCS:GetRangedWeaponSkill() end --https://us.forums.blizzard.com/en/wow/t/block-value-formula/283718/18 +local enhancingTotems = nil function BCS:GetBlockValue() local blockValue = 0 local _, strength = UnitStat("player", 1) @@ -1966,7 +1953,7 @@ function BCS:GetBlockValue() --enhancing totems _,_, value = strfind(left:GetText(), "increases block amount by (%d+)%%") if value and rank > 0 then - mod = mod + tonumber(value) + enhancingTotems = tonumber(value) break end end @@ -1979,6 +1966,9 @@ function BCS:GetBlockValue() if value then blockValue = blockValue + tonumber(value) end + if enhancingTotems and BCS:GetPlayerAura("Stoneskin Totem") then + mod = mod + enhancingTotems + end mod = mod/100 blockValue = blockValue + (strength/20 - 1) From 3374ba997ef70acd501d801b41e2104baecfc935 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Fri, 22 Nov 2024 01:24:26 +0300 Subject: [PATCH 32/39] remove temporary fix for ranged crit --- BetterCharacterStats.lua | 4 ++-- helper.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 05e2244..24fae23 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -899,12 +899,12 @@ function BCS:SetRangedCritChance(statFrame) local skill = BCS:GetRangedWeaponSkill() local level = UnitLevel("player") -- apply skill difference modifier - --[[local skillDiff = skill - (level*5) + local skillDiff = skill - (level*5) if (skill >= (level*5)) then crit = crit + (skillDiff * 0.04) else crit = crit + (skillDiff * 0.2) - end]] + end if crit < 0 then crit = 0 end text:SetText(format("%.2f%%", crit)) statFrame.tooltip = (L.RANGED_CRIT_TOOLTIP) diff --git a/helper.lua b/helper.lua index b2678e4..fb350f7 100644 --- a/helper.lua +++ b/helper.lua @@ -1966,7 +1966,7 @@ function BCS:GetBlockValue() if value then blockValue = blockValue + tonumber(value) end - if enhancingTotems and BCS:GetPlayerAura("Stoneskin Totem") then + if enhancingTotems and BCS:GetPlayerAura("^Stoneskin") then mod = mod + enhancingTotems end From f0d7908cdc1e931a9ec67ea0f88e0d288052af49 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sun, 24 Nov 2024 02:28:02 +0300 Subject: [PATCH 33/39] fix priest talent Spiritual Guidance --- helper.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/helper.lua b/helper.lua index fb350f7..fe58abd 100644 --- a/helper.lua +++ b/helper.lua @@ -1122,6 +1122,7 @@ function BCS:GetSpellCritFromClass(class) end local impInnerFire = nil +local spiritualGuidance = nil function BCS:GetSpellPower(school) if school then local spellPower = 0; @@ -1339,7 +1340,7 @@ function BCS:GetSpellPower(school) if BCS.needScanTalents then impInnerFire = nil - BCScache["talents"].damage_and_healing = 0 + spiritualGuidance = nil -- scan talents for tab=1, GetNumTalentTabs() do for talent=1, GetNumTalents(tab) do @@ -1352,8 +1353,7 @@ function BCS:GetSpellPower(school) -- Spiritual Guidance local _,_, value = strfind(left:GetText(), L["Increases spell damage and healing by up to (%d+)%% of your total Spirit."]) if value and rank > 0 then - local stat, spirit = UnitStat("player", 5) - BCScache["talents"].damage_and_healing = BCScache["talents"].damage_and_healing + floor(((tonumber(value) / 100) * spirit)) + spiritualGuidance = tonumber(value) break end -- Improved Inner Fire @@ -1432,6 +1432,12 @@ function BCS:GetSpellPower(school) secondaryPowerName = L.SPELL_SCHOOL_SHADOW end + if spiritualGuidance ~= nil then + BCScache["talents"].damage_and_healing = 0 + local _, spirit = UnitStat("player", 5) + BCScache["talents"].damage_and_healing = BCScache["talents"].damage_and_healing + floor(((spiritualGuidance / 100) * spirit)) + end + damageAndHealing = BCScache["gear"].damage_and_healing + BCScache["talents"].damage_and_healing + BCScache["auras"].damage_and_healing damageOnly = BCScache["auras"].only_damage + BCScache["gear"].only_damage From 4ce5456daa9da6e56f9481a40a17dfbf7d314897 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Thu, 28 Nov 2024 16:28:30 +0300 Subject: [PATCH 34/39] small update moved player model slightly higher (to adjust for the reduced space by added dropdowns) some code cleanup uncapped total avoidance (I believe its more informative that way) --- BetterCharacterStats.lua | 53 ++++++++++++++++++++++- helper.lua | 90 +++++++++++++++++++++------------------- 2 files changed, 98 insertions(+), 45 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 24fae23..ed817d0 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -81,6 +81,42 @@ function BCS:OnLoad() self.Frame:RegisterEvent("CHAT_MSG_SKILL") --gaining weapon skill self.Frame:RegisterEvent("CHAT_MSG_ADDON") --needed to recieve aura bonuses from other people end + +local function PostHookFunction(original,hook) + return function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) + original(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) + hook(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) + end +end + +local z, x, y = -0.2, 0, 0.1 + +function BCS_PaperDollFrame_OnEvent(event, unit) + if ( event == "PLAYER_ENTERING_WORLD" ) then + CharacterModelFrame:SetPosition(0, 0, 0) + CharacterModelFrame:SetUnit("player") + CharacterModelFrame:SetPosition(z, x, y) + return + end + if ( unit and unit == "player" ) then + if ( event == "UNIT_MODEL_CHANGED" ) then + CharacterModelFrame:SetPosition(0, 0, 0) + CharacterModelFrame:SetUnit("player") + CharacterModelFrame:SetPosition(z, x, y) + return + end + end +end + +function BCS_PaperDollFrame_OnShow() + CharacterModelFrame:SetPosition(0, 0, 0) + CharacterModelFrame:SetUnit("player") + CharacterModelFrame:SetPosition(z, x, y) +end + +PaperDollFrame_OnShow = PostHookFunction(PaperDollFrame_OnShow, BCS_PaperDollFrame_OnShow) +PaperDollFrame_OnEvent = PostHookFunction(PaperDollFrame_OnEvent, BCS_PaperDollFrame_OnEvent) + -- Scan stuff depending on event, but make sure to scan everything when addon is loaded function BCS:OnEvent() --[[if BCS.Debug then @@ -147,6 +183,16 @@ function BCS:OnEvent() end elseif event == "ADDON_LOADED" and arg1 == "BetterCharacterStats" then BCSFrame:UnregisterEvent("ADDON_LOADED") + + local _, race = UnitRace("player") + if race == "Gnome" then + y = 0 + elseif race == "Dwarf" then + y = 0.05 + elseif race == "Troll" then + y = 0.15 + end + BCS.needScanGear = true BCS.needScanTalents = true BCS.needScanAuras = true @@ -159,12 +205,15 @@ function BCS:OnEvent() UIDropDownMenu_SetSelectedValue(PlayerStatFrameRightDropDown, IndexRight) end end + --sending messages local sender = CreateFrame("Frame", "BCSsender") sender:RegisterEvent("PLAYER_AURAS_CHANGED") sender:RegisterEvent("CHAT_MSG_ADDON") sender:SetScript("OnEvent", function() - if not (UnitInParty("player") or UnitInRaid("player")) then return end + if not (UnitInParty("player") or UnitInRaid("player")) then + return + end if event then local player = UnitName("player") if event == "PLAYER_AURAS_CHANGED" then @@ -1066,7 +1115,7 @@ function BCS:SetTotalAvoidance(statFrame) local missChance = 5 + skillDiff * 0.04 local total = missChance + (GetBlockChance() + GetParryChance() + GetDodgeChance()) - if total > 100 then total = 100 end + --if total > 100 then total = 100 end if total < 0 then total = 0 end label:SetText(L.TOTAL_COLON) diff --git a/helper.lua b/helper.lua index fe58abd..132d229 100644 --- a/helper.lua +++ b/helper.lua @@ -203,7 +203,7 @@ function BCS:GetHitRating(hitOnly) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Rogue local _,_, value = strfind(left:GetText(), L["Increases your chance to hit with melee weapons by (%d)%%."]) if value and rank > 0 then @@ -329,7 +329,7 @@ function BCS:GetSpellHitRating() for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Mage -- Elemental Precision local _,_, value = strfind(left:GetText(), L["Reduces the chance that the opponent can resist your Frost and Fire spells by (%d)%%."]) @@ -411,7 +411,7 @@ function BCS:GetCritChance() local crit = 0 --scan spellbook for tab=1, GetNumSpellTabs() do - local name, texture, offset, numSpells = GetSpellTabInfo(tab) + local _, _, offset, numSpells = GetSpellTabInfo(tab) for spell=1, numSpells do local currentPage = ceil(spell/SPELLS_PER_PAGE) local SpellID = spell + offset + ( SPELLS_PER_PAGE * (currentPage - 1)) @@ -458,7 +458,7 @@ function BCS:GetRangedCritChance() for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) local _,_, value = strfind(left:GetText(), L["Increases your critical strike chance with ranged weapons by (%d)%%."]) if value and rank > 0 then BCScache["talents"].ranged_crit = BCScache["talents"].ranged_crit + tonumber(value) @@ -716,7 +716,7 @@ function BCS:GetSpellCritChance() for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Arcane Instability local _,_, value = strfind(left:GetText(), L["Increases your spell damage and critical srike chance by (%d+)%%."]) if value and rank > 0 then @@ -833,7 +833,7 @@ function BCS:GetSpellCritFromClass(class) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Holy Power local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy Light and Flash of Light by (%d+)%%."]) if value and rank > 0 then @@ -868,7 +868,7 @@ function BCS:GetSpellCritFromClass(class) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Improved Moonfire local _,_, value = strfind(left:GetText(), L["Increases the damage and critical strike chance of your Moonfire spell by (%d+)%%."]) if value and rank > 0 then @@ -901,7 +901,7 @@ function BCS:GetSpellCritFromClass(class) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Devastation local _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Destruction spells by (%d+)%%."]) if value and rank > 0 then @@ -939,7 +939,7 @@ function BCS:GetSpellCritFromClass(class) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Arcane Impact local _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Arcane Explosion and Arcane Missiles spells by an additional (%d+)%%."]) if value and rank > 0 then @@ -1006,7 +1006,7 @@ function BCS:GetSpellCritFromClass(class) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Divinity local _,_, value = strfind(left:GetText(), L["Increases the critical effect chance of your Holy and Discipline spells by (%d+)%%."]) if value and rank > 0 then @@ -1076,7 +1076,7 @@ function BCS:GetSpellCritFromClass(class) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Call of Thunder local _,_, value = strfind(left:GetText(), L["Increases the critical strike chance of your Lightning Bolt and Chain Lightning spells by an additional (%d+)%%."]) if value and rank > 0 then @@ -1348,7 +1348,7 @@ function BCS:GetSpellPower(school) for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Priest -- Spiritual Guidance local _,_, value = strfind(left:GetText(), L["Increases spell damage and healing by up to (%d+)%% of your total Spirit."]) @@ -1460,7 +1460,7 @@ function BCS:GetHealingPower() for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Paladin -- Ironclad local _,_, value = strfind(left:GetText(), L["Increases your healing power by (%d+)%% of your Armor."]) @@ -1601,23 +1601,23 @@ end local function GetRegenMPPerSpirit() local addvalue = 0 - local stat, Spirit, posBuff, negBuff = UnitStat("player", 5) - local lClass, class = UnitClass("player") + local _, spirit = UnitStat("player", 5) + local _, class = UnitClass("player") if class == "DRUID" then - addvalue = (Spirit / 5 + 15) + addvalue = (spirit / 5 + 15) elseif class == "HUNTER" then - addvalue = (Spirit / 5 + 15) + addvalue = (spirit / 5 + 15) elseif class == "MAGE" then - addvalue = (Spirit / 4 + 12.5) + addvalue = (spirit / 4 + 12.5) elseif class == "PALADIN" then - addvalue = (Spirit / 5 + 15) + addvalue = (spirit / 5 + 15) elseif class == "PRIEST" then - addvalue = (Spirit / 4 + 12.5) + addvalue = (spirit / 4 + 12.5) elseif class == "SHAMAN" then - addvalue = (Spirit / 5 + 17) + addvalue = (spirit / 5 + 17) elseif class == "WARLOCK" then - addvalue = (Spirit / 5 + 15) + addvalue = (spirit / 5 + 15) end return addvalue @@ -1640,7 +1640,7 @@ function BCS:GetManaRegen() for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) -- Priest (Meditation) / Druid (Reflection) / Mage (Arcane Meditation) / Shaman (Improved Water Shield) local _,_, value = strfind(left:GetText(), L["Allows (%d+)%% of your Mana regeneration to continue while casting."]) if value and rank > 0 then @@ -1732,8 +1732,8 @@ function BCS:GetManaRegen() BCScache["auras"].casting = 0 BCScache["auras"].mp5 = 0 -- improved Shadowform - for i = 1, MAX_SKILLLINE_TABS do - local name, texture, offset, numSpells = GetSpellTabInfo(i); + for tab=1, GetNumSpellTabs() do + local _, _, offset, numSpells = GetSpellTabInfo(tab); for s = offset + 1, offset + numSpells do local spell = GetSpellName(s, BOOKTYPE_SPELL); if spell == "Improved Shadowform" and BCS:GetPlayerAura("Shadowform") then @@ -1817,9 +1817,7 @@ function BCS:GetWeaponSkill(skillName) -- loop through skills local skillIndex = 1 while true do - local name, isHeader, isExpanded, skillRank, numTempPoints, skillModifier, - skillMaxRank, isAbandonable, stepCost, rankCost, minLevel, skillCostType, - skillDescription = GetSkillLineInfo(skillIndex) + local name, _, _, skillRank, _, skillModifier = GetSkillLineInfo(skillIndex) if not name then return 0 end @@ -1868,40 +1866,46 @@ function BCS:GetWeaponSkillForWeaponType(weaponType) return BCS:GetWeaponSkill("Unarmed") end -function BCS:GetItemInfoForSlot(slot) +function BCS:GetItemTypeForSlot(slot) local _, _, id = string.find(GetInventoryItemLink("player", GetInventorySlotInfo(slot)) or "", "(item:%d+:%d+:%d+:%d+)"); if not id then return end - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(id); + local _, _, _, _, _, itemType = GetItemInfo(id); - return itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice; + return itemType end function BCS:GetMHWeaponSkill() - if not BCS.needScanSkills then return BCScache["skills"].mh end - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("MainHandSlot") + if not BCS.needScanSkills then + return BCScache["skills"].mh + end + local itemType = BCS:GetItemTypeForSlot("MainHandSlot") BCScache["skills"].mh = BCS:GetWeaponSkillForWeaponType(itemType) + return BCScache["skills"].mh end function BCS:GetOHWeaponSkill() - if not BCS.needScanSkills then return BCScache["skills"].oh end - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("SecondaryHandSlot") + if not BCS.needScanSkills then + return BCScache["skills"].oh + end + + local itemType = BCS:GetItemTypeForSlot("SecondaryHandSlot") BCScache["skills"].oh = BCS:GetWeaponSkillForWeaponType(itemType) + return BCScache["skills"].oh end function BCS:GetRangedWeaponSkill() - if not BCS.needScanSkills then return BCScache["skills"].ranged end - local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, - itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = BCS:GetItemInfoForSlot("RangedSlot") + if not BCS.needScanSkills then + return BCScache["skills"].ranged + end + + local itemType = BCS:GetItemTypeForSlot("RangedSlot") BCScache["skills"].ranged = BCS:GetWeaponSkillForWeaponType(itemType) + return BCScache["skills"].ranged end @@ -1942,7 +1946,7 @@ function BCS:GetBlockValue() for line=1, BCS_Tooltip:NumLines() do local left = getglobal(BCS_Prefix .. "TextLeft" .. line) if left:GetText() then - local name, iconTexture, tier, column, rank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, talent) + local _, _, _, _, rank = GetTalentInfo(tab, talent) --warrior/paladin local _,_, value = strfind(left:GetText(), "amount of damage absorbed by your shield by (%d+)%%") if value and rank > 0 then From eb92ab89546801047588666be2e24d6835f807a2 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sun, 1 Dec 2024 20:37:53 +0300 Subject: [PATCH 35/39] refactor --- BetterCharacterStats.lua | 947 +++++++++++++-------------------------- 1 file changed, 319 insertions(+), 628 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index ed817d0..f497832 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -89,8 +89,8 @@ local function PostHookFunction(original,hook) end end +-- there is less space for player character model with this addon, zoom out and move it up slightly local z, x, y = -0.2, 0, 0.1 - function BCS_PaperDollFrame_OnEvent(event, unit) if ( event == "PLAYER_ENTERING_WORLD" ) then CharacterModelFrame:SetPosition(0, 0, 0) @@ -117,6 +117,18 @@ end PaperDollFrame_OnShow = PostHookFunction(PaperDollFrame_OnShow, BCS_PaperDollFrame_OnShow) PaperDollFrame_OnEvent = PostHookFunction(PaperDollFrame_OnEvent, BCS_PaperDollFrame_OnEvent) +local function strsplit(delimiter, subject) + if not subject then + return nil + end + local delimiter, fields = delimiter or ":", {} + local pattern = string.format("([^%s]+)", delimiter) + string.gsub(subject, pattern, function(c) + fields[table.getn(fields) + 1] = c + end) + return unpack(fields) +end + -- Scan stuff depending on event, but make sure to scan everything when addon is loaded function BCS:OnEvent() --[[if BCS.Debug then @@ -132,7 +144,7 @@ function BCS:OnEvent() end]] if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then BCS.needScanAuras = true - local type, player, amount = hcstrsplit(",", arg2) + local type, player, amount = strsplit(",", arg2) if type and player and amount then if player ~= UnitName("player") then amount = tonumber(amount) @@ -223,7 +235,7 @@ sender:SetScript("OnEvent", function() end end if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then - local type, name, amount = hcstrsplit(",", arg2) + local type, name, amount = strsplit(",", arg2) if name ~= player then local _, treebonus = BCS:GetHealingPower() if not amount and type == "TREE" and treebonus then @@ -270,13 +282,121 @@ function BCS:UpdateStats() BCS:Print(format("Average: %d (%d results), Exact: %d", avg, getn(avgV), timeUsed))]] end +local function BCS_AddTooltip(statFrame, tooltipExtra) + statFrame:SetScript("OnEnter", function() + GameTooltip:SetOwner(this, "ANCHOR_RIGHT") + GameTooltip:SetText(this.tooltip) + GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + if tooltipExtra then + GameTooltip:AddLine(tooltipExtra) + end + GameTooltip:Show() + end) + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + +local function BCS_AddDamageTooltip(damageText, statFrame, speed, offhandSpeed, ranged) + local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent + local minOffHandDamage, maxOffHandDamage + + if ranged then + rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") + speed = rangedAttackSpeed + else + minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent = UnitDamage("player") + end + + local displayMin = max(floor(minDamage), 1) + local displayMax = max(ceil(maxDamage), 1) + + 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) + local damagePerSecond = (max(fullDamage, 1) / speed) + local damageTooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) + local green = "|cff20ff20" + local red = "|cffff2020" + + if (totalBonus == 0) then + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(displayMin .. " - " .. displayMax) + else + damageText:SetText(displayMin .. "-" .. displayMax) + end + else + local color + if (totalBonus > 0) then + color = green + else + color = red + end + if ((displayMin < 100) and (displayMax < 100)) then + damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") + else + damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|r") + end + if (physicalBonusPos > 0) then + damageTooltip = damageTooltip .. green .. " +" .. physicalBonusPos .. "|r" + end + if (physicalBonusNeg < 0) then + damageTooltip = damageTooltip .. red .. " " .. physicalBonusNeg .. "|r" + end + if (percent > 1) then + damageTooltip = damageTooltip .. green .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + elseif (percent < 1) then + damageTooltip = damageTooltip .. red .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + end + end + statFrame.damage = damageTooltip + statFrame.attackSpeed = speed + statFrame.dps = damagePerSecond + + -- If there's an offhand speed then add the offhand info to the tooltip + if (offhandSpeed) then + minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg + maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg + + local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5 + local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent + local offhandDamagePerSecond = (max(offhandFullDamage, 1) / offhandSpeed) + local offhandDamageTooltip = max(floor(minOffHandDamage), 1) .. " - " .. max(ceil(maxOffHandDamage), 1) + if (physicalBonusPos > 0) then + offhandDamageTooltip = offhandDamageTooltip .. green .. " +" .. physicalBonusPos .. "|r" + end + if (physicalBonusNeg < 0) then + offhandDamageTooltip = offhandDamageTooltip .. red .. " " .. physicalBonusNeg .. "|r" + end + if (percent > 1) then + offhandDamageTooltip = offhandDamageTooltip .. green .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + elseif (percent < 1) then + offhandDamageTooltip = offhandDamageTooltip .. red .. " x" .. floor(percent * 100 + 0.5) .. "%|r" + end + statFrame.offhandDamage = offhandDamageTooltip + statFrame.offhandAttackSpeed = offhandSpeed + statFrame.offhandDps = offhandDamagePerSecond + else + statFrame.offhandAttackSpeed = nil + end + + if ranged then + statFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) + else + statFrame:SetScript("OnEnter", CharacterDamageFrame_OnEnter) + end + + statFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + end) +end + function BCS:SetStat(statFrame, statIndex) local label = getglobal(statFrame:GetName() .. "Label") local text = getglobal(statFrame:GetName() .. "StatText") - local stat - local effectiveStat - local posBuff - local negBuff local statIndexTable = { "STRENGTH", "AGILITY", @@ -294,7 +414,7 @@ function BCS:SetStat(statFrame, statIndex) end) label:SetText(TEXT(getglobal("SPELL_STAT" .. (statIndex - 1) .. "_NAME")) .. ":") - stat, effectiveStat, posBuff, negBuff = UnitStat("player", statIndex) + local stat, effectiveStat, posBuff, negBuff = UnitStat("player", statIndex) -- Set the tooltip text local tooltipText = HIGHLIGHT_FONT_COLOR_CODE .. getglobal("SPELL_STAT" .. (statIndex - 1) .. "_NAME") .. " " @@ -329,138 +449,37 @@ function BCS:SetStat(statFrame, statIndex) end function BCS:SetArmor(statFrame) - local base, effectiveArmor, armor, posBuff, negBuff = UnitArmor("player") - local totalBufs = posBuff + negBuff - local frame = statFrame - local label = getglobal(frame:GetName() .. "Label") - local text = getglobal(frame:GetName() .. "StatText") + local label = getglobal(statFrame:GetName() .. "Label") + local text = getglobal(statFrame:GetName() .. "StatText") - PaperDollFormatStat(ARMOR, base, posBuff, negBuff, frame, text) + PaperDollFormatStat(ARMOR, base, posBuff, negBuff, statFrame, text) label:SetText(TEXT(ARMOR_COLON)) local playerLevel = UnitLevel("player") local armorReduction = effectiveArmor / ((85 * playerLevel) + 400) armorReduction = 100 * (armorReduction / (armorReduction + 1)) - frame.tooltipSubtext = format(ARMOR_TOOLTIP, playerLevel, armorReduction) + statFrame.tooltipSubtext = format(ARMOR_TOOLTIP, playerLevel, armorReduction) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + BCS_AddTooltip(statFrame) end function BCS:SetDamage(statFrame) - local label = getglobal(statFrame:GetName() .. "Label") - label:SetText(TEXT(DAMAGE_COLON)) local damageText = getglobal(statFrame:GetName() .. "StatText") - local damageFrame = statFrame - - damageFrame:SetScript("OnEnter", CharacterDamageFrame_OnEnter) - damageFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - + local label = getglobal(statFrame:GetName() .. "Label") local speed, offhandSpeed = UnitAttackSpeed("player") + + BCS_AddDamageTooltip(damageText, statFrame, speed, offhandSpeed) - local minDamage - local maxDamage - local minOffHandDamage - local maxOffHandDamage - local physicalBonusPos - local physicalBonusNeg - local percent - minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent = UnitDamage("player") - local displayMin = max(floor(minDamage), 1) - local displayMax = max(ceil(maxDamage), 1) - - 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) - local damagePerSecond = (max(fullDamage, 1) / speed) - local damageTooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) - - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - if (totalBonus == 0) then - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(displayMin .. " - " .. displayMax) - else - damageText:SetText(displayMin .. "-" .. displayMax) - end - else - - local color - if (totalBonus > 0) then - color = colorPos - else - color = colorNeg - end - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") - else - damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|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 - damageFrame.damage = damageTooltip - damageFrame.attackSpeed = speed - damageFrame.dps = damagePerSecond - - -- If there's an offhand speed then add the offhand info to the tooltip - if (offhandSpeed) then - minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg - maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg - - local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5 - local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent - local offhandDamagePerSecond = (max(offhandFullDamage, 1) / offhandSpeed) - local offhandDamageTooltip = max(floor(minOffHandDamage), 1) .. " - " .. 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 - damageFrame.offhandDamage = offhandDamageTooltip - damageFrame.offhandAttackSpeed = offhandSpeed - damageFrame.offhandDps = offhandDamagePerSecond - else - damageFrame.offhandAttackSpeed = nil - end - + label:SetText(TEXT(DAMAGE_COLON)) end function BCS:SetAttackSpeed(statFrame) - local damageText = getglobal(statFrame:GetName() .. "StatText") - local damageFrame = statFrame + local label = getglobal(statFrame:GetName() .. "Label") local speed, offhandSpeed = UnitAttackSpeed("player") + speed = format("%.2f", speed) if (offhandSpeed) then offhandSpeed = format("%.2f", offhandSpeed) @@ -472,107 +491,19 @@ function BCS:SetAttackSpeed(statFrame) text = speed end - local minDamage - local maxDamage - local minOffHandDamage - local maxOffHandDamage - local physicalBonusPos - local physicalBonusNeg - local percent - minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent = UnitDamage("player") - local displayMin = max(floor(minDamage), 1) - local displayMax = max(ceil(maxDamage), 1) - - 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) - local damagePerSecond = (max(fullDamage, 1) / speed) - local damageTooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) - - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - if (totalBonus == 0) then - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(displayMin .. " - " .. displayMax) - else - damageText:SetText(displayMin .. "-" .. displayMax) - end - else - - local color - if (totalBonus > 0) then - color = colorPos - else - color = colorNeg - end - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") - else - damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|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 - damageFrame.damage = damageTooltip - damageFrame.attackSpeed = speed - damageFrame.dps = damagePerSecond - - -- If there's an offhand speed then add the offhand info to the tooltip - if (offhandSpeed) then - minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg - maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg + BCS_AddDamageTooltip(damageText, statFrame, speed, offhandSpeed) - local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5 - local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent - local offhandDamagePerSecond = (max(offhandFullDamage, 1) / offhandSpeed) - local offhandDamageTooltip = max(floor(minOffHandDamage), 1) .. " - " .. 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 - damageFrame.offhandDamage = offhandDamageTooltip - damageFrame.offhandAttackSpeed = offhandSpeed - damageFrame.offhandDps = offhandDamagePerSecond - else - damageFrame.offhandAttackSpeed = nil - end - local label = getglobal(statFrame:GetName() .. "Label") - local value = getglobal(statFrame:GetName() .. "StatText") label:SetText(TEXT(SPEED) .. ":") - value:SetText(text) - statFrame:SetScript("OnEnter", CharacterDamageFrame_OnEnter) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + damageText:SetText(text) end function BCS:SetAttackPower(statFrame) - local base, posBuff, negBuff = UnitAttackPower("player") - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") local tooltipText = HIGHLIGHT_FONT_COLOR_CODE .. MELEE_ATTACK_POWER .. " " + local base, posBuff, negBuff = UnitAttackPower("player") local effectiveStat = base + posBuff + negBuff + if ((posBuff == 0) and (negBuff == 0)) then text:SetText(effectiveStat) statFrame.tooltip = tooltipText .. base .. FONT_COLOR_CODE_CLOSE @@ -598,111 +529,102 @@ function BCS:SetAttackPower(statFrame) text:SetText(GREEN_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) end end + label:SetText(TEXT(ATTACK_POWER_COLON)) - PaperDollFormatStat(MELEE_ATTACK_POWER, base, posBuff, negBuff, frame, text) - frame.tooltipSubtext= format(MELEE_ATTACK_POWER_TOOLTIP, max((base + posBuff + negBuff), 0) / ATTACK_POWER_MAGIC_NUMBER) - if frame.tooltip then - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - end + PaperDollFormatStat(MELEE_ATTACK_POWER, base, posBuff, negBuff, statFrame, text) + statFrame.tooltipSubtext = format(MELEE_ATTACK_POWER_TOOLTIP, max((base + posBuff + negBuff), 0) / ATTACK_POWER_MAGIC_NUMBER) + + BCS_AddTooltip(statFrame) end function BCS:SetSpellPower(statFrame, school) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - - local colorPos = "|cff20ff20" - --local colorNeg = "|cffff2020" + local green = "|cff20ff20" if school then - label:SetText(L["SPELL_SCHOOL_" .. strupper(school)]) local base = BCS:GetSpellPower() local fromSchool = BCS:GetSpellPower(school) local output = base + fromSchool if fromSchool > 0 then - output = colorPos .. output .. "|r" + output = green .. output .. "|r" end - + + label:SetText(L["SPELL_SCHOOL_" .. strupper(school)]) text:SetText(output) if fromSchool > 0 then - frame.tooltip = format(L.SPELL_SCHOOL_SECONDARY_TOOLTIP , school, base + fromSchool, base, fromSchool) + statFrame.tooltip = format(L.SPELL_SCHOOL_SECONDARY_TOOLTIP , school, base + fromSchool, base, fromSchool) else - frame.tooltip = format(L.SPELL_SCHOOL_TOOLTIP , school, base) + statFrame.tooltip = format(L.SPELL_SCHOOL_TOOLTIP , school, base) end - frame.tooltipSubtext = format(L.SPELL_SCHOOL_TOOLTIP_SUB, strlower(school)) + statFrame.tooltipSubtext = format(L.SPELL_SCHOOL_TOOLTIP_SUB, strlower(school)) else local damageAndHealing, secondaryPower, secondaryName, damageOnly = BCS:GetSpellPower() local total = damageAndHealing + damageOnly label:SetText(L.SPELL_POWER_COLON) if secondaryPower > 0 then - text:SetText(colorPos..total + secondaryPower) + text:SetText(green..total + secondaryPower) else text:SetText(total + secondaryPower) end if secondaryPower ~= 0 then - frame.tooltip = format(L.SPELL_POWER_SECONDARY_TOOLTIP, (total + secondaryPower), total, secondaryPower, secondaryName) - frame.tooltipSubtext = format(L.SPELL_POWER_SECONDARY_TOOLTIP_SUB) + statFrame.tooltip = format(L.SPELL_POWER_SECONDARY_TOOLTIP, (total + secondaryPower), total, secondaryPower, secondaryName) + statFrame.tooltipSubtext = format(L.SPELL_POWER_SECONDARY_TOOLTIP_SUB) else - frame.tooltip = format(L.SPELL_POWER_TOOLTIP, total) - frame.tooltipSubtext = format(L.SPELL_POWER_TOOLTIP_SUB) + statFrame.tooltip = format(L.SPELL_POWER_TOOLTIP, total) + statFrame.tooltipSubtext = format(L.SPELL_POWER_TOOLTIP_SUB) end end - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + + BCS_AddTooltip(statFrame) end function BCS:SetHitRating(statFrame, ratingType) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") local _, class = UnitClass("player") label:SetText(L.MELEE_HIT_RATING_COLON) + if ratingType == "MELEE" then local rating = BCS:GetHitRating() rating = rating .. "%" text:SetText(rating) - frame.tooltip = (L.MELEE_HIT_TOOLTIP) - frame.tooltipSubtext = format(L.MELEE_HIT_TOOLTIP_SUB) + + statFrame.tooltip = (L.MELEE_HIT_TOOLTIP) + statFrame.tooltipSubtext = format(L.MELEE_HIT_TOOLTIP_SUB) + elseif ratingType == "RANGED" then -- If no ranged attack then set to n/a if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then text:SetText(NOT_APPLICABLE) return end + local rating = BCS:GetRangedHitRating() rating = rating .. "%" text:SetText(rating) - frame.tooltip = (L.RANGED_HIT_TOOLTIP) - frame.tooltipSubtext = format(L.RANGED_HIT_TOOLTIP_SUB) + + statFrame.tooltip = (L.RANGED_HIT_TOOLTIP) + statFrame.tooltipSubtext = format(L.RANGED_HIT_TOOLTIP_SUB) + elseif ratingType == "SPELL" then local spell_hit, spell_hit_fire, spell_hit_frost, spell_hit_arcane, spell_hit_shadow, spell_hit_holy = BCS:GetSpellHitRating() - frame.tooltip = format(L.SPELL_HIT_TOOLTIP) + text:SetText(spell_hit .. "%") - frame.tooltipSubtext = format(L.SPELL_HIT_TOOLTIP_SUB) - if frame.tooltip then - frame:SetScript("OnEnter", function() + + statFrame.tooltip = format(L.SPELL_HIT_TOOLTIP) + statFrame.tooltipSubtext = format(L.SPELL_HIT_TOOLTIP_SUB) + + if statFrame.tooltip then + statFrame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + if spell_hit_fire > 0 then GameTooltip:AddLine(format(L.SPELL_SCHOOL_FIRE.." spells: %.f%%", spell_hit + spell_hit_fire)) end @@ -722,23 +644,18 @@ function BCS:SetHitRating(statFrame, ratingType) if spell_hit_holy > 0 then GameTooltip:AddLine(format(L.SPELL_SCHOOL_HOLY.." and Discipline spells: %.f%%", spell_hit + spell_hit_holy)) end + GameTooltip:Show() end) - frame:SetScript("OnLeave", function() + + statFrame:SetScript("OnLeave", function() GameTooltip:Hide() end) end end - if frame.tooltip and ratingType ~= "SPELL" then - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + + if ratingType ~= "SPELL" then + BCS_AddTooltip(statFrame) end end @@ -751,67 +668,53 @@ function BCS:SetMeleeCritChance(statFrame) statFrame.tooltip = (L.MELEE_CRIT_TOOLTIP) statFrame.tooltipSubtext = (L.MELEE_CRIT_TOOLTIP_SUB) - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + + BCS_AddTooltip(statFrame) end function BCS:SetWeaponSkill(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.WEAPON_SKILL_COLON) + if OffhandHasWeapon() == 1 then text:SetText(format("%d |%d", BCS:GetMHWeaponSkill(), BCS:GetOHWeaponSkill())) else text:SetText(format("%d", BCS:GetMHWeaponSkill())) - end + end + statFrame.tooltip = format(L.MELEE_WEAPON_SKILL_TOOLTIP) statFrame.tooltipSubtext = format(L.MELEE_WEAPON_SKILL_TOOLTIP_SUB) - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + + BCS_AddTooltip(statFrame) end function BCS:SetRangedWeaponSkill(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.WEAPON_SKILL_COLON) + -- If no ranged attack then set to n/a if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then text:SetText(NOT_APPLICABLE) return end + text:SetText(format("%d", BCS:GetRangedWeaponSkill())) + statFrame.tooltip = format(L.RANGED_WEAPON_SKILL_TOOLTIP) statFrame.tooltipSubtext = format(L.RANGED_WEAPON_SKILL_TOOLTIP_SUB) - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + + BCS_AddTooltip(statFrame) end function BCS:SetSpellCritChance(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") local _, class = UnitClass("player") + label:SetText(L.SPELL_CRIT_COLON) local generic = BCS:GetSpellCritChance() @@ -822,6 +725,7 @@ function BCS:SetSpellCritChance(statFrame) local total4 = generic + spell4 local total5 = generic + spell5 local total6 = generic + spell6 + if total1 > 100 then total1 = 100 end if total2 > 100 then total2 = 100 end if total3 > 100 then total3 = 100 end @@ -830,18 +734,24 @@ function BCS:SetSpellCritChance(statFrame) if total6 > 100 then total6 = 100 end text:SetText(format("%.2f%%", generic)) - if class == "WARLOCK" and spell1 > 0 then -- warlock spells that can crit are all destruction so just add this to generic + + -- warlock spells that can crit are all destruction so just add this to generic + if class == "WARLOCK" and spell1 > 0 then text:SetText(format("%.2f%%", generic + spell1)) - elseif class == "PRIEST" and spell3 > 0 and spell2 > 0 then -- if priest have both talents add lowest to generic cos there will be no more spells left that can crit + + -- if priest have both talents add lowest to generic cos there will be no more spells left that can crit + elseif class == "PRIEST" and spell3 > 0 and spell2 > 0 then if spell2 < spell3 then text:SetText(format("%.2f%%", generic + spell2)) elseif spell2 >= spell3 then text:SetText(format("%.2f%%", generic + spell3)) end end - frame.tooltip = format(L.SPELL_CRIT_TOOLTIP) - frame.tooltipSubtext = format(L.SPELL_CRIT_TOOLTIP_SUB) - frame:SetScript("OnEnter", function() + + statFrame.tooltip = format(L.SPELL_CRIT_TOOLTIP) + statFrame.tooltipSubtext = format(L.SPELL_CRIT_TOOLTIP_SUB) + + statFrame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetText(this.tooltip) GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) @@ -926,11 +836,13 @@ function BCS:SetSpellCritChance(statFrame) end if spell5 > 0 then GameTooltip:AddLine(format("Healing spells: %.2f%%", total5)) - end + end end + GameTooltip:Show() end) - frame:SetScript("OnLeave", function() + + statFrame:SetScript("OnLeave", function() GameTooltip:Hide() end) end @@ -938,45 +850,50 @@ end function BCS:SetRangedCritChance(statFrame) local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.RANGED_CRIT_COLON) + -- If no ranged attack then set to n/a if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then text:SetText(NOT_APPLICABLE) return end + local crit = BCS:GetRangedCritChance() + -- apply skill difference modifier local skill = BCS:GetRangedWeaponSkill() local level = UnitLevel("player") - -- apply skill difference modifier local skillDiff = skill - (level*5) + if (skill >= (level*5)) then crit = crit + (skillDiff * 0.04) else crit = crit + (skillDiff * 0.2) end - if crit < 0 then crit = 0 end + + if crit < 0 then + crit = 0 + end + text:SetText(format("%.2f%%", crit)) + statFrame.tooltip = (L.RANGED_CRIT_TOOLTIP) statFrame.tooltipSubtext = (L.RANGED_CRIT_TOOLTIP_SUB) - statFrame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - statFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + + BCS_AddTooltip(statFrame) end function BCS:SetHealing(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") - local damageAndHealing = BCS:GetSpellPower() local healingOnly, treebonus, ironclad = BCS:GetHealingPower() local total = damageAndHealing + healingOnly + local tooltipExtra + + if ironclad > 0 then + tooltipExtra = format("Healing power from Ironclad: %d", ironclad) + end if treebonus and aura <= treebonus then total = total + treebonus @@ -988,341 +905,192 @@ function BCS:SetHealing(statFrame) text:SetText(format("%d",total)) if healingOnly ~= 0 then - frame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (total), damageAndHealing, healingOnly) + statFrame.tooltip = format(L.SPELL_HEALING_POWER_SECONDARY_TOOLTIP, (total), damageAndHealing, healingOnly) else - frame.tooltip = format(L.SPELL_HEALING_POWER_TOOLTIP, (total)) + statFrame.tooltip = format(L.SPELL_HEALING_POWER_TOOLTIP, (total)) end - - frame.tooltipSubtext = format(L.SPELL_HEALING_POWER_TOOLTIP_SUB) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - if ironclad > 0 then - GameTooltip:AddLine(format("Healing power from Ironclad: %d", ironclad)) - end - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + statFrame.tooltipSubtext = format(L.SPELL_HEALING_POWER_TOOLTIP_SUB) + + BCS_AddTooltip(statFrame, tooltipExtra) end function BCS:SetManaRegen(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(L.MANA_REGEN_COLON) + -- if not a mana user and not a druid set to N/A local _,class = UnitClass("player") if (UnitPowerType("player") ~= 0 and not(class=="DRUID"))then text:SetText(NOT_APPLICABLE) - frame.tooltip = nil - else + statFrame.tooltip = nil + return + end + local base, casting, mp5 = BCS:GetManaRegen() local mp2 = mp5 * 0.4 local totalRegen = base + mp2 local totalRegenWhileCasting = (casting / 100) * base + mp2 - - text:SetText(format("%d (%d)", totalRegen, totalRegenWhileCasting)) - frame.tooltip = format(L.SPELL_MANA_REGEN_TOOLTIP, totalRegen, totalRegenWhileCasting) - frame.tooltipSubtext = format(L.SPELL_MANA_REGEN_TOOLTIP_SUB, base, casting, mp5, mp2) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - end + + text:SetText(format("%d (%d)", totalRegen, totalRegenWhileCasting)) + + statFrame.tooltip = format(L.SPELL_MANA_REGEN_TOOLTIP, totalRegen, totalRegenWhileCasting) + statFrame.tooltipSubtext = format(L.SPELL_MANA_REGEN_TOOLTIP_SUB, base, casting, mp5, mp2) + + BCS_AddTooltip(statFrame) end function BCS:SetDodge(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") label:SetText(L.DODGE_COLON) text:SetText(format("%.2f%%", GetDodgeChance())) - frame.tooltip = format(L.PLAYER_DODGE_TOOLTIP) - frame.tooltipSubtext = format(L.PLAYER_DODGE_TOOLTIP_SUB) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + statFrame.tooltip = format(L.PLAYER_DODGE_TOOLTIP) + statFrame.tooltipSubtext = format(L.PLAYER_DODGE_TOOLTIP_SUB) + + BCS_AddTooltip(statFrame) end function BCS:SetParry(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") label:SetText(L.PARRY_COLON) text:SetText(format("%.2f%%", GetParryChance())) - frame.tooltip = format(L.PLAYER_PARRY_TOOLTIP) - frame.tooltipSubtext = format(L.PLAYER_PARRY_TOOLTIP_SUB) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + statFrame.tooltip = format(L.PLAYER_PARRY_TOOLTIP) + statFrame.tooltipSubtext = format(L.PLAYER_PARRY_TOOLTIP_SUB) + + BCS_AddTooltip(statFrame) end function BCS:SetBlock(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") local blockChance = GetBlockChance() + local tooltipExtra + + if blockChance > 0 then + tooltipExtra = "Block Value: "..BCS:GetBlockValue() + end label:SetText(L.BLOCK_COLON) text:SetText(format("%.2f%%", blockChance )) - frame.tooltip = format(L.PLAYER_BLOCK_TOOLTIP) - frame.tooltipSubtext = format(L.PLAYER_BLOCK_TOOLTIP_SUB) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - if blockChance > 0 then - GameTooltip:AddLine("Block Value: "..BCS:GetBlockValue()) - end - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + statFrame.tooltip = format(L.PLAYER_BLOCK_TOOLTIP) + statFrame.tooltipSubtext = format(L.PLAYER_BLOCK_TOOLTIP_SUB) + + BCS_AddTooltip(statFrame, tooltipExtra) end + function BCS:SetTotalAvoidance(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + -- apply skill modifier local base, mod = UnitDefense("player") local skillDiff = base + mod - UnitLevel("player") * 5 local missChance = 5 + skillDiff * 0.04 + local total = missChance + GetBlockChance() + GetParryChance() + GetDodgeChance() - local total = missChance + (GetBlockChance() + GetParryChance() + GetDodgeChance()) - --if total > 100 then total = 100 end - if total < 0 then total = 0 end + if total < 0 then + total = 0 + end label:SetText(L.TOTAL_COLON) text:SetText(format("%.2f%%", total)) - frame.tooltip = format(L.TOTAL_AVOIDANCE_TOOLTIP) - frame.tooltipSubtext = format(L.TOTAL_AVOIDANCE_TOOLTIP_SUB) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + statFrame.tooltip = format(L.TOTAL_AVOIDANCE_TOOLTIP) + statFrame.tooltipSubtext = format(L.TOTAL_AVOIDANCE_TOOLTIP_SUB) + + BCS_AddTooltip(statFrame) end function BCS:SetDefense(statFrame) local base, modifier = UnitDefense("player") - - local frame = statFrame local label = getglobal(statFrame:GetName() .. "Label") local text = getglobal(statFrame:GetName() .. "StatText") + local posBuff = 0 + local negBuff = 0 label:SetText(TEXT(DEFENSE_COLON)) - local posBuff = 0 - local negBuff = 0 if (modifier > 0) then posBuff = modifier elseif (modifier < 0) then negBuff = modifier end - PaperDollFormatStat(DEFENSE_COLON, base, posBuff, negBuff, frame, text) - frame.tooltip = format(L.DEFENSE_TOOLTIP) - frame.tooltipSubtext = format(L.DEFENSE_TOOLTIP_SUB) - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) + + PaperDollFormatStat(DEFENSE_COLON, base, posBuff, negBuff, statFrame, text) + statFrame.tooltip = format(L.DEFENSE_TOOLTIP) + statFrame.tooltipSubtext = format(L.DEFENSE_TOOLTIP_SUB) + + BCS_AddTooltip(statFrame) end function BCS:SetRangedDamage(statFrame) local label = getglobal(statFrame:GetName() .. "Label") local damageText = getglobal(statFrame:GetName() .. "StatText") - local damageFrame = statFrame + label:SetText(TEXT(DAMAGE_COLON)) + -- If no ranged attack then set to n/a if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then damageText:SetText(NOT_APPLICABLE) - damageFrame.damage = nil + statFrame.damage = nil return end - damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) - damageFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - - local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") - local displayMin = max(floor(minDamage), 1) - local displayMax = max(ceil(maxDamage), 1) - - 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) - local damagePerSecond = (max(fullDamage, 1) / rangedAttackSpeed) - local tooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) - if (totalBonus == 0) then - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(displayMin .. " - " .. displayMax) - else - damageText:SetText(displayMin .. "-" .. displayMax) - end - else - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - local color - if (totalBonus > 0) then - color = colorPos - else - color = colorNeg - end - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") - else - damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|r") - end - if (physicalBonusPos > 0) then - tooltip = tooltip .. colorPos .. " +" .. physicalBonusPos .. "|r" - end - if (physicalBonusNeg < 0) then - tooltip = tooltip .. colorNeg .. " " .. physicalBonusNeg .. "|r" - end - if (percent > 1) then - tooltip = tooltip .. colorPos .. " x" .. floor(percent * 100 + 0.5) .. "%|r" - elseif (percent < 1) then - tooltip = tooltip .. colorNeg .. " x" .. floor(percent * 100 + 0.5) .. "%|r" - end - damageFrame.tooltip = tooltip .. " " .. format(TEXT(DPS_TEMPLATE), damagePerSecond) - end - damageFrame.attackSpeed = rangedAttackSpeed - damageFrame.damage = tooltip - damageFrame.dps = damagePerSecond + BCS_AddDamageTooltip(damageText, statFrame, nil, nil, true) end -function BCS:SetRangedAttackSpeed(startFrame) - local label = getglobal(startFrame:GetName() .. "Label") - local damageText = getglobal(startFrame:GetName() .. "StatText") - local damageFrame = startFrame +function BCS:SetRangedAttackSpeed(statFrame) + local label = getglobal(statFrame:GetName() .. "Label") + local damageText = getglobal(statFrame:GetName() .. "StatText") + label:SetText(TEXT(SPEED) .. ":") + -- If no ranged attack then set to n/a if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then damageText:SetText(NOT_APPLICABLE) - damageFrame.damage = nil + statFrame.damage = nil return end - damageFrame:SetScript("OnEnter", CharacterRangedDamageFrame_OnEnter) - damageFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - - local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent = UnitRangedDamage("player") - local displayMin = max(floor(minDamage), 1) - local displayMax = max(ceil(maxDamage), 1) - - 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) - local damagePerSecond = (max(fullDamage, 1) / rangedAttackSpeed) - local tooltip = max(floor(minDamage), 1) .. " - " .. max(ceil(maxDamage), 1) - - if (totalBonus == 0) then - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(displayMin .. " - " .. displayMax) - else - damageText:SetText(displayMin .. "-" .. displayMax) - end - else - local colorPos = "|cff20ff20" - local colorNeg = "|cffff2020" - local color - if (totalBonus > 0) then - color = colorPos - else - color = colorNeg - end - if ((displayMin < 100) and (displayMax < 100)) then - damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r") - else - damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|r") - end - if (physicalBonusPos > 0) then - tooltip = tooltip .. colorPos .. " +" .. physicalBonusPos .. "|r" - end - if (physicalBonusNeg < 0) then - tooltip = tooltip .. colorNeg .. " " .. physicalBonusNeg .. "|r" - end - if (percent > 1) then - tooltip = tooltip .. colorPos .. " x" .. floor(percent * 100 + 0.5) .. "%|r" - elseif (percent < 1) then - tooltip = tooltip .. colorNeg .. " x" .. floor(percent * 100 + 0.5) .. "%|r" - end - damageFrame.tooltip = tooltip .. " " .. format(TEXT(DPS_TEMPLATE), damagePerSecond) - end - damageText:SetText(format("%.2f", rangedAttackSpeed)) + BCS_AddDamageTooltip(damageText, statFrame, nil, nil, true) - damageFrame.attackSpeed = rangedAttackSpeed - damageFrame.damage = tooltip - damageFrame.dps = damagePerSecond + damageText:SetText(format("%.2f",UnitRangedDamage("player"))) end function BCS:SetRangedAttackPower(statFrame) - local frame = statFrame local text = getglobal(statFrame:GetName() .. "StatText") local label = getglobal(statFrame:GetName() .. "Label") + label:SetText(TEXT(ATTACK_POWER_COLON)) + -- If no ranged attack then set to n/a if UnitHasRelicSlot("player") or not (GetInventoryItemLink("player",18)) then text:SetText(NOT_APPLICABLE) - frame.tooltip = nil + statFrame.tooltip = nil return end + if ( HasWandEquipped() ) then text:SetText("--"); - frame.tooltip = nil; + statFrame.tooltip = nil; return; end - local base, posBuff, negBuff = UnitRangedAttackPower("player") - PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, frame, text) - frame.tooltipSubtext = format(RANGED_ATTACK_POWER_TOOLTIP, base / ATTACK_POWER_MAGIC_NUMBER) + local base, posBuff, negBuff = UnitRangedAttackPower("player") local tooltipText = HIGHLIGHT_FONT_COLOR_CODE .. RANGED_ATTACK_POWER .. " " local effectiveStat = base + posBuff + negBuff + + PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, statFrame, text) + statFrame.tooltipSubtext = format(RANGED_ATTACK_POWER_TOOLTIP, base / ATTACK_POWER_MAGIC_NUMBER) + if ((posBuff == 0) and (negBuff == 0)) then text:SetText(effectiveStat) statFrame.tooltip = tooltipText .. base .. FONT_COLOR_CODE_CLOSE @@ -1348,21 +1116,13 @@ function BCS:SetRangedAttackPower(statFrame) text:SetText(GREEN_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE) end end + label:SetText(TEXT(ATTACK_POWER_COLON)) - PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, frame, text) - frame.tooltipSubtext= format(RANGED_ATTACK_POWER_TOOLTIP, max((base + posBuff + negBuff), 0) / ATTACK_POWER_MAGIC_NUMBER) - if frame.tooltip then - frame:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(this.tooltip) - GameTooltip:AddLine(this.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - GameTooltip:Show() - end) - frame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - end + PaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, statFrame, text) + statFrame.tooltipSubtext = format(RANGED_ATTACK_POWER_TOOLTIP, max((base + posBuff + negBuff), 0) / ATTACK_POWER_MAGIC_NUMBER) + + BCS_AddTooltip(statFrame) end function BCS:UpdatePaperdollStats(prefix, index) @@ -1443,10 +1203,12 @@ local function PlayerStatFrameLeftDropDown_OnClick() BCS.needScanTalents = true BCS.needScanAuras = true BCS.needScanSkills = true + UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) IndexLeft = this.value BCSConfig["DropdownLeft"] = IndexLeft BCS:UpdatePaperdollStats("PlayerStatFrameLeft", this.value) + BCS.needScanGear = false BCS.needScanTalents = false BCS.needScanAuras = false @@ -1458,10 +1220,12 @@ local function PlayerStatFrameRightDropDown_OnClick() BCS.needScanTalents = true BCS.needScanAuras = true BCS.needScanSkills = true + UIDropDownMenu_SetSelectedValue(getglobal(this.owner), this.value) IndexRight = this.value BCSConfig["DropdownRight"] = IndexRight BCS:UpdatePaperdollStats("PlayerStatFrameRight", this.value) + BCS.needScanGear = false BCS.needScanTalents = false BCS.needScanAuras = false @@ -1513,76 +1277,3 @@ function PlayerStatFrameRightDropDown_OnLoad() UIDropDownMenu_SetWidth(99, this) UIDropDownMenu_JustifyText("LEFT") end - ---pfUI.api.strsplit -function hcstrsplit(delimiter, subject) - if not subject then - return nil - end - local delimiter, fields = delimiter or ":", {} - local pattern = string.format("([^%s]+)", delimiter) - string.gsub(subject, pattern, function(c) - fields[table.getn(fields) + 1] = c - end) - return unpack(fields) -end ---[[ ---Update announcing code taken from pfUI -local major, minor, fix = hcstrsplit(".", tostring(GetAddOnMetadata("BetterCharacterStats", "Version"))) - -local alreadyshown = false -local localversion = tonumber(major * 10000 + minor * 100 + fix) -local remoteversion = tonumber(bcsupdateavailable) or 0 -local loginchannels = { "BATTLEGROUND", "RAID", "GUILD", "PARTY" } -local groupchannels = { "BATTLEGROUND", "RAID", "PARTY" } - -bcsupdater = CreateFrame("Frame") -bcsupdater:RegisterEvent("CHAT_MSG_ADDON") -bcsupdater:RegisterEvent("PLAYER_ENTERING_WORLD") -bcsupdater:RegisterEvent("PARTY_MEMBERS_CHANGED") -bcsupdater:SetScript("OnEvent", function() - if event == "CHAT_MSG_ADDON" and arg1 == "bcs" then - local v, remoteversion = hcstrsplit(":", arg2) - local remoteversion = tonumber(remoteversion) - if v == "VERSION" and remoteversion then - if remoteversion > localversion then - bcsupdateavailable = remoteversion - if not alreadyshown then - DEFAULT_CHAT_FRAME:AddMessage("|cffffffffBetterCharacterStats|r New version available! https://github.com/Lexiebean/BetterCharacterStats") - alreadyshown = true - end - end - end - --This is a little check that I can use to see if people are actually using the addon. - if v == "PING?" then - for _, chan in pairs(loginchannels) do - SendAddonMessage("bcs", "PONG!:" .. GetAddOnMetadata("BetterCharacterStats", "Version"), chan) - end - end - if v == "PONG!" then - --print(arg1 .." "..arg2.." "..arg3.." "..arg4) - end - end - - if event == "PARTY_MEMBERS_CHANGED" then - local groupsize = GetNumRaidMembers() > 0 and GetNumRaidMembers() or GetNumPartyMembers() > 0 and GetNumPartyMembers() or 0 - if (this.group or 0) < groupsize then - for _, chan in pairs(groupchannels) do - SendAddonMessage("bcs", "VERSION:" .. localversion, chan) - end - end - this.group = groupsize - end - - if event == "PLAYER_ENTERING_WORLD" then - if not alreadyshown and localversion < remoteversion then - DEFAULT_CHAT_FRAME:AddMessage("|cffffffffBetterCharacterStats|r New version available! https://github.com/Lexiebean/BetterCharacterStats") - bcsupdateavailable = localversion - alreadyshown = true - end - - for _, chan in pairs(loginchannels) do - SendAddonMessage("bcs", "VERSION:" .. localversion, chan) - end - end -end)]] From a5a44d30d0dd190cf45f0648ad5f1da9040662b4 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sat, 7 Dec 2024 04:14:18 +0300 Subject: [PATCH 36/39] ranged crit from shoulder enchant --- Localization.lua | 2 +- helper.lua | 192 ++++++++++++++++++----------------------------- 2 files changed, 72 insertions(+), 122 deletions(-) diff --git a/Localization.lua b/Localization.lua index 96a13aa..bafa9c0 100644 --- a/Localization.lua +++ b/Localization.lua @@ -1,7 +1,7 @@ BCS = BCS or {} BCS["L"] = { - + ["%+(%d+)%% Critical Strike"] = "%+(%d+)%% Critical Strike", ["([%d.]+)%% chance to crit"] = "([%d.]+)%% chance to crit", ["^Set: Improves your chance to hit by (%d)%%."] = "^Set: Improves your chance to hit by (%d)%%.", diff --git a/helper.lua b/helper.lua index 132d229..d3fe64e 100644 --- a/helper.lua +++ b/helper.lua @@ -440,15 +440,32 @@ function BCS:GetRangedCritChance() local vallvl1 = 0 local vallvl60 = 0 local classrate = 0 - if class == "MAGE" then vallvl1 = 12.9 vallvl60 = 20 - elseif class == "ROGUE" then vallvl1 = 2.2 vallvl60 = 29 - elseif class == "HUNTER" then vallvl1 = 3.5 vallvl60 = 53 - elseif class == "PRIEST" then vallvl1 = 11 vallvl60 = 20 - elseif class == "WARLOCK" then vallvl1 = 8.4 vallvl60 = 20 - elseif class == "WARRIOR" then vallvl1 = 3.9 vallvl60 = 20 - else return crit end + + if class == "MAGE" then + vallvl1 = 12.9 + vallvl60 = 20 + elseif class == "ROGUE" then + vallvl1 = 2.2 + vallvl60 = 29 + elseif class == "HUNTER" then + vallvl1 = 3.5 + vallvl60 = 53 + elseif class == "PRIEST" then + vallvl1 = 11 + vallvl60 = 20 + elseif class == "WARLOCK" then + vallvl1 = 8.4 + vallvl60 = 20 + elseif class == "WARRIOR" then + vallvl1 = 3.9 + vallvl60 = 20 + else + return crit + end + classrate = vallvl1 * (60 - UnitLevel("player")) / 59 + vallvl60 * (UnitLevel("player") - 1) / 59 crit = agility / classrate + if BCS.needScanTalents then BCScache["talents"].ranged_crit = 0 --scan talents @@ -495,6 +512,11 @@ function BCS:GetRangedCritChance() if value then BCScache["gear"].ranged_crit = BCScache["gear"].ranged_crit + tonumber(value) end + -- Might of the Scourge (shoulder enchant) + _,_, value = strfind(left:GetText(), L["%+(%d+)%% Critical Strike"]) + if value then + BCScache["gear"].ranged_crit = BCScache["gear"].ranged_crit + tonumber(value) + end _,_, value = strfind(left:GetText(), "(.+) %(%d/%d%)") if value then @@ -552,11 +574,17 @@ function BCS:GetRangedCritChance() end end end - if class == "MAGE" then crit = crit + 3.2 - elseif class == "PRIEST" then crit = crit + 3 - elseif class == "WARLOCK" then crit = crit + 2 + + if class == "MAGE" then + crit = crit + 3.2 + elseif class == "PRIEST" then + crit = crit + 3 + elseif class == "WARLOCK" then + crit = crit + 2 end + crit = crit + BCScache["gear"].ranged_crit + BCScache["talents"].ranged_crit + BCScache["auras"].ranged_crit + return crit end @@ -735,92 +763,10 @@ function BCS:GetSpellCritChance() end function BCS:GetSpellCritFromClass(class) - if not class then return 0, 0, 0, 0, 0, 0 end - --[[ - Warlock: - Devastation: + 1/2/3/4/5 % - Shadowbolt - Immolate - Searing Pain - Soulfire - Hellfire ? - Rain of Fire ? - Shadowburn - is there more? - Improved Searing Pain: + 2/4/6/8/10 % - Searing Pain - Mage: - Arcane Impact: + 2/4/6 % - Arcane Explosion - Arcane Missiles - Incinerate: + 2/4 % -? - Fireblast - Scorch - Improved Flamestrike: + 5/10/15 % - Flamestrike - Critical Mass: + 2/4/6 % - Fireball - Fireblast - Scorch - Flamestrike - Pyroblast - Blast Wave - Combustion: - +10% +20% +30% fire spell crit and so on untill 3 fire spell crits; DOES have stacks; - Shatter: - "Increases the critical strike chance of all your spells against frozen targets by (%d+)%%." - + to all spells agains FROZEN target - Paladin: - Holy power: + 1/2/3/4/5 % - Holy Light - Flash of Light - Holy Shock - Lay on Hands ? - Divine Favor: 100% while active - Holy Light - Flash of Light - Holy Shock - Druid: - Improved Moonfire: + 2/4/6/8/10 % - Moonfire - Improved Regrowth: + 10/20/30/40/50 % - Regrowth - Shaman: - Call of Thunder: + 1/2/4/6 % ? - Lightning Bolt - Chain Lightning - Tidal Mastery: + 1/2/3/4/5 % - Lightning Bolt - Chain Lightning - Lesser Healing Wave - Healing Wave - Chain Heal - Lightning shield - Stormstrike ? - (baseline?) Elemental Mastery: 100% while active (fire, frost, nature damage spells) - Lightning Bolt - Chain Lightning - Earth Shock - Flame Shock - Frost Shock - Fire Nova - Priest: - Force of Will: + 1/2/3/4/5 % - Smite - Holy Fire - Mind Blast - Pain Spike - Mana Burn - Holy Nova - Holy Specialization: + 1/2/3/4/5 % - Lesser Heal - Heal - Flash Heal - Greater Heal - Prayer of Healing - Smite - Desperate Prayer - ]] + if not class then + return 0, 0, 0, 0, 0, 0 + end + if class == "PALADIN" then --scan talents if BCS.needScanTalents or BCS.needScanAuras then @@ -854,8 +800,9 @@ function BCS:GetSpellCritFromClass(class) end return BCScache["talents"].paladin_holy_light, - BCScache["talents"].paladin_flash, - BCScache["talents"].paladin_shock, 0, 0, 0 + BCScache["talents"].paladin_flash, + BCScache["talents"].paladin_shock, 0, 0, 0 + elseif class == "DRUID" then --scan talents if BCS.needScanTalents then @@ -888,7 +835,8 @@ function BCS:GetSpellCritFromClass(class) end return BCScache["talents"].druid_moonfire, - BCScache["talents"].druid_regrowth, 0, 0, 0, 0 + BCScache["talents"].druid_regrowth, 0, 0, 0, 0 + elseif class == "WARLOCK" then --scan talents if BCS.needScanTalents then @@ -922,7 +870,8 @@ function BCS:GetSpellCritFromClass(class) end return BCScache["talents"].warlock_destruction_spells, - BCScache["talents"].warlock_searing_pain, 0, 0, 0, 0 + BCScache["talents"].warlock_searing_pain, 0, 0, 0, 0 + elseif class == "MAGE" then --scan talents if BCS.needScanTalents or BCS.needScanAuras then @@ -982,18 +931,20 @@ function BCS:GetSpellCritFromClass(class) local _, _, value = BCS:GetPlayerAura(L["Increases critical strike chance from Fire damage spells by (%d+)%%."]) -- Combustion if value then - BCScache["talents"].mage_fire_spells = BCScache["talents"].mage_fire_spells + value - BCScache["talents"].mage_fireblast = BCScache["talents"].mage_fireblast + value - BCScache["talents"].mage_flamestrike = BCScache["talents"].mage_flamestrike + value - BCScache["talents"].mage_scorch = BCScache["talents"].mage_scorch + value + BCScache["talents"].mage_fire_spells = BCScache["talents"].mage_fire_spells + tonumber(value) + BCScache["talents"].mage_fireblast = BCScache["talents"].mage_fireblast + tonumber(value) + BCScache["talents"].mage_flamestrike = BCScache["talents"].mage_flamestrike + tonumber(value) + BCScache["talents"].mage_scorch = BCScache["talents"].mage_scorch + tonumber(value) end end + return BCScache["talents"].mage_arcane_spells, - BCScache["talents"].mage_fire_spells, - BCScache["talents"].mage_fireblast, - BCScache["talents"].mage_scorch, - BCScache["talents"].mage_flamestrike, - BCScache["talents"].mage_shatter + BCScache["talents"].mage_fire_spells, + BCScache["talents"].mage_fireblast, + BCScache["talents"].mage_scorch, + BCScache["talents"].mage_flamestrike, + BCScache["talents"].mage_shatter + elseif class == "PRIEST" then if BCS.needScanTalents then BCScache["talents"].priest_holy_spells = 0 @@ -1061,7 +1012,11 @@ function BCS:GetSpellCritFromClass(class) local holySpells = BCScache["talents"].priest_holy_spells + BCScache["gear"].priest_holy_spells - return holySpells, BCScache["talents"].priest_discipline_spells, BCScache["talents"].priest_offensive_spells, BCScache["gear"].priest_prayer, 0, 0 + return holySpells, + BCScache["talents"].priest_discipline_spells, + BCScache["talents"].priest_offensive_spells, + BCScache["gear"].priest_prayer, 0, 0 + elseif class == "SHAMAN" then if BCS.needScanTalents then BCScache["talents"].shaman_lightning_bolt = 0 @@ -1110,12 +1065,15 @@ function BCS:GetSpellCritFromClass(class) BCScache["auras"].shaman_firefrost_spells = 100 end end + local lightningBolt = BCScache["auras"].shaman_lightning_bolt + BCScache["talents"].shaman_lightning_bolt local chainLightning = BCScache["auras"].shaman_chain_lightning + BCScache["talents"].shaman_chain_lightning + return lightningBolt, chainLightning, - BCScache["talents"].shaman_lightning_shield, - BCScache["auras"].shaman_firefrost_spells, - BCScache["talents"].shaman_healing_spells, 0 + BCScache["talents"].shaman_lightning_shield, + BCScache["auras"].shaman_firefrost_spells, + BCScache["talents"].shaman_healing_spells, 0 + else return 0, 0, 0, 0, 0, 0 end @@ -1573,14 +1531,6 @@ function BCS:GetHealingPower() if healPowerFromAura then BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) end - - -- ? - -- already included in GetSpellPower - --[[_, _, healPowerFromAura = BCS:GetPlayerAura("Increases damage and healing done by magical spells and effects by up to (%d+).") - if healPowerFromAura then - BCScache["auras"].healing = BCScache["auras"].healing + tonumber(healPowerFromAura) - end]] - --Dreamshard Elixir _, _, healPowerFromAura = BCS:GetPlayerAura("Healing done is increased by up to (%d+)") if healPowerFromAura then From 58857a8ab3f3c29eedd7f8de101d10fb0611f501 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sun, 5 Jan 2025 18:35:34 +0300 Subject: [PATCH 37/39] elemental devastation aura --- helper.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/helper.lua b/helper.lua index d3fe64e..7b92a2d 100644 --- a/helper.lua +++ b/helper.lua @@ -397,6 +397,11 @@ function BCS:GetSpellHitRating() if hitFromAura then BCScache["auras"].spell_hit = BCScache["auras"].spell_hit + tonumber(hitFromAura) end + -- Elemental Devastation + _, _, hitFromAura = BCS:GetPlayerAura("Increases your chance to hit with spells by (%d+)%%") + if hitFromAura then + BCScache["auras"].spell_hit = BCScache["auras"].spell_hit + tonumber(hitFromAura) + end end hit = BCScache["gear"].spell_hit + BCScache["talents"].spell_hit + BCScache["auras"].spell_hit hit_fire = BCScache["talents"].spell_hit_fire From 7358eb69aac6eb589c4a7bd05e38ae9fa65ee6dd Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Sun, 5 Jan 2025 19:36:35 +0300 Subject: [PATCH 38/39] removed ChatThrottleLib --- BetterCharacterStats.lua | 4 +- BetterCharacterStats.toc | 5 +- ChatThrottleLib/ChatThrottleLib.lua | 464 ---------------------------- 3 files changed, 4 insertions(+), 469 deletions(-) delete mode 100644 ChatThrottleLib/ChatThrottleLib.lua diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index f497832..6192d17 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -230,7 +230,7 @@ sender:SetScript("OnEvent", function() local player = UnitName("player") if event == "PLAYER_AURAS_CHANGED" then if BCS:GetPlayerAura("Tree of Life Aura") then - ChatThrottleLib:SendAddonMessage("BULK","bcs", "TREE"..","..player, "PARTY") + SendAddonMessage("bcs", "TREE"..","..player, "PARTY") --BCS:Print("sent tree request") end end @@ -239,7 +239,7 @@ sender:SetScript("OnEvent", function() if name ~= player then local _, treebonus = BCS:GetHealingPower() if not amount and type == "TREE" and treebonus then - ChatThrottleLib:SendAddonMessage("BULK","bcs", "TREE"..","..player..","..treebonus, "PARTY") + SendAddonMessage("bcs", "TREE"..","..player..","..treebonus, "PARTY") --BCS:Print("sent tree response, amount="..treebonus) end end diff --git a/BetterCharacterStats.toc b/BetterCharacterStats.toc index ada335f..37c9c4f 100644 --- a/BetterCharacterStats.toc +++ b/BetterCharacterStats.toc @@ -2,7 +2,6 @@ ## Title: BetterCharacterStats ## Author: moh, Bennylava, |cffbe5effLexie|r, Spit, Pepopo ## Version: 1.12.6 -## SavedVariablesPerCharacter: BCSConfig bcsupdateavailable BCScache +## SavedVariablesPerCharacter: BCSConfig BCScache -BetterCharacterStats.xml -ChatThrottleLib\ChatThrottleLib.lua \ No newline at end of file +BetterCharacterStats.xml \ No newline at end of file diff --git a/ChatThrottleLib/ChatThrottleLib.lua b/ChatThrottleLib/ChatThrottleLib.lua deleted file mode 100644 index 04efd9b..0000000 --- a/ChatThrottleLib/ChatThrottleLib.lua +++ /dev/null @@ -1,464 +0,0 @@ --- --- ChatThrottleLib by Mikk --- --- Manages AddOn chat output to keep player from getting kicked off. --- --- ChatThrottleLib.SendChatMessage/.SendAddonMessage functions that accept --- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage. --- --- Priorities get an equal share of available bandwidth when fully loaded. --- Communication channels are separated on extension+chattype+destination and --- get round-robinned. (Destination only matters for whispers and channels, --- obviously) --- --- Will install hooks for SendChatMessage and SendAdd[Oo]nMessage to measure --- bandwidth bypassing the library and use less bandwidth itself. --- --- --- Fully embeddable library. Just copy this file into your addon directory, --- add it to the .toc, and it's done. --- --- Can run as a standalone addon also, but, really, just embed it! :-) --- - -local CTL_VERSION = 13 - -local MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800. -local MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff - -local BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now. - -local MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value - -if(ChatThrottleLib and ChatThrottleLib.version>=CTL_VERSION) then - -- There's already a newer (or same) version loaded. Buh-bye. - return; -end - - - -if(not ChatThrottleLib) then - ChatThrottleLib = {} -end - -local ChatThrottleLib = ChatThrottleLib -local strlen = strlen -local setmetatable = setmetatable -local getn = getn -local tremove = tremove -local tinsert = tinsert -local tostring = tostring -local GetTime = GetTime -local format = format - -ChatThrottleLib.version=CTL_VERSION; - - ------------------------------------------------------------------------ --- Double-linked ring implementation - -local Ring = {} -local RingMeta = { __index=Ring } - -function Ring:New() - local ret = {} - setmetatable(ret, RingMeta) - return ret; -end - -function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position) - if(self.pos) then - obj.prev = self.pos.prev; - obj.prev.next = obj; - obj.next = self.pos; - obj.next.prev = obj; - else - obj.next = obj; - obj.prev = obj; - self.pos = obj; - end -end - -function Ring:Remove(obj) - obj.next.prev = obj.prev; - obj.prev.next = obj.next; - if(self.pos == obj) then - self.pos = obj.next; - if(self.pos == obj) then - self.pos = nil; - end - end -end - - - ------------------------------------------------------------------------ --- Recycling bin for pipes (kept in a linked list because that's --- how they're worked with in the rotating rings; just reusing members) - -ChatThrottleLib.PipeBin = { count=0 } - -function ChatThrottleLib.PipeBin:Put(pipe) - for i=getn(pipe),1,-1 do - tremove(pipe, i); - end - pipe.prev = nil; - pipe.next = self.list; - self.list = pipe; - self.count = self.count+1; -end - -function ChatThrottleLib.PipeBin:Get() - if(self.list) then - local ret = self.list; - self.list = ret.next; - ret.next=nil; - self.count = self.count - 1; - return ret; - end - return {}; -end - -function ChatThrottleLib.PipeBin:Tidy() - if(self.count < 25) then - return; - end - - if(self.count > 100) then - n=self.count-90; - else - n=10; - end - for i=2,n do - self.list = self.list.next; - end - local delme = self.list; - self.list = self.list.next; - delme.next = nil; -end - - - - ------------------------------------------------------------------------ --- Recycling bin for messages - -ChatThrottleLib.MsgBin = {} - -function ChatThrottleLib.MsgBin:Put(msg) - msg.text = nil; - tinsert(self, msg); -end - -function ChatThrottleLib.MsgBin:Get() - local ret = tremove(self, getn(self)); - if(ret) then return ret; end - return {}; -end - -function ChatThrottleLib.MsgBin:Tidy() - if(getn(self)<50) then - return; - end - if(getn(self)>150) then -- "can't happen" but ... - for n=getn(self),120,-1 do - tremove(self,n); - end - else - for n=getn(self),getn(self)-20,-1 do - tremove(self,n); - end - end -end - - ------------------------------------------------------------------------ --- ChatThrottleLib:Init --- Initialize queues, set up frame for OnUpdate, etc - - -function ChatThrottleLib:Init() - - -- Set up queues - if(not self.Prio) then - self.Prio = {} - self.Prio["ALERT"] = { ByName={}, Ring = Ring:New(), avail=0 }; - self.Prio["NORMAL"] = { ByName={}, Ring = Ring:New(), avail=0 }; - self.Prio["BULK"] = { ByName={}, Ring = Ring:New(), avail=0 }; - end - - -- v4: total send counters per priority - for _,Prio in pairs(self.Prio) do - Prio.nTotalSent = Prio.nTotalSent or 0; - end - - self.avail = self.avail or 0; -- v5 - self.nTotalSent = self.nTotalSent or 0; -- v5 - - - -- Set up a frame to get OnUpdate events - if(not self.Frame) then - self.Frame = CreateFrame("Frame"); - self.Frame:Hide(); - end - self.Frame.Show = self.Frame.Show; -- cache for speed - self.Frame.Hide = self.Frame.Hide; -- cache for speed - self.Frame:SetScript("OnUpdate", self.OnUpdate); - self.Frame:SetScript("OnEvent", self.OnEvent); -- v11: Monitor P_E_W so we can throttle hard for a few seconds - self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD"); - self.OnUpdateDelay=0; - self.LastAvailUpdate=GetTime(); - self.HardThrottlingBeginTime=GetTime(); -- v11: Throttle hard for a few seconds after startup - - -- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7) - if(not self.ORIG_SendChatMessage) then - --SendChatMessage - self.ORIG_SendChatMessage = SendChatMessage; - SendChatMessage = function(a1,a2,a3,a4) return ChatThrottleLib.Hook_SendChatMessage(a1,a2,a3,a4); end - --SendAdd[Oo]nMessage - if(SendAddonMessage or SendAddOnMessage) then -- v10: don't pretend like it doesn't exist if it doesn't! - self.ORIG_SendAddonMessage = SendAddonMessage or SendAddOnMessage; - SendAddonMessage = function(a1,a2,a3) return ChatThrottleLib.Hook_SendAddonMessage(a1,a2,a3); end - if(SendAddOnMessage) then -- in case Slouken changes his mind... - SendAddOnMessage = SendAddonMessage; - end - end - end - self.nBypass = 0; -end - - ------------------------------------------------------------------------ --- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage -function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination) - local self = ChatThrottleLib; - local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(destination or "")) + 40; - self.avail = self.avail - size; - self.nBypass = self.nBypass + size; - return self.ORIG_SendChatMessage(text, chattype, language, destination); -end -function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype) - local self = ChatThrottleLib; - local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(prefix or "")) + 40; - self.avail = self.avail - size; - self.nBypass = self.nBypass + size; - return self.ORIG_SendAddonMessage(prefix, text, chattype); -end - - - ------------------------------------------------------------------------ --- ChatThrottleLib:UpdateAvail --- Update self.avail with how much bandwidth is currently available - -function ChatThrottleLib:UpdateAvail() - local now = GetTime(); - local newavail = MAX_CPS * (now-self.LastAvailUpdate); - - if(now - self.HardThrottlingBeginTime < 5) then - -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then - self.avail = min(self.avail + (newavail*0.1), MAX_CPS*0.5); - elseif(GetFramerate()ring.pos[1].nSize) do - local msg = tremove(Prio.Ring.pos, 1); - if(not Prio.Ring.pos[1]) then - local pipe = Prio.Ring.pos; - Prio.Ring:Remove(pipe); - Prio.ByName[pipe.name] = nil; - self.PipeBin:Put(pipe); - else - Prio.Ring.pos = Prio.Ring.pos.next; - end - Prio.avail = Prio.avail - msg.nSize; - msg.f(msg[1], msg[2], msg[3], msg[4]); - Prio.nTotalSent = Prio.nTotalSent + msg.nSize; - self.MsgBin:Put(msg); - end -end - - -function ChatThrottleLib.OnEvent() - -- v11: We know that the rate limiter is touchy after login. Assume that it's touch after zoning, too. - self = ChatThrottleLib; - if(event == "PLAYER_ENTERING_WORLD") then - self.HardThrottlingBeginTime=GetTime(); -- Throttle hard for a few seconds after zoning - self.avail = 0; - end -end - - -function ChatThrottleLib.OnUpdate() - self = ChatThrottleLib; - - self.OnUpdateDelay = self.OnUpdateDelay + arg1; - if(self.OnUpdateDelay < 0.08) then - return; - end - self.OnUpdateDelay = 0; - - self:UpdateAvail(); - - if(self.avail<0) then - return; -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu. - end - - -- See how many of or priorities have queued messages - local n=0; - for prioname,Prio in pairs(self.Prio) do - if(Prio.Ring.pos or Prio.avail<0) then - n=n+1; - end - end - - -- Anything queued still? - if(n<1) then - -- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing - for prioname,Prio in pairs(self.Prio) do - self.avail = self.avail + Prio.avail; - Prio.avail = 0; - end - self.bQueueing = false; - self.Frame:Hide(); - return; - end - - -- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues - local avail= self.avail/n; - self.avail = 0; - - for prioname,Prio in pairs(self.Prio) do - if(Prio.Ring.pos or Prio.avail<0) then - Prio.avail = Prio.avail + avail; - if(Prio.Ring.pos and Prio.avail>Prio.Ring.pos[1].nSize) then - self:Despool(Prio); - end - end - end - - -- Expire recycled tables if needed - self.MsgBin:Tidy(); - self.PipeBin:Tidy(); -end - - - - ------------------------------------------------------------------------ --- Spooling logic - - -function ChatThrottleLib:Enqueue(prioname, pipename, msg) - local Prio = self.Prio[prioname]; - local pipe = Prio.ByName[pipename]; - if(not pipe) then - self.Frame:Show(); - pipe = self.PipeBin:Get(); - pipe.name = pipename; - Prio.ByName[pipename] = pipe; - Prio.Ring:Add(pipe); - end - - tinsert(pipe, msg); - - self.bQueueing = true; -end - - - -function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination) - if(not (self and prio and text and self.Prio[prio] ) ) then - error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix" or nil, "text"[, "chattype"[, "language"[, "destination"]]]', 2); - end - - prefix = prefix or tostring(this); -- each frame gets its own queue if prefix is not given - - local nSize = strlen(text) + MSG_OVERHEAD; - - -- Check if there's room in the global available bandwidth gauge to send directly - if(not self.bQueueing and nSize < self:UpdateAvail()) then - self.avail = self.avail - nSize; - self.ORIG_SendChatMessage(text, chattype, language, destination); - self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize; - return; - end - - -- Message needs to be queued - msg=self.MsgBin:Get(); - msg.f=self.ORIG_SendChatMessage - msg[1]=text; - msg[2]=chattype or "SAY"; - msg[3]=language; - msg[4]=destination; - msg.n = 4 - msg.nSize = nSize; - - self:Enqueue(prio, format("%s/%s/%s", prefix, chattype, destination or ""), msg); -end - - -function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype) - if(not (self and prio and prefix and text and chattype and self.Prio[prio] ) ) then - error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype")', 0); - end - - local nSize = strlen(prefix) + 1 + strlen(text) + MSG_OVERHEAD; - - -- Check if there's room in the global available bandwidth gauge to send directly - if(not self.bQueueing and nSize < self:UpdateAvail()) then - self.avail = self.avail - nSize; - self.ORIG_SendAddonMessage(prefix, text, chattype); - self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize; - return; - end - - -- Message needs to be queued - msg=self.MsgBin:Get(); - msg.f=self.ORIG_SendAddonMessage; - msg[1]=prefix; - msg[2]=text; - msg[3]=chattype; - msg.n = 3 - msg.nSize = nSize; - - self:Enqueue(prio, format("%s/%s", prefix, chattype), msg); -end - - - - ------------------------------------------------------------------------ --- Get the ball rolling! - -ChatThrottleLib:Init(); - ---[[ WoWBench debugging snippet -if(WOWB_VER) then - local function SayTimer() - print("SAY: "..GetTime().." "..arg1); - end - ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer); - ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY"); -end -]] - - From 8c270a8b1f7f8238e035753b064b50814d53dbe0 Mon Sep 17 00:00:00 2001 From: Spit <19otari98@gmail.com> Date: Thu, 16 Jan 2025 13:44:22 +0300 Subject: [PATCH 39/39] added flask --- BetterCharacterStats.lua | 3 ++- BetterCharacterStats.toc | 2 +- helper.lua | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/BetterCharacterStats.lua b/BetterCharacterStats.lua index 6192d17..8368261 100644 --- a/BetterCharacterStats.lua +++ b/BetterCharacterStats.lua @@ -543,8 +543,9 @@ function BCS:SetSpellPower(statFrame, school) local green = "|cff20ff20" if school then - local base = BCS:GetSpellPower() + local base, _, _, dmgOnly = BCS:GetSpellPower() local fromSchool = BCS:GetSpellPower(school) + base = base + dmgOnly local output = base + fromSchool if fromSchool > 0 then diff --git a/BetterCharacterStats.toc b/BetterCharacterStats.toc index 37c9c4f..42e4641 100644 --- a/BetterCharacterStats.toc +++ b/BetterCharacterStats.toc @@ -1,7 +1,7 @@ ## Interface: 11200 ## Title: BetterCharacterStats ## Author: moh, Bennylava, |cffbe5effLexie|r, Spit, Pepopo -## Version: 1.12.6 +## Version: 1.12.7 ## SavedVariablesPerCharacter: BCSConfig BCScache BetterCharacterStats.xml \ No newline at end of file diff --git a/helper.lua b/helper.lua index 7b92a2d..b3d0e9b 100644 --- a/helper.lua +++ b/helper.lua @@ -1352,6 +1352,11 @@ function BCS:GetSpellPower(school) if spellPowerFromAura then BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) end + -- Flask of Supreme Power + _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell damage increased by up to (%d+)") + if spellPowerFromAura then + BCScache["auras"].only_damage = BCScache["auras"].only_damage + tonumber(spellPowerFromAura) + end -- Danonzo's Tel'Abim Delight _, _, spellPowerFromAura = BCS:GetPlayerAura("Spell Damage increased by (%d+)") if spellPowerFromAura then