- The top-left control guide follows the cabinet's ChangeMode: `decide` alone on the credit screen, the `all` loop (rim to choose + face to decide) on mode select when the list has more than one board, hidden during the drum select. entry.lua / entry/box.lua publish the phase, global/indicator.lua reads it. - The open mode board's title sits in the middle of the dark band at the top of the plate; the text object's box is taller than its ink, so the nominal y is set for the ink (-118 -> -97). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
104 lines
5.5 KiB
Lua
104 lines
5.5 KiB
Lua
-- YataiDON-HSS override of PyTaikoGreen/global/indicator.lua
|
|
-- Arcade common/control_guide: white top-left panel with a drum; 'main/taiko_small/all' is a 650-frame
|
|
-- loop at the lumen's 60 fps (10.83 s): frames 0..209 right stick + up arrow (hits @60,145),
|
|
-- 210..419 left stick + down arrow (hits @270,355), 420..649 both sticks + 「決定」 pill (face flash
|
|
-- 521..569). Round 4: re-baked every 2nd frame (325 cells = 30 fps, 352x276 cells, y offset 12 in
|
|
-- texture.json, origin = screen (0,0) so skin_config *_indicator positions should be {0,0}) into
|
|
-- global/indicator/background; the previous bake was every 5th frame (12 fps) which read as sluggish.
|
|
-- Wall-clock loop length is the arcade's (elapsed ms * 60 / FRAME_STEP). The other parent textures
|
|
-- (text, drum_face/kat/don, blue_arrow) are not drawn. All engine call sites use State.SELECT;
|
|
-- the other states fall back to the same loop.
|
|
Indicator = {}
|
|
Indicator.__index = Indicator
|
|
|
|
Indicator.State = {
|
|
SKIP = 0,
|
|
SIDE = 1,
|
|
SELECT = 2,
|
|
WAIT = 3,
|
|
}
|
|
|
|
local FRAME_STEP = 2 -- arcade frames per baked frame (bake_guide.py STEP)
|
|
local ARCADE_FPS = 60
|
|
|
|
function Indicator.new(state)
|
|
local self = setmetatable({}, Indicator)
|
|
self.state = state
|
|
self.background = tex.load_texture("global/indicator/background")
|
|
self.frame_count = tex.get_texture_info("indicator", "background").frame_count
|
|
self.t0 = tex.get_current_ms()
|
|
return self
|
|
end
|
|
|
|
function Indicator:update(current_ms) end
|
|
|
|
-- The baked loop is two guides back to back: cells 0..SPLIT-1 (arcade frames 0..419) = rim hit
|
|
-- + arrow (song select: "pick with the rim"), cells SPLIT..DECIDE_END-1 (arcade frames 420..649,
|
|
-- 230 frames = 3.83 s, the same length as the arcade's taiko_small 'decide' loop) = both sticks +
|
|
-- 決定 pill (entry: "decide with the face"). The engine passes the same State everywhere,
|
|
-- so which guide a screen wants is carried by its skin_config position: the
|
|
-- song-select keys are set to y=1 (see skin_config), entry/others to y=0.
|
|
local SPLIT, DECIDE_END = math.floor(420 / FRAME_STEP), math.floor(650 / FRAME_STEP) -- cells 210..324 = both sticks + 決定
|
|
__hss_costume_panel = __hss_costume_panel or {}
|
|
__hss_entry_guide = __hss_entry_guide or nil -- { ms, phase = "side" | "mode", count } from the entry scripts
|
|
|
|
-- ROUND 11 drew the 段位道場 shutter doors from HERE, purely for layering: the
|
|
-- indicator was the last skin-owned draw on SONG_SELECT and therefore the only slot
|
|
-- that landed over the whole HUD (LUA_CAPABILITIES C-dan-3). ROUND 14 added the real
|
|
-- slot -- `SongSelect:draw_top(dan_progress)`, called from SongSelectScreen::draw()
|
|
-- immediately before dan_transition->draw() -- so the doors now live in
|
|
-- song_select.lua where they belong and this file is back to being the indicator.
|
|
--
|
|
-- The fallback is kept for one reason only: on an engine WITHOUT draw_top, nothing
|
|
-- would ever call the rig. `dan_doors.draw()` returns false unless a transition is
|
|
-- actually running, and song_select.lua marks the frame it already drew, so on the
|
|
-- current engine this costs one table lookup and draws nothing twice.
|
|
local _dd_ok, dan_doors = pcall(require, "song_select/dan_doors")
|
|
|
|
function Indicator:draw(x, y, fade)
|
|
fade = fade or 1.0
|
|
if _dd_ok and not dan_doors.drawn_this_frame() and dan_doors.draw() then return end
|
|
-- arcade costume select (entry/costume.nulm) hides the top-left control guide: its own
|
|
-- title box (100..898 x 142..268) sits where the guide panel is; costume_menu.lua keeps
|
|
-- __hss_costume_panel[side] fresh while a costume menu is open (skin_config gives both
|
|
-- indicator_entry_* the same (0,0), so the side cannot be told apart here -> hide for any side)
|
|
local now = tex.get_current_ms()
|
|
for _, t in pairs(__hss_costume_panel) do
|
|
if now - t < 100 then return end
|
|
end
|
|
-- entry phases (published by entry.lua / entry/box.lua while they draw): TaikoSelect hides
|
|
-- the guide, ModeSelect with several boards shows the `all` loop instead of `decide`
|
|
local g = __hss_entry_guide
|
|
local show_all = false
|
|
if g and now - g.ms < 100 then
|
|
if g.phase == "side" then return end
|
|
show_all = (g.phase == "mode") and (g.count or 1) > 1
|
|
end
|
|
local elapsed = tex.get_current_ms() - self.t0
|
|
local frame
|
|
if (y or 0) >= 1 or show_all then
|
|
frame = math.floor(elapsed / 1000 * ARCADE_FPS / FRAME_STEP) % SPLIT
|
|
if (y or 0) >= 1 then y = y - 1 end
|
|
else
|
|
local n = DECIDE_END - SPLIT
|
|
frame = SPLIT + math.floor(elapsed / 1000 * ARCADE_FPS / FRAME_STEP) % n
|
|
end
|
|
tex.draw_texture(self.background, { frame = frame, x = x, y = y, fade = fade })
|
|
end
|
|
|
|
-- ROUND 17 — the top-most slot on DAN_SELECT.
|
|
--
|
|
-- `DanSelectScreen::draw()` calls this as its very last statement, after the coin
|
|
-- overlay, the GLOBAL::DAN_SELECT plate and the allnet chip (Indicator::draw_top,
|
|
-- src/objects/global/indicator.{h,cpp}). It is DAN_SELECT's equivalent of
|
|
-- `SongSelect:draw_top`, and it exists for exactly one thing: the 段位道場 shutter's
|
|
-- SECOND half. The cabinet's doors OPEN on the dan-select screen
|
|
-- (`loading_dani_intro` f187..200) — up to round 16 our transition ended with a
|
|
-- hard cut on SONG_SELECT and the reveal was never played at all.
|
|
--
|
|
-- `dan_doors.draw_open()` returns false unless a transition actually handed over,
|
|
-- so on every other visit to DAN_SELECT this is one table lookup and no draw.
|
|
function Indicator:draw_top()
|
|
if _dd_ok then dan_doors.draw_open() end
|
|
end
|