Files
YataiDONNijiiro/Scripts/global/coin_overlay.lua
T
2026-09-30 15:29:22 -04:00

102 lines
5.0 KiB
Lua

-- Global credit line / QR chip / 2P invite cloud, drawn on every non-game screen.
CoinOverlay = {}
CoinOverlay.__index = CoinOverlay
local ca_ok, cs_anim = pcall(require, "anim/sampler")
if not ca_ok then cs_anim = { safe = function()
local n = {}
n.at = function() return nil end; n.get = function() return nil end
n.label = function() return nil end; n.has = function() return false end
n.first = function() return 0 end; n.last = function() return 0 end
return n
end } end
local credit_side = cs_anim.safe("anim/credit_side")
local credit_side_len = math.max(1, credit_side:last() - credit_side:first() + 1) -- 180 frames = 3 s
local credit_side_pop_f = 8
function CoinOverlay.new()
local self = setmetatable({}, CoinOverlay)
self.text = text.create_text("free_play", { 255, 255, 255, 255 }, { 0, 0, 0, 255 }, false, 3, 5)
self.config = tex.get_skin_config("free_play")
self.qr = tex.get_texture("global/overlay/banapass_osaifu_keitai") -- QR chip (0 NG / 1 OK)
self.bubble = tex.get_texture("global/overlay/camera") -- 2P cloud bubble
self.bubble_player = text.create_text("credit_side_player", { 255, 255, 255, 255 }, { 0, 0, 0, 255 }, false, 4, 2)
self.bubble_msg = text.create_text("credit_side_msg", { 255, 255, 255, 255 }, { 0, 0, 0, 255 }, false, 4, 2)
self.bubble_cfg_p = tex.get_skin_config("credit_side_player")
self.bubble_cfg_m = tex.get_skin_config("credit_side_msg")
self.blink_t0 = tex.get_current_ms()
return self
end
function CoinOverlay:update(current_ms) end
local FREE_PLAY_CY = 1046
local BUBBLE_PLAYER_CY = 749
local BUBBLE_MSG_CY = 802
local BUBBLE_BOX_W = 416 -- cloud art width
-- Centred, whole-pixel-snapped OutlinedText draw clamped to `box_w`.
local function draw_bubble_line(t, cfg, cx, cy, fade)
if not t or t.width == nil then return end
local w = math.floor(math.min(t.width, BUBBLE_BOX_W) + 0.5)
t:draw({ x = math.floor(cx - w / 2 - cfg.x + 0.5),
y = math.floor(cy - t.height / 2 - cfg.y + 0.5),
x2 = w - t.width,
fade = fade })
end
local CREDIT_SCREENS = {
ENTRY = true,
PRACTICE_SELECT = true, AI_SELECT = true,
TITLE = true, RESULT = true,
-- DAN_SELECT and SONG_SELECT intentionally absent (no credit line there).
}
function CoinOverlay:draw(x, y)
local screen = tex.current_screen and tex.current_screen() or ""
-- unknown/blank screen keeps the always-on behaviour
local show_credit = (screen == "") or (CREDIT_SCREENS[screen] == true)
if show_credit then
local text_x = math.floor(tex.get_screen_width() / 2 - self.text.width / 2 - self.config.x + 0.5)
local text_y = math.floor(FREE_PLAY_CY - self.text.height / 2 - self.config.y + 0.5)
self.text:draw({ x = text_x, y = text_y })
end
if tex.in_transition and tex.in_transition() then return end
-- per-frame hook for a screen to draw above the credit text
if YD_DRAW_ABOVE_CREDIT then
local fn = YD_DRAW_ABOVE_CREDIT
YD_DRAW_ABOVE_CREDIT = nil
fn()
end
local chip_screens = (screen == "ENTRY" or screen == "SONG_SELECT" or screen == "SONG_SELECT_2P"
or screen == "PRACTICE_SELECT" or screen == "AI_SELECT" or screen == "DAN_SELECT")
if chip_screens and not (tex.in_transition and tex.in_transition()) then
tex.draw_texture(self.qr, { frame = 0 })
end
local scr = (screen ~= "") and screen or "ENTRY"
local on_entry_or_select = (scr == "ENTRY" or scr == "SONG_SELECT" or scr == "SONG_SELECT_2P"
or scr == "PRACTICE_SELECT" or scr == "AI_SELECT")
local pn = tex.player_num()
local both_joined = (pn == 3) or (scr == "SONG_SELECT_2P")
or (scr == "ENTRY" and YD_ENTRY_BOTH_JOINED == true)
local credit_up = (scr == "ENTRY") and YD_ENTRY_CREDIT_MS ~= nil
and (tex.get_current_ms() - YD_ENTRY_CREDIT_MS) < 100
local join_window = (scr == "ENTRY") or not tex.songs_played or (tex.songs_played() < 2)
if on_entry_or_select and join_window and not credit_up and not both_joined and (pn == 1 or pn == 2) then
local side = (pn == 1) and 0 or 1
local cx_p = (pn == 1) and self.bubble_cfg_p.x or (tex.get_screen_width() - self.bubble_cfg_p.x)
local cx_m = (pn == 1) and self.bubble_cfg_m.x or (tex.get_screen_width() - self.bubble_cfg_m.x)
local elapsed = tex.get_current_ms() - self.blink_t0
local f = (elapsed * 0.06) % credit_side_len -- arcade frame 0..179
local pop = math.min(1, elapsed * 0.06 / credit_side_pop_f) -- pop-in on first show
local fade = (credit_side:get("#3@0", f, "a") or 0) * pop
local fade_t = (credit_side:get("credit_all_instance", f, "a") or 0) * pop
tex.draw_texture(self.bubble, { index = side, fade = fade })
draw_bubble_line(self.bubble_player, self.bubble_cfg_p, cx_p, BUBBLE_PLAYER_CY, fade_t)
draw_bubble_line(self.bubble_msg, self.bubble_cfg_m, cx_m, BUBBLE_MSG_CY, fade_t)
end
end