AnySCT 0.3.1

This commit is contained in:
2026-10-15 14:55:12 +02:00
parent 4600cc0719
commit 4a0c325fd7
8 changed files with 93 additions and 14 deletions
+61 -5
View File
@@ -24,7 +24,6 @@ AnySCT_STYLE = {
fadeOutWord = 1.0, -- Miss / Dodge / Parry / Block ...
fadeOutAbsorb = 0.09, -- "Absorb" is a quick flicker
riseHeight = 120, -- px a normal text rises (engine: 2 world units; screen distance varies)
critRiseFactor = 0, -- crits do not rise, they pop in place
sizeScale = 0.018333, -- text pixel size = scale x screen diagonal (1024x768 -> 23 px)
critSizeScale = 0.0275, -- crits (1024x768 -> 35 px)
shadow = 0.002, -- shadow offset, fraction of the viewport per axis (down-right)
@@ -230,6 +229,43 @@ S.ANCHOR_W, S.ANCHOR_H, S.ANCHOR_LABEL_SIZE, S.PLATE_LABEL_SIZE = 200, 30, 12, 1
function S.EstTextWidth(text, size) return string.len(text) * size * 0.62 end
-- Where anchor-mode damage lines start so they clear the box (and the list label above it).
function S.AnchorLineOffset(showLabel) return showLabel and 16 or 2 end
-- ---- stack geometry -------------------------------------------------------------------------
-- A line occupies [bottom - suffixH, bottom + numberH]: the number sits on its anchor point, the
-- suffix (spell / name) hangs below it. Crits are reserved at the peak of their size pop. A new line
-- is inserted at the bottom; every older line of the same mob moves up by the new line's height plus
-- the suffix height of the line directly above it, which is what makes the new line fit under it.
function S.CritPeak(kf)
local m = 1
for i = 1, table.getn(kf) do if kf[i][2] > m then m = kf[i][2] end end
return m
end
-- Distance of a line's anchor point from its start: the same rise rate for every line of a tower, so
-- older lines (larger t) only ever move away from newer ones.
function S.LineOffset(t, dur, rise, push) return t / dur * rise + push end
function S.NumberHeight(base, isCrit, peak) return isCrit and base * peak or base end
function S.SuffixHeight(base, hasSuffix)
if not hasSuffix then return 0 end
local sz = math.floor(base * 0.3)
if sz < 10 then sz = 10 end
return sz + 2
end
function S.StackAdvance(base, isCrit, peak, prevSuffixH)
return S.NumberHeight(base, isCrit, peak) + (prevSuffixH or 0)
end
-- A crit of a tiny proc must not pop at full crit size: scale by the amount against the source's
-- running average hit (0.5 .. 1).
function S.CritFactor(amount, ref)
if not ref or ref <= 0 then return 1 end
local f = (amount or 0) / ref
if f > 1 then return 1 end
if f < 0.5 then return 0.5 end
return f
end
function S.UpdateRef(ref, amount)
if not ref then return amount end
return ref + (amount - ref) * 0.1
end
-- ---- merging identical attacks ---------------------------------------------------------------
-- Is the result a word (Miss / Dodge / ...)? Same rule as S.Format.
function S.IsWordResult(res, opt)
@@ -370,6 +406,8 @@ if CreateFrame then
local POOL_MAX = 100 -- slot tables only; FontStrings are created on first use (ensureFs)
local critAnimated = S.CurveAnimated(STYLE.critKeyframes)
local critActive = S.CurveActive(STYLE.critKeyframes)
local avgHit = {} -- per source: running average hit, for the crit pop scale
local critPeak = S.CritPeak(STYLE.critKeyframes)
local GAP = 3 -- px between the plate top and the text
local anchor, float, listLabel
@@ -548,13 +586,14 @@ if CreateFrame then
if t < STYLE.fadeIn then a = t / STYLE.fadeIn end
if t > s.fadeOut then a = a * (s.dur - t) / (s.dur - s.fadeOut) end
local rise = s.rise
-- crits rise with the tower like every other line: a line that stood still would
-- let the newer, rising lines below it run into it
if s.crit then
rise = rise * STYLE.critRiseFactor
if critAnimated then
s.fs:SetTextHeight(s.base * S.KeyScale(STYLE.critKeyframes, t / s.dur))
end
end
local off = (t / s.dur * rise + s.push) * s.dir
local off = S.LineOffset(t, s.dur, rise, s.push) * s.dir
s.fs:ClearAllPoints()
if s.plate then
needScan = true
@@ -632,9 +671,26 @@ if CreateFrame then
local base = S.TextSize(scale, factor, sw, sh)
s.base = base * mul
-- older lines of the same mob move one text height away
-- tiny crits (procs) pop smaller: scale by the amount against the source's running average hit
local refKey = res.source or "?"
if not isWord and res.kind ~= "heal" then
if s.crit then s.base = s.base * S.CritFactor(res.amount, avgHit[refKey]) end
avgHit[refKey] = S.UpdateRef(avgHit[refKey], res.amount or 0)
end
s.sfxH = S.SuffixHeight(s.base, suffix ~= nil)
-- older lines of the same mob make room for this line's real height (crit peak included) plus
-- the suffix hanging below the line right above it
local prevSfx, prevT = 0, nil
for j = 1, POOL_MAX do
if slots[j].active and slots[j].key == key then slots[j].push = slots[j].push + s.base end
local m = slots[j]
if m.active and m.key == key and j ~= i and (not prevT or m.t < prevT) then
prevT, prevSfx = m.t, m.sfxH or 0
end
end
local adv = S.StackAdvance(s.base, s.crit, critPeak, prevSfx)
for j = 1, POOL_MAX do
if slots[j].active and slots[j].key == key and j ~= i then slots[j].push = slots[j].push + adv end
end
s.active = true