diff --git a/Graphics/game/dan_info/gauge_border_plate.png b/Graphics/game/dan_info/gauge_border_plate.png index f532a2e..fc32ed4 100644 --- a/Graphics/game/dan_info/gauge_border_plate.png +++ b/Graphics/game/dan_info/gauge_border_plate.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:060e1ae8a3ffcdd68fdf642a80c86263295536652c41dbf76817aacd0c0128e9 -size 4548 +oid sha256:f17f353558be8f2c6e3a3be114c03611384c1475d292e8b38bd176e60299c953 +size 5771 diff --git a/Graphics/game/gauge_dan/1p_lamp.png b/Graphics/game/gauge_dan/1p_lamp.png new file mode 100644 index 0000000..5c6a55b --- /dev/null +++ b/Graphics/game/gauge_dan/1p_lamp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7073f04a6f717214aabd6f60f80fde4a4656012327780ccfaa6df51b0cf6269 +size 102 diff --git a/Graphics/game/gauge_dan/2p_lamp.png b/Graphics/game/gauge_dan/2p_lamp.png new file mode 100644 index 0000000..b4dba75 --- /dev/null +++ b/Graphics/game/gauge_dan/2p_lamp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:feee6a6b22b4fbe5fefb51a7568f1f0c9f553e37f543f5498042ab37357bd18e +size 101 diff --git a/Graphics/game/gauge_dan/bar_fade_clear.png b/Graphics/game/gauge_dan/bar_fade_clear.png new file mode 100644 index 0000000..ccc1a03 --- /dev/null +++ b/Graphics/game/gauge_dan/bar_fade_clear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0b93b68d5618c46103efe2f338affdee84f0afd82c967016640ccd347b357c5 +size 844 diff --git a/Graphics/game/gauge_dan/lamp_clear.png b/Graphics/game/gauge_dan/lamp_clear.png new file mode 100644 index 0000000..e5d92e8 --- /dev/null +++ b/Graphics/game/gauge_dan/lamp_clear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ecf728861f1e98daff53b3cbfb5acb5c7e48c90dc0268bb1f7b82361deb1af18 +size 101 diff --git a/Graphics/game/gauge_dan/texture.json b/Graphics/game/gauge_dan/texture.json index ba6afd6..e6403e5 100644 --- a/Graphics/game/gauge_dan/texture.json +++ b/Graphics/game/gauge_dan/texture.json @@ -100,5 +100,25 @@ "tamashii_fire": { "x": 1698, "y": 34 + }, + "track_red": { + "x": 738, + "y": 242 + }, + "1p_lamp": { + "x": 738, + "y": 242 + }, + "2p_lamp": { + "x": 738, + "y": 242 + }, + "lamp_clear": { + "x": 738, + "y": 242 + }, + "bar_fade_clear": { + "x": 733, + "y": 241 } } diff --git a/Graphics/game/gauge_dan/track_red.png b/Graphics/game/gauge_dan/track_red.png new file mode 100644 index 0000000..2e6970c --- /dev/null +++ b/Graphics/game/gauge_dan/track_red.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15b7143bdf6632718f0b1ce429ab81a3e221429f15c7e9de48712521d7091a6f +size 162 diff --git a/Scripts/background/bg_collabs/dan.lua b/Scripts/background/bg_collabs/dan.lua index bc9f4dd..615d9fb 100644 --- a/Scripts/background/bg_collabs/dan.lua +++ b/Scripts/background/bg_collabs/dan.lua @@ -155,14 +155,18 @@ function DanBackground:draw_back() self.chibi:draw() end --- dan soul gauge separator overlay (static, drawn at a hardcoded fade). +-- the soul gauge's strip the lane covers (the cabinet draws the gauge over the lane), then +-- its threshold marker, on top of everything +local LANE_TOP, GAUGE_BOTTOM = 276, 288 function DanBackground:draw_fore() - if not self._gauge_overlay then - self._gauge_overlay = tex.get_texture("game/gauge_dan/overlay") or 0 - end - if self._gauge_overlay ~= 0 then - tex.draw_texture(self._gauge_overlay, { fade = 0.15 }) + local redraw = _G.g_dan_gauge_redraw + if redraw then + tex.begin_scissor(0, LANE_TOP, tex.get_screen_width(), GAUGE_BOTTOM - LANE_TOP) + local ok, err = pcall(redraw) + tex.end_scissor() + if not ok then error(err, 0) end end + self.dan_info:draw_marker() end -- dan condition plate, drawn in the gauge's own layer. diff --git a/Scripts/background/bg_objects/dan_info.lua b/Scripts/background/bg_objects/dan_info.lua index 27dc810..b2dbce6 100644 --- a/Scripts/background/bg_objects/dan_info.lua +++ b/Scripts/background/bg_objects/dan_info.lua @@ -1,5 +1,7 @@ -- 段位道場 exam-panel extras only Lua can draw: the soul-gauge pass-threshold --- callout plate + captions, anchored on the gauge's own 50-cell grid. +-- callout plate + captions and the white threshold marker on the threshold cell, anchored +-- on the gauge's own 50-cell grid. It also hands the threshold (in cells) to the gauge script +-- (g_dan_gauge_border), which colours the track by it. local M = {} M.__index = M @@ -11,23 +13,30 @@ local LABEL_SIZE = 30 -- arcade MS 明朝 36; ours reads local WHITE = { 255, 255, 255, 255 } local BLACK = { 0, 0, 0, 255 } -local PLATE_W, PLATE_H = 586, 60 +local PLATE_W, PLATE_H = 586, 60 -- the plate's grey body; the art adds a 9 px margin +local PLATE_ART_PAD = 9 -- (the pill's top/left edge and the drop shadow) local PLATE_GAP = 12 -- px between the plate's bottom and the bar top local PLATE_OVERHANG = 24 -- px the plate extends PAST the threshold local PILL_CX, PILL_CY = 150, 20 -- 魂ゲージ ink centre, plate-local local VALUE_RIGHT = 532 -- 100%以上 is RIGHT-aligned to this -local VALUE_CY = 22 -- its ink centre y, plate-local +local VALUE_CY = 35 -- its ink centre y, plate-local local NAME_SIZE = 26 -- arcade id 142 local VALUE_SIZE = 36 -- arcade id 141 +-- the threshold marker (gauge_border_cell): its white inside (x 7, y 7 in the art) lands on +-- the threshold cell's left edge + 1, from y 238, as the cabinet's border_N +local MARKER_INNER_X, MARKER_INNER_Y = 7, 7 +local MARKER_Y = 238 + local CAP_FILL = { 255, 255, 255, 255 } local CAP_OUTLINE = { 80, 60, 45, 255 } -- #503C2D local VALUE_OUTLINE = { 0, 0, 0, 255 } function M.new() return setmetatable({ state = nil, label = nil, label_for = nil, - name_label = nil, plate = nil, plate_tried = false }, M) + name_label = nil, plate = nil, plate_tried = false, + marker = nil, marker_tried = false }, M) end function M:plate_id() @@ -38,9 +47,12 @@ function M:plate_id() return self.plate end --- Called from Background:handle_dan. -function M:handle(state) - self.state = state +function M:marker_id() + if not self.marker_tried then + self.marker_tried = true + self.marker = tex.get_texture("game/dan_info/gauge_border_cell") + end + return self.marker end local function gauge_exam(state) @@ -51,6 +63,14 @@ local function gauge_exam(state) return nil end +-- Called from Background:handle_dan. +function M:handle(state) + self.state = state + local ex = gauge_exam(state) + _G.g_dan_gauge_border = (ex and ex.red and ex.red > 0) + and math.max(1, math.min(CELL_COUNT, math.floor(ex.red / 2))) or nil +end + -- Called from Background:draw_fore(), i.e. after the whole GAME_DAN HUD. function M:draw() local st = self.state @@ -84,7 +104,7 @@ function M:draw() local px = math.max(0, math.floor(x - PLATE_W + PLATE_OVERHANG + 0.5)) local py = GAUGE_Y - PLATE_GAP - PLATE_H if pid then - tex.draw_texture(pid, { x = px, y = py }) + tex.draw_texture(pid, { x = px - PLATE_ART_PAD, y = py - PLATE_ART_PAD }) end -- fail soft: with no plate art the two captions still draw, at the same places @@ -103,4 +123,16 @@ function M:draw() end end +-- The threshold marker, drawn over the lane's frame as on the cabinet (it reaches below the +-- gauge), so from Background:draw_fore() rather than with the plate in the gauge layer. +function M:draw_marker() + local ex = gauge_exam(self.state) + if not ex or not ex.red or ex.red <= 0 then return end + local n = math.max(1, math.min(CELL_COUNT, math.floor(ex.red / 2))) + local mid = self:marker_id() + if not mid then return end + local cell_left = GAUGE_X0 + CELL_PITCH * (n - 1) + tex.draw_texture(mid, { x = cell_left + 1 - MARKER_INNER_X, y = MARKER_Y - MARKER_INNER_Y }) +end + return M diff --git a/Scripts/game/gauge.lua b/Scripts/game/gauge.lua index f659b97..df9d3d1 100644 --- a/Scripts/game/gauge.lua +++ b/Scripts/game/gauge.lua @@ -4,6 +4,7 @@ -- 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 +-- The dan gauge is drawn as the cabinet's tamashii_gauge (see draw_dan below). -- 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) @@ -23,10 +24,21 @@ assert(load_parent("game/gauge"), "game/gauge: the parent skin has no gauge scri 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(...) +function Gauge.new(is_2p, dan, string_diff, opts) + local self = parent_new(is_2p, dan, string_diff, opts) local mark = tex.get_skin_config("gauge_clear_mark_offset") self.clear_mark_offset = mark and mark.x + if dan then + local screen = (opts and opts.screen) or "game" + local p = (opts and opts.player_str and (opts.player_str .. "_")) or (is_2p and "2p_" or "1p_") + local function t(name) return tex.get_texture(screen .. "/gauge_dan/" .. name) end + self.cab = { + track_red = t("track_red"), + lamp = t(p .. "lamp"), + lamp_clear = t("lamp_clear"), + fade_clear = t("bar_fade_clear"), + } + end return self end @@ -101,3 +113,77 @@ function Gauge:render(y, mirror, idx, points, previous_points, max_points, clear self:blit(self.tamashii_dark, nil, nil, y, nil, nil, nil, idx) end end + +-- The dan gauge as the cabinet's tamashii_gauge draws it: the gold track (border), the red +-- track (track_red, gauge_bg) up to the threshold, the lit cells as one lamp stretched 21 px +-- per cell (lamp_clear, yellow, once the gauge reaches the threshold), the glow on a newly lit +-- cell, the cell separators at the cabinet's 103/255, then 魂: grey, white once cleared, and +-- in flames at full. The threshold comes from the dan exam (background dan_info sets +-- g_dan_gauge_border, in cells); without it, or without the cabinet pieces, the parent draws. +local CAB_CELL = 21 +local CAB_TRACK = 20.88 -- gauge_bg: 160 px x 0.1305 per cell +local CAB_SEPARATOR = 103 / 255 +local parent_draw_dan = Gauge.draw_dan + +-- The cabinet draws the gauge over the lane; the engine draws the lane after it, so its top +-- edge (y 276, 184 px x 1.5) hides the cells' last rows. The gauge leaves a redraw for the +-- dan background's draw_fore (g_dan_gauge_redraw), which repeats it clipped to that strip. +local function draw_cab(self, border, points, previous_points, max_points, is_rainbow, + anim_active, anim_alpha, rainbow_fade, rainbow_frac, fire_frame) + local cab = self.cab + local function layer(t, x, x2, fade, frame, scale, center) + if t then + tex.draw_texture(t, { x = x, x2 = x2, fade = fade, frame = frame, scale = scale, center = center }) + end + end + + local length, solid, alpha, show_up = self:cells(points, previous_points, max_points, anim_active, anim_alpha) + local clear = length >= border + + layer(self.border) + if border > 0 then layer(cab.track_red, nil, CAB_TRACK * border - 160) end + if solid > 0 then layer(clear and cab.lamp_clear or cab.lamp, nil, CAB_CELL * solid - 8) 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) + layer(self.rainbow, nil, nil, rainbow_fade, frame_a) + layer(self.rainbow, nil, nil, rainbow_fade * f, frame_b) + end + + if show_up and length > 0 then + layer(clear and cab.fade_clear or self.bar_fade, (length - 1) * CAB_CELL, nil, alpha) + end + + layer(self.overlay, nil, nil, CAB_SEPARATOR) + + if is_rainbow then + layer(self.fire, nil, nil, nil, fire_frame, 0.75, true) + layer(self.tamashii) + if fire_frame == 0 or fire_frame == 1 or fire_frame == 4 or fire_frame == 5 then + layer(self.tamashii_overlay, nil, nil, 0.5) + end + elseif clear then + layer(self.tamashii) + else + layer(self.tamashii_dark) + end +end + +function Gauge:draw_dan(points, previous_points, max_points, is_rainbow, + anim_active, anim_alpha, rainbow_fade, rainbow_frac, fire_frame) + local cab = self.cab + local border = _G.g_dan_gauge_border + if not (cab and cab.track_red and cab.lamp and cab.lamp_clear and border) then + _G.g_dan_gauge_redraw = nil + return parent_draw_dan(self, points, previous_points, max_points, is_rainbow, + anim_active, anim_alpha, rainbow_fade, rainbow_frac, fire_frame) + end + draw_cab(self, border, points, previous_points, max_points, is_rainbow, + anim_active, anim_alpha, rainbow_fade, rainbow_frac, fire_frame) + _G.g_dan_gauge_redraw = function() + draw_cab(self, border, points, previous_points, max_points, is_rainbow, + anim_active, anim_alpha, rainbow_fade, rainbow_frac, fire_frame) + end +end