71 lines
3.1 KiB
Lua
71 lines
3.1 KiB
Lua
-- 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
|