size the sparkle to the Pokemon it belongs to

Flat numbers cannot work here and both previous attempts proved it in
opposite directions. The first ring was 7 world units across, which is inside
anything bigger than a Rattata -- and additive drawing keeps the depth test,
so all sixty quads a frame were rejected and nobody saw them. Correcting by
eye gave a ring 24 across starting 20 units up, which is taller than the
tallest Pokemon in the game: it hung in the sky above a Ponyta with nothing
underneath it.

A mon on the map is 5 to 18 world pixels tall (StadiumMon REF_HEIGHT 14). One
ring cannot fit a Diglett and a Gyarados, so every distance is now a fraction
of the mon: Stadium pushes each side's worldHeight and worldRadius into
ShinyFx every frame -- worldRadius exists precisely so "a caller can size
something to its footprint" -- and the burst is measured off those.

Two more things the pictures showed. The ring is an ELLIPSE with its axes
measured separately: flattened enough to read as a ring from the battle's low
seat, a single radius reaches only a third of the body's height, so the top
and bottom stars sit on the Pokemon. And it OPENS from clear of the body
rather than from a point -- springing out of nothing means every star spends
the first frames stacked at the centre, which is the middle of the mon and
looks exactly like the sparkles being stuck inside it.

Shot against Ponyta and Gyarados, an order of magnitude apart in size: the
ring hugs each silhouette from outside and no star lands on either body.
This commit is contained in:
DramaticShape
2026-08-08 13:01:09 -04:00
parent eb69bc7db8
commit 322defbbd0
2 changed files with 89 additions and 15 deletions
+11
View File
@@ -412,6 +412,17 @@ function Stadium.update(dt, battle, groundY)
-- the battle (see StadiumPack.keep). The shiny flag rides along: the
-- shiny and normal models are separate cache entries.
if mon.species then StadiumPack.keep(mon.species, mon.shiny) end
-- how big this Pokemon actually is, so a shiny's sparkle can be sized to
-- it rather than to a constant that is wrong for most of the dex (see
-- the header of ShinyFx). Pushed every frame: the model can arrive a
-- frame or two after the burst is armed, and a send-out is still growing
-- while it plays.
if mon.rig and mon.model then
ShinyFx.setMetrics(side, mon:worldHeight(), mon:worldRadius())
else
ShinyFx.setMetrics(side, nil)
end
mon.visible = (mon.rig ~= nil) and onField(battle, side, mon)
and not (battler and battler.substituteHP)
-- LET'S GO capture mode: the player's model is out of the shot the