Files
PyTaikoGreen/Scripts/global/network_msg.lua
T
2026-10-14 10:27:20 -04:00

134 lines
4.1 KiB
Lua

NetworkMsg = {}
NetworkMsg.__index = NetworkMsg
NetworkMsg.LABELS = {
clear_reading = { bar = 0, dots = 315 },
clear_reading_ok = { bar = 1 },
error_reading_ng = { bar = 2 },
error_data_ban = { bar = 2 },
error_disconnect = { bar = 2 },
error_assign_limit = { bar = 2 },
error_cannot_assign = { bar = 2 },
notice_pickup_card = { bar = 3 },
clear_reading_maybe = { bar = 0, dots = 335 },
error_lost_card = { bar = 2 },
error_userdata = { bar = 2 },
error_already_gasha = { bar = 2 },
error_not_play = { bar = 2 },
error_touch_again = { bar = 2 },
error_close_shop = { bar = 2 },
error_offline_gasha = { bar = 2 },
error_card_gasha = { bar = 2 },
error_end_gasha = { bar = 2 },
error_bnid = { bar = 2 },
error_shop_already = { bar = 2 },
error_shop_failed = { bar = 2 },
error_shop_shortage = { bar = 2 },
shop_get_OK = { bar = 1 },
error_offline_shop = { bar = 2 },
}
local BAR_CENTER = 312 -- bar top 232 + 80
local BIG, SMALL = 30, 20
local BIG_H, SMALL_H = 36, 28
local DOT_PITCH = 40
local FRAME_MS = 1000 / 60
local TILE_W = 64
local SCROLL_PX_PER_MS = TILE_W / (121 * FRAME_MS)
local FADE_MS = 150
local DOT_START = 10
local DOT_LOOP = 149
local DOT_WAITING = 5
local function dot_frame(t)
t = t % DOT_LOOP
if t < 60 then return 0 end
if t < 76 then return math.min(8, 1 + math.floor((t - 60) / 2)) end
if t < 135 then return 8 end
return 7 - math.floor((t - 135) / 2)
end
function NetworkMsg.new()
local self = setmetatable({}, NetworkMsg)
self.dim = tex.get_texture("global/network_msg/dim")
self.bar = tex.get_texture("global/network_msg/bar")
self.dot = tex.get_texture("global/network_msg/dot")
self.label = nil
self.cache = {}
self.start_ms = 0
self.now = 0
self.fade = 0
self.visible = false
return self
end
local function build(key)
local lines = {}
for line in (tex.skin_text("network_msg_" .. key) .. "\n"):gmatch("(.-)\n") do
local small = line:sub(1, 1) == "~"
if small then line = line:sub(2) end
lines[#lines + 1] = {
text = text.create_raw_text(line, small and SMALL or BIG, { 255, 255, 255, 255 }, { 0, 0, 0, 255 }, false, 5, 2.0),
h = small and SMALL_H or BIG_H,
}
end
return lines
end
function NetworkMsg:show(label)
if not NetworkMsg.LABELS[label] then return end
if self.label ~= label then self.start_ms = self.now end
self.label = label
self.visible = true
if not self.cache[label] then self.cache[label] = build(label) end
end
function NetworkMsg:hide() self.visible = false end
function NetworkMsg:update(current_ms)
local dt = math.max(0, current_ms - self.now)
self.now = current_ms
local step = dt / FADE_MS
if self.visible then
self.fade = math.min(1, self.fade + step)
else
self.fade = math.max(0, self.fade - step)
if self.fade == 0 then self.label = nil end
end
end
function NetworkMsg:draw()
if not self.label then return end
local info = NetworkMsg.LABELS[self.label]
local lines = self.cache[self.label]
local fade = self.fade
tex.draw_texture(self.dim, { fade = 0.5 * fade })
local phase = (self.now * SCROLL_PX_PER_MS) % TILE_W
for k = 0, 21 do
tex.draw_texture(self.bar, { frame = info.bar, x = k * TILE_W - phase, fade = fade })
end
local y
if info.dots then
y = 272 - BIG_H / 2 -- title sits above the dots, not centred on the bar
else
local total = 0
for _, l in ipairs(lines) do total = total + l.h end
y = BAR_CENTER - total / 2
end
for _, l in ipairs(lines) do
l.text:draw({ x = 640 - l.text.width / 2, y = y + (l.h - l.text.height) / 2, fade = fade })
y = y + l.h
if info.dots then y = 310 - SMALL_H / 2 end
end
if info.dots then
local f = math.floor((self.now - self.start_ms) / FRAME_MS)
for i = 0, 5 do
local t = f - i * DOT_START
tex.draw_texture(self.dot, { frame = t < 0 and DOT_WAITING or dot_frame(t), x = i * DOT_PITCH, y = info.dots - 315, fade = fade })
end
end
end