-- YataiDON-HSS child-only helper (ROUND 52, r52-lua-divergence-fixes). -- -- The COLLAB dancer-count model, ported from the reference build -- `EnsoGraphicDancer::Process` (EnsoGraphicDancer.obj.c:2723-2752). The -- function is evaluated EVERY frame and is a pure function of the gauge; the -- byte at +108 selects between the two branches: -- -- r = current_gauge / CLEAR_POINT -- +327256 / +327164 -- normal troupes (+108 set): n = clamp(floor(2r + 3), 3, 5) -- ROUND 18 -- dance_b_* collabs (+108 0): n = clamp(floor(4r + 1), 1, 5) -- THIS FILE -- -- i.e. a collab troupe starts at ONE dancer, gains one for every quarter of -- the CLEAR point (not the full bar), and is symmetric -- the count falls -- again when the gauge falls. The skin's collabs used the pre-R18 model -- (floor(progress * MAX) over the whole bar); ROUND 52 replaces it with this. -- The upper clamp is the collab's own MAX_DANCERS (per the user's directive -- the per-collab maxima stay as shipped; reference's own clamp is 5). -- -- The divisor handling (clear_progress plumbed as handle_gauge's 5th arg, -- with the "learn the difficulty at the is_clear flip" fallback) is the same -- fail-soft scheme background.lua:handle_dancer_count has used since R18. local CollabDancerModel = {} CollabDancerModel.__index = CollabDancerModel local GAUGE_MAX = 87.0 local CLEAR_STARTS = { 52, 60, 69 } -- easy / normal / hard+oni local CLEAR_DEFAULT = 69 / GAUGE_MAX function CollabDancerModel.new(max_dancers) return setmetatable({ max = max_dancers, clear_progress = nil }, CollabDancerModel) end -- Returns the absolute troupe size for this frame. function CollabDancerModel:target(progress, is_clear, clear_progress) if clear_progress and clear_progress > 0 then self.clear_progress = clear_progress elseif is_clear and not self.clear_progress then local p = progress or 0 for _, cs in ipairs(CLEAR_STARTS) do if p < cs / GAUGE_MAX + 0.0005 then self.clear_progress = cs / GAUGE_MAX break end end self.clear_progress = self.clear_progress or CLEAR_DEFAULT end local cp = self.clear_progress or CLEAR_DEFAULT local r = (progress or 0) / cp local n = math.floor(4 * r + 1) -- the engine flips is_clear one gauge unit early; honour it so the full -- troupe and the クリア state arrive on the same frame (same nudge R18 -- applies to the normal troupes). if is_clear then n = self.max end if n < 1 then n = 1 elseif n > self.max then n = self.max end return n end -- Drives a BaseDancerGroup-shaped object (add_dancer/remove_dancer/ -- active_count) to the target count. Skips quietly until the group has -- spawned its initial dancer (active_count 0 = first update not yet run). function CollabDancerModel:apply(group, progress, is_clear, clear_progress) local cur = group.active_count or 0 if cur <= 0 then return end local n = self:target(progress, is_clear, clear_progress) for _ = 1, n - cur do group:add_dancer() end for _ = 1, cur - n do group:remove_dancer() end end return CollabDancerModel