@@ -696,13 +696,13 @@ cached = {
696696 -- secret/nil reads do not render as a real 0.0%.
697697 versTotal = nil ,
698698 versTotalRating = 0 ,
699- armorDR = 0 ,
699+ armorDR = nil ,
700700 itemLevelOverall = nil ,
701701 itemLevelEquipped = nil ,
702702 durabilityValue = 100 , -- holds avg or min depending on cached.useWorstDurability
703703 repairCost = 0 , -- live repair cost in copper (sum from per-slot tooltip scan)
704704 -- WARNING: GetUnitSpeed returns secret values in combat → arithmetic taints. Cache OOC.
705- speedPct = 0 ,
705+ speedPct = nil ,
706706 speedWasSwimming = nil ,
707707 -- Last clean hide-zero decision per stat row. Secret combat reads cannot be safely
708708 -- compared to 0, so they reuse this instead of making absent rows appear.
@@ -2093,6 +2093,7 @@ local function ScanDurabilityAndCost()
20932093 local sum , count , totalCost = 0 , 0 , 0
20942094 local minPct
20952095 local repairCostPending = false
2096+ local repairCostKnownCount = 0
20962097 for slot = DURABILITY_SLOT_MIN , DURABILITY_SLOT_MAX do
20972098 if not DURABILITY_SKIP_SLOTS [slot ] then
20982099 local cur , max = GetInventoryItemDurability (slot )
@@ -2109,6 +2110,7 @@ local function ScanDurabilityAndCost()
21092110 end
21102111 local cost = data .repairCost
21112112 if SAFE_NUM .IsCleanFiniteNumber (cost ) and not issecretvalue (cost ) then
2113+ repairCostKnownCount = repairCostKnownCount + 1
21122114 if cost > 0 then
21132115 totalCost = totalCost + cost
21142116 end
@@ -2122,8 +2124,8 @@ local function ScanDurabilityAndCost()
21222124 end
21232125 end
21242126 end
2125- if count == 0 then return 100 , 100 , 0 , repairCostPending end
2126- return sum / count , minPct , totalCost , repairCostPending
2127+ if count == 0 then return 100 , 100 , 0 , repairCostPending , repairCostKnownCount end
2128+ return sum / count , minPct , totalCost , repairCostPending , repairCostKnownCount
21272129end
21282130
21292131-- WARNING: repairCost can lag behind durability: C_TooltipInfo may return nil
@@ -2134,10 +2136,10 @@ end
21342136local durabilityRetryScheduled = false
21352137
21362138local function RefreshDurabilityCache ()
2137- local avg , mn , cost , repairCostPending = ScanDurabilityAndCost ()
2139+ local avg , mn , cost , repairCostPending , repairCostKnownCount = ScanDurabilityAndCost ()
21382140 cached .durabilityValue = cached .useWorstDurability and mn or avg
2139- if repairCostPending and cost < = 0 then
2140- cached .repairCost = cached . repairCost or 0
2141+ if repairCostPending and ( repairCostKnownCount or 0 ) = = 0 then
2142+ cached .repairCost = 0
21412143 else
21422144 cached .repairCost = cost
21432145 end
@@ -2572,8 +2574,7 @@ end
25722574-- WARNING: GetStringWidth/GetStringHeight on a FontString whose text contains in-combat
25732575-- secret-tainted substrings return secret-tainted numbers. Arithmetic on those errors.
25742576-- Mitigation: keep last non-secret measurement; refresh cache only if current read is
2575- -- non-secret. Used for all 4 measurement points in SetTextSafe (label/rating/value
2576- -- widths + label height for repair Y positioning).
2577+ -- non-secret. Used for column widths and row-height reads in SetTextSafe.
25772578local function MeasuredOrCached (fs , current_cache , method )
25782579 local v = fs [method ](fs )
25792580 if v and not issecretvalue (v ) then
@@ -2612,6 +2613,8 @@ function Panel:SetTextSafe(labelStr, ratingStr, valueStr, lineCount, repairStr,
26122613 if hasRows then
26132614 self .cachedRatingW = MeasuredOrCached (self .ratingText , self .cachedRatingW , " GetStringWidth" )
26142615 self .cachedValueW = MeasuredOrCached (self .valueText , self .cachedValueW , " GetStringWidth" )
2616+ self .cachedRatingH = MeasuredOrCached (self .ratingText , self .cachedRatingH , " GetStringHeight" )
2617+ self .cachedValueH = MeasuredOrCached (self .valueText , self .cachedValueH , " GetStringHeight" )
26152618 if not labelsHidden then
26162619 self .cachedLabelW = MeasuredOrCached (self .labelText , self .cachedLabelW , " GetStringWidth" )
26172620 -- labelText height drives Repair-row Y positioning; cache same way as widths.
@@ -2634,8 +2637,15 @@ function Panel:SetTextSafe(labelStr, ratingStr, valueStr, lineCount, repairStr,
26342637 -- column space without overlapping stat content rows.
26352638 local repairLabelW = 0
26362639 local lineH = GetNumberDB (" fontSize" )
2637- if hasRows and not labelsHidden and self .cachedLabelH then
2638- lineH = self .cachedLabelH / lineCount
2640+ if hasRows then
2641+ if labelsHidden then
2642+ local renderedH = 0
2643+ if hasRating and self .cachedRatingH then renderedH = math.max (renderedH , self .cachedRatingH ) end
2644+ if hasValue and self .cachedValueH then renderedH = math.max (renderedH , self .cachedValueH ) end
2645+ if renderedH > 0 then lineH = renderedH / lineCount end
2646+ elseif self .cachedLabelH then
2647+ lineH = self .cachedLabelH / lineCount
2648+ end
26392649 end
26402650 self .lastLineH = lineH
26412651
@@ -2775,6 +2785,8 @@ function Panel:ApplyStyle(font, size, force)
27752785 -- lineCount back). lastLineCount is intentionally NOT reset here — Panel:Reflow
27762786 -- relies on it as the cached content-line-count for re-feeding SetTextSafe.
27772787 self .cachedLabelH = nil
2788+ self .cachedRatingH = nil
2789+ self .cachedValueH = nil
27782790 self .heightDirty = true
27792791end
27802792
@@ -3630,11 +3642,23 @@ local function OnPlayerEnteringWorld()
36303642 if next (db ) == nil then
36313643 local swiftStatsDB = type (_G .SwiftStatsDB ) == " table" and _G .SwiftStatsDB or nil
36323644 local swiftStatsLocalDB = type (_G .SwiftStatsLocalDB ) == " table" and _G .SwiftStatsLocalDB or nil
3633- local source = (swiftStatsDB and next (swiftStatsDB ) ~= nil and swiftStatsDB )
3634- or (swiftStatsLocalDB and next (swiftStatsLocalDB ) ~= nil and swiftStatsLocalDB )
3645+ local source , sourceIsLocal
3646+ if swiftStatsDB and next (swiftStatsDB ) ~= nil then
3647+ source = swiftStatsDB
3648+ sourceIsLocal = false
3649+ elseif swiftStatsLocalDB and next (swiftStatsLocalDB ) ~= nil then
3650+ source = swiftStatsLocalDB
3651+ sourceIsLocal = true
3652+ end
36353653 if source then
36363654 for k , v in pairs (source ) do
3637- db [k ] = (type (v ) == " table" ) and CopyTable (v ) or v
3655+ local copyKey = k ~= " dbVersion"
3656+ if not copyKey and sourceIsLocal and NormalizeDBVersion (v ) <= CURRENT_DB_VERSION then
3657+ copyKey = true
3658+ end
3659+ if copyKey then
3660+ db [k ] = (type (v ) == " table" ) and CopyTable (v ) or v
3661+ end
36383662 end
36393663 end
36403664 end
@@ -5638,12 +5662,16 @@ function addon:PrintDebugDump()
56385662 tostring (cached .showArmor ), tostring (cached .showStagger )))
56395663
56405664 -- Panel positions: nil-guard (DB may be partial in pre-PEW edge cases)
5641- local function PosLine (label , p , rp , x , y )
5665+ local function PosLine (label , p , rp , x , y , fallbackY )
56425666 if not p then return label .. " : <unset>" end
5643- return string.format (" %s: %s/%s %+d/%+d" , label , p , rp , x or 0 , y or 0 )
5667+ local point = NormalizeAnchorPoint (p , " CENTER" )
5668+ local relativePoint = NormalizeAnchorPoint (rp , point )
5669+ local xOfs = NormalizePositionOffset (x , 0 )
5670+ local yOfs = NormalizePositionOffset (y , fallbackY or 0 )
5671+ return string.format (" %s: %s/%s %+.0f/%+.0f" , label , point , relativePoint , xOfs , yOfs )
56445672 end
5645- PrintMsg (PosLine (" main" , GetDB (" point" ), GetDB (" relativePoint" ), GetDB (" xOfs" ), GetDB (" yOfs" )))
5646- PrintMsg (PosLine (" side" , GetDB (" defensive_point" ), GetDB (" defensive_relativePoint" ), GetDB (" defensive_xOfs" ), GetDB (" defensive_yOfs" )))
5673+ PrintMsg (PosLine (" main" , GetDB (" point" ), GetDB (" relativePoint" ), GetDB (" xOfs" ), GetDB (" yOfs" ), defaults . yOfs ))
5674+ PrintMsg (PosLine (" side" , GetDB (" defensive_point" ), GetDB (" defensive_relativePoint" ), GetDB (" defensive_xOfs" ), GetDB (" defensive_yOfs" ), defaults . defensive_yOfs ))
56475675end
56485676
56495677local function PrintDebugPerf ()
@@ -6048,12 +6076,21 @@ if addon and addon.__statsproSmoke == true then
60486076 }
60496077 end ,
60506078 panelVisualState = function ()
6079+ local firstOverlay = mainPanel .tooltipOverlays and mainPanel .tooltipOverlays [1 ] or nil
6080+ local secondOverlay = mainPanel .tooltipOverlays and mainPanel .tooltipOverlays [2 ] or nil
60516081 return {
60526082 textOutlineStyle = cached .textOutlineStyle ,
60536083 mainFrameHeight = mainPanel .frame :GetHeight (),
6084+ mainLastLineH = mainPanel .lastLineH ,
60546085 mainBackgroundAlpha = mainPanel .frame .backdropColor and mainPanel .frame .backdropColor .a or nil ,
60556086 mainBackgroundTextureAlpha = mainPanel .backgroundTexture and mainPanel .backgroundTexture .colorTexture and mainPanel .backgroundTexture .colorTexture .a or nil ,
60566087 mainBackgroundTexturePoints = mainPanel .backgroundTexture and mainPanel .backgroundTexture .points or nil ,
6088+ mainRepairPoints = mainPanel .repairText .points ,
6089+ mainRepairLabelPoints = mainPanel .repairLabelText .points ,
6090+ mainFirstOverlayHeight = firstOverlay and firstOverlay :GetHeight () or nil ,
6091+ mainFirstOverlayPoints = firstOverlay and firstOverlay .points or nil ,
6092+ mainSecondOverlayHeight = secondOverlay and secondOverlay :GetHeight () or nil ,
6093+ mainSecondOverlayPoints = secondOverlay and secondOverlay .points or nil ,
60576094 mainLabelFlags = mainPanel .labelText .fontFlags ,
60586095 mainRatingFlags = mainPanel .ratingText .fontFlags ,
60596096 mainValueFlags = mainPanel .valueText .fontFlags ,
@@ -6073,6 +6110,10 @@ if addon and addon.__statsproSmoke == true then
60736110 renderMainPanelForSmoke = function (labelStr , ratingStr , valueStr , lineCount , repairStr , repairLabelStr , targetRows )
60746111 mainPanel :SetTextSafe (labelStr , ratingStr , valueStr , lineCount , repairStr , repairLabelStr , targetRows )
60756112 end ,
6113+ setMainPanelStringHeightMultiplier = function (column , multiplier )
6114+ local fs = ({ label = mainPanel .labelText , rating = mainPanel .ratingText , value = mainPanel .valueText })[column ]
6115+ if fs then fs .statsProStringHeightMultiplier = multiplier end
6116+ end ,
60766117 mainPanelTooltipState = function ()
60776118 return {
60786119 overlayCount = # (mainPanel .tooltipOverlays or {}),
0 commit comments