Compare commits

..

6 Commits

Author SHA1 Message Date
9b379d32b3 Corrects the color defects in tiles.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-09 15:58:54 +02:00
5fc6ae5c14 Draws outlines around the figures.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-09 15:48:04 +02:00
1e3716196e Removes the setting of the transparent color to fix the linter error.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-09 13:54:43 +02:00
4b5f11969b Changes the Norman's silhouette. Change the background color of the sprites to pink.
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-09 13:47:24 +02:00
a4a6ad2ab2 Introduces the transparent color. The default is the pink. 2026-04-09 13:46:05 +02:00
87d4f5843b Merge pull request 'beta1 release' (#46) from develop into master
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Reviewed-on: http://git.teletype.hu/games/impostor/pulls/46
2026-03-22 22:49:23 +00:00
40 changed files with 580 additions and 635 deletions

View File

@@ -1,27 +0,0 @@
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

@@ -1,33 +0,0 @@
// 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"
}

2
.gitignore vendored
View File

@@ -1,4 +1,3 @@
.claude
.local .local
impostor.lua impostor.lua
impostor.original.lua impostor.original.lua
@@ -7,4 +6,3 @@ docs
minify.lua minify.lua
*.tic *.tic
*.zip *.zip
NOTES_*

View File

@@ -10,6 +10,7 @@ globals = {
"Discussion", "Discussion",
"Util", "Util",
"Decision", "Decision",
"Situation",
"Screen", "Screen",
"Sprite", "Sprite",
"UI", "UI",
@@ -30,7 +31,7 @@ globals = {
"MenuWindow", "MenuWindow",
"GameWindow", "GameWindow",
"PopupWindow", "PopupWindow",
"ControlsWindow", "ConfigurationWindow",
"AudioTestWindow", "AudioTestWindow",
"MinigameButtonMashWindow", "MinigameButtonMashWindow",
"MinigameRhythmWindow", "MinigameRhythmWindow",
@@ -65,10 +66,6 @@ globals = {
"map", "map",
"time", "time",
"RLE", "RLE",
"mouse",
"Mouse",
"print",
"musicator_generate_pattern",
} }

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.mouse.lua
system/system.asciiart.lua system/system.asciiart.lua
system/system.rle.lua system/system.rle.lua
logic/logic.meter.lua logic/logic.meter.lua
@@ -39,7 +38,10 @@ sprite/sprite.matrix_architect.lua
sprite/sprite.matrix_neo.lua sprite/sprite.matrix_neo.lua
sprite/sprite.matrix_oraculum.lua sprite/sprite.matrix_oraculum.lua
sprite/sprite.matrix_trinity.lua sprite/sprite.matrix_trinity.lua
situation/situation.manager.lua
situation/situation.drink_coffee.lua
decision/decision.manager.lua decision/decision.manager.lua
decision/decision.have_a_coffee.lua
decision/decision.go_to_home.lua decision/decision.go_to_home.lua
decision/decision.go_to_toilet.lua decision/decision.go_to_toilet.lua
decision/decision.go_to_walking_to_office.lua decision/decision.go_to_walking_to_office.lua
@@ -70,7 +72,7 @@ window/window.intro.title.lua
window/window.intro.ttg.lua window/window.intro.ttg.lua
window/window.intro.brief.lua window/window.intro.brief.lua
window/window.menu.lua window/window.menu.lua
window/window.controls.lua window/window.configuration.lua
window/window.audiotest.lua window/window.audiotest.lua
window/window.popup.lua window/window.popup.lua
window/window.minigame.mash.lua window/window.minigame.mash.lua

View File

@@ -0,0 +1,16 @@
Decision.register({
id = "have_a_coffee",
label = "Have a Coffee",
handle = function()
local new_situation_id = Situation.apply("drink_coffee", Context.game.current_screen)
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")
Context.game.current_situation = new_situation_id
end,
})

View File

@@ -134,7 +134,6 @@ end
--- @param decisions table A table of decision items.<br/> --- @param decisions table A table of decision items.<br/>
--- @param selected_decision_index number The current index of the selected decision.<br/> --- @param selected_decision_index number The current index of the selected decision.<br/>
--- @return number selected_decision_index The updated index of the selected decision. --- @return number selected_decision_index The updated index of the selected decision.
--- @return boolean mouse_confirmed True if the user clicked the center to confirm.
function Decision.update(decisions, selected_decision_index) function Decision.update(decisions, selected_decision_index)
if Input.left() then if Input.left() then
Audio.sfx_beep() Audio.sfx_beep()
@@ -143,22 +142,5 @@ function Decision.update(decisions, selected_decision_index)
Audio.sfx_beep() Audio.sfx_beep()
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1) selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
end end
return selected_decision_index
local bar_h = 16
local bar_y = Config.screen.height - bar_h
local prev_zone = { x = 0, y = bar_y, w = 15, h = bar_h }
local next_zone = { x = Config.screen.width-15, y = bar_y, w = 15, h = bar_h }
local confirm_zone = { x = 15, y = bar_y, w = Config.screen.width-30, h = bar_h }
if Mouse.zone(prev_zone) then
Audio.sfx_beep()
selected_decision_index = Util.safeindex(decisions, selected_decision_index - 1)
elseif Mouse.zone(next_zone) then
Audio.sfx_beep()
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
elseif Mouse.zone(confirm_zone) then
return selected_decision_index, true
end
return selected_decision_index, false
end end

View File

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

View File

@@ -23,12 +23,11 @@ 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/>
--- * 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, `current_situation` (string|nil) active situation ID.<br/>
function Context.initial_data() function Context.initial_data()
return { return {
current_menu_item = 1, current_menu_item = 1,
test_mode = false, test_mode = false,
mouse_trace = false,
popup = { popup = {
show = false, show = false,
content = {} content = {}
@@ -47,10 +46,9 @@ function Context.initial_data()
have_done_work_today = false, have_done_work_today = false,
should_ascend = false, should_ascend = false,
have_met_sumphore = false, have_met_sumphore = false,
office_sprites = {},
walking_to_office_sprites = {},
game = { game = {
current_screen = "home", current_screen = "home",
current_situation = nil,
}, },
day_count = 1, day_count = 1,
delta_time = 0, delta_time = 0,

View File

@@ -3,12 +3,12 @@ Util = {}
Meter = {} Meter = {}
Minigame = {} Minigame = {}
Decision = {} Decision = {}
Situation = {}
Screen = {} Screen = {}
Map = {} Map = {}
UI = {} UI = {}
Print = {} Print = {}
Input = {} Input = {}
Mouse = {}
Sprite = {} Sprite = {}
Audio = {} Audio = {}
Focus = {} Focus = {}

View File

@@ -2,7 +2,7 @@
-- 000:0404005f574fc2c3c71d2b53fff1e8ab52367e2553ffa30000875129adff83769c00e436fa77a8ff004dc3c3c7ffccaa -- 000:0404005f574fc2c3c71d2b53fff1e8ab52367e2553ffa30000875129adff83769c00e436fa77a8ff004dc3c3c7ffccaa
-- </PALETTE> -- </PALETTE>
-- <TILES> -- <TILES>
-- 000:00000000c666666006606060c636366006606060c606366006666660c0000000 -- 000:0000000006666660066060600636366006606060060636600666666000000000
-- 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:000000004444442044444240c004442044444240e424242042424240c0000000 -- 016:0000000044444420444442400004442044444240e42424204242424000000000
-- 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:22222220c10012203033022030130220303302203013022030330220c0000000 -- 032:2222222001001220303302203013022030330220301302203033022000000000
-- 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:111111111111111111111111c000100022220444e222044422220444e2220444 -- 048:1111111111111111111111110000100022220444e222044422220444e2220444
-- 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:09191990c991990209199020c999020209902020c902020200202020c0000000 -- 080:0919199009919902091990200999020209902020090202020020202000000000
-- 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:00000000c111111100000000c106666601051555c105155501056555c0066611 -- 096:0000000001111111000000000106666601051555010515550105655500066611
-- 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:11111111111111111111111111111111111111111111111111110111c0004000 -- 112:1111111111111111111111111111111111111111111111111111011100004000
-- 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:00000000c111111001101010c131311001101010c101311001111110c0000000 -- 176:0000000001111110011010100131311001101010010131100111111000000000
-- 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:00000010c000001000000010c000001000000010c000001011111110c0000000 -- 224:0000001000000010000000100000001000000010000000101111111000000000
-- 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:02220111c222001102220000c222033302220333c222200002222222c2222222 -- 240:0222011102220011022200000222033302220333022220000222222202222222
-- 241:1002222001202220002022203002222031222220022222202222222022222220 -- 241:1002222001202220002022203002222031222220022222202222222022222220
-- 242:3333333333333330333333033333113313130013313100311313131331313131 -- 242:3333333333333330333333033333113313130013313100311313131331313131
-- 243:0333333300333333030333330331133303100313113001310013131300313131 -- 243:0333333300333333030333330331133303100313113001310013131300313131
@@ -251,130 +251,262 @@
-- 247:0000000011111110000000003333301013131010313130101313101031313000 -- 247:0000000011111110000000003333301013131010313130101313101031313000
-- </TILES> -- </TILES>
-- <SPRITES> -- <SPRITES>
-- 002:00000000000000000000444400044444000444440044ffff004fffff004f3333 -- 000:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 003:0000000000000000441600004242600044241000ff426000fff4100033f26000 -- 001:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 004:00000333000035550003655500365555003555ff00356fff00365f3f00355fff -- 002:cccccccccccc0000ccc04444cc044444cc044444c044ffffc04fffffc04f3333
-- 005:33000000553000005563000055563000ff553000fff53000f3f63000fff53000 -- 003:cccccccc0000cccc44160ccc424260cc442410ccff4260ccfff410cc00f260cc
-- 008:0000005a00005a55000055a50000a55a00005a5700005533000575f30000757f -- 004:ccccc000cccc0555ccc06555cc065555cc0555ffcc056fffcc065f0fcc055fff
-- 009:55a50000a55a50005a55a00057555500fff7a5003f335a00fff3f500fffffa00 -- 005:00cccccc550ccccc5560cccc55560cccff550cccfff50cccf0f60cccfff50ccc
-- 016:0000000000000000000000000000003000000353000035350003535100353535 -- 006:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 017:0000000000000000000000003000000053300000151300005151300015151300 -- 007:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 018:004f99ff000fffff0000ff3300000fff00003666000355550035652503163555 -- 008:cccc0000ccc05a55ccc055a5ccc0a55accc05a57ccc05533cc0575f3ccc0757f
-- 019:99f41000fff26000ff600000f600000063300000555330005555530055535530 -- 009:00000ccca55a50cc5a55a0cc5755550cfff7a50c3f335a0cfff3f50cfffffa0c
-- 020:00356f6f003655f60365511f3653122f3531222f363221220532232203322322 -- 010:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 021:f6f530006f563000f1156300f2215300f2226300221233002232130022121300 -- 011:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 022:000000000000005100000155000055150000157f0000551300057f3f00017fff -- 012:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 023:00000000555000005155000015515000ff7f5100ff31f200fff3ff0033fff200 -- 013:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 024:0000057f00000005000000050000559900055911005599110055119900551199 -- 014:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 025:f3ff5000fff500005f5000004415100077995100449915007711955044119550 -- 015:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 026:00000000000001330001331300031333001333330031f7f7001133390031999f -- 016:cccccccccccccccccccccccccccccc0cccccc050cccc0535ccc05351cc053535
-- 027:0000000013310000131330003333130033333100f7f113003337310099975300 -- 017:cccccccccccccccccccccccc0ccccccc500ccccc1510cccc51510ccc151510cc
-- 028:000000000000000000000a77000057770005777700577777005775a50077a7ff -- 018:c04f99ffcc0fffffccc0ff00cccc0fffcccc0666ccc05555cc056525c0160555
-- 029:0000000000000000777a0000777750007777750077777750a5a57750fff7a770 -- 019:99f410ccfff260ccff600cccf60ccccc600ccccc55500ccc555550cc5550550c
-- 030:000000000000051500001151000555550001517f000557ff0001ff3f0007ff1f -- 020:cc056f6fcc0655f6c065511f0650122f0501222f06022122c5022322c0022322
-- 031:00000000150000005110000055500000f7110000ff750000f3f10000f1f50000 -- 021:f6f50ccc6f560cccf11560ccf22150ccf22260cc221230cc223210cc221210cc
-- 032:0033535100353533003351ff00351f3f0003ff3f0003ffff00003ff3000323ff -- 022:cccccc00ccccc051cccc0155ccc05515ccc0157fccc05513cc057f0fcc017fff
-- 033:5555530033555300ff155300f3f15300f3ff3000ffff30003ff30000ff323000 -- 023:000ccccc5550cccc51550ccc155150ccff7f510cff31f20cfff0ff0c00fff20c
-- 034:036135250316355503613525031633110333331103f333330333333300033333 -- 024:cccc057fccccc005cccc0555ccc05599cc055911c0559911c0551199c0551199
-- 035:55565530555355305556553013335530133333303333ff303333333033330000 -- 025:f3ff50ccfff50ccc5f50cccc441500cc7799510c4499150c7711955044119550
-- 036:00322322003223330033331a003ff31a003ff3a1003333a100003a1a00003a1a -- 026:ccccc000ccc00133cc013313cc031333c0133333c031f7f7c0113339c031999f
-- 037:223213003332130011133300111f300011133000111300001113000011130000 -- 027:0000cccc13310ccc131330cc3333130c3333310cf7f1130c3337310c9997530c
-- 038:000007ff0001117f0016171f0155175501561755155117555f7157555ff15755 -- 028:ccccccccccccc000cccc0a77ccc05777cc057777c0577777c05775a5c077a7ff
-- 039:fffff700333f2000ffff7100555571105555716155557111555575ff555575ff -- 029:cccccccc0000cccc777a0ccc777750cc7777750c77777750a5a57750fff7a770
-- 040:005599110055991100ff533300fff511007fff110007f5110000311300003113 -- 030:ccccc000cccc0515ccc01151cc055555cc01517fcc0557ffcc01ff0fcc07ff1f
-- 041:479915504499155047333f7014113ff011113f70111130003311300003113000 -- 031:00cccccc150ccccc5110cccc5550ccccf7110cccff750cccf0f10cccf1f50ccc
-- 042:0035777f0001776600005777000000550088885508bbb84508bbb8448bb8b844 -- 032:cc035351cc053500cc0351ffcc051f0fccc0ff0fccc0ffffcccc0ff0ccc020ff
-- 043:77775300677500007750000055880000558b8000548bb800228bbb80428b8b80 -- 033:555550cc005550ccff1550ccf0f150ccf0ff0cccffff0ccc0ff0ccccff020ccc
-- 044:005a7f3f0057ff3f07f7ffff07757fdf077a57fd0575357f005a66a70006aa6f -- 034:c0613525c0163555c0613525c0163311c0003311c0f03333cc003333ccc03333
-- 045:ff3f7a50ff3ff750fffff777ffdf7577ddf75a77ff75157577a66a50ff6aa600 -- 035:5556550c5553550c5556550c1330550c1330000c3330ff0c333000cc3330cccc
-- 046:0005ffff00005ff3000005ff0017775500242777002121710024277100212171 -- 036:cc022322cc022333cc03331acc0ff31acc0ff3a1ccc003a1cccc0a1acccc0a1a
-- 047:fff500003f500000f50000005771000077720000171200001772000017120000 -- 037:223210cc333210cc111300cc111f0ccc11100ccc1110cccc1110cccc1110cccc
-- 048:00323123003231430032314300313339000f3333000033300000333000033330 -- 038:ccc007ffcc01117fc016171f0155175501561755055117550f7157550ff15755
-- 049:324303003443030034430300933313003333f000033300000333000003333000 -- 039:fffff70c000f20ccffff710c555571105555716055557110555575f0555575f0
-- 050:0003333000033330000333300003333000053530003311300031113000333330 -- 040:c0559911c0559911c0ff5333c0fff511c07fff11cc07f511ccc03110cccc0110
-- 051:3333000033330000333300003333000035350000311330003111300033333000 -- 041:479915504499155047333f7014113ff011113f701111000c00110cccc0110ccc
-- 052:000031a1000031a100003a1a00003a1a00003333000003f3000003f300000330 -- 042:c035777fcc017766ccc05777cc088855c08bb85508bbb84508bbb8440bb8b844
-- 053:111300001113000011130000111300003333000003f3000003f3000003300000 -- 043:7777530c677500cc7750cccc55880ccc558b80cc548bb80c228bbb80428b8b80
-- 054:5ff7646607f59999000991330003993000099130000133300001221000011100 -- 044:cc0a7f3fc075ff3f0777ffff07757fdf077a57fd0575357fc05a66a7cc06aa6f
-- 055:666646ff999993f7339913000039930000991300001333000012210000111000 -- 045:ff3f7a0cff3ff70cfffff770ffdf7570ddf75a70ff75157077a66a50ff6aa60c
-- 056:0000311300003113000031130000311300003113000033330000165100001111 -- 046:cc05ffffccc05ff3cccc05ffcc007755c0242777c0212171c0242771c0212171
-- 057:0311300003113000031130000311300003113000033330000165100001111000 -- 047:fff50ccc3f50ccccf50ccccc5770cccc77720ccc17120ccc17720ccc17120ccc
-- 058:8888b8445f78b8445f58884405031330000331300003133000053550000577f0 -- 048:cc020123cc020143cc020143cc010309cc0f0300ccc0030ccccc030cccc0000c
-- 059:218b8880428b87f5218885f5031330500331300003133000053550000577f000 -- 049:324030cc344030cc344030cc903010cc0030f0ccc0300cccc030ccccc0000ccc
-- 060:0056aa66001f6aaa001fa666007f6aaa00006aaa0000a666000007d7000001d1 -- 050:ccc0330cccc0330cccc0330cccc0330cccc0350ccc03110ccc01110ccc00000c
-- 061:666aa650aaaa6f106666af10aaaa6f70aaaa60006666a000007d7000001d1000 -- 051:0330cccc0330cccc0330cccc0330cccc0530cccc01130ccc01110ccc00000ccc
-- 062:0024277700ff611100fff333005f533300003333000033300000333000001110 -- 052:cccc01a1cccc01a1cccc0a1acccc0a1acccc0000ccccc0f0ccccc0f0ccccc00c
-- 063:77720000116f0000335ff000333f000033300000333000003330000001110000 -- 053:1110cccc1110cccc1110cccc1110cccc0000ccccc0f0ccccc0f0ccccc00ccccc
-- 064:00000000000000000000011100003311000111170003317f000117ff00553333 -- 054:0ff7646607f59999c0099100cc03990ccc09910ccc01330ccc01220ccc0000cc
-- 065:0000000000000000110000001110000077110000ff710000ff77000013330000 -- 055:666646f0999993f00099100cc03990ccc09910ccc01330ccc01220ccc0000ccc
-- 066:00000000000000330000033300003333000033f7000035ff000535ff0007f333 -- 056:cccc0110cccc0110cccc0110cccc0110cccc0110cccc0330cccc0650cccc0000
-- 067:0000000030000000333300003333000037f30000ffff0000ffff0000f333f000 -- 057:c0110cccc0110cccc0110cccc0110cccc0110cccc0330cccc0650cccc0000ccc
-- 068:000000000000000000000000000000000000000000000122000012440001447f -- 058:0888b8440f78b8440f58884405031300c0c0310cccc0130cccc0350cccc0000c
-- 069:00000000000000000000000000000000000000002210000044210000f7441000 -- 059:218b8880428b87f0218885f000130050c0310c0cc0130cccc0350cccc0000ccc
-- 070:000000000000000000000333000038880003888800388881038388310338835f -- 060:c056aa66c01f6aaac01fa666c07f6aaacc0f6aaaccc0a666cccc07d7cccc0000
-- 071:00000000000000003330000088880000883380003355380016665300f7ff7300 -- 061:666aa650aaaa6f106666af10aaaa6f70aaaa600c6666a0cc007d70cccc0000cc
-- 072:0000000000000000000000550000055500005577000057ff00007f55000fff33 -- 062:c0242777c0ff6111c0fff333c05f5333cc003300cccc030ccccc030ccccc000c
-- 073:0000000000000000555550005555550077777550ffffff507f755f703f333fff -- 063:77720ccc116f0ccc335ff0cc333f0ccc0330cccc030ccccc030ccccc0000cccc
-- 074:0000000000000011000001130000113100011313000131310013137c003131ff -- 064:ccccccccccccc000cccc0111ccc03311cc011117cc03317fcc0117ffc0553333
-- 075:000000001110000013110000313110001313100031313100ffff7100fffff100 -- 065:cccccccc00cccccc110ccccc1110cccc77110cccff710cccff770ccc13330ccc
-- 076:0000000000000055000005550000055500005577000057ff0007ff55000fff99 -- 066:cccccc00ccccc033cccc0333ccc03333ccc033f7ccc035ffcc0535ffcc07f333
-- 077:0000000055550000555550005555500075775500fffff5005f555f703f993ff0 -- 067:0ccccccc3000cccc33330ccc33330ccc37f30cccffff0cccffff0cccf333f0cc
-- 078:0000000000000000000000000000000000001111000014440000144400001555 -- 068:ccccccccccccccccccccccccccccccccccccc000cccc0122ccc01244cc01447f
-- 079:0000000000000000000000000000000011100000441000004410000055100000 -- 069:cccccccccccccccccccccccccccccccc000ccccc2210cccc44210cccf74410cc
-- 080:0077533f000ff77f0005fff500005ff70000015f0005f315005ff3ff00ff3333 -- 070:ccccccccccccccccccccc000cccc0888ccc08888cc088880c0838801c038805f
-- 081:f33f0000f77f00005ff000007f500000f500000053f00000f3f50000333f0000 -- 071:cccccccccccccccc0000cccc88880ccc880080cc0055080c1666530cf7ff730c
-- 082:000fff330005ffff000057f50000007f000333350031313f0031313303113133 -- 072:cccccccccccccc00ccccc055cccc0555ccc05577ccc057ffccc07f55cc0fff33
-- 083:ff33f000ffff100055f10000ff70000055330000ff3130003331300033311300 -- 073:cccccccc00000ccc555550cc5555550c77777550ffffff507f755f703f333ff0
-- 084:000447ff000fffff0007f33f000ff11f000f7fff0000ff750000042400001142 -- 074:cccccccccccccc00ccccc013cccc0131ccc01313ccc03131cc031377cc0131ff
-- 085:ff744000ffff1000f33f7000f11f5000fff7f00057ff00004240000044110000 -- 075:cccccccc000ccccc1310cccc31310ccc13130ccc313130ccffff70ccfffff0cc
-- 086:038383390338833b038383130338337f0383835f003838350003838300003333 -- 076:cccccccccccccc00ccccc055cccc0555ccc05577ccc057ffcc07ff55cc0fff99
-- 087:99539900bb33bb0099513900fffff530ff66f1007fff53001555310033333000 -- 077:cccccccc0000cccc55550ccc555550cc7577550cfffff50c5f555f0c3f993f0c
-- 088:000f7ff300005fff000007ff0000007f0000021f000024410002444400124244 -- 078:cccccccccccccccccccccccccccccccccccc0000cccc0444cccc0444cccc0555
-- 089:fff3ff7ff1ffff50fffff700111f7000ffff1000111142004244442042442410 -- 079:cccccccccccccccccccccccccccccccc000ccccc440ccccc440ccccc550ccccc
-- 090:005f5733005f1f2300015fff0000077f00011117001244210144414201421444 -- 080:c077500fcc0ff77fcc05fff5ccc05ff7cccc015fccc0f315cc0ff3ffc0ff3333
-- 091:ff33f500ff23f500fffff00011ff500077710000112410004442410042441410 -- 081:f00f0cccf77f0ccc5ff0cccc7f50ccccf50ccccc53f0ccccf3f50ccc333f0ccc
-- 092:00005fff000005ff0000001f0000000100000114000018140000181400018114 -- 082:cc0fff00cc05ffffccc057f5cccc007fccc03335cc01313fc031313303113133
-- 093:fffff500111f5000fff500001110000042411000424180004241810042411100 -- 083:ff00f0ccffff10cc55f10cccff70cccc5530ccccff310ccc33310ccc333110cc
-- 094:00001fff00001f3f0000cf3f0000cfff00000cf3000023cc000131ff001f1f11 -- 084:cc0447ffcc0fffffcc07f33fcc0ff11fcc0f7fffccc0ff75cccc0424cccc0142
-- 095:ff1000003f1000003ff00000fff00000fc000000c3200000f13100001f1f1000 -- 085:ff7440ccffff10ccf33f70ccf11f50ccfff7f0cc57ff0ccc4240cccc44110ccc
-- 096:00ff33330033133305f333330ff31333033333330f5313330ff1311107f13333 -- 086:c0838039c038803bc0838013c038307fc083805fcc083805ccc08383cccc0333
-- 097:333f0000333f5000333f5000333ff000333330003335f500111ff5003337f000 -- 087:9953990cbb33bb0c9951390cfffff50cff66f10c7fff50cc15550ccc33330ccc
-- 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:333113003331130033333300213113004233330021317f0033317f5001317500 -- 099:333110cc333110cc333330cc213110cc423330cc21317f0c33317f501131750c
-- 100:0002441400244441024444240242442414424424144144241441442414414424 -- 100:ccc04414cc044441c0444424c042442404424424044144240441442404414424
-- 101:4144210014444200424444204244422042444241424441414244414142444141 -- 101:414420cc1444420c424444204244422042444240424441404244414042444140
-- 102:000333330033a3530032a353003a332303a23333032a333303a23333032a3333 -- 102:ccc03333cc03a353cc02a353cc0a3323c0a23333c02a3333c0a23333c02a3333
-- 103:3333300055353300553533002232323033333130333332303333313333333233 -- 103:33330ccc553530cc553530cc2232320c3333310c3333320c3333313033333230
-- 104:001441440014424400144144001441240017f311001ff133001fff330007f333 -- 104:c0144144c0144244c0144144c0144124c017f311c01ff133c01fff33cc07f330
-- 105:4244142042442410424414204244122012113f7031333ff033333ff030333f00 -- 105:4244142042442410424414204244122012113f7031333ff033333ff000033f0c
-- 106:01421444014414440142144431421444011111110fff1a5a0ff755a505755a51 -- 106:c0421444c0441444c0421444c0421444c0111111c0ff1a5ac0f755a5c0755a50
-- 107:44441410424414104444141042441410111111105a5a55f5a5a5a5f5111a5170 -- 107:4444140c4244140c4444140c4244140c1111110c5a5a55f0a5a5a5f0001a5170
-- 108:0001181400018114000118140001811300011333005fff33000f773300055333 -- 108:ccc01814ccc08114ccc01814ccc08113cc001333c05fff33cc0f7733cc055330
-- 109:424181104241181042418110222318101113310033335ff03333f77033335500 -- 109:4241810c4241180c4241810c2223180c1113310c33335ff03333f7700033550c
-- 112:0553333300033330000333000033330000333300003333000011110000121200 -- 110:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 113:3330000033300000333000003330000033300000333000001111000012120000 -- 111:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 114:05f5313103003131033311310311113103111131003111300003333000012120 -- 112:05533333c0033330ccc0330ccc03330cc03330ccc03330ccc01110ccc0000ccc
-- 115:0131130001311300013113000131130001311300003113000033330000121200 -- 113:33000ccc030ccccc030ccccc030ccccc030ccccc030ccccc0110cccc0000cccc
-- 116:0fff242407f72211005544200002442000024420000244200002222000024440 -- 114:05f53131c0003131c0331131c0111131c0111130cc01110cccc0330cccc0000c
-- 117:424441f1112227f1024425500244200002442000024420000222200002444000 -- 115:113110cc113110cc113110cc113110cc003110cccc0110cccc0330cccc0000cc
-- 118:0333333307ff333307f733330070333000003330000033300000111000001110 -- 116:0fff242407f72211c0552400cc00240cccc0240cccc0240cccc0220cccc0000c
-- 119:33333575333331f1333335750033300000333000003330000011100000111100 -- 117:424441f0112227f000442550c044200cc04420ccc04420ccc02220ccc00000cc
-- 120:0000033300000333000003330000033300000333000003330000033300000111 -- 118:0333333307ff333307f73300c070030ccc0c030ccccc030ccccc010ccccc000c
-- 121:0033300000333000003330000033300000333000003330000033300010111100 -- 119:33333570333331f000033570cc03300ccc030ccccc030ccccc010ccccc0000cc
-- 122:005015a100001a51000015a100001a51000015a1000022510000924900009999 -- 120:ccc00330ccccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc000
-- 123:0315a150001a51000015a100001a51000015a100002251000092490000999900 -- 121:cc0300cccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccc0c0000cc
-- 124:0000033300000333000003330000033300000333000003330000033300000111 -- 122:c05015a0cc0c0a50cccc05a0cccc0a50cccc05a0cccc0250cccc0990cccc0000
-- 125:0333000003330000033300000333000003330000033300000333000000111000 -- 123:c015a150cc0a500ccc05a0cccc0a50cccc05a0cccc0250cccc0990cccc0000cc
-- 129:0000000000000000000000000000000000000000011515101151515151515151 -- 124:ccc00330ccccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc000
-- 144:0000000500000015000000150000057f000005ff0000017f0000331700073331 -- 125:c03000ccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc0000ccc
-- 145:1ffffff7ff0fff0fff1fff1fffffffffff7555fffffffffffff111ff57fffff7 -- 126:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 146:1000000071000000f5000000ff000000ff500000ff5000007513100051333700 -- 127:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 160:0077333303331333333313333331333333313333355133335ff513335ff71111 -- 128:ccccccccccccccccccccccccccccccccccccccccccccccccccccccc0ccccccc0
-- 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:133337003733133077731330333331333333313333333155333337ff1111175f -- 162:1333370c3733130c7773130c333331303333313033333150333337f011111750
-- 176:0775333300031333000333130000333300001333000033330000033300000111 -- 163:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 177:3335773333333533333333331313131333333333300000033000000310000001 -- 164:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 178:3333357533331000331300001333000033310000333300003331000011110000 -- 165:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-- 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:ffffffffff0010201020102010201020102010201020102000ffffffffff40404040404087f3f3f3f397a7b7c7d7a7e7f70818a7b7c7d7a7b7c7d7a70b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 000:ffffffffff0010201020102010201020102010201020102000ffffffffff40404040404087f3f3f3f397a7b7c7d7a7e7f70818a7b7c7d7a7b7c7d7a70b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
@@ -387,7 +519,7 @@
-- 007:ffffffffffb264748494a4b4c4d46494649464940040e4f4b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 007:ffffffffffb264748494a4b4c4d46494649464940040e4f4b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 008:ffffffffffe1c30515d325d33545c3d355d3c3d365b17585e1ffffffffff4040404040404098989898404040404040404040404040404040404040407c1e7e8e1e1e1e9eae1ebe1e1e1e1e1e1e1e1e72821ebe1e72821ebe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 008:ffffffffffe1c30515d325d33545c3d355d3c3d365b17585e1ffffffffff4040404040404098989898404040404040404040404040404040404040407c1e7e8e1e1e1e9eae1ebe1e1e1e1e1e1e1e1e72821ebe1e72821ebe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 009:ffffffffffb264e395a5b594e39564c5d5946494e5b1b1f5b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e05151ebe1ecedeeefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 009:ffffffffffb264e395a5b594e39564c5d5946494e5b1b1f5b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e05151ebe1ecedeeefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 010:ffffffffffe1c306162636d34656c395d5d3c3d376b1b1b1e1ffffffffff404040404040409898989840b9c9c9d9e9f90a0a0a0a4040400a0a0a0a407c1ee395eefe1e0f1f2f3f1e1e1e1e1e1e1e1ee3952f3f1ee3952f3f1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 010:ffffffffffe1c306162636d34656c3e3d5d3c3d376b1b1b1e1ffffffffff404040404040409898989840b9c9c9d9e9f90a0a0a0a4040400a0a0a0a407c1ee395eefe1e0f1f2f3f1e1e1e1e1e1e1e1ee3952f3f1ee3952f3f1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 011:ffffffffffb264946494649464948696a694649410201020b2ffffffffff4040404040404040404040401a2a3a4a5a6a7a40404040404040404040405d1ee3952f3f1e4f5f1ebe1e1e1e1e1e1e1e1ee3951ebe1ee3951ebe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 011:ffffffffffb264946494649464948696a694649410201020b2ffffffffff4040404040404040404040401a2a3a4a5a6a7a40404040404040404040405d1ee3952f3f1e4f5f1ebe1e1e1e1e1e1e1e1ee3951ebe1ee3951ebe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 012:ffffffffffe1c37282d3c3d3c3d3b6c6d6d3c3d300e6f607e1ffffffffff4040404040404098989898408a9aaabaca9ada40404040404040404040407c1e4f5f1ebe1e0515eefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 012:ffffffffffe1c37282d3c3d3c3d3b6c6d6d3c3d300e6f607e1ffffffffff4040404040404098989898408a9aaabaca9ada40404040404040404040407c1e4f5f1ebe1e0515eefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 013:ffffffffffb264e395946494649464946494649465172737b2ffffffffffeaeaeaeaeaeaeafafafafaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaea5d1e0515eefe1e6f7f2f3f1e1e1e1e1e1e1e1e6f7f2f3f1e6f7f2f3f1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 013:ffffffffffb264e395946494649464946494649465172737b2ffffffffffeaeaeaeaeaeaeafafafafaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaea5d1e0515eefe1e6f7f2f3f1e1e1e1e1e1e1e1e6f7f2f3f1e6f7f2f3f1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

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-beta2 -- version: 1.0-beta1
-- script: lua -- script: lua

View File

@@ -8,6 +8,7 @@ local _screens = {}
--- @param screen_data.name string Display name of the screen. --- @param screen_data.name string Display name of the screen.
--- @param screen_data.decisions table Array of decision ID strings available on this screen. --- @param screen_data.decisions table Array of decision ID strings available on this screen.
--- @param screen_data.background string Map ID used as background. --- @param screen_data.background string Map ID used as background.
--- @param[opt] screen_data.situations table Array of situation ID strings. Defaults to {}.
--- @param[opt] screen_data.init function Called when the screen is entered. Defaults to noop. --- @param[opt] screen_data.init function Called when the screen is entered. Defaults to noop.
--- @param[opt] screen_data.update function Called each frame while screen is active. Defaults to noop. --- @param[opt] screen_data.update function Called each frame while screen is active. Defaults to noop.
--- @param[opt] screen_data.draw function Called after the focus overlay to draw screen-specific overlays. Defaults to noop. --- @param[opt] screen_data.draw function Called after the focus overlay to draw screen-specific overlays. Defaults to noop.
@@ -15,6 +16,9 @@ function Screen.register(screen_data)
if _screens[screen_data.id] then if _screens[screen_data.id] then
trace("Warning: Overwriting screen with id: " .. screen_data.id) trace("Warning: Overwriting screen with id: " .. screen_data.id)
end end
if not screen_data.situations then
screen_data.situations = {}
end
if not screen_data.init then if not screen_data.init then
screen_data.init = function() end screen_data.init = function() end
end end
@@ -39,6 +43,7 @@ end
--- * name (string) Display name.<br/> --- * name (string) Display name.<br/>
--- * decisions (table) Array of decision ID strings.<br/> --- * decisions (table) Array of decision ID strings.<br/>
--- * background (string) Map ID used as background.<br/> --- * background (string) Map ID used as background.<br/>
--- * situations (table) Array of situation ID strings.<br/>
--- * init (function) Called when the screen is entered.<br/> --- * init (function) Called when the screen is entered.<br/>
--- * update (function) Called each frame while screen is active. --- * update (function) Called each frame while screen is active.
function Screen.get_by_id(screen_id) function Screen.get_by_id(screen_id)
@@ -53,6 +58,7 @@ end
--- * name (string) Display name of the screen.<br/> --- * name (string) Display name of the screen.<br/>
--- * decisions (table) Array of decision ID strings available on this screen.<br/> --- * decisions (table) Array of decision ID strings available on this screen.<br/>
--- * background (string) Map ID used as background.<br/> --- * background (string) Map ID used as background.<br/>
--- * situations (table) Array of situation ID strings.<br/>
--- * init (function) Called when the screen is entered.<br/> --- * init (function) Called when the screen is entered.<br/>
--- * update (function) Called each frame while screen is active.<br/> --- * update (function) Called each frame while screen is active.<br/>
function Screen.get_all() function Screen.get_all()

View File

@@ -240,12 +240,9 @@ Screen.register({
end end
end end
elseif state == STATE_CHOICE then elseif state == STATE_CHOICE then
local menu_x = (Config.screen.width - 60) / 2 selected_choice = UI.update_menu(MysteriousManScreen.choices, selected_choice)
local menu_y = (Config.screen.height - 20) / 2
local confirmed
selected_choice, confirmed = UI.update_menu(MysteriousManScreen.choices, selected_choice, menu_x, menu_y)
if Input.select() or confirmed then if Input.select() then
Audio.sfx_select() Audio.sfx_select()
if selected_choice == 1 then if selected_choice == 1 then
MysteriousManScreen.wake_up() MysteriousManScreen.wake_up()

View File

@@ -6,45 +6,26 @@ Screen.register({
"go_to_walking_to_home", "go_to_walking_to_home",
"have_a_coffee", "have_a_coffee",
}, },
situations = {
"drink_coffee",
},
init = function() init = function()
Audio.music_play_room_work() Audio.music_play_room_work()
Context.have_been_to_office = true
local possible_sprites = {
"dev_project_manager",
"dev_hr_girl",
"dev_introvert",
"dev_extrovert",
"dev_guru",
"dev_operator",
{id="dev_buddy", y_correct=1 * 8},
{id="dev_boy", y_correct=1 * 8},
{id="dev_girl", y_correct=1 * 8}
}
local possible_positions = {
{x = 6 * 8, y = 4 * 8},
{x = 10 * 8, y = 11 * 8 + 4},
{x = 12 * 8, y = 4 * 8},
{x = 15 * 8, y = 9 * 8},
{x = 16 * 8, y = 4 * 8},
{x = 17 * 8, y = 8 * 8},
{x = 17 * 8, y = 11 * 8},
{x = 20 * 8, y = 4 * 8},
{x = 23 * 8, y = 5 * 8},
{x = 22 * 8, y = 10 * 8 + 4},
{x = 27 * 8, y = 10 * 8 + 4},
{x = -4 + 5 * 8, y = 9 * 8}
}
Context.office_sprites = Sprite.list_randomize(possible_sprites, possible_positions)
end, end,
background = "office", background = "office",
draw = function() draw = function()
if Window.get_current_id() == "game" then if Window.get_current_id() == "game" then
Sprite.draw_at("norman", 13 * 8, 9 * 8) Sprite.draw_at("norman", 13 * 8, 9 * 8)
Sprite.draw_at("dev_buddy", 15 * 8, 9 * 8)
Sprite.draw_list(Context.office_sprites) Sprite.draw_at("dev_project_manager", 6 * 8, 4 * 8)
Sprite.draw_at("dev_hr_girl", 12 * 8, 4 * 8)
Sprite.draw_at("dev_introvert", -4 + 5 * 8, 9 * 8)
Sprite.draw_at("dev_extrovert", 20 * 8, 4 * 8)
Sprite.draw_at("dev_girl", 23 * 8, 5 * 8)
Sprite.draw_at("dev_boy", 10 * 8, 11 * 8 + 4)
Sprite.draw_at("dev_guru", 22 * 8, 10 * 8 + 4)
Sprite.draw_at("dev_operator", 27 * 8, 10 * 8 + 4)
end end
Context.have_been_to_office = true
end end
}) })

View File

@@ -16,7 +16,7 @@ Screen.register({
end, end,
update = function() update = function()
if not Context.stat_screen_active then return end if not Context.stat_screen_active then return end
if Input.select() or Input.select() then if Input.select() or Input.player_interact() then
Focus.stop() Focus.stop()
Context.stat_screen_active = false Context.stat_screen_active = false
Meter.show() Meter.show()

View File

@@ -8,28 +8,6 @@ Screen.register({
}, },
init = function() init = function()
Audio.music_play_room_work() Audio.music_play_room_work()
local possible_sprites = {
"matrix_trinity",
"matrix_neo",
{id="matrix_oraculum", y_correct=1 * 8},
"matrix_architect"
}
local possible_positions = {
{x = 5 * 8, y = 11 * 8},
{x = 7 * 8, y = 11 * 8},
{x = 9 * 8, y = 11 * 8},
{x = 11 * 8, y = 11 * 8},
{x = 13 * 8, y = 11 * 8},
{x = 15 * 8, y = 11 * 8},
{x = 18 * 8, y = 11 * 8},
{x = 21 * 8, y = 11 * 8},
{x = 24 * 8, y = 11 * 8},
{x = 27 * 8, y = 11 * 8},
}
Context.walking_to_office_sprites = Sprite.list_randomize(possible_sprites, possible_positions)
end, end,
background = "street", background = "street",
draw = function() draw = function()
@@ -38,8 +16,10 @@ Screen.register({
Sprite.draw_at("sumphore", 9 * 8, 2 * 8) Sprite.draw_at("sumphore", 9 * 8, 2 * 8)
Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8) Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8)
Sprite.draw_at("dev_guard", 22 * 8, 2 * 8) Sprite.draw_at("dev_guard", 22 * 8, 2 * 8)
Sprite.draw_at("matrix_trinity", 5 * 8, 11 * 8)
Sprite.draw_list(Context.walking_to_office_sprites) Sprite.draw_at("matrix_neo", 7 * 8, 11 * 8)
Sprite.draw_at("matrix_oraculum", 9 * 8, 12 * 8)
Sprite.draw_at("matrix_architect", 11 * 8, 11 * 8)
end end
end end
}) })

View File

@@ -0,0 +1,6 @@
Situation.register({
id = "drink_coffee",
handle = function()
Audio.sfx_select()
end,
})

View File

@@ -0,0 +1,84 @@
--- @section Situation
local _situations = {}
--- Registers a situation definition.
--- @within Situation
--- @param situation table The situation data table.
--- @param situation.id string Unique situation identifier.<br/>
--- @param[opt] situation.screen_id string ID of the screen this situation belongs to.<br/>
--- @param[opt] situation.handle function Called when the situation is applied. Defaults to noop.<br/>
--- @param[opt] situation.update function Called each frame while situation is active. Defaults to noop.<br/>
function Situation.register(situation)
if not situation or not situation.id then
PopupWindow.show({"Error: Invalid situation object registered (missing id)!"})
return
end
if not situation.handle then
situation.handle = function() end
end
if not situation.update then
situation.update = function() end
end
if _situations[situation.id] then
trace("Warning: Overwriting situation with id: " .. situation.id)
end
_situations[situation.id] = situation
end
--- Gets a situation by ID.
--- @within Situation
--- @param id string The situation ID.
--- @return result table The situation table or nil. </br>
--- Fields: </br>
--- * id (string) Unique situation identifier.<br/>
--- * screen_id (string) ID of the screen this situation belongs to.<br/>
--- * handle (function) Called when the situation is applied.<br/>
--- * update (function) Called each frame while situation is active.<br/>
function Situation.get_by_id(id)
return _situations[id]
end
--- Gets all registered situations, optionally filtered by screen ID.
--- @within Situation
--- @param screen_id string Optional. If provided, returns situations associated with this screen ID.
--- @return result table A table containing all registered situation data, indexed by their IDs, or an array filtered by screen_id. </br>
--- Fields: </br>
--- * id (string) Unique situation identifier.<br/>
--- * screen_id (string) ID of the screen this situation belongs to.<br/>
--- * handle (function) Called when the situation is applied.<br/>
--- * update (function) Called each frame while situation is active.<br/>
function Situation.get_all(screen_id)
if screen_id then
local filtered_situations = {}
for _, situation in pairs(_situations) do
if situation.screen_id == screen_id then
table.insert(filtered_situations, situation)
end
end
return filtered_situations
end
return _situations
end
--- Applies a situation, checking screen compatibility and returning the new situation ID if successful.
--- @within Situation
--- @param id string The situation ID to apply.
--- @param current_screen_id string The ID of the currently active screen.
--- @return string|nil The ID of the applied situation if successful, otherwise nil.
function Situation.apply(id, current_screen_id)
local situation = Situation.get_by_id(id)
local screen = Screen.get_by_id(current_screen_id)
if not situation then
trace("Error: No situation found with id: " .. id)
return nil
end
if Util.contains(screen.situations, id) then
situation.handle()
return id
else
trace("Info: Situation " .. id .. " cannot be applied to current screen (id: " .. current_screen_id .. ").")
return nil
end
end

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 0 local colorkey = params.colorkey or sprite_data.colorkey or Config.colors.transparent
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
@@ -73,70 +73,6 @@ function Sprite.generate_table(width, height, starting_s, x_base, y_base, x_step
return sprites return sprites
end end
--- Immediately draws a list of sprites
--- @within Sprite
--- @param sprite_list table An array of tables, each containing: `id` (string) sprite identifier, `x` (number) x-coordinate, `y` (number) y-coordinate, and optional `colorkey`, `scale`, `flip_x`, `flip_y`, `rot` parameters.
function Sprite.draw_list(sprite_list)
for _, sprite_info in ipairs(sprite_list) do
local sprite_data = _sprites[sprite_info.id]
if not sprite_data then
trace("Error: Attempted to draw non-registered sprite with id: " .. sprite_info.id)
else
draw_sprite_instance(sprite_data, sprite_info)
end
end
end
--- Given a list of sprite IDs (or sprite entries with correction offsets) and a list of possible positions, randomly assigns each sprite to a unique position and returns a drawable list.
--- @within Sprite
--- @param sprite_ids table An array of sprite identifier values or tables.
--- Each entry may be either:
--- - string: sprite ID to draw.
--- - table: { sprite_id = string, x_correct = number, y_correct = number }.
--- @param positions table An array of tables, each containing `x` and `y` fields for possible sprite positions.
function Sprite.list_randomize(sprite_ids, positions)
if #sprite_ids > #positions then
trace("Error: More sprite IDs than available positions in Sprite.draw_randomized")
return
end
local shuffled_positions = {}
for i, pos in ipairs(positions) do
shuffled_positions[i] = pos
end
for i = #shuffled_positions, 2, -1 do
local j = math.random(i)
shuffled_positions[i], shuffled_positions[j] = shuffled_positions[j], shuffled_positions[i]
end
local drawable_list = {}
for i, sprite_entry in ipairs(sprite_ids) do
local sprite_id = sprite_entry
local x_correct = 0
local y_correct = 0
if type(sprite_entry) == "table" then
sprite_id = sprite_entry.sprite_id or sprite_entry.id
x_correct = sprite_entry.x_correct or 0
y_correct = sprite_entry.y_correct or 0
end
local sprite_data = _sprites[sprite_id]
if not sprite_data then
trace("Error: Attempted to draw non-registered sprite with id: " .. tostring(sprite_id))
else
local pos = shuffled_positions[i]
table.insert(drawable_list, {
id = sprite_id,
x = pos.x + x_correct,
y = pos.y + y_correct
})
end
end
return drawable_list
end
--- Schedules a sprite for drawing. --- Schedules a sprite for drawing.
--- @within Sprite --- @within Sprite
--- @param id string The unique identifier of the sprite.<br/> --- @param id string The unique identifier of the sprite.<br/>

View File

@@ -5,9 +5,10 @@ local INPUT_KEY_LEFT = 2
local INPUT_KEY_RIGHT = 3 local INPUT_KEY_RIGHT = 3
local INPUT_KEY_A = 4 local INPUT_KEY_A = 4
local INPUT_KEY_B = 5 local INPUT_KEY_B = 5
local INPUT_KEY_Y = 7
local INPUT_KEY_SPACE = 48 local INPUT_KEY_SPACE = 48
local INPUT_KEY_ENTER = 50
local INPUT_KEY_BACKSPACE = 51 local INPUT_KEY_BACKSPACE = 51
local INPUT_KEY_ENTER = 50
--- Checks if Up is pressed. --- Checks if Up is pressed.
--- @within Input --- @within Input
@@ -21,12 +22,22 @@ function Input.left() return btnp(INPUT_KEY_LEFT) end
--- Checks if Right is pressed. --- Checks if Right is pressed.
--- @within Input --- @within Input
function Input.right() return btnp(INPUT_KEY_RIGHT) end function Input.right() return btnp(INPUT_KEY_RIGHT) end
--- Checks if Space is pressed.
--- @within Input
function Input.space() return keyp(INPUT_KEY_SPACE) end
--- Checks if Select is pressed. --- Checks if Select is pressed.
--- @within Input --- @within Input
function Input.select() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_SPACE) or Mouse.clicked() end function Input.select() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_SPACE) end
--- Checks if Back is pressed. --- Checks if Menu Confirm is pressed.
--- @within Input --- @within Input
function Input.back() return btnp(INPUT_KEY_B) or keyp(INPUT_KEY_BACKSPACE) end function Input.menu_confirm() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_ENTER) end
--- Checks if Enter is pressed. --- Checks if Player Interact is pressed.
--- @within Input --- @within Input
function Input.enter() return keyp(INPUT_KEY_ENTER) end function Input.player_interact() return btnp(INPUT_KEY_B) or keyp(INPUT_KEY_ENTER) end
--- Checks if Menu Back is pressed.
--- @within Input
function Input.menu_back() return btnp(INPUT_KEY_Y) or keyp(INPUT_KEY_BACKSPACE) end
--- Checks if Toggle Popup is pressed.
--- @within Input
function Input.toggle_popup() return keyp(INPUT_KEY_ENTER) end

View File

@@ -17,7 +17,6 @@ end
--- @within Main --- @within Main
function TIC() function TIC()
init_game() init_game()
Mouse.update()
local now = time() local now = time()
if Context.last_frame_time == 0 then if Context.last_frame_time == 0 then

View File

@@ -1,81 +0,0 @@
--- @section Mouse
local _mx, _my = 0, 0
local _mleft, _mleft_prev = false, false
local _consumed = false
--- Updates mouse state. Call once per frame.
--- @within Mouse
function Mouse.update()
_mleft_prev = _mleft
_consumed = false
local mt = {mouse()}
_mx, _my, _mleft = mt[1], mt[2], mt[3]
-- trace mouse position and tile for testing purposes
if Context.test_mode and Context.mouse_trace then
trace("Mouse: (" .. _mx .. "," .. _my .. "), tile: (" .. math.floor(_mx / 8) .. "," .. math.floor(_my / 8) .. ")")
end
end
--- Returns current mouse X position.
--- @within Mouse
function Mouse.x() return _mx end
--- Returns current mouse Y position.
--- @within Mouse
function Mouse.y() return _my end
--- Returns true if the mouse button was just pressed this frame (and not yet consumed).
--- @within Mouse
function Mouse.clicked() return _mleft and not _mleft_prev and not _consumed end
--- Returns true if the mouse button is held down.
--- @within Mouse
function Mouse.held() return _mleft end
--- Marks the current click as consumed so Mouse.clicked() won't fire again this frame.
--- @within Mouse
function Mouse.consume() _consumed = true end
--- Returns true if the mouse is within the given rectangle.
--- @within Mouse
--- @param x number Left edge.
--- @param y number Top edge.
--- @param w number Width.
--- @param h number Height.
function Mouse.in_rect(x, y, w, h)
return _mx >= x and _mx < x + w and _my >= y and _my < y + h
end
--- Returns true if the mouse is within the given circle.
--- @within Mouse
--- @param cx number Center x.
--- @param cy number Center y.
--- @param r number Radius.
function Mouse.in_circle(cx, cy, r)
local dx = _mx - cx
local dy = _my - cy
return (dx * dx + dy * dy) <= (r * r)
end
--- Returns true if the mouse was clicked inside the given rectangle, and consumes the click.
--- @within Mouse
--- @param rect table A table with fields: x, y, w, h.
function Mouse.zone(rect)
if Mouse.clicked() and Mouse.in_rect(rect.x, rect.y, rect.w, rect.h) then
Mouse.consume()
return true
end
return false
end
--- Returns true if the mouse was clicked inside the given circle, and consumes the click.
--- @within Mouse
--- @param circle table A table with fields: x, y, r.
function Mouse.zone_circle(circle)
if Mouse.clicked() and Mouse.in_circle(circle.x, circle.y, circle.r) then
Mouse.consume()
return true
end
return false
end

View File

@@ -10,7 +10,7 @@ function Print.text(text, x, y, color, fixed, scale)
local shadow_color = Config.colors.black local shadow_color = Config.colors.black
if color == shadow_color then shadow_color = Config.colors.light_grey end if color == shadow_color then shadow_color = Config.colors.light_grey end
scale = scale or 1 scale = scale or 1
print(text, x + scale, y + scale, shadow_color, fixed, scale) print(text, x + 1, y + 1, shadow_color, fixed, scale)
print(text, x, y, color, fixed, scale) print(text, x, y, color, fixed, scale)
end end
@@ -24,7 +24,7 @@ end
--- @param[opt] scale number The scaling factor.<br/> --- @param[opt] scale number The scaling factor.<br/>
function Print.text_center(text, x, y, color, fixed, scale) function Print.text_center(text, x, y, color, fixed, scale)
scale = scale or 1 scale = scale or 1
local text_width = print(text, 0, -6 * scale, 0, fixed, scale) local text_width = print(text, 0, -6, 0, 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

View File

@@ -38,12 +38,8 @@ end
--- @within UI --- @within UI
--- @param items table A table of menu items.<br/> --- @param items table A table of menu items.<br/>
--- @param selected_item number The current index of the selected item.<br/> --- @param selected_item number The current index of the selected item.<br/>
--- @param[opt] x number Menu x position (required for mouse support).<br/>
--- @param[opt] y number Menu y position (required for mouse support).<br/>
--- @param[opt] centered boolean Whether the menu is centered horizontally.<br/>
--- @return number selected_item The updated index of the selected item. --- @return number selected_item The updated index of the selected item.
--- @return boolean mouse_confirmed True if the user clicked on a menu item. function UI.update_menu(items, selected_item)
function UI.update_menu(items, selected_item, x, y, centered)
if Input.up() then if Input.up() then
Audio.sfx_beep() Audio.sfx_beep()
selected_item = selected_item - 1 selected_item = selected_item - 1
@@ -57,25 +53,7 @@ function UI.update_menu(items, selected_item, x, y, centered)
selected_item = 1 selected_item = 1
end end
end end
return selected_item
if x ~= nil and y ~= nil then
local menu_x = x
if centered then
local max_w = 0
for _, item in ipairs(items) do
local w = print(item.label, 0, -10, 0, false, 1, false)
if w > max_w then max_w = w end
end
menu_x = (Config.screen.width - max_w) / 2
end
for i, _ in ipairs(items) do
if Mouse.zone({ x = menu_x - 8, y = y + (i-1) * 10, w = Config.screen.width, h = 10 }) then
return i, true
end
end
end
return selected_item, false
end end
--- Draws a bordered textbox with scrolling text. --- Draws a bordered textbox with scrolling text.

View File

@@ -107,9 +107,9 @@ function AudioTestWindow.update()
AudioTestWindow.menuitems = AudioTestWindow.generate_menuitems( AudioTestWindow.menuitems = AudioTestWindow.generate_menuitems(
AudioTestWindow.list_func, AudioTestWindow.index_func AudioTestWindow.list_func, AudioTestWindow.index_func
) )
elseif Input.select() then elseif Input.menu_confirm() then
AudioTestWindow.menuitems[AudioTestWindow.index_menu].decision() AudioTestWindow.menuitems[AudioTestWindow.index_menu].decision()
elseif Input.back() then elseif Input.menu_back() then
AudioTestWindow.back() AudioTestWindow.back()
end end
end end

View File

@@ -0,0 +1,102 @@
--- @section ConfigurationWindow
ConfigurationWindow.controls = {}
ConfigurationWindow.selected_control = 1
--- Initializes configuration window.
--- @within ConfigurationWindow
function ConfigurationWindow.init()
ConfigurationWindow.controls = {
{
label = "Save",
action = function() Config.save() end,
type = "action_item"
},
{
label = "Restore Defaults",
action = function() Config.reset() end,
type = "action_item"
},
}
end
--- Draws configuration window.
--- @within ConfigurationWindow
function ConfigurationWindow.draw()
UI.draw_top_bar("Configuration")
local x_start = 10
local y_start = 40
local x_value_right_align = Config.screen.width - 10
local char_width = 4
for i, control in ipairs(ConfigurationWindow.controls) do
local current_y = y_start + (i - 1) * 12
local color = Config.colors.light_blue
if control.type == "numeric_stepper" then
local value = control.get()
local label_text = control.label
local value_text = string.format(control.format, value)
local value_x = x_value_right_align - (#value_text * char_width)
if i == ConfigurationWindow.selected_control then
color = Config.colors.item
Print.text("<", x_start - 8, current_y, color)
Print.text(label_text, x_start, current_y, color)
Print.text(value_text, value_x, current_y, color)
Print.text(">", x_value_right_align + 4, current_y, color)
else
Print.text(label_text, x_start, current_y, color)
Print.text(value_text, value_x, current_y, color)
end
elseif control.type == "action_item" then
local label_text = control.label
if i == ConfigurationWindow.selected_control then
color = Config.colors.item
Print.text("<", x_start - 8, current_y, color)
Print.text(label_text, x_start, current_y, color)
Print.text(">", x_start + 8 + (#label_text * char_width) + 4, current_y, color)
else
Print.text(label_text, x_start, current_y, color)
end
end
end
Print.text("Press B to go back", x_start, 120, Config.colors.light_grey)
end
--- Updates configuration window logic.
--- @within ConfigurationWindow
function ConfigurationWindow.update()
if Input.menu_back() then
GameWindow.set_state("menu")
return
end
if Input.up() then
ConfigurationWindow.selected_control = ConfigurationWindow.selected_control - 1
if ConfigurationWindow.selected_control < 1 then
ConfigurationWindow.selected_control = #ConfigurationWindow.controls
end
elseif Input.down() then
ConfigurationWindow.selected_control = ConfigurationWindow.selected_control + 1
if ConfigurationWindow.selected_control > #ConfigurationWindow.controls then
ConfigurationWindow.selected_control = 1
end
end
local control = ConfigurationWindow.controls[ConfigurationWindow.selected_control]
if control then
if control.type == "numeric_stepper" then
local current_value = control.get()
if Input.left() then
local new_value = math.max(control.min, current_value - control.step)
control.set(new_value)
elseif Input.right() then
local new_value = math.min(control.max, current_value + control.step)
control.set(new_value)
end
elseif control.type == "action_item" then
if Input.menu_confirm() then
control.action()
end
end
end
end

View File

@@ -26,7 +26,7 @@ end
--- @within ContinuedWindow --- @within ContinuedWindow
function ContinuedWindow.update() function ContinuedWindow.update()
ContinuedWindow.timer = ContinuedWindow.timer - 1 ContinuedWindow.timer = ContinuedWindow.timer - 1
if ContinuedWindow.timer <= 0 or Input.select() or Input.select() then if ContinuedWindow.timer <= 0 or Input.select() or Input.menu_confirm() then
Window.set_current("menu") Window.set_current("menu")
MenuWindow.refresh_menu_items() MenuWindow.refresh_menu_items()
end end

View File

@@ -1,44 +0,0 @@
--- @section ControlsWindow
local _controls = {
{ action = "Navigate", keyboard = "Arrow keys", gamepad = "D-pad" },
{ action = "Select / OK", keyboard = "Space", gamepad = "Z button" },
{ action = "Back", keyboard = "Backspace", gamepad = "B button" },
{ action = "Click", keyboard = "Mouse", gamepad = "" },
}
--- Draws the controls window.
--- @within ControlsWindow
function ControlsWindow.draw()
UI.draw_top_bar("Controls")
local col_action = 4
local col_keyboard = 80
local col_gamepad = 170
local row_h = 10
local y_header = 18
local y_start = 30
Print.text("Action", col_action, y_header, Config.colors.light_grey)
Print.text("Keyboard", col_keyboard, y_header, Config.colors.light_grey)
Print.text("Gamepad", col_gamepad, y_header, Config.colors.light_grey)
line(col_action, y_header + 8, Config.screen.width - 4, y_header + 8, Config.colors.dark_grey)
for i, entry in ipairs(_controls) do
local y = y_start + (i - 1) * row_h
Print.text(entry.action, col_action, y, Config.colors.white)
Print.text(entry.keyboard, col_keyboard, y, Config.colors.light_blue)
if entry.gamepad ~= "" then
Print.text(entry.gamepad, col_gamepad, y, Config.colors.light_blue)
end
end
Print.text("Space / Z button or click to go back", col_action, Config.screen.height - 10, Config.colors.light_grey)
end
--- Updates the controls window logic.
--- @within ControlsWindow
function ControlsWindow.update()
if Input.back() or Input.select() then
Window.set_current("menu")
end
end

View File

@@ -52,7 +52,7 @@ function EndWindow.update()
end end
end end
if Input.select() then if Input.menu_confirm() then
Audio.sfx_select() Audio.sfx_select()
if Context._end.selection == 1 then if Context._end.selection == 1 then
Context._end.state = "ending" Context._end.state = "ending"
@@ -69,7 +69,7 @@ function EndWindow.update()
end end
end end
elseif Context._end.state == "ending" then elseif Context._end.state == "ending" then
if Input.select() then if Input.menu_confirm() then
Window.set_current("menu") Window.set_current("menu")
MenuWindow.refresh_menu_items() MenuWindow.refresh_menu_items()
end end

View File

@@ -38,7 +38,7 @@ end
--- @within GameWindow --- @within GameWindow
function GameWindow.update() function GameWindow.update()
Focus.update() Focus.update()
if Input.back() then if Input.menu_back() then
Window.set_current("menu") Window.set_current("menu")
MenuWindow.refresh_menu_items() MenuWindow.refresh_menu_items()
return return
@@ -48,6 +48,14 @@ function GameWindow.update()
if not screen or not screen.update then return end if not screen or not screen.update then return end
screen.update() screen.update()
-- Handle current situation updates
if Context.game.current_situation then
local current_situation_obj = Situation.get_by_id(Context.game.current_situation)
if current_situation_obj and type(current_situation_obj.update) == "function" then
current_situation_obj.update()
end
end
if Context.stat_screen_active then return end if Context.stat_screen_active then return end
-- Fetch and filter decisions locally -- Fetch and filter decisions locally
@@ -60,7 +68,7 @@ function GameWindow.update()
_selected_decision_index = 1 _selected_decision_index = 1
end end
local new_selected_decision_index, mouse_confirmed = Decision.update( local new_selected_decision_index = Decision.update(
_available_decisions, _available_decisions,
_selected_decision_index _selected_decision_index
) )
@@ -69,7 +77,7 @@ function GameWindow.update()
_selected_decision_index = new_selected_decision_index _selected_decision_index = new_selected_decision_index
end end
if Input.select() or mouse_confirmed then if Input.select() then
local selected_decision = _available_decisions[_selected_decision_index] local selected_decision = _available_decisions[_selected_decision_index]
if selected_decision and selected_decision.handle then if selected_decision and selected_decision.handle then
Audio.sfx_select() Audio.sfx_select()

View File

@@ -31,7 +31,7 @@ function BriefIntroWindow.update()
lines = lines + 1 lines = lines + 1
end end
if BriefIntroWindow.y < -lines * 8 or Input.select() or Input.select() then if BriefIntroWindow.y < -lines * 8 or Input.select() or Input.menu_confirm() then
Window.set_current("menu") Window.set_current("menu")
end end
end end

View File

@@ -30,7 +30,7 @@ end
--- @within TitleIntroWindow --- @within TitleIntroWindow
function TitleIntroWindow.update() function TitleIntroWindow.update()
TitleIntroWindow.timer = TitleIntroWindow.timer - 1 TitleIntroWindow.timer = TitleIntroWindow.timer - 1
if TitleIntroWindow.timer <= 0 or Input.select() or Input.select() then if TitleIntroWindow.timer <= 0 or Input.select() or Input.menu_confirm() then
Window.set_current("intro_ttg") Window.set_current("intro_ttg")
end end
end end

View File

@@ -27,13 +27,13 @@ function TTGIntroWindow.update()
TTGIntroWindow.glitch_started = true TTGIntroWindow.glitch_started = true
end end
-- Count enter presses during the intro -- Count menu_back presses during the intro
if Input.enter() then if Input.menu_back() then
TTGIntroWindow.space_count = TTGIntroWindow.space_count + 1 TTGIntroWindow.space_count = TTGIntroWindow.space_count + 1
end end
TTGIntroWindow.timer = TTGIntroWindow.timer - 1 TTGIntroWindow.timer = TTGIntroWindow.timer - 1
if TTGIntroWindow.timer <= 0 or Input.select() then if TTGIntroWindow.timer <= 0 or Input.menu_confirm() then
-- Evaluate exactly 3 presses at the end of the intro -- Evaluate exactly 3 presses at the end of the intro
if TTGIntroWindow.space_count == 3 then if TTGIntroWindow.space_count == 3 then
Context.test_mode = true Context.test_mode = true

View File

@@ -1,62 +1,18 @@
--- @section MenuWindow --- @section MenuWindow
local _menu_items = {} local _menu_items = {}
local _click_timer = 0
local _anim = 0
local _menu_max_w = 0
local ANIM_SPEED = 2.5
local HEADER_H = 28
--- Calculates the animated x position of the menu block.
--- @within MenuWindow
--- @return number x The left edge x coordinate for the menu.
function MenuWindow.calc_menu_x()
local center_start = Config.screen.width / 2
local center_end = Config.screen.width * 0.72
local center = center_start + _anim * (center_end - center_start)
return math.floor(center - _menu_max_w / 2)
end
--- Draws the header with title and separator.
--- @within MenuWindow
function MenuWindow.draw_header()
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)
local cx = Config.screen.width / 2
local subtitle = "Definitely not an"
if Context.test_mode then subtitle = subtitle .. " [TEST]" end
local sub_w = print(subtitle, 0, -6, 0, false, 1, true)
print(subtitle, math.floor(cx - sub_w / 2) + 1, 5, Config.colors.dark_grey, false, 1, true)
print(subtitle, math.floor(cx - sub_w / 2), 4, Config.colors.light_grey, false, 1, true)
Print.text_center("IMPOSTOR", cx, 12, Config.colors.item, false, 2)
end
--- Draws the 4x scaled Norman sprite on the left side of the screen.
--- @within MenuWindow
function MenuWindow.draw_norman()
local nx = math.floor(Config.screen.width * 0.45 / 2) - 32
local ny = HEADER_H + math.floor((Config.screen.height - HEADER_H - 96) / 2)
spr(272, nx, ny, 0, 4)
spr(273, nx + 32, ny, 0, 4)
spr(288, nx, ny + 32, 0, 4)
spr(289, nx + 32, ny + 32, 0, 4)
spr(304, nx, ny + 64, 0, 4)
spr(305, nx + 32, ny + 64, 0, 4)
end
--- Draws the menu window. --- Draws the menu window.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.draw() function MenuWindow.draw()
MenuWindow.draw_header() local title = "Definitely not an Impostor"
if Context.test_mode then
if _anim > 0 then title = title .. " (TEST MODE)"
MenuWindow.draw_norman()
end end
UI.draw_top_bar(title)
local menu_h = #_menu_items * 10 local menu_h = #_menu_items * 10
local y = HEADER_H + math.floor((Config.screen.height - HEADER_H - 10 - menu_h) / 2) local y = 10 + (Config.screen.height - 10 - 10 - menu_h) / 2
UI.draw_menu(_menu_items, Context.current_menu_item, MenuWindow.calc_menu_x(), y, false) UI.draw_menu(_menu_items, Context.current_menu_item, 0, y, true)
local ttg_text = "TTG" local ttg_text = "TTG"
local ttg_w = print(ttg_text, 0, -10, 0, false, 1, false) local ttg_w = print(ttg_text, 0, -10, 0, false, 1, false)
@@ -66,32 +22,9 @@ end
--- Updates the menu window logic. --- Updates the menu window logic.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.update() function MenuWindow.update()
if _anim < 1 then Context.current_menu_item = UI.update_menu(_menu_items, Context.current_menu_item)
_anim = math.min(1, _anim + ANIM_SPEED * Context.delta_time)
end
local menu_h = #_menu_items * 10 if Input.menu_confirm() then
local y = HEADER_H + math.floor((Config.screen.height - HEADER_H - 10 - menu_h) / 2)
if _click_timer > 0 then
_click_timer = _click_timer - Context.delta_time
if _click_timer <= 0 then
_click_timer = 0
local selected_item = _menu_items[Context.current_menu_item]
if selected_item and selected_item.decision then
selected_item.decision()
end
end
return
end
local new_item, mouse_confirmed = UI.update_menu(_menu_items, Context.current_menu_item, MenuWindow.calc_menu_x(), y, false)
Context.current_menu_item = new_item
if mouse_confirmed then
Audio.sfx_select()
_click_timer = 0.5
elseif Input.select() then
local selected_item = _menu_items[Context.current_menu_item] local selected_item = _menu_items[Context.current_menu_item]
if selected_item and selected_item.decision then if selected_item and selected_item.decision then
Audio.sfx_select() Audio.sfx_select()
@@ -131,10 +64,11 @@ function MenuWindow.exit()
exit() exit()
end end
--- Opens the controls screen. --- Opens the configuration menu.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.controls() function MenuWindow.configuration()
Window.set_current("controls") ConfigurationWindow.init()
GameWindow.set_state("configuration")
end end
--- Opens the audio test menu. --- Opens the audio test menu.
@@ -151,7 +85,7 @@ function MenuWindow.continued()
GameWindow.set_state("continued") GameWindow.set_state("continued")
end end
--- Opens the DDR minigame test. --- Opens the minigame ddr test menu.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.ddr_test() function MenuWindow.ddr_test()
AudioTestWindow.init() AudioTestWindow.init()
@@ -159,7 +93,7 @@ function MenuWindow.ddr_test()
MinigameDDRWindow.start("menu", "generated", { special_mode = "only_nothing" }) MinigameDDRWindow.start("menu", "generated", { special_mode = "only_nothing" })
end end
--- Refreshes the list of menu items based on current game state. --- Refreshes menu items.
--- @within MenuWindow --- @within MenuWindow
function MenuWindow.refresh_menu_items() function MenuWindow.refresh_menu_items()
_menu_items = {} _menu_items = {}
@@ -170,7 +104,7 @@ function MenuWindow.refresh_menu_items()
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 = "Load Game", decision = MenuWindow.load_game})
table.insert(_menu_items, {label = "Controls", decision = MenuWindow.controls}) table.insert(_menu_items, {label = "Configuration", decision = MenuWindow.configuration})
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})
@@ -180,13 +114,5 @@ function MenuWindow.refresh_menu_items()
table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit}) table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit})
_menu_max_w = 0
for _, item in ipairs(_menu_items) do
local w = print(item.label, 0, -10, 0, false, 1, false)
if w > _menu_max_w then _menu_max_w = w end
end
Context.current_menu_item = 1 Context.current_menu_item = 1
_click_timer = 0
_anim = 0
end end

View File

@@ -355,12 +355,6 @@ function MinigameDDRWindow.update()
right = Input.right() right = Input.right()
} }
for _, target in ipairs(mg.target_arrows) do
if Mouse.zone({ x = target.x, y = mg.target_y, w = mg.arrow_size, h = mg.arrow_size }) then
input_map[target.dir] = true
end
end
for dir, pressed in pairs(input_map) do for dir, pressed in pairs(input_map) do
if pressed and mg.input_cooldowns[dir] == 0 then if pressed and mg.input_cooldowns[dir] == 0 then
mg.input_cooldowns[dir] = mg.input_cooldown_duration mg.input_cooldowns[dir] = mg.input_cooldown_duration

View File

@@ -83,9 +83,7 @@ function MinigameButtonMashWindow.update()
return return
end end
local mouse_on_button = Mouse.zone_circle({ x = mg.button_x, y = mg.button_y, r = mg.button_size }) if Input.select() then
if Input.select() or mouse_on_button then
Audio.sfx_drum_high() Audio.sfx_drum_high()
mg.bar_fill = mg.bar_fill + mg.fill_per_press mg.bar_fill = mg.bar_fill + mg.fill_per_press

View File

@@ -95,9 +95,7 @@ function MinigameRhythmWindow.update()
if mg.press_cooldown > 0 then if mg.press_cooldown > 0 then
mg.press_cooldown = mg.press_cooldown - 1 mg.press_cooldown = mg.press_cooldown - 1
end end
local mouse_on_button = Mouse.zone_circle({ x = mg.button_x, y = mg.button_y, r = mg.button_size }) if Input.select() and mg.press_cooldown == 0 then
if (Input.select() or mouse_on_button) and mg.press_cooldown == 0 then
mg.button_pressed_timer = mg.button_press_duration mg.button_pressed_timer = mg.button_press_duration
mg.press_cooldown = mg.press_cooldown_duration mg.press_cooldown = mg.press_cooldown_duration
local target_left = mg.target_center - (mg.target_width / 2) local target_left = mg.target_center - (mg.target_width / 2)

View File

@@ -28,7 +28,7 @@ end
--- @within PopupWindow --- @within PopupWindow
function PopupWindow.update() function PopupWindow.update()
if Context.popup.show then if Context.popup.show then
if Input.select() or Input.back() then if Input.menu_confirm() or Input.menu_back() then
PopupWindow.hide() PopupWindow.hide()
end end
end end

View File

@@ -16,8 +16,8 @@ Window.register("game", GameWindow)
PopupWindow = {} PopupWindow = {}
Window.register("popup", PopupWindow) Window.register("popup", PopupWindow)
ControlsWindow = {} ConfigurationWindow = {}
Window.register("controls", ControlsWindow) Window.register("configuration", ConfigurationWindow)
AudioTestWindow = {} AudioTestWindow = {}
Window.register("audiotest", AudioTestWindow) Window.register("audiotest", AudioTestWindow)