Compare commits

..

1 Commits

Author SHA1 Message Date
2297f1b6e0 - devcontainer: tic80 compiles and graphics runs, tested on linux
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-16 22:03:20 +02:00
36 changed files with 376 additions and 1401 deletions

27
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,27 @@
FROM alpine:3.23
RUN apk update && apk add --no-cache \
xeyes \
jack \
git \
luarocks \
mc \
make \
cmake \
ruby \
bash \
curl \
ca-certificates \
g++ \
pulseaudio \
mesa-dev \
mesa-gles \
glu-dev
RUN git clone --recursive --depth=1 https://github.com/nesbox/TIC-80.git /root/TIC-80 \
&& cd /root/TIC-80/build \
&& cmake -DBUILD_PRO=1 .. \
&& make -j$(nproc) \
&& make install
CMD ["/bin/sh"]

View File

@@ -0,0 +1,33 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/alpine
{
"name": "Alpine Edge",
"build": {
"dockerfile": "Dockerfile"
},
"mounts": [
{
"source": "/tmp/.X11-unix",
"target": "/tmp/.X11-unix",
"type": "bind"
}
],
"containerEnv": {
"DISPLAY": "${localEnv:DISPLAY}",
"PULSE_SERVER": "tcp:host.docker.internal:4713"
},
"postCreateCommand": "if [ -n \"$WSL_DISTRO_NAME\" ]; then echo 'export DISPLAY=host.docker.internal:0.0' >> ~/.bashrc; fi"
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

View File

@@ -24,7 +24,6 @@ globals = {
"Minigame", "Minigame",
"Window", "Window",
"ContinuedWindow", "ContinuedWindow",
"CreditsWindow",
"TTGIntroWindow", "TTGIntroWindow",
"BriefIntroWindow", "BriefIntroWindow",
"TitleIntroWindow", "TitleIntroWindow",
@@ -39,14 +38,6 @@ globals = {
"MysteriousManScreen", "MysteriousManScreen",
"DiscussionWindow", "DiscussionWindow",
"EndWindow", "EndWindow",
<<<<<<< HEAD
"PlayerNameWindow",
"TextInput",
"CodeGenerator",
"CreditsWindow",
=======
"GameOverWindow",
>>>>>>> develop
"mset", "mset",
"mget", "mget",
"btnp", "btnp",

View File

@@ -6,7 +6,6 @@ init/init.context.lua
system/system.util.lua system/system.util.lua
system/system.print.lua system/system.print.lua
system/system.input.lua system/system.input.lua
system/system.textinput.lua
system/system.mouse.lua system/system.mouse.lua
system/system.asciiart.lua system/system.asciiart.lua
system/system.rle.lua system/system.rle.lua
@@ -17,7 +16,6 @@ logic/logic.timer.lua
logic/logic.trigger.lua logic/logic.trigger.lua
logic/logic.minigame.lua logic/logic.minigame.lua
logic/logic.glitch.lua logic/logic.glitch.lua
logic/logic.codegenerator.lua
logic/logic.discussion.lua logic/logic.discussion.lua
system/system.ui.lua system/system.ui.lua
audio/audio.manager.lua audio/audio.manager.lua
@@ -50,7 +48,6 @@ decision/decision.go_to_end.lua
decision/decision.go_to_walking_to_home.lua decision/decision.go_to_walking_to_home.lua
decision/decision.go_to_sleep.lua decision/decision.go_to_sleep.lua
decision/decision.do_work.lua decision/decision.do_work.lua
decision/decision.have_a_coffee.lua
decision/decision.sumphore_discussion.lua decision/decision.sumphore_discussion.lua
discussion/discussion.sumphore.lua discussion/discussion.sumphore.lua
discussion/discussion.coworker.lua discussion/discussion.coworker.lua
@@ -68,7 +65,6 @@ screen/screen.work.lua
screen/screen.mysterious_man.lua screen/screen.mysterious_man.lua
window/window.manager.lua window/window.manager.lua
window/window.register.lua window/window.register.lua
window/window.gameover.lua
window/window.end.lua window/window.end.lua
window/window.intro.title.lua window/window.intro.title.lua
window/window.intro.ttg.lua window/window.intro.ttg.lua
@@ -82,8 +78,6 @@ window/window.minigame.rhythm.lua
window/window.minigame.ddr.lua window/window.minigame.ddr.lua
window/window.discussion.lua window/window.discussion.lua
window/window.continued.lua window/window.continued.lua
window/window.credits.lua
window/window.player_name.lua
window/window.game.lua window/window.game.lua
system/system.main.lua system/system.main.lua
meta/meta.assets.lua meta/meta.assets.lua

View File

@@ -1,23 +1,7 @@
local function apply_home_toilet_meter_delta()
local max = Meter.get_max()
Meter.add("bm", -math.floor(max * 0.15))
Meter.add("ism", -math.floor(max * 0.10))
Meter.add("wpm", math.floor(max * 0.05))
end
Decision.register({ Decision.register({
id = "go_to_toilet", id = "go_to_toilet",
label = "Go to Toilet", label = "Go to Toilet",
handle = function() handle = function()
if not Context.have_done_work_today and not Context.toilet_meters_today_morning then
apply_home_toilet_meter_delta()
Context.toilet_meters_today_morning = true
elseif Context.have_been_to_office
and Context.have_done_work_today
and not Context.toilet_meters_today_evening then
apply_home_toilet_meter_delta()
Context.toilet_meters_today_evening = true
end
Util.go_to_screen_by_id("toilet") Util.go_to_screen_by_id("toilet")
end, end,
}) })

View File

@@ -1,14 +0,0 @@
Decision.register({
id = "have_a_coffee",
label = "Have a Coffee",
handle = function()
local level = Ascension.get_level()
local disc_id = "coworker_disc_0"
-- TODO: Add more discussions for levels above 3
if level >= 1 and level <= 3 then
local suffix = Context.have_done_work_today and ("_asc_" .. level) or ("_" .. level)
disc_id = "coworker_disc" .. suffix
end
Discussion.start(disc_id, "game")
end,
})

View File

@@ -123,13 +123,9 @@ function Decision.draw(decisions, selected_decision_index)
local selected_decision = decisions[selected_decision_index] local selected_decision = decisions[selected_decision_index]
local decision_label = Decision.get_label(selected_decision) local decision_label = Decision.get_label(selected_decision)
local text_y = bar_y + 4 local text_y = bar_y + 4
local left_arrow_color = Input.left() and Config.colors.white or Config.colors.orange Print.text("<", 2, text_y, Config.colors.light_blue)
local right_arrow_color = Input.right() and Config.colors.white or Config.colors.orange Print.text_center(decision_label, Config.screen.width / 2, text_y, Config.colors.item)
local left_arrow_contour_color = Input.left() and Config.colors.white or Config.colors.black Print.text(">", Config.screen.width - 6, text_y, Config.colors.light_blue)
local right_arrow_contour_color = Input.right() and Config.colors.white or Config.colors.black
Print.text_center_contour("<", 6, text_y, left_arrow_color, false, 1, left_arrow_contour_color)
Print.text_center_contour(decision_label, Config.screen.width / 2, text_y, Config.colors.orange)
Print.text_center_contour(">", Config.screen.width - 6, text_y, right_arrow_color, false, 1, right_arrow_contour_color)
end end
end end

View File

@@ -7,9 +7,6 @@ Decision.register({
focus_center_x = (Config.screen.width / 2) - 22, focus_center_x = (Config.screen.width / 2) - 22,
focus_center_y = (Config.screen.height / 2) - 18, focus_center_y = (Config.screen.height / 2) - 18,
focus_initial_radius = 0, focus_initial_radius = 0,
on_win = function()
Audio.music_play_room_work()
end
}) })
end, end,
}) })

View File

@@ -1,6 +1,5 @@
Discussion.register({ Discussion.register({
id = "coworker_disc_0", id = "coworker_disc_0",
on_end = Meter.apply_coworker_discussion_reward,
steps = { steps = {
{ {
question = "Good morning Normal, enjoying your coffee as usual, huh?", question = "Good morning Normal, enjoying your coffee as usual, huh?",
@@ -19,7 +18,6 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "coworker_disc_1", id = "coworker_disc_1",
on_end = Meter.apply_coworker_discussion_reward,
steps = { steps = {
{ {
question = "Norman, you look confused, what's up?", question = "Norman, you look confused, what's up?",
@@ -38,12 +36,11 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "coworker_disc_asc_1", id = "coworker_disc_asc_1",
on_end = Meter.apply_coworker_discussion_reward,
steps = { steps = {
{ {
question = "Normann you look weird and unfocused. You are usually locked in and not like this, what's up?", question = "Normann you look weird and unfocused. You are usually locked in and not like this, what's up?",
answers = { answers = {
{ label = "Some bugs I noticed, maybe...", next_step = 2 }, { label = "Nothing it's just, I noticed some bugs in the simulation, maybe.", next_step = 2 },
}, },
}, },
{ {
@@ -57,7 +54,6 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "coworker_disc_2", id = "coworker_disc_2",
on_end = Meter.apply_coworker_discussion_reward,
steps = { steps = {
{ {
question = "Hey Norman, do you have new socks on? That's a weird color!", question = "Hey Norman, do you have new socks on? That's a weird color!",
@@ -83,7 +79,6 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "coworker_disc_asc_2", id = "coworker_disc_asc_2",
on_end = Meter.apply_coworker_discussion_reward,
steps = { steps = {
{ {
question = "Normann, are you ok? You were doing weird things while typing?", question = "Normann, are you ok? You were doing weird things while typing?",
@@ -102,7 +97,6 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "coworker_disc_3", id = "coworker_disc_3",
on_end = Meter.apply_coworker_discussion_reward,
steps = { steps = {
{ {
question = "You look so happy, did you catch a bull or something?", question = "You look so happy, did you catch a bull or something?",
@@ -126,7 +120,6 @@ Discussion.register({
}) })
Discussion.register({ Discussion.register({
id = "coworker_disc_asc_3", id = "coworker_disc_asc_3",
on_end = Meter.apply_coworker_discussion_reward,
steps = { steps = {
{ {
question = "Normal, you should take a break, you don't live up to your name today", question = "Normal, you should take a break, you don't live up to your name today",

View File

@@ -1,6 +1,5 @@
Discussion.register({ Discussion.register({
id = "sumphore_disc_asc_1", id = "sumphore_disc_asc_1",
on_end = Meter.apply_sumphore_discussion_reward,
steps = { steps = {
{ {
question = "Are you still seeking the ox?", question = "Are you still seeking the ox?",
@@ -20,7 +19,6 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "sumphore_disc_asc_2", id = "sumphore_disc_asc_2",
on_end = Meter.apply_sumphore_discussion_reward,
steps = { steps = {
{ {
question = "How's work? Your face looks strange", question = "How's work? Your face looks strange",
@@ -63,7 +61,6 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "sumphore_disc_asc_3", id = "sumphore_disc_asc_3",
on_end = Meter.apply_sumphore_discussion_reward,
steps = { steps = {
{ {
question = "Do you think it's work you're doing?", question = "Do you think it's work you're doing?",
@@ -91,7 +88,6 @@ Discussion.register({
Discussion.register({ Discussion.register({
id = "homeless_guy", id = "homeless_guy",
on_end = Meter.apply_sumphore_discussion_reward,
steps = { steps = {
{ {
question = "Sup bro, how are you?", question = "Sup bro, how are you?",

View File

@@ -93,7 +93,7 @@ function Ascension.draw(x, y, options)
else else
color = lit_color color = lit_color
end end
Print.text_contour(ch, x + (i - 1) * spacing, y, color, false, 1) print(ch, x + (i - 1) * spacing, y, color, false, 1, true)
end end
end end

View File

@@ -17,9 +17,7 @@ function Config.initial_data()
blue = 3, blue = 3,
white = 4, white = 4,
item = 7, item = 7,
meter_bg = 1, meter_bg = 1
transparent = 12,
orange = 7
}, },
timing = { timing = {
minigame_win_duration = 180 minigame_win_duration = 180

View File

@@ -23,10 +23,6 @@ Context = {}
--- * have_met_sumphore (boolean) Whether the player has talked to the homeless guy.<br/> --- * have_met_sumphore (boolean) Whether the player has talked to the homeless guy.<br/>
--- * have_been_to_office (boolean) Whether the player has been to the office.<br/> --- * have_been_to_office (boolean) Whether the player has been to the office.<br/>
--- * have_done_work_today (boolean) Whether the player has done work today.<br/> --- * have_done_work_today (boolean) Whether the player has done work today.<br/>
--- * toilet_meters_today_morning (boolean) Whether the home (before work) toilet meter delta was already applied this day.<br/>
--- * toilet_meters_today_evening (boolean) Whether the home (after work) toilet meter delta was already applied this day.<br/>
--- * coworker_discussion_meter_applied_today (boolean) Whether the daily coworker discussion meter roll was already applied this day.<br/>
--- * sumphore_discussion_meter_applied_today (boolean) Whether the daily sumphore discussion meter roll was already applied this day.<br/>
--- * game (table) Current game progress state. Contains: `current_screen` (string) active screen ID<br/> --- * game (table) Current game progress state. Contains: `current_screen` (string) active screen ID<br/>
function Context.initial_data() function Context.initial_data()
return { return {
@@ -49,10 +45,6 @@ function Context.initial_data()
home_norman_visible = false, home_norman_visible = false,
have_been_to_office = false, have_been_to_office = false,
have_done_work_today = false, have_done_work_today = false,
toilet_meters_today_morning = false,
toilet_meters_today_evening = false,
coworker_discussion_meter_applied_today = false,
sumphore_discussion_meter_applied_today = false,
should_ascend = false, should_ascend = false,
have_met_sumphore = false, have_met_sumphore = false,
office_sprites = {}, office_sprites = {},
@@ -110,15 +102,15 @@ function Context.new_game()
MysteriousManScreen.start({ MysteriousManScreen.start({
text = [[ text = [[
Norman was never a bad Norman was never a bad
...
simulation engineer, simulation engineer,
...
but but
...
we need to be careful we need to be careful
...
letting him improve. letting him improve.
...
We need to distract him. We need to distract him.
]], ]],
on_text_complete = function() on_text_complete = function()
@@ -132,9 +124,8 @@ function Context.new_game()
target_points = 100, target_points = 100,
instruction_text = "Wake up Norman!", instruction_text = "Wake up Norman!",
show_progress_text = false, show_progress_text = false,
meter_on_complete = Meter.apply_wakeup_reward,
on_win = function() on_win = function()
Audio.music_play_room_work() Audio.music_play_wakingup()
Meter.show() Meter.show()
Window.set_current("game") Window.set_current("game")
end, end,

View File

@@ -1,60 +0,0 @@
--- @section CodeGenerator
CodeGenerator = {}
local SALT = 27471
local BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local NAME_LEN = 3
-- Per-position offsets derived from SALT so each character slot
-- maps to a different region of the 2-char base-36 space.
local SALTS = {
SALT % 36,
math.floor(SALT / 36) % 36,
math.floor(SALT / 1296) % 36,
}
--- Encodes a number (0935) as exactly 2 base-36 characters.
--- @within CodeGenerator
function CodeGenerator.encode_pair(n)
return BASE36:sub(math.floor(n / 36) + 1, math.floor(n / 36) + 1)
.. BASE36:sub(n % 36 + 1, n % 36 + 1)
end
--- Decodes 2 base-36 characters back to a number.
--- @within CodeGenerator
function CodeGenerator.decode_pair(s)
local d1 = BASE36:find(s:sub(1, 1), 1, true) - 1
local d2 = BASE36:find(s:sub(2, 2), 1, true) - 1
return d1 * 36 + d2
end
--- Encrypts a player name into a code twice its length.
--- Each input character (A-Z, value 0-25) is encoded as
--- c + SALTS[i] * 26, producing 2 base-36 output characters.
--- @within CodeGenerator
--- @param text string NAME_LEN-character uppercase player name.
--- @return string Encrypted code (2 * NAME_LEN base-36 characters).
function CodeGenerator.encrypt(text)
local result = ""
for i = 1, NAME_LEN do
local c = math.max(0, (string.byte(text, i) or 65) - 65)
result = result .. CodeGenerator.encode_pair(c + SALTS[i] * 26)
end
return result
end
--- Decrypts a personal code back to the original player name.
--- @within CodeGenerator
--- @param encrypted_text string The code to decrypt (2 * NAME_LEN chars).
--- @return string Original player name, or "???" if the code is invalid.
function CodeGenerator.decrypt(encrypted_text)
local t = encrypted_text:upper()
if #t ~= NAME_LEN * 2 then return "???" end
local result = ""
for i = 1, NAME_LEN do
local pair = CodeGenerator.decode_pair(t:sub((i - 1) * 2 + 1, i * 2))
result = result .. string.char(pair % 26 + 65)
end
return result
end

View File

@@ -8,10 +8,6 @@ function Day.increase()
if Context.day_count == 3 then if Context.day_count == 3 then
Context.should_ascend = true Context.should_ascend = true
end end
if Context.day_count >= 100 and not Ascension.is_complete() then
GameOverWindow.show("days")
return
end
for _, handler in ipairs(_day_increase_handlers) do for _, handler in ipairs(_day_increase_handlers) do
handler() handler()
end end
@@ -31,13 +27,6 @@ Day.register_handler(function()
m.bm = math.max(0, m.bm - METER_DECAY_PER_DAY) m.bm = math.max(0, m.bm - METER_DECAY_PER_DAY)
end) end)
Day.register_handler(function()
Context.toilet_meters_today_morning = false
Context.toilet_meters_today_evening = false
Context.coworker_discussion_meter_applied_today = false
Context.sumphore_discussion_meter_applied_today = false
end)
Day.register_handler(function() Day.register_handler(function()
if Context.should_ascend then if Context.should_ascend then
Ascension.increase() Ascension.increase()

View File

@@ -1,8 +1,6 @@
--- @section Meter --- @section Meter
local METER_MAX = 1000 local METER_MAX = 1000
local BM_METER_DEFAULT = 200 local METER_DEFAULT = 500
local ISM_METER_DEFAULT = 500
local WPM_METER_DEFAULT = 200
local METER_GAIN_PER_CHORE = 100 local METER_GAIN_PER_CHORE = 100
local METER_DECAY_PER_DAY = 20 local METER_DECAY_PER_DAY = 20
local COMBO_BASE_BONUS = 0.02 local COMBO_BASE_BONUS = 0.02
@@ -10,11 +8,10 @@ local COMBO_MAX_BONUS = 0.16
local COMBO_TIMEOUT_FRAMES = 600 local COMBO_TIMEOUT_FRAMES = 600
-- Internal meters for tracking game progress and player stats. -- Internal meters for tracking game progress and player stats.
Meter.COLOR_ISM = Config.colors.orange Meter.COLOR_ISM = Config.colors.red
Meter.COLOR_WPM = Config.colors.blue Meter.COLOR_WPM = Config.colors.blue
Meter.COLOR_BM = Config.colors.red Meter.COLOR_BM = Config.colors.black
Meter.COLOR_BG = Config.colors.meter_bg Meter.COLOR_BG = Config.colors.meter_bg
Meter.COLOR_CONTOUR = Config.colors.white
--- Gets initial meter values. --- Gets initial meter values.
--- @within Meter --- @within Meter
@@ -28,9 +25,9 @@ Meter.COLOR_CONTOUR = Config.colors.white
--- * hidden (boolean) Whether meters are hidden. --- * hidden (boolean) Whether meters are hidden.
function Meter.get_initial() function Meter.get_initial()
return { return {
ism = ISM_METER_DEFAULT, ism = METER_DEFAULT,
wpm = WPM_METER_DEFAULT, wpm = METER_DEFAULT,
bm = BM_METER_DEFAULT, bm = METER_DEFAULT,
combo = 0, combo = 0,
combo_timer = 0, combo_timer = 0,
hidden = false, hidden = false,
@@ -105,127 +102,20 @@ function Meter.add(key, amount)
if not Context or not Context.meters then return end if not Context or not Context.meters then return end
local m = Context.meters local m = Context.meters
if m[key] ~= nil then if m[key] ~= nil then
if amount > 0 and (key == "ism" or key == "bm") and m[key] >= METER_MAX then m[key] = math.min(METER_MAX, m[key] + amount)
GameOverWindow.show(key)
return
end
m[key] = math.max(0, math.min(METER_MAX, m[key] + amount))
end end
end end
--- Called on minigame completion. --- Called on minigame completion.
--- @within Meter --- @within Meter
--- @param is_work boolean If true (work-style minigame), apply combo to WPM/ISM/BM and advance combo. DDR uses `Meter.apply_ddr_reward` instead. Otherwise flat equal gain, combo unchanged. function Meter.on_minigame_complete()
function Meter.on_minigame_complete(is_work)
local m = Context.meters local m = Context.meters
if is_work then local gain = math.floor(METER_GAIN_PER_CHORE * Meter.get_combo_multiplier())
local mult = Meter.get_combo_multiplier() Meter.add("wpm", gain)
local wpm_delta = math.floor(METER_GAIN_PER_CHORE / mult) Meter.add("ism", gain)
local ism_bm_delta = math.floor(METER_GAIN_PER_CHORE * mult) Meter.add("bm", gain)
Meter.add("wpm", wpm_delta)
Meter.add("ism", ism_bm_delta)
Meter.add("bm", ism_bm_delta)
m.combo = m.combo + 1 m.combo = m.combo + 1
m.combo_timer = 0 m.combo_timer = 0
else
local flat = METER_GAIN_PER_CHORE
Meter.add("wpm", flat)
Meter.add("ism", flat)
Meter.add("bm", flat)
end
end
--- Meter changes after DDR: uses max-meter percentages; combo advances like other work minigames.
--- 0 mistakes: WPM 10%, ISM +5%, BM +5%. 13: WPM 5%, ISM +10%, BM +10%. More than 3: WPM unchanged, ISM +10%, BM +10%.
--- @within Meter
--- @param mistake_count number Total mistakes (missed arrows, wrong inputs, and special-mode rule violations).
function Meter.apply_ddr_reward(mistake_count)
if not Context or not Context.meters then return end
local max = Meter.get_max()
local m = Context.meters
local wpm_pct, ism_pct, bm_pct
if mistake_count == 0 then
wpm_pct, ism_pct, bm_pct = -0.10, 0.05, 0.05
elseif mistake_count <= 3 then
wpm_pct, ism_pct, bm_pct = -0.05, 0.10, 0.10
else
wpm_pct, ism_pct, bm_pct = 0, 0.10, 0.10
end
if wpm_pct ~= 0 then
Meter.add("wpm", math.floor(max * wpm_pct))
end
if ism_pct ~= 0 then
Meter.add("ism", math.floor(max * ism_pct))
end
if bm_pct ~= 0 then
Meter.add("bm", math.floor(max * bm_pct))
end
m.combo = m.combo + 1
m.combo_timer = 0
end
--- Meter changes for the wake-up button mash: faster completion is better for WPM.
--- Perfect: under 2s — WPM +20%. Good: 23s — WPM +10%, ISM +5%, BM +5%. Bad: over 3s — WPM 5%, ISM +10%, BM +10%.
--- @within Meter
--- @param elapsed_sec number Seconds from minigame start until the bar was filled.
function Meter.apply_wakeup_reward(elapsed_sec)
if not Context or not Context.meters then return end
local max = Meter.get_max()
local wpm_pct, ism_pct, bm_pct
if elapsed_sec < 2 then
wpm_pct, ism_pct, bm_pct = 0.20, 0, 0
elseif elapsed_sec <= 3 then
wpm_pct, ism_pct, bm_pct = 0.10, 0.05, 0.05
else
wpm_pct, ism_pct, bm_pct = -0.05, 0.10, 0.10
end
if wpm_pct ~= 0 then
Meter.add("wpm", math.floor(max * wpm_pct))
end
if ism_pct ~= 0 then
Meter.add("ism", math.floor(max * ism_pct))
end
if bm_pct ~= 0 then
Meter.add("bm", math.floor(max * bm_pct))
end
end
--- Random single meter shift after finishing a coworker discussion: ISM +10%, WPM 10%, or BM +10%.
--- @within Meter
function Meter.apply_coworker_discussion_reward()
if not Context or not Context.meters then return end
if Context.coworker_discussion_meter_applied_today then return end
local max = Meter.get_max()
local delta = math.floor(max * 0.10)
local roll = math.random(1, 3)
if roll == 1 then
Meter.add("ism", delta)
elseif roll == 2 then
Meter.add("wpm", -delta)
else
Meter.add("bm", delta)
end
Context.coworker_discussion_meter_applied_today = true
end
--- After finishing a sumphore discussion: reduce whichever of ISM / WPM / BM is highest by 10% of max (stable tie to ISM, then WPM, then BM).
--- @within Meter
function Meter.apply_sumphore_discussion_reward()
if not Context or not Context.meters then return end
if Context.sumphore_discussion_meter_applied_today then return end
local m = Context.meters
local max = Meter.get_max()
local delta = math.floor(max * 0.10)
local biggest_val_key = "ism"
local biggest_val = m.ism
for _, key in ipairs({ "wpm", "bm" }) do
if m[key] > biggest_val then
biggest_val = m[key]
biggest_val_key = key
end
end
Meter.add(biggest_val_key, -delta)
Context.sumphore_discussion_meter_applied_today = true
end end
--- Draws meters. --- Draws meters.
@@ -236,16 +126,16 @@ function Meter.draw()
local m = Context.meters local m = Context.meters
local max = Meter.get_max() local max = Meter.get_max()
local screen_w = Config.screen.width local bar_w = 44
local screen_h = Config.screen.height
local bar_w = screen_w * 0.25
local bar_h = 2 local bar_h = 2
local edge = math.max(2, math.floor(screen_w * 0.03)) local bar_x = 182
local bar_x = screen_w - bar_w - edge local label_x = 228
local line_h = 3 local line_h = 5
local start_y = screen_h * 0.05 local start_y = 1
local bar_offset = math.floor((line_h - bar_h) / 2)
local meter_list = { local meter_list = {
{ key = "wpm", label = "WPM", color = Meter.COLOR_WPM, row = 0 }, { key = "wpm", label = "WPM", color = Meter.COLOR_WPM, row = 0 },
{ key = "ism", label = "ISM", color = Meter.COLOR_ISM, row = 1 }, { key = "ism", label = "ISM", color = Meter.COLOR_ISM, row = 1 },
@@ -254,16 +144,15 @@ function Meter.draw()
for _, meter in ipairs(meter_list) do for _, meter in ipairs(meter_list) do
local label_y = start_y + meter.row * line_h local label_y = start_y + meter.row * line_h
local bar_y = label_y local bar_y = label_y + bar_offset
local fill_w = math.max(0, math.floor((m[meter.key] / max) * bar_w)) local fill_w = math.max(0, math.floor((m[meter.key] / max) * bar_w))
rect(bar_x - 1, bar_y - 1, bar_w + 2, bar_h + 2, Meter.COLOR_CONTOUR)
rect(bar_x, bar_y, bar_w, bar_h, Meter.COLOR_BG) rect(bar_x, bar_y, bar_w, bar_h, Meter.COLOR_BG)
if fill_w > 0 then if fill_w > 0 then
rect(bar_x, bar_y, fill_w, bar_h, meter.color) rect(bar_x, bar_y, fill_w, bar_h, meter.color)
end end
---print(meter.label, label_x, label_y, meter.color, false, 1, true) print(meter.label, label_x, label_y, meter.color, false, 1, true)
end end
local ascension_y = start_y + 3 * line_h + 1 local ascension_y = start_y + 3 * line_h + 1
Ascension.draw(bar_x, ascension_y, { spacing = 8 }) Ascension.draw(bar_x, ascension_y, { spacing = 5 })
end end

View File

@@ -12,9 +12,8 @@ function Minigame.draw_win_overlay(win_text)
local box_h = th + padding * 2 local box_h = th + padding * 2
local box_x = (Config.screen.width - box_w) / 2 local box_x = (Config.screen.width - box_w) / 2
local box_y = (Config.screen.height - box_h) / 2 local box_y = (Config.screen.height - box_h) / 2
local text_x = Config.screen.width / 2
rect(box_x, box_y, box_w, box_h, Config.colors.dark_grey) rect(box_x, box_y, box_w, box_h, Config.colors.dark_grey)
rectb(box_x, box_y, box_w, box_h, Config.colors.white) rectb(box_x, box_y, box_w, box_h, Config.colors.white)
Print.text_center_contour(text, text_x, box_y + padding, Config.colors.black, false, 1, Config.colors.white) Print.text_center(text, Config.screen.width / 2, box_y + padding, Config.colors.white)
end end

View File

@@ -2,7 +2,7 @@
-- 000:0404005f574fc2c3c71d2b53fff1e8ab52367e2553ffa30000875129adff83769c00e436fa77a8ff004dc3c3c7ffccaa -- 000:0404005f574fc2c3c71d2b53fff1e8ab52367e2553ffa30000875129adff83769c00e436fa77a8ff004dc3c3c7ffccaa
-- </PALETTE> -- </PALETTE>
-- <TILES> -- <TILES>
-- 000:0000000006666660066060600636366006606060060636600666666000000000 -- 000:00000000c666666006606060c636366006606060c606366006666660c0000000
-- 001:0000000006666666060600600666666606000600066666660633633300000000 -- 001:0000000006666666060600600666666606000600066666660633633300000000
-- 002:0000000066666666006000066666666660060006666666666333363300000000 -- 002:0000000066666666006000066666666660060006666666666333363300000000
-- 004:1111111111111111111111111111111111111111111111111111111111111111 -- 004:1111111111111111111111111111111111111111111111111111111111111111
@@ -17,7 +17,7 @@
-- 013:1000000004444444044444440444444404444444044444440444444404444444 -- 013:1000000004444444044444440444444404444444044444440444444404444444
-- 014:0000000144444240444424204444424044442420444442404444242044444240 -- 014:0000000144444240444424204444424044442420444442404444242044444240
-- 015:0000000004244444024444440424400002444444042424240242424200000000 -- 015:0000000004244444024444440424400002444444042424240242424200000000
-- 016:0000000044444420444442400004442044444240e42424204242424000000000 -- 016:000000004444442044444240c004442044444240e424242042424240c0000000
-- 017:0000000002424240042424200244444004244440024404400424044002440440 -- 017:0000000002424240042424200244444004244440024404400424044002440440
-- 018:0000000002424240042424200444424004444420044042400440442004404240 -- 018:0000000002424240042424200444424004444420044042400440442004404240
-- 019:0222222200010012055016020150660205501602015066020550160200000000 -- 019:0222222200010012055016020150660205501602015066020550160200000000
@@ -33,7 +33,7 @@
-- 029:0440442004404240044044200444424004444420024242400424242000000000 -- 029:0440442004404240044044200444424004444420024242400424242000000000
-- 030:0000000006666660036060600360666006606060036660600360666003606060 -- 030:0000000006666660036060600360666006606060036660600360666003606060
-- 031:0222222200010010033033030130130103303303013013010330330300000000 -- 031:0222222200010010033033030130130103303303013013010330330300000000
-- 032:2222222001001220303302203013022030330220301302203033022000000000 -- 032:22222220c10012203033022030130220303302203013022030330220c0000000
-- 033:0333011103330111033301110333011103330111033301110333011100000000 -- 033:0333011103330111033301110333011103330111033301110333011100000000
-- 034:1110011111100111111001111110011111100111111001111110011100000000 -- 034:1110011111100111111001111110011111100111111001111110011100000000
-- 035:1110333011103330111033301110333011103330111033301110333000000000 -- 035:1110333011103330111033301110333011103330111033301110333000000000
@@ -49,7 +49,7 @@
-- 045:2222222022222220222222202222222022222220000000001111100011111000 -- 045:2222222022222220222222202222222022222220000000001111100011111000
-- 046:1111111111111111111111111000000002222222022222220222222202222222 -- 046:1111111111111111111111111000000002222222022222220222222202222222
-- 047:1111111111111111111111110000000022222222222222222222222222222222 -- 047:1111111111111111111111110000000022222222222222222222222222222222
-- 048:1111111111111111111111110000100022220444e222044422220444e2220444 -- 048:111111111111111111111111c000100022220444e222044422220444e2220444
-- 049:1111111111111111111111111100001100222201022222200222222002222220 -- 049:1111111111111111111111111100001100222201022222200222222002222220
-- 050:1111111011111110111111101111111011111110111111101111111011110000 -- 050:1111111011111110111111101111111011111110111111101111111011110000
-- 051:1111111111111111111111111111111111111111111111111111111100011111 -- 051:1111111111111111111111111111111111111111111111111111111100011111
@@ -81,7 +81,7 @@
-- 077:0000000011111110000000006611166655555551555555515555555166666111 -- 077:0000000011111110000000006611166655555551555555515555555166666111
-- 078:1111111111111111111100001110919111101010110191011019191000919190 -- 078:1111111111111111111100001110919111101010110191011019191000919190
-- 079:1111111111111111000000009191919000000010111110901111101000000090 -- 079:1111111111111111000000009191919000000010111110901111101000000090
-- 080:0919199009919902091990200999020209902020090202020020202000000000 -- 080:09191990c991990209199020c999020209902020c902020200202020c0000000
-- 081:0000000002020200202020200200022020002220000222202022222002222220 -- 081:0000000002020200202020200200022020002220000222202022222002222220
-- 082:5555555555555055555501056666010155550105555501055555010566610106 -- 082:5555555555555055555501056666010155550105555501055555010566610106
-- 083:5555555555555555000000000222222202222222022222220222222202222222 -- 083:5555555555555555000000000222222202222222022222220222222202222222
@@ -97,7 +97,7 @@
-- 093:0222022002220220022202200222022002220220022202200222022002220220 -- 093:0222022002220220022202200222022002220220022202200222022002220220
-- 094:1033330110333301103333011033330110333301103333011033330110000001 -- 094:1033330110333301103333011033330110333301103333011033330110000001
-- 095:3333101033331090333310103333109011113010111130901111301011113000 -- 095:3333101033331090333310103333109011113010111130901111301011113000
-- 096:0000000001111111000000000106666601051555010515550105655500066611 -- 096:00000000c111111100000000c106666601051555c105155501056555c0066611
-- 097:0000000011111110000000006666101055555010555550105555501066616000 -- 097:0000000011111110000000006666101055555010555550105555501066616000
-- 098:5555555555555550555555056666116655550055555500555555655566666611 -- 098:5555555555555550555555056666116655550055555500555555655566666611
-- 099:0555555500555555050555550661111105500555115005550055555500616666 -- 099:0555555500555555050555550661111105500555115005550055555500616666
@@ -113,7 +113,7 @@
-- 109:1111111011111110111111101111111011111110111111100000000566000066 -- 109:1111111011111110111111101111111011111110111111100000000566000066
-- 110:1111111111111111111111111111010011101044111010441110104400000010 -- 110:1111111111111111111111111111010011101044111010441110104400000010
-- 111:1111111111111111111111110011111144011111440111114401111110000000 -- 111:1111111111111111111111110011111144011111440111114401111110000000
-- 112:1111111111111111111111111111111111111111111111111111011100004000 -- 112:11111111111111111111111111111111111111111111111111110111c0004000
-- 113:3333104433331044333310003333111111113333111133331111333311113333 -- 113:3333104433331044333310003333111111113333111133331111333311113333
-- 114:4403111144031111000311113333111111110000111044441104444411014444 -- 114:4403111144031111000311113333111111110000111044441104444411014444
-- 115:3304440133044401330444013304440100104033440103334440333344103333 -- 115:3304440133044401330444013304440100104033440103334440333344103333
@@ -177,7 +177,7 @@
-- 173:0333333010333330103333301033333010333330100000001111111111111111 -- 173:0333333010333330103333301033333010333330100000001111111111111111
-- 174:111111111111111111111111111111111111111112222222a1a1a1a21a1a1a12 -- 174:111111111111111111111111111111111111111112222222a1a1a1a21a1a1a12
-- 175:1111111111111111111111111111111111111111444444444444444444444444 -- 175:1111111111111111111111111111111111111111444444444444444444444444
-- 176:0000000001111110011010100131311001101010010131100111111000000000 -- 176:00000000c111111001101010c131311001101010c101311001111110c0000000
-- 177:0000000001111111010100100111111101000100011111110133133300000000 -- 177:0000000001111111010100100111111101000100011111110133133300000000
-- 178:0000000011111111001000011111111110010001111111111333313300000000 -- 178:0000000011111111001000011111111110010001111111111333313300000000
-- 179:11111111111111111111111111111111111100001110b161110b100010810101 -- 179:11111111111111111111111111111111111100001110b161110b100010810101
@@ -225,7 +225,7 @@
-- 221:0200000002000000020000000200000002000000020000000211111100000000 -- 221:0200000002000000020000000200000002000000020000000211111100000000
-- 222:0000000000000000000000000000000000000000000000001111111100000000 -- 222:0000000000000000000000000000000000000000000000001111111100000000
-- 223:000000000000000000000000000000000000000000000000111dd11100000000 -- 223:000000000000000000000000000000000000000000000000111dd11100000000
-- 224:0000001000000010000000100000001000000010000000101111111000000000 -- 224:00000010c000001000000010c000001000000010c000001011111110c0000000
-- 225:3333333333333333333333333333333313131313313131311313131331313131 -- 225:3333333333333333333333333333333313131313313131311313131331313131
-- 226:0203333302033333020333330203333302031313020131310203131300013131 -- 226:0203333302033333020333330203333302031313020131310203131300013131
-- 227:3333302033333020333330203333302013131020313130201313102031313000 -- 227:3333302033333020333330203333302013131020313130201313102031313000
@@ -241,7 +241,7 @@
-- 237:1444402044140220444402204144022000402220220222200222222010222220 -- 237:1444402044140220444402204144022000402220220222200222222010222220
-- 238:3333330033333022333302223333022213130222313102221313101231313100 -- 238:3333330033333022333302223333022213130222313102221313101231313100
-- 239:0003010322200103222201032222010322220103222201012210101300013131 -- 239:0003010322200103222201032222010322220103222201012210101300013131
-- 240:0222011102220011022200000222033302220333022220000222222202222222 -- 240:02220111c222001102220000c222033302220333c222200002222222c2222222
-- 241:1002222001202220002022203002222031222220022222202222222022222220 -- 241:1002222001202220002022203002222031222220022222202222222022222220
-- 242:3333333333333330333333033333113313130013313100311313131331313131 -- 242:3333333333333330333333033333113313130013313100311313131331313131
-- 243:0333333300333333030333330331133303100313113001310013131300313131 -- 243:0333333300333333030333330331133303100313113001310013131300313131
@@ -251,281 +251,149 @@
-- 247:0000000011111110000000003333301013131010313130101313101031313000 -- 247:0000000011111110000000003333301013131010313130101313101031313000
-- </TILES> -- </TILES>
-- <SPRITES> -- <SPRITES>
-- 000:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 002:00000000000000000000444400044444000444440044ffff004fffff004f3333
-- 001:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 003:0000000000000000441600004242600044241000ff426000fff4100033f26000
-- 002:cccccccccccc0000ccc04444cc044444cc044444c044ffffc04fffffc04f3333 -- 004:00000333000035550003655500365555003555ff00356fff00365f3f00355fff
-- 003:cccccccc0000cccc44160ccc424260cc442410ccff4260ccfff410cc00f260cc -- 005:33000000553000005563000055563000ff553000fff53000f3f63000fff53000
-- 004:ccccc000cccc0555ccc06555cc065555cc0555ffcc056fffcc065f0fcc055fff -- 008:0000005a00005a55000055a50000a55a00005a5700005533000575f30000757f
-- 005:00cccccc550ccccc5560cccc55560cccff550cccfff50cccf0f60cccfff50ccc -- 009:55a50000a55a50005a55a00057555500fff7a5003f335a00fff3f500fffffa00
-- 006:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 016:0000000000000000000000000000003000000353000035350003535100353535
-- 007:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 017:0000000000000000000000003000000053300000151300005151300015151300
-- 008:cccc0000ccc05a55ccc055a5ccc0a55accc05a57ccc05533cc0575f3ccc0757f -- 018:004f99ff000fffff0000ff3300000fff00003666000355550035652503163555
-- 009:00000ccca55a50cc5a55a0cc5755550cfff7a50c3f335a0cfff3f50cfffffa0c -- 019:99f41000fff26000ff600000f600000063300000555330005555530055535530
-- 010:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 020:00356f6f003655f60365511f3653122f3531222f363221220532232203322322
-- 011:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 021:f6f530006f563000f1156300f2215300f2226300221233002232130022121300
-- 012:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 022:000000000000005100000155000055150000157f0000551300057f3f00017fff
-- 013:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 023:00000000555000005155000015515000ff7f5100ff31f200fff3ff0033fff200
-- 014:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 024:0000057f00000005000000050000559900055911005599110055119900551199
-- 015:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 025:f3ff5000fff500005f5000004415100077995100449915007711955044119550
-- 016:cccccccccccccccccccccccccccccc0cccccc050cccc0535ccc05351cc053535 -- 026:00000000000001330001331300031333001333330031f7f7001133390031999f
-- 017:cccccccccccccccccccccccc0ccccccc500ccccc1510cccc51510ccc151510cc -- 027:0000000013310000131330003333130033333100f7f113003337310099975300
-- 018:c04f99ffcc0fffffccc0ff00cccc0fffcccc0666ccc05555cc056525c0160555 -- 028:000000000000000000000a77000057770005777700577777005775a50077a7ff
-- 019:99f410ccfff260ccff600cccf60ccccc600ccccc55500ccc555550cc5550550c -- 029:0000000000000000777a0000777750007777750077777750a5a57750fff7a770
-- 020:cc056f6fcc0655f6c065511f0650122f0501222f06022122c5022322c0022322 -- 030:000000000000051500001151000555550001517f000557ff0001ff3f0007ff1f
-- 021:f6f50ccc6f560cccf11560ccf22150ccf22260cc221230cc223210cc221210cc -- 031:00000000150000005110000055500000f7110000ff750000f3f10000f1f50000
-- 022:cccccc00ccccc051cccc0155ccc05515ccc0157fccc05513cc057f0fcc017fff -- 032:0033535100353533003351ff00351f3f0003ff3f0003ffff00003ff3000323ff
-- 023:000ccccc5550cccc51550ccc155150ccff7f510cff31f20cfff0ff0c00fff20c -- 033:5555530033555300ff155300f3f15300f3ff3000ffff30003ff30000ff323000
-- 024:cccc057fccccc005cccc0555ccc05599cc055911c0559911c0551199c0551199 -- 034:036135250316355503613525031633110333331103f333330333333300033333
-- 025:f3ff50ccfff50ccc5f50cccc441500cc7799510c4499150c7711955044119550 -- 035:55565530555355305556553013335530133333303333ff303333333033330000
-- 026:ccccc000ccc00133cc013313cc031333c0133333c031f7f7c0113339c031999f -- 036:00322322003223330033331a003ff31a003ff3a1003333a100003a1a00003a1a
-- 027:0000cccc13310ccc131330cc3333130c3333310cf7f1130c3337310c9997530c -- 037:223213003332130011133300111f300011133000111300001113000011130000
-- 028:ccccccccccccc000cccc0a77ccc05777cc057777c0577777c05775a5c077a7ff -- 038:000007ff0001117f0016171f0155175501561755155117555f7157555ff15755
-- 029:cccccccc0000cccc777a0ccc777750cc7777750c77777750a5a57750fff7a770 -- 039:fffff700333f2000ffff7100555571105555716155557111555575ff555575ff
-- 030:ccccc000cccc0515ccc01151cc055555cc01517fcc0557ffcc01ff0fcc07ff1f -- 040:005599110055991100ff533300fff511007fff110007f5110000311300003113
-- 031:00cccccc150ccccc5110cccc5550ccccf7110cccff750cccf0f10cccf1f50ccc -- 041:479915504499155047333f7014113ff011113f70111130003311300003113000
-- 032:cc035351cc053500cc0351ffcc051f0fccc0ff0fccc0ffffcccc0ff0ccc020ff -- 042:0035777f0001776600005777000000550088885508bbb84508bbb8448bb8b844
-- 033:555550cc005550ccff1550ccf0f150ccf0ff0cccffff0ccc0ff0ccccff020ccc -- 043:77775300677500007750000055880000558b8000548bb800228bbb80428b8b80
-- 034:c0613525c0163555c0613525c0163311c0003311c0f03333cc003333ccc03333 -- 044:005a7f3f0057ff3f07f7ffff07757fdf077a57fd0575357f005a66a70006aa6f
-- 035:5556550c5553550c5556550c1330550c1330000c3330ff0c333000cc3330cccc -- 045:ff3f7a50ff3ff750fffff777ffdf7577ddf75a77ff75157577a66a50ff6aa600
-- 036:cc022322cc022333cc03331acc0ff31acc0ff3a1ccc003a1cccc0a1acccc0a1a -- 046:0005ffff00005ff3000005ff0017775500242777002121710024277100212171
-- 037:223210cc333210cc111300cc111f0ccc11100ccc1110cccc1110cccc1110cccc -- 047:fff500003f500000f50000005771000077720000171200001772000017120000
-- 038:ccc007ffcc01117fc016171f0155175501561755055117550f7157550ff15755 -- 048:00323123003231430032314300313339000f3333000033300000333000033330
-- 039:fffff70c000f20ccffff710c555571105555716055557110555575f0555575f0 -- 049:324303003443030034430300933313003333f000033300000333000003333000
-- 040:c0559911c0559911c0ff5333c0fff511c07fff11cc07f511ccc03110cccc0110 -- 050:0003333000033330000333300003333000053530003311300031113000333330
-- 041:479915504499155047333f7014113ff011113f701111000c00110cccc0110ccc -- 051:3333000033330000333300003333000035350000311330003111300033333000
-- 042:c035777fcc017766ccc05777cc088855c08bb85508bbb84508bbb8440bb8b844 -- 052:000031a1000031a100003a1a00003a1a00003333000003f3000003f300000330
-- 043:7777530c677500cc7750cccc55880ccc558b80cc548bb80c228bbb80428b8b80 -- 053:111300001113000011130000111300003333000003f3000003f3000003300000
-- 044:cc0a7f3fc075ff3f0777ffff07757fdf077a57fd0575357fc05a66a7cc06aa6f -- 054:5ff7646607f59999000991330003993000099130000133300001221000011100
-- 045:ff3f7a0cff3ff70cfffff770ffdf7570ddf75a70ff75157077a66a50ff6aa60c -- 055:666646ff999993f7339913000039930000991300001333000012210000111000
-- 046:cc05ffffccc05ff3cccc05ffcc007755c0242777c0212171c0242771c0212171 -- 056:0000311300003113000031130000311300003113000033330000165100001111
-- 047:fff50ccc3f50ccccf50ccccc5770cccc77720ccc17120ccc17720ccc17120ccc -- 057:0311300003113000031130000311300003113000033330000165100001111000
-- 048:cc020123cc020143cc020143cc010309cc0f0300ccc0030ccccc030cccc0000c -- 058:8888b8445f78b8445f58884405031330000331300003133000053550000577f0
-- 049:324030cc344030cc344030cc903010cc0030f0ccc0300cccc030ccccc0000ccc -- 059:218b8880428b87f5218885f5031330500331300003133000053550000577f000
-- 050:ccc0330cccc0330cccc0330cccc0330cccc0350ccc03110ccc01110ccc00000c -- 060:0056aa66001f6aaa001fa666007f6aaa00006aaa0000a666000007d7000001d1
-- 051:0330cccc0330cccc0330cccc0330cccc0530cccc01130ccc01110ccc00000ccc -- 061:666aa650aaaa6f106666af10aaaa6f70aaaa60006666a000007d7000001d1000
-- 052:cccc01a1cccc01a1cccc0a1acccc0a1acccc0000ccccc0f0ccccc0f0ccccc00c -- 062:0024277700ff611100fff333005f533300003333000033300000333000001110
-- 053:1110cccc1110cccc1110cccc1110cccc0000ccccc0f0ccccc0f0ccccc00ccccc -- 063:77720000116f0000335ff000333f000033300000333000003330000001110000
-- 054:0ff7646607f59999c0099100cc03990ccc09910ccc01330ccc01220ccc0000cc -- 064:00000000000000000000011100003311000111170003317f000117ff00553333
-- 055:666646f0999993f00099100cc03990ccc09910ccc01330ccc01220ccc0000ccc -- 065:0000000000000000110000001110000077110000ff710000ff77000013330000
-- 056:cccc0110cccc0110cccc0110cccc0110cccc0110cccc0330cccc0650cccc0000 -- 066:00000000000000330000033300003333000033f7000035ff000535ff0007f333
-- 057:c0110cccc0110cccc0110cccc0110cccc0110cccc0330cccc0650cccc0000ccc -- 067:0000000030000000333300003333000037f30000ffff0000ffff0000f333f000
-- 058:0888b8440f78b8440f58884405031300c0c0310cccc0130cccc0350cccc0000c -- 068:000000000000000000000000000000000000000000000122000012440001447f
-- 059:218b8880428b87f0218885f000130050c0310c0cc0130cccc0350cccc0000ccc -- 069:00000000000000000000000000000000000000002210000044210000f7441000
-- 060:c056aa66c01f6aaac01fa666c07f6aaacc0f6aaaccc0a666cccc07d7cccc0000 -- 070:000000000000000000000333000038880003888800388881038388310338835f
-- 061:666aa650aaaa6f106666af10aaaa6f70aaaa600c6666a0cc007d70cccc0000cc -- 071:00000000000000003330000088880000883380003355380016665300f7ff7300
-- 062:c0242777c0ff6111c0fff333c05f5333cc003300cccc030ccccc030ccccc000c -- 072:0000000000000000000000550000055500005577000057ff00007f55000fff33
-- 063:77720ccc116f0ccc335ff0cc333f0ccc0330cccc030ccccc030ccccc0000cccc -- 073:0000000000000000555550005555550077777550ffffff507f755f703f333fff
-- 064:ccccccccccccc000cccc0111ccc03311cc011117cc03317fcc0117ffc0553333 -- 074:0000000000000011000001130000113100011313000131310013137c003131ff
-- 065:cccccccc00cccccc110ccccc1110cccc77110cccff710cccff770ccc13330ccc -- 075:000000001110000013110000313110001313100031313100ffff7100fffff100
-- 066:cccccc00ccccc033cccc0333ccc03333ccc033f7ccc035ffcc0535ffcc07f333 -- 076:0000000000000055000005550000055500005577000057ff0007ff55000fff99
-- 067:0ccccccc3000cccc33330ccc33330ccc37f30cccffff0cccffff0cccf333f0cc -- 077:0000000055550000555550005555500075775500fffff5005f555f703f993ff0
-- 068:ccccccccccccccccccccccccccccccccccccc000cccc0122ccc01244cc01447f -- 078:0000000000000000000000000000000000001111000014440000144400001555
-- 069:cccccccccccccccccccccccccccccccc000ccccc2210cccc44210cccf74410cc -- 079:0000000000000000000000000000000011100000441000004410000055100000
-- 070:ccccccccccccccccccccc000cccc0888ccc08888cc088880c0838801c038805f -- 080:0077533f000ff77f0005fff500005ff70000015f0005f315005ff3ff00ff3333
-- 071:cccccccccccccccc0000cccc88880ccc880080cc0055080c1666530cf7ff730c -- 081:f33f0000f77f00005ff000007f500000f500000053f00000f3f50000333f0000
-- 072:cccccccccccccc00ccccc055cccc0555ccc05577ccc057ffccc07f55cc0fff33 -- 082:000fff330005ffff000057f50000007f000333350031313f0031313303113133
-- 073:cccccccc00000ccc555550cc5555550c77777550ffffff507f755f703f333ff0 -- 083:ff33f000ffff100055f10000ff70000055330000ff3130003331300033311300
-- 074:cccccccccccccc00ccccc013cccc0131ccc01313ccc03131cc031377cc0131ff -- 084:000447ff000fffff0007f33f000ff11f000f7fff0000ff750000042400001142
-- 075:cccccccc000ccccc1310cccc31310ccc13130ccc313130ccffff70ccfffff0cc -- 085:ff744000ffff1000f33f7000f11f5000fff7f00057ff00004240000044110000
-- 076:cccccccccccccc00ccccc055cccc0555ccc05577ccc057ffcc07ff55cc0fff99 -- 086:038383390338833b038383130338337f0383835f003838350003838300003333
-- 077:cccccccc0000cccc55550ccc555550cc7577550cfffff50c5f555f0c3f993f0c -- 087:99539900bb33bb0099513900fffff530ff66f1007fff53001555310033333000
-- 078:cccccccccccccccccccccccccccccccccccc0000cccc0444cccc0444cccc0555 -- 088:000f7ff300005fff000007ff0000007f0000021f000024410002444400124244
-- 079:cccccccccccccccccccccccccccccccc000ccccc440ccccc440ccccc550ccccc -- 089:fff3ff7ff1ffff50fffff700111f7000ffff1000111142004244442042442410
-- 080:c077500fcc0ff77fcc05fff5ccc05ff7cccc015fccc0f315cc0ff3ffc0ff3333 -- 090:005f5733005f1f2300015fff0000077f00011117001244210144414201421444
-- 081:f00f0cccf77f0ccc5ff0cccc7f50ccccf50ccccc53f0ccccf3f50ccc333f0ccc -- 091:ff33f500ff23f500fffff00011ff500077710000112410004442410042441410
-- 082:cc0fff00cc05ffffccc057f5cccc007fccc03335cc01313fc031313303113133 -- 092:00005fff000005ff0000001f0000000100000114000018140000181400018114
-- 083:ff00f0ccffff10cc55f10cccff70cccc5530ccccff310ccc33310ccc333110cc -- 093:fffff500111f5000fff500001110000042411000424180004241810042411100
-- 084:cc0447ffcc0fffffcc07f33fcc0ff11fcc0f7fffccc0ff75cccc0424cccc0142 -- 094:00001fff00001f3f0000cf3f0000cfff00000cf3000023cc000131ff001f1f11
-- 085:ff7440ccffff10ccf33f70ccf11f50ccfff7f0cc57ff0ccc4240cccc44110ccc -- 095:ff1000003f1000003ff00000fff00000fc000000c3200000f13100001f1f1000
-- 086:c0838039c038803bc0838013c038307fc083805fcc083805ccc08383cccc0333 -- 096:00ff33330033133305f333330ff31333033333330f5313330ff1311107f13333
-- 087:9953990cbb33bb0c9951390cfffff50cff66f10c7fff50cc15550ccc33330ccc -- 097:333f0000333f5000333f5000333ff000333330003335f500111ff5003337f000
-- 088:cc0f7ff0ccc05fffcccc07ffccccc07fcccc021fccc02441cc024444c0124244
-- 089:fff0ff70f1ffff50fffff70c111f70ccffff10cc1111420c4244442042442410
-- 090:cc0f5733cc0f1f23ccc00fffcccc077fccc01117cc024421c0444142c0421444
-- 091:ff33f0ccff23f0ccfffff0cc11ff0ccc7770cccc11240ccc444240cc4244140c
-- 092:ccc05fffcccc05ffccccc01fcccccc01ccccc014cccc0814ccc01814ccc08114
-- 093:fffff50c111f50ccfff50ccc1110cccc42410ccc424180cc424180cc424110cc
-- 094:cccc0fffcccc0f3fcccc0f0fcccc0fffccccc0f3cccc0377ccc031ffcc0f1f11
-- 095:ff0ccccc3f0ccccc0f0cccccff0cccccf0cccccc730cccccf130cccc1f1f0ccc
-- 096:c0ff3333c033133305f333330ff31333033333330f5313330ff1311107f13333
-- 097:333f0ccc333f50cc333f50cc333ff0cc333330cc3335f50c111ff50c3337f0cc
-- 098:03113133031131330333313303113131033331320555313107ff313307ff3131 -- 098:03113133031131330333313303113131033331320555313107ff313307ff3131
-- 099:333110cc333110cc333330cc213110cc423330cc21317f0c33317f501131750c -- 099:333113003331130033333300213113004233330021317f0033317f5001317500
-- 100:ccc04414cc044441c0444424c042442404424424044144240441442404414424 -- 100:0002441400244441024444240242442414424424144144241441442414414424
-- 101:414420cc1444420c424444204244422042444240424441404244414042444140 -- 101:4144210014444200424444204244422042444241424441414244414142444141
-- 102:ccc03333cc03a353cc02a353cc0a3323c0a23333c02a3333c0a23333c02a3333 -- 102:000333330033a3530032a353003a332303a23333032a333303a23333032a3333
-- 103:33330ccc553530cc553530cc2232320c3333310c3333320c3333313033333230 -- 103:3333300055353300553533002232323033333130333332303333313333333233
-- 104:c0144144c0144244c0144144c0144124c017f311c01ff133c01fff33cc07f330 -- 104:001441440014424400144144001441240017f311001ff133001fff330007f333
-- 105:4244142042442410424414204244122012113f7031333ff033333ff000033f0c -- 105:4244142042442410424414204244122012113f7031333ff033333ff030333f00
-- 106:c0421444c0441444c0421444c0421444c0111111c0ff1a5ac0f755a5c0755a50 -- 106:01421444014414440142144431421444011111110fff1a5a0ff755a505755a51
-- 107:4444140c4244140c4444140c4244140c1111110c5a5a55f0a5a5a5f0001a5170 -- 107:44441410424414104444141042441410111111105a5a55f5a5a5a5f5111a5170
-- 108:ccc01814ccc08114ccc01814ccc08113cc001333c05fff33cc0f7733cc055330 -- 108:0001181400018114000118140001811300011333005fff33000f773300055333
-- 109:4241810c4241180c4241810c2223180c1113310c33335ff03333f7700033550c -- 109:424181104241181042418110222318101113310033335ff03333f77033335500
-- 110:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 112:0553333300033330000333000033330000333300003333000011110000121200
-- 111:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 113:3330000033300000333000003330000033300000333000001111000012120000
-- 112:05533333c0033330ccc0330ccc03330cc03330ccc03330ccc01110ccc0000ccc -- 114:05f5313103003131033311310311113103111131003111300003333000012120
-- 113:33000ccc030ccccc030ccccc030ccccc030ccccc030ccccc0110cccc0000cccc -- 115:0131130001311300013113000131130001311300003113000033330000121200
-- 114:05f53131c0003131c0331131c0111131c0111130cc01110cccc0330cccc0000c -- 116:0fff242407f72211005544200002442000024420000244200002222000024440
-- 115:113110cc113110cc113110cc113110cc003110cccc0110cccc0330cccc0000cc -- 117:424441f1112227f1024425500244200002442000024420000222200002444000
-- 116:0fff242407f72211c0552400cc00240cccc0240cccc0240cccc0220cccc0000c -- 118:0333333307ff333307f733330070333000003330000033300000111000001110
-- 117:424441f0112227f000442550c044200cc04420ccc04420ccc02220ccc00000cc -- 119:33333575333331f1333335750033300000333000003330000011100000111100
-- 118:0333333307ff333307f73300c070030ccc0c030ccccc030ccccc010ccccc000c -- 120:0000033300000333000003330000033300000333000003330000033300000111
-- 119:33333570333331f000033570cc03300ccc030ccccc030ccccc010ccccc0000cc -- 121:0033300000333000003330000033300000333000003330000033300010111100
-- 120:ccc00330ccccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc000 -- 122:005015a100001a51000015a100001a51000015a1000022510000924900009999
-- 121:cc0300cccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccc0c0000cc -- 123:0315a150001a51000015a100001a51000015a100002251000092490000999900
-- 122:c05015a0cc0c0a50cccc05a0cccc0a50cccc05a0cccc0250cccc0990cccc0000 -- 124:0000033300000333000003330000033300000333000003330000033300000111
-- 123:c015a150cc0a500ccc05a0cccc0a50cccc05a0cccc0250cccc0990cccc0000cc -- 125:0333000003330000033300000333000003330000033300000333000000111000
-- 124:ccc00330ccccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc000 -- 129:0000000000000000000000000000000000000000011515101151515151515151
-- 125:c03000ccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc0000ccc -- 144:0000000500000015000000150000057f000005ff0000017f0000331700073331
-- 126:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 145:1ffffff7ff0fff0fff1fff1fffffffffff7555fffffffffffff111ff57fffff7
-- 127:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 146:1000000071000000f5000000ff000000ff500000ff5000007513100051333700
-- 128:ccccccccccccccccccccccccccccccccccccccccccccccccccccccc0ccccccc0 -- 160:0077333303331333333313333331333333313333355133335ff513335ff71111
-- 129:ccccccccccccccccccccccccccccccccc000000c011515101151515151515151
-- 130:cccccccccccccccccccccccccccccccccccccccccccccccc0ccccccc10cccccc
-- 131:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 132:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 133:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 134:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 135:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 136:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 137:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 138:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 139:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 140:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 141:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 142:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 143:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 144:cccccc05ccccc015ccccc015cccc057fcccc05ffcccc017fccc03317cc073331
-- 145:1ffffff7ff0fff0fff0fff0fffffffffff7555fffffffffffff111ff57fffff7
-- 146:10cccccc710cccccf50cccccff0cccccff50ccccff510ccc751310cc5133370c
-- 147:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 148:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 149:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 150:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 151:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 152:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 153:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 154:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 155:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 156:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 157:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 158:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 159:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 160:c077333303331333033313330331333303313333055133330ff513330ff71111
-- 161:1111111133333333333337333333373333333733333337333333373311117711 -- 161:1111111133333333333337333333373333333733333337333333373311117711
-- 162:1333370c3733130c7773130c333331303333313033333150333337f011111750 -- 162:133337003733133077731330333331333333313333333155333337ff1111175f
-- 163:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 176:0775333300031333000333130000333300001333000033330000033300000111
-- 164:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 177:3335773333333533333333331313131333333333300000033000000310000001
-- 165:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -- 178:3333357533331000331300001333000033310000333300003331000011110000
-- 166:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 167:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 168:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 169:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 170:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 171:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 172:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 173:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 174:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 175:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 176:07753333c0031333ccc03313cccc0333cccc0333cccc0333ccccc033ccccc000
-- 177:33357733333335333333333313131313000000000cccccc00cccccc00cccccc0
-- 178:333335703333100c33100ccc1330cccc3330cccc3330cccc3330cccc0000cccc
-- 179:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 180:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 181:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 182:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 183:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 184:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 185:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 186:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 187:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 188:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 189:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 190:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 191:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 192:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 193:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 194:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 195:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 196:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 197:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 198:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 199:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 200:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 201:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 202:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 203:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 204:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 205:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 206:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 207:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 208:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 209:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 210:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 211:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 212:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 213:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 214:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 215:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 216:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 217:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 218:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 219:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 220:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 221:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 222:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 223:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 224:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 225:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 226:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 227:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 228:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 229:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 230:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 231:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 232:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 233:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 234:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 235:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 236:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 237:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 238:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 239:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 240:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 241:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 242:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 243:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 244:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 245:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 246:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 247:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 248:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 249:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 250:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 251:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 252:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 253:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 254:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 255:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- </SPRITES> -- </SPRITES>
-- <MAP> -- <MAP>
-- 000:20102010200010201020102010201020102010201020102000102010201040404040404087f3f3f3f397a7b7c7d7a7e7f70818a7b7c7d7a7b7c7d7a70b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 000:ffffffffff0010201020102010201020102010201020102000ffffffffff40404040404087f3f3f3f397a7b7c7d7a7e7f70818a7b7c7d7a7b7c7d7a70b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 001:40404040400040404040404040404040404040404040404000404040404040404040404087f3f3f3f328a7384858a76878f388a7384858a7384858a70b40403b4b4040404040404040404040404040404040404040404040400b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 001:ffffffffff0040404040404040404040404040404040404000ffffffffff40404040404087f3f3f3f328a7384858a76878f388a7384858a7384858a70b40403b4b4040404040404040404040404040404040404040404040400b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 002:408090a04000406070408090a040b0c0d0e0f001f001112100408090a040984098409840a8f3f3f3f3b8a7a7a7a7a7c8d8e8f8a7a7a7a7a7a7a7a7a70b405b6b7b4040404040404040404040404040d0e0f001f001f00111210b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 002:ffffffffff00406070408090a040b0c0d0e0f001f001112100ffffffffff984098409840a8f3f3f3f3b8a7a7a7a7a7c8d8e8f8a7a7a7a7a7a7a7a7a70b405b6b7b4040404040404040404040404040d0e0f001f001f00111210b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 003:4051617140004031414051617140814091a1b1b1b1b1c1d1004051617140984098409840a8f3f3f3f3091919191919293949591919191919191919190b8b9babbb4040cbdbebfb0c401c2c2c2c3c4091a14c5c6c6c6c6cc1d10b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 003:ffffffffff004031414051617140814091a1b1b1b1b1c1d100ffffffffff984098409840a8f3f3f3f3091919191919293949591919191919191919190b8b9babbb4040cbdbebfb0c401c2c2c2c3c4091a14c5c6c6c6c6cc1d10b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 004:4012223240e140f1024012223240814042a15262728292a2e14012223240984098409840a8f3f3f3f369f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f37c8c9cacbc7282ccdcecfc0d401d3030302d4042a13d4d7282728292a27c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 004:ffffffffffe140f1024012223240814042a15262728292a2e1ffffffffff984098409840a8f3f3f3f369f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f37c8c9cacbc7282ccdcecfc0d401d3030302d4042a13d4d7282728292a27c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 005:4040404040b240c2d240e2f203132333435363738393a3b3b24040404040984098409840a8f3f3f3f369f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f35d406d7d40e3958d9dadbdcd40ddedfded0e404353839383938393a3b35d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 005:ffffffffffb240c2d240e2f203132333435363738393a3b3b2ffffffffff984098409840a8f3f3f3f369f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f35d406d7d40e3958d9dadbdcd40ddedfded0e404353839383938393a3b35d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 006:d3c3d3c3d3e1c3d3c3d3e3f30414c3d32434445410201020e1c3d3c3d3c3404040404040798989898999a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a97c1e1e1e1e44542e1e1e1e3e1e444e4e4e541e243444544454445444547c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 006:ffffffffffe1c3d3c3d3e3f30414c3d32434445410201020e1ffffffffff404040404040798989898999a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a97c1e1e1e1e44542e1e1e1e3e1e444e4e4e541e243444544454445444547c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 007:9464354594b264748494a4b4c4d46494649464940040e4f4b264354594644040404040404040404040404040404040404040404040404040404040405d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 007:ffffffffffb264748494a4b4c4d46494649464940040e4f4b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 008:d3c3e395d3e1c30515d325d33545c3d355d3c3d365b17585e1c3e395d3254040404040404098989898404040404040404040404040404040404040407c1e7e8e1e1e1e9eae1ebe1e1e1e1e1e1e1e1e72821ebe1e72821ebe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 008:ffffffffffe1c30515d325d33545c3d355d3c3d365b17585e1ffffffffff4040404040404098989898404040404040404040404040404040404040407c1e7e8e1e1e1e9eae1ebe1e1e1e1e1e1e1e1e72821ebe1e72821ebe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 009:9464465694b264e395a5b594e39564c5d5946494e5b1b1f5b264e395a5b54040404040404040404040404040404040404040404040404040404040405d1e05151ebe1ecedeeefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 009:ffffffffffb264e395a5b594e39564c5d5946494e5b1b1f5b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e05151ebe1ecedeeefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 010:d3c3d3c3d3e1c306162636d34656c3e3d5d3c3d376b1b1b1e1c3e3952636404040404040409898989840b9c9c9d9e9f90a0a0a0a4040400a0a0a0a407c1ee395eefe1e0f1f2f3f1e1e1e1e1e1e1e1ee3952f3f1ee3952f3f1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 010:ffffffffffe1c306162636d34656c395d5d3c3d376b1b1b1e1ffffffffff404040404040409898989840b9c9c9d9e9f90a0a0a0a4040400a0a0a0a407c1ee395eefe1e0f1f2f3f1e1e1e1e1e1e1e1ee3952f3f1ee3952f3f1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 011:9464946494b264946494649464948696a694649410201020b264e395d3254040404040404040404040401a2a3a4a5a6a7a40404040404040404040405d1ee3952f3f1e4f5f1ebe1e1e1e1e1e1e1e1ee3951ebe1ee3951ebe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 011:ffffffffffb264946494649464948696a694649410201020b2ffffffffff4040404040404040404040401a2a3a4a5a6a7a40404040404040404040405d1ee3952f3f1e4f5f1ebe1e1e1e1e1e1e1e1ee3951ebe1ee3951ebe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 012:d3c37282d3e1c37282d3c3d3c3d3b6c6d6d3c3d300e6f607e1c3e395a5b54040404040404098989898408a9aaabaca9ada40404040404040404040407c1e4f5f1ebe1e0515eefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 012:ffffffffffe1c37282d3c3d3c3d3b6c6d6d3c3d300e6f607e1ffffffffff4040404040404098989898408a9aaabaca9ada40404040404040404040407c1e4f5f1ebe1e0515eefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 013:9464e39594b264e395946494649464946494649465172737b26406162636eaeaeaeaeaeaeafafafafaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaea5d1e0515eefe1e6f7f2f3f1e1e1e1e1e1e1e1e6f7f2f3f1e6f7f2f3f1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 013:ffffffffffb264e395946494649464946494649465172737b2ffffffffffeaeaeaeaeaeaeafafafafaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaea5d1e0515eefe1e6f7f2f3f1e1e1e1e1e1e1e1e6f7f2f3f1e6f7f2f3f1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 014:d3c34454d3e1c34454d3c3d3c3d3c3d3c3d3c3d3e5b14757e1c3d3c3d3c3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f37c1e6f7f2f3f1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 014:ffffffffffe1c34454d3c3d3c3d3c3d3c3d3c3d3e5b14757e1fffffffffff3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f37c1e6f7f2f3f1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 015:9464946494b2649464946494649464946494649476b1b1b1b26494649464f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f35d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 015:ffffffffffb2649464946494649464946494649476b1b1b1b2fffffffffff3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f35d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 016:201020102000102010207667770010201020102010201020001020102010f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f30b1b2b1b2b7667776777761b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 016:ffffffffff0010201020766777001020102010201020102000fffffffffff3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f30b1b2b1b2b7667776777761b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- </MAP> -- </MAP>
-- <SFX> -- <SFX>
-- 016:00000000000000400040004000700070007000400040004000700070007000c000c000c000c000c000c000c000c000c000c000c000c000c000c000c0470000000000 -- 016:00000000000000400040004000700070007000400040004000700070007000c000c000c000c000c000c000c000c000c000c000c000c000c000c000c0470000000000

View File

@@ -4,5 +4,5 @@
-- desc: Life of a programmer -- desc: Life of a programmer
-- site: https://git.teletype.hu/games/impostor -- site: https://git.teletype.hu/games/impostor
-- license: MIT License -- license: MIT License
-- version: 1.0-beta3 -- version: 1.0-beta2
-- script: lua -- script: lua

View File

@@ -6,52 +6,52 @@ local STATE_CHOICE = "choice"
local ASC_01_TEXT = [[ local ASC_01_TEXT = [[
Normann seems to be in line, Normann seems to be in line,
...
and stays seeking for oxes and stays seeking for oxes
...
within the confines. within the confines.
...
Very good. Very good.
]] ]]
local ASC_12_TEXT = [[ local ASC_12_TEXT = [[
We have a problem! We have a problem!
...
Normann formed his first thought. Normann formed his first thought.
...
He saw the tracks. He saw the tracks.
]] ]]
local ASC_23_TEXT = [[ local ASC_23_TEXT = [[
Not good, not terrible. Not good, not terrible.
...
Normann caught his glimpse Normann caught his glimpse
...
of another way of another way
...
- quite literally - - quite literally -
...
if this continues, if this continues,
...
we will lose control. we will lose control.
]] ]]
local ASC_34_TEXT = [[ local ASC_34_TEXT = [[
There is no turning back now for Norman. There is no turning back now for Norman.
...
He caught on. He caught on.
...
I hoped it would never come to this... I hoped it would never come to this...
]] ]]
--[[ Norman speaks for the first time during MM screen ]] --[[ Norman speaks for the first time during MM screen ]]
local ASC_45_TEXT = [[ local ASC_45_TEXT = [[
Wait, who are you? Wait, who are you?
...
*silence* *silence*
...
Why am I seeing this? Why am I seeing this?
...
*silence* *silence*
...
]] ]]
local ascension_texts = { local ascension_texts = {
@@ -132,7 +132,6 @@ function MysteriousManScreen.wake_up()
target_points = 100, target_points = 100,
instruction_text = "Wake up Norman!", instruction_text = "Wake up Norman!",
show_progress_text = false, show_progress_text = false,
meter_on_complete = Meter.apply_wakeup_reward,
on_win = function() on_win = function()
Audio.music_play_wakingup() Audio.music_play_wakingup()
Meter.show() Meter.show()
@@ -262,18 +261,16 @@ Screen.register({
end end
if state == STATE_TEXT then if state == STATE_TEXT then
local screen_w = Config.screen.width local cx = Config.screen.width / 2
local line_y = text_y local line_y = text_y
for line in (text .. "\n"):gmatch("(.-)\n") do for line in (text .. "\n"):gmatch("(.-)\n") do
local line_w = print(line, 0, -6, 0, false, 1) Print.text_center(line, cx, line_y, Config.colors.light_grey)
local line_x = math.floor((screen_w - line_w) / 2)
Print.text_contour(line, (line_x - 8), line_y, Config.colors.black, false, 1)
line_y = line_y + 8 line_y = line_y + 8
end end
elseif state == STATE_DAY then elseif state == STATE_DAY then
MysteriousManScreen.draw_day_switch_background() MysteriousManScreen.draw_day_switch_background()
local day_text = day_text_override or ("day " .. Context.day_count) local day_text = day_text_override or ("Day " .. Context.day_count)
Print.text_center_contour( Print.text_center(
day_text, day_text,
Config.screen.width / 2, Config.screen.width / 2,
Config.screen.height / 2 - 3, Config.screen.height / 2 - 3,

View File

@@ -36,13 +36,13 @@ Screen.register({
Sprite.draw_at("norman", norman_x, norman_y) Sprite.draw_at("norman", norman_x, norman_y)
Print.text_center_contour("day " .. Context.day_count, cx, 10, Config.colors.black) Print.text_center("day " .. Context.day_count, cx, 10, Config.colors.white)
local narrative = "reflecting on my past and present...\nboth eventually flushed..." local narrative = "reflecting on my past and present\n...\nboth eventually flushed."
local wrapped = UI.word_wrap(narrative, 38) local wrapped = UI.word_wrap(narrative, 38)
local text_y = 24 local text_y = 24
for _, line in ipairs(wrapped) do for _, line in ipairs(wrapped) do
Print.text_center_contour(line, cx, text_y, Config.colors.black) Print.text_center(line, cx, text_y, Config.colors.light_grey)
text_y = text_y + 8 text_y = text_y + 8
end end
@@ -51,37 +51,31 @@ Screen.register({
local decay_pct = Meter.get_decay_percentage() local decay_pct = Meter.get_decay_percentage()
local decay_text = string.format("-%d%%", decay_pct) local decay_text = string.format("-%d%%", decay_pct)
local combo_mult = Meter.get_combo_multiplier() local combo_mult = Meter.get_combo_multiplier()
local ism_bm_combo_pct = math.floor((combo_mult - 1) * 100) local combo_pct = math.floor((combo_mult - 1) * 100)
local wpm_combo_pct = math.floor((1 / combo_mult - 1) * 100 + 0.5) local mult_text = string.format("+%d%%", combo_pct)
local meter_start_y = text_y + 10 local meter_start_y = text_y + 10
local meter_list = { local meter_list = {
{ key = "wpm", label = "Work Productivity Meter", color = Meter.COLOR_WPM }, { key = "wpm", label = "Work Productivity Meter" },
{ key = "ism", label = "Impostor Syndrome Meter", color = Meter.COLOR_ISM }, { key = "ism", label = "Impostor Syndrome Meter" },
{ key = "bm", label = "Burnout Meter", color = Meter.COLOR_BM }, { key = "bm", label = "Burnout Meter" },
} }
for i, meter in ipairs(meter_list) do for i, meter in ipairs(meter_list) do
local y = meter_start_y + (i - 1) * 20 local y = meter_start_y + (i - 1) * 20
Print.text_center_contour(meter.label, cx, y, meter.color, false, 1, Config.colors.white) Print.text_center(meter.label, cx, y, Config.colors.white)
local bar_y = y + 8 local bar_y = y + 8
local fill_w = math.max(0, math.floor((m[meter.key] / max_val) * bar_w)) local fill_w = math.max(0, math.floor((m[meter.key] / max_val) * bar_w))
rect(bar_x, bar_y, bar_w, bar_h, Meter.COLOR_BG) rect(bar_x, bar_y, bar_w, bar_h, Meter.COLOR_BG)
if fill_w > 0 then if fill_w > 0 then
rect(bar_x, bar_y, fill_w, bar_h, meter.color) rect(bar_x, bar_y, fill_w, bar_h, Config.colors.blue)
end end
local mult_text
if meter.key == "wpm" then
mult_text = string.format("%+d%%", wpm_combo_pct)
else
mult_text = string.format("+%d%%", ism_bm_combo_pct)
end
local decay_w = print(decay_text, 0, -6, 0, false, 1) local decay_w = print(decay_text, 0, -6, 0, false, 1)
Print.text_contour(decay_text, bar_x - decay_w - 4, bar_y, Config.colors.light_blue, false, 1, Config.colors.white) Print.text(decay_text, bar_x - decay_w - 4, bar_y, Config.colors.light_blue)
Print.text_contour(mult_text, bar_x + bar_w + 4, bar_y, Config.colors.light_blue, false, 1, Config.colors.white) Print.text(mult_text, bar_x + bar_w + 4, bar_y, Config.colors.light_blue)
end end
if Ascension.get_level() > 0 then if Ascension.get_level() > 0 then

View File

@@ -3,7 +3,7 @@ local _sprites = {}
local _active_sprites = {} local _active_sprites = {}
local function draw_sprite_instance(sprite_data, params) local function draw_sprite_instance(sprite_data, params)
local colorkey = params.colorkey or sprite_data.colorkey or Config.colors.transparent local colorkey = params.colorkey or sprite_data.colorkey or 0
local scale = params.scale or sprite_data.scale or 1 local scale = params.scale or sprite_data.scale or 1
local flip_x = params.flip_x or sprite_data.flip_x or 0 local flip_x = params.flip_x or sprite_data.flip_x or 0
local flip_y = params.flip_y or sprite_data.flip_y or 0 local flip_y = params.flip_y or sprite_data.flip_y or 0

View File

@@ -30,9 +30,3 @@ function Input.back() return btnp(INPUT_KEY_B) or keyp(INPUT_KEY_BACKSPACE) end
--- Checks if Enter is pressed. --- Checks if Enter is pressed.
--- @within Input --- @within Input
function Input.enter() return keyp(INPUT_KEY_ENTER) end function Input.enter() return keyp(INPUT_KEY_ENTER) end
--- Checks if Up is pressed or held (with repeat).
--- @within Input
function Input.up_repeat() return btnp(INPUT_KEY_UP, 20, 4) end
--- Checks if Down is pressed or held (with repeat).
--- @within Input
function Input.down_repeat() return btnp(INPUT_KEY_DOWN, 20, 4) end

View File

@@ -14,28 +14,6 @@ function Print.text(text, x, y, color, fixed, scale)
print(text, x, y, color, fixed, scale) print(text, x, y, color, fixed, scale)
end end
--- Prints text with a contour (outline) instead of shadow.
--- @within Print
--- @param text string The text to print.<br/>
--- @param x number The x-coordinate.<br/>
--- @param y number The y-coordinate.<br/>
--- @param color number The color of the text.<br/>
--- @param[opt] fixed boolean If true, uses fixed-width font.<br/>
--- @param[opt] scale number The scaling factor (also used for outline thickness).<br/>
--- @param[opt] contour_color number Outline color; defaults to black; if equal to text color, uses white.<br/>
function Print.text_contour(text, x, y, color, fixed, scale, contour_color)
scale = scale or 1
local cc = contour_color
if cc == nil then cc = Config.colors.black end
if color == cc then cc = Config.colors.white end
local ox = { -scale, scale, 0, 0, -scale, scale, -scale, scale }
local oy = { 0, 0, -scale, scale, -scale, -scale, scale, scale }
for i = 1, 8 do
print(text, x + ox[i], y + oy[i], cc, fixed, scale)
end
print(text, x, y, color, fixed, scale)
end
--- Prints centered text with shadow. --- Prints centered text with shadow.
--- @within Print --- @within Print
--- @param text string The text to print.<br/> --- @param text string The text to print.<br/>
@@ -50,19 +28,3 @@ function Print.text_center(text, x, y, color, fixed, scale)
local centered_x = x - (text_width / 2) local centered_x = x - (text_width / 2)
Print.text(text, centered_x, y, color, fixed, scale) Print.text(text, centered_x, y, color, fixed, scale)
end end
--- Prints centered text with contour instead of shadow.
--- @within Print
--- @param text string The text to print.<br/>
--- @param x number The x-coordinate for centering.<br/>
--- @param y number The y-coordinate.<br/>
--- @param color number The color of the text.<br/>
--- @param[opt] fixed boolean If true, uses fixed-width font.<br/>
--- @param[opt] scale number The scaling factor.<br/>
--- @param[opt] contour_color number Outline color; defaults to black; if equal to text color, uses white.<br/>
function Print.text_center_contour(text, x, y, color, fixed, scale, contour_color)
scale = scale or 1
local text_width = print(text, 0, -6 * scale, 0, fixed, scale)
local centered_x = x - (text_width / 2)
Print.text_contour(text, centered_x, y, color, fixed, scale, contour_color)
end

View File

@@ -1,81 +0,0 @@
--- @section TextInput
TextInput = {}
local LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local _pos = {}
local _cursor = 1
local _max_len = 3
--- Initialises a new text input session.
--- @within TextInput
--- @param max_len number Maximum character count (default 3).
function TextInput.init(max_len)
_max_len = max_len or 3
_pos = {}
for i = 1, _max_len do _pos[i] = 1 end
_cursor = 1
end
--- Advances to the next letter at the cursor position (wraps Z→A).
--- @within TextInput
function TextInput.next_letter()
_pos[_cursor] = (_pos[_cursor] % #LETTERS) + 1
end
--- Goes back to the previous letter at the cursor position (wraps A→Z).
--- @within TextInput
function TextInput.prev_letter()
_pos[_cursor] = ((_pos[_cursor] - 2) % #LETTERS) + 1
end
--- Confirms the current letter and advances the cursor to the next position.
--- When called on the last position the cursor moves into the done state.
--- @within TextInput
function TextInput.select_letter()
if _cursor <= _max_len then _cursor = _cursor + 1 end
end
--- Moves the cursor one position to the right (stops at last position).
--- @within TextInput
function TextInput.next_position()
if _cursor < _max_len then _cursor = _cursor + 1 end
end
--- Moves the cursor one position to the left (stops at first position).
--- Also steps back out of the done state.
--- @within TextInput
function TextInput.prev_position()
if _cursor > 1 then _cursor = _cursor - 1 end
end
--- Returns the assembled name string.
--- @within TextInput
--- @return string
function TextInput.get_name()
local s = ""
for i = 1, _max_len do s = s .. LETTERS:sub(_pos[i], _pos[i]) end
return s
end
--- Returns the current 1-based cursor position.
--- @within TextInput
--- @return number
function TextInput.get_position()
return _cursor
end
--- Returns the letter at the given 1-based position.
--- @within TextInput
--- @param i number
--- @return string
function TextInput.get_letter(i)
return LETTERS:sub(_pos[i], _pos[i])
end
--- Returns true when all positions have been confirmed.
--- @within TextInput
--- @return boolean
function TextInput.is_done()
return _cursor > _max_len
end

View File

@@ -90,54 +90,12 @@ end
--- @param[opt] bg_color number The background fill color (default: Config.colors.dark_grey).<br/> --- @param[opt] bg_color number The background fill color (default: Config.colors.dark_grey).<br/>
--- @param[opt] border_color number The border color (default: Config.colors.white).<br/> --- @param[opt] border_color number The border color (default: Config.colors.white).<br/>
--- @param[opt] center_text boolean Whether to center each line inside the box. Defaults to false.<br/> --- @param[opt] center_text boolean Whether to center each line inside the box. Defaults to false.<br/>
local function draw_rounded_rect_fill(x, y, w, h, corner_radius, color)
local inner_w = w - corner_radius * 2
local inner_h = h - corner_radius * 2
if inner_w > 0 and inner_h > 0 then
rect(x + corner_radius, y + corner_radius, inner_w, inner_h, color)
end
if inner_w > 0 and corner_radius > 0 then
rect(x + corner_radius, y, inner_w, corner_radius, color)
rect(x + corner_radius, y + h - corner_radius, inner_w, corner_radius, color)
end
if corner_radius > 0 and inner_h > 0 then
rect(x, y + corner_radius, corner_radius, inner_h, color)
rect(x + w - corner_radius, y + corner_radius, corner_radius, inner_h, color)
end
for row = 0, corner_radius - 1 do
for col = 0, corner_radius - 1 do
if col + row >= corner_radius - 1 then
pix(x + corner_radius - 1 - col, y + corner_radius - 1 - row, color)
pix(x + w - corner_radius + col, y + corner_radius - 1 - row, color)
pix(x + corner_radius - 1 - col, y + h - corner_radius + row, color)
pix(x + w - corner_radius + col, y + h - corner_radius + row, color)
end
end
end
end
local function draw_rounded_rect_border(x, y, w, h, corner_radius, color)
line(x + corner_radius, y, x + w - corner_radius - 1, y, color)
line(x + corner_radius, y + h - 1, x + w - corner_radius - 1, y + h - 1, color)
line(x, y + corner_radius, x, y + h - corner_radius - 1, color)
line(x + w - 1, y + corner_radius, x + w - 1, y + h - corner_radius - 1, color)
pix(x + corner_radius - 1, y + 1, color)
pix(x + 1, y + corner_radius - 1, color)
pix(x + w - corner_radius, y + 1, color)
pix(x + w - 2, y + corner_radius - 1, color)
pix(x + corner_radius - 1, y + h - 2, color)
pix(x + 1, y + h - corner_radius, color)
pix(x + w - corner_radius, y + h - 2, color)
pix(x + w - 2, y + h - corner_radius, color)
end
function UI.draw_textbox(text, box_x, box_y, box_w, box_h, scroll_y, color, bg_color, border_color, center_text) function UI.draw_textbox(text, box_x, box_y, box_w, box_h, scroll_y, color, bg_color, border_color, center_text)
color = color or Config.colors.white color = color or Config.colors.white
bg_color = bg_color or Config.colors.black bg_color = bg_color or Config.colors.dark_grey
border_color = border_color or Config.colors.white border_color = border_color or Config.colors.white
center_text = center_text or false center_text = center_text or false
local r = 3
local padding = 4 local padding = 4
local line_height = 8 local line_height = 8
local inner_x = box_x + padding local inner_x = box_x + padding
@@ -152,7 +110,7 @@ function UI.draw_textbox(text, box_x, box_y, box_w, box_h, scroll_y, color, bg_c
base_y = inner_y + math.floor((visible_height - text_height) / 2) base_y = inner_y + math.floor((visible_height - text_height) / 2)
end end
draw_rounded_rect_fill(box_x, box_y, box_w, box_h, r, bg_color) rect(box_x, box_y, box_w, box_h, bg_color)
for i, line in ipairs(lines) do for i, line in ipairs(lines) do
local ly = base_y + (i - 1) * line_height - scroll_y local ly = base_y + (i - 1) * line_height - scroll_y
@@ -165,7 +123,7 @@ function UI.draw_textbox(text, box_x, box_y, box_w, box_h, scroll_y, color, bg_c
end end
end end
draw_rounded_rect_border(box_x, box_y, box_w, box_h, r, border_color) rectb(box_x, box_y, box_w, box_h, border_color)
end end
--- Wraps text. --- Wraps text.

View File

@@ -1,197 +0,0 @@
--- @section CreditsWindow
local _time = 0.0
local _scroll_x = 0.0
local _scroll_total_w = 0
local _scroll_chars = {}
local _title_chars = {}
local _title_total_w = 0
local _stars = {}
local TITLE = "TELETYPE GAMES"
local SCROLL_PARTS = {
"WEB: GAMES.TELETYPE.HU",
"BBS: GAMES.TELETYPE.HU:2323",
"IRC: LIBERA.CHAT #TELETYPEGAMES",
"YOUTUBE.COM/@TELETYPEGAMES",
}
local SCROLL_SEP = " * "
local SCROLL_SPEED = 55.0
local SCROLL_Y = 129
local SCROLL_ZONE_COLS = { 7, 4, 9 }
local TITLE_Y = 4
local TITLE_FALL_DUR = 0.45
local TITLE_DELAY_STEP = 0.18
local RASTER_COLS = { 1, 3, 9, 10, 11, 4, 11, 10, 9, 3, 1 }
local RASTER_Y_TOP = 26
local RASTER_Y_BOT = 110
local AUTHORS = {
"Mr. Zero - Zsolt Tasnadi",
"Mr. One - Balazs Tari",
"Mr. Two - Zoltan Timar",
"Mr. Three - Bela Mezo",
}
local AUTHORS_BASE_Y = 56
local AUTHORS_LINE_H = 12
local AUTHORS_ENTRY_DT = 0.65
local AUTHORS_ENTRY_V = 2.5
local RAINBOW = { 4, 9, 3, 7, 13, 2, 9, 4 }
local NUM_STARS = 40
--- Initialises credits state and pre-computes character metrics.
--- @within CreditsWindow
function CreditsWindow.init()
_time = 0.0
_scroll_x = Config.screen.width + 4.0
_title_chars = {}
_title_total_w = 0
for i = 1, #TITLE do
local ch = TITLE:sub(i, i)
local w = print(ch, 0, -100, 0, false, 2)
_title_chars[i] = { ch = ch, ox = _title_total_w, w = w }
_title_total_w = _title_total_w + w
end
_scroll_chars = {}
_scroll_total_w = 0
local function append_str(str, col)
for i = 1, #str do
local ch = str:sub(i, i)
local w = print(ch, 0, -100, 0, false, 1)
_scroll_chars[#_scroll_chars + 1] = { ch = ch, ox = _scroll_total_w, w = w, col = col }
_scroll_total_w = _scroll_total_w + w
end
end
for _, part in ipairs(SCROLL_PARTS) do
append_str(part, RAINBOW[math.random(#RAINBOW)])
append_str(SCROLL_SEP, Config.colors.white)
end
_stars = {}
for i = 1, NUM_STARS do
_stars[i] = {
x = math.random(0, Config.screen.width - 1) + 0.0,
y = math.random(0, Config.screen.height - 1),
spd = (i % 3 + 1) * 10.0,
col = ({ 1, 2, 4, 4 })[(i % 4) + 1],
}
end
end
local function draw_stars()
for _, s in ipairs(_stars) do
pix(math.floor(s.x), s.y, s.col)
end
end
local function draw_rasters()
local cy = RASTER_Y_TOP + math.floor(math.sin(_time * 1.3) * 6)
for i, col in ipairs(RASTER_COLS) do
local y = cy + i - 1
if y >= 0 and y < Config.screen.height then
line(0, y, Config.screen.width - 1, y, col)
end
end
local cy2 = RASTER_Y_BOT + math.floor(math.sin(_time * 1.7 + 1.5) * 5)
for i, col in ipairs(RASTER_COLS) do
local y = cy2 + i - 1
if y >= 0 and y < Config.screen.height then
line(0, y, Config.screen.width - 1, y, col)
end
end
end
local function bounce_out(p)
local n1, d1 = 7.5625, 2.75
if p < 1 / d1 then
return n1 * p * p
elseif p < 2 / d1 then
p = p - 1.5 / d1; return n1 * p * p + 0.75
elseif p < 2.5 / d1 then
p = p - 2.25 / d1; return n1 * p * p + 0.9375
else
p = p - 2.625 / d1; return n1 * p * p + 0.984375
end
end
local function draw_title()
local sx = math.floor((Config.screen.width - _title_total_w) / 2)
local n = #_title_chars
local max_dist = (n - 1) / 2.0
for i, tc in ipairs(_title_chars) do
local dist = math.abs(i - (n + 1) / 2.0)
local delay = (max_dist - dist) * TITLE_DELAY_STEP
local t = math.max(0, _time - delay)
local p = math.min(1, t / TITLE_FALL_DUR)
local y = math.floor(-14 + bounce_out(p) * (TITLE_Y + 14))
print(tc.ch, sx + tc.ox + 1, y + 1, 0, false, 2)
print(tc.ch, sx + tc.ox, y, Config.colors.light_blue, false, 2)
end
end
local function draw_authors()
local col = Config.colors.light_blue
for i, lbl in ipairs(AUTHORS) do
local enter_t = math.max(0, _time - (i - 1) * AUTHORS_ENTRY_DT)
local slide = math.max(0, 1 - enter_t * AUTHORS_ENTRY_V)
local x_off = math.floor(slide * (Config.screen.width + 40))
local yo = (slide < 0.01) and math.floor(math.sin(_time * 2.0 + i * 1.1) * 2) or 0
Print.text(lbl, 12 + x_off, AUTHORS_BASE_Y + (i - 1) * AUTHORS_LINE_H + yo, col)
end
end
local function draw_scroller()
local third = Config.screen.width / 3
for pass = 0, 1 do
local base = _scroll_x + pass * _scroll_total_w
for _, sc in ipairs(_scroll_chars) do
local x = math.floor(base + sc.ox)
if x >= Config.screen.width then break end
if x + sc.w > 0 then
local zone = math.max(1, math.min(3, math.floor(x / third) + 1))
print(sc.ch, x, SCROLL_Y, SCROLL_ZONE_COLS[zone], false, 1)
end
end
end
end
--- Draws the credits window.
--- @within CreditsWindow
function CreditsWindow.draw()
cls(Config.colors.black)
draw_stars()
draw_rasters()
draw_title()
Print.text_center("Authors", Config.screen.width / 2, 47, Config.colors.light_grey)
draw_authors()
draw_scroller()
end
--- Updates credits window logic.
--- @within CreditsWindow
function CreditsWindow.update()
_time = _time + Context.delta_time
for _, s in ipairs(_stars) do
s.x = s.x + s.spd * Context.delta_time
if s.x >= Config.screen.width then s.x = s.x - Config.screen.width end
end
_scroll_x = _scroll_x - SCROLL_SPEED * Context.delta_time
if _scroll_x <= -_scroll_total_w then
_scroll_x = _scroll_x + _scroll_total_w
end
if Input.back() or Input.select() then
Window.set_current("menu")
end
end

View File

@@ -24,7 +24,7 @@ function DiscussionWindow.draw()
TEXTBOX_W, TEXTBOX_H, TEXTBOX_W, TEXTBOX_H,
Context.discussion.scroll_y, Context.discussion.scroll_y,
Config.colors.white, Config.colors.white,
Config.colors.black, Config.colors.dark_grey,
Config.colors.light_blue, Config.colors.light_blue,
true true
) )
@@ -37,13 +37,9 @@ function DiscussionWindow.draw()
local selected = answers[Context.discussion.selected_answer] local selected = answers[Context.discussion.selected_answer]
local label = selected.label local label = selected.label
local answer_text_y = bar_y + 4 local answer_text_y = bar_y + 4
local left_arrow_color = Input.left() and Config.colors.white or Config.colors.orange Print.text("<", 2, answer_text_y, Config.colors.light_blue)
local right_arrow_color = Input.right() and Config.colors.white or Config.colors.orange Print.text_center(label, Config.screen.width / 2, answer_text_y, Config.colors.item)
local left_arrow_contour_color = Input.left() and Config.colors.white or Config.colors.black Print.text(">", Config.screen.width - 6, answer_text_y, Config.colors.light_blue)
local right_arrow_contour_color = Input.right() and Config.colors.white or Config.colors.black
Print.text_center_contour("<", 6, answer_text_y, left_arrow_color, false, 1, left_arrow_contour_color)
Print.text_center(label, Config.screen.width / 2, answer_text_y, Config.colors.orange)
Print.text_center_contour(">", Config.screen.width - 6, answer_text_y, right_arrow_color, false, 1, right_arrow_contour_color)
end end
end end

View File

@@ -30,15 +30,9 @@ function EndWindow.draw()
Print.text(yes_text, centerX - 40, y, yes_color) Print.text(yes_text, centerX - 40, y, yes_color)
Print.text(no_text, centerX + 10, y, no_color) Print.text(no_text, centerX + 10, y, no_color)
elseif Context._end.state == "ending" then elseif Context._end.state == "ending" then
local cx = Config.screen.width / 2 Print.text_center("Game over -- good ending.", Config.screen.width / 2, 50, Config.colors.light_blue)
local name = Context.player_name or "AAA" Print.text_center("Congratulations!", Config.screen.width / 2, 70, Config.colors.white)
local code = CodeGenerator.encrypt(name) Print.text_center("Press Z to return to menu", Config.screen.width / 2, 110, Config.colors.light_grey)
Print.text_center("Game over -- good ending.", cx, 40, Config.colors.light_blue)
Print.text_center("Congrats " .. name .. "!", cx, 54, Config.colors.white)
Print.text_center("Your personal code:", cx, 72, Config.colors.light_grey)
Print.text_center(code, cx, 84, Config.colors.white, false, 3)
Print.text_center("Write it down!", cx, 112, Config.colors.item)
Print.text_center("Press Z to return to menu", cx, 126, Config.colors.dark_grey)
end end
end end

View File

@@ -1,59 +0,0 @@
--- @section GameOverWindow
local GAME_OVER_ART = [[
_###_ __#__ #___# #####
#____ _#_#_ ##_## #____
#_### ##### #_#_# ####_
#___# #___# #___# #____
_###_ #___# #___# #####
_###_ #___# ##### ####_
#___# #___# #____ #___#
#___# _#_#_ ####_ ####_
#___# __#__ #____ #_#__
_###_ __#__ ##### #__##
]]
local REASON_MESSAGES = {
ism = "Your impostor syndrome consumed you.",
bm = "You burned out like a cheap candle.",
days = "100 days passed. The cycle never broke.",
}
--- Shows the game over screen.
--- @within GameOverWindow
--- @param reason string One of "ism", "bm", "days".
function GameOverWindow.show(reason)
GameOverWindow.reason = reason
Context.game_in_progress = false
Glitch.show()
Window.set_current("game_over")
end
--- Draws the game over screen.
--- @within GameOverWindow
function GameOverWindow.draw()
cls(Config.colors.black)
local cx = Config.screen.width / 2
local bounds = AsciiArt.draw(GAME_OVER_ART, {
char_w = 4,
char_h = 6,
line_gap = 1,
word_gap = 10,
color = Config.colors.red,
})
local msg = REASON_MESSAGES[GameOverWindow.reason] or ""
Print.text_center(msg, cx, bounds.bottom + 8, Config.colors.white)
Print.text_center("Press Z to restart", cx, Config.screen.height - 10, Config.colors.light_grey)
end
--- Updates the game over screen logic.
--- @within GameOverWindow
function GameOverWindow.update()
if Input.select() then
Context.reset()
MenuWindow.refresh_menu_items()
Window.set_current("menu")
end
end

View File

@@ -19,7 +19,7 @@ end
--- Draws the header with title and separator. --- Draws the header with title and separator.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.draw_header() function MenuWindow.draw_header()
rect(0, 0, Config.screen.width, HEADER_H, Config.colors.black) rect(0, 0, Config.screen.width, HEADER_H, Config.colors.dark_grey)
rect(0, HEADER_H - 2, Config.screen.width, 2, Config.colors.light_blue) rect(0, HEADER_H - 2, Config.screen.width, 2, Config.colors.light_blue)
local cx = Config.screen.width / 2 local cx = Config.screen.width / 2
@@ -37,19 +37,17 @@ end
function MenuWindow.draw_norman() function MenuWindow.draw_norman()
local nx = math.floor(Config.screen.width * 0.45 / 2) - 32 local nx = math.floor(Config.screen.width * 0.45 / 2) - 32
local ny = HEADER_H + math.floor((Config.screen.height - HEADER_H - 96) / 2) local ny = HEADER_H + math.floor((Config.screen.height - HEADER_H - 96) / 2)
spr(272, nx, ny, Config.colors.transparent, 4) spr(272, nx, ny, 0, 4)
spr(273, nx + 32, ny, Config.colors.transparent, 4) spr(273, nx + 32, ny, 0, 4)
spr(288, nx, ny + 32, Config.colors.transparent, 4) spr(288, nx, ny + 32, 0, 4)
spr(289, nx + 32, ny + 32, Config.colors.transparent, 4) spr(289, nx + 32, ny + 32, 0, 4)
spr(304, nx, ny + 64, Config.colors.transparent, 4) spr(304, nx, ny + 64, 0, 4)
spr(305, nx + 32, ny + 64, Config.colors.transparent, 4) spr(305, nx + 32, ny + 64, 0, 4)
end end
--- Draws the menu window. --- Draws the menu window.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.draw() function MenuWindow.draw()
cls(Config.colors.blue
)
MenuWindow.draw_header() MenuWindow.draw_header()
if _anim > 0 then if _anim > 0 then
@@ -102,13 +100,17 @@ function MenuWindow.update()
end end
end end
--- Opens player name entry then starts a new game. --- Starts a new game from the menu.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.new_game() function MenuWindow.new_game()
PlayerNameWindow.init(function()
Context.new_game() Context.new_game()
end) end
Window.set_current("player_name")
--- Loads a game from the menu.
--- @within MenuWindow
function MenuWindow.load_game()
Context.load_game()
GameWindow.set_state("game")
end end
--- Saves the current game from the menu. --- Saves the current game from the menu.
@@ -135,20 +137,6 @@ function MenuWindow.controls()
Window.set_current("controls") Window.set_current("controls")
end end
--- Opens the player name entry screen (test mode shortcut).
--- @within MenuWindow
function MenuWindow.player_name()
PlayerNameWindow.init()
Window.set_current("player_name")
end
--- Opens the credits screen.
--- @within MenuWindow
function MenuWindow.credits()
CreditsWindow.init()
Window.set_current("credits")
end
--- Opens the audio test menu. --- Opens the audio test menu.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.audio_test() function MenuWindow.audio_test()
@@ -163,14 +151,6 @@ function MenuWindow.continued()
GameWindow.set_state("continued") GameWindow.set_state("continued")
end end
--- Opens the end screen for testing.
--- @within MenuWindow
function MenuWindow.end_screen()
Context._end.state = "ending"
Context._end.selection = 1
GameWindow.set_state("end")
end
--- Opens the DDR minigame test. --- Opens the DDR minigame test.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.ddr_test() function MenuWindow.ddr_test()
@@ -189,15 +169,13 @@ function MenuWindow.refresh_menu_items()
end end
table.insert(_menu_items, {label = "New Game", decision = MenuWindow.new_game}) table.insert(_menu_items, {label = "New Game", decision = MenuWindow.new_game})
table.insert(_menu_items, {label = "Load Game", decision = MenuWindow.load_game})
table.insert(_menu_items, {label = "Controls", decision = MenuWindow.controls}) table.insert(_menu_items, {label = "Controls", decision = MenuWindow.controls})
table.insert(_menu_items, {label = "Credits", decision = MenuWindow.credits})
if Context.test_mode then if Context.test_mode then
table.insert(_menu_items, {label = "Audio Test", decision = MenuWindow.audio_test}) table.insert(_menu_items, {label = "Audio Test", decision = MenuWindow.audio_test})
table.insert(_menu_items, {label = "To Be Continued...", decision = MenuWindow.continued}) table.insert(_menu_items, {label = "To Be Continued...", decision = MenuWindow.continued})
table.insert(_menu_items, {label = "DDR Test", decision = MenuWindow.ddr_test}) table.insert(_menu_items, {label = "DDR Test", decision = MenuWindow.ddr_test})
table.insert(_menu_items, {label = "End Screen", decision = MenuWindow.end_screen})
table.insert(_menu_items, {label = "Player Name", decision = MenuWindow.player_name})
end end
table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit}) table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit})

View File

@@ -1,44 +1,7 @@
--- @section MinigameDDRWindow --- @section MinigameDDRWindow
---@class MinigameDDRState
---@field special_mode string
---@field bar_fill number
---@field max_fill number
---@field fill_per_hit number
---@field miss_penalty number
---@field bar_x number
---@field bar_y number
---@field bar_width number
---@field bar_height number
---@field arrow_size number
---@field arrow_spawn_timer number
---@field arrow_spawn_interval number
---@field arrow_fall_speed number
---@field arrows table
---@field target_y number
---@field target_arrows table
---@field hit_threshold number
---@field button_pressed_timers table
---@field button_press_duration number
---@field input_cooldowns table
---@field input_cooldown_duration number
---@field frame_counter number
---@field current_song table?
---@field pattern_index number
---@field use_pattern boolean
---@field generated_length number
---@field return_window string?
---@field win_timer number
---@field on_win fun(ctx: MinigameDDRState)|nil
---@field total_misses number
---@field total_hits number
---@field special_mode_condition boolean
---@field special_mode_counter number
---@field debug_song_key string|nil
---@field debug_status string|nil
--- Background drawing for DDR minigame. --- Background drawing for DDR minigame.
--- @within MinigameDDRWindow --- @witin MinigameDDRWindow
function MinigameDDRWindow.draw_background() function MinigameDDRWindow.draw_background()
local img_values = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1} local img_values = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}
local img_runs = {809,40,5,26,178,42,4,7,30,10,127,103,11,1,116,124,116,124,115,18,60,47,115,10,105,10,115,9,108,9,114,9,108,9,114,9,108,9,114,9,33,31,44,9,114,9,34,28,46,9,114,9,108,9,114,9,108,9,114,9,108,9,114,9,108,9,114,9,109,8,114,9,109,8,114,9,109,9,112,10,105,1,3,9,111,11,104,2,3,9,111,11,101,5,3,9,111,11,101,5,3,9,111,9,103,5,3,9,111,9,99,1,2,6,3,9,111,9,99,1,2,8,1,9,111,9,3,1,88,1,3,1,2,11,1,9,111,9,3,1,88,1,3,14,1,9,111,9,3,1,88,1,3,1,2,11,1,9,111,9,3,1,88,1,5,12,1,9,111,9,3,1,88,1,3,14,1,9,111,9,3,1,88,3,1,1,2,11,1,9,111,9,3,1,88,3,1,14,1,9,111,9,3,1,88,3,2,13,2,8,111,9,3,1,88,3,3,12,3,8,110,9,3,1,88,3,3,12,3,9,109,9,3,1,88,3,1,14,3,9,109,9,3,1,90,1,1,7,3,4,3,9,109,9,3,1,90,1,1,5,6,3,3,9,108,10,3,1,44,1,4,1,40,1,1,5,7,2,3,9,108,10,3,1,44,1,4,1,38,3,1,5,7,3,2,9,108,10,3,1,48,1,39,3,1,5,7,2,3,9,108,10,3,1,88,3,1,5,6,3,3,9,108,10,3,1,32,5,4,4,3,2,38,3,1,15,2,9,108,10,3,1,41,5,2,2,2,4,32,3,1,15,2,9,108,10,2,2,41,9,2,5,3,1,3,1,23,3,1,9,1,5,2,9,108,10,2,2,41,12,35,3,1,7,4,4,2,9,108,10,2,2,32,26,30,3,1,5,7,3,2,9,108,10,2,2,36,21,31,9,7,3,2,9,108,10,2,2,35,23,30,10,6,3,2,9,108,10,2,2,35,23,30,11,4,4,2,9,108,10,2,2,34,24,30,19,2,9,108,10,2,2,33,25,30,19,2,9,108,10,2,2,32,28,28,19,2,9,108,10,2,2,32,30,26,19,2,9,108,10,2,2,33,31,24,19,2,9,108,10,2,4,37,17,32,19,2,10,107,10,2,5,85,19,2,10,107,10,2,109,2,10,107,12,1,107,3,10,107,133,107,133,107,133,107,133,107,133,107,133,107,133,118,111,129,6,63,3,28,10,121,13,98,6,142,7,76,6,129,10,13,5,77,15,109,4,31,4,78,4,24,7,75,173,66,176,64,177,62,178,62,178,62,56,31,2,7,2,2,3,2,1,2,1,61,8,62,56,114,8,62,56,114,8,62,56,114,8,62,56,114,8,62,9,8,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,115,8,61,8,8,40,115,8,61,56,115,8,61,13,2,1,1,1,1,16,1,1,2,17,115,8,61,13,2,1,1,1,2,1,1,10,2,1,1,1,2,1,2,7,1,6,115,8,60,14,2,1,1,1,5,9,2,1,1,1,2,1,2,6,2,6,115,8,59,15,2,1,1,1,5,9,2,1,1,1,2,1,2,6,2,6,115,8,59,15,2,1,1,1,6,8,2,1,1,1,2,1,2,14,115,8,59,6,1,11,1,1,7,10,1,1,2,1,2,14,115,8,59,6,1,11,1,1,7,10,1,1,2,1,2,1,1,12,115,9,58,6,1,1,2,10,9,8,1,1,2,1,2,1,1,12,115,9,58,6,1,1,2,8,1,1,9,8,1,1,2,1,2,1,1,11,116,9,58,6,1,1,2,1,2,7,9,8,1,1,2,1,2,1,1,11,116,9,58,6,1,1,2,1,2,7,9,10,2,1,2,1,1,11,116,9,58,57,116,9,58,58,115,9,102,13,116,9,58,48,2,10,1,3,22,84,5,7,58,158,7,5,6,6,75,3,7,2,7,1,7,2,6,1,6,2,6,2,4,4,6,2,6,1,6,2,6,3,6,1,6,5,7,8,7,9,11,1,9,2,50,1,22,1,14,5,3,5,3,4,3,6,3,5,2,16,2,5,3,14,2,6,2,6,5,5,11,4,30,1,50,1,37,6,3,5,3,5,2,6,3,5,3,6,1,7,2,6,2,15,2,6,2,5,6,5,12,1,15,1,106,93,2,8,10,5,2,6,2,5,4,4,100,7,3,13,2,65,3,8,3,5,2,5,4,4,3,5,4,4,100,94,2,5,3,5,4,4,6,5,2,5,105,86,2,13,3,5,4,4,6,5,2,1,1,3,102,4,2,24,2,62,1,1,2,7,3,5,4,5,4,5,2,8,4,2,92,5,2,24,2,61,5,5,7,2,5,6,3,4,3,7,102,88,6,7,12,8,6,1,3,7,103,87,6,7,11,9,6,1,3,7,110,1,9,9,5,1,2,1,3,47,162,1,10,6,27,34,162,1,10,6,27,34,97,3,57,14,2,7,26,66,9,33,5,2,17,223,17,223,18,222,47,193,53,1,3,163,19,1,85,109,14,29,36,151,784} local img_runs = {809,40,5,26,178,42,4,7,30,10,127,103,11,1,116,124,116,124,115,18,60,47,115,10,105,10,115,9,108,9,114,9,108,9,114,9,108,9,114,9,33,31,44,9,114,9,34,28,46,9,114,9,108,9,114,9,108,9,114,9,108,9,114,9,108,9,114,9,109,8,114,9,109,8,114,9,109,9,112,10,105,1,3,9,111,11,104,2,3,9,111,11,101,5,3,9,111,11,101,5,3,9,111,9,103,5,3,9,111,9,99,1,2,6,3,9,111,9,99,1,2,8,1,9,111,9,3,1,88,1,3,1,2,11,1,9,111,9,3,1,88,1,3,14,1,9,111,9,3,1,88,1,3,1,2,11,1,9,111,9,3,1,88,1,5,12,1,9,111,9,3,1,88,1,3,14,1,9,111,9,3,1,88,3,1,1,2,11,1,9,111,9,3,1,88,3,1,14,1,9,111,9,3,1,88,3,2,13,2,8,111,9,3,1,88,3,3,12,3,8,110,9,3,1,88,3,3,12,3,9,109,9,3,1,88,3,1,14,3,9,109,9,3,1,90,1,1,7,3,4,3,9,109,9,3,1,90,1,1,5,6,3,3,9,108,10,3,1,44,1,4,1,40,1,1,5,7,2,3,9,108,10,3,1,44,1,4,1,38,3,1,5,7,3,2,9,108,10,3,1,48,1,39,3,1,5,7,2,3,9,108,10,3,1,88,3,1,5,6,3,3,9,108,10,3,1,32,5,4,4,3,2,38,3,1,15,2,9,108,10,3,1,41,5,2,2,2,4,32,3,1,15,2,9,108,10,2,2,41,9,2,5,3,1,3,1,23,3,1,9,1,5,2,9,108,10,2,2,41,12,35,3,1,7,4,4,2,9,108,10,2,2,32,26,30,3,1,5,7,3,2,9,108,10,2,2,36,21,31,9,7,3,2,9,108,10,2,2,35,23,30,10,6,3,2,9,108,10,2,2,35,23,30,11,4,4,2,9,108,10,2,2,34,24,30,19,2,9,108,10,2,2,33,25,30,19,2,9,108,10,2,2,32,28,28,19,2,9,108,10,2,2,32,30,26,19,2,9,108,10,2,2,33,31,24,19,2,9,108,10,2,4,37,17,32,19,2,10,107,10,2,5,85,19,2,10,107,10,2,109,2,10,107,12,1,107,3,10,107,133,107,133,107,133,107,133,107,133,107,133,107,133,118,111,129,6,63,3,28,10,121,13,98,6,142,7,76,6,129,10,13,5,77,15,109,4,31,4,78,4,24,7,75,173,66,176,64,177,62,178,62,178,62,56,31,2,7,2,2,3,2,1,2,1,61,8,62,56,114,8,62,56,114,8,62,56,114,8,62,56,114,8,62,9,8,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,115,8,61,8,8,40,115,8,61,56,115,8,61,13,2,1,1,1,1,16,1,1,2,17,115,8,61,13,2,1,1,1,2,1,1,10,2,1,1,1,2,1,2,7,1,6,115,8,60,14,2,1,1,1,5,9,2,1,1,1,2,1,2,6,2,6,115,8,59,15,2,1,1,1,5,9,2,1,1,1,2,1,2,6,2,6,115,8,59,15,2,1,1,1,6,8,2,1,1,1,2,1,2,14,115,8,59,6,1,11,1,1,7,10,1,1,2,1,2,14,115,8,59,6,1,11,1,1,7,10,1,1,2,1,2,1,1,12,115,9,58,6,1,1,2,10,9,8,1,1,2,1,2,1,1,12,115,9,58,6,1,1,2,8,1,1,9,8,1,1,2,1,2,1,1,11,116,9,58,6,1,1,2,1,2,7,9,8,1,1,2,1,2,1,1,11,116,9,58,6,1,1,2,1,2,7,9,10,2,1,2,1,1,11,116,9,58,57,116,9,58,58,115,9,102,13,116,9,58,48,2,10,1,3,22,84,5,7,58,158,7,5,6,6,75,3,7,2,7,1,7,2,6,1,6,2,6,2,4,4,6,2,6,1,6,2,6,3,6,1,6,5,7,8,7,9,11,1,9,2,50,1,22,1,14,5,3,5,3,4,3,6,3,5,2,16,2,5,3,14,2,6,2,6,5,5,11,4,30,1,50,1,37,6,3,5,3,5,2,6,3,5,3,6,1,7,2,6,2,15,2,6,2,5,6,5,12,1,15,1,106,93,2,8,10,5,2,6,2,5,4,4,100,7,3,13,2,65,3,8,3,5,2,5,4,4,3,5,4,4,100,94,2,5,3,5,4,4,6,5,2,5,105,86,2,13,3,5,4,4,6,5,2,1,1,3,102,4,2,24,2,62,1,1,2,7,3,5,4,5,4,5,2,8,4,2,92,5,2,24,2,61,5,5,7,2,5,6,3,4,3,7,102,88,6,7,12,8,6,1,3,7,103,87,6,7,11,9,6,1,3,7,110,1,9,9,5,1,2,1,3,47,162,1,10,6,27,34,162,1,10,6,27,34,97,3,57,14,2,7,26,66,9,33,5,2,17,223,17,223,18,222,47,193,53,1,3,163,19,1,85,109,14,29,36,151,784}
@@ -49,7 +12,7 @@ end
--- Gets initial DDR minigame configuration. --- Gets initial DDR minigame configuration.
--- @within MinigameDDRWindow --- @within MinigameDDRWindow
---@return MinigameDDRState --- @return result table The default DDR minigame configuration.
function MinigameDDRWindow.init_context() function MinigameDDRWindow.init_context()
local arrow_size = 12 local arrow_size = 12
local arrow_spacing = 30 local arrow_spacing = 30
@@ -70,7 +33,7 @@ function MinigameDDRWindow.init_context()
arrow_spawn_interval = 45, arrow_spawn_interval = 45,
arrow_fall_speed = 1.5, arrow_fall_speed = 1.5,
arrows = {}, arrows = {},
target_y = 120, target_y = 115,
target_arrows = { target_arrows = {
{ dir = "left", x = start_x }, { dir = "left", x = start_x },
{ dir = "down", x = start_x + arrow_size + arrow_spacing }, { dir = "down", x = start_x + arrow_size + arrow_spacing },
@@ -97,11 +60,10 @@ function MinigameDDRWindow.init_context()
} }
end end
--- Builds song data (and optional generated pattern) for the minigame.
--- @within MinigameDDRWindow
function MinigameDDRWindow.prepareSong(song, generated_length, special_mode) function MinigameDDRWindow.prepareSong(song, generated_length, special_mode)
local current_song = Util.deepcopy(song) local current_song = Util.deepcopy(song)
if current_song.generated then if current_song.generated then
local pattern = musicator_generate_pattern(generated_length, current_song.bpm, current_song.spd * 4) local pattern = musicator_generate_pattern(generated_length, current_song.bpm, current_song.spd * 4)
current_song.pattern = pattern current_song.pattern = pattern
@@ -117,9 +79,6 @@ function MinigameDDRWindow.prepareSong(song, generated_length, special_mode)
return current_song return current_song
end end
--- Handles hit feedback and special-mode scoring for one arrow.
--- @within MinigameDDRWindow
---@param game_context MinigameDDRState
function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context) function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context)
local special_mode = game_context.special_mode local special_mode = game_context.special_mode
@@ -130,7 +89,6 @@ function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context)
Audio.sfx_arrowhit(arrow.note) Audio.sfx_arrowhit(arrow.note)
game_context.special_mode_counter = game_context.special_mode_counter + 1 game_context.special_mode_counter = game_context.special_mode_counter + 1
else else
game_context.total_misses = game_context.total_misses + 1
if game_context.special_mode_condition then Audio.sfx_bloop() end if game_context.special_mode_condition then Audio.sfx_bloop() end
game_context.special_mode_condition = false game_context.special_mode_condition = false
end end
@@ -142,26 +100,22 @@ function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context)
game_context.bar_fill = game_context.bar_fill - game_context.fill_per_hit game_context.bar_fill = game_context.bar_fill - game_context.fill_per_hit
end end
else else
game_context.total_misses = game_context.total_misses + 1
if game_context.special_mode_condition then Audio.sfx_bloop() end if game_context.special_mode_condition then Audio.sfx_bloop() end
game_context.special_mode_condition = false game_context.special_mode_condition = false
end end
elseif special_mode == "only_nothing" then elseif special_mode == "only_nothing" then
game_context.total_misses = game_context.total_misses + 1
if game_context.special_mode_condition then Audio.sfx_bloop() end if game_context.special_mode_condition then Audio.sfx_bloop() end
game_context.special_mode_condition = false game_context.special_mode_condition = false
end end
end end
--- Ends the minigame: win timer, sfx, and special-mode pass/fail bookkeeping.
--- @within MinigameDDRWindow
function MinigameDDRWindow.on_end(game_context) function MinigameDDRWindow.on_end(game_context)
Audio.sfx_select() Audio.sfx_select()
game_context.win_timer = Config.timing.minigame_win_duration game_context.win_timer = Config.timing.minigame_win_duration
local num_special = 0 local num_special = 0
for _, v in ipairs(game_context.current_song.pattern) do for _,v in ipairs(game_context.current_song.pattern) do
if game_context.special_mode == "only_left" then if game_context.special_mode == "only_left" then
num_special = num_special + ((v.dir == "left" and 1) or 0) num_special = num_special + ((v.dir == "left" and 1) or 0)
else else
@@ -169,16 +123,16 @@ function MinigameDDRWindow.on_end(game_context)
end end
end end
local sm = game_context.special_mode
local was_ok = true local was_ok = true
if sm == "normal" or sm == "only_special" or sm == "only_left" then if game_context.special_mode == "normal" then
was_ok = game_context.special_mode_counter == num_special
elseif game_context.special_mode == "only_special" then
was_ok = game_context.special_mode_counter == num_special
elseif game_context.special_mode == "only_left" then
was_ok = game_context.special_mode_counter == num_special was_ok = game_context.special_mode_counter == num_special
end end
game_context.special_mode_condition = game_context.special_mode_condition and was_ok game_context.special_mode_condition = game_context.special_mode_condition and was_ok
if game_context.special_mode_condition and sm ~= "normal" then
game_context.bar_fill = game_context.max_fill
end
end end
--- Initializes DDR minigame state. --- Initializes DDR minigame state.
@@ -238,14 +192,12 @@ end
local function spawn_arrow() local function spawn_arrow()
trace("random arrow") trace("random arrow")
---@type MinigameDDRState
local mg = Context.minigame_ddr local mg = Context.minigame_ddr
local y0 = mg.bar_y + mg.bar_height + 10
local target = mg.target_arrows[math.random(1, 4)] local target = mg.target_arrows[math.random(1, 4)]
table.insert(mg.arrows, { table.insert(mg.arrows, {
dir = target.dir, dir = target.dir,
x = target.x, x = target.x,
y = y0 y = mg.bar_y + mg.bar_height + 10
}) })
end end
@@ -253,15 +205,13 @@ end
--- @within MinigameDDRWindow --- @within MinigameDDRWindow
--- @param direction string The direction of the arrow ("left", "down", "up", "right"). --- @param direction string The direction of the arrow ("left", "down", "up", "right").
local function spawn_arrow_dir(direction, note, special) local function spawn_arrow_dir(direction, note, special)
---@type MinigameDDRState
local mg = Context.minigame_ddr local mg = Context.minigame_ddr
local y0 = mg.bar_y + mg.bar_height + 10
for _, target in ipairs(mg.target_arrows) do for _, target in ipairs(mg.target_arrows) do
if target.dir == direction then if target.dir == direction then
table.insert(mg.arrows, { table.insert(mg.arrows, {
dir = direction, dir = direction,
x = target.x, x = target.x,
y = y0, y = mg.bar_y + mg.bar_height + 10,
note = note, note = note,
special = special special = special
}) })
@@ -275,7 +225,6 @@ end
--- @param arrow table The arrow data. --- @param arrow table The arrow data.
--- @return boolean True if the arrow is hit, false otherwise. --- @return boolean True if the arrow is hit, false otherwise.
local function check_hit(arrow) local function check_hit(arrow)
---@type MinigameDDRState
local mg = Context.minigame_ddr local mg = Context.minigame_ddr
local distance = math.abs(arrow.y - mg.target_y) local distance = math.abs(arrow.y - mg.target_y)
return distance <= mg.hit_threshold return distance <= mg.hit_threshold
@@ -286,53 +235,34 @@ end
--- @param arrow table The arrow data. --- @param arrow table The arrow data.
--- @return boolean True if the arrow is missed, false otherwise. --- @return boolean True if the arrow is missed, false otherwise.
local function check_miss(arrow) local function check_miss(arrow)
---@type MinigameDDRState
local mg = Context.minigame_ddr local mg = Context.minigame_ddr
return arrow.y > mg.target_y + mg.hit_threshold return arrow.y > mg.target_y + mg.hit_threshold
end end
--- Rotates a point (px, py) around (cx, cy) by a number of 90-degree CW steps. --- Draws an arrow.
--- @within MinigameDDRWindow
local function rotate(px, py, cx, cy, steps)
local dx, dy = px - cx, py - cy
for _ = 1, steps % 4 do
dx, dy = dy, -dx
end
return cx + dx, cy + dy
end
local arrow_rotations = { down = 0, right = 1, up = 2, left = 3 }
--- Draws an arrow by rotating the "down" arrow shape.
--- @within MinigameDDRWindow --- @within MinigameDDRWindow
--- @param x number The x-coordinate. --- @param x number The x-coordinate.
--- @param y number The y-coordinate. --- @param y number The y-coordinate.
--- @param direction string The direction of the arrow. --- @param direction string The direction of the arrow.
--- @param color number The color of the arrow. --- @param color number The color of the arrow.
local function draw_arrow(x, y, direction, color) local function draw_arrow(x, y, direction, color)
local size = 14 local size = 12
local half = size / 2 local half = size / 2
local pivot_x, pivot_y = x + half, y + half if direction == "left" then
local steps = arrow_rotations[direction] or 0 tri(x + half, y, x, y + half, x + half, y + size, color)
rectb(x + half, y + half - 2, half, 4, color)
local head_left_x, head_left_y = rotate(x, y + half, pivot_x, pivot_y, steps) elseif direction == "right" then
local head_tip_x, head_tip_y = rotate(x + half, y + size, pivot_x, pivot_y, steps) tri(x + half, y, x + size, y + half, x + half, y + size, color)
local head_right_x, head_right_y = rotate(x + size, y + half, pivot_x, pivot_y, steps) rectb(x, y + half - 2, half, 4, color)
elseif direction == "up" then
tri(head_left_x, head_left_y, tri(x, y + half, x + half, y, x + size, y + half, color)
head_tip_x, head_tip_y, rectb(x + half - 2, y + half, 4, half, color)
head_right_x, head_right_y, color) elseif direction == "down" then
tri(x, y + half, x + half, y + size, x + size, y + half, color)
local stem_top_x, stem_top_y = rotate(x + half - 3, y, pivot_x, pivot_y, steps) rectb(x + half - 2, y, 4, half, color)
local stem_bot_x, stem_bot_y = rotate(x + half + 3, y + half, pivot_x, pivot_y, steps) end
local stem_x = math.min(stem_top_x, stem_bot_x)
local stem_y = math.min(stem_top_y, stem_bot_y)
local stem_w = math.abs(stem_bot_x - stem_top_x)
local stem_h = math.abs(stem_bot_y - stem_top_y)
rectb(stem_x, stem_y, stem_w, stem_h, color)
end end
--- Updates DDR minigame logic. --- Updates DDR minigame logic.
--- @within MinigameDDRWindow --- @within MinigameDDRWindow
function MinigameDDRWindow.update() function MinigameDDRWindow.update()
@@ -342,8 +272,7 @@ function MinigameDDRWindow.update()
mg.win_timer = mg.win_timer - 1 mg.win_timer = mg.win_timer - 1
if mg.win_timer == 0 then if mg.win_timer == 0 then
Audio.music_stop() Audio.music_stop()
Meter.apply_ddr_reward(mg.total_misses) Meter.on_minigame_complete()
if not Context.game_in_progress then return end
if mg.on_win then if mg.on_win then
mg.on_win(mg) mg.on_win(mg)
else else
@@ -394,7 +323,10 @@ function MinigameDDRWindow.update()
arrow.y = arrow.y + mg.arrow_fall_speed arrow.y = arrow.y + mg.arrow_fall_speed
if check_miss(arrow) then if check_miss(arrow) then
table.insert(arrows_to_remove, i) table.insert(arrows_to_remove, i)
mg.bar_fill = math.max(0, mg.bar_fill - mg.miss_penalty) mg.bar_fill = mg.bar_fill - mg.miss_penalty
if mg.bar_fill < 0 then
mg.bar_fill = 0
end
mg.total_misses = mg.total_misses + 1 mg.total_misses = mg.total_misses + 1
end end
end end
@@ -438,14 +370,20 @@ function MinigameDDRWindow.update()
if arrow.dir == dir and check_hit(arrow) then if arrow.dir == dir and check_hit(arrow) then
MinigameDDRWindow.on_arrow_hit_special(arrow, mg) MinigameDDRWindow.on_arrow_hit_special(arrow, mg)
mg.bar_fill = math.min(mg.max_fill, mg.bar_fill + mg.fill_per_hit) mg.bar_fill = mg.bar_fill + mg.fill_per_hit
if mg.bar_fill > mg.max_fill then
mg.bar_fill = mg.max_fill
end
table.remove(mg.arrows, i) table.remove(mg.arrows, i)
hit = true hit = true
break break
end end
end end
if not hit then if not hit then
mg.bar_fill = math.max(0, mg.bar_fill - 2) mg.bar_fill = mg.bar_fill - 2
if mg.bar_fill < 0 then
mg.bar_fill = 0
end
mg.total_misses = mg.total_misses + 1 mg.total_misses = mg.total_misses + 1
end end
end end
@@ -455,7 +393,6 @@ end
--- Draws DDR minigame. --- Draws DDR minigame.
--- @within MinigameDDRWindow --- @within MinigameDDRWindow
function MinigameDDRWindow.draw() function MinigameDDRWindow.draw()
---@type MinigameDDRState|nil
local mg = Context.minigame_ddr local mg = Context.minigame_ddr
if not mg then if not mg then
cls(0) cls(0)
@@ -483,6 +420,8 @@ function MinigameDDRWindow.draw()
end end
rect(mg.bar_x, mg.bar_y, fill_width, mg.bar_height, bar_color) rect(mg.bar_x, mg.bar_y, fill_width, mg.bar_height, bar_color)
end end
local percentage = math.floor((mg.bar_fill / mg.max_fill) * 100)
Print.text_center(percentage .. "%", mg.bar_x + mg.bar_width / 2, mg.bar_y + 2, Config.colors.black)
if mg.target_arrows then if mg.target_arrows then
for _, target in ipairs(mg.target_arrows) do for _, target in ipairs(mg.target_arrows) do
local is_pressed = mg.button_pressed_timers[target.dir] and mg.button_pressed_timers[target.dir] > 0 local is_pressed = mg.button_pressed_timers[target.dir] and mg.button_pressed_timers[target.dir] > 0
@@ -496,7 +435,7 @@ function MinigameDDRWindow.draw()
draw_arrow(arrow.x, arrow.y, arrow.dir, arrow_color) draw_arrow(arrow.x, arrow.y, arrow.dir, arrow_color)
end end
end end
Print.text_center_contour("Hit the arrows!", Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_blue) Print.text_center("Hit the arrows!", Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_grey)
local debug_y = 60 local debug_y = 60
if mg.debug_status then if mg.debug_status then
Print.text_center(mg.debug_status, Config.screen.width / 2, debug_y, Config.colors.item) Print.text_center(mg.debug_status, Config.screen.width / 2, debug_y, Config.colors.item)
@@ -520,8 +459,7 @@ function MinigameDDRWindow.draw()
elseif Context.test_mode then elseif Context.test_mode then
Print.text_center("RANDOM MODE", Config.screen.width / 2, debug_y, Config.colors.blue) Print.text_center("RANDOM MODE", Config.screen.width / 2, debug_y, Config.colors.blue)
end end
if mg.win_timer > 0 then
if mg.win_timer > 0 then
if mg.special_mode_condition then if mg.special_mode_condition then
Minigame.draw_win_overlay("SUCCESS...?") Minigame.draw_win_overlay("SUCCESS...?")
elseif mg.total_hits < 10 then elseif mg.total_hits < 10 then
@@ -529,5 +467,5 @@ function MinigameDDRWindow.draw()
else else
Minigame.draw_win_overlay() Minigame.draw_win_overlay()
end end
end end
end end

View File

@@ -1,35 +1,6 @@
--- @section MinigameButtonMashWindow
---@class MinigameButtonMashState
---@field bar_fill number
---@field target_points number
---@field fill_per_press number
---@field base_degradation number
---@field degradation_multiplier number
---@field button_pressed_timer number
---@field button_press_duration number
---@field instruction_text string
---@field show_progress_text boolean
---@field return_window string?
---@field bar_x number
---@field bar_y number
---@field bar_width number
---@field bar_height number
---@field button_x number
---@field button_y number
---@field button_size number
---@field focus_center_x number?
---@field focus_center_y number?
---@field focus_initial_radius number
---@field win_timer number
---@field on_win (fun())?
---@field meter_on_complete (fun(elapsed_sec: number))?
---@field start_ms number?
---@field elapsed_sec number?
--- Gets initial button mash minigame configuration. --- Gets initial button mash minigame configuration.
--- @within MinigameButtonMashWindow --- @within MinigameButtonMashWindow
---@return MinigameButtonMashState --- @return result table The default button mash minigame configuration.
function MinigameButtonMashWindow.init_context() function MinigameButtonMashWindow.init_context()
return { return {
bar_fill = 0, bar_fill = 0,
@@ -53,11 +24,7 @@ function MinigameButtonMashWindow.init_context()
focus_center_y = nil, focus_center_y = nil,
focus_initial_radius = 0, focus_initial_radius = 0,
win_timer = 0, win_timer = 0,
on_win = nil, on_win = nil
--- If set, called with elapsed_sec instead of Meter.on_minigame_complete()
meter_on_complete = nil,
start_ms = nil,
elapsed_sec = nil,
} }
end end
@@ -82,12 +49,9 @@ end
--- @param return_window string The window ID to return to after the minigame.<br/> --- @param return_window string The window ID to return to after the minigame.<br/>
--- @param[opt] params table Optional parameters for minigame configuration.<br/> --- @param[opt] params table Optional parameters for minigame configuration.<br/>
function MinigameButtonMashWindow.start(return_window, params) function MinigameButtonMashWindow.start(return_window, params)
Audio.music_stop()
MinigameButtonMashWindow.init(params) MinigameButtonMashWindow.init(params)
---@type MinigameButtonMashState
local mg = Context.minigame_button_mash local mg = Context.minigame_button_mash
mg.return_window = return_window or "game" mg.return_window = return_window or "game"
mg.start_ms = time()
if mg.focus_center_x then if mg.focus_center_x then
Focus.start_driven(mg.focus_center_x, mg.focus_center_y, { Focus.start_driven(mg.focus_center_x, mg.focus_center_y, {
initial_radius = mg.focus_initial_radius initial_radius = mg.focus_initial_radius
@@ -99,18 +63,12 @@ end
--- Updates button mash minigame logic. --- Updates button mash minigame logic.
--- @within MinigameButtonMashWindow --- @within MinigameButtonMashWindow
function MinigameButtonMashWindow.update() function MinigameButtonMashWindow.update()
---@type MinigameButtonMashState
local mg = Context.minigame_button_mash local mg = Context.minigame_button_mash
if mg.win_timer > 0 then if mg.win_timer > 0 then
mg.win_timer = mg.win_timer - 1 mg.win_timer = mg.win_timer - 1
if mg.win_timer == 0 then if mg.win_timer == 0 then
if mg.meter_on_complete then Meter.on_minigame_complete()
mg.meter_on_complete(mg.elapsed_sec or 0)
else
Meter.on_minigame_complete(false)
end
if not Context.game_in_progress then return end
if mg.focus_center_x then Focus.stop() end if mg.focus_center_x then Focus.stop() end
Context.home_norman_visible = true Context.home_norman_visible = true
Context.have_done_work_today = false Context.have_done_work_today = false
@@ -138,7 +96,6 @@ function MinigameButtonMashWindow.update()
end end
if mg.bar_fill >= mg.target_points then if mg.bar_fill >= mg.target_points then
Audio.sfx_select() Audio.sfx_select()
mg.elapsed_sec = (time() - mg.start_ms) / 1000
mg.win_timer = Config.timing.minigame_win_duration mg.win_timer = Config.timing.minigame_win_duration
return return
end end
@@ -158,7 +115,6 @@ end
--- Draws button mash minigame. --- Draws button mash minigame.
--- @within MinigameButtonMashWindow --- @within MinigameButtonMashWindow
function MinigameButtonMashWindow.draw() function MinigameButtonMashWindow.draw()
---@type MinigameButtonMashState
local mg = Context.minigame_button_mash local mg = Context.minigame_button_mash
if mg.return_window == "game" then if mg.return_window == "game" then
GameWindow.draw_with_underlay(function() GameWindow.draw_with_underlay(function()
@@ -189,7 +145,7 @@ function MinigameButtonMashWindow.draw()
circ(mg.button_x, mg.button_y, mg.button_size - 2, button_color) circ(mg.button_x, mg.button_y, mg.button_size - 2, button_color)
end end
Print.text_center("Z", mg.button_x, mg.button_y - 3, button_color) Print.text_center("Z", mg.button_x, mg.button_y - 3, button_color)
Print.text_center_contour(mg.instruction_text, Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_blue) Print.text_center(mg.instruction_text, Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_grey)
if mg.show_progress_text then if mg.show_progress_text then
local points_text = math.floor(mg.bar_fill) .. "/" .. mg.target_points local points_text = math.floor(mg.bar_fill) .. "/" .. mg.target_points
Print.text_center(points_text, mg.bar_x + mg.bar_width / 2, mg.bar_y + 2, Config.colors.black) Print.text_center(points_text, mg.bar_x + mg.bar_width / 2, mg.bar_y + 2, Config.colors.black)

View File

@@ -53,7 +53,6 @@ end
--- @param return_window string The window ID to return to after the minigame.<br/> --- @param return_window string The window ID to return to after the minigame.<br/>
--- @param[opt] params table Optional parameters for minigame configuration.<br/> --- @param[opt] params table Optional parameters for minigame configuration.<br/>
function MinigameRhythmWindow.start(return_window, params) function MinigameRhythmWindow.start(return_window, params)
Audio.music_stop()
MinigameRhythmWindow.init(params) MinigameRhythmWindow.init(params)
local mg = Context.minigame_rhythm local mg = Context.minigame_rhythm
mg.return_window = return_window or "game" mg.return_window = return_window or "game"
@@ -73,8 +72,7 @@ function MinigameRhythmWindow.update()
if mg.win_timer > 0 then if mg.win_timer > 0 then
mg.win_timer = mg.win_timer - 1 mg.win_timer = mg.win_timer - 1
if mg.win_timer == 0 then if mg.win_timer == 0 then
Meter.on_minigame_complete(false) Meter.on_minigame_complete()
if not Context.game_in_progress then return end
if mg.focus_center_x then Focus.stop() end if mg.focus_center_x then Focus.stop() end
if mg.on_win then if mg.on_win then
mg.on_win() mg.on_win()
@@ -148,14 +146,14 @@ function MinigameRhythmWindow.draw()
local target_left = mg.target_center - (mg.target_width / 2) local target_left = mg.target_center - (mg.target_width / 2)
local target_x = mg.bar_x + (target_left * mg.bar_width) local target_x = mg.bar_x + (target_left * mg.bar_width)
local target_width_pixels = mg.target_width * mg.bar_width local target_width_pixels = mg.target_width * mg.bar_width
rect(target_x, mg.bar_y, target_width_pixels, mg.bar_height, Config.colors.orange) rect(target_x, mg.bar_y, target_width_pixels, mg.bar_height, Config.colors.light_blue)
local line_x = mg.bar_x + (mg.line_position * mg.bar_width) local line_x = mg.bar_x + (mg.line_position * mg.bar_width)
rect(line_x - 1, mg.bar_y, 2, mg.bar_height, Config.colors.light_blue) rect(line_x - 1, mg.bar_y, 2, mg.bar_height, Config.colors.item)
Print.text_center_contour( Print.text_center(
"Sleep Norman ... Sleep!", "Sleep Norman ... Sleep!",
Config.screen.width / 2, Config.screen.width / 2,
mg.bar_y + mg.bar_height + 14, mg.bar_y + mg.bar_height + 14,
Config.colors.light_blue Config.colors.light_grey
) )
local button_color = Config.colors.light_grey local button_color = Config.colors.light_grey
if mg.button_pressed_timer > 0 then if mg.button_pressed_timer > 0 then

View File

@@ -1,115 +0,0 @@
--- @section PlayerNameWindow
local _frame = 0
local _on_confirm = nil
local MAX_LEN = 3
local BOX_W = 24
local BOX_H = 24
local BOX_GAP = 12
local BOX_Y = 50
local WARN_Y = 104
local function box_start_x()
return math.floor((Config.screen.width - (MAX_LEN * BOX_W + (MAX_LEN - 1) * BOX_GAP)) / 2)
end
local function box_x(i)
return box_start_x() + (i - 1) * (BOX_W + BOX_GAP)
end
--- Initialises the player name window.
--- @within PlayerNameWindow
--- @param on_confirm function Called with the entered name when the player saves.
function PlayerNameWindow.init(on_confirm)
_frame = 0
_on_confirm = on_confirm
TextInput.init(MAX_LEN)
end
local function draw_boxes()
local cursor = TextInput.get_position()
local blink = math.floor(_frame / 18) % 2 == 0
for i = 1, MAX_LEN do
local x = box_x(i)
local is_cur = (i == cursor)
local done = TextInput.is_done()
local fill = (is_cur and not done) and Config.colors.blue or Config.colors.black
local border = (is_cur and not done) and Config.colors.white
or done and Config.colors.light_blue
or Config.colors.dark_grey
rect (x, BOX_Y, BOX_W, BOX_H, fill)
rectb(x, BOX_Y, BOX_W, BOX_H, border)
local show = not (is_cur and blink and not done)
if show then
local ch = TextInput.get_letter(i)
local cw = print(ch, 0, -100, 0, false, 2)
local cx = x + math.floor((BOX_W - cw) / 2)
local cy = BOX_Y + math.floor((BOX_H - 11) / 2)
local col = (is_cur and not done) and Config.colors.white or Config.colors.light_grey
print(ch, cx, cy, col, false, 2)
end
end
-- caret arrow below active box
if not TextInput.is_done() then
local cx = box_x(cursor) + math.floor(BOX_W / 2)
local ay = BOX_Y + BOX_H + 4
line(cx - 4, ay, cx, ay + 4, Config.colors.white)
line(cx + 4, ay, cx, ay + 4, Config.colors.white)
end
end
--- Draws the player name window.
--- @within PlayerNameWindow
function PlayerNameWindow.draw()
cls(Config.colors.black)
Print.text_center("Player Name", Config.screen.width / 2, 14, Config.colors.white, false, 2)
draw_boxes()
if TextInput.is_done() then
Print.text_center("Z: save name B: edit", Config.screen.width / 2, BOX_Y + BOX_H + 12, Config.colors.light_blue)
else
Print.text_center("Up/Dn: letter Lft/Rgt: move Z: ok", Config.screen.width / 2, BOX_Y + BOX_H + 12, Config.colors.dark_grey)
end
-- Warning section
rect(0, WARN_Y, Config.screen.width, Config.screen.height - WARN_Y, Config.colors.blue)
rectb(0, WARN_Y, Config.screen.width, Config.screen.height - WARN_Y, Config.colors.light_blue)
Print.text_center("Remember your name!", Config.screen.width / 2, WARN_Y + 8, Config.colors.white)
Print.text_center("You will need it to load the game.", Config.screen.width / 2, WARN_Y + 20, Config.colors.light_grey)
end
--- Updates player name window logic.
--- @within PlayerNameWindow
function PlayerNameWindow.update()
_frame = _frame + 1
if TextInput.is_done() then
if Input.select() then
Context.player_name = TextInput.get_name()
if _on_confirm then _on_confirm() else Window.set_current("menu") end
elseif Input.back() then
TextInput.prev_position()
end
return
end
if Input.up_repeat() then TextInput.next_letter() end
if Input.down_repeat() then TextInput.prev_letter() end
if Input.right() then TextInput.next_position() end
if Input.select() then TextInput.select_letter() end
if Input.left() or Input.back() then
if TextInput.get_position() > 1 then
TextInput.prev_position()
else
Window.set_current("menu")
end
end
end

View File

@@ -31,9 +31,6 @@ Window.register("minigame_rhythm", MinigameRhythmWindow)
MinigameDDRWindow = {} MinigameDDRWindow = {}
Window.register("minigame_ddr", MinigameDDRWindow) Window.register("minigame_ddr", MinigameDDRWindow)
GameOverWindow = {}
Window.register("game_over", GameOverWindow)
EndWindow = {} EndWindow = {}
Window.register("end", EndWindow) Window.register("end", EndWindow)
@@ -42,9 +39,3 @@ Window.register("discussion", DiscussionWindow)
ContinuedWindow = {} ContinuedWindow = {}
Window.register("continued", ContinuedWindow) Window.register("continued", ContinuedWindow)
CreditsWindow = {}
Window.register("credits", CreditsWindow)
PlayerNameWindow = {}
Window.register("player_name", PlayerNameWindow)