From 0fed3df4190267623cd6bdf1b1f5ce1b5338a5dd Mon Sep 17 00:00:00 2001 From: TaikoZhong <108016253+GanYiZhong@users.noreply.github.com> Date: Wed, 14 Oct 2026 10:07:41 +0800 Subject: [PATCH] gauge: this skin's render() for its 50-cell fade-in grid Co-Authored-By: Claude Opus 5.5 --- Scripts/game/gauge.lua | 103 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 Scripts/game/gauge.lua diff --git a/Scripts/game/gauge.lua b/Scripts/game/gauge.lua new file mode 100644 index 0000000..f659b97 --- /dev/null +++ b/Scripts/game/gauge.lua @@ -0,0 +1,103 @@ +-- This skin's gauge: the parent's script with render() replaced. The parent's render() is laid +-- out for its 87-cell flash gauge; this skin's 50 x 21 px grid fades each new cell in: +-- * gauge_cell_fade_in: the fading sprite is the new cell itself, so it sits on cell +-- length-1 (at length it left a dark gap cell before it) +-- * the clear mark sits gauge_clear_mark_offset cells (skin_config: 1, the cell edge) before +-- the exact clear fraction, not the parent's 87/60 +-- Everything else is the parent's file, loaded from its own copy. + +-- the parent skin's copy of a script: the second match on package.path (the first is this file) +local function load_parent(name) + local seen = false + for tmpl in package.path:gmatch("[^;]+") do + local chunk = loadfile((tmpl:gsub("%?", name))) + if chunk then + if seen then return chunk end + seen = true + end + end +end + +assert(load_parent("game/gauge"), "game/gauge: the parent skin has no gauge script")() + +local function clamp(v, lo, hi) return math.max(lo, math.min(hi, v)) end + +local parent_new = Gauge.new +function Gauge.new(...) + local self = parent_new(...) + local mark = tex.get_skin_config("gauge_clear_mark_offset") + self.clear_mark_offset = mark and mark.x + return self +end + +function Gauge:render(y, mirror, idx, points, previous_points, max_points, clear_points, + is_clear, is_rainbow, anim_active, anim_alpha, rainbow_fade, rainbow_frac, fire_frame) + -- blit(t, mirror, x, y, x2, fade, frame, index, scale, center, cap) + if not self.no_border then self:blit(self.border, mirror, nil, y, nil, nil, nil, idx) end + self:blit(self.unfilled, mirror, nil, y, nil, nil, nil, idx) + + local units, bw = self.bar_units, self.bar_width + local length, solid, alpha, show_up, pending, fade_in = + self:cells(points, previous_points, max_points, anim_active, anim_alpha) + local clear_point = clamp(clear_points * units // max_points, 1, units) + -- the parent's art: the clear mark at the exact fraction minus 87/60 cells (x 897/967/1037 on + -- easy/normal/hard), not on a cell edge + local cpx = clear_points * units / max_points - (self.clear_mark_offset or units / 60) + + if solid > 0 then + self:blit(self.bar, nil, nil, y, + math.min(solid, cpx) * bw - bw, nil, nil, idx) + end + + -- first gold cell lights exactly when the gauge is cleared (not by a cell-count test: + -- on 87 cells 8000 -> 69.6 would light it a cell early/late vs. the clear state) + if is_clear and not (fade_in and pending and length == clear_point) then + self:blit(self.clear_transition, mirror, cpx * bw, y, nil, nil, nil, idx) + end + + -- gold zone: cells clear_point .. solid-1, one cell wide piece so stretch is (n-1)*bw + local gold_x = (cpx + 1) * bw + if solid * bw >= gold_x + bw then + local gold_x2 = solid * bw - gold_x - bw + self:blit(self.clear_top, mirror, gold_x, y, gold_x2, nil, nil, idx) + self:blit(self.clear_bottom, nil, gold_x, y, gold_x2, nil, nil, idx) + end + + if is_rainbow and rainbow_fade >= 0 then + local frame_a = math.floor(rainbow_frac) % 8 + local frame_b = (frame_a + 1) % 8 + local f = rainbow_frac - math.floor(rainbow_frac) + self:blit(self.rainbow, mirror, nil, y, nil, rainbow_fade, frame_a, idx) + self:blit(self.rainbow, mirror, nil, y, nil, rainbow_fade * f, frame_b, idx) + end + + if show_up then + -- flash: the glow rides the leading edge of the fill; fade-in: the sprite is the new + -- cell itself (the fill stops one cell short until it lands) + local fx = (fade_in and length - 1 or length) * bw + if length == clear_point then + self:blit(self.clear_transition_fade, mirror, cpx * bw, y, nil, alpha, nil, idx) + elseif length > clear_point then + self:blit(self.clear_fade, nil, fx, y, nil, alpha, nil, idx) + else + self:blit(self.bar_fade, nil, fx, y, nil, alpha, nil, idx) + end + end + + self:blit(self.overlay, mirror, nil, y, nil, 0.15, nil, idx, nil, nil, true) + if self.footer then self:blit(self.footer, nil, nil, y, nil, nil, nil, idx) end + + self:draw_fire(y, idx, is_rainbow, fire_frame) + + local label = self.art_tier + idx * 3 + if is_clear then + self:blit(self.clear, nil, nil, y, nil, nil, nil, label) + self:blit(self.tamashii, nil, nil, y, nil, nil, nil, idx) + if is_rainbow and (fire_frame == 0 or fire_frame == 1 or fire_frame == 4 or fire_frame == 5) then + self:blit(self.tamashii_overlay, nil, nil, y, nil, 0.5, nil, idx, nil, nil, true) + end + else + self:blit(self.clear_dark, nil, nil, y, nil, nil, nil, label) + self:blit(self.tamashii_dark, nil, nil, y, nil, nil, nil, idx) + end +end -- 2.54.0