Compare commits
80 Commits
continue-w
...
feature/ta
| Author | SHA1 | Date | |
|---|---|---|---|
| ae3415b417 | |||
| ce819eae2b | |||
| 658e6908b5 | |||
| 5ae1eec48a | |||
| 04eb825646 | |||
|
|
e797377ec1 | ||
|
|
9d56ca2e7a | ||
| 9b379d32b3 | |||
| 5fc6ae5c14 | |||
| 1e3716196e | |||
| 4b5f11969b | |||
| a4a6ad2ab2 | |||
| 8921f02821 | |||
| 211af18c26 | |||
| b337ae8516 | |||
| 10316d3075 | |||
| 589b225ab0 | |||
| 7697b35336 | |||
| 6e1cf1db3e | |||
| 020bfd4134 | |||
| 87d4f5843b | |||
| 8e610f14a0 | |||
| 753509b4ea | |||
| 7dbbbb4668 | |||
| 3290d0fb89 | |||
| 4cf7df511b | |||
| 8b0bcdbe95 | |||
| 7c3a011ffc | |||
| 6ee874655e | |||
| 3420694287 | |||
| e12a27e4e1 | |||
| 81b47c3760 | |||
| 53ccda7702 | |||
| 2912d7c482 | |||
| 284c5aa4c8 | |||
| 93df710d14 | |||
| 4e6590174a | |||
| 6a33be82e9 | |||
|
|
9a3c9ee28c | ||
| 197cb9403b | |||
|
|
c41bf23a45 | ||
| 9d6d2c2c6f | |||
|
|
fb8ae157b6 | ||
|
|
803ddc482b | ||
|
|
ed14a86997 | ||
|
|
9263a90961 | ||
|
|
05091c7af2 | ||
|
|
f79233521d | ||
|
|
46d3ff2ebc | ||
|
|
3e6fa41021 | ||
| d899a74411 | |||
| 4c7d43fea3 | |||
| 94563d32c0 | |||
| 9da44700cb | |||
| b72875c42f | |||
| 6b4d47a438 | |||
| d916ddeeb5 | |||
|
|
ca883a15bd | ||
|
|
b4dcdaba58 | ||
| 823c3313af | |||
| 47e41f4054 | |||
| 65e0f131c0 | |||
| 6a6d5ab1fe | |||
| 6807f7ae7f | |||
| c8d8999ba3 | |||
| c8073aff02 | |||
| 0d7dcad54a | |||
| e12021a432 | |||
| 29e7361303 | |||
| 2311232290 | |||
| c0e4562971 | |||
| 2079de587a | |||
| ec19e7fe12 | |||
| 2034fbd9b0 | |||
| 883ad5fcbf | |||
| 30c894c2f0 | |||
| 10e99ad25d | |||
| 37967639f4 | |||
| e5a942dd00 | |||
| 7a162d86b9 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,6 +1,10 @@
|
||||
.claude
|
||||
.local
|
||||
impostor.lua
|
||||
impostor.original.lua
|
||||
prompts
|
||||
docs
|
||||
minify.lua
|
||||
*.tic
|
||||
*.zip
|
||||
NOTES_*
|
||||
|
||||
12
.luacheckrc
12
.luacheckrc
@@ -10,7 +10,6 @@ globals = {
|
||||
"Discussion",
|
||||
"Util",
|
||||
"Decision",
|
||||
"Situation",
|
||||
"Screen",
|
||||
"Sprite",
|
||||
"UI",
|
||||
@@ -18,6 +17,7 @@ globals = {
|
||||
"Input",
|
||||
"Audio",
|
||||
"AsciiArt",
|
||||
"Ascension",
|
||||
"Config",
|
||||
"Context",
|
||||
"Meter",
|
||||
@@ -30,12 +30,12 @@ globals = {
|
||||
"MenuWindow",
|
||||
"GameWindow",
|
||||
"PopupWindow",
|
||||
"ConfigurationWindow",
|
||||
"ControlsWindow",
|
||||
"AudioTestWindow",
|
||||
"MinigameButtonMashWindow",
|
||||
"MinigameRhythmWindow",
|
||||
"MinigameDDRWindow",
|
||||
"MysteriousManWindow",
|
||||
"MysteriousManScreen",
|
||||
"DiscussionWindow",
|
||||
"EndWindow",
|
||||
"mset",
|
||||
@@ -63,6 +63,12 @@ globals = {
|
||||
"index_menu",
|
||||
"Map",
|
||||
"map",
|
||||
"time",
|
||||
"RLE",
|
||||
"mouse",
|
||||
"Mouse",
|
||||
"print",
|
||||
"musicator_generate_pattern",
|
||||
}
|
||||
|
||||
|
||||
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -30,5 +30,5 @@
|
||||
"files.associations": {
|
||||
"*.conf": "bitbake",
|
||||
"*.inc": "bitbake"
|
||||
}
|
||||
},
|
||||
}
|
||||
9
.vscode/tasks.json
vendored
9
.vscode/tasks.json
vendored
@@ -6,12 +6,17 @@
|
||||
{
|
||||
"label": "Run TIC80",
|
||||
"type": "shell",
|
||||
"command": "tic80 --fs=. impostor.lua"
|
||||
"command": "tic80 --fs=. impostor.lua",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Build & Run TIC80",
|
||||
"type": "shell",
|
||||
"command": "make build && tic80 --fs=. impostor.lua",
|
||||
"command": "make clean && make build && tic80 --fs=. impostor.lua",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 8.2 KiB |
31
impostor.inc
31
impostor.inc
@@ -1,11 +1,14 @@
|
||||
meta/meta.header.lua
|
||||
init/init.module.lua
|
||||
init/init.config.lua
|
||||
init/init.ascension.lua
|
||||
init/init.context.lua
|
||||
system/system.util.lua
|
||||
system/system.print.lua
|
||||
system/system.input.lua
|
||||
system/system.mouse.lua
|
||||
system/system.asciiart.lua
|
||||
system/system.rle.lua
|
||||
logic/logic.meter.lua
|
||||
logic/logic.focus.lua
|
||||
logic/logic.day.lua
|
||||
@@ -16,13 +19,27 @@ logic/logic.glitch.lua
|
||||
logic/logic.discussion.lua
|
||||
system/system.ui.lua
|
||||
audio/audio.manager.lua
|
||||
audio/audio.generator.lua
|
||||
audio/audio.songs.lua
|
||||
sprite/sprite.manager.lua
|
||||
sprite/sprite.norman.lua
|
||||
situation/situation.manager.lua
|
||||
situation/situation.drink_coffee.lua
|
||||
sprite/sprite.sumphore.lua
|
||||
sprite/sprite.pizza_vendor.lua
|
||||
sprite/sprite.dev_boy.lua
|
||||
sprite/sprite.dev_buddy.lua
|
||||
sprite/sprite.dev_extrovert.lua
|
||||
sprite/sprite.dev_girl.lua
|
||||
sprite/sprite.dev_guard.lua
|
||||
sprite/sprite.dev_guru.lua
|
||||
sprite/sprite.dev_hr_girl.lua
|
||||
sprite/sprite.dev_introvert.lua
|
||||
sprite/sprite.dev_operator.lua
|
||||
sprite/sprite.dev_project_manager.lua
|
||||
sprite/sprite.matrix_architect.lua
|
||||
sprite/sprite.matrix_neo.lua
|
||||
sprite/sprite.matrix_oraculum.lua
|
||||
sprite/sprite.matrix_trinity.lua
|
||||
decision/decision.manager.lua
|
||||
decision/decision.have_a_coffee.lua
|
||||
decision/decision.go_to_home.lua
|
||||
decision/decision.go_to_toilet.lua
|
||||
decision/decision.go_to_walking_to_office.lua
|
||||
@@ -31,8 +48,10 @@ decision/decision.go_to_end.lua
|
||||
decision/decision.go_to_walking_to_home.lua
|
||||
decision/decision.go_to_sleep.lua
|
||||
decision/decision.do_work.lua
|
||||
decision/decision.start_discussion.lua
|
||||
decision/decision.have_a_coffee.lua
|
||||
decision/decision.sumphore_discussion.lua
|
||||
discussion/discussion.sumphore.lua
|
||||
discussion/discussion.coworker.lua
|
||||
map/map.manager.lua
|
||||
map/map.bedroom.lua
|
||||
map/map.street.lua
|
||||
@@ -44,6 +63,7 @@ screen/screen.walking_to_office.lua
|
||||
screen/screen.office.lua
|
||||
screen/screen.walking_to_home.lua
|
||||
screen/screen.work.lua
|
||||
screen/screen.mysterious_man.lua
|
||||
window/window.manager.lua
|
||||
window/window.register.lua
|
||||
window/window.end.lua
|
||||
@@ -51,13 +71,12 @@ window/window.intro.title.lua
|
||||
window/window.intro.ttg.lua
|
||||
window/window.intro.brief.lua
|
||||
window/window.menu.lua
|
||||
window/window.configuration.lua
|
||||
window/window.controls.lua
|
||||
window/window.audiotest.lua
|
||||
window/window.popup.lua
|
||||
window/window.minigame.mash.lua
|
||||
window/window.minigame.rhythm.lua
|
||||
window/window.minigame.ddr.lua
|
||||
window/window.mysterious_man.lua
|
||||
window/window.discussion.lua
|
||||
window/window.continued.lua
|
||||
window/window.game.lua
|
||||
|
||||
744
inc/audio/audio.generator.lua
Normal file
744
inc/audio/audio.generator.lua
Normal file
@@ -0,0 +1,744 @@
|
||||
local musicator_markov_model = {
|
||||
model = {
|
||||
["...|..."] = {
|
||||
next = {
|
||||
["..."] = 0.71111111111111,
|
||||
["A-4"] = 0.0074074074074074,
|
||||
["B-4"] = 0.0037037037037037,
|
||||
["C-3"] = 0.011111111111111,
|
||||
["C-4"] = 0.037037037037037,
|
||||
["C-5"] = 0.11111111111111,
|
||||
["C-6"] = 0.0037037037037037,
|
||||
["D-4"] = 0.011111111111111,
|
||||
["D-5"] = 0.018518518518519,
|
||||
["E-4"] = 0.0074074074074074,
|
||||
["E-5"] = 0.025925925925926,
|
||||
["F-5"] = 0.0074074074074074,
|
||||
["G-3"] = 0.0037037037037037,
|
||||
["G-4"] = 0.022222222222222,
|
||||
["G-5"] = 0.018518518518519
|
||||
},
|
||||
total = 270
|
||||
},
|
||||
["...|A-4"] = {
|
||||
next = {
|
||||
["..."] = 0.9,
|
||||
["C-5"] = 0.1
|
||||
},
|
||||
total = 10
|
||||
},
|
||||
["...|A-5"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 8
|
||||
},
|
||||
["...|B-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["...|B-5"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 5
|
||||
},
|
||||
["...|C-3"] = {
|
||||
next = {
|
||||
["..."] = 0.66666666666667,
|
||||
["C-5"] = 0.33333333333333
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["...|C-4"] = {
|
||||
next = {
|
||||
["..."] = 0.875,
|
||||
["D-4"] = 0.083333333333333,
|
||||
["E-4"] = 0.041666666666667
|
||||
},
|
||||
total = 24
|
||||
},
|
||||
["...|C-5"] = {
|
||||
next = {
|
||||
["..."] = 0.73333333333333,
|
||||
["B-4"] = 0.033333333333333,
|
||||
["C-5"] = 0.066666666666667,
|
||||
["D-5"] = 0.13333333333333,
|
||||
["E-5"] = 0.033333333333333
|
||||
},
|
||||
total = 60
|
||||
},
|
||||
["...|C-6"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["...|D-4"] = {
|
||||
next = {
|
||||
["..."] = 0.92857142857143,
|
||||
["D-4"] = 0.071428571428571
|
||||
},
|
||||
total = 14
|
||||
},
|
||||
["...|D-5"] = {
|
||||
next = {
|
||||
["..."] = 0.80645161290323,
|
||||
["C-5"] = 0.032258064516129,
|
||||
["D-5"] = 0.032258064516129,
|
||||
["E-5"] = 0.12903225806452
|
||||
},
|
||||
total = 31
|
||||
},
|
||||
["...|D-6"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["...|E-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 19
|
||||
},
|
||||
["...|E-5"] = {
|
||||
next = {
|
||||
["..."] = 0.77777777777778,
|
||||
["C-5"] = 0.022222222222222,
|
||||
["D-5"] = 0.13333333333333,
|
||||
["F-5"] = 0.066666666666667
|
||||
},
|
||||
total = 45
|
||||
},
|
||||
["...|F-3"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["...|F-4"] = {
|
||||
next = {
|
||||
["..."] = 0.8,
|
||||
["D-4"] = 0.1,
|
||||
["F-4"] = 0.1
|
||||
},
|
||||
total = 10
|
||||
},
|
||||
["...|F-5"] = {
|
||||
next = {
|
||||
["..."] = 0.66666666666667,
|
||||
["D-5"] = 0.066666666666667,
|
||||
["E-5"] = 0.066666666666667,
|
||||
["G-5"] = 0.2
|
||||
},
|
||||
total = 15
|
||||
},
|
||||
["...|G-3"] = {
|
||||
next = {
|
||||
["..."] = 0.8,
|
||||
["G-5"] = 0.2
|
||||
},
|
||||
total = 5
|
||||
},
|
||||
["...|G-4"] = {
|
||||
next = {
|
||||
["..."] = 0.95652173913043,
|
||||
["E-4"] = 0.043478260869565
|
||||
},
|
||||
total = 23
|
||||
},
|
||||
["...|G-5"] = {
|
||||
next = {
|
||||
["..."] = 0.875,
|
||||
["A-5"] = 0.0625,
|
||||
["E-5"] = 0.0625
|
||||
},
|
||||
total = 16
|
||||
},
|
||||
["...|G-6"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["A-4|..."] = {
|
||||
next = {
|
||||
["..."] = 0.55555555555556,
|
||||
["C-5"] = 0.33333333333333,
|
||||
["D-5"] = 0.11111111111111
|
||||
},
|
||||
total = 9
|
||||
},
|
||||
["A-4|B-4"] = {
|
||||
next = {
|
||||
["C-5"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["A-4|C-5"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["A-4|G-4"] = {
|
||||
next = {
|
||||
["F-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["A-5|..."] = {
|
||||
next = {
|
||||
["..."] = 0.2,
|
||||
["B-5"] = 0.1,
|
||||
["E-4"] = 0.1,
|
||||
["E-5"] = 0.4,
|
||||
["F-5"] = 0.1,
|
||||
["G-5"] = 0.1
|
||||
},
|
||||
total = 10
|
||||
},
|
||||
["A-5|G-5"] = {
|
||||
next = {
|
||||
["..."] = 0.33333333333333,
|
||||
["A-5"] = 0.66666666666667
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["B-4|..."] = {
|
||||
next = {
|
||||
["A-4"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["B-4|A-4"] = {
|
||||
next = {
|
||||
["G-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["B-4|C-5"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["B-5|..."] = {
|
||||
next = {
|
||||
["..."] = 0.2,
|
||||
["A-5"] = 0.2,
|
||||
["D-6"] = 0.4,
|
||||
["G-5"] = 0.2
|
||||
},
|
||||
total = 5
|
||||
},
|
||||
["C-3|..."] = {
|
||||
next = {
|
||||
["C-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["C-3|C-5"] = {
|
||||
next = {
|
||||
["..."] = 0.33333333333333,
|
||||
["C-3"] = 0.66666666666667
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["C-4|..."] = {
|
||||
next = {
|
||||
["..."] = 0.5,
|
||||
["D-4"] = 0.125,
|
||||
["E-4"] = 0.041666666666667,
|
||||
["F-3"] = 0.041666666666667,
|
||||
["G-3"] = 0.16666666666667,
|
||||
["G-4"] = 0.083333333333333,
|
||||
["G-5"] = 0.041666666666667
|
||||
},
|
||||
total = 24
|
||||
},
|
||||
["C-4|D-4"] = {
|
||||
next = {
|
||||
["E-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["C-4|E-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["C-5|..."] = {
|
||||
next = {
|
||||
["..."] = 0.40677966101695,
|
||||
["A-4"] = 0.067796610169492,
|
||||
["C-5"] = 0.050847457627119,
|
||||
["D-5"] = 0.20338983050847,
|
||||
["E-5"] = 0.15254237288136,
|
||||
["F-5"] = 0.016949152542373,
|
||||
["G-4"] = 0.10169491525424
|
||||
},
|
||||
total = 59
|
||||
},
|
||||
["C-5|B-4"] = {
|
||||
next = {
|
||||
["A-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["C-5|C-3"] = {
|
||||
next = {
|
||||
["C-5"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["C-5|C-5"] = {
|
||||
next = {
|
||||
["..."] = 0.8,
|
||||
["C-5"] = 0.2
|
||||
},
|
||||
total = 5
|
||||
},
|
||||
["C-5|D-5"] = {
|
||||
next = {
|
||||
["..."] = 0.3,
|
||||
["C-5"] = 0.2,
|
||||
["D-5"] = 0.1,
|
||||
["E-5"] = 0.4
|
||||
},
|
||||
total = 10
|
||||
},
|
||||
["C-5|E-5"] = {
|
||||
next = {
|
||||
["..."] = 0.33333333333333,
|
||||
["D-5"] = 0.33333333333333,
|
||||
["G-5"] = 0.33333333333333
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["C-6|..."] = {
|
||||
next = {
|
||||
["A-5"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["D-4|..."] = {
|
||||
next = {
|
||||
["..."] = 0.26666666666667,
|
||||
["A-5"] = 0.066666666666667,
|
||||
["C-4"] = 0.2,
|
||||
["E-4"] = 0.4,
|
||||
["F-3"] = 0.066666666666667
|
||||
},
|
||||
total = 15
|
||||
},
|
||||
["D-4|C-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["D-4|D-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["D-4|E-4"] = {
|
||||
next = {
|
||||
["F-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["D-5|..."] = {
|
||||
next = {
|
||||
["..."] = 0.2258064516129,
|
||||
["A-4"] = 0.032258064516129,
|
||||
["A-5"] = 0.032258064516129,
|
||||
["C-5"] = 0.2258064516129,
|
||||
["E-5"] = 0.29032258064516,
|
||||
["F-5"] = 0.096774193548387,
|
||||
["G-5"] = 0.096774193548387
|
||||
},
|
||||
total = 31
|
||||
},
|
||||
["D-5|C-5"] = {
|
||||
next = {
|
||||
["..."] = 0.77777777777778,
|
||||
["D-5"] = 0.22222222222222
|
||||
},
|
||||
total = 9
|
||||
},
|
||||
["D-5|D-5"] = {
|
||||
next = {
|
||||
["..."] = 0.5,
|
||||
["E-5"] = 0.5
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["D-5|E-5"] = {
|
||||
next = {
|
||||
["..."] = 0.33333333333333,
|
||||
["E-5"] = 0.11111111111111,
|
||||
["F-5"] = 0.55555555555556
|
||||
},
|
||||
total = 9
|
||||
},
|
||||
["D-5|F-5"] = {
|
||||
next = {
|
||||
["E-5"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["D-6|..."] = {
|
||||
next = {
|
||||
["B-5"] = 0.66666666666667,
|
||||
["G-6"] = 0.33333333333333
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["E-4|..."] = {
|
||||
next = {
|
||||
["..."] = 0.19047619047619,
|
||||
["B-5"] = 0.047619047619048,
|
||||
["C-4"] = 0.14285714285714,
|
||||
["D-4"] = 0.23809523809524,
|
||||
["F-4"] = 0.19047619047619,
|
||||
["G-4"] = 0.19047619047619
|
||||
},
|
||||
total = 21
|
||||
},
|
||||
["E-4|D-4"] = {
|
||||
next = {
|
||||
["C-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["E-4|F-4"] = {
|
||||
next = {
|
||||
["G-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["E-5|..."] = {
|
||||
next = {
|
||||
["..."] = 0.18604651162791,
|
||||
["A-5"] = 0.046511627906977,
|
||||
["C-5"] = 0.27906976744186,
|
||||
["D-5"] = 0.2093023255814,
|
||||
["E-5"] = 0.069767441860465,
|
||||
["F-5"] = 0.093023255813953,
|
||||
["G-4"] = 0.023255813953488,
|
||||
["G-5"] = 0.093023255813953
|
||||
},
|
||||
total = 43
|
||||
},
|
||||
["E-5|C-5"] = {
|
||||
next = {
|
||||
["E-5"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["E-5|D-5"] = {
|
||||
next = {
|
||||
["..."] = 0.125,
|
||||
["C-5"] = 0.75,
|
||||
["F-5"] = 0.125
|
||||
},
|
||||
total = 8
|
||||
},
|
||||
["E-5|E-5"] = {
|
||||
next = {
|
||||
["F-5"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["E-5|F-5"] = {
|
||||
next = {
|
||||
["..."] = 0.5,
|
||||
["E-5"] = 0.4,
|
||||
["G-5"] = 0.1
|
||||
},
|
||||
total = 10
|
||||
},
|
||||
["E-5|G-5"] = {
|
||||
next = {
|
||||
["..."] = 0.5,
|
||||
["F-5"] = 0.5
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["F-3|..."] = {
|
||||
next = {
|
||||
["C-4"] = 1
|
||||
},
|
||||
total = 3
|
||||
},
|
||||
["F-4|..."] = {
|
||||
next = {
|
||||
["D-4"] = 0.11111111111111,
|
||||
["E-4"] = 0.44444444444444,
|
||||
["G-4"] = 0.44444444444444
|
||||
},
|
||||
total = 9
|
||||
},
|
||||
["F-4|D-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["F-4|E-4"] = {
|
||||
next = {
|
||||
["D-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["F-4|F-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["F-4|G-4"] = {
|
||||
next = {
|
||||
["A-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["F-5|..."] = {
|
||||
next = {
|
||||
["..."] = 0.2,
|
||||
["A-5"] = 0.066666666666667,
|
||||
["D-5"] = 0.2,
|
||||
["E-5"] = 0.46666666666667,
|
||||
["G-5"] = 0.066666666666667
|
||||
},
|
||||
total = 15
|
||||
},
|
||||
["F-5|A-5"] = {
|
||||
next = {
|
||||
["G-5"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["F-5|D-5"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["F-5|E-5"] = {
|
||||
next = {
|
||||
["..."] = 0.5,
|
||||
["D-5"] = 0.16666666666667,
|
||||
["F-5"] = 0.16666666666667,
|
||||
["G-5"] = 0.16666666666667
|
||||
},
|
||||
total = 6
|
||||
},
|
||||
["F-5|G-5"] = {
|
||||
next = {
|
||||
["..."] = 0.75,
|
||||
["A-5"] = 0.25
|
||||
},
|
||||
total = 4
|
||||
},
|
||||
["G-3|..."] = {
|
||||
next = {
|
||||
["C-4"] = 0.5,
|
||||
["D-4"] = 0.25,
|
||||
["F-3"] = 0.25
|
||||
},
|
||||
total = 4
|
||||
},
|
||||
["G-3|G-5"] = {
|
||||
next = {
|
||||
["..."] = 0.5,
|
||||
["G-3"] = 0.5
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["G-4|..."] = {
|
||||
next = {
|
||||
["..."] = 0.090909090909091,
|
||||
["A-4"] = 0.090909090909091,
|
||||
["C-4"] = 0.045454545454545,
|
||||
["C-5"] = 0.18181818181818,
|
||||
["D-5"] = 0.045454545454545,
|
||||
["E-4"] = 0.22727272727273,
|
||||
["E-5"] = 0.045454545454545,
|
||||
["F-4"] = 0.27272727272727
|
||||
},
|
||||
total = 22
|
||||
},
|
||||
["G-4|A-4"] = {
|
||||
next = {
|
||||
["B-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["G-4|E-4"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["G-4|F-4"] = {
|
||||
next = {
|
||||
["E-4"] = 1
|
||||
},
|
||||
total = 2
|
||||
},
|
||||
["G-5|..."] = {
|
||||
next = {
|
||||
["..."] = 0.35,
|
||||
["A-5"] = 0.05,
|
||||
["B-5"] = 0.05,
|
||||
["C-5"] = 0.05,
|
||||
["D-4"] = 0.05,
|
||||
["E-5"] = 0.25,
|
||||
["F-5"] = 0.2
|
||||
},
|
||||
total = 20
|
||||
},
|
||||
["G-5|A-5"] = {
|
||||
next = {
|
||||
["..."] = 0.5,
|
||||
["G-5"] = 0.5
|
||||
},
|
||||
total = 4
|
||||
},
|
||||
["G-5|E-5"] = {
|
||||
next = {
|
||||
["..."] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["G-5|F-5"] = {
|
||||
next = {
|
||||
["A-5"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["G-5|G-3"] = {
|
||||
next = {
|
||||
["G-5"] = 1
|
||||
},
|
||||
total = 1
|
||||
},
|
||||
["G-6|..."] = {
|
||||
next = {
|
||||
["D-6"] = 1
|
||||
},
|
||||
total = 1
|
||||
}
|
||||
},
|
||||
order = 2
|
||||
}
|
||||
|
||||
local function musicator_unmake_key(k)
|
||||
local result = {}
|
||||
for t in string.gmatch(k, "[^|]+") do
|
||||
result[#result + 1] = t
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local function musicator_count_notes(sequence)
|
||||
local result = 0
|
||||
|
||||
for _,v in ipairs(sequence) do
|
||||
if v ~= "..." then
|
||||
result = result + 1
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local function musicator_generate_sequence(model_data, length)
|
||||
local order = model_data.order
|
||||
local model = model_data.model
|
||||
|
||||
-- random start key
|
||||
local model_keys = {}
|
||||
for k,_ in pairs(model) do
|
||||
model_keys[#model_keys + 1] = k
|
||||
end
|
||||
local start_key = model_keys[math.ceil(math.random() * #model_keys)]
|
||||
|
||||
-- sequence starts with the start key
|
||||
local seq = musicator_unmake_key(start_key)
|
||||
|
||||
-- generation loop
|
||||
while musicator_count_notes(seq) < length do
|
||||
local current_key = table.concat({table.unpack(seq, #seq - order + 1, #seq)}, "|") -- luacheck: ignore
|
||||
|
||||
local chosen = "..."
|
||||
|
||||
local key_data = model[current_key]
|
||||
if key_data then
|
||||
local r = math.random()
|
||||
local prob_sum = 0.0
|
||||
for new_note, new_prob in pairs(key_data.next) do
|
||||
prob_sum = prob_sum + new_prob
|
||||
if prob_sum < r then
|
||||
chosen = new_note
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- print(current_key .. " --> " .. chosen)
|
||||
|
||||
seq[#seq+1] = chosen
|
||||
end
|
||||
|
||||
return seq
|
||||
end
|
||||
|
||||
local function musicator_row_to_frame(row, bpm, spd)
|
||||
local frames_per_row = (150 * spd) / bpm
|
||||
return math.floor(row * frames_per_row)
|
||||
end
|
||||
|
||||
local function musicator_note_to_direction(note)
|
||||
local subnote = note:sub(1,1)
|
||||
|
||||
local mapping = {
|
||||
C="left",
|
||||
D="up",
|
||||
E="up",
|
||||
F="right",
|
||||
G="right",
|
||||
A="down"
|
||||
}
|
||||
|
||||
return mapping[subnote] or "up"
|
||||
end
|
||||
|
||||
-- converts generated sequence to pattern that the ddr minigame can consume
|
||||
local function musicator_sequence_to_pattern(sequence, bpm, spd)
|
||||
local result = {}
|
||||
|
||||
for i, note in ipairs(sequence) do
|
||||
if note ~= "..." then
|
||||
|
||||
local at_ms = musicator_row_to_frame(i, bpm, spd)
|
||||
local direction = musicator_note_to_direction(note)
|
||||
|
||||
result[#result + 1] = { frame=at_ms, dir=direction, note=note }
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local function musicator_generate_pattern(length, bpm, spd)
|
||||
return musicator_sequence_to_pattern(musicator_generate_sequence(musicator_markov_model, length), bpm, spd)
|
||||
end
|
||||
@@ -1,48 +1,93 @@
|
||||
--- @section Audio
|
||||
|
||||
Audio = {
|
||||
music_playing = nil
|
||||
}
|
||||
|
||||
--- Stops current music.
|
||||
--- @within Audio
|
||||
function Audio.music_stop() music() end
|
||||
function Audio.music_stop()
|
||||
music()
|
||||
Audio.music_playing = nil
|
||||
end
|
||||
|
||||
--- Plays track, doesn't restart if already playing.
|
||||
function Audio.music_play(track)
|
||||
if Audio.music_playing ~= track then
|
||||
music(track)
|
||||
Audio.music_playing = track
|
||||
end
|
||||
end
|
||||
|
||||
--- Plays main menu music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_mainmenu() end
|
||||
|
||||
--- Plays mystery man music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_mystery() Audio.music_play(2) end
|
||||
|
||||
--- Plays waking up music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_wakingup() end
|
||||
|
||||
--- Plays room morning music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_room_morning() end
|
||||
|
||||
--- Plays room street 1 music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_room_street_1() end
|
||||
|
||||
--- Plays room street 2 music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_room_street_2() end
|
||||
|
||||
--- Plays room music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_room_() end
|
||||
|
||||
--- Plays room work music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_room_work() music(0) end
|
||||
function Audio.music_play_room_work() Audio.music_play(0) end
|
||||
|
||||
--- Plays activity work music.
|
||||
--- @within Audio
|
||||
function Audio.music_play_activity_work() music(1) end
|
||||
function Audio.music_play_activity_work() Audio.music_play(1) end
|
||||
|
||||
--- Plays select sound effect.
|
||||
--- @within Audio
|
||||
function Audio.sfx_select() sfx(17, 'C-7', 30) end
|
||||
|
||||
--- Plays deselect sound effect.
|
||||
--- @within Audio
|
||||
function Audio.sfx_deselect() sfx(18, 'C-7', 30) end
|
||||
|
||||
--- Plays beep sound effect.
|
||||
--- @within Audio
|
||||
function Audio.sfx_beep() sfx(19, 'C-6', 30) end
|
||||
|
||||
--- Plays success sound effect.
|
||||
--- @within Audio
|
||||
function Audio.sfx_success() sfx(16, 'C-7', 60) end
|
||||
|
||||
--- Plays bloop sound effect.
|
||||
--- @within Audio
|
||||
function Audio.sfx_bloop() sfx(21, 'C-3', 60) end
|
||||
--- Plays alarm sound effect.
|
||||
|
||||
--- Plays alarm sound effect
|
||||
--- @within Audio
|
||||
function Audio.sfx_alarm() sfx(61) end
|
||||
function Audio.sfx_alarm() sfx(34, "C-5", 240) end
|
||||
|
||||
--- Plays drum sound effect.
|
||||
--- @within Audio
|
||||
function Audio.sfx_drum_low() sfx(61, "C-2") end
|
||||
|
||||
--- Plays drum sound effect.
|
||||
--- @within Audio
|
||||
function Audio.sfx_drum_high() sfx(61, "C-6") end
|
||||
|
||||
--- Plays sound effect for arrow hit
|
||||
--- @within Audio
|
||||
--- @param note string The note for the sound to play
|
||||
function Audio.sfx_arrowhit(note) sfx(56, note) end
|
||||
|
||||
@@ -105,6 +105,15 @@ Songs = {
|
||||
fps = 60,
|
||||
end_frame = nil, -- No end frame for random mode
|
||||
pattern = {} -- Empty, will spawn randomly in game
|
||||
},
|
||||
generated = {
|
||||
name = "Markov Mode",
|
||||
bpm = 150,
|
||||
spd = 6,
|
||||
fps = 60,
|
||||
end_frame = nil, -- calculated
|
||||
pattern = {}, -- generated
|
||||
generated = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,31 @@ Decision.register({
|
||||
handle = function()
|
||||
Meter.hide()
|
||||
Util.go_to_screen_by_id("work")
|
||||
MinigameDDRWindow.start("game", nil, {
|
||||
on_win = function()
|
||||
|
||||
local modes_for_ascension_levels = {}
|
||||
modes_for_ascension_levels[0] = "normal"
|
||||
modes_for_ascension_levels[1] = "only_special"
|
||||
modes_for_ascension_levels[2] = "only_left"
|
||||
modes_for_ascension_levels[3] = "only_nothing"
|
||||
|
||||
MinigameDDRWindow.start("game", "generated", {
|
||||
on_win = function(game_context)
|
||||
if (game_context.special_mode_condition and Context.ascension.level == 1) then
|
||||
Context.should_ascend = true
|
||||
elseif (game_context.special_mode_condition and Context.ascension.level == 2) then
|
||||
Context.should_ascend = true
|
||||
elseif (game_context.special_mode_condition and Context.ascension.level == 3) then
|
||||
Context.should_ascend = true
|
||||
elseif (game_context.special_mode_condition and Context.ascension.level == 4) then
|
||||
Context.should_ascend = true
|
||||
end
|
||||
|
||||
Meter.show()
|
||||
Util.go_to_screen_by_id("office")
|
||||
Window.set_current("game")
|
||||
Context.have_done_work_today = true
|
||||
end,
|
||||
special_mode = modes_for_ascension_levels[Ascension.get_level()]
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
Decision.register({
|
||||
id = "go_to_end",
|
||||
label = "Break the cycle",
|
||||
condition = function()
|
||||
return Ascension.is_complete()
|
||||
end,
|
||||
handle = function()
|
||||
Window.set_current("end")
|
||||
end,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
Decision.register({
|
||||
id = "go_to_home",
|
||||
label = "Go to Home",
|
||||
label = "Go Home",
|
||||
condition = function()
|
||||
return Context.have_been_to_office and Context.have_done_work_today
|
||||
end,
|
||||
handle = function()
|
||||
Util.go_to_screen_by_id("home")
|
||||
end,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
Decision.register({
|
||||
id = "go_to_sleep",
|
||||
label = "Go to Sleep",
|
||||
condition = function()
|
||||
return Context.have_been_to_office and Context.have_done_work_today
|
||||
end,
|
||||
handle = function()
|
||||
Meter.hide()
|
||||
Day.increase()
|
||||
@@ -9,7 +12,12 @@ Decision.register({
|
||||
focus_center_y = (Config.screen.height / 2) - 18,
|
||||
focus_initial_radius = 0,
|
||||
on_win = function()
|
||||
MysteriousManWindow.start()
|
||||
local ascended = Ascension.consume_increase()
|
||||
local level = Ascension.get_level()
|
||||
MysteriousManScreen.start({
|
||||
skip_text = not ascended,
|
||||
text = ascended and MysteriousManScreen.get_text_for_level(level) or nil,
|
||||
})
|
||||
end,
|
||||
})
|
||||
end,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Decision.register({
|
||||
id = "go_to_walking_to_home",
|
||||
label = "Walking to home",
|
||||
label = "Walk home",
|
||||
handle = function()
|
||||
Util.go_to_screen_by_id("walking_to_home")
|
||||
end,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Decision.register({
|
||||
id = "go_to_walking_to_office",
|
||||
label = "Walking to office",
|
||||
label = "Walk to office",
|
||||
handle = function()
|
||||
Util.go_to_screen_by_id("walking_to_office")
|
||||
end,
|
||||
|
||||
@@ -2,7 +2,13 @@ Decision.register({
|
||||
id = "have_a_coffee",
|
||||
label = "Have a Coffee",
|
||||
handle = function()
|
||||
local new_situation_id = Situation.apply("drink_coffee", Context.game.current_screen)
|
||||
Context.game.current_situation = new_situation_id
|
||||
local level = Ascension.get_level()
|
||||
local disc_id = "coworker_disc_0"
|
||||
-- TODO: Add more discussions for levels above 3
|
||||
if level >= 1 and level <= 3 then
|
||||
local suffix = Context.have_done_work_today and ("_asc_" .. level) or ("_" .. level)
|
||||
disc_id = "coworker_disc" .. suffix
|
||||
end
|
||||
Discussion.start(disc_id, "game")
|
||||
end,
|
||||
})
|
||||
@@ -123,9 +123,13 @@ function Decision.draw(decisions, selected_decision_index)
|
||||
local selected_decision = decisions[selected_decision_index]
|
||||
local decision_label = Decision.get_label(selected_decision)
|
||||
local text_y = bar_y + 4
|
||||
Print.text("<", 2, text_y, Config.colors.light_blue)
|
||||
Print.text_center(decision_label, Config.screen.width / 2, text_y, Config.colors.item)
|
||||
Print.text(">", Config.screen.width - 6, text_y, Config.colors.light_blue)
|
||||
local left_arrow_color = Input.left() and Config.colors.white or Config.colors.orange
|
||||
local right_arrow_color = Input.right() and Config.colors.white or Config.colors.orange
|
||||
local left_arrow_contour_color = Input.left() and Config.colors.white or Config.colors.black
|
||||
local right_arrow_contour_color = Input.right() and Config.colors.white or Config.colors.black
|
||||
Print.text_center_contour("<", 6, text_y, left_arrow_color, false, 1, left_arrow_contour_color)
|
||||
Print.text_center_contour(decision_label, Config.screen.width / 2, text_y, Config.colors.orange)
|
||||
Print.text_center_contour(">", Config.screen.width - 6, text_y, right_arrow_color, false, 1, right_arrow_contour_color)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -134,6 +138,7 @@ end
|
||||
--- @param decisions table A table of decision items.<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 boolean mouse_confirmed True if the user clicked the center to confirm.
|
||||
function Decision.update(decisions, selected_decision_index)
|
||||
if Input.left() then
|
||||
Audio.sfx_beep()
|
||||
@@ -142,5 +147,22 @@ function Decision.update(decisions, selected_decision_index)
|
||||
Audio.sfx_beep()
|
||||
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
||||
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
|
||||
|
||||
@@ -7,6 +7,9 @@ Decision.register({
|
||||
focus_center_x = (Config.screen.width / 2) - 22,
|
||||
focus_center_y = (Config.screen.height / 2) - 18,
|
||||
focus_initial_radius = 0,
|
||||
on_win = function()
|
||||
Audio.music_play_room_work()
|
||||
end
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
Decision.register({
|
||||
id = "play_ddr",
|
||||
label = "Play DDR (Random)",
|
||||
handle = function() Meter.hide() MinigameDDRWindow.start("game", nil) end,
|
||||
handle = function()
|
||||
Meter.hide()
|
||||
MinigameDDRWindow.start("game", nil)
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
Decision.register({
|
||||
id = "start_discussion",
|
||||
label = function()
|
||||
if Context.day_count >= 3 then
|
||||
return "Talk to Sumphore"
|
||||
end
|
||||
return "Talk to the homeless guy"
|
||||
end,
|
||||
handle = function()
|
||||
if Context.day_count < 3 then
|
||||
Discussion.start("homeless_guy", "game")
|
||||
end
|
||||
if Context.day_count >= 3 then
|
||||
Discussion.start("sumphore_day_3", "game")
|
||||
return
|
||||
end
|
||||
end,
|
||||
})
|
||||
23
inc/decision/decision.sumphore_discussion.lua
Normal file
23
inc/decision/decision.sumphore_discussion.lua
Normal file
@@ -0,0 +1,23 @@
|
||||
Decision.register({
|
||||
id = "sumphore_discussion",
|
||||
label = function()
|
||||
if Context.have_met_sumphore then
|
||||
return "Talk to Sumphore"
|
||||
end
|
||||
return "Talk to the homeless guy"
|
||||
end,
|
||||
handle = function()
|
||||
if not Context.have_met_sumphore then
|
||||
Discussion.start("homeless_guy", "game")
|
||||
return
|
||||
end
|
||||
local level = Ascension.get_level()
|
||||
|
||||
-- TODO: Add more discussions for levels above 3
|
||||
if level >= 1 and level <= 3 then
|
||||
Discussion.start("sumphore_disc_asc_" .. level, "game")
|
||||
else
|
||||
Discussion.start("homeless_guy", "game", 4)
|
||||
end
|
||||
end,
|
||||
})
|
||||
137
inc/discussion/discussion.coworker.lua
Normal file
137
inc/discussion/discussion.coworker.lua
Normal file
@@ -0,0 +1,137 @@
|
||||
Discussion.register({
|
||||
id = "coworker_disc_0",
|
||||
steps = {
|
||||
{
|
||||
question = "Good morning Normal, enjoying your coffee as usual, huh?",
|
||||
answers = {
|
||||
{ label = "The name is Norman, not Normal", next_step = 2 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Can't work without some good coffee, no? ",
|
||||
answers = {
|
||||
{ label = "Mhmm", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_1",
|
||||
steps = {
|
||||
{
|
||||
question = "Norman, you look confused, what's up?",
|
||||
answers = {
|
||||
{ label = "Just some bugs I noticed", next_step = 2 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Your coffee also seems whiter than usual!",
|
||||
answers = {
|
||||
{ label = "I feel like latte today", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_asc_1",
|
||||
steps = {
|
||||
{
|
||||
question = "Normann you look weird and unfocused. You are usually locked in and not like this, what's up?",
|
||||
answers = {
|
||||
{ label = "Some bugs I noticed, maybe...", next_step = 2 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Are you fixing bugs nobody noticed before?",
|
||||
answers = {
|
||||
{ label = "Maybe", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_2",
|
||||
steps = {
|
||||
{
|
||||
question = "Hey Norman, do you have new socks on? That's a weird color!",
|
||||
answers = {
|
||||
{ label = "Huh? True ...", next_step = 2 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "You look strange today, Normal, you put your tie on backwards, is everything ok? ",
|
||||
answers = {
|
||||
{ label = "Get it right, Norman ... NORMAN!", next_step = 3 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Yo Normann, text goes from left to right, not right to left, these parts!",
|
||||
answers = {
|
||||
{ label = "Uhm...why?", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_asc_2",
|
||||
steps = {
|
||||
{
|
||||
question = "Normann, are you ok? You were doing weird things while typing?",
|
||||
answers = {
|
||||
{ label = "Naw", next_step = 2 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Oh, it's ok, I'm not wathcing you. Noone really is. *giggle*",
|
||||
answers = {
|
||||
{ label = "Huh ?", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_3",
|
||||
steps = {
|
||||
{
|
||||
question = "You look so happy, did you catch a bull or something?",
|
||||
answers = {
|
||||
{ label = "What do you mean?", next_step = 2 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Most people catch colds! You are so strange!",
|
||||
answers = {
|
||||
{ label = "An apple a day keeps the cold away", next_step = 3 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "You look like you don't really want to work today, are you ok?",
|
||||
answers = {
|
||||
{ label = "Oh brother", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
Discussion.register({
|
||||
id = "coworker_disc_asc_3",
|
||||
steps = {
|
||||
{
|
||||
question = "Normal, you should take a break, you don't live up to your name today",
|
||||
answers = {
|
||||
{ label = "Norman is the name ...", next_step = 2 },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "You aren't as enthusiastic as you were before!",
|
||||
answers = {
|
||||
{ label = "Burnout comes for everyone", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
Discussion.register({
|
||||
id = "sumphore_day_3",
|
||||
id = "sumphore_disc_asc_1",
|
||||
steps = {
|
||||
{
|
||||
question = "Are you still seeking the ox?",
|
||||
@@ -17,6 +17,74 @@ Discussion.register({
|
||||
},
|
||||
})
|
||||
|
||||
Discussion.register({
|
||||
id = "sumphore_disc_asc_2",
|
||||
steps = {
|
||||
{
|
||||
question = "How's work? Your face looks strange",
|
||||
answers = {
|
||||
{ label = "I just really need to take a break.", next_step = 2 },
|
||||
{ label = "Not sure what you mean.", next_step = nil },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Are you seeing things?",
|
||||
answers = {
|
||||
{ label = "How did you know ?", next_step = 3 },
|
||||
{ label = "I'm not sure what you mean.", next_step = nil },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Come have a drink, I could tell you some stories.",
|
||||
answers = {
|
||||
{ label = "No, drink makes you stupid and I need to be in top shape.", next_step = 4, on_select = function()
|
||||
Meter.add("ism", 10)
|
||||
end },
|
||||
{ label = "I could use a drink.", next_step = nil, on_select = function()
|
||||
Meter.add("bm", 10)
|
||||
end },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Always trying to do the right thing, huh? What if you did the left thing instead?",
|
||||
answers = {
|
||||
{ label = "I've never thought of that up till now.", next_step = nil, on_select = function()
|
||||
Meter.add("ism", 5)
|
||||
end },
|
||||
{ label = "Silly wordgames, I like them.", next_step = nil, on_select = function()
|
||||
Meter.add("wpm", 10)
|
||||
end },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Discussion.register({
|
||||
id = "sumphore_disc_asc_3",
|
||||
steps = {
|
||||
{
|
||||
question = "Do you think it's work you're doing?",
|
||||
answers = {
|
||||
{ label = "... that sounds like it's from a movie.", next_step = 2 },
|
||||
{ label = "Are you drunk, old man?", next_step = nil },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "You might just be trying too hard, why dont you just flow for a while?",
|
||||
answers = {
|
||||
{ label = "Flow where ?", next_step = 3 },
|
||||
{ label = "I'm not sure what you mean.", next_step = nil },
|
||||
},
|
||||
},
|
||||
{
|
||||
question = "Flow carelessly, without any effort",
|
||||
answers = {
|
||||
{ label = "Consuming sth other than alcohol ?", next_step = nil },
|
||||
{ label = "Deja vu", next_step = nil },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Discussion.register({
|
||||
id = "homeless_guy",
|
||||
@@ -46,7 +114,9 @@ Discussion.register({
|
||||
{
|
||||
question = "My name is Sumphore, nice to meet you.",
|
||||
answers = {
|
||||
{ label = "Nice to meet you, Sumphore.", next_step = 5 },
|
||||
{ label = "Nice to meet you, Sumphore.", next_step = 5, on_select = function()
|
||||
Context.have_met_sumphore = true
|
||||
end },
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
169
inc/init/init.ascension.lua
Normal file
169
inc/init/init.ascension.lua
Normal file
@@ -0,0 +1,169 @@
|
||||
--- @section Ascension
|
||||
local ASCENSION_MAX_LEVEL = 9
|
||||
local ASCENSION_WORD = "ASCENSION"
|
||||
local _increased_this_cycle = false
|
||||
|
||||
local _flash_active = false
|
||||
local _flash_timer = 0
|
||||
local _flash_total = 0
|
||||
local FLASH_DURATION = 120
|
||||
|
||||
local _fade_active = false
|
||||
local _fade_timer = 0
|
||||
local FADE_DURATION = 120
|
||||
local FADE_COLORS = nil
|
||||
|
||||
--- Gets initial ascension state.
|
||||
--- @within Ascension
|
||||
--- @return result table Initial ascension state. </br>
|
||||
--- Fields: </br>
|
||||
--- * level (number) Current ascension level (0-9).
|
||||
function Ascension.get_initial()
|
||||
_increased_this_cycle = false
|
||||
return {
|
||||
level = 0,
|
||||
}
|
||||
end
|
||||
|
||||
--- Gets the current ascension level.
|
||||
--- @within Ascension
|
||||
--- @return number The current ascension level (0-9).
|
||||
function Ascension.get_level()
|
||||
if not Context or not Context.ascension then return 0 end
|
||||
return Context.ascension.level
|
||||
end
|
||||
|
||||
--- Gets the maximum ascension level.
|
||||
--- @within Ascension
|
||||
--- @return number The maximum ascension level.
|
||||
function Ascension.get_max_level()
|
||||
return ASCENSION_MAX_LEVEL
|
||||
end
|
||||
|
||||
--- Increases the ascension level by 1, clamped to the max.
|
||||
--- @within Ascension
|
||||
function Ascension.increase()
|
||||
if not Context or not Context.ascension then return end
|
||||
Context.ascension.level = math.min(ASCENSION_MAX_LEVEL, Context.ascension.level + 1)
|
||||
_increased_this_cycle = true
|
||||
end
|
||||
|
||||
--- Returns true if ascension was incremented since the last consume call.
|
||||
--- @within Ascension
|
||||
--- @return boolean Whether ascension increased this cycle.
|
||||
function Ascension.did_increase()
|
||||
return _increased_this_cycle
|
||||
end
|
||||
|
||||
--- Consumes the increase flag, returning its value and resetting it.
|
||||
--- @within Ascension
|
||||
--- @return boolean Whether ascension had increased this cycle.
|
||||
function Ascension.consume_increase()
|
||||
local result = _increased_this_cycle
|
||||
_increased_this_cycle = false
|
||||
return result
|
||||
end
|
||||
|
||||
--- Returns true when the ascension meter is fully complete (level 10).
|
||||
--- @within Ascension
|
||||
--- @return boolean Whether the cycle can be broken.
|
||||
function Ascension.is_complete()
|
||||
return Ascension.get_level() >= ASCENSION_MAX_LEVEL
|
||||
end
|
||||
|
||||
--- Draws the ascension meter as individual letters of "ASCENSION".
|
||||
--- Each letter lights up per level. Drawn beneath existing meter bars.
|
||||
--- @within Ascension
|
||||
--- @param x number Left x position.
|
||||
--- @param y number Top y position.
|
||||
--- @param options table Optional overrides: lit_color, dim_color, spacing.
|
||||
function Ascension.draw(x, y, options)
|
||||
if not Context or not Context.ascension then return end
|
||||
options = options or {}
|
||||
local level = Context.ascension.level
|
||||
if level < 1 then return end
|
||||
local lit_color = options.lit_color or Config.colors.white
|
||||
local spacing = options.spacing or 5
|
||||
|
||||
for i = 1, level do
|
||||
local ch = ASCENSION_WORD:sub(i, i)
|
||||
local color
|
||||
if i == level and _fade_active then
|
||||
color = Ascension.get_fade_color()
|
||||
else
|
||||
color = lit_color
|
||||
end
|
||||
Print.text_contour(ch, x + (i - 1) * spacing, y, color, false, 1)
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns the current fade-in color based on progress through the palette.
|
||||
--- @within Ascension
|
||||
--- @return number The palette color index for the current fade step.
|
||||
function Ascension.get_fade_color()
|
||||
if not FADE_COLORS then
|
||||
FADE_COLORS = {
|
||||
Config.colors.black,
|
||||
Config.colors.dark_grey,
|
||||
Config.colors.light_grey,
|
||||
Config.colors.white,
|
||||
}
|
||||
end
|
||||
if not _fade_active then return Config.colors.white end
|
||||
local progress = math.min(_fade_timer / FADE_DURATION, 1)
|
||||
local idx = math.floor(progress * (#FADE_COLORS - 1)) + 1
|
||||
return FADE_COLORS[idx]
|
||||
end
|
||||
|
||||
--- Starts the fade-in effect for the most recently gained letter.
|
||||
--- @within Ascension
|
||||
function Ascension.start_fade()
|
||||
_fade_active = true
|
||||
_fade_timer = 0
|
||||
end
|
||||
|
||||
--- Starts the ascension flash effect.
|
||||
--- @within Ascension
|
||||
function Ascension.start_flash()
|
||||
_flash_active = true
|
||||
_flash_timer = 0
|
||||
_flash_total = FLASH_DURATION
|
||||
end
|
||||
|
||||
--- Updates and draws the ascension flash overlay.
|
||||
--- Call once per frame from the main loop.
|
||||
--- @within Ascension
|
||||
function Ascension.draw_flash()
|
||||
if not _flash_active then return end
|
||||
_flash_timer = _flash_timer + 1
|
||||
|
||||
local sw = Config.screen.width
|
||||
local sh = Config.screen.height
|
||||
|
||||
local progress = _flash_timer / FLASH_DURATION
|
||||
local pulse = math.abs(math.sin(progress * math.pi * 6))
|
||||
local flash_color = (pulse > 0.5) and Config.colors.white or Config.colors.light_grey
|
||||
rect(0, 0, sw, sh, flash_color)
|
||||
|
||||
if _flash_timer >= _flash_total then
|
||||
_flash_active = false
|
||||
Ascension.start_fade()
|
||||
end
|
||||
end
|
||||
|
||||
--- Updates the fade-in timer. Call once per frame from the main loop.
|
||||
--- @within Ascension
|
||||
function Ascension.update_fade()
|
||||
if not _fade_active then return end
|
||||
_fade_timer = _fade_timer + 1
|
||||
if _fade_timer >= FADE_DURATION then
|
||||
_fade_active = false
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns whether a flash effect is currently active.
|
||||
--- @within Ascension
|
||||
--- @return boolean Whether the flash is playing.
|
||||
function Ascension.is_flashing()
|
||||
return _flash_active
|
||||
end
|
||||
@@ -17,7 +17,9 @@ function Config.initial_data()
|
||||
blue = 3,
|
||||
white = 4,
|
||||
item = 7,
|
||||
meter_bg = 1
|
||||
meter_bg = 1,
|
||||
transparent = 12,
|
||||
orange = 7
|
||||
},
|
||||
timing = {
|
||||
minigame_win_duration = 180
|
||||
|
||||
@@ -17,12 +17,18 @@ Context = {}
|
||||
--- * minigame_button_mash (table) Button mash minigame state (see Minigame.get_default_button_mash).<br/>
|
||||
--- * minigame_rhythm (table) Rhythm minigame state (see Minigame.get_default_rhythm).<br/>
|
||||
--- * meters (table) Meter values (see Meter.get_initial).<br/>
|
||||
--- * ascension (table) Ascension meter state (see Ascension.get_initial).<br/>
|
||||
--- * triggers (table) Active trigger runtime state, keyed by trigger ID.<br/>
|
||||
--- * stat_screen_active (boolean) Whether the stat screen overlay is currently shown.<br/>
|
||||
--- * game (table) Current game progress state. Contains: `current_screen` (string) active screen ID, `current_situation` (string|nil) active situation ID.<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_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/>
|
||||
function Context.initial_data()
|
||||
return {
|
||||
current_menu_item = 1,
|
||||
test_mode = false,
|
||||
mouse_trace = false,
|
||||
popup = {
|
||||
show = false,
|
||||
content = {}
|
||||
@@ -33,14 +39,22 @@ function Context.initial_data()
|
||||
minigame_button_mash = {},
|
||||
minigame_rhythm = {},
|
||||
meters = Meter.get_initial(),
|
||||
ascension = Ascension.get_initial(),
|
||||
timer = Timer.get_initial(),
|
||||
triggers = {},
|
||||
home_norman_visible = false,
|
||||
have_been_to_office = false,
|
||||
have_done_work_today = false,
|
||||
should_ascend = false,
|
||||
have_met_sumphore = false,
|
||||
office_sprites = {},
|
||||
walking_to_office_sprites = {},
|
||||
game = {
|
||||
current_screen = "home",
|
||||
current_situation = nil,
|
||||
},
|
||||
day_count = 1,
|
||||
delta_time = 0,
|
||||
last_frame_time = 0,
|
||||
glitch = {
|
||||
enabled = false,
|
||||
state = "active",
|
||||
@@ -85,13 +99,19 @@ function Context.new_game()
|
||||
Context.game_in_progress = true
|
||||
MenuWindow.refresh_menu_items()
|
||||
Screen.get_by_id(Context.game.current_screen).init()
|
||||
MysteriousManWindow.start({
|
||||
MysteriousManScreen.start({
|
||||
text = [[
|
||||
Norman was never a bad
|
||||
simulation engineer, but
|
||||
we need to be careful in
|
||||
letting him improve. We
|
||||
need to distract him.
|
||||
|
||||
simulation engineer,
|
||||
|
||||
but
|
||||
|
||||
we need to be careful
|
||||
|
||||
letting him improve.
|
||||
|
||||
We need to distract him.
|
||||
]],
|
||||
on_text_complete = function()
|
||||
Audio.sfx_alarm()
|
||||
@@ -105,8 +125,7 @@ function Context.new_game()
|
||||
instruction_text = "Wake up Norman!",
|
||||
show_progress_text = false,
|
||||
on_win = function()
|
||||
Audio.music_play_wakingup()
|
||||
Context.home_norman_visible = true
|
||||
Audio.music_play_room_work()
|
||||
Meter.show()
|
||||
Window.set_current("game")
|
||||
end,
|
||||
|
||||
@@ -3,12 +3,12 @@ Util = {}
|
||||
Meter = {}
|
||||
Minigame = {}
|
||||
Decision = {}
|
||||
Situation = {}
|
||||
Screen = {}
|
||||
Map = {}
|
||||
UI = {}
|
||||
Print = {}
|
||||
Input = {}
|
||||
Mouse = {}
|
||||
Sprite = {}
|
||||
Audio = {}
|
||||
Focus = {}
|
||||
@@ -16,4 +16,7 @@ Day = {}
|
||||
Timer = {}
|
||||
Trigger = {}
|
||||
Discussion = {}
|
||||
RLE = {}
|
||||
AsciiArt = {}
|
||||
Ascension = {}
|
||||
MysteriousManScreen = {}
|
||||
|
||||
@@ -5,6 +5,9 @@ local _day_increase_handlers = {}
|
||||
--- @within Day
|
||||
function Day.increase()
|
||||
Context.day_count = Context.day_count + 1
|
||||
if Context.day_count == 3 then
|
||||
Context.should_ascend = true
|
||||
end
|
||||
for _, handler in ipairs(_day_increase_handlers) do
|
||||
handler()
|
||||
end
|
||||
@@ -23,3 +26,10 @@ Day.register_handler(function()
|
||||
m.wpm = math.max(0, m.wpm - METER_DECAY_PER_DAY)
|
||||
m.bm = math.max(0, m.bm - METER_DECAY_PER_DAY)
|
||||
end)
|
||||
|
||||
Day.register_handler(function()
|
||||
if Context.should_ascend then
|
||||
Ascension.increase()
|
||||
end
|
||||
Context.should_ascend = false
|
||||
end)
|
||||
@@ -37,15 +37,18 @@ end
|
||||
--- @within Discussion
|
||||
--- @param id string The discussion ID to start.
|
||||
--- @param return_window string The window ID to return to after the discussion.
|
||||
function Discussion.start(id, return_window)
|
||||
--- @param[opt] start_step number The step index to start from (defaults to 1).
|
||||
function Discussion.start(id, return_window, start_step)
|
||||
local discussion = _discussions[id]
|
||||
if not discussion then
|
||||
trace("Error: Discussion not found: " .. tostring(id))
|
||||
return
|
||||
end
|
||||
local step = start_step or 1
|
||||
if not discussion.steps[step] then step = 1 end
|
||||
Context.discussion.active = true
|
||||
Context.discussion.id = id
|
||||
Context.discussion.step = 1
|
||||
Context.discussion.step = step
|
||||
Context.discussion.selected_answer = 1
|
||||
Context.discussion.scroll_y = 0
|
||||
Context.discussion.scroll_timer = 0
|
||||
|
||||
@@ -8,10 +8,11 @@ local COMBO_MAX_BONUS = 0.16
|
||||
local COMBO_TIMEOUT_FRAMES = 600
|
||||
|
||||
-- Internal meters for tracking game progress and player stats.
|
||||
Meter.COLOR_ISM = Config.colors.red
|
||||
Meter.COLOR_ISM = Config.colors.orange
|
||||
Meter.COLOR_WPM = Config.colors.blue
|
||||
Meter.COLOR_BM = Config.colors.black
|
||||
Meter.COLOR_BM = Config.colors.red
|
||||
Meter.COLOR_BG = Config.colors.meter_bg
|
||||
Meter.COLOR_CONTOUR = Config.colors.white
|
||||
|
||||
--- Gets initial meter values.
|
||||
--- @within Meter
|
||||
@@ -126,16 +127,16 @@ function Meter.draw()
|
||||
|
||||
local m = Context.meters
|
||||
local max = Meter.get_max()
|
||||
local bar_w = 44
|
||||
local screen_w = Config.screen.width
|
||||
local screen_h = Config.screen.height
|
||||
local bar_w = screen_w * 0.25
|
||||
local bar_h = 2
|
||||
local bar_x = 182
|
||||
local label_x = 228
|
||||
local line_h = 5
|
||||
local start_y = 1
|
||||
local edge = math.max(2, math.floor(screen_w * 0.03))
|
||||
local bar_x = screen_w - bar_w - edge
|
||||
local line_h = 3
|
||||
local start_y = screen_h * 0.05
|
||||
|
||||
|
||||
local bar_offset = math.floor((line_h - bar_h) / 2)
|
||||
|
||||
local meter_list = {
|
||||
{ key = "wpm", label = "WPM", color = Meter.COLOR_WPM, row = 0 },
|
||||
{ key = "ism", label = "ISM", color = Meter.COLOR_ISM, row = 1 },
|
||||
@@ -144,12 +145,16 @@ function Meter.draw()
|
||||
|
||||
for _, meter in ipairs(meter_list) do
|
||||
local label_y = start_y + meter.row * line_h
|
||||
local bar_y = label_y + bar_offset
|
||||
local bar_y = label_y
|
||||
local fill_w = math.max(0, math.floor((m[meter.key] / max) * bar_w))
|
||||
rect(bar_x - 1, bar_y - 1, bar_w + 2, bar_h + 2, Meter.COLOR_CONTOUR)
|
||||
rect(bar_x, bar_y, bar_w, bar_h, Meter.COLOR_BG)
|
||||
if fill_w > 0 then
|
||||
rect(bar_x, bar_y, fill_w, bar_h, meter.color)
|
||||
end
|
||||
print(meter.label, label_x, label_y, meter.color, false, 1, true)
|
||||
---print(meter.label, label_x, label_y, meter.color, false, 1, true)
|
||||
end
|
||||
|
||||
local ascension_y = start_y + 3 * line_h + 1
|
||||
Ascension.draw(bar_x, ascension_y, { spacing = 8 })
|
||||
end
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
|
||||
--- Draws a unified win message overlay.
|
||||
--- @within Minigame
|
||||
function Minigame.draw_win_overlay()
|
||||
local text = "SUCCESS"
|
||||
local tw = #text * 4
|
||||
function Minigame.draw_win_overlay(win_text)
|
||||
local text = win_text or "SUCCESS"
|
||||
local tw = #text * 6
|
||||
local th = 6
|
||||
local padding = 4
|
||||
local box_w = tw + padding * 2
|
||||
local box_h = th + padding * 2
|
||||
local box_x = (Config.screen.width - box_w) / 2
|
||||
local box_y = (Config.screen.height - box_h) / 2
|
||||
|
||||
local text_x = Config.screen.width / 2
|
||||
rect(box_x, box_y, box_w, box_h, Config.colors.dark_grey)
|
||||
rectb(box_x, box_y, box_w, box_h, Config.colors.white)
|
||||
Print.text_center(text, Config.screen.width / 2, box_y + padding, Config.colors.white)
|
||||
Print.text_center_contour(text, text_x, box_y + padding, Config.colors.black, false, 1, Config.colors.white)
|
||||
end
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ function Timer.update()
|
||||
if not in_minigame then
|
||||
t.progress = t.progress + (1 / timer_duration)
|
||||
if t.progress >= 1 then
|
||||
Day.increase()
|
||||
t.progress = t.progress - 1
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- 000:0404005f574fc2c3c71d2b53fff1e8ab52367e2553ffa30000875129adff83769c00e436fa77a8ff004dc3c3c7ffccaa
|
||||
-- </PALETTE>
|
||||
-- <TILES>
|
||||
-- 000:00000000c666666006606060c636366006606060c606366006666660c0000000
|
||||
-- 000:0000000006666660066060600636366006606060060636600666666000000000
|
||||
-- 001:0000000006666666060600600666666606000600066666660633633300000000
|
||||
-- 002:0000000066666666006000066666666660060006666666666333363300000000
|
||||
-- 004:1111111111111111111111111111111111111111111111111111111111111111
|
||||
@@ -17,7 +17,7 @@
|
||||
-- 013:1000000004444444044444440444444404444444044444440444444404444444
|
||||
-- 014:0000000144444240444424204444424044442420444442404444242044444240
|
||||
-- 015:0000000004244444024444440424400002444444042424240242424200000000
|
||||
-- 016:000000004444442044444240c004442044444240e424242042424240c0000000
|
||||
-- 016:0000000044444420444442400004442044444240e42424204242424000000000
|
||||
-- 017:0000000002424240042424200244444004244440024404400424044002440440
|
||||
-- 018:0000000002424240042424200444424004444420044042400440442004404240
|
||||
-- 019:0222222200010012055016020150660205501602015066020550160200000000
|
||||
@@ -33,7 +33,7 @@
|
||||
-- 029:0440442004404240044044200444424004444420024242400424242000000000
|
||||
-- 030:0000000006666660036060600360666006606060036660600360666003606060
|
||||
-- 031:0222222200010010033033030130130103303303013013010330330300000000
|
||||
-- 032:22222220c10012203033022030130220303302203013022030330220c0000000
|
||||
-- 032:2222222001001220303302203013022030330220301302203033022000000000
|
||||
-- 033:0333011103330111033301110333011103330111033301110333011100000000
|
||||
-- 034:1110011111100111111001111110011111100111111001111110011100000000
|
||||
-- 035:1110333011103330111033301110333011103330111033301110333000000000
|
||||
@@ -49,7 +49,7 @@
|
||||
-- 045:2222222022222220222222202222222022222220000000001111100011111000
|
||||
-- 046:1111111111111111111111111000000002222222022222220222222202222222
|
||||
-- 047:1111111111111111111111110000000022222222222222222222222222222222
|
||||
-- 048:111111111111111111111111c000100022220444e222044422220444e2220444
|
||||
-- 048:1111111111111111111111110000100022220444e222044422220444e2220444
|
||||
-- 049:1111111111111111111111111100001100222201022222200222222002222220
|
||||
-- 050:1111111011111110111111101111111011111110111111101111111011110000
|
||||
-- 051:1111111111111111111111111111111111111111111111111111111100011111
|
||||
@@ -81,7 +81,7 @@
|
||||
-- 077:0000000011111110000000006611166655555551555555515555555166666111
|
||||
-- 078:1111111111111111111100001110919111101010110191011019191000919190
|
||||
-- 079:1111111111111111000000009191919000000010111110901111101000000090
|
||||
-- 080:09191990c991990209199020c999020209902020c902020200202020c0000000
|
||||
-- 080:0919199009919902091990200999020209902020090202020020202000000000
|
||||
-- 081:0000000002020200202020200200022020002220000222202022222002222220
|
||||
-- 082:5555555555555055555501056666010155550105555501055555010566610106
|
||||
-- 083:5555555555555555000000000222222202222222022222220222222202222222
|
||||
@@ -97,7 +97,7 @@
|
||||
-- 093:0222022002220220022202200222022002220220022202200222022002220220
|
||||
-- 094:1033330110333301103333011033330110333301103333011033330110000001
|
||||
-- 095:3333101033331090333310103333109011113010111130901111301011113000
|
||||
-- 096:00000000c111111100000000c106666601051555c105155501056555c0066611
|
||||
-- 096:0000000001111111000000000106666601051555010515550105655500066611
|
||||
-- 097:0000000011111110000000006666101055555010555550105555501066616000
|
||||
-- 098:5555555555555550555555056666116655550055555500555555655566666611
|
||||
-- 099:0555555500555555050555550661111105500555115005550055555500616666
|
||||
@@ -113,7 +113,7 @@
|
||||
-- 109:1111111011111110111111101111111011111110111111100000000566000066
|
||||
-- 110:1111111111111111111111111111010011101044111010441110104400000010
|
||||
-- 111:1111111111111111111111110011111144011111440111114401111110000000
|
||||
-- 112:11111111111111111111111111111111111111111111111111110111c0004000
|
||||
-- 112:1111111111111111111111111111111111111111111111111111011100004000
|
||||
-- 113:3333104433331044333310003333111111113333111133331111333311113333
|
||||
-- 114:4403111144031111000311113333111111110000111044441104444411014444
|
||||
-- 115:3304440133044401330444013304440100104033440103334440333344103333
|
||||
@@ -177,7 +177,7 @@
|
||||
-- 173:0333333010333330103333301033333010333330100000001111111111111111
|
||||
-- 174:111111111111111111111111111111111111111112222222a1a1a1a21a1a1a12
|
||||
-- 175:1111111111111111111111111111111111111111444444444444444444444444
|
||||
-- 176:00000000c111111001101010c131311001101010c101311001111110c0000000
|
||||
-- 176:0000000001111110011010100131311001101010010131100111111000000000
|
||||
-- 177:0000000001111111010100100111111101000100011111110133133300000000
|
||||
-- 178:0000000011111111001000011111111110010001111111111333313300000000
|
||||
-- 179:11111111111111111111111111111111111100001110b161110b100010810101
|
||||
@@ -225,7 +225,7 @@
|
||||
-- 221:0200000002000000020000000200000002000000020000000211111100000000
|
||||
-- 222:0000000000000000000000000000000000000000000000001111111100000000
|
||||
-- 223:000000000000000000000000000000000000000000000000111dd11100000000
|
||||
-- 224:00000010c000001000000010c000001000000010c000001011111110c0000000
|
||||
-- 224:0000001000000010000000100000001000000010000000101111111000000000
|
||||
-- 225:3333333333333333333333333333333313131313313131311313131331313131
|
||||
-- 226:0203333302033333020333330203333302031313020131310203131300013131
|
||||
-- 227:3333302033333020333330203333302013131020313130201313102031313000
|
||||
@@ -241,7 +241,7 @@
|
||||
-- 237:1444402044140220444402204144022000402220220222200222222010222220
|
||||
-- 238:3333330033333022333302223333022213130222313102221313101231313100
|
||||
-- 239:0003010322200103222201032222010322220103222201012210101300013131
|
||||
-- 240:02220111c222001102220000c222033302220333c222200002222222c2222222
|
||||
-- 240:0222011102220011022200000222033302220333022220000222222202222222
|
||||
-- 241:1002222001202220002022203002222031222220022222202222222022222220
|
||||
-- 242:3333333333333330333333033333113313130013313100311313131331313131
|
||||
-- 243:0333333300333333030333330331133303100313113001310013131300313131
|
||||
@@ -251,28 +251,262 @@
|
||||
-- 247:0000000011111110000000003333301013131010313130101313101031313000
|
||||
-- </TILES>
|
||||
-- <SPRITES>
|
||||
-- 002:00000000000000000000444400044444000444440044ffff004fffff004f3333
|
||||
-- 003:0000000000000000441600004242600044241000ff426000fff4100033f26000
|
||||
-- 004:00000333000035550003655500365555003555ff00356fff00365f3f00355fff
|
||||
-- 005:33000000553000005563000055563000ff553000fff53000f3f63000fff53000
|
||||
-- 016:0000000000000000000000000000003000000353000035350003535100353535
|
||||
-- 017:0000000000000000000000003000000053300000151300005151300015151300
|
||||
-- 018:004f99ff000fffff0000ff3300000fff00003666000355550035652503163555
|
||||
-- 019:99f41000fff26000ff600000f600000063300000555330005555530055535530
|
||||
-- 020:00356f6f003655f60365511f3653122f3531222f363221220532232203322322
|
||||
-- 021:f6f530006f563000f1156300f2215300f2226300221233002232130022121300
|
||||
-- 032:0033535100353533003351ff00351f3f0003ff3f0003ffff00003ff3000323ff
|
||||
-- 033:5555530033555300ff155300f3f15300f3ff3000ffff30003ff30000ff323000
|
||||
-- 034:036135250316355503613525031633110333331103f333330333333300033333
|
||||
-- 035:55565530555355305556553013335530133333303333ff303333333033330000
|
||||
-- 036:00322322003223330033331a003ff31a003ff3a1003333a100003a1a00003a1a
|
||||
-- 037:223213003332130011133300111f300011133000111300001113000011130000
|
||||
-- 048:00323123003231430032314300313339000f3333000033300000333000033330
|
||||
-- 049:324303003443030034430300933313003333f000033300000333000003333000
|
||||
-- 050:0003333000033330000333300003333000053530003311300031113000333330
|
||||
-- 051:3333000033330000333300003333000035350000311330003111300033333000
|
||||
-- 052:000031a1000031a100003a1a00003a1a00003333000003f3000003f300000330
|
||||
-- 053:111300001113000011130000111300003333000003f3000003f3000003300000
|
||||
-- 000:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 001:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 002:cccccccccccc0000ccc04444cc044444cc044444c044ffffc04fffffc04f3333
|
||||
-- 003:cccccccc0000cccc44160ccc424260cc442410ccff4260ccfff410cc00f260cc
|
||||
-- 004:ccccc000cccc0555ccc06555cc065555cc0555ffcc056fffcc065f0fcc055fff
|
||||
-- 005:00cccccc550ccccc5560cccc55560cccff550cccfff50cccf0f60cccfff50ccc
|
||||
-- 006:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 007:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 008:cccc0000ccc05a55ccc055a5ccc0a55accc05a57ccc05533cc0575f3ccc0757f
|
||||
-- 009:00000ccca55a50cc5a55a0cc5755550cfff7a50c3f335a0cfff3f50cfffffa0c
|
||||
-- 010:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 011:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 012:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 013:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 014:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 015:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 016:cccccccccccccccccccccccccccccc0cccccc050cccc0535ccc05351cc053535
|
||||
-- 017:cccccccccccccccccccccccc0ccccccc500ccccc1510cccc51510ccc151510cc
|
||||
-- 018:c04f99ffcc0fffffccc0ff00cccc0fffcccc0666ccc05555cc056525c0160555
|
||||
-- 019:99f410ccfff260ccff600cccf60ccccc600ccccc55500ccc555550cc5550550c
|
||||
-- 020:cc056f6fcc0655f6c065511f0650122f0501222f06022122c5022322c0022322
|
||||
-- 021:f6f50ccc6f560cccf11560ccf22150ccf22260cc221230cc223210cc221210cc
|
||||
-- 022:cccccc00ccccc051cccc0155ccc05515ccc0157fccc05513cc057f0fcc017fff
|
||||
-- 023:000ccccc5550cccc51550ccc155150ccff7f510cff31f20cfff0ff0c00fff20c
|
||||
-- 024:cccc057fccccc005cccc0555ccc05599cc055911c0559911c0551199c0551199
|
||||
-- 025:f3ff50ccfff50ccc5f50cccc441500cc7799510c4499150c7711955044119550
|
||||
-- 026:ccccc000ccc00133cc013313cc031333c0133333c031f7f7c0113339c031999f
|
||||
-- 027:0000cccc13310ccc131330cc3333130c3333310cf7f1130c3337310c9997530c
|
||||
-- 028:ccccccccccccc000cccc0a77ccc05777cc057777c0577777c05775a5c077a7ff
|
||||
-- 029:cccccccc0000cccc777a0ccc777750cc7777750c77777750a5a57750fff7a770
|
||||
-- 030:ccccc000cccc0515ccc01151cc055555cc01517fcc0557ffcc01ff0fcc07ff1f
|
||||
-- 031:00cccccc150ccccc5110cccc5550ccccf7110cccff750cccf0f10cccf1f50ccc
|
||||
-- 032:cc035351cc053500cc0351ffcc051f0fccc0ff0fccc0ffffcccc0ff0ccc020ff
|
||||
-- 033:555550cc005550ccff1550ccf0f150ccf0ff0cccffff0ccc0ff0ccccff020ccc
|
||||
-- 034:c0613525c0163555c0613525c0163311c0003311c0f03333cc003333ccc03333
|
||||
-- 035:5556550c5553550c5556550c1330550c1330000c3330ff0c333000cc3330cccc
|
||||
-- 036:cc022322cc022333cc03331acc0ff31acc0ff3a1ccc003a1cccc0a1acccc0a1a
|
||||
-- 037:223210cc333210cc111300cc111f0ccc11100ccc1110cccc1110cccc1110cccc
|
||||
-- 038:ccc007ffcc01117fc016171f0155175501561755055117550f7157550ff15755
|
||||
-- 039:fffff70c000f20ccffff710c555571105555716055557110555575f0555575f0
|
||||
-- 040:c0559911c0559911c0ff5333c0fff511c07fff11cc07f511ccc03110cccc0110
|
||||
-- 041:479915504499155047333f7014113ff011113f701111000c00110cccc0110ccc
|
||||
-- 042:c035777fcc017766ccc05777cc088855c08bb85508bbb84508bbb8440bb8b844
|
||||
-- 043:7777530c677500cc7750cccc55880ccc558b80cc548bb80c228bbb80428b8b80
|
||||
-- 044:cc0a7f3fc075ff3f0777ffff07757fdf077a57fd0575357fc05a66a7cc06aa6f
|
||||
-- 045:ff3f7a0cff3ff70cfffff770ffdf7570ddf75a70ff75157077a66a50ff6aa60c
|
||||
-- 046:cc05ffffccc05ff3cccc05ffcc007755c0242777c0212171c0242771c0212171
|
||||
-- 047:fff50ccc3f50ccccf50ccccc5770cccc77720ccc17120ccc17720ccc17120ccc
|
||||
-- 048:cc020123cc020143cc020143cc010309cc0f0300ccc0030ccccc030cccc0000c
|
||||
-- 049:324030cc344030cc344030cc903010cc0030f0ccc0300cccc030ccccc0000ccc
|
||||
-- 050:ccc0330cccc0330cccc0330cccc0330cccc0350ccc03110ccc01110ccc00000c
|
||||
-- 051:0330cccc0330cccc0330cccc0330cccc0530cccc01130ccc01110ccc00000ccc
|
||||
-- 052:cccc01a1cccc01a1cccc0a1acccc0a1acccc0000ccccc0f0ccccc0f0ccccc00c
|
||||
-- 053:1110cccc1110cccc1110cccc1110cccc0000ccccc0f0ccccc0f0ccccc00ccccc
|
||||
-- 054:0ff7646607f59999c0099100cc03990ccc09910ccc01330ccc01220ccc0000cc
|
||||
-- 055:666646f0999993f00099100cc03990ccc09910ccc01330ccc01220ccc0000ccc
|
||||
-- 056:cccc0110cccc0110cccc0110cccc0110cccc0110cccc0330cccc0650cccc0000
|
||||
-- 057:c0110cccc0110cccc0110cccc0110cccc0110cccc0330cccc0650cccc0000ccc
|
||||
-- 058:0888b8440f78b8440f58884405031300c0c0310cccc0130cccc0350cccc0000c
|
||||
-- 059:218b8880428b87f0218885f000130050c0310c0cc0130cccc0350cccc0000ccc
|
||||
-- 060:c056aa66c01f6aaac01fa666c07f6aaacc0f6aaaccc0a666cccc07d7cccc0000
|
||||
-- 061:666aa650aaaa6f106666af10aaaa6f70aaaa600c6666a0cc007d70cccc0000cc
|
||||
-- 062:c0242777c0ff6111c0fff333c05f5333cc003300cccc030ccccc030ccccc000c
|
||||
-- 063:77720ccc116f0ccc335ff0cc333f0ccc0330cccc030ccccc030ccccc0000cccc
|
||||
-- 064:ccccccccccccc000cccc0111ccc03311cc011117cc03317fcc0117ffc0553333
|
||||
-- 065:cccccccc00cccccc110ccccc1110cccc77110cccff710cccff770ccc13330ccc
|
||||
-- 066:cccccc00ccccc033cccc0333ccc03333ccc033f7ccc035ffcc0535ffcc07f333
|
||||
-- 067:0ccccccc3000cccc33330ccc33330ccc37f30cccffff0cccffff0cccf333f0cc
|
||||
-- 068:ccccccccccccccccccccccccccccccccccccc000cccc0122ccc01244cc01447f
|
||||
-- 069:cccccccccccccccccccccccccccccccc000ccccc2210cccc44210cccf74410cc
|
||||
-- 070:ccccccccccccccccccccc000cccc0888ccc08888cc088880c0838801c038805f
|
||||
-- 071:cccccccccccccccc0000cccc88880ccc880080cc0055080c1666530cf7ff730c
|
||||
-- 072:cccccccccccccc00ccccc055cccc0555ccc05577ccc057ffccc07f55cc0fff33
|
||||
-- 073:cccccccc00000ccc555550cc5555550c77777550ffffff507f755f703f333ff0
|
||||
-- 074:cccccccccccccc00ccccc013cccc0131ccc01313ccc03131cc031377cc0131ff
|
||||
-- 075:cccccccc000ccccc1310cccc31310ccc13130ccc313130ccffff70ccfffff0cc
|
||||
-- 076:cccccccccccccc00ccccc055cccc0555ccc05577ccc057ffcc07ff55cc0fff99
|
||||
-- 077:cccccccc0000cccc55550ccc555550cc7577550cfffff50c5f555f0c3f993f0c
|
||||
-- 078:cccccccccccccccccccccccccccccccccccc0000cccc0444cccc0444cccc0555
|
||||
-- 079:cccccccccccccccccccccccccccccccc000ccccc440ccccc440ccccc550ccccc
|
||||
-- 080:c077500fcc0ff77fcc05fff5ccc05ff7cccc015fccc0f315cc0ff3ffc0ff3333
|
||||
-- 081:f00f0cccf77f0ccc5ff0cccc7f50ccccf50ccccc53f0ccccf3f50ccc333f0ccc
|
||||
-- 082:cc0fff00cc05ffffccc057f5cccc007fccc03335cc01313fc031313303113133
|
||||
-- 083:ff00f0ccffff10cc55f10cccff70cccc5530ccccff310ccc33310ccc333110cc
|
||||
-- 084:cc0447ffcc0fffffcc07f33fcc0ff11fcc0f7fffccc0ff75cccc0424cccc0142
|
||||
-- 085:ff7440ccffff10ccf33f70ccf11f50ccfff7f0cc57ff0ccc4240cccc44110ccc
|
||||
-- 086:c0838039c038803bc0838013c038307fc083805fcc083805ccc08383cccc0333
|
||||
-- 087:9953990cbb33bb0c9951390cfffff50cff66f10c7fff50cc15550ccc33330ccc
|
||||
-- 088:cc0f7ff0ccc05fffcccc07ffccccc07fcccc021fccc02441cc024444c0124244
|
||||
-- 089:fff0ff70f1ffff50fffff70c111f70ccffff10cc1111420c4244442042442410
|
||||
-- 090:cc0f5733cc0f1f23ccc00fffcccc077fccc01117cc024421c0444142c0421444
|
||||
-- 091:ff33f0ccff23f0ccfffff0cc11ff0ccc7770cccc11240ccc444240cc4244140c
|
||||
-- 092:ccc05fffcccc05ffccccc01fcccccc01ccccc014cccc0814ccc01814ccc08114
|
||||
-- 093:fffff50c111f50ccfff50ccc1110cccc42410ccc424180cc424180cc424110cc
|
||||
-- 094:cccc0fffcccc0f3fcccc0f0fcccc0fffccccc0f3cccc0377ccc031ffcc0f1f11
|
||||
-- 095:ff0ccccc3f0ccccc0f0cccccff0cccccf0cccccc730cccccf130cccc1f1f0ccc
|
||||
-- 096:c0ff3333c033133305f333330ff31333033333330f5313330ff1311107f13333
|
||||
-- 097:333f0ccc333f50cc333f50cc333ff0cc333330cc3335f50c111ff50c3337f0cc
|
||||
-- 098:03113133031131330333313303113131033331320555313107ff313307ff3131
|
||||
-- 099:333110cc333110cc333330cc213110cc423330cc21317f0c33317f501131750c
|
||||
-- 100:ccc04414cc044441c0444424c042442404424424044144240441442404414424
|
||||
-- 101:414420cc1444420c424444204244422042444240424441404244414042444140
|
||||
-- 102:ccc03333cc03a353cc02a353cc0a3323c0a23333c02a3333c0a23333c02a3333
|
||||
-- 103:33330ccc553530cc553530cc2232320c3333310c3333320c3333313033333230
|
||||
-- 104:c0144144c0144244c0144144c0144124c017f311c01ff133c01fff33cc07f330
|
||||
-- 105:4244142042442410424414204244122012113f7031333ff033333ff000033f0c
|
||||
-- 106:c0421444c0441444c0421444c0421444c0111111c0ff1a5ac0f755a5c0755a50
|
||||
-- 107:4444140c4244140c4444140c4244140c1111110c5a5a55f0a5a5a5f0001a5170
|
||||
-- 108:ccc01814ccc08114ccc01814ccc08113cc001333c05fff33cc0f7733cc055330
|
||||
-- 109:4241810c4241180c4241810c2223180c1113310c33335ff03333f7700033550c
|
||||
-- 110:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 111:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 112:05533333c0033330ccc0330ccc03330cc03330ccc03330ccc01110ccc0000ccc
|
||||
-- 113:33000ccc030ccccc030ccccc030ccccc030ccccc030ccccc0110cccc0000cccc
|
||||
-- 114:05f53131c0003131c0331131c0111131c0111130cc01110cccc0330cccc0000c
|
||||
-- 115:113110cc113110cc113110cc113110cc003110cccc0110cccc0330cccc0000cc
|
||||
-- 116:0fff242407f72211c0552400cc00240cccc0240cccc0240cccc0220cccc0000c
|
||||
-- 117:424441f0112227f000442550c044200cc04420ccc04420ccc02220ccc00000cc
|
||||
-- 118:0333333307ff333307f73300c070030ccc0c030ccccc030ccccc010ccccc000c
|
||||
-- 119:33333570333331f000033570cc03300ccc030ccccc030ccccc010ccccc0000cc
|
||||
-- 120:ccc00330ccccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc000
|
||||
-- 121:cc0300cccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccc0c0000cc
|
||||
-- 122:c05015a0cc0c0a50cccc05a0cccc0a50cccc05a0cccc0250cccc0990cccc0000
|
||||
-- 123:c015a150cc0a500ccc05a0cccc0a50cccc05a0cccc0250cccc0990cccc0000cc
|
||||
-- 124:ccc00330ccccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc000
|
||||
-- 125:c03000ccc030ccccc030ccccc030ccccc030ccccc030ccccc030ccccc0000ccc
|
||||
-- 126:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 127:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 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
|
||||
-- 162:1333370c3733130c7773130c333331303333313033333150333337f011111750
|
||||
-- 163:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 164:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
-- 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>
|
||||
-- <MAP>
|
||||
-- 000:ffffffffff0010201020102010201020102010201020102000ffffffffff40404040404087f3f3f3f397a7b7c7d7a7e7f70818a7b7c7d7a7b7c7d7a70b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
@@ -285,7 +519,7 @@
|
||||
-- 007:ffffffffffb264748494a4b4c4d46494649464940040e4f4b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 008:ffffffffffe1c30515d325d33545c3d355d3c3d365b17585e1ffffffffff4040404040404098989898404040404040404040404040404040404040407c1e7e8e1e1e1e9eae1ebe1e1e1e1e1e1e1e1e72821ebe1e72821ebe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 009:ffffffffffb264e395a5b594e39564c5d5946494e5b1b1f5b2ffffffffff4040404040404040404040404040404040404040404040404040404040405d1e05151ebe1ecedeeefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 010:ffffffffffe1c306162636d34656c395d5d3c3d376b1b1b1e1ffffffffff404040404040409898989840b9c9c9d9e9f90a0a0a0a4040400a0a0a0a407c1ee395eefe1e0f1f2f3f1e1e1e1e1e1e1e1ee3952f3f1ee3952f3f1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 010:ffffffffffe1c306162636d34656c3e3d5d3c3d376b1b1b1e1ffffffffff404040404040409898989840b9c9c9d9e9f90a0a0a0a4040400a0a0a0a407c1ee395eefe1e0f1f2f3f1e1e1e1e1e1e1e1ee3952f3f1ee3952f3f1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 011:ffffffffffb264946494649464948696a694649410201020b2ffffffffff4040404040404040404040401a2a3a4a5a6a7a40404040404040404040405d1ee3952f3f1e4f5f1ebe1e1e1e1e1e1e1e1ee3951ebe1ee3951ebe1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 012:ffffffffffe1c37282d3c3d3c3d3b6c6d6d3c3d300e6f607e1ffffffffff4040404040404098989898408a9aaabaca9ada40404040404040404040407c1e4f5f1ebe1e0515eefe1e1e1e1e1e1e1e1ee395eefe1ee395eefe1e7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 013:ffffffffffb264e395946494649464946494649465172737b2ffffffffffeaeaeaeaeaeaeafafafafaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaea5d1e0515eefe1e6f7f2f3f1e1e1e1e1e1e1e1e6f7f2f3f1e6f7f2f3f1e5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
@@ -294,26 +528,27 @@
|
||||
-- 016:ffffffffff0010201020766777001020102010201020102000fffffffffff3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f30b1b2b1b2b7667776777761b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- </MAP>
|
||||
-- <SFX>
|
||||
-- 000:060006400600064006000640060006400600060006000600060006000600060006000600060006000600060006000600060006000600060006000600300000000900
|
||||
-- 016:05000500050005400540054005700570057005400540054005700570057005c005c005c005c005c005c005c005c005c005c005c005c005c005c005c0470000000000
|
||||
-- 017:040004000400040004000400046004600460046004600460146024c034c054c064c084c0a4c0b4c0c4c0c4c0d4c0d4c0e4c0f4c0f4c0f4c0f4c0f4c0400000000000
|
||||
-- 018:04c004c004c004c004c004c0046004600460046004600460240034005400640084009400a400b400c400d400d400e400e400e400f400f400f400f400300000000000
|
||||
-- 019:0400040004000400040004d014d014d024d034d054d074d094d0b4d0c4d0e4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0f4d0400000000000
|
||||
-- 016:00000000000000400040004000700070007000400040004000700070007000c000c000c000c000c000c000c000c000c000c000c000c000c000c000c0470000000000
|
||||
-- 017:030003000300030003000300036003600360036003600360136023c033c053c063c083c0a3c0b3c0c3c0c3c0d3c0d3c0e3c0f3c0f3c0f3c0f3c0f3c0400000000000
|
||||
-- 018:03c003c003c003c003c003c0036003600360036003600360230033005300630083009300a300b300c300d300d300e300e300e300f300f300f300f300400000000000
|
||||
-- 019:0300030003000300030003d013d013d023d033d053d073d093d0b3d0c3d0e3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0400000000000
|
||||
-- 020:090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900500000000000
|
||||
-- 021:01000100010001000100f10001100110011001100110f11001200120012001200120f1201130113011302130213021302130313041308130a130d130380000000000
|
||||
-- 032:010001100100011001000110010001100100010001000100010001000100010001000100010001000100010001000100010001000100010001000100301000000800
|
||||
-- 033:000000010002000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d40000000004
|
||||
-- 044:0600f6000620f6000600f6000610f600f600f6000600f600f600f600f6000600060006000600060006000600060006000600060006000600060006004600000f0f00
|
||||
-- 045:0000f0000020f0000000f0000010f000f000f0000000f000f000f000f0000000000000000000000000000000000000000000000000000000000000004600000f0f00
|
||||
-- 021:01000100010001000100f10001100110011001100110f11001200120012001200120f1201130113011302130213021302130313041308130a130d130580000000000
|
||||
-- 022:03b003100300030003000300130063009300b300c300d300d300e300e300e300f300f300f300f300f300f300f300f300f300f300f300f300f300f300400000000000
|
||||
-- 032:010001100100011001000110010001100100010001000100010001000100010001000100010001000100010001000100010001000100010001000100400000000800
|
||||
-- 033:000000010002000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c40000000004
|
||||
-- 034:02000240020002000200020002000200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f2004700000f0200
|
||||
-- 044:0600f6000620f6000600f6000610f600f600f6000600f600f600f600f6000600060006000600060006000600060006000600060006000600060006001600000f0f00
|
||||
-- 045:0000f0000020f0000000f0000010f000f000f0000000f000f000f000f0000000000000000000000000000000000000000000000000000000000000005600000f0f00
|
||||
-- 048:090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900400000000000
|
||||
-- 056:4100510061406140717081709100b100c100d100e100e100e100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f10058a000000600
|
||||
-- 057:000000010002000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d40000000004
|
||||
-- 058:41004110410041104100411041004110c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100500000080800
|
||||
-- 059:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000
|
||||
-- 060:220022002200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200100000000000
|
||||
-- 061:9f009f00bf00df00df00ef00ef00ef00ef00ef00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00400000000000
|
||||
-- 062:00000100010001000100510081008100910091009100a100a100a100a100a100b100b100b100b100c100c100c100d100d100d100e100e100e100f100484000000000
|
||||
-- 063:00b000100000000000000000100060009000b000c000d000d000e000e000e000f000f000f000f000f000f000f000f000f000f000f000f000f000f000200000000000
|
||||
-- 056:4100510061406140717081709100b100c100d100e100e100e100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100480000000600
|
||||
-- 057:000000010002000300020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000000004
|
||||
-- 058:41004110410041104100411041004110c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100003000080800
|
||||
-- 059:03000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030000b000000000
|
||||
-- 060:220022002200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200500000000000
|
||||
-- 061:9f009f00bf00df00df00ef00ef00ef00ef00ef00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00100000000000
|
||||
-- 062:00000100010001000100510081008100910091009100a100a100a100a100a100b100b100b100b100c100c100c100d100d100d100e100e100e100f100580000000000
|
||||
-- 063:00b000100000000000000000100060009000b000c000d000d000e000e000e000f000f000f000f000f000f000f000f000f000f000f000f000f000f000500000000000
|
||||
-- </SFX>
|
||||
-- <WAVES>
|
||||
-- 000:bcceefceedddddc84333121268abaa99
|
||||
@@ -331,10 +566,13 @@
|
||||
-- 000:4008b50000000000000000001008c10000004008b50000001008c1000000000000000000e008b30000004008b50000001008c10000000008c10000000008c10000000000000000000000000000000000000000000000000000000000000000004008b50000000000000000001008c10000004008b50000001008c10000000008c1000000e008b30000004008b50000001008c10000000008c10000000008c10000000008c10000000008c10000000008c1000000000000000000000000000000
|
||||
-- 001:4008b50000000000000000001008c10000004008b50000001008c1000000000000000000e008b30000004008b50000001008c10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007008b50000007008b50000001008c10000007008b50000001008c10000000008c10000007008b50000009008b50000001008c10000009008b50000001008c10000009008b50000009008b50000001008c10000009008b50000001008c1000000
|
||||
-- 003:4008d30000000000000000000000000000000000000000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000004008d30000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000000000000000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000004008d30000004008d9000000000000000000000000000000000000000000
|
||||
-- 004:40088d000000e0088b000000b0088b000881e0088b00000040088d000000e0088b000881b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e00889000000
|
||||
-- 005:400881000000000881000000000881000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000
|
||||
-- 004:43398d000000e0088b000000b0088b000881e0088b00000040088d000000e0088b000881b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e00889000000
|
||||
-- 005:455981000000000881000000000881000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000
|
||||
-- 008:4aa9b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005008b30000000000000000000000000000000000000000000008b10000000000000000000008910000000000000000004008b30000000000000000000000000000000000000000000000000000000000000000000008b1000000000000000000f008b1000000000000000000000000000000000000000000000891000000000000000000000000000000000000000000
|
||||
-- 009:4779d30000000000000000004008d30000000000000000004008db0000000000000000004008d30000000000000000004008d30000000000000000004008d30000000000000000004008db0000000000000000004008d30000000000000000004008d30000000000000000004008d30000000000000000004008db0000000000000000004008d30000000000000000004008d30000000000000000004008d30000000000000000004008db0000000000000000004008d3000000000000000000
|
||||
-- </PATTERNS>
|
||||
-- <TRACKS>
|
||||
-- 000:100001200001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 000:1000012000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff
|
||||
-- 001:581000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- 002:900082000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- </TRACKS>
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
-- desc: Life of a programmer
|
||||
-- site: https://git.teletype.hu/games/impostor
|
||||
-- license: MIT License
|
||||
-- version: 0.8
|
||||
-- version: 1.0-beta2
|
||||
-- script: lua
|
||||
|
||||
@@ -5,7 +5,11 @@ Screen.register({
|
||||
"go_to_toilet",
|
||||
"go_to_walking_to_office",
|
||||
"go_to_sleep",
|
||||
"go_to_end",
|
||||
},
|
||||
init = function()
|
||||
Audio.music_play_room_work()
|
||||
end,
|
||||
background = "bedroom",
|
||||
draw = function()
|
||||
if Context.home_norman_visible and Window.get_current_id() == "game" then
|
||||
|
||||
@@ -8,7 +8,6 @@ local _screens = {}
|
||||
--- @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.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.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.
|
||||
@@ -16,11 +15,11 @@ function Screen.register(screen_data)
|
||||
if _screens[screen_data.id] then
|
||||
trace("Warning: Overwriting screen with id: " .. screen_data.id)
|
||||
end
|
||||
if not screen_data.situations then
|
||||
screen_data.situations = {}
|
||||
end
|
||||
if not screen_data.init then
|
||||
screen_data.init = function() end
|
||||
end
|
||||
if not screen_data.exit then
|
||||
screen_data.exit = function() end
|
||||
end
|
||||
if not screen_data.update then
|
||||
screen_data.update = function() end
|
||||
@@ -40,7 +39,6 @@ end
|
||||
--- * name (string) Display name.<br/>
|
||||
--- * decisions (table) Array of decision ID strings.<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/>
|
||||
--- * update (function) Called each frame while screen is active.
|
||||
function Screen.get_by_id(screen_id)
|
||||
@@ -55,7 +53,6 @@ end
|
||||
--- * name (string) Display name of the screen.<br/>
|
||||
--- * decisions (table) Array of decision ID strings available on this screen.<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/>
|
||||
--- * update (function) Called each frame while screen is active.<br/>
|
||||
function Screen.get_all()
|
||||
|
||||
287
inc/screen/screen.mysterious_man.lua
Normal file
287
inc/screen/screen.mysterious_man.lua
Normal file
@@ -0,0 +1,287 @@
|
||||
--- @section MysteriousManScreen
|
||||
|
||||
local STATE_TEXT = "text"
|
||||
local STATE_DAY = "day"
|
||||
local STATE_CHOICE = "choice"
|
||||
|
||||
local ASC_01_TEXT = [[
|
||||
Normann seems to be in line,
|
||||
|
||||
and stays seeking for oxes
|
||||
|
||||
within the confines.
|
||||
|
||||
Very good.
|
||||
]]
|
||||
|
||||
local ASC_12_TEXT = [[
|
||||
We have a problem!
|
||||
|
||||
Normann formed his first thought.
|
||||
|
||||
He saw the tracks.
|
||||
]]
|
||||
local ASC_23_TEXT = [[
|
||||
Not good, not terrible.
|
||||
|
||||
Normann caught his glimpse
|
||||
|
||||
of another way
|
||||
|
||||
- quite literally -
|
||||
|
||||
if this continues,
|
||||
|
||||
we will lose control.
|
||||
]]
|
||||
local ASC_34_TEXT = [[
|
||||
There is no turning back now for Norman.
|
||||
|
||||
He caught on.
|
||||
|
||||
I hoped it would never come to this...
|
||||
]]
|
||||
|
||||
--[[ Norman speaks for the first time during MM screen ]]
|
||||
local ASC_45_TEXT = [[
|
||||
Wait, who are you?
|
||||
|
||||
*silence*
|
||||
|
||||
Why am I seeing this?
|
||||
|
||||
*silence*
|
||||
|
||||
]]
|
||||
|
||||
local ascension_texts = {
|
||||
[1] = ASC_01_TEXT,
|
||||
[2] = ASC_12_TEXT,
|
||||
[3] = ASC_23_TEXT,
|
||||
[4] = ASC_34_TEXT,
|
||||
[5] = ASC_45_TEXT,
|
||||
}
|
||||
|
||||
function MysteriousManScreen.get_text_for_level(level)
|
||||
return ascension_texts[level] or ASC_01_TEXT
|
||||
end
|
||||
|
||||
local state = STATE_TEXT
|
||||
local text_y = Config.screen.height
|
||||
local text_speed = 12 -- pixels per second
|
||||
local day_timer = 0
|
||||
local day_display_seconds = 2
|
||||
local text_done = false
|
||||
local text_done_timer = 0
|
||||
local TEXT_DONE_HOLD_SECONDS = 2
|
||||
local selected_choice = 1
|
||||
local text = ASC_01_TEXT
|
||||
local day_text_override = nil
|
||||
local on_text_complete = nil
|
||||
local show_mysterious_screen = true
|
||||
local trigger_flash_on_wake = false
|
||||
|
||||
MysteriousManScreen.choices = {
|
||||
{
|
||||
label = "Wake Up",
|
||||
},
|
||||
{
|
||||
label = "Stay in Bed",
|
||||
},
|
||||
}
|
||||
|
||||
-- Draws the background image
|
||||
-- @within MysteriousManScreen
|
||||
function MysteriousManScreen.draw_background()
|
||||
local img_values = {0,1,0,1,0,1,0,1,0,1,0,1,2,1,4,1,0,2,4,1,0,2,4,1,0,2,4,1,0,2,4,1,0,2,4,2,1,4,2,1,4,1,0,2,4,1,0,1,4,2,1,2,1,0,1,2,4,1,0,2,4,2,1,0,1,2,1,2,1,0,1,4,1,0,2,4,2,0,1,0,1,0,1,2,4,1,0,2,4,2,1,0,1,4,1,0,2,4,2,0,1,2,4,1,0,2,4,1,0,1,0,4,1,0,2,4,0,1,0,1,0,1,0,4,1,0,2,4,0,1,4,1,0,2,4,0,1,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,0,4,1,0,2,4,1,0,1,0,4,1,0,2,4,1,0,1,0,1,4,1,0,2,4,1,2,1,0,1,4,1,0,2,4,2,1,0,1,2,4,1,0,2,4,2,1,0,1,2,4,1,0,2,4,1,2,0,1,0,1,0,1,2,1,2,1,0,2,4,1,0,2,4,0,1,0,1,2,1,0,1,0,2,4,1,0,2,4,2,1,0,1,0,1,4,1,0,2,4,2,1,0,1,0,2,4,2,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,0,1,0,1,4,1,0,2,4,1,0,1,0,1,0,1,4,1,0,2,4,2,1,0,1,0,2,0,1,4,1,0,2,4,1,0,1,0,1,2,0,1,4,1,0,2,4,2,1,0,1,0,1,4,1,0,2,4,2,1,0,2,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,4,1,0,2,4,1,0,1,0,1,4,1,0,2,4,0,1,0,1,0,1,0,1,4,1,0,2,4,0,1,0,1,0,1,4,1,0,2,4,1,0,1,0,2,4,1,0,2,4,2,1,0,1,0,1,0,1,2,4,1,0,2,4,2,1,0,1,0,1,0,1,2,4,1,0,2,4,2,1,0,1,0,1,0,1,4,1,0,2,4,2,4,1,0,1,0,1,0,1,0,1,0,1,2,1,4,2,4,1,0,2,4,2,1,0,1,0,1,0,1,0,1,0,1,2,1,4,2,4,1,0,2,4,2,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,4,1,0,2,4,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,4,1,0,2,4,2,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,2,1,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,1,0,1,0,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,1,0,1,0,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,2,0,1,0,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,1,0,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,2,0,1,0,1,0,4,1,0,2,4,0,1,0,1,0,2,1,0,1,0,1,4,1,0,2,4,1,0,1,0,1,0,1,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,1,4,1,0,2,4,1,0,1,0,1,0,1,0,2,0,1,4,1,0,2,4,0,1,0,1,0,1,0,1,0,1,0,4,1,0,2,4,1,0,1,0,1,0,1,0,1,0,1,4,1,0,2,4,1,0,2,0,1,0,1,0,1,0,1,4,1,0,2,4,1,0,1,0,1,0,1,2,4,1,0,2,4,1,0,1,0,1,0,1,0,4,1,0,2,4,1,0,1,0,1,0,1,0,4,1,0,2,4,1,0,2,0,1,0,1,0,4,1,0,2,4,1,0,1,0,1,4,1,0,2,4,1,0,1,0,1,2,4,1,0,2,4,1,0,1,0,1,2,4,1,0,2,4,2,1,0,1,0,1,2,4,1,0,2,4,2,1,0,1,0,1,2,4,1,0,2,4,2,0,1,0,1,4,1,0,2,4,2,0,1,0,1,0,4,1,0,2,4,1,0,1,0,1,0,1,4,1,0,2,4,0,1,0,1,4,2,1,0,1,2,1,2,1,0,1,2,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,0,1,2,0,1,0,2,1,0,1,2,0,1,0,2,0,1,0,1,0,1,2,0,1,0,1,0,1,0,2,0,1,0,1,0,1,0,2,0,1,0,1,0,2,1,0,1,0,1,2,0,1,0,2,0,2,1,0,1,2,0,2,1,0,1,0,1,2,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,0,2,1,0,1,0,1,0,1,0,1,0,2,1,0,1,2,0,1,0,1,2,1,0,1,0,1,0,1,0,2,1,0,2,0,1,0,1,0,2,0,1,0,1,0,2,0,1,0,2,0,1,0,1,0,2,1,0,1,2,0,1,0,1,0,1,0,1,0,2,0,1,0,2,0,1,0,2,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}
|
||||
local img_runs = {1480,1,151,1,87,1,1,150,1,1,86,1,2,148,1,2,87,2,148,2,88,2,148,2,88,2,148,2,88,2,148,2,88,2,70,1,2,9,1,2,63,2,88,2,69,1,2,3,5,1,1,1,1,1,1,1,61,2,88,2,68,1,1,3,1,2,1,3,2,3,2,61,2,88,2,68,1,6,1,4,1,5,1,1,60,2,88,2,67,1,1,17,2,60,2,88,2,67,1,19,1,1,59,2,88,2,67,1,19,1,1,59,2,88,2,67,4,1,11,1,1,1,3,59,2,88,2,67,21,1,59,2,88,2,67,21,1,59,2,88,2,66,1,21,2,58,2,88,2,66,1,21,1,1,58,2,88,2,66,4,17,2,1,58,2,88,2,65,2,5,1,15,2,58,2,88,2,63,1,1,2,22,4,55,2,88,2,57,2,2,34,2,2,49,2,88,2,55,1,2,39,3,1,47,2,88,2,55,5,1,3,2,2,1,25,1,1,1,1,1,1,1,47,2,88,2,57,1,2,1,29,1,4,1,1,1,1,49,2,88,2,59,1,2,8,15,9,2,52,2,88,2,62,2,1,1,1,24,1,1,1,54,2,88,2,66,1,22,1,58,2,88,2,66,1,21,1,59,2,88,2,66,2,20,1,59,2,88,2,65,3,20,2,58,2,88,2,63,2,2,1,20,1,1,2,56,2,88,2,61,2,4,1,20,1,2,2,55,2,88,2,59,1,1,6,1,19,1,4,2,54,2,88,2,58,2,7,2,17,1,1,6,2,52,3,87,2,56,1,2,9,1,26,2,51,3,87,2,55,1,1,40,1,50,2,88,2,54,2,41,1,50,2,88,2,53,2,42,2,49,2,88,2,52,2,44,2,48,2,88,2,51,2,46,2,47,2,88,2,50,2,16,1,31,1,47,2,88,2,50,3,1,14,1,29,1,1,2,46,2,88,2,50,18,1,29,1,2,1,46,2,88,2,50,4,14,1,33,1,45,2,88,2,53,1,3,11,2,15,1,13,1,2,46,2,88,2,56,1,1,11,1,15,1,10,2,1,49,2,88,2,55,2,3,10,2,12,2,8,8,46,2,88,2,50,1,1,4,4,1,9,2,11,2,8,2,4,2,1,2,1,1,42,2,88,2,48,2,3,8,1,9,2,9,3,7,2,8,1,1,2,1,1,40,2,88,2,45,3,2,1,1,1,1,8,1,7,1,1,3,6,4,6,1,8,1,1,1,1,4,2,38,2,88,2,45,1,2,2,22,4,4,4,6,1,10,1,1,2,1,2,1,2,37,2,88,2,42,1,1,1,4,1,2,19,1,1,4,1,5,21,1,2,6,35,2,88,2,42,2,1,1,1,1,15,2,8,3,4,3,6,1,17,1,1,2,1,1,1,34,2,88,2,41,3,1,1,15,2,9,3,5,2,8,1,21,1,1,34,2,88,2,41,1,1,1,16,2,11,2,5,2,9,2,18,2,1,34,2,88,2,41,1,2,1,14,2,13,1,5,1,12,1,17,1,2,34,2,88,2,41,1,16,1,17,1,2,1,14,2,17,1,1,33,2,88,2,41,1,2,1,12,1,17,1,3,2,15,1,14,1,1,1,1,33,2,88,2,41,15,1,22,1,17,1,1,11,1,3,1,33,2,88,2,41,1,14,2,40,1,15,1,33,2,88,2,41,1,15,2,35,1,3,1,10,1,4,1,33,2,88,2,41,1,3,1,12,2,36,2,11,1,4,1,33,2,88,2,40,1,1,18,1,35,1,12,1,4,1,1,32,2,88,2,40,2,4,1,14,1,33,1,12,1,6,1,32,2,88,2,40,1,6,1,14,1,31,1,13,1,6,1,32,2,88,2,39,2,22,2,28,1,21,1,1,31,2,88,2,39,2,24,1,26,1,22,1,1,31,2,88,2,39,2,25,1,24,1,23,1,1,31,2,88,2,39,1,27,1,22,2,23,1,1,31,2,88,2,39,1,49,2,24,3,30,2,88,2,39,1,48,1,27,1,1,30,2,88,2,39,1,47,2,27,1,1,30,2,88,2,37,1,1,47,2,28,1,1,30,2,88,2,37,1,1,46,1,30,2,1,29,2,88,2,37,1,47,1,30,2,30,2,88,2,37,1,1,2,43,1,33,30,3,87,2,37,1,45,1,31,1,1,2,29,3,87,2,37,45,1,35,1,29,1,1,88,2,1,35,1,1,80,2,1,26,1,3,86,1,1,2,1,21,1,4,4,2,1,3,80,30,1,2,125,2,80,2,156,2,79,2,1,156,2,1,77,4,156,1,3,76,3,1,140,1,15,1,2,2,74,2,1,1,1,5,3,129,1,18,1,82,1,7,1,129,1,18,1,82,1,9,1,123,3,20,1,1,80,2,11,1,1,119,1,22,1,1,1,2,76,4,1,154,2,2,63,1,14,3,1,126,1,27,2,65,1,17,1,17,2,132,4,66,1,17,4,113,39,66,2,16,31,191,1,1,1,15,1,153,2,15,3,48,2,16,2,152,1,16,1,1,1,48,2,16,2,152,1,1,2,2,1,10,1,1,1,48,1,13,6,153,1,3,13,1,1,48,1,15,2,1,1,153,3,64,1,16,2,154,1,1,83,1,154,1,17,1,66,1,154,1,17,1,66,1,155,1,82,1,156,1,82,1,156,1,1,80,1,1,157,2,78,2,158,2,78,2,158,1,80,1,158,1,79,2,158,1,79,1,159,1,79,1,160,1,77,2,160,1,77,1,162,1,74,1,1,1,162,1,75,1,239,1,165,1,72,1,166,1,240,1,69,1,412,1,63,1,175,1,63,2,238,1,175,1,63,1,239,1,807}
|
||||
RLE.draw(img_values, img_runs)
|
||||
end
|
||||
|
||||
function MysteriousManScreen.draw_day_switch_background()
|
||||
local img_values = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}
|
||||
local img_runs = {86,2,238,2,225,1,10,5,224,1,8,8,221,4,5,2,1,8,219,6,2,13,217,1,2,19,1,1,213,2,4,19,2,1,211,2,5,19,3,1,208,1,7,20,4,1,204,2,7,2,1,19,5,1,201,2,7,2,3,19,6,1,198,2,7,2,5,9,2,1,2,5,7,1,195,2,7,2,7,5,7,7,8,1,192,2,7,2,9,5,8,6,9,1,188,3,7,2,11,5,9,5,10,1,186,2,7,2,13,5,9,5,11,1,182,2,7,3,15,5,9,5,12,1,179,2,8,2,17,5,9,5,13,1,176,2,7,3,19,5,9,5,14,1,173,2,7,3,21,5,9,5,15,1,169,3,7,2,24,5,9,5,16,1,166,2,8,2,26,5,9,5,3,1,177,2,8,3,27,5,9,5,4,1,13,1,159,3,7,3,30,5,8,6,5,1,170,3,7,3,32,5,7,7,6,1,13,1,153,2,8,2,35,19,7,1,164,2,7,3,37,19,8,1,160,3,7,3,39,19,9,1,156,3,8,3,41,19,10,1,153,3,8,2,44,19,25,1,136,3,8,2,46,19,160,2,8,3,48,19,157,3,7,4,50,7,6,6,15,1,139,2,9,3,52,6,7,6,16,1,12,1,122,3,8,3,55,6,7,6,17,1,132,4,7,3,57,6,7,6,159,2,60,6,7,6,32,1,123,3,62,6,7,6,33,1,119,4,64,6,7,6,22,1,128,3,67,6,7,6,150,2,1,1,67,6,7,6,153,1,67,6,7,6,25,1,11,1,115,1,67,6,7,6,26,1,126,1,67,6,7,6,28,1,124,1,67,6,7,6,29,1,11,1,111,1,67,6,7,6,30,1,11,1,110,1,66,7,6,8,42,1,109,1,66,21,32,1,10,1,71,4,33,1,66,21,115,1,2,1,33,1,66,21,119,1,32,1,66,21,36,1,115,1,66,21,48,1,66,1,2,1,33,1,66,21,38,1,10,1,65,4,33,1,66,21,152,1,66,21,152,1,66,8,6,7,152,1,66,7,7,7,114,6,32,1,66,7,7,7,114,6,32,1,66,7,7,7,57,1,56,2,2,2,32,1,66,7,7,7,58,1,18,1,35,7,32,1,12,1,49,1,3,7,7,7,19,1,1,1,2,2,24,1,8,2,46,1,4,8,32,1,66,8,6,7,12,1,1,1,4,3,2,2,2,2,2,1,18,2,7,3,44,1,3,9,32,1,12,1,1,1,51,8,6,7,14,1,1,2,1,1,1,1,2,3,1,3,1,1,3,1,2,2,11,4,1,1,2,5,41,1,3,10,32,1,12,3,51,8,5,8,7,3,2,1,1,1,1,2,1,1,1,1,1,4,1,6,1,2,2,2,1,2,1,3,1,2,1,6,1,2,1,4,39,3,2,3,1,6,32,1,8,1,2,6,2,1,4,1,2,1,7,1,30,8,5,8,2,2,3,1,1,1,6,2,1,11,1,6,2,2,1,2,1,6,1,15,24,5,1,3,1,7,2,3,1,10,28,1,14,1,9,2,1,1,38,8,1,1,2,9,1,3,10,1,1,6,10,1,2,2,1,1,3,9,1,4,1,6,1,7,8,47,26,1,27,1,7,1,18,1,4,1,4,13,1,9,1,3,3,1,1,1,1,4,1,1,2,3,2,5,2,7,1,2,1,6,1,7,1,16,1,53,25,1,66,8,1,1,3,8,1,3,3,1,1,2,3,1,1,1,1,4,2,2,2,1,7,1,2,1,1,1,1,4,1,3,1,31,7,2,1,15,6,2,1,7,1,2,25,1,66,7,7,7,29,1,2,1,3,1,6,1,16,1,2,3,6,14,5,16,2,6,10,2,25,1,66,7,7,7,57,1,7,6,1,36,9,8,1,1,25,1,66,7,7,7,68,35,7,11,5,1,25,1,66,7,7,7,69,2,1,3,1,22,7,16,2,1,2,1,25,1,66,8,6,7,75,19,6,21,2,1,2,1,92,21,79,4,1,7,4,26,2,1,2,1,2,1,89,21,91,12,9,1,1,7,2,1,28,1,66,21,87,12,13,9,98,21,84,11,19,6,99,21,80,12,22,2,3,1,32,1,66,21,70,1,5,13,25,6,99,21,73,13,28,6,2,1,29,1,66,21,69,14,31,7,31,1,66,21,58,2,6,14,39,1,99,8,4,9,55,1,6,15,42,1,99,8,5,8,51,2,6,15,145,8,5,8,48,2,5,17,147,8,5,8,43,3,6,17,150,8,5,8,40,2,6,18,153,8,5,8,36,3,5,20,155,8,5,8,32,4,5,19,1,2,156,8,5,8,29,3,6,19,95,1,66,8,5,8,25,4,5,21,97,1,66,8,5,8,22,4,5,21,167,8,5,8,18,5,5,21,170,8,5,8,14,6,4,23,105,1,66,8,5,8,11,4,6,23,108,1,66,8,5,8,8,4,6,23,111,1,66,8,5,8,4,4,6,24,114,1,66,8,5,14,7,23,116,1,66,8,6,8,2,1,4,25,119,1,66,8,5,8,3,1,2,24,122,1,66,8,3,38,124,1,65,24,1,22,127,1,63,1,1,44,130,1,63,7,1,5,1,30,132,1,58,3,1,42,135,1,58,14,2,27,138,1,56,10,1,32,140,1,53,8,4,27,1,3,143,1,49,9,1,1,2,1,1,24,2,2,147,1,47,7,5,32,148,1,30,1,12,8,5,32,151,1,28,1,1,1,3,1,4,4,1,3,6,35,151,1,22,10,1,10,1,1,4,39,151,1,20,25,2,41,151,1,18,47,1,22,151,1,18,70,148,2,1,1,17,71,148,4,17,71,148,4,14,61,2,10,149,6,10,63,2,10,149,8,4,66,4,9,149,80,2,9,149,91,149,92,78,3,67,92,148,80,3,9,148,92,148,92,148,92,148,92,74,1,3,2,68,92,73,3,2,3,67,92,69,1,3,3,2,2,68,94,66,2,1,5,2,3,67,95,58,15,2,1,69,96,55,21,68}
|
||||
-- pal = {184,167,183,121,70,74}
|
||||
-- pal = b8a7b779464a
|
||||
RLE.draw(img_values, img_runs)
|
||||
end
|
||||
|
||||
-- Transitions from the text phase to the day display phase, starting the timer for how long the day label is shown.
|
||||
-- @within MysteriousManScreen
|
||||
function MysteriousManScreen.go_to_day_state()
|
||||
if on_text_complete then
|
||||
on_text_complete()
|
||||
on_text_complete = nil
|
||||
end
|
||||
if Context.game.current_screen ~= "mysterious_man" then
|
||||
return
|
||||
end
|
||||
state = STATE_DAY
|
||||
day_timer = day_display_seconds
|
||||
end
|
||||
|
||||
-- Norman chooses to wake up, starting the button mash minigame and flash, then going to the next day.
|
||||
-- @within MysteriousManScreen
|
||||
function MysteriousManScreen.wake_up()
|
||||
Context.home_norman_visible = false
|
||||
Util.go_to_screen_by_id("home")
|
||||
MinigameButtonMashWindow.start("game", {
|
||||
focus_center_x = (Config.screen.width / 2) - 22,
|
||||
focus_center_y = (Config.screen.height / 2) - 18,
|
||||
focus_initial_radius = 0,
|
||||
target_points = 100,
|
||||
instruction_text = "Wake up Norman!",
|
||||
show_progress_text = false,
|
||||
on_win = function()
|
||||
Audio.music_play_wakingup()
|
||||
Meter.show()
|
||||
if trigger_flash_on_wake then
|
||||
trigger_flash_on_wake = false
|
||||
Ascension.start_flash()
|
||||
end
|
||||
Window.set_current("game")
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Norman chooses to stay in bed, skipping the minigame and flash, and going straight to the next day.
|
||||
-- @within MysteriousManScreen
|
||||
function MysteriousManScreen.stay_in_bed()
|
||||
Day.increase()
|
||||
state = STATE_DAY
|
||||
day_timer = day_display_seconds
|
||||
end
|
||||
|
||||
--- Starts the mysterious man screen.
|
||||
--- @param[opt] options table Optional configuration.</br>
|
||||
--- Fields: </br>
|
||||
--- * text (string) Override for the scrolling text.<br/>
|
||||
--- * day_text (string) Override for the centered day label.<br/>
|
||||
--- * on_text_complete (function) Callback fired once when the text phase ends.<br/>
|
||||
--- * skip_text (boolean) If true, skip the text phase and go straight to day display.<br/>
|
||||
function MysteriousManScreen.start(options)
|
||||
options = options or {}
|
||||
day_timer = 0
|
||||
text_done = false
|
||||
text_done_timer = 0
|
||||
selected_choice = 1
|
||||
text = options.text or ASC_01_TEXT
|
||||
text_y = Config.screen.height
|
||||
day_text_override = options.day_text
|
||||
on_text_complete = options.on_text_complete
|
||||
Meter.hide()
|
||||
trigger_flash_on_wake = not options.skip_text
|
||||
if options.skip_text then
|
||||
show_mysterious_screen = false
|
||||
state = STATE_DAY
|
||||
day_timer = day_display_seconds
|
||||
else
|
||||
show_mysterious_screen = true
|
||||
state = STATE_TEXT
|
||||
end
|
||||
Util.go_to_screen_by_id("mysterious_man")
|
||||
Window.set_current("game")
|
||||
end
|
||||
|
||||
--- Sets the scrolling text content.
|
||||
--- @param new_text string The text to display.
|
||||
function MysteriousManScreen.set_text(new_text)
|
||||
text = new_text
|
||||
end
|
||||
|
||||
Screen.register({
|
||||
id = "mysterious_man",
|
||||
name = "Mysterious Man",
|
||||
decisions = {},
|
||||
background_color = Config.colors.black,
|
||||
init = function()
|
||||
Audio.music_play_mystery()
|
||||
end,
|
||||
exit = function()
|
||||
Audio.music_stop()
|
||||
end,
|
||||
update = function()
|
||||
if state == STATE_TEXT then
|
||||
if not text_done then
|
||||
text_y = text_y - (text_speed * Context.delta_time)
|
||||
|
||||
local lines = 1
|
||||
for _ in string.gmatch(text, "\n") do
|
||||
lines = lines + 1
|
||||
end
|
||||
|
||||
if text_y < -lines * 8 or Input.select() then
|
||||
text_done = true
|
||||
text_done_timer = TEXT_DONE_HOLD_SECONDS
|
||||
-- If skipped by user, go to day state immediately
|
||||
if Input.select() then
|
||||
MysteriousManScreen.go_to_day_state()
|
||||
end
|
||||
end
|
||||
else
|
||||
text_done_timer = text_done_timer - Context.delta_time
|
||||
if text_done_timer <= 0 or Input.select() then
|
||||
MysteriousManScreen.go_to_day_state()
|
||||
-- to be continued
|
||||
if 4 <= Ascension.get_level() then
|
||||
Window.set_current("continued")
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif state == STATE_DAY then
|
||||
day_timer = day_timer - Context.delta_time
|
||||
|
||||
if day_timer <= 0 or Input.select() then
|
||||
if trigger_flash_on_wake or Ascension.get_level() < 1 then
|
||||
MysteriousManScreen.wake_up()
|
||||
else
|
||||
state = STATE_CHOICE
|
||||
selected_choice = 1
|
||||
end
|
||||
end
|
||||
elseif state == STATE_CHOICE then
|
||||
local menu_x = (Config.screen.width - 60) / 2
|
||||
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
|
||||
Audio.sfx_select()
|
||||
if selected_choice == 1 then
|
||||
MysteriousManScreen.wake_up()
|
||||
else
|
||||
MysteriousManScreen.stay_in_bed()
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
draw = function()
|
||||
if show_mysterious_screen then
|
||||
MysteriousManScreen.draw_background()
|
||||
end
|
||||
|
||||
if state == STATE_TEXT then
|
||||
local screen_w = Config.screen.width
|
||||
local line_y = text_y
|
||||
for line in (text .. "\n"):gmatch("(.-)\n") do
|
||||
local line_w = print(line, 0, -6, 0, false, 1)
|
||||
local line_x = math.floor((screen_w - line_w) / 2)
|
||||
Print.text_contour(line, (line_x - 8), line_y, Config.colors.black, false, 1)
|
||||
line_y = line_y + 8
|
||||
end
|
||||
elseif state == STATE_DAY then
|
||||
MysteriousManScreen.draw_day_switch_background()
|
||||
local day_text = day_text_override or ("day " .. Context.day_count)
|
||||
Print.text_center_contour(
|
||||
day_text,
|
||||
Config.screen.width / 2,
|
||||
Config.screen.height / 2 - 3,
|
||||
Config.colors.white
|
||||
)
|
||||
elseif state == STATE_CHOICE then
|
||||
local menu_x = (Config.screen.width - 60) / 2
|
||||
local menu_y = (Config.screen.height - 20) / 2
|
||||
UI.draw_menu(MysteriousManScreen.choices, selected_choice, menu_x, menu_y)
|
||||
end
|
||||
end,
|
||||
})
|
||||
@@ -6,8 +6,45 @@ Screen.register({
|
||||
"go_to_walking_to_home",
|
||||
"have_a_coffee",
|
||||
},
|
||||
situations = {
|
||||
"drink_coffee",
|
||||
},
|
||||
background = "office"
|
||||
init = function()
|
||||
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,
|
||||
background = "office",
|
||||
draw = function()
|
||||
if Window.get_current_id() == "game" then
|
||||
Sprite.draw_at("norman", 13 * 8, 9 * 8)
|
||||
|
||||
Sprite.draw_list(Context.office_sprites)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ Screen.register({
|
||||
},
|
||||
background = "bedroom",
|
||||
init = function()
|
||||
Audio.music_play_mystery()
|
||||
Context.stat_screen_active = true
|
||||
Meter.hide()
|
||||
local cx = Config.screen.width * 0.75
|
||||
@@ -15,10 +16,11 @@ Screen.register({
|
||||
end,
|
||||
update = function()
|
||||
if not Context.stat_screen_active then return end
|
||||
if Input.select() or Input.player_interact() then
|
||||
if Input.select() or Input.select() then
|
||||
Focus.stop()
|
||||
Context.stat_screen_active = false
|
||||
Meter.show()
|
||||
Util.go_to_screen_by_id("home")
|
||||
end
|
||||
end,
|
||||
draw = function()
|
||||
@@ -34,13 +36,13 @@ Screen.register({
|
||||
|
||||
Sprite.draw_at("norman", norman_x, norman_y)
|
||||
|
||||
Print.text_center("day " .. Context.day_count, cx, 10, Config.colors.white)
|
||||
Print.text_center_contour("day " .. Context.day_count, cx, 10, Config.colors.black)
|
||||
|
||||
local narrative = "reflecting on my past and present\n...\nboth eventually flushed."
|
||||
local narrative = "reflecting on my past and present...\nboth eventually flushed..."
|
||||
local wrapped = UI.word_wrap(narrative, 38)
|
||||
local text_y = 24
|
||||
for _, line in ipairs(wrapped) do
|
||||
Print.text_center(line, cx, text_y, Config.colors.light_grey)
|
||||
Print.text_center_contour(line, cx, text_y, Config.colors.black)
|
||||
text_y = text_y + 8
|
||||
end
|
||||
|
||||
@@ -54,26 +56,35 @@ Screen.register({
|
||||
local meter_start_y = text_y + 10
|
||||
|
||||
local meter_list = {
|
||||
{ key = "wpm", label = "Work Productivity Meter" },
|
||||
{ key = "ism", label = "Impostor Syndrome Meter" },
|
||||
{ key = "bm", label = "Burnout Meter" },
|
||||
{ key = "wpm", label = "Work Productivity Meter", color = Meter.COLOR_WPM },
|
||||
{ key = "ism", label = "Impostor Syndrome Meter", color = Meter.COLOR_ISM },
|
||||
{ key = "bm", label = "Burnout Meter", color = Meter.COLOR_BM },
|
||||
}
|
||||
|
||||
for i, meter in ipairs(meter_list) do
|
||||
local y = meter_start_y + (i - 1) * 20
|
||||
|
||||
Print.text_center(meter.label, cx, y, Config.colors.white)
|
||||
Print.text_center_contour(meter.label, cx, y, meter.color, false, 1, Config.colors.white)
|
||||
|
||||
local bar_y = y + 8
|
||||
local fill_w = math.max(0, math.floor((m[meter.key] / max_val) * bar_w))
|
||||
rect(bar_x, bar_y, bar_w, bar_h, Meter.COLOR_BG)
|
||||
if fill_w > 0 then
|
||||
rect(bar_x, bar_y, fill_w, bar_h, Config.colors.blue)
|
||||
rect(bar_x, bar_y, fill_w, bar_h, meter.color)
|
||||
end
|
||||
|
||||
local decay_w = print(decay_text, 0, -6, 0, false, 1)
|
||||
Print.text(decay_text, bar_x - decay_w - 4, bar_y, Config.colors.light_blue)
|
||||
Print.text(mult_text, bar_x + bar_w + 4, bar_y, Config.colors.light_blue)
|
||||
Print.text_contour(decay_text, bar_x - decay_w - 4, bar_y, Config.colors.light_blue, false, 1, Config.colors.white)
|
||||
Print.text_contour(mult_text, bar_x + bar_w + 4, bar_y, Config.colors.light_blue, false, 1, Config.colors.white)
|
||||
end
|
||||
|
||||
if Ascension.get_level() > 0 then
|
||||
local asc_y = meter_start_y + #meter_list * 20
|
||||
local asc_letter_y = asc_y + 10
|
||||
local asc_spacing = 8
|
||||
local asc_total_w = Ascension.get_level() * asc_spacing
|
||||
local asc_x = math.floor((sw - asc_total_w) / 2)
|
||||
Ascension.draw(asc_x, asc_letter_y, { spacing = asc_spacing })
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -5,5 +5,15 @@ Screen.register({
|
||||
"go_to_home",
|
||||
"go_to_office",
|
||||
},
|
||||
background = "street"
|
||||
init = function()
|
||||
Audio.music_play_room_work()
|
||||
end,
|
||||
background = "street",
|
||||
draw = function()
|
||||
if Window.get_current_id() == "game" then
|
||||
Sprite.draw_at("norman", 7 * 8, 3 * 8)
|
||||
Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8)
|
||||
Sprite.draw_at("dev_guard", 22 * 8, 2 * 8)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
@@ -4,7 +4,42 @@ Screen.register({
|
||||
decisions = {
|
||||
"go_to_home",
|
||||
"go_to_office",
|
||||
"start_discussion",
|
||||
"sumphore_discussion",
|
||||
},
|
||||
background = "street"
|
||||
init = function()
|
||||
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,
|
||||
background = "street",
|
||||
draw = function()
|
||||
if Window.get_current_id() == "game" then
|
||||
Sprite.draw_at("norman", 7 * 8, 3 * 8)
|
||||
Sprite.draw_at("sumphore", 9 * 8, 2 * 8)
|
||||
Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8)
|
||||
Sprite.draw_at("dev_guard", 22 * 8, 2 * 8)
|
||||
|
||||
Sprite.draw_list(Context.walking_to_office_sprites)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
Situation.register({
|
||||
id = "drink_coffee",
|
||||
handle = function()
|
||||
Audio.sfx_select()
|
||||
Sprite.show("norman", 100, 100)
|
||||
end,
|
||||
})
|
||||
@@ -1,84 +0,0 @@
|
||||
--- @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
|
||||
4
inc/sprite/sprite.dev_boy.lua
Normal file
4
inc/sprite/sprite.dev_boy.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_boy",
|
||||
sprites = Sprite.generate_table(2, 3, 278, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_buddy.lua
Normal file
4
inc/sprite/sprite.dev_buddy.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_buddy",
|
||||
sprites = Sprite.generate_table(2, 3, 286, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_extrovert.lua
Normal file
4
inc/sprite/sprite.dev_extrovert.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_extrovert",
|
||||
sprites = Sprite.generate_table(2, 4, 330, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_girl.lua
Normal file
4
inc/sprite/sprite.dev_girl.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_girl",
|
||||
sprites = Sprite.generate_table(2, 3, 284, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_guard.lua
Normal file
4
inc/sprite/sprite.dev_guard.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_guard",
|
||||
sprites = Sprite.generate_table(3, 4, 384, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_guru.lua
Normal file
4
inc/sprite/sprite.dev_guru.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_guru",
|
||||
sprites = Sprite.generate_table(2, 4, 264, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_hr_girl.lua
Normal file
4
inc/sprite/sprite.dev_hr_girl.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_hr_girl",
|
||||
sprites = Sprite.generate_table(2, 4, 260, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_introvert.lua
Normal file
4
inc/sprite/sprite.dev_introvert.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_introvert",
|
||||
sprites = Sprite.generate_table(2, 4, 332, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_operator.lua
Normal file
4
inc/sprite/sprite.dev_operator.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_operator",
|
||||
sprites = Sprite.generate_table(2, 4, 326, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.dev_project_manager.lua
Normal file
4
inc/sprite/sprite.dev_project_manager.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "dev_project_manager",
|
||||
sprites = Sprite.generate_table(2, 4, 328, -4, -4, 8, 8)
|
||||
})
|
||||
@@ -3,7 +3,7 @@ local _sprites = {}
|
||||
local _active_sprites = {}
|
||||
|
||||
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 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
|
||||
@@ -50,6 +50,93 @@ function Sprite.register(sprite_data)
|
||||
_sprites[sprite_data.id] = sprite_data
|
||||
end
|
||||
|
||||
--- Generates a sprites table for a rectangular composite sprite.
|
||||
--- @within Sprite
|
||||
--- @param width number The number of sprites wide.<br/>
|
||||
--- @param height number The number of sprites tall.<br/>
|
||||
--- @param starting_s number The sprite index of the top-left tile.<br/>
|
||||
--- @param x_base number The base x-offset for the leftmost column.<br/>
|
||||
--- @param y_base number The base y-offset for the topmost row.<br/>
|
||||
--- @param x_step number The x-offset increment per column.<br/>
|
||||
--- @param y_step number The y-offset increment per row.<br/>
|
||||
--- @return table The sprites table array.
|
||||
function Sprite.generate_table(width, height, starting_s, x_base, y_base, x_step, y_step)
|
||||
local sprites = {}
|
||||
for row = 0, height - 1 do
|
||||
for col = 0, width - 1 do
|
||||
local s = starting_s + row * 16 + col
|
||||
local x_offset = x_base + col * x_step
|
||||
local y_offset = y_base + row * y_step
|
||||
table.insert(sprites, { s = s, x_offset = x_offset, y_offset = y_offset })
|
||||
end
|
||||
end
|
||||
return sprites
|
||||
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.
|
||||
--- @within Sprite
|
||||
--- @param id string The unique identifier of the sprite.<br/>
|
||||
|
||||
4
inc/sprite/sprite.matrix_architect.lua
Normal file
4
inc/sprite/sprite.matrix_architect.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "matrix_architect",
|
||||
sprites = Sprite.generate_table(2, 4, 324, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.matrix_neo.lua
Normal file
4
inc/sprite/sprite.matrix_neo.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "matrix_neo",
|
||||
sprites = Sprite.generate_table(2, 4, 322, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.matrix_oraculum.lua
Normal file
4
inc/sprite/sprite.matrix_oraculum.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "matrix_oraculum",
|
||||
sprites = Sprite.generate_table(2, 3, 282, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.matrix_trinity.lua
Normal file
4
inc/sprite/sprite.matrix_trinity.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "matrix_trinity",
|
||||
sprites = Sprite.generate_table(2, 4, 320, -4, -4, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.pizza_vendor.lua
Normal file
4
inc/sprite/sprite.pizza_vendor.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "pizza_vendor",
|
||||
sprites = Sprite.generate_table(2, 2, 334, -1, -8, 8, 8)
|
||||
})
|
||||
4
inc/sprite/sprite.sumphore.lua
Normal file
4
inc/sprite/sprite.sumphore.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
Sprite.register({
|
||||
id = "sumphore",
|
||||
sprites = Sprite.generate_table(2, 4, 258, -4, -4, 8, 8)
|
||||
})
|
||||
@@ -44,7 +44,7 @@ function AsciiArt.draw(text, options)
|
||||
for j = 1, #line do
|
||||
local char = line:sub(j, j)
|
||||
if char == "#" then
|
||||
rect(x_offset + (j - 1) * char_w, current_y, char_w - 1, char_h - 1, color)
|
||||
rect(x_offset + (j - 1) * char_w, current_y, char_w, char_h, color)
|
||||
end
|
||||
end
|
||||
current_y = current_y + char_h + line_gap
|
||||
|
||||
@@ -5,10 +5,9 @@ local INPUT_KEY_LEFT = 2
|
||||
local INPUT_KEY_RIGHT = 3
|
||||
local INPUT_KEY_A = 4
|
||||
local INPUT_KEY_B = 5
|
||||
local INPUT_KEY_Y = 7
|
||||
local INPUT_KEY_SPACE = 48
|
||||
local INPUT_KEY_BACKSPACE = 51
|
||||
local INPUT_KEY_ENTER = 50
|
||||
local INPUT_KEY_BACKSPACE = 51
|
||||
|
||||
--- Checks if Up is pressed.
|
||||
--- @within Input
|
||||
@@ -24,16 +23,10 @@ function Input.left() return btnp(INPUT_KEY_LEFT) end
|
||||
function Input.right() return btnp(INPUT_KEY_RIGHT) end
|
||||
--- Checks if Select is pressed.
|
||||
--- @within Input
|
||||
function Input.select() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_SPACE) end
|
||||
--- Checks if Menu Confirm is pressed.
|
||||
function Input.select() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_SPACE) or Mouse.clicked() end
|
||||
--- Checks if Back is pressed.
|
||||
--- @within Input
|
||||
function Input.menu_confirm() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_ENTER) end
|
||||
--- Checks if Player Interact is pressed.
|
||||
function Input.back() return btnp(INPUT_KEY_B) or keyp(INPUT_KEY_BACKSPACE) end
|
||||
--- Checks if Enter is pressed.
|
||||
--- @within Input
|
||||
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
|
||||
function Input.enter() return keyp(INPUT_KEY_ENTER) end
|
||||
|
||||
@@ -17,6 +17,16 @@ end
|
||||
--- @within Main
|
||||
function TIC()
|
||||
init_game()
|
||||
Mouse.update()
|
||||
|
||||
local now = time()
|
||||
if Context.last_frame_time == 0 then
|
||||
Context.delta_time = 0
|
||||
else
|
||||
Context.delta_time = (now - Context.last_frame_time) / 1000
|
||||
end
|
||||
Context.last_frame_time = now
|
||||
|
||||
cls(Config.colors.black)
|
||||
local handler = Window.get_current_handler() -- Get handler from Window manager
|
||||
if handler then
|
||||
@@ -26,8 +36,10 @@ function TIC()
|
||||
Timer.update()
|
||||
Trigger.update()
|
||||
Glitch.draw()
|
||||
Ascension.update_fade()
|
||||
if Context.game_in_progress then
|
||||
Meter.draw()
|
||||
Timer.draw()
|
||||
end
|
||||
Ascension.draw_flash()
|
||||
end
|
||||
|
||||
81
inc/system/system.mouse.lua
Normal file
81
inc/system/system.mouse.lua
Normal file
@@ -0,0 +1,81 @@
|
||||
--- @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
|
||||
@@ -10,7 +10,29 @@ function Print.text(text, x, y, color, fixed, scale)
|
||||
local shadow_color = Config.colors.black
|
||||
if color == shadow_color then shadow_color = Config.colors.light_grey end
|
||||
scale = scale or 1
|
||||
print(text, x + 1, y + 1, shadow_color, fixed, scale)
|
||||
print(text, x + scale, y + scale, shadow_color, fixed, scale)
|
||||
print(text, x, y, color, fixed, scale)
|
||||
end
|
||||
|
||||
--- Prints text with a contour (outline) instead of shadow.
|
||||
--- @within Print
|
||||
--- @param text string The text to print.<br/>
|
||||
--- @param x number The x-coordinate.<br/>
|
||||
--- @param y number The y-coordinate.<br/>
|
||||
--- @param color number The color of the text.<br/>
|
||||
--- @param[opt] fixed boolean If true, uses fixed-width font.<br/>
|
||||
--- @param[opt] scale number The scaling factor (also used for outline thickness).<br/>
|
||||
--- @param[opt] contour_color number Outline color; defaults to black; if equal to text color, uses white.<br/>
|
||||
function Print.text_contour(text, x, y, color, fixed, scale, contour_color)
|
||||
scale = scale or 1
|
||||
local cc = contour_color
|
||||
if cc == nil then cc = Config.colors.black end
|
||||
if color == cc then cc = Config.colors.white end
|
||||
local ox = { -scale, scale, 0, 0, -scale, scale, -scale, scale }
|
||||
local oy = { 0, 0, -scale, scale, -scale, -scale, scale, scale }
|
||||
for i = 1, 8 do
|
||||
print(text, x + ox[i], y + oy[i], cc, fixed, scale)
|
||||
end
|
||||
print(text, x, y, color, fixed, scale)
|
||||
end
|
||||
|
||||
@@ -24,7 +46,23 @@ end
|
||||
--- @param[opt] scale number The scaling factor.<br/>
|
||||
function Print.text_center(text, x, y, color, fixed, scale)
|
||||
scale = scale or 1
|
||||
local text_width = print(text, 0, -6, 0, fixed, scale)
|
||||
local text_width = print(text, 0, -6 * scale, 0, fixed, scale)
|
||||
local centered_x = x - (text_width / 2)
|
||||
Print.text(text, centered_x, y, color, fixed, scale)
|
||||
end
|
||||
|
||||
--- Prints centered text with contour instead of shadow.
|
||||
--- @within Print
|
||||
--- @param text string The text to print.<br/>
|
||||
--- @param x number The x-coordinate for centering.<br/>
|
||||
--- @param y number The y-coordinate.<br/>
|
||||
--- @param color number The color of the text.<br/>
|
||||
--- @param[opt] fixed boolean If true, uses fixed-width font.<br/>
|
||||
--- @param[opt] scale number The scaling factor.<br/>
|
||||
--- @param[opt] contour_color number Outline color; defaults to black; if equal to text color, uses white.<br/>
|
||||
function Print.text_center_contour(text, x, y, color, fixed, scale, contour_color)
|
||||
scale = scale or 1
|
||||
local text_width = print(text, 0, -6 * scale, 0, fixed, scale)
|
||||
local centered_x = x - (text_width / 2)
|
||||
Print.text_contour(text, centered_x, y, color, fixed, scale, contour_color)
|
||||
end
|
||||
|
||||
22
inc/system/system.rle.lua
Normal file
22
inc/system/system.rle.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
--- @section RLE
|
||||
RLE = {}
|
||||
|
||||
--- Draws an RLE-encoded image.
|
||||
--- @param runs table Array of run lengths.
|
||||
--- @param values table Array of pixel values (colors).
|
||||
function RLE.draw(img_values, img_runs)
|
||||
local SCREEN_WIDTH=240
|
||||
local SCREEN_HEIGHT=136
|
||||
local val_i=0
|
||||
local run=0
|
||||
for y=0,SCREEN_HEIGHT-1 do
|
||||
for x=0,SCREEN_WIDTH-1 do
|
||||
if run==0 then
|
||||
val_i=val_i+1
|
||||
run=img_runs[val_i]
|
||||
end
|
||||
run=run-1
|
||||
pix(x,y,img_values[val_i])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -38,8 +38,12 @@ end
|
||||
--- @within UI
|
||||
--- @param items table A table of menu items.<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.
|
||||
function UI.update_menu(items, selected_item)
|
||||
--- @return boolean mouse_confirmed True if the user clicked on a menu item.
|
||||
function UI.update_menu(items, selected_item, x, y, centered)
|
||||
if Input.up() then
|
||||
Audio.sfx_beep()
|
||||
selected_item = selected_item - 1
|
||||
@@ -53,7 +57,25 @@ function UI.update_menu(items, selected_item)
|
||||
selected_item = 1
|
||||
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
|
||||
|
||||
--- Draws a bordered textbox with scrolling text.
|
||||
@@ -68,12 +90,54 @@ end
|
||||
--- @param[opt] bg_color number The background fill color (default: Config.colors.dark_grey).<br/>
|
||||
--- @param[opt] border_color number The border color (default: Config.colors.white).<br/>
|
||||
--- @param[opt] center_text boolean Whether to center each line inside the box. Defaults to false.<br/>
|
||||
local function draw_rounded_rect_fill(x, y, w, h, corner_radius, color)
|
||||
local inner_w = w - corner_radius * 2
|
||||
local inner_h = h - corner_radius * 2
|
||||
if inner_w > 0 and inner_h > 0 then
|
||||
rect(x + corner_radius, y + corner_radius, inner_w, inner_h, color)
|
||||
end
|
||||
if inner_w > 0 and corner_radius > 0 then
|
||||
rect(x + corner_radius, y, inner_w, corner_radius, color)
|
||||
rect(x + corner_radius, y + h - corner_radius, inner_w, corner_radius, color)
|
||||
end
|
||||
if corner_radius > 0 and inner_h > 0 then
|
||||
rect(x, y + corner_radius, corner_radius, inner_h, color)
|
||||
rect(x + w - corner_radius, y + corner_radius, corner_radius, inner_h, color)
|
||||
end
|
||||
for row = 0, corner_radius - 1 do
|
||||
for col = 0, corner_radius - 1 do
|
||||
if col + row >= corner_radius - 1 then
|
||||
pix(x + corner_radius - 1 - col, y + corner_radius - 1 - row, color)
|
||||
pix(x + w - corner_radius + col, y + corner_radius - 1 - row, color)
|
||||
pix(x + corner_radius - 1 - col, y + h - corner_radius + row, color)
|
||||
pix(x + w - corner_radius + col, y + h - corner_radius + row, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function draw_rounded_rect_border(x, y, w, h, corner_radius, color)
|
||||
line(x + corner_radius, y, x + w - corner_radius - 1, y, color)
|
||||
line(x + corner_radius, y + h - 1, x + w - corner_radius - 1, y + h - 1, color)
|
||||
line(x, y + corner_radius, x, y + h - corner_radius - 1, color)
|
||||
line(x + w - 1, y + corner_radius, x + w - 1, y + h - corner_radius - 1, color)
|
||||
pix(x + corner_radius - 1, y + 1, color)
|
||||
pix(x + 1, y + corner_radius - 1, color)
|
||||
pix(x + w - corner_radius, y + 1, color)
|
||||
pix(x + w - 2, y + corner_radius - 1, color)
|
||||
pix(x + corner_radius - 1, y + h - 2, color)
|
||||
pix(x + 1, y + h - corner_radius, color)
|
||||
pix(x + w - corner_radius, y + h - 2, color)
|
||||
pix(x + w - 2, y + h - corner_radius, color)
|
||||
end
|
||||
|
||||
function UI.draw_textbox(text, box_x, box_y, box_w, box_h, scroll_y, color, bg_color, border_color, center_text)
|
||||
color = color or Config.colors.white
|
||||
bg_color = bg_color or Config.colors.dark_grey
|
||||
bg_color = bg_color or Config.colors.black
|
||||
border_color = border_color or Config.colors.white
|
||||
center_text = center_text or false
|
||||
|
||||
local r = 3
|
||||
local padding = 4
|
||||
local line_height = 8
|
||||
local inner_x = box_x + padding
|
||||
@@ -88,7 +152,7 @@ function UI.draw_textbox(text, box_x, box_y, box_w, box_h, scroll_y, color, bg_c
|
||||
base_y = inner_y + math.floor((visible_height - text_height) / 2)
|
||||
end
|
||||
|
||||
rect(box_x, box_y, box_w, box_h, bg_color)
|
||||
draw_rounded_rect_fill(box_x, box_y, box_w, box_h, r, bg_color)
|
||||
|
||||
for i, line in ipairs(lines) do
|
||||
local ly = base_y + (i - 1) * line_height - scroll_y
|
||||
@@ -101,7 +165,7 @@ function UI.draw_textbox(text, box_x, box_y, box_w, box_h, scroll_y, color, bg_c
|
||||
end
|
||||
end
|
||||
|
||||
rectb(box_x, box_y, box_w, box_h, border_color)
|
||||
draw_rounded_rect_border(box_x, box_y, box_w, box_h, r, border_color)
|
||||
end
|
||||
|
||||
--- Wraps text.
|
||||
|
||||
@@ -14,10 +14,14 @@ end
|
||||
--- @within Util
|
||||
--- @param screen_id string The ID of the screen to go to.<br/>
|
||||
function Util.go_to_screen_by_id(screen_id)
|
||||
local screen = Screen.get_by_id(screen_id)
|
||||
if screen then
|
||||
local prev_screen = Screen.get_by_id(Context.game.current_screen)
|
||||
local new_screen = Screen.get_by_id(screen_id)
|
||||
if new_screen then
|
||||
Context.game.current_screen = screen_id
|
||||
screen.init()
|
||||
if prev_screen and prev_screen.exit then
|
||||
prev_screen.exit()
|
||||
end
|
||||
new_screen.init()
|
||||
else
|
||||
PopupWindow.show({"Error: Screen '" .. screen_id .. "' not found!"})
|
||||
end
|
||||
@@ -36,3 +40,30 @@ function Util.contains(t, value)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Deep copies tables
|
||||
--- @within Util
|
||||
--- @param orig any The value to deep copy.
|
||||
--- @param seen any Used for recursive calls to handle loops
|
||||
--- @return any any The copied object
|
||||
function Util.deepcopy(orig, seen)
|
||||
if type(orig) ~= "table" then
|
||||
return orig
|
||||
end
|
||||
|
||||
if seen and seen[orig] then
|
||||
return seen[orig] -- handle cycles / shared refs
|
||||
end
|
||||
|
||||
local copy = {}
|
||||
seen = seen or {}
|
||||
seen[orig] = copy
|
||||
|
||||
for k, v in pairs(orig) do
|
||||
local new_k = Util.deepcopy(k, seen)
|
||||
local new_v = Util.deepcopy(v, seen)
|
||||
copy[new_k] = new_v
|
||||
end
|
||||
|
||||
return setmetatable(copy, getmetatable(orig))
|
||||
end
|
||||
|
||||
@@ -107,9 +107,9 @@ function AudioTestWindow.update()
|
||||
AudioTestWindow.menuitems = AudioTestWindow.generate_menuitems(
|
||||
AudioTestWindow.list_func, AudioTestWindow.index_func
|
||||
)
|
||||
elseif Input.menu_confirm() then
|
||||
elseif Input.select() then
|
||||
AudioTestWindow.menuitems[AudioTestWindow.index_menu].decision()
|
||||
elseif Input.menu_back() then
|
||||
elseif Input.back() then
|
||||
AudioTestWindow.back()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
--- @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
|
||||
@@ -26,7 +26,7 @@ end
|
||||
--- @within ContinuedWindow
|
||||
function ContinuedWindow.update()
|
||||
ContinuedWindow.timer = ContinuedWindow.timer - 1
|
||||
if ContinuedWindow.timer <= 0 or Input.select() or Input.menu_confirm() then
|
||||
if ContinuedWindow.timer <= 0 or Input.select() or Input.select() then
|
||||
Window.set_current("menu")
|
||||
MenuWindow.refresh_menu_items()
|
||||
end
|
||||
|
||||
44
inc/window/window.controls.lua
Normal file
44
inc/window/window.controls.lua
Normal file
@@ -0,0 +1,44 @@
|
||||
--- @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
|
||||
@@ -24,7 +24,7 @@ function DiscussionWindow.draw()
|
||||
TEXTBOX_W, TEXTBOX_H,
|
||||
Context.discussion.scroll_y,
|
||||
Config.colors.white,
|
||||
Config.colors.dark_grey,
|
||||
Config.colors.black,
|
||||
Config.colors.light_blue,
|
||||
true
|
||||
)
|
||||
@@ -37,9 +37,13 @@ function DiscussionWindow.draw()
|
||||
local selected = answers[Context.discussion.selected_answer]
|
||||
local label = selected.label
|
||||
local answer_text_y = bar_y + 4
|
||||
Print.text("<", 2, answer_text_y, Config.colors.light_blue)
|
||||
Print.text_center(label, Config.screen.width / 2, answer_text_y, Config.colors.item)
|
||||
Print.text(">", Config.screen.width - 6, answer_text_y, Config.colors.light_blue)
|
||||
local left_arrow_color = Input.left() and Config.colors.white or Config.colors.orange
|
||||
local right_arrow_color = Input.right() and Config.colors.white or Config.colors.orange
|
||||
local left_arrow_contour_color = Input.left() and Config.colors.white or Config.colors.black
|
||||
local right_arrow_contour_color = Input.right() and Config.colors.white or Config.colors.black
|
||||
Print.text_center_contour("<", 6, answer_text_y, left_arrow_color, false, 1, left_arrow_contour_color)
|
||||
Print.text_center(label, Config.screen.width / 2, answer_text_y, Config.colors.orange)
|
||||
Print.text_center_contour(">", Config.screen.width - 6, answer_text_y, right_arrow_color, false, 1, right_arrow_contour_color)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -52,14 +52,14 @@ function EndWindow.update()
|
||||
end
|
||||
end
|
||||
|
||||
if Input.menu_confirm() then
|
||||
if Input.select() then
|
||||
Audio.sfx_select()
|
||||
if Context._end.selection == 1 then
|
||||
Context._end.state = "ending"
|
||||
else
|
||||
-- NO: increment day and go home
|
||||
Day.increase()
|
||||
Context.game.current_screen = "home"
|
||||
Util.go_to_screen_by_id("home")
|
||||
Window.set_current("game")
|
||||
-- Initialize home screen
|
||||
local home_screen = Screen.get_by_id("home")
|
||||
@@ -69,7 +69,7 @@ function EndWindow.update()
|
||||
end
|
||||
end
|
||||
elseif Context._end.state == "ending" then
|
||||
if Input.menu_confirm() then
|
||||
if Input.select() then
|
||||
Window.set_current("menu")
|
||||
MenuWindow.refresh_menu_items()
|
||||
end
|
||||
|
||||
@@ -38,7 +38,7 @@ end
|
||||
--- @within GameWindow
|
||||
function GameWindow.update()
|
||||
Focus.update()
|
||||
if Input.menu_back() then
|
||||
if Input.back() then
|
||||
Window.set_current("menu")
|
||||
MenuWindow.refresh_menu_items()
|
||||
return
|
||||
@@ -48,14 +48,6 @@ function GameWindow.update()
|
||||
if not screen or not screen.update then return end
|
||||
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
|
||||
|
||||
-- Fetch and filter decisions locally
|
||||
@@ -68,7 +60,7 @@ function GameWindow.update()
|
||||
_selected_decision_index = 1
|
||||
end
|
||||
|
||||
local new_selected_decision_index = Decision.update(
|
||||
local new_selected_decision_index, mouse_confirmed = Decision.update(
|
||||
_available_decisions,
|
||||
_selected_decision_index
|
||||
)
|
||||
@@ -77,7 +69,7 @@ function GameWindow.update()
|
||||
_selected_decision_index = new_selected_decision_index
|
||||
end
|
||||
|
||||
if Input.select() then
|
||||
if Input.select() or mouse_confirmed then
|
||||
local selected_decision = _available_decisions[_selected_decision_index]
|
||||
if selected_decision and selected_decision.handle then
|
||||
Audio.sfx_select()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- @section BriefIntroWindow
|
||||
BriefIntroWindow.y = Config.screen.height
|
||||
BriefIntroWindow.speed = 0.5
|
||||
BriefIntroWindow.speed = 30 -- pixels per second
|
||||
BriefIntroWindow.text = [[
|
||||
Norman Reds’ everyday life
|
||||
seems ordinary: work,
|
||||
@@ -24,14 +24,14 @@ end
|
||||
--- Updates the brief intro window logic.
|
||||
--- @within BriefIntroWindow
|
||||
function BriefIntroWindow.update()
|
||||
BriefIntroWindow.y = BriefIntroWindow.y - BriefIntroWindow.speed
|
||||
BriefIntroWindow.y = BriefIntroWindow.y - (BriefIntroWindow.speed * Context.delta_time)
|
||||
|
||||
local lines = 1
|
||||
for _ in string.gmatch(BriefIntroWindow.text, "\n") do
|
||||
lines = lines + 1
|
||||
end
|
||||
|
||||
if BriefIntroWindow.y < -lines * 8 or Input.select() or Input.menu_confirm() then
|
||||
if BriefIntroWindow.y < -lines * 8 or Input.select() or Input.select() then
|
||||
Window.set_current("menu")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
--- @section TitleIntroWindow
|
||||
TitleIntroWindow.timer = 180 -- 3 seconds at 60fps
|
||||
TitleIntroWindow.text = [[
|
||||
## ### ### ### ### ### ### ### ## # #
|
||||
# # # # # # # # # # # # # #
|
||||
# # ### ### # # # # # ### # # #
|
||||
## ### ### ### ### ### ### ### # # #
|
||||
# # # # # # # # # # # # #
|
||||
# # ### ### # # # # # ### # #
|
||||
# # # # # # # # # # # #
|
||||
## ### # ### # # ### # ### ## #
|
||||
|
||||
# # ### ### ## # #
|
||||
@@ -30,7 +30,7 @@ end
|
||||
--- @within TitleIntroWindow
|
||||
function TitleIntroWindow.update()
|
||||
TitleIntroWindow.timer = TitleIntroWindow.timer - 1
|
||||
if TitleIntroWindow.timer <= 0 or Input.select() or Input.menu_confirm() then
|
||||
if TitleIntroWindow.timer <= 0 or Input.select() or Input.select() then
|
||||
Window.set_current("intro_ttg")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
--- @section TTGIntroWindow
|
||||
TTGIntroWindow.timer = 180
|
||||
TTGIntroWindow.glitch_started = false
|
||||
TTGIntroWindow.space_count = 0
|
||||
TTGIntroWindow.space_timer = 0
|
||||
TTGIntroWindow.text = [[
|
||||
###### ###### ######
|
||||
## ## #
|
||||
@@ -25,8 +27,19 @@ function TTGIntroWindow.update()
|
||||
TTGIntroWindow.glitch_started = true
|
||||
end
|
||||
|
||||
-- Count enter presses during the intro
|
||||
if Input.enter() then
|
||||
TTGIntroWindow.space_count = TTGIntroWindow.space_count + 1
|
||||
end
|
||||
|
||||
TTGIntroWindow.timer = TTGIntroWindow.timer - 1
|
||||
if TTGIntroWindow.timer <= 0 or Input.select() or Input.menu_confirm() then
|
||||
if TTGIntroWindow.timer <= 0 or Input.select() then
|
||||
-- Evaluate exactly 3 presses at the end of the intro
|
||||
if TTGIntroWindow.space_count == 3 then
|
||||
Context.test_mode = true
|
||||
MenuWindow.refresh_menu_items()
|
||||
Audio.sfx_success()
|
||||
end
|
||||
Glitch.hide()
|
||||
Window.set_current("intro_brief")
|
||||
end
|
||||
|
||||
@@ -1,14 +1,64 @@
|
||||
--- @section MenuWindow
|
||||
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.black)
|
||||
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, Config.colors.transparent, 4)
|
||||
spr(273, nx + 32, ny, Config.colors.transparent, 4)
|
||||
spr(288, nx, ny + 32, Config.colors.transparent, 4)
|
||||
spr(289, nx + 32, ny + 32, Config.colors.transparent, 4)
|
||||
spr(304, nx, ny + 64, Config.colors.transparent, 4)
|
||||
spr(305, nx + 32, ny + 64, Config.colors.transparent, 4)
|
||||
end
|
||||
|
||||
--- Draws the menu window.
|
||||
--- @within MenuWindow
|
||||
function MenuWindow.draw()
|
||||
UI.draw_top_bar("Definitely not an Impostor")
|
||||
cls(Config.colors.blue
|
||||
)
|
||||
MenuWindow.draw_header()
|
||||
|
||||
if _anim > 0 then
|
||||
MenuWindow.draw_norman()
|
||||
end
|
||||
|
||||
local menu_h = #_menu_items * 10
|
||||
local y = 10 + (Config.screen.height - 10 - 10 - menu_h) / 2
|
||||
UI.draw_menu(_menu_items, Context.current_menu_item, 0, y, true)
|
||||
local y = HEADER_H + math.floor((Config.screen.height - HEADER_H - 10 - menu_h) / 2)
|
||||
UI.draw_menu(_menu_items, Context.current_menu_item, MenuWindow.calc_menu_x(), y, false)
|
||||
|
||||
local ttg_text = "TTG"
|
||||
local ttg_w = print(ttg_text, 0, -10, 0, false, 1, false)
|
||||
@@ -18,9 +68,32 @@ end
|
||||
--- Updates the menu window logic.
|
||||
--- @within MenuWindow
|
||||
function MenuWindow.update()
|
||||
Context.current_menu_item = UI.update_menu(_menu_items, Context.current_menu_item)
|
||||
if _anim < 1 then
|
||||
_anim = math.min(1, _anim + ANIM_SPEED * Context.delta_time)
|
||||
end
|
||||
|
||||
if Input.menu_confirm() then
|
||||
local menu_h = #_menu_items * 10
|
||||
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]
|
||||
if selected_item and selected_item.decision then
|
||||
Audio.sfx_select()
|
||||
@@ -60,11 +133,10 @@ function MenuWindow.exit()
|
||||
exit()
|
||||
end
|
||||
|
||||
--- Opens the configuration menu.
|
||||
--- Opens the controls screen.
|
||||
--- @within MenuWindow
|
||||
function MenuWindow.configuration()
|
||||
ConfigurationWindow.init()
|
||||
GameWindow.set_state("configuration")
|
||||
function MenuWindow.controls()
|
||||
Window.set_current("controls")
|
||||
end
|
||||
|
||||
--- Opens the audio test menu.
|
||||
@@ -81,7 +153,15 @@ function MenuWindow.continued()
|
||||
GameWindow.set_state("continued")
|
||||
end
|
||||
|
||||
--- Refreshes menu items.
|
||||
--- Opens the DDR minigame test.
|
||||
--- @within MenuWindow
|
||||
function MenuWindow.ddr_test()
|
||||
AudioTestWindow.init()
|
||||
GameWindow.set_state("minigame_ddr")
|
||||
MinigameDDRWindow.start("menu", "generated", { special_mode = "only_nothing" })
|
||||
end
|
||||
|
||||
--- Refreshes the list of menu items based on current game state.
|
||||
--- @within MenuWindow
|
||||
function MenuWindow.refresh_menu_items()
|
||||
_menu_items = {}
|
||||
@@ -92,10 +172,23 @@ function MenuWindow.refresh_menu_items()
|
||||
|
||||
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 = "Configuration", decision = MenuWindow.configuration})
|
||||
table.insert(_menu_items, {label = "Controls", decision = MenuWindow.controls})
|
||||
|
||||
if Context.test_mode then
|
||||
table.insert(_menu_items, {label = "Audio Test", decision = MenuWindow.audio_test})
|
||||
table.insert(_menu_items, {label = "To Be Continued...", decision = MenuWindow.continued})
|
||||
table.insert(_menu_items, {label = "DDR Test", decision = MenuWindow.ddr_test})
|
||||
end
|
||||
|
||||
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
|
||||
_click_timer = 0
|
||||
_anim = 0
|
||||
end
|
||||
|
||||
@@ -1,14 +1,62 @@
|
||||
--- @section MinigameDDRWindow
|
||||
|
||||
---@class MinigameDDRState
|
||||
---@field special_mode string
|
||||
---@field bar_fill number
|
||||
---@field max_fill number
|
||||
---@field fill_per_hit number
|
||||
---@field miss_penalty number
|
||||
---@field bar_x number
|
||||
---@field bar_y number
|
||||
---@field bar_width number
|
||||
---@field bar_height number
|
||||
---@field arrow_size number
|
||||
---@field arrow_spawn_timer number
|
||||
---@field arrow_spawn_interval number
|
||||
---@field arrow_fall_speed number
|
||||
---@field arrows table
|
||||
---@field target_y number
|
||||
---@field target_arrows table
|
||||
---@field hit_threshold number
|
||||
---@field button_pressed_timers table
|
||||
---@field button_press_duration number
|
||||
---@field input_cooldowns table
|
||||
---@field input_cooldown_duration number
|
||||
---@field frame_counter number
|
||||
---@field current_song table?
|
||||
---@field pattern_index number
|
||||
---@field use_pattern boolean
|
||||
---@field generated_length number
|
||||
---@field return_window string?
|
||||
---@field win_timer number
|
||||
---@field on_win fun(ctx: MinigameDDRState)|nil
|
||||
---@field total_misses number
|
||||
---@field total_hits number
|
||||
---@field special_mode_condition boolean
|
||||
---@field special_mode_counter number
|
||||
---@field debug_song_key string|nil
|
||||
---@field debug_status string|nil
|
||||
|
||||
--- Background drawing for DDR minigame.
|
||||
--- @within MinigameDDRWindow
|
||||
function MinigameDDRWindow.draw_background()
|
||||
local img_values = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}
|
||||
local img_runs = {809,40,5,26,178,42,4,7,30,10,127,103,11,1,116,124,116,124,115,18,60,47,115,10,105,10,115,9,108,9,114,9,108,9,114,9,108,9,114,9,33,31,44,9,114,9,34,28,46,9,114,9,108,9,114,9,108,9,114,9,108,9,114,9,108,9,114,9,109,8,114,9,109,8,114,9,109,9,112,10,105,1,3,9,111,11,104,2,3,9,111,11,101,5,3,9,111,11,101,5,3,9,111,9,103,5,3,9,111,9,99,1,2,6,3,9,111,9,99,1,2,8,1,9,111,9,3,1,88,1,3,1,2,11,1,9,111,9,3,1,88,1,3,14,1,9,111,9,3,1,88,1,3,1,2,11,1,9,111,9,3,1,88,1,5,12,1,9,111,9,3,1,88,1,3,14,1,9,111,9,3,1,88,3,1,1,2,11,1,9,111,9,3,1,88,3,1,14,1,9,111,9,3,1,88,3,2,13,2,8,111,9,3,1,88,3,3,12,3,8,110,9,3,1,88,3,3,12,3,9,109,9,3,1,88,3,1,14,3,9,109,9,3,1,90,1,1,7,3,4,3,9,109,9,3,1,90,1,1,5,6,3,3,9,108,10,3,1,44,1,4,1,40,1,1,5,7,2,3,9,108,10,3,1,44,1,4,1,38,3,1,5,7,3,2,9,108,10,3,1,48,1,39,3,1,5,7,2,3,9,108,10,3,1,88,3,1,5,6,3,3,9,108,10,3,1,32,5,4,4,3,2,38,3,1,15,2,9,108,10,3,1,41,5,2,2,2,4,32,3,1,15,2,9,108,10,2,2,41,9,2,5,3,1,3,1,23,3,1,9,1,5,2,9,108,10,2,2,41,12,35,3,1,7,4,4,2,9,108,10,2,2,32,26,30,3,1,5,7,3,2,9,108,10,2,2,36,21,31,9,7,3,2,9,108,10,2,2,35,23,30,10,6,3,2,9,108,10,2,2,35,23,30,11,4,4,2,9,108,10,2,2,34,24,30,19,2,9,108,10,2,2,33,25,30,19,2,9,108,10,2,2,32,28,28,19,2,9,108,10,2,2,32,30,26,19,2,9,108,10,2,2,33,31,24,19,2,9,108,10,2,4,37,17,32,19,2,10,107,10,2,5,85,19,2,10,107,10,2,109,2,10,107,12,1,107,3,10,107,133,107,133,107,133,107,133,107,133,107,133,107,133,118,111,129,6,63,3,28,10,121,13,98,6,142,7,76,6,129,10,13,5,77,15,109,4,31,4,78,4,24,7,75,173,66,176,64,177,62,178,62,178,62,56,31,2,7,2,2,3,2,1,2,1,61,8,62,56,114,8,62,56,114,8,62,56,114,8,62,56,114,8,62,9,8,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,114,9,61,8,9,39,115,8,61,8,8,40,115,8,61,56,115,8,61,13,2,1,1,1,1,16,1,1,2,17,115,8,61,13,2,1,1,1,2,1,1,10,2,1,1,1,2,1,2,7,1,6,115,8,60,14,2,1,1,1,5,9,2,1,1,1,2,1,2,6,2,6,115,8,59,15,2,1,1,1,5,9,2,1,1,1,2,1,2,6,2,6,115,8,59,15,2,1,1,1,6,8,2,1,1,1,2,1,2,14,115,8,59,6,1,11,1,1,7,10,1,1,2,1,2,14,115,8,59,6,1,11,1,1,7,10,1,1,2,1,2,1,1,12,115,9,58,6,1,1,2,10,9,8,1,1,2,1,2,1,1,12,115,9,58,6,1,1,2,8,1,1,9,8,1,1,2,1,2,1,1,11,116,9,58,6,1,1,2,1,2,7,9,8,1,1,2,1,2,1,1,11,116,9,58,6,1,1,2,1,2,7,9,10,2,1,2,1,1,11,116,9,58,57,116,9,58,58,115,9,102,13,116,9,58,48,2,10,1,3,22,84,5,7,58,158,7,5,6,6,75,3,7,2,7,1,7,2,6,1,6,2,6,2,4,4,6,2,6,1,6,2,6,3,6,1,6,5,7,8,7,9,11,1,9,2,50,1,22,1,14,5,3,5,3,4,3,6,3,5,2,16,2,5,3,14,2,6,2,6,5,5,11,4,30,1,50,1,37,6,3,5,3,5,2,6,3,5,3,6,1,7,2,6,2,15,2,6,2,5,6,5,12,1,15,1,106,93,2,8,10,5,2,6,2,5,4,4,100,7,3,13,2,65,3,8,3,5,2,5,4,4,3,5,4,4,100,94,2,5,3,5,4,4,6,5,2,5,105,86,2,13,3,5,4,4,6,5,2,1,1,3,102,4,2,24,2,62,1,1,2,7,3,5,4,5,4,5,2,8,4,2,92,5,2,24,2,61,5,5,7,2,5,6,3,4,3,7,102,88,6,7,12,8,6,1,3,7,103,87,6,7,11,9,6,1,3,7,110,1,9,9,5,1,2,1,3,47,162,1,10,6,27,34,162,1,10,6,27,34,97,3,57,14,2,7,26,66,9,33,5,2,17,223,17,223,18,222,47,193,53,1,3,163,19,1,85,109,14,29,36,151,784}
|
||||
-- pal = {220,220,220,90,90,90}
|
||||
-- pal = dcdcdc5a5a5a
|
||||
RLE.draw(img_values, img_runs)
|
||||
end
|
||||
|
||||
--- Gets initial DDR minigame configuration.
|
||||
--- @within MinigameDDRWindow
|
||||
--- @return result table The default DDR minigame configuration.
|
||||
---@return MinigameDDRState
|
||||
function MinigameDDRWindow.init_context()
|
||||
local arrow_size = 12
|
||||
local arrow_spacing = 30
|
||||
local total_width = (4 * arrow_size) + (3 * arrow_spacing)
|
||||
local start_x = (Config.screen.width - total_width) / 2
|
||||
return {
|
||||
special_mode = "normal", -- "normal", "only_special", "only_left", "only_nothing"
|
||||
bar_fill = 0,
|
||||
max_fill = 100,
|
||||
fill_per_hit = 10,
|
||||
@@ -22,7 +70,7 @@ function MinigameDDRWindow.init_context()
|
||||
arrow_spawn_interval = 45,
|
||||
arrow_fall_speed = 1.5,
|
||||
arrows = {},
|
||||
target_y = 115,
|
||||
target_y = 120,
|
||||
target_arrows = {
|
||||
{ dir = "left", x = start_x },
|
||||
{ dir = "down", x = start_x + arrow_size + arrow_spacing },
|
||||
@@ -38,12 +86,95 @@ function MinigameDDRWindow.init_context()
|
||||
current_song = nil,
|
||||
pattern_index = 1,
|
||||
use_pattern = false,
|
||||
generated_length = 30,
|
||||
return_window = nil,
|
||||
win_timer = 0,
|
||||
on_win = nil
|
||||
on_win = nil,
|
||||
total_misses = 0,
|
||||
total_hits = 0,
|
||||
special_mode_condition = true,
|
||||
special_mode_counter = 0
|
||||
}
|
||||
end
|
||||
|
||||
--- Builds song data (and optional generated pattern) for the minigame.
|
||||
--- @within MinigameDDRWindow
|
||||
function MinigameDDRWindow.prepareSong(song, generated_length, special_mode)
|
||||
local current_song = Util.deepcopy(song)
|
||||
|
||||
if current_song.generated then
|
||||
local pattern = musicator_generate_pattern(generated_length, current_song.bpm, current_song.spd * 4)
|
||||
current_song.pattern = pattern
|
||||
current_song.end_frame = pattern[#pattern].frame
|
||||
|
||||
if special_mode == "only_special" then
|
||||
for i, _ in ipairs(current_song.pattern) do
|
||||
current_song.pattern[i].special = (i % 5 == 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return current_song
|
||||
end
|
||||
|
||||
--- Handles hit feedback and special-mode scoring for one arrow.
|
||||
--- @within MinigameDDRWindow
|
||||
---@param game_context MinigameDDRState
|
||||
function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context)
|
||||
local special_mode = game_context.special_mode
|
||||
|
||||
if special_mode == "normal" then
|
||||
Audio.sfx_arrowhit(arrow.note)
|
||||
elseif special_mode == "only_special" then
|
||||
if arrow.special then
|
||||
Audio.sfx_arrowhit(arrow.note)
|
||||
game_context.special_mode_counter = game_context.special_mode_counter + 1
|
||||
else
|
||||
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||
game_context.special_mode_condition = false
|
||||
end
|
||||
elseif special_mode == "only_left" then
|
||||
if arrow.dir == "left" then
|
||||
Audio.sfx_arrowhit(arrow.note)
|
||||
game_context.special_mode_counter = game_context.special_mode_counter + 1
|
||||
if game_context.max_fill <= game_context.bar_fill + game_context.fill_per_hit then
|
||||
game_context.bar_fill = game_context.bar_fill - game_context.fill_per_hit
|
||||
end
|
||||
else
|
||||
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||
game_context.special_mode_condition = false
|
||||
end
|
||||
elseif special_mode == "only_nothing" then
|
||||
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||
game_context.special_mode_condition = false
|
||||
end
|
||||
end
|
||||
|
||||
--- Ends the minigame: win timer, sfx, and special-mode pass/fail bookkeeping.
|
||||
--- @within MinigameDDRWindow
|
||||
function MinigameDDRWindow.on_end(game_context)
|
||||
Audio.sfx_select()
|
||||
|
||||
game_context.win_timer = Config.timing.minigame_win_duration
|
||||
|
||||
local num_special = 0
|
||||
for _, v in ipairs(game_context.current_song.pattern) do
|
||||
if game_context.special_mode == "only_left" then
|
||||
num_special = num_special + ((v.dir == "left" and 1) or 0)
|
||||
else
|
||||
num_special = num_special + ((v.special and 1) or 0)
|
||||
end
|
||||
end
|
||||
|
||||
local sm = game_context.special_mode
|
||||
local was_ok = true
|
||||
if sm == "normal" or sm == "only_special" or sm == "only_left" then
|
||||
was_ok = game_context.special_mode_counter == num_special
|
||||
end
|
||||
|
||||
game_context.special_mode_condition = game_context.special_mode_condition and was_ok
|
||||
end
|
||||
|
||||
--- Initializes DDR minigame state.
|
||||
--- @within MinigameDDRWindow
|
||||
--- @param params table Optional parameters for configuration.<br/>
|
||||
@@ -64,13 +195,22 @@ end
|
||||
--- @param[opt] params table Optional parameters for minigame configuration.</br>
|
||||
function MinigameDDRWindow.start(return_window, song_key, params)
|
||||
MinigameDDRWindow.init(params)
|
||||
|
||||
Audio.music_play_activity_work()
|
||||
|
||||
Context.minigame_ddr.return_window = return_window or "game"
|
||||
Context.minigame_ddr.debug_song_key = song_key
|
||||
if song_key and Songs and Songs[song_key] then
|
||||
Context.minigame_ddr.current_song = Songs[song_key]
|
||||
Context.minigame_ddr.use_pattern = true
|
||||
Context.minigame_ddr.pattern_index = 1
|
||||
Context.minigame_ddr.debug_status = "Pattern loaded: " .. song_key
|
||||
|
||||
Context.minigame_ddr.current_song = MinigameDDRWindow.prepareSong(
|
||||
Songs[song_key],
|
||||
Context.minigame_ddr.generated_length,
|
||||
Context.minigame_ddr.special_mode
|
||||
)
|
||||
|
||||
else
|
||||
Context.minigame_ddr.use_pattern = false
|
||||
if song_key then
|
||||
@@ -79,32 +219,45 @@ function MinigameDDRWindow.start(return_window, song_key, params)
|
||||
Context.minigame_ddr.debug_status = "Random mode"
|
||||
end
|
||||
end
|
||||
|
||||
if not Context.test_mode then
|
||||
Context.minigame_ddr.debug_status = ""
|
||||
end
|
||||
|
||||
Window.set_current("minigame_ddr")
|
||||
end
|
||||
|
||||
--- Spawns a random arrow.
|
||||
--- @within MinigameDDRWindow
|
||||
local function spawn_arrow()
|
||||
trace("random arrow")
|
||||
|
||||
---@type MinigameDDRState
|
||||
local mg = Context.minigame_ddr
|
||||
local y0 = mg.bar_y + mg.bar_height + 10
|
||||
local target = mg.target_arrows[math.random(1, 4)]
|
||||
table.insert(mg.arrows, {
|
||||
dir = target.dir,
|
||||
x = target.x,
|
||||
y = mg.bar_y + mg.bar_height + 10
|
||||
y = y0
|
||||
})
|
||||
end
|
||||
|
||||
--- Spawns an arrow in a specific direction.
|
||||
--- @within MinigameDDRWindow
|
||||
--- @param direction string The direction of the arrow ("left", "down", "up", "right").
|
||||
local function spawn_arrow_dir(direction)
|
||||
local function spawn_arrow_dir(direction, note, special)
|
||||
---@type MinigameDDRState
|
||||
local mg = Context.minigame_ddr
|
||||
local y0 = mg.bar_y + mg.bar_height + 10
|
||||
for _, target in ipairs(mg.target_arrows) do
|
||||
if target.dir == direction then
|
||||
table.insert(mg.arrows, {
|
||||
dir = direction,
|
||||
x = target.x,
|
||||
y = mg.bar_y + mg.bar_height + 10
|
||||
y = y0,
|
||||
note = note,
|
||||
special = special
|
||||
})
|
||||
break
|
||||
end
|
||||
@@ -116,6 +269,7 @@ end
|
||||
--- @param arrow table The arrow data.
|
||||
--- @return boolean True if the arrow is hit, false otherwise.
|
||||
local function check_hit(arrow)
|
||||
---@type MinigameDDRState
|
||||
local mg = Context.minigame_ddr
|
||||
local distance = math.abs(arrow.y - mg.target_y)
|
||||
return distance <= mg.hit_threshold
|
||||
@@ -126,34 +280,53 @@ end
|
||||
--- @param arrow table The arrow data.
|
||||
--- @return boolean True if the arrow is missed, false otherwise.
|
||||
local function check_miss(arrow)
|
||||
---@type MinigameDDRState
|
||||
local mg = Context.minigame_ddr
|
||||
return arrow.y > mg.target_y + mg.hit_threshold
|
||||
end
|
||||
|
||||
--- Draws an arrow.
|
||||
--- Rotates a point (px, py) around (cx, cy) by a number of 90-degree CW steps.
|
||||
--- @within MinigameDDRWindow
|
||||
local function rotate(px, py, cx, cy, steps)
|
||||
local dx, dy = px - cx, py - cy
|
||||
for _ = 1, steps % 4 do
|
||||
dx, dy = dy, -dx
|
||||
end
|
||||
return cx + dx, cy + dy
|
||||
end
|
||||
|
||||
local arrow_rotations = { down = 0, right = 1, up = 2, left = 3 }
|
||||
|
||||
--- Draws an arrow by rotating the "down" arrow shape.
|
||||
--- @within MinigameDDRWindow
|
||||
--- @param x number The x-coordinate.
|
||||
--- @param y number The y-coordinate.
|
||||
--- @param direction string The direction of the arrow.
|
||||
--- @param color number The color of the arrow.
|
||||
local function draw_arrow(x, y, direction, color)
|
||||
local size = 12
|
||||
local size = 14
|
||||
local half = size / 2
|
||||
if direction == "left" then
|
||||
tri(x + half, y, x, y + half, x + half, y + size, color)
|
||||
rect(x + half, y + half - 2, half, 4, color)
|
||||
elseif direction == "right" then
|
||||
tri(x + half, y, x + size, y + half, x + half, y + size, color)
|
||||
rect(x, y + half - 2, half, 4, color)
|
||||
elseif direction == "up" then
|
||||
tri(x, y + half, x + half, y, x + size, y + half, color)
|
||||
rect(x + half - 2, y + half, 4, half, color)
|
||||
elseif direction == "down" then
|
||||
tri(x, y + half, x + half, y + size, x + size, y + half, color)
|
||||
rect(x + half - 2, y, 4, half, color)
|
||||
end
|
||||
local pivot_x, pivot_y = x + half, y + half
|
||||
local steps = arrow_rotations[direction] or 0
|
||||
|
||||
local head_left_x, head_left_y = rotate(x, y + half, pivot_x, pivot_y, steps)
|
||||
local head_tip_x, head_tip_y = rotate(x + half, y + size, pivot_x, pivot_y, steps)
|
||||
local head_right_x, head_right_y = rotate(x + size, y + half, pivot_x, pivot_y, steps)
|
||||
|
||||
tri(head_left_x, head_left_y,
|
||||
head_tip_x, head_tip_y,
|
||||
head_right_x, head_right_y, color)
|
||||
|
||||
local stem_top_x, stem_top_y = rotate(x + half - 3, y, pivot_x, pivot_y, steps)
|
||||
local stem_bot_x, stem_bot_y = rotate(x + half + 3, y + half, pivot_x, pivot_y, steps)
|
||||
local stem_x = math.min(stem_top_x, stem_bot_x)
|
||||
local stem_y = math.min(stem_top_y, stem_bot_y)
|
||||
local stem_w = math.abs(stem_bot_x - stem_top_x)
|
||||
local stem_h = math.abs(stem_bot_y - stem_top_y)
|
||||
rectb(stem_x, stem_y, stem_w, stem_h, color)
|
||||
end
|
||||
|
||||
|
||||
--- Updates DDR minigame logic.
|
||||
--- @within MinigameDDRWindow
|
||||
function MinigameDDRWindow.update()
|
||||
@@ -162,9 +335,10 @@ function MinigameDDRWindow.update()
|
||||
if mg.win_timer > 0 then
|
||||
mg.win_timer = mg.win_timer - 1
|
||||
if mg.win_timer == 0 then
|
||||
Audio.music_stop()
|
||||
Meter.on_minigame_complete()
|
||||
if mg.on_win then
|
||||
mg.on_win()
|
||||
mg.on_win(mg)
|
||||
else
|
||||
Meter.show()
|
||||
Window.set_current(mg.return_window)
|
||||
@@ -174,22 +348,26 @@ function MinigameDDRWindow.update()
|
||||
end
|
||||
|
||||
if mg.bar_fill >= mg.max_fill then
|
||||
mg.win_timer = Config.timing.minigame_win_duration
|
||||
MinigameDDRWindow.on_end(mg)
|
||||
return
|
||||
end
|
||||
|
||||
mg.frame_counter = mg.frame_counter + 1
|
||||
|
||||
if mg.use_pattern and mg.current_song and mg.current_song.end_frame then
|
||||
if mg.frame_counter > mg.current_song.end_frame and #mg.arrows == 0 then
|
||||
mg.win_timer = Config.timing.minigame_win_duration
|
||||
MinigameDDRWindow.on_end(mg)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if mg.use_pattern and mg.current_song and mg.current_song.pattern then
|
||||
local pattern = mg.current_song.pattern
|
||||
while mg.pattern_index <= #pattern do
|
||||
local spawn_entry = pattern[mg.pattern_index]
|
||||
|
||||
if mg.frame_counter >= spawn_entry.frame then
|
||||
spawn_arrow_dir(spawn_entry.dir)
|
||||
spawn_arrow_dir(spawn_entry.dir, spawn_entry.note, spawn_entry.special)
|
||||
mg.pattern_index = mg.pattern_index + 1
|
||||
else
|
||||
break
|
||||
@@ -202,37 +380,48 @@ function MinigameDDRWindow.update()
|
||||
mg.arrow_spawn_timer = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- move arrow downwards
|
||||
local arrows_to_remove = {}
|
||||
for i, arrow in ipairs(mg.arrows) do
|
||||
arrow.y = arrow.y + mg.arrow_fall_speed
|
||||
if check_miss(arrow) then
|
||||
table.insert(arrows_to_remove, i)
|
||||
mg.bar_fill = mg.bar_fill - mg.miss_penalty
|
||||
if mg.bar_fill < 0 then
|
||||
mg.bar_fill = 0
|
||||
end
|
||||
mg.bar_fill = math.max(0, mg.bar_fill - mg.miss_penalty)
|
||||
mg.total_misses = mg.total_misses + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- iterate backwards to avoid index shift issues
|
||||
for i = #arrows_to_remove, 1, -1 do
|
||||
table.remove(mg.arrows, arrows_to_remove[i])
|
||||
end
|
||||
|
||||
for dir, _ in pairs(mg.input_cooldowns) do
|
||||
if mg.input_cooldowns[dir] > 0 then
|
||||
mg.input_cooldowns[dir] = mg.input_cooldowns[dir] - 1
|
||||
end
|
||||
end
|
||||
|
||||
for dir, _ in pairs(mg.button_pressed_timers) do
|
||||
if mg.button_pressed_timers[dir] > 0 then
|
||||
mg.button_pressed_timers[dir] = mg.button_pressed_timers[dir] - 1
|
||||
end
|
||||
end
|
||||
|
||||
local input_map = {
|
||||
left = Input.left(),
|
||||
down = Input.down(),
|
||||
up = Input.up(),
|
||||
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
|
||||
if pressed and mg.input_cooldowns[dir] == 0 then
|
||||
mg.input_cooldowns[dir] = mg.input_cooldown_duration
|
||||
@@ -240,20 +429,17 @@ function MinigameDDRWindow.update()
|
||||
local hit = false
|
||||
for i, arrow in ipairs(mg.arrows) do
|
||||
if arrow.dir == dir and check_hit(arrow) then
|
||||
mg.bar_fill = mg.bar_fill + mg.fill_per_hit
|
||||
if mg.bar_fill > mg.max_fill then
|
||||
mg.bar_fill = mg.max_fill
|
||||
end
|
||||
MinigameDDRWindow.on_arrow_hit_special(arrow, mg)
|
||||
|
||||
mg.bar_fill = math.min(mg.max_fill, mg.bar_fill + mg.fill_per_hit)
|
||||
table.remove(mg.arrows, i)
|
||||
hit = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not hit then
|
||||
mg.bar_fill = mg.bar_fill - 2
|
||||
if mg.bar_fill < 0 then
|
||||
mg.bar_fill = 0
|
||||
end
|
||||
mg.bar_fill = math.max(0, mg.bar_fill - 2)
|
||||
mg.total_misses = mg.total_misses + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -262,6 +448,7 @@ end
|
||||
--- Draws DDR minigame.
|
||||
--- @within MinigameDDRWindow
|
||||
function MinigameDDRWindow.draw()
|
||||
---@type MinigameDDRState|nil
|
||||
local mg = Context.minigame_ddr
|
||||
if not mg then
|
||||
cls(0)
|
||||
@@ -272,13 +459,14 @@ function MinigameDDRWindow.draw()
|
||||
end
|
||||
return
|
||||
end
|
||||
if mg.return_window == "game" then
|
||||
GameWindow.draw()
|
||||
end
|
||||
-- if mg.return_window == "game" then
|
||||
-- GameWindow.draw()
|
||||
-- end
|
||||
rect(0, 0, Config.screen.width, Config.screen.height, Config.colors.black)
|
||||
rect(mg.bar_x - 2, mg.bar_y - 2, mg.bar_width + 4, mg.bar_height + 4, Config.colors.light_grey)
|
||||
rectb(mg.bar_x - 2, mg.bar_y - 2, mg.bar_width + 4, mg.bar_height + 4, Config.colors.dark_grey)
|
||||
local fill_width = (mg.bar_fill / mg.max_fill) * mg.bar_width
|
||||
MinigameDDRWindow.draw_background()
|
||||
if fill_width > 0 then
|
||||
local bar_color = Config.colors.light_blue
|
||||
if mg.bar_fill > 66 then
|
||||
@@ -288,8 +476,6 @@ function MinigameDDRWindow.draw()
|
||||
end
|
||||
rect(mg.bar_x, mg.bar_y, fill_width, mg.bar_height, bar_color)
|
||||
end
|
||||
local percentage = math.floor((mg.bar_fill / mg.max_fill) * 100)
|
||||
Print.text_center(percentage .. "%", mg.bar_x + mg.bar_width / 2, mg.bar_y + 2, Config.colors.black)
|
||||
if mg.target_arrows then
|
||||
for _, target in ipairs(mg.target_arrows) do
|
||||
local is_pressed = mg.button_pressed_timers[target.dir] and mg.button_pressed_timers[target.dir] > 0
|
||||
@@ -299,16 +485,17 @@ function MinigameDDRWindow.draw()
|
||||
end
|
||||
if mg.arrows then
|
||||
for _, arrow in ipairs(mg.arrows) do
|
||||
draw_arrow(arrow.x, arrow.y, arrow.dir, Config.colors.blue)
|
||||
local arrow_color = arrow.special and Config.colors.white or Config.colors.blue
|
||||
draw_arrow(arrow.x, arrow.y, arrow.dir, arrow_color)
|
||||
end
|
||||
end
|
||||
Print.text_center("Hit the arrows!", Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_grey)
|
||||
Print.text_center_contour("Hit the arrows!", Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_blue)
|
||||
local debug_y = 60
|
||||
if mg.debug_status then
|
||||
Print.text_center(mg.debug_status, Config.screen.width / 2, debug_y, Config.colors.item)
|
||||
debug_y = debug_y + 10
|
||||
end
|
||||
if mg.use_pattern then
|
||||
if mg.use_pattern and Context.test_mode then
|
||||
Print.text_center(
|
||||
"PATTERN MODE - Frame:" .. mg.frame_counter,
|
||||
Config.screen.width / 2,
|
||||
@@ -323,10 +510,17 @@ function MinigameDDRWindow.draw()
|
||||
Config.colors.light_blue
|
||||
)
|
||||
end
|
||||
else
|
||||
elseif Context.test_mode then
|
||||
Print.text_center("RANDOM MODE", Config.screen.width / 2, debug_y, Config.colors.blue)
|
||||
end
|
||||
if mg.win_timer > 0 then
|
||||
|
||||
if mg.win_timer > 0 then
|
||||
if mg.special_mode_condition then
|
||||
Minigame.draw_win_overlay("SUCCESS...?")
|
||||
elseif mg.total_hits < 10 then
|
||||
Minigame.draw_win_overlay("MEH...")
|
||||
else
|
||||
Minigame.draw_win_overlay()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -49,6 +49,7 @@ end
|
||||
--- @param return_window string The window ID to return to after the minigame.<br/>
|
||||
--- @param[opt] params table Optional parameters for minigame configuration.<br/>
|
||||
function MinigameButtonMashWindow.start(return_window, params)
|
||||
Audio.music_stop()
|
||||
MinigameButtonMashWindow.init(params)
|
||||
local mg = Context.minigame_button_mash
|
||||
mg.return_window = return_window or "game"
|
||||
@@ -70,6 +71,9 @@ function MinigameButtonMashWindow.update()
|
||||
if mg.win_timer == 0 then
|
||||
Meter.on_minigame_complete()
|
||||
if mg.focus_center_x then Focus.stop() end
|
||||
Context.home_norman_visible = true
|
||||
Context.have_done_work_today = false
|
||||
Context.have_been_to_office = false
|
||||
if mg.on_win then
|
||||
mg.on_win()
|
||||
else
|
||||
@@ -80,7 +84,11 @@ function MinigameButtonMashWindow.update()
|
||||
return
|
||||
end
|
||||
|
||||
if Input.select() then
|
||||
local mouse_on_button = Mouse.zone_circle({ x = mg.button_x, y = mg.button_y, r = mg.button_size })
|
||||
|
||||
if Input.select() or mouse_on_button then
|
||||
Audio.sfx_drum_high()
|
||||
|
||||
mg.bar_fill = mg.bar_fill + mg.fill_per_press
|
||||
mg.button_pressed_timer = mg.button_press_duration
|
||||
if mg.bar_fill > mg.target_points then
|
||||
@@ -88,6 +96,7 @@ function MinigameButtonMashWindow.update()
|
||||
end
|
||||
end
|
||||
if mg.bar_fill >= mg.target_points then
|
||||
Audio.sfx_select()
|
||||
mg.win_timer = Config.timing.minigame_win_duration
|
||||
return
|
||||
end
|
||||
@@ -137,7 +146,7 @@ function MinigameButtonMashWindow.draw()
|
||||
circ(mg.button_x, mg.button_y, mg.button_size - 2, button_color)
|
||||
end
|
||||
Print.text_center("Z", mg.button_x, mg.button_y - 3, button_color)
|
||||
Print.text_center(mg.instruction_text, Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_grey)
|
||||
Print.text_center_contour(mg.instruction_text, Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_blue)
|
||||
if mg.show_progress_text then
|
||||
local points_text = math.floor(mg.bar_fill) .. "/" .. mg.target_points
|
||||
Print.text_center(points_text, mg.bar_x + mg.bar_width / 2, mg.bar_y + 2, Config.colors.black)
|
||||
|
||||
@@ -53,6 +53,7 @@ end
|
||||
--- @param return_window string The window ID to return to after the minigame.<br/>
|
||||
--- @param[opt] params table Optional parameters for minigame configuration.<br/>
|
||||
function MinigameRhythmWindow.start(return_window, params)
|
||||
Audio.music_stop()
|
||||
MinigameRhythmWindow.init(params)
|
||||
local mg = Context.minigame_rhythm
|
||||
mg.return_window = return_window or "game"
|
||||
@@ -95,7 +96,9 @@ function MinigameRhythmWindow.update()
|
||||
if mg.press_cooldown > 0 then
|
||||
mg.press_cooldown = mg.press_cooldown - 1
|
||||
end
|
||||
if Input.select() and mg.press_cooldown == 0 then
|
||||
local mouse_on_button = Mouse.zone_circle({ x = mg.button_x, y = mg.button_y, r = mg.button_size })
|
||||
|
||||
if (Input.select() or mouse_on_button) and mg.press_cooldown == 0 then
|
||||
mg.button_pressed_timer = mg.button_press_duration
|
||||
mg.press_cooldown = mg.press_cooldown_duration
|
||||
local target_left = mg.target_center - (mg.target_width / 2)
|
||||
@@ -114,6 +117,7 @@ function MinigameRhythmWindow.update()
|
||||
end
|
||||
end
|
||||
if mg.score >= mg.max_score then
|
||||
Audio.sfx_select()
|
||||
mg.win_timer = Config.timing.minigame_win_duration
|
||||
return
|
||||
end
|
||||
@@ -143,14 +147,14 @@ function MinigameRhythmWindow.draw()
|
||||
local target_left = mg.target_center - (mg.target_width / 2)
|
||||
local target_x = mg.bar_x + (target_left * mg.bar_width)
|
||||
local target_width_pixels = mg.target_width * mg.bar_width
|
||||
rect(target_x, mg.bar_y, target_width_pixels, mg.bar_height, Config.colors.light_blue)
|
||||
rect(target_x, mg.bar_y, target_width_pixels, mg.bar_height, Config.colors.orange)
|
||||
local line_x = mg.bar_x + (mg.line_position * mg.bar_width)
|
||||
rect(line_x - 1, mg.bar_y, 2, mg.bar_height, Config.colors.item)
|
||||
Print.text_center(
|
||||
rect(line_x - 1, mg.bar_y, 2, mg.bar_height, Config.colors.light_blue)
|
||||
Print.text_center_contour(
|
||||
"Sleep Norman ... Sleep!",
|
||||
Config.screen.width / 2,
|
||||
mg.bar_y + mg.bar_height + 14,
|
||||
Config.colors.light_grey
|
||||
Config.colors.light_blue
|
||||
)
|
||||
local button_color = Config.colors.light_grey
|
||||
if mg.button_pressed_timer > 0 then
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
--- @section MysteriousManWindow
|
||||
|
||||
local STATE_TEXT = "text"
|
||||
local STATE_DAY = "day"
|
||||
local STATE_CHOICE = "choice"
|
||||
|
||||
local DEFAULT_TEXT = [[
|
||||
Misterious man appears
|
||||
during your sleep.
|
||||
|
||||
He says nothing.
|
||||
He doesn't need to.
|
||||
|
||||
He says nothing.
|
||||
]]
|
||||
|
||||
local state = STATE_TEXT
|
||||
local text_y = Config.screen.height
|
||||
local text_speed = 0.4
|
||||
local day_timer = 0
|
||||
local day_display_frames = 120
|
||||
local selected_choice = 1
|
||||
local text = DEFAULT_TEXT
|
||||
local day_text_override = nil
|
||||
local on_text_complete = nil
|
||||
|
||||
local choices = {
|
||||
{
|
||||
label = "Wake Up",
|
||||
},
|
||||
{
|
||||
label = "Stay in Bed",
|
||||
},
|
||||
}
|
||||
|
||||
--- Sets the scrolling text content.
|
||||
--- @within MysteriousManWindow
|
||||
--- @param new_text string The text to display.
|
||||
function MysteriousManWindow.set_text(new_text)
|
||||
text = new_text
|
||||
end
|
||||
|
||||
--- Starts the mysterious man window.
|
||||
--- @within MysteriousManWindow
|
||||
--- @param[opt] options table Optional window configuration.</br>
|
||||
--- Fields: </br>
|
||||
--- * text (string) Override for the scrolling text.<br/>
|
||||
--- * day_text (string) Override for the centered day label.<br/>
|
||||
--- * on_text_complete (function) Callback fired once when the text phase ends.<br/>
|
||||
function MysteriousManWindow.start(options)
|
||||
options = options or {}
|
||||
state = STATE_TEXT
|
||||
text_y = Config.screen.height
|
||||
day_timer = 0
|
||||
selected_choice = 1
|
||||
text = options.text or DEFAULT_TEXT
|
||||
day_text_override = options.day_text
|
||||
on_text_complete = options.on_text_complete
|
||||
Meter.hide()
|
||||
Window.set_current("mysterious_man")
|
||||
end
|
||||
|
||||
local function go_to_day_state()
|
||||
if on_text_complete then
|
||||
on_text_complete()
|
||||
on_text_complete = nil
|
||||
end
|
||||
if Window.get_current_id() ~= "mysterious_man" then
|
||||
return
|
||||
end
|
||||
state = STATE_DAY
|
||||
day_timer = day_display_frames
|
||||
end
|
||||
|
||||
local function wake_up()
|
||||
Context.home_norman_visible = false
|
||||
Util.go_to_screen_by_id("home")
|
||||
MinigameButtonMashWindow.start("game", {
|
||||
focus_center_x = (Config.screen.width / 2) - 22,
|
||||
focus_center_y = (Config.screen.height / 2) - 18,
|
||||
focus_initial_radius = 0,
|
||||
target_points = 100,
|
||||
instruction_text = "Wake up Norman!",
|
||||
show_progress_text = false,
|
||||
on_win = function()
|
||||
Audio.music_play_wakingup()
|
||||
Context.home_norman_visible = true
|
||||
Meter.show()
|
||||
Window.set_current("game")
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
local function stay_in_bed()
|
||||
Day.increase()
|
||||
state = STATE_DAY
|
||||
day_timer = day_display_frames
|
||||
end
|
||||
|
||||
--- Updates the mysterious man window logic.
|
||||
--- @within MysteriousManWindow
|
||||
function MysteriousManWindow.update()
|
||||
if state == STATE_TEXT then
|
||||
text_y = text_y - text_speed
|
||||
|
||||
local lines = 1
|
||||
for _ in string.gmatch(text, "\n") do
|
||||
lines = lines + 1
|
||||
end
|
||||
|
||||
if text_y < -lines * 8 then
|
||||
go_to_day_state()
|
||||
end
|
||||
|
||||
if Input.select() then
|
||||
go_to_day_state()
|
||||
end
|
||||
elseif state == STATE_DAY then
|
||||
day_timer = day_timer - 1
|
||||
|
||||
if day_timer <= 0 or Input.select() then
|
||||
state = STATE_CHOICE
|
||||
selected_choice = 1
|
||||
end
|
||||
elseif state == STATE_CHOICE then
|
||||
selected_choice = UI.update_menu(choices, selected_choice)
|
||||
|
||||
if Input.select() then
|
||||
Audio.sfx_select()
|
||||
if selected_choice == 1 then
|
||||
wake_up()
|
||||
else
|
||||
stay_in_bed()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Draws the mysterious man window.
|
||||
--- @within MysteriousManWindow
|
||||
function MysteriousManWindow.draw()
|
||||
rect(0, 0, Config.screen.width, Config.screen.height, Config.colors.black)
|
||||
|
||||
if state == STATE_TEXT then
|
||||
local x = (Config.screen.width - 132) / 2
|
||||
Print.text(text, x, text_y, Config.colors.light_grey)
|
||||
elseif state == STATE_DAY then
|
||||
local day_text = day_text_override or ("Day " .. Context.day_count)
|
||||
Print.text_center(
|
||||
day_text,
|
||||
Config.screen.width / 2,
|
||||
Config.screen.height / 2 - 3,
|
||||
Config.colors.white
|
||||
)
|
||||
elseif state == STATE_CHOICE then
|
||||
local menu_x = (Config.screen.width - 60) / 2
|
||||
local menu_y = (Config.screen.height - 20) / 2
|
||||
UI.draw_menu(choices, selected_choice, menu_x, menu_y)
|
||||
end
|
||||
end
|
||||
@@ -28,7 +28,7 @@ end
|
||||
--- @within PopupWindow
|
||||
function PopupWindow.update()
|
||||
if Context.popup.show then
|
||||
if Input.menu_confirm() or Input.menu_back() then
|
||||
if Input.select() or Input.back() then
|
||||
PopupWindow.hide()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,8 +16,8 @@ Window.register("game", GameWindow)
|
||||
PopupWindow = {}
|
||||
Window.register("popup", PopupWindow)
|
||||
|
||||
ConfigurationWindow = {}
|
||||
Window.register("configuration", ConfigurationWindow)
|
||||
ControlsWindow = {}
|
||||
Window.register("controls", ControlsWindow)
|
||||
|
||||
AudioTestWindow = {}
|
||||
Window.register("audiotest", AudioTestWindow)
|
||||
@@ -31,9 +31,6 @@ Window.register("minigame_rhythm", MinigameRhythmWindow)
|
||||
MinigameDDRWindow = {}
|
||||
Window.register("minigame_ddr", MinigameDDRWindow)
|
||||
|
||||
MysteriousManWindow = {}
|
||||
Window.register("mysterious_man", MysteriousManWindow)
|
||||
|
||||
EndWindow = {}
|
||||
Window.register("end", EndWindow)
|
||||
|
||||
|
||||
46
tools/musicator/midi_converter.py
Normal file
46
tools/musicator/midi_converter.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from mido import MidiFile
|
||||
|
||||
MIDI_FILE = "/tmp/teletype_impostor_musicator/maestro-v3.0.0/2018/MIDI-Unprocessed_Schubert7-9_MID--AUDIO_16_R2_2018_wav.midi"
|
||||
|
||||
# resolution: rows per beat (e.g. 4 = 16th notes)
|
||||
ROWS_PER_BEAT = 4
|
||||
|
||||
names = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]
|
||||
|
||||
def note_name(n):
|
||||
octave = n // 12 - 1
|
||||
return f"{names[n % 12]}-{octave}"
|
||||
|
||||
mid = MidiFile(MIDI_FILE)
|
||||
tpb = mid.ticks_per_beat
|
||||
|
||||
row_ticks = tpb // ROWS_PER_BEAT
|
||||
|
||||
time = 0
|
||||
rows = {}
|
||||
|
||||
for msg in mid:
|
||||
time += msg.time
|
||||
if msg.type == "note_on" and msg.velocity > 0:
|
||||
row = int(time // row_ticks)
|
||||
rows.setdefault(row, []).append(msg.note)
|
||||
|
||||
# build monophonic sequence (highest note wins)
|
||||
max_row = max(rows.keys())
|
||||
sequence = []
|
||||
|
||||
for r in range(max_row + 1):
|
||||
if r in rows:
|
||||
n = max(rows[r])
|
||||
sequence.append(note_name(n))
|
||||
else:
|
||||
sequence.append("...")
|
||||
|
||||
# trim (optional)
|
||||
sequence = sequence[:512]
|
||||
|
||||
# output as Lua
|
||||
print("sequence = {")
|
||||
for n in sequence:
|
||||
print(f' "{n}",')
|
||||
print("}")
|
||||
127
tools/musicator/musicator.lua
Normal file
127
tools/musicator/musicator.lua
Normal file
@@ -0,0 +1,127 @@
|
||||
-- key separator: |
|
||||
-- empty note: "..."
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
local unpack = unpack or table.unpack
|
||||
|
||||
local function make_key(tbl)
|
||||
return table.concat(tbl, "|")
|
||||
end
|
||||
|
||||
local function unmake_key(k)
|
||||
local result = {}
|
||||
for t in string.gmatch(k, "[^|]+") do
|
||||
result[#result + 1] = t
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local function add_key(str, value)
|
||||
return str .. "|" .. value
|
||||
end
|
||||
|
||||
local function split_last(full)
|
||||
local i = full:match(".*()|")
|
||||
return full:sub(1, i-1), full:sub(i+1)
|
||||
end
|
||||
|
||||
local function has_value (tab, val)
|
||||
for index, value in ipairs(tab) do
|
||||
if value == val then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- helper: split key into parts
|
||||
local function split(k)
|
||||
local t = {}
|
||||
for part in string.gmatch(k, "[^|]+") do
|
||||
t[#t+1] = part
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function build_markov_model(sequence, order)
|
||||
-- TODO: add {"..." x order} to beginning?
|
||||
|
||||
local model = { }
|
||||
|
||||
-- count
|
||||
for i = 1, #sequence - order do
|
||||
local key = make_key({unpack(sequence, i, i + order - 1)})
|
||||
local next_note = sequence[i + order]
|
||||
|
||||
local data = model[key] or { next={}, total=0 }
|
||||
|
||||
data.next[next_note] = (data.next[next_note] or 0) + 1
|
||||
data.total = data.total + 1
|
||||
|
||||
model[key] = data
|
||||
end
|
||||
|
||||
-- normalize
|
||||
for temp_key,temp_data in pairs(model) do
|
||||
for temp_note, temp_count in pairs(temp_data.next) do
|
||||
model[temp_key].next[temp_note] = temp_count / temp_data.total
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
for k,v in pairs(model) do
|
||||
print("-----" .. k)
|
||||
for k2,v2 in pairs(v.next) do
|
||||
print(k2, v2)
|
||||
end
|
||||
end
|
||||
--]]
|
||||
|
||||
return {
|
||||
order = order,
|
||||
model = model
|
||||
}
|
||||
end
|
||||
|
||||
function generate_sequence(model_data, length)
|
||||
local order = model_data.order
|
||||
local model_data = model_data.model
|
||||
|
||||
-- random start key
|
||||
local model_keys = {}
|
||||
for k,_ in pairs(model) do
|
||||
model_keys[#model_keys + 1] = k
|
||||
end
|
||||
local start_key = model_keys[math.ceil(math.random() * #model_keys)]
|
||||
|
||||
-- sequence starts with the start key
|
||||
local seq = unmake_key(start_key)
|
||||
|
||||
-- generation loop
|
||||
while #seq < length do
|
||||
local current_key = table.concat({unpack(seq, #seq - order + 1, #seq)}, "|")
|
||||
|
||||
local chosen = "..."
|
||||
|
||||
local key_data = model[current_key]
|
||||
if key_data then
|
||||
local r = math.random()
|
||||
local prob_sum = 0.0
|
||||
for new_note, new_prob in pairs(key_data.next) do
|
||||
prob_sum = prob_sum + new_prob
|
||||
if prob_sum < r then
|
||||
chosen = new_note
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- print(current_key .. " --> " .. chosen)
|
||||
|
||||
seq[#seq+1] = chosen
|
||||
end
|
||||
|
||||
return seq
|
||||
end
|
||||
42
tools/musicator/sequence_to_strudel.py
Normal file
42
tools/musicator/sequence_to_strudel.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import sys
|
||||
import re
|
||||
|
||||
ROWS_PER_BEAT = 4 # keep consistent with your MIDI extraction
|
||||
SOUND = "piano"
|
||||
|
||||
def parse_sequence(text):
|
||||
return re.findall(r'"([^"]+)"', text)
|
||||
|
||||
def to_strudel_notes(seq):
|
||||
out = []
|
||||
for n in seq:
|
||||
if n == "..." or n == "---":
|
||||
out.append("~")
|
||||
else:
|
||||
# C-5 → c5, C#5 → c#5
|
||||
note = n.replace("-", "")
|
||||
out.append(note.lower())
|
||||
return out
|
||||
|
||||
def chunk(seq, size):
|
||||
for i in range(0, len(seq), size):
|
||||
yield seq[i:i+size]
|
||||
|
||||
# read from stdin
|
||||
text = sys.stdin.read()
|
||||
|
||||
sequence = parse_sequence(text)
|
||||
notes = to_strudel_notes(sequence)
|
||||
|
||||
# group into musical lines (4 beats)
|
||||
lines = []
|
||||
for group in chunk(notes, ROWS_PER_BEAT * 4):
|
||||
lines.append(" ".join(group))
|
||||
|
||||
pattern = "\n".join(lines)
|
||||
|
||||
print("note(`")
|
||||
print(pattern)
|
||||
print(f"`).sound(\"{SOUND}\")")
|
||||
|
||||
# npm install -g strudel-cli
|
||||
414
tools/musicator/teach.lua
Normal file
414
tools/musicator/teach.lua
Normal file
@@ -0,0 +1,414 @@
|
||||
-- teach the musicator
|
||||
-- uses samples from: https://magenta.tensorflow.org/datasets/maestro#v300
|
||||
|
||||
--require("luarocks.loader")
|
||||
--require("luamidi")
|
||||
|
||||
require("./musicator")
|
||||
local inspect = require("inspect")
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
function flatten(v)
|
||||
local res = {}
|
||||
local function flatten(v)
|
||||
if type(v) ~= "table" then
|
||||
table.insert(res, v)
|
||||
return
|
||||
end
|
||||
for _, v in ipairs(v) do
|
||||
flatten(v)
|
||||
end
|
||||
end
|
||||
flatten(v)
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
local training_data = {
|
||||
|
||||
-- simple ascending phrase
|
||||
{
|
||||
"C-4","...","D-4","...","E-4","...","G-4","...",
|
||||
"E-4","...","D-4","...","C-4","...","...","..."
|
||||
},
|
||||
|
||||
-- descending answer
|
||||
{
|
||||
"G-4","...","F-4","...","E-4","...","D-4","...",
|
||||
"C-4","...","D-4","...","E-4","...","...","..."
|
||||
},
|
||||
|
||||
-- arpeggio major
|
||||
{
|
||||
"C-4","...","E-4","...","G-4","...","C-5","...",
|
||||
"G-4","...","E-4","...","C-4","...","...","..."
|
||||
},
|
||||
|
||||
-- arpeggio minor
|
||||
{
|
||||
"A-4","...","C-5","...","E-5","...","A-5","...",
|
||||
"E-5","...","C-5","...","A-4","...","...","..."
|
||||
},
|
||||
|
||||
-- stepwise melody (folk-like)
|
||||
{
|
||||
"D-4","...","E-4","...","F-4","...","G-4","...",
|
||||
"F-4","...","E-4","...","D-4","...","...","..."
|
||||
},
|
||||
|
||||
-- repeated note rhythm
|
||||
{
|
||||
"C-5","C-5","...","C-5","...","C-5","C-5","...",
|
||||
"D-5","...","E-5","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- bounce pattern
|
||||
{
|
||||
"C-5","...","G-4","...","C-5","...","G-4","...",
|
||||
"D-5","...","A-4","...","D-5","...","...","..."
|
||||
},
|
||||
|
||||
-- scale run up
|
||||
{
|
||||
"C-4","D-4","E-4","F-4","G-4","A-4","B-4","C-5",
|
||||
"...","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- scale run down
|
||||
{
|
||||
"C-5","B-4","A-4","G-4","F-4","E-4","D-4","C-4",
|
||||
"...","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- syncopated feel
|
||||
{
|
||||
"C-5","...","...","D-5","...","...","E-5","...",
|
||||
"C-5","...","...","G-4","...","...","...","..."
|
||||
},
|
||||
|
||||
-- triplet-ish feel (simulated)
|
||||
{
|
||||
"E-5","D-5","C-5","...","E-5","D-5","C-5","...",
|
||||
"G-4","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- small jumps
|
||||
{
|
||||
"C-5","...","E-5","...","D-5","...","F-5","...",
|
||||
"E-5","...","C-5","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- call
|
||||
{
|
||||
"G-4","...","A-4","...","C-5","...","A-4","...",
|
||||
"...","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- response
|
||||
{
|
||||
"E-4","...","F-4","...","G-4","...","F-4","...",
|
||||
"D-4","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- denser pattern (DDR-like)
|
||||
{
|
||||
"C-5","D-5","E-5","...","D-5","E-5","F-5","...",
|
||||
"E-5","D-5","C-5","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- alternating pattern (good for gameplay)
|
||||
{
|
||||
"C-5","...","E-5","...","C-5","...","E-5","...",
|
||||
"D-5","...","F-5","...","D-5","...","...","..."
|
||||
},
|
||||
|
||||
-- higher register variant
|
||||
{
|
||||
"G-5","...","A-5","...","B-5","...","D-6","...",
|
||||
"B-5","...","A-5","...","G-5","...","...","..."
|
||||
},
|
||||
|
||||
-- low register grounding
|
||||
{
|
||||
"C-4","...","G-3","...","C-4","...","G-3","...",
|
||||
"F-3","...","C-4","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- variant of ascending with offset
|
||||
{
|
||||
"...","C-4","...","D-4","...","E-4","...","G-4",
|
||||
"...","E-4","...","D-4","...","C-4","...","..."
|
||||
},
|
||||
|
||||
-- staggered rhythm
|
||||
{
|
||||
"C-4","...","...","D-4","...","E-4","...","...",
|
||||
"G-4","...","E-4","...","D-4","...","...","..."
|
||||
},
|
||||
|
||||
-- broken arpeggio (different spacing)
|
||||
{
|
||||
"C-4","E-4","...","G-4","...","C-5","...",
|
||||
"G-4","E-4","...","C-4","...","...","...","..."
|
||||
},
|
||||
|
||||
-- minor variation (shifted)
|
||||
{
|
||||
"...","A-4","C-5","...","E-5","...","A-5","...",
|
||||
"E-5","...","C-5","...","A-4","...","...","..."
|
||||
},
|
||||
|
||||
-- repeated + variation
|
||||
{
|
||||
"D-4","D-4","...","E-4","...","F-4","F-4","...",
|
||||
"G-4","...","F-4","...","E-4","...","...","..."
|
||||
},
|
||||
|
||||
-- zig-zag motion
|
||||
{
|
||||
"C-5","...","E-5","...","D-5","...","F-5","...",
|
||||
"E-5","...","G-5","...","F-5","...","...","..."
|
||||
},
|
||||
|
||||
-- alternating step/jump
|
||||
{
|
||||
"C-5","...","D-5","...","G-5","...","F-5","...",
|
||||
"E-5","...","C-5","...","D-5","...","...","..."
|
||||
},
|
||||
|
||||
-- denser burst pattern
|
||||
{
|
||||
"C-5","D-5","E-5","F-5","...","E-5","D-5","C-5",
|
||||
"...","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- rolling pattern
|
||||
{
|
||||
"E-5","...","D-5","...","C-5","...","D-5","...",
|
||||
"E-5","...","G-5","...","E-5","...","...","..."
|
||||
},
|
||||
|
||||
-- syncopation variant
|
||||
{
|
||||
"...","C-5","...","...","E-5","...","...","G-5",
|
||||
"...","E-5","...","C-5","...","...","...","..."
|
||||
},
|
||||
|
||||
-- low-high interplay
|
||||
{
|
||||
"C-4","...","G-4","...","C-5","...","G-4","...",
|
||||
"E-4","...","C-4","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- descending but staggered
|
||||
{
|
||||
"C-5","...","...","B-4","...","A-4","...","...",
|
||||
"G-4","...","F-4","...","E-4","...","...","..."
|
||||
},
|
||||
|
||||
-- small trill-like feel
|
||||
{
|
||||
"E-5","F-5","E-5","...","E-5","F-5","E-5","...",
|
||||
"D-5","...","C-5","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- call variant (shifted timing)
|
||||
{
|
||||
"...","G-4","...","A-4","...","C-5","...","A-4",
|
||||
"...","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- response variant
|
||||
{
|
||||
"...","E-4","...","F-4","...","G-4","...","F-4",
|
||||
"D-4","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- dense DDR-ish alternating
|
||||
{
|
||||
"C-5","...","D-5","...","C-5","...","D-5","...",
|
||||
"E-5","...","F-5","...","E-5","...","...","..."
|
||||
},
|
||||
|
||||
-- higher variation arpeggio
|
||||
{
|
||||
"G-5","...","B-5","...","D-6","...","G-6","...",
|
||||
"D-6","...","B-5","...","G-5","...","...","..."
|
||||
},
|
||||
|
||||
-- low groove pattern
|
||||
{
|
||||
"C-3","...","C-4","...","G-3","...","C-4","...",
|
||||
"F-3","...","C-4","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- slightly chaotic (good for branching)
|
||||
{
|
||||
"C-5","...","E-5","D-5","...","G-5","...","F-5",
|
||||
"...","D-5","...","C-5","...","...","...","..."
|
||||
},
|
||||
|
||||
-- mixed density
|
||||
{
|
||||
"C-5","D-5","...","E-5","...","F-5","G-5","...",
|
||||
"E-5","...","D-5","C-5","...","...","...","..."
|
||||
},
|
||||
|
||||
-- offset staircase up
|
||||
{
|
||||
"...","C-4","D-4","E-4","F-4","G-4","A-4","B-4",
|
||||
"C-5","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- offset staircase down
|
||||
{
|
||||
"...","C-5","B-4","A-4","G-4","F-4","E-4","D-4",
|
||||
"C-4","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- dense zigzag
|
||||
{
|
||||
"C-5","E-5","D-5","F-5","E-5","G-5","F-5","A-5",
|
||||
"G-5","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- jack pattern (DDR classic)
|
||||
{
|
||||
"C-5","C-5","C-5","...","C-5","C-5","...","...",
|
||||
"D-5","D-5","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- alternating two-note burst
|
||||
{
|
||||
"C-5","D-5","C-5","D-5","C-5","D-5","...","...",
|
||||
"E-5","F-5","E-5","F-5","...","...","...","..."
|
||||
},
|
||||
|
||||
-- wide jumps
|
||||
{
|
||||
"C-4","...","G-5","...","D-4","...","A-5","...",
|
||||
"E-4","...","B-5","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- rolling triplet-ish
|
||||
{
|
||||
"C-5","E-5","G-5","...","E-5","C-5","E-5","...",
|
||||
"G-5","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- syncopated dense
|
||||
{
|
||||
"...","C-5","D-5","...","E-5","...","F-5","G-5",
|
||||
"...","E-5","...","C-5","...","...","...","..."
|
||||
},
|
||||
|
||||
-- mirrored pattern
|
||||
{
|
||||
"C-5","D-5","E-5","F-5","E-5","D-5","C-5","...",
|
||||
"...","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- chord-outline arpeggio feel
|
||||
{
|
||||
"C-4","...","G-4","...","E-5","...","G-4","...",
|
||||
"C-4","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- broken rhythm variant
|
||||
{
|
||||
"C-5","...","D-5","E-5","...","F-5","...","G-5",
|
||||
"E-5","...","D-5","...","C-5","...","...","..."
|
||||
},
|
||||
|
||||
-- fast burst then rest
|
||||
{
|
||||
"C-5","D-5","E-5","F-5","G-5","A-5","...","...",
|
||||
"...","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- low-high bounce fast
|
||||
{
|
||||
"C-3","C-5","C-3","C-5","C-3","C-5","...","...",
|
||||
"G-3","G-5","G-3","G-5","...","...","...","..."
|
||||
},
|
||||
|
||||
-- repeated with shift
|
||||
{
|
||||
"...","E-5","...","E-5","...","E-5","...","...",
|
||||
"D-5","...","C-5","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- clustered mid
|
||||
{
|
||||
"D-5","E-5","F-5","...","E-5","D-5","C-5","...",
|
||||
"D-5","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- broken descending
|
||||
{
|
||||
"C-6","...","A-5","...","F-5","...","D-5","...",
|
||||
"C-5","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- chaotic jumpy (important for branching)
|
||||
{
|
||||
"C-5","...","F-5","D-5","...","A-5","...","E-5",
|
||||
"...","G-5","...","C-5","...","...","...","..."
|
||||
},
|
||||
|
||||
-- double-step pattern
|
||||
{
|
||||
"C-5","D-5","D-5","E-5","E-5","F-5","...","...",
|
||||
"G-5","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- uneven spacing
|
||||
{
|
||||
"C-5","...","...","D-5","E-5","...","...","F-5",
|
||||
"G-5","...","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- fast alternating high
|
||||
{
|
||||
"G-5","A-5","G-5","A-5","G-5","A-5","...","...",
|
||||
"F-5","E-5","...","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- low groove with variation
|
||||
{
|
||||
"C-3","...","C-4","...","G-3","...","D-4","...",
|
||||
"F-3","...","C-4","...","...","...","...","..."
|
||||
},
|
||||
|
||||
-- semi-random filler (very useful)
|
||||
{
|
||||
"C-5","...","E-5","...","D-5","...","G-5","...",
|
||||
"F-5","...","A-5","...","E-5","...","...","..."
|
||||
},
|
||||
|
||||
-- near-repetition (state collision booster)
|
||||
{
|
||||
"C-5","...","D-5","...","E-5","...","C-5","...",
|
||||
"D-5","...","E-5","...","C-5","...","...","..."
|
||||
},
|
||||
|
||||
-- same but shifted (VERY important)
|
||||
{
|
||||
"...","C-5","...","D-5","...","E-5","...","C-5",
|
||||
"...","D-5","...","E-5","...","C-5","...","..."
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
local model = build_markov_model(flatten(training_data), 2)
|
||||
|
||||
print(inspect(model))
|
||||
|
||||
--[[
|
||||
local generated = generate_sequence(model, 100)
|
||||
|
||||
for i,v in ipairs(generated) do
|
||||
print(v)
|
||||
end
|
||||
--]]
|
||||
Reference in New Issue
Block a user