-- 段位道場 exam-panel extras only Lua can draw: the soul-gauge pass-threshold -- callout plate + captions, anchored on the gauge's own 50-cell grid. local M = {} M.__index = M local GAUGE_Y = 248 local GAUGE_X0 = 738 -- cell 1 starts here local CELL_PITCH = 21 local CELL_COUNT = 50 local LABEL_SIZE = 30 -- arcade MS 明朝 36; ours reads heavier local WHITE = { 255, 255, 255, 255 } local BLACK = { 0, 0, 0, 255 } local PLATE_W, PLATE_H = 586, 60 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 NAME_SIZE = 26 -- arcade id 142 local VALUE_SIZE = 36 -- arcade id 141 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) end function M:plate_id() if not self.plate_tried then self.plate_tried = true self.plate = tex.get_texture("game/dan_info/gauge_border_plate") end return self.plate end -- Called from Background:handle_dan. function M:handle(state) self.state = state end local function gauge_exam(state) if not state or not state.exams then return nil end for _, e in ipairs(state.exams) do if e.type == "gauge" then return e end end return nil end -- Called from Background:draw_fore(), i.e. after the whole GAME_DAN HUD. function M:draw() local st = self.state if not st then return end local ex = gauge_exam(st) if not ex or not ex.red or ex.red <= 0 then return end -- the threshold, on the gauge's own 50-cell grid (2 % quantised) local pct = ex.red local n = math.floor(pct / 2) if n < 1 then n = 1 end -- border_0 == border_1 on the cabinet if n > CELL_COUNT then n = CELL_COUNT end -- dan.json may say >100 %; the cabinet cannot local x = GAUGE_X0 + CELL_PITCH * n - CELL_PITCH / 2 - 1 if self.label_for ~= ex.red then -- skin_config: dan_gauge_name (魂ゲージ) and dan_exam_text_gauge ("%s %以上", %% = %) local fmt = tex.skin_text("dan_exam_text_gauge"):gsub("%%%%", "\1") local caption = fmt:gsub("%%s", tostring(ex.red)):gsub("\1", "%%") self.label = text.create_raw_text(caption, VALUE_SIZE, CAP_FILL, VALUE_OUTLINE, false, 4.0 / tex.get_screen_scale()) self.name_label = text.create_raw_text(tex.skin_text("dan_gauge_name"), NAME_SIZE, CAP_FILL, CAP_OUTLINE, false, 3.0 / tex.get_screen_scale()) self.label_for = ex.red end local pid = self:plate_id() -- the plate overhangs the threshold by 24 px (the baked arrow lands ON it) -- and floats PLATE_GAP above the bar 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 }) end -- fail soft: with no plate art the two captions still draw, at the same places if self.name_label then self.name_label:draw({ x = math.floor(px + PILL_CX - self.name_label.width / 2 + 0.5), y = math.floor(py + PILL_CY - self.name_label.height / 2 + 0.5), }) end if self.label then -- tx_border is RIGHT-aligned; its box's right edge is plate-local 532 self.label:draw({ x = math.floor(px + VALUE_RIGHT - self.label.width + 0.5), y = math.floor(py + VALUE_CY - self.label.height / 2 + 0.5), }) end end return M