Compare commits
23 Commits
7dbbbb4668
...
feature/13
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ae1eec48a | |||
| 8921f02821 | |||
| 211af18c26 | |||
| b337ae8516 | |||
| 10316d3075 | |||
| 589b225ab0 | |||
| 7697b35336 | |||
| 6e1cf1db3e | |||
| 020bfd4134 | |||
| 8e610f14a0 | |||
| 753509b4ea | |||
| 3290d0fb89 | |||
| 4cf7df511b | |||
| 8b0bcdbe95 | |||
| 7c3a011ffc | |||
| 6ee874655e | |||
| 3420694287 | |||
| e12a27e4e1 | |||
| 53ccda7702 | |||
| 4e6590174a | |||
| 6a33be82e9 | |||
|
|
9a3c9ee28c | ||
|
|
c41bf23a45 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
.claude
|
||||||
.local
|
.local
|
||||||
impostor.lua
|
impostor.lua
|
||||||
impostor.original.lua
|
impostor.original.lua
|
||||||
@@ -5,4 +6,5 @@ prompts
|
|||||||
docs
|
docs
|
||||||
minify.lua
|
minify.lua
|
||||||
*.tic
|
*.tic
|
||||||
*.zip
|
*.zip
|
||||||
|
NOTES_*
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ globals = {
|
|||||||
"Discussion",
|
"Discussion",
|
||||||
"Util",
|
"Util",
|
||||||
"Decision",
|
"Decision",
|
||||||
"Situation",
|
|
||||||
"Screen",
|
"Screen",
|
||||||
"Sprite",
|
"Sprite",
|
||||||
"UI",
|
"UI",
|
||||||
@@ -31,7 +30,7 @@ globals = {
|
|||||||
"MenuWindow",
|
"MenuWindow",
|
||||||
"GameWindow",
|
"GameWindow",
|
||||||
"PopupWindow",
|
"PopupWindow",
|
||||||
"ConfigurationWindow",
|
"ControlsWindow",
|
||||||
"AudioTestWindow",
|
"AudioTestWindow",
|
||||||
"MinigameButtonMashWindow",
|
"MinigameButtonMashWindow",
|
||||||
"MinigameRhythmWindow",
|
"MinigameRhythmWindow",
|
||||||
@@ -66,6 +65,10 @@ globals = {
|
|||||||
"map",
|
"map",
|
||||||
"time",
|
"time",
|
||||||
"RLE",
|
"RLE",
|
||||||
|
"mouse",
|
||||||
|
"Mouse",
|
||||||
|
"print",
|
||||||
|
"musicator_generate_pattern",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ init/init.context.lua
|
|||||||
system/system.util.lua
|
system/system.util.lua
|
||||||
system/system.print.lua
|
system/system.print.lua
|
||||||
system/system.input.lua
|
system/system.input.lua
|
||||||
|
system/system.mouse.lua
|
||||||
system/system.asciiart.lua
|
system/system.asciiart.lua
|
||||||
system/system.rle.lua
|
system/system.rle.lua
|
||||||
logic/logic.meter.lua
|
logic/logic.meter.lua
|
||||||
@@ -18,6 +19,7 @@ logic/logic.glitch.lua
|
|||||||
logic/logic.discussion.lua
|
logic/logic.discussion.lua
|
||||||
system/system.ui.lua
|
system/system.ui.lua
|
||||||
audio/audio.manager.lua
|
audio/audio.manager.lua
|
||||||
|
audio/audio.generator.lua
|
||||||
audio/audio.songs.lua
|
audio/audio.songs.lua
|
||||||
sprite/sprite.manager.lua
|
sprite/sprite.manager.lua
|
||||||
sprite/sprite.norman.lua
|
sprite/sprite.norman.lua
|
||||||
@@ -37,10 +39,7 @@ sprite/sprite.matrix_architect.lua
|
|||||||
sprite/sprite.matrix_neo.lua
|
sprite/sprite.matrix_neo.lua
|
||||||
sprite/sprite.matrix_oraculum.lua
|
sprite/sprite.matrix_oraculum.lua
|
||||||
sprite/sprite.matrix_trinity.lua
|
sprite/sprite.matrix_trinity.lua
|
||||||
situation/situation.manager.lua
|
|
||||||
situation/situation.drink_coffee.lua
|
|
||||||
decision/decision.manager.lua
|
decision/decision.manager.lua
|
||||||
decision/decision.have_a_coffee.lua
|
|
||||||
decision/decision.go_to_home.lua
|
decision/decision.go_to_home.lua
|
||||||
decision/decision.go_to_toilet.lua
|
decision/decision.go_to_toilet.lua
|
||||||
decision/decision.go_to_walking_to_office.lua
|
decision/decision.go_to_walking_to_office.lua
|
||||||
@@ -71,7 +70,7 @@ window/window.intro.title.lua
|
|||||||
window/window.intro.ttg.lua
|
window/window.intro.ttg.lua
|
||||||
window/window.intro.brief.lua
|
window/window.intro.brief.lua
|
||||||
window/window.menu.lua
|
window/window.menu.lua
|
||||||
window/window.configuration.lua
|
window/window.controls.lua
|
||||||
window/window.audiotest.lua
|
window/window.audiotest.lua
|
||||||
window/window.popup.lua
|
window/window.popup.lua
|
||||||
window/window.minigame.mash.lua
|
window/window.minigame.mash.lua
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
local musicator_markov_model = {
|
||||||
model = {
|
model = {
|
||||||
["...|..."] = {
|
["...|..."] = {
|
||||||
next = {
|
next = {
|
||||||
@@ -640,3 +640,105 @@
|
|||||||
},
|
},
|
||||||
order = 2
|
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
|
--- @section Audio
|
||||||
|
|
||||||
|
Audio = {
|
||||||
|
music_playing = nil
|
||||||
|
}
|
||||||
|
|
||||||
--- Stops current music.
|
--- Stops current music.
|
||||||
--- @within Audio
|
--- @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.
|
--- Plays main menu music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_mainmenu() end
|
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.
|
--- Plays waking up music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_wakingup() end
|
function Audio.music_play_wakingup() end
|
||||||
|
|
||||||
--- Plays room morning music.
|
--- Plays room morning music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_morning() end
|
function Audio.music_play_room_morning() end
|
||||||
|
|
||||||
--- Plays room street 1 music.
|
--- Plays room street 1 music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_street_1() end
|
function Audio.music_play_room_street_1() end
|
||||||
|
|
||||||
--- Plays room street 2 music.
|
--- Plays room street 2 music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_street_2() end
|
function Audio.music_play_room_street_2() end
|
||||||
|
|
||||||
--- Plays room music.
|
--- Plays room music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_() end
|
function Audio.music_play_room_() end
|
||||||
|
|
||||||
--- Plays room work music.
|
--- Plays room work music.
|
||||||
--- @within Audio
|
--- @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.
|
--- Plays activity work music.
|
||||||
--- @within Audio
|
--- @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.
|
--- Plays select sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_select() sfx(17, 'C-7', 30) end
|
function Audio.sfx_select() sfx(17, 'C-7', 30) end
|
||||||
|
|
||||||
--- Plays deselect sound effect.
|
--- Plays deselect sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_deselect() sfx(18, 'C-7', 30) end
|
function Audio.sfx_deselect() sfx(18, 'C-7', 30) end
|
||||||
|
|
||||||
--- Plays beep sound effect.
|
--- Plays beep sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_beep() sfx(19, 'C-6', 30) end
|
function Audio.sfx_beep() sfx(19, 'C-6', 30) end
|
||||||
|
|
||||||
--- Plays success sound effect.
|
--- Plays success sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_success() sfx(16, 'C-7', 60) end
|
function Audio.sfx_success() sfx(16, 'C-7', 60) end
|
||||||
|
|
||||||
--- Plays bloop sound effect.
|
--- Plays bloop sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_bloop() sfx(21, 'C-3', 60) end
|
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(34, "C-5", 240) end
|
||||||
|
|
||||||
|
--- Plays drum sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_alarm() sfx(61) end
|
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,
|
fps = 60,
|
||||||
end_frame = nil, -- No end frame for random mode
|
end_frame = nil, -- No end frame for random mode
|
||||||
pattern = {} -- Empty, will spawn randomly in game
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,40 +171,3 @@ Songs.custom_song = {
|
|||||||
}, 130)
|
}, 130)
|
||||||
}
|
}
|
||||||
]]
|
]]
|
||||||
|
|
||||||
--[[
|
|
||||||
function generate_sequence(model_data, length)
|
|
||||||
local order = model.order
|
|
||||||
local model_data = model_data.model
|
|
||||||
|
|
||||||
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)]
|
|
||||||
|
|
||||||
local seq = unmake_key(start_key)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
seq[#seq+1] = chosen
|
|
||||||
end
|
|
||||||
|
|
||||||
return seq
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|||||||
@@ -4,17 +4,31 @@ Decision.register({
|
|||||||
handle = function()
|
handle = function()
|
||||||
Meter.hide()
|
Meter.hide()
|
||||||
Util.go_to_screen_by_id("work")
|
Util.go_to_screen_by_id("work")
|
||||||
MinigameDDRWindow.start("game", nil, {
|
|
||||||
on_win = function()
|
local modes_for_ascension_levels = {}
|
||||||
if (Context.minigame_ddr.special_condition_met and Context.ascension.level == 1) then
|
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
|
Context.should_ascend = true
|
||||||
Context.minigame_ddr.special_condition_met = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Meter.show()
|
Meter.show()
|
||||||
Util.go_to_screen_by_id("office")
|
Util.go_to_screen_by_id("office")
|
||||||
Window.set_current("game")
|
Window.set_current("game")
|
||||||
Context.have_done_work_today = true
|
Context.have_done_work_today = true
|
||||||
end,
|
end,
|
||||||
|
special_mode = modes_for_ascension_levels[Ascension.get_level()]
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Decision.register({
|
Decision.register({
|
||||||
id = "go_to_home",
|
id = "go_to_home",
|
||||||
label = "Go to Home",
|
label = "Go Home",
|
||||||
condition = function()
|
condition = function()
|
||||||
return Context.have_been_to_office and Context.have_done_work_today
|
return Context.have_been_to_office and Context.have_done_work_today
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Decision.register({
|
Decision.register({
|
||||||
id = "go_to_walking_to_home",
|
id = "go_to_walking_to_home",
|
||||||
label = "Walking to home",
|
label = "Walk home",
|
||||||
handle = function()
|
handle = function()
|
||||||
Util.go_to_screen_by_id("walking_to_home")
|
Util.go_to_screen_by_id("walking_to_home")
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Decision.register({
|
Decision.register({
|
||||||
id = "go_to_walking_to_office",
|
id = "go_to_walking_to_office",
|
||||||
label = "Walking to office",
|
label = "Walk to office",
|
||||||
handle = function()
|
handle = function()
|
||||||
Util.go_to_screen_by_id("walking_to_office")
|
Util.go_to_screen_by_id("walking_to_office")
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
Decision.register({
|
|
||||||
id = "have_a_coffee",
|
|
||||||
label = "Have a Coffee",
|
|
||||||
handle = function()
|
|
||||||
local new_situation_id = Situation.apply("drink_coffee", Context.game.current_screen)
|
|
||||||
local level = Ascension.get_level()
|
|
||||||
local disc_id = "coworker_disc_0"
|
|
||||||
-- TODO: Add more discussions for levels above 3
|
|
||||||
if level >= 1 and level <= 3 then
|
|
||||||
local suffix = Context.have_done_work_today and ("_asc_" .. level) or ("_" .. level)
|
|
||||||
disc_id = "coworker_disc" .. suffix
|
|
||||||
end
|
|
||||||
Discussion.start(disc_id, "game")
|
|
||||||
Context.game.current_situation = new_situation_id
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
@@ -134,6 +134,7 @@ end
|
|||||||
--- @param decisions table A table of decision items.<br/>
|
--- @param decisions table A table of decision items.<br/>
|
||||||
--- @param selected_decision_index number The current index of the selected decision.<br/>
|
--- @param selected_decision_index number The current index of the selected decision.<br/>
|
||||||
--- @return number selected_decision_index The updated index of the selected decision.
|
--- @return number selected_decision_index The updated index of the selected decision.
|
||||||
|
--- @return boolean mouse_confirmed True if the user clicked the center to confirm.
|
||||||
function Decision.update(decisions, selected_decision_index)
|
function Decision.update(decisions, selected_decision_index)
|
||||||
if Input.left() then
|
if Input.left() then
|
||||||
Audio.sfx_beep()
|
Audio.sfx_beep()
|
||||||
@@ -142,5 +143,22 @@ function Decision.update(decisions, selected_decision_index)
|
|||||||
Audio.sfx_beep()
|
Audio.sfx_beep()
|
||||||
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
||||||
end
|
end
|
||||||
return selected_decision_index
|
|
||||||
|
local bar_h = 16
|
||||||
|
local bar_y = Config.screen.height - bar_h
|
||||||
|
local prev_zone = { x = 0, y = bar_y, w = 15, h = bar_h }
|
||||||
|
local next_zone = { x = Config.screen.width-15, y = bar_y, w = 15, h = bar_h }
|
||||||
|
local confirm_zone = { x = 15, y = bar_y, w = Config.screen.width-30, h = bar_h }
|
||||||
|
|
||||||
|
if Mouse.zone(prev_zone) then
|
||||||
|
Audio.sfx_beep()
|
||||||
|
selected_decision_index = Util.safeindex(decisions, selected_decision_index - 1)
|
||||||
|
elseif Mouse.zone(next_zone) then
|
||||||
|
Audio.sfx_beep()
|
||||||
|
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
||||||
|
elseif Mouse.zone(confirm_zone) then
|
||||||
|
return selected_decision_index, true
|
||||||
|
end
|
||||||
|
|
||||||
|
return selected_decision_index, false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
Decision.register({
|
Decision.register({
|
||||||
id = "play_ddr",
|
id = "play_ddr",
|
||||||
label = "Play DDR (Random)",
|
label = "Play DDR (Random)",
|
||||||
handle = function() Meter.hide() MinigameDDRWindow.start("game", nil) end,
|
handle = function()
|
||||||
|
Meter.hide()
|
||||||
|
MinigameDDRWindow.start("game", nil)
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ Context = {}
|
|||||||
--- * have_met_sumphore (boolean) Whether the player has talked to the homeless guy.<br/>
|
--- * have_met_sumphore (boolean) Whether the player has talked to the homeless guy.<br/>
|
||||||
--- * have_been_to_office (boolean) Whether the player has been to the office.<br/>
|
--- * have_been_to_office (boolean) Whether the player has been to the office.<br/>
|
||||||
--- * have_done_work_today (boolean) Whether the player has done work today.<br/>
|
--- * have_done_work_today (boolean) Whether the player has done work today.<br/>
|
||||||
--- * game (table) Current game progress state. Contains: `current_screen` (string) active screen ID, `current_situation` (string|nil) active situation ID.<br/>
|
--- * game (table) Current game progress state. Contains: `current_screen` (string) active screen ID<br/>
|
||||||
function Context.initial_data()
|
function Context.initial_data()
|
||||||
return {
|
return {
|
||||||
current_menu_item = 1,
|
current_menu_item = 1,
|
||||||
test_mode = false,
|
test_mode = false,
|
||||||
|
mouse_trace = false,
|
||||||
popup = {
|
popup = {
|
||||||
show = false,
|
show = false,
|
||||||
content = {}
|
content = {}
|
||||||
@@ -46,9 +47,10 @@ function Context.initial_data()
|
|||||||
have_done_work_today = false,
|
have_done_work_today = false,
|
||||||
should_ascend = false,
|
should_ascend = false,
|
||||||
have_met_sumphore = false,
|
have_met_sumphore = false,
|
||||||
|
office_sprites = {},
|
||||||
|
walking_to_office_sprites = {},
|
||||||
game = {
|
game = {
|
||||||
current_screen = "home",
|
current_screen = "home",
|
||||||
current_situation = nil,
|
|
||||||
},
|
},
|
||||||
day_count = 1,
|
day_count = 1,
|
||||||
delta_time = 0,
|
delta_time = 0,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ Util = {}
|
|||||||
Meter = {}
|
Meter = {}
|
||||||
Minigame = {}
|
Minigame = {}
|
||||||
Decision = {}
|
Decision = {}
|
||||||
Situation = {}
|
|
||||||
Screen = {}
|
Screen = {}
|
||||||
Map = {}
|
Map = {}
|
||||||
UI = {}
|
UI = {}
|
||||||
Print = {}
|
Print = {}
|
||||||
Input = {}
|
Input = {}
|
||||||
|
Mouse = {}
|
||||||
Sprite = {}
|
Sprite = {}
|
||||||
Audio = {}
|
Audio = {}
|
||||||
Focus = {}
|
Focus = {}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
--- Draws a unified win message overlay.
|
--- Draws a unified win message overlay.
|
||||||
--- @within Minigame
|
--- @within Minigame
|
||||||
function Minigame.draw_win_overlay()
|
function Minigame.draw_win_overlay(win_text)
|
||||||
local text = "SUCCESS"
|
local text = win_text or "SUCCESS"
|
||||||
local tw = #text * 6
|
local tw = #text * 6
|
||||||
local th = 6
|
local th = 6
|
||||||
local padding = 4
|
local padding = 4
|
||||||
|
|||||||
@@ -396,26 +396,27 @@
|
|||||||
-- 016:ffffffffff0010201020766777001020102010201020102000fffffffffff3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f30b1b2b1b2b7667776777761b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
-- 016:ffffffffff0010201020766777001020102010201020102000fffffffffff3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f30b1b2b1b2b7667776777761b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b1b2b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
-- </MAP>
|
-- </MAP>
|
||||||
-- <SFX>
|
-- <SFX>
|
||||||
-- 000:060006400600064006000640060006400600060006000600060006000600060006000600060006000600060006000600060006000600060006000600300000000900
|
|
||||||
-- 016:00000000000000400040004000700070007000400040004000700070007000c000c000c000c000c000c000c000c000c000c000c000c000c000c000c0470000000000
|
-- 016:00000000000000400040004000700070007000400040004000700070007000c000c000c000c000c000c000c000c000c000c000c000c000c000c000c0470000000000
|
||||||
-- 017:000000000000000000000000006000600060006000600060106020c030c050c060c080c0a0c0b0c0c0c0c0c0d0c0d0c0e0c0f0c0f0c0f0c0f0c0f0c0400000000000
|
-- 017:030003000300030003000300036003600360036003600360136023c033c053c063c083c0a3c0b3c0c3c0c3c0d3c0d3c0e3c0f3c0f3c0f3c0f3c0f3c0400000000000
|
||||||
-- 018:00c000c000c000c000c000c0006000600060006000600060200030005000600080009000a000b000c000d000d000e000e000e000f000f000f000f000500000000000
|
-- 018:03c003c003c003c003c003c0036003600360036003600360230033005300630083009300a300b300c300d300d300e300e300e300f300f300f300f300400000000000
|
||||||
-- 019:0000000000000000000000d010d010d020d030d050d070d090d0b0d0c0d0e0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0f0d0500000000000
|
-- 019:0300030003000300030003d013d013d023d033d053d073d093d0b3d0c3d0e3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0f3d0400000000000
|
||||||
-- 020:090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900500000000000
|
-- 020:090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900500000000000
|
||||||
-- 021:01000100010001000100f10001100110011001100110f11001200120012001200120f1201130113011302130213021302130313041308130a130d130580000000000
|
-- 021:01000100010001000100f10001100110011001100110f11001200120012001200120f1201130113011302130213021302130313041308130a130d130580000000000
|
||||||
|
-- 022:03b003100300030003000300130063009300b300c300d300d300e300e300e300f300f300f300f300f300f300f300f300f300f300f300f300f300f300400000000000
|
||||||
-- 032:010001100100011001000110010001100100010001000100010001000100010001000100010001000100010001000100010001000100010001000100400000000800
|
-- 032:010001100100011001000110010001100100010001000100010001000100010001000100010001000100010001000100010001000100010001000100400000000800
|
||||||
-- 033:000000010002000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d40000000004
|
-- 033:000000010002000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c40000000004
|
||||||
-- 044:0600f6000620f6000600f6000610f600f600f6000600f600f600f600f6000600060006000600060006000600060006000600060006000600060006004600000f0f00
|
-- 034:02000240020002000200020002000200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f200f2004700000f0200
|
||||||
-- 045:0000f0000020f0000000f0000010f000f000f0000000f000f000f000f0000000000000000000000000000000000000000000000000000000000000004600000f0f00
|
-- 044:0600f6000620f6000600f6000610f600f600f6000600f600f600f600f6000600060006000600060006000600060006000600060006000600060006001600000f0f00
|
||||||
|
-- 045:0000f0000020f0000000f0000010f000f000f0000000f000f000f000f0000000000000000000000000000000000000000000000000000000000000005600000f0f00
|
||||||
-- 048:090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900400000000000
|
-- 048:090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900090009000900400000000000
|
||||||
-- 056:4100510061406140717081709100b100c100d100e100e100e100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f10058a000000600
|
-- 056:4100510061406140717081709100b100c100d100e100e100e100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100f100480000000600
|
||||||
-- 057:000000010002000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d40000000004
|
-- 057:000000010002000300020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000000004
|
||||||
-- 058:41004110410041104100411041004110c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100500000080800
|
-- 058:41004110410041104100411041004110c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100c100003000080800
|
||||||
-- 059:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000
|
-- 059:03000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030000b000000000
|
||||||
-- 060:220022002200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200100000000000
|
-- 060:220022002200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200820082008200500000000000
|
||||||
-- 061:9f009f00bf00df00df00ef00ef00ef00ef00ef00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00400000000000
|
-- 061:9f009f00bf00df00df00ef00ef00ef00ef00ef00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00100000000000
|
||||||
-- 062:00000100010001000100510081008100910091009100a100a100a100a100a100b100b100b100b100c100c100c100d100d100d100e100e100e100f100484000000000
|
-- 062:00000100010001000100510081008100910091009100a100a100a100a100a100b100b100b100b100c100c100c100d100d100d100e100e100e100f100580000000000
|
||||||
-- 063:00b000100000000000000000100060009000b000c000d000d000e000e000e000f000f000f000f000f000f000f000f000f000f000f000f000f000f000200000000000
|
-- 063:00b000100000000000000000100060009000b000c000d000d000e000e000e000f000f000f000f000f000f000f000f000f000f000f000f000f000f000500000000000
|
||||||
-- </SFX>
|
-- </SFX>
|
||||||
-- <WAVES>
|
-- <WAVES>
|
||||||
-- 000:bcceefceedddddc84333121268abaa99
|
-- 000:bcceefceedddddc84333121268abaa99
|
||||||
@@ -433,10 +434,13 @@
|
|||||||
-- 000:4008b50000000000000000001008c10000004008b50000001008c1000000000000000000e008b30000004008b50000001008c10000000008c10000000008c10000000000000000000000000000000000000000000000000000000000000000004008b50000000000000000001008c10000004008b50000001008c10000000008c1000000e008b30000004008b50000001008c10000000008c10000000008c10000000008c10000000008c10000000008c1000000000000000000000000000000
|
-- 000:4008b50000000000000000001008c10000004008b50000001008c1000000000000000000e008b30000004008b50000001008c10000000008c10000000008c10000000000000000000000000000000000000000000000000000000000000000004008b50000000000000000001008c10000004008b50000001008c10000000008c1000000e008b30000004008b50000001008c10000000008c10000000008c10000000008c10000000008c10000000008c1000000000000000000000000000000
|
||||||
-- 001:4008b50000000000000000001008c10000004008b50000001008c1000000000000000000e008b30000004008b50000001008c10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007008b50000007008b50000001008c10000007008b50000001008c10000000008c10000007008b50000009008b50000001008c10000009008b50000001008c10000009008b50000009008b50000001008c10000009008b50000001008c1000000
|
-- 001:4008b50000000000000000001008c10000004008b50000001008c1000000000000000000e008b30000004008b50000001008c10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007008b50000007008b50000001008c10000007008b50000001008c10000000008c10000007008b50000009008b50000001008c10000009008b50000001008c10000009008b50000009008b50000001008c10000009008b50000001008c1000000
|
||||||
-- 003:4008d30000000000000000000000000000000000000000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000004008d30000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000000000000000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000004008d30000004008d9000000000000000000000000000000000000000000
|
-- 003:4008d30000000000000000000000000000000000000000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000004008d30000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000000000000000004008d90000000000000000000000000000000000000000004008d30000000000000000000000000000004008d30000004008d9000000000000000000000000000000000000000000
|
||||||
-- 004:49998d000000e0088b000000b0088b000881e0088b00000040088d000000e0088b000881b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e00889000000
|
-- 004:43398d000000e0088b000000b0088b000881e0088b00000040088d000000e0088b000881b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088d000000e0088b000000b0088b000000e0088b00000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e0088900000040088b000000e00889000000b00889000000e00889000000
|
||||||
-- 005:400881000000000881000000000881000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000
|
-- 005:455981000000000881000000000881000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000400881000000000000000000000000000000000000000000400883000000000000000000000000000000000000000000
|
||||||
|
-- 008:4aa9b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005008b30000000000000000000000000000000000000000000008b10000000000000000000008910000000000000000004008b30000000000000000000000000000000000000000000000000000000000000000000008b1000000000000000000f008b1000000000000000000000000000000000000000000000891000000000000000000000000000000000000000000
|
||||||
|
-- 009:4779d30000000000000000004008d30000000000000000004008db0000000000000000004008d30000000000000000004008d30000000000000000004008d30000000000000000004008db0000000000000000004008d30000000000000000004008d30000000000000000004008d30000000000000000004008db0000000000000000004008d30000000000000000004008d30000000000000000004008d30000000000000000004008db0000000000000000004008d3000000000000000000
|
||||||
-- </PATTERNS>
|
-- </PATTERNS>
|
||||||
-- <TRACKS>
|
-- <TRACKS>
|
||||||
-- 000:1000012000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff
|
-- 000:1000012000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff
|
||||||
-- 001:581000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
-- 001:581000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
-- 002:900082000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
-- </TRACKS>
|
-- </TRACKS>
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
-- desc: Life of a programmer
|
-- desc: Life of a programmer
|
||||||
-- site: https://git.teletype.hu/games/impostor
|
-- site: https://git.teletype.hu/games/impostor
|
||||||
-- license: MIT License
|
-- license: MIT License
|
||||||
-- version: 1.0-beta1
|
-- version: 1.0-beta2
|
||||||
-- script: lua
|
-- script: lua
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ Screen.register({
|
|||||||
"go_to_sleep",
|
"go_to_sleep",
|
||||||
"go_to_end",
|
"go_to_end",
|
||||||
},
|
},
|
||||||
|
init = function()
|
||||||
|
Audio.music_play_room_work()
|
||||||
|
end,
|
||||||
background = "bedroom",
|
background = "bedroom",
|
||||||
draw = function()
|
draw = function()
|
||||||
if Context.home_norman_visible and Window.get_current_id() == "game" then
|
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.name string Display name of the screen.
|
||||||
--- @param screen_data.decisions table Array of decision ID strings available on this screen.
|
--- @param screen_data.decisions table Array of decision ID strings available on this screen.
|
||||||
--- @param screen_data.background string Map ID used as background.
|
--- @param screen_data.background string Map ID used as background.
|
||||||
--- @param[opt] screen_data.situations table Array of situation ID strings. Defaults to {}.
|
|
||||||
--- @param[opt] screen_data.init function Called when the screen is entered. Defaults to noop.
|
--- @param[opt] screen_data.init function Called when the screen is entered. Defaults to noop.
|
||||||
--- @param[opt] screen_data.update function Called each frame while screen is active. Defaults to noop.
|
--- @param[opt] screen_data.update function Called each frame while screen is active. Defaults to noop.
|
||||||
--- @param[opt] screen_data.draw function Called after the focus overlay to draw screen-specific overlays. Defaults to noop.
|
--- @param[opt] screen_data.draw function Called after the focus overlay to draw screen-specific overlays. Defaults to noop.
|
||||||
@@ -16,9 +15,6 @@ function Screen.register(screen_data)
|
|||||||
if _screens[screen_data.id] then
|
if _screens[screen_data.id] then
|
||||||
trace("Warning: Overwriting screen with id: " .. screen_data.id)
|
trace("Warning: Overwriting screen with id: " .. screen_data.id)
|
||||||
end
|
end
|
||||||
if not screen_data.situations then
|
|
||||||
screen_data.situations = {}
|
|
||||||
end
|
|
||||||
if not screen_data.init then
|
if not screen_data.init then
|
||||||
screen_data.init = function() end
|
screen_data.init = function() end
|
||||||
end
|
end
|
||||||
@@ -43,7 +39,6 @@ end
|
|||||||
--- * name (string) Display name.<br/>
|
--- * name (string) Display name.<br/>
|
||||||
--- * decisions (table) Array of decision ID strings.<br/>
|
--- * decisions (table) Array of decision ID strings.<br/>
|
||||||
--- * background (string) Map ID used as background.<br/>
|
--- * background (string) Map ID used as background.<br/>
|
||||||
--- * situations (table) Array of situation ID strings.<br/>
|
|
||||||
--- * init (function) Called when the screen is entered.<br/>
|
--- * init (function) Called when the screen is entered.<br/>
|
||||||
--- * update (function) Called each frame while screen is active.
|
--- * update (function) Called each frame while screen is active.
|
||||||
function Screen.get_by_id(screen_id)
|
function Screen.get_by_id(screen_id)
|
||||||
@@ -58,7 +53,6 @@ end
|
|||||||
--- * name (string) Display name of the screen.<br/>
|
--- * name (string) Display name of the screen.<br/>
|
||||||
--- * decisions (table) Array of decision ID strings available on this screen.<br/>
|
--- * decisions (table) Array of decision ID strings available on this screen.<br/>
|
||||||
--- * background (string) Map ID used as background.<br/>
|
--- * background (string) Map ID used as background.<br/>
|
||||||
--- * situations (table) Array of situation ID strings.<br/>
|
|
||||||
--- * init (function) Called when the screen is entered.<br/>
|
--- * init (function) Called when the screen is entered.<br/>
|
||||||
--- * update (function) Called each frame while screen is active.<br/>
|
--- * update (function) Called each frame while screen is active.<br/>
|
||||||
function Screen.get_all()
|
function Screen.get_all()
|
||||||
|
|||||||
@@ -194,6 +194,12 @@ Screen.register({
|
|||||||
name = "Mysterious Man",
|
name = "Mysterious Man",
|
||||||
decisions = {},
|
decisions = {},
|
||||||
background_color = Config.colors.black,
|
background_color = Config.colors.black,
|
||||||
|
init = function()
|
||||||
|
Audio.music_play_mystery()
|
||||||
|
end,
|
||||||
|
exit = function()
|
||||||
|
Audio.music_stop()
|
||||||
|
end,
|
||||||
update = function()
|
update = function()
|
||||||
if state == STATE_TEXT then
|
if state == STATE_TEXT then
|
||||||
if not text_done then
|
if not text_done then
|
||||||
@@ -216,6 +222,10 @@ Screen.register({
|
|||||||
text_done_timer = text_done_timer - Context.delta_time
|
text_done_timer = text_done_timer - Context.delta_time
|
||||||
if text_done_timer <= 0 or Input.select() then
|
if text_done_timer <= 0 or Input.select() then
|
||||||
MysteriousManScreen.go_to_day_state()
|
MysteriousManScreen.go_to_day_state()
|
||||||
|
-- to be continued
|
||||||
|
if 4 <= Ascension.get_level() then
|
||||||
|
Window.set_current("continued")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif state == STATE_DAY then
|
elseif state == STATE_DAY then
|
||||||
@@ -230,9 +240,12 @@ Screen.register({
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif state == STATE_CHOICE then
|
elseif state == STATE_CHOICE then
|
||||||
selected_choice = UI.update_menu(MysteriousManScreen.choices, selected_choice)
|
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() then
|
if Input.select() or confirmed then
|
||||||
Audio.sfx_select()
|
Audio.sfx_select()
|
||||||
if selected_choice == 1 then
|
if selected_choice == 1 then
|
||||||
MysteriousManScreen.wake_up()
|
MysteriousManScreen.wake_up()
|
||||||
|
|||||||
@@ -6,23 +6,45 @@ Screen.register({
|
|||||||
"go_to_walking_to_home",
|
"go_to_walking_to_home",
|
||||||
"have_a_coffee",
|
"have_a_coffee",
|
||||||
},
|
},
|
||||||
situations = {
|
init = function()
|
||||||
"drink_coffee",
|
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",
|
background = "office",
|
||||||
draw = function()
|
draw = function()
|
||||||
if Window.get_current_id() == "game" then
|
if Window.get_current_id() == "game" then
|
||||||
Sprite.draw_at("norman", 13 * 8, 9 * 8)
|
Sprite.draw_at("norman", 13 * 8, 9 * 8)
|
||||||
Sprite.draw_at("dev_buddy", 15 * 8, 9 * 8)
|
|
||||||
Sprite.draw_at("dev_project_manager", 6 * 8, 4 * 8)
|
Sprite.draw_list(Context.office_sprites)
|
||||||
Sprite.draw_at("dev_hr_girl", 12 * 8, 4 * 8)
|
|
||||||
Sprite.draw_at("dev_introvert", -4 + 5 * 8, 9 * 8)
|
|
||||||
Sprite.draw_at("dev_extrovert", 20 * 8, 4 * 8)
|
|
||||||
Sprite.draw_at("dev_girl", 23 * 8, 5 * 8)
|
|
||||||
Sprite.draw_at("dev_boy", 10 * 8, 11 * 8 + 4)
|
|
||||||
Sprite.draw_at("dev_guru", 22 * 8, 10 * 8 + 4)
|
|
||||||
Sprite.draw_at("dev_operator", 27 * 8, 10 * 8 + 4)
|
|
||||||
end
|
end
|
||||||
Context.have_been_to_office = true
|
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Screen.register({
|
|||||||
},
|
},
|
||||||
background = "bedroom",
|
background = "bedroom",
|
||||||
init = function()
|
init = function()
|
||||||
|
Audio.music_play_mystery()
|
||||||
Context.stat_screen_active = true
|
Context.stat_screen_active = true
|
||||||
Meter.hide()
|
Meter.hide()
|
||||||
local cx = Config.screen.width * 0.75
|
local cx = Config.screen.width * 0.75
|
||||||
@@ -15,7 +16,7 @@ Screen.register({
|
|||||||
end,
|
end,
|
||||||
update = function()
|
update = function()
|
||||||
if not Context.stat_screen_active then return end
|
if not Context.stat_screen_active then return end
|
||||||
if Input.select() or Input.player_interact() then
|
if Input.select() or Input.select() then
|
||||||
Focus.stop()
|
Focus.stop()
|
||||||
Context.stat_screen_active = false
|
Context.stat_screen_active = false
|
||||||
Meter.show()
|
Meter.show()
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ Screen.register({
|
|||||||
"go_to_home",
|
"go_to_home",
|
||||||
"go_to_office",
|
"go_to_office",
|
||||||
},
|
},
|
||||||
|
init = function()
|
||||||
|
Audio.music_play_room_work()
|
||||||
|
end,
|
||||||
background = "street",
|
background = "street",
|
||||||
draw = function()
|
draw = function()
|
||||||
if Window.get_current_id() == "game" then
|
if Window.get_current_id() == "game" then
|
||||||
|
|||||||
@@ -6,6 +6,31 @@ Screen.register({
|
|||||||
"go_to_office",
|
"go_to_office",
|
||||||
"sumphore_discussion",
|
"sumphore_discussion",
|
||||||
},
|
},
|
||||||
|
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",
|
background = "street",
|
||||||
draw = function()
|
draw = function()
|
||||||
if Window.get_current_id() == "game" then
|
if Window.get_current_id() == "game" then
|
||||||
@@ -13,10 +38,8 @@ Screen.register({
|
|||||||
Sprite.draw_at("sumphore", 9 * 8, 2 * 8)
|
Sprite.draw_at("sumphore", 9 * 8, 2 * 8)
|
||||||
Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8)
|
Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8)
|
||||||
Sprite.draw_at("dev_guard", 22 * 8, 2 * 8)
|
Sprite.draw_at("dev_guard", 22 * 8, 2 * 8)
|
||||||
Sprite.draw_at("matrix_trinity", 5 * 8, 11 * 8)
|
|
||||||
Sprite.draw_at("matrix_neo", 7 * 8, 11 * 8)
|
Sprite.draw_list(Context.walking_to_office_sprites)
|
||||||
Sprite.draw_at("matrix_oraculum", 9 * 8, 12 * 8)
|
|
||||||
Sprite.draw_at("matrix_architect", 11 * 8, 11 * 8)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
Situation.register({
|
|
||||||
id = "drink_coffee",
|
|
||||||
handle = function()
|
|
||||||
Audio.sfx_select()
|
|
||||||
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
|
|
||||||
@@ -73,6 +73,70 @@ function Sprite.generate_table(width, height, starting_s, x_base, y_base, x_step
|
|||||||
return sprites
|
return sprites
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Immediately draws a list of sprites
|
||||||
|
--- @within Sprite
|
||||||
|
--- @param sprite_list table An array of tables, each containing: `id` (string) sprite identifier, `x` (number) x-coordinate, `y` (number) y-coordinate, and optional `colorkey`, `scale`, `flip_x`, `flip_y`, `rot` parameters.
|
||||||
|
function Sprite.draw_list(sprite_list)
|
||||||
|
for _, sprite_info in ipairs(sprite_list) do
|
||||||
|
local sprite_data = _sprites[sprite_info.id]
|
||||||
|
if not sprite_data then
|
||||||
|
trace("Error: Attempted to draw non-registered sprite with id: " .. sprite_info.id)
|
||||||
|
else
|
||||||
|
draw_sprite_instance(sprite_data, sprite_info)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Given a list of sprite IDs (or sprite entries with correction offsets) and a list of possible positions, randomly assigns each sprite to a unique position and returns a drawable list.
|
||||||
|
--- @within Sprite
|
||||||
|
--- @param sprite_ids table An array of sprite identifier values or tables.
|
||||||
|
--- Each entry may be either:
|
||||||
|
--- - string: sprite ID to draw.
|
||||||
|
--- - table: { sprite_id = string, x_correct = number, y_correct = number }.
|
||||||
|
--- @param positions table An array of tables, each containing `x` and `y` fields for possible sprite positions.
|
||||||
|
function Sprite.list_randomize(sprite_ids, positions)
|
||||||
|
if #sprite_ids > #positions then
|
||||||
|
trace("Error: More sprite IDs than available positions in Sprite.draw_randomized")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local shuffled_positions = {}
|
||||||
|
for i, pos in ipairs(positions) do
|
||||||
|
shuffled_positions[i] = pos
|
||||||
|
end
|
||||||
|
for i = #shuffled_positions, 2, -1 do
|
||||||
|
local j = math.random(i)
|
||||||
|
shuffled_positions[i], shuffled_positions[j] = shuffled_positions[j], shuffled_positions[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
local drawable_list = {}
|
||||||
|
for i, sprite_entry in ipairs(sprite_ids) do
|
||||||
|
local sprite_id = sprite_entry
|
||||||
|
local x_correct = 0
|
||||||
|
local y_correct = 0
|
||||||
|
|
||||||
|
if type(sprite_entry) == "table" then
|
||||||
|
sprite_id = sprite_entry.sprite_id or sprite_entry.id
|
||||||
|
x_correct = sprite_entry.x_correct or 0
|
||||||
|
y_correct = sprite_entry.y_correct or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local sprite_data = _sprites[sprite_id]
|
||||||
|
if not sprite_data then
|
||||||
|
trace("Error: Attempted to draw non-registered sprite with id: " .. tostring(sprite_id))
|
||||||
|
else
|
||||||
|
local pos = shuffled_positions[i]
|
||||||
|
table.insert(drawable_list, {
|
||||||
|
id = sprite_id,
|
||||||
|
x = pos.x + x_correct,
|
||||||
|
y = pos.y + y_correct
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return drawable_list
|
||||||
|
end
|
||||||
|
|
||||||
--- Schedules a sprite for drawing.
|
--- Schedules a sprite for drawing.
|
||||||
--- @within Sprite
|
--- @within Sprite
|
||||||
--- @param id string The unique identifier of the sprite.<br/>
|
--- @param id string The unique identifier of the sprite.<br/>
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ local INPUT_KEY_LEFT = 2
|
|||||||
local INPUT_KEY_RIGHT = 3
|
local INPUT_KEY_RIGHT = 3
|
||||||
local INPUT_KEY_A = 4
|
local INPUT_KEY_A = 4
|
||||||
local INPUT_KEY_B = 5
|
local INPUT_KEY_B = 5
|
||||||
local INPUT_KEY_Y = 7
|
|
||||||
local INPUT_KEY_SPACE = 48
|
local INPUT_KEY_SPACE = 48
|
||||||
local INPUT_KEY_BACKSPACE = 51
|
|
||||||
local INPUT_KEY_ENTER = 50
|
local INPUT_KEY_ENTER = 50
|
||||||
|
local INPUT_KEY_BACKSPACE = 51
|
||||||
|
|
||||||
--- Checks if Up is pressed.
|
--- Checks if Up is pressed.
|
||||||
--- @within Input
|
--- @within Input
|
||||||
@@ -22,22 +21,12 @@ function Input.left() return btnp(INPUT_KEY_LEFT) end
|
|||||||
--- Checks if Right is pressed.
|
--- Checks if Right is pressed.
|
||||||
--- @within Input
|
--- @within Input
|
||||||
function Input.right() return btnp(INPUT_KEY_RIGHT) end
|
function Input.right() return btnp(INPUT_KEY_RIGHT) end
|
||||||
--- Checks if Space is pressed.
|
|
||||||
--- @within Input
|
|
||||||
function Input.space() return keyp(INPUT_KEY_SPACE) end
|
|
||||||
|
|
||||||
--- Checks if Select is pressed.
|
--- Checks if Select is pressed.
|
||||||
--- @within Input
|
--- @within Input
|
||||||
function Input.select() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_SPACE) end
|
function Input.select() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_SPACE) or Mouse.clicked() end
|
||||||
--- Checks if Menu Confirm is pressed.
|
--- Checks if Back is pressed.
|
||||||
--- @within Input
|
--- @within Input
|
||||||
function Input.menu_confirm() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_ENTER) end
|
function Input.back() return btnp(INPUT_KEY_B) or keyp(INPUT_KEY_BACKSPACE) end
|
||||||
--- Checks if Player Interact is pressed.
|
--- Checks if Enter is pressed.
|
||||||
--- @within Input
|
--- @within Input
|
||||||
function Input.player_interact() return btnp(INPUT_KEY_B) or keyp(INPUT_KEY_ENTER) end
|
function Input.enter() return 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
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ end
|
|||||||
--- @within Main
|
--- @within Main
|
||||||
function TIC()
|
function TIC()
|
||||||
init_game()
|
init_game()
|
||||||
|
Mouse.update()
|
||||||
|
|
||||||
local now = time()
|
local now = time()
|
||||||
if Context.last_frame_time == 0 then
|
if Context.last_frame_time == 0 then
|
||||||
|
|||||||
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,7 @@ function Print.text(text, x, y, color, fixed, scale)
|
|||||||
local shadow_color = Config.colors.black
|
local shadow_color = Config.colors.black
|
||||||
if color == shadow_color then shadow_color = Config.colors.light_grey end
|
if color == shadow_color then shadow_color = Config.colors.light_grey end
|
||||||
scale = scale or 1
|
scale = scale or 1
|
||||||
print(text, x + 1, y + 1, shadow_color, fixed, scale)
|
print(text, x + scale, y + scale, shadow_color, fixed, scale)
|
||||||
print(text, x, y, color, fixed, scale)
|
print(text, x, y, color, fixed, scale)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ end
|
|||||||
--- @param[opt] scale number The scaling factor.<br/>
|
--- @param[opt] scale number The scaling factor.<br/>
|
||||||
function Print.text_center(text, x, y, color, fixed, scale)
|
function Print.text_center(text, x, y, color, fixed, scale)
|
||||||
scale = scale or 1
|
scale = scale or 1
|
||||||
local text_width = print(text, 0, -6, 0, fixed, scale)
|
local text_width = print(text, 0, -6 * scale, 0, fixed, scale)
|
||||||
local centered_x = x - (text_width / 2)
|
local centered_x = x - (text_width / 2)
|
||||||
Print.text(text, centered_x, y, color, fixed, scale)
|
Print.text(text, centered_x, y, color, fixed, scale)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -38,8 +38,12 @@ end
|
|||||||
--- @within UI
|
--- @within UI
|
||||||
--- @param items table A table of menu items.<br/>
|
--- @param items table A table of menu items.<br/>
|
||||||
--- @param selected_item number The current index of the selected item.<br/>
|
--- @param selected_item number The current index of the selected item.<br/>
|
||||||
|
--- @param[opt] x number Menu x position (required for mouse support).<br/>
|
||||||
|
--- @param[opt] y number Menu y position (required for mouse support).<br/>
|
||||||
|
--- @param[opt] centered boolean Whether the menu is centered horizontally.<br/>
|
||||||
--- @return number selected_item The updated index of the selected item.
|
--- @return number selected_item The updated index of the selected item.
|
||||||
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
|
if Input.up() then
|
||||||
Audio.sfx_beep()
|
Audio.sfx_beep()
|
||||||
selected_item = selected_item - 1
|
selected_item = selected_item - 1
|
||||||
@@ -53,7 +57,25 @@ function UI.update_menu(items, selected_item)
|
|||||||
selected_item = 1
|
selected_item = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return selected_item
|
|
||||||
|
if x ~= nil and y ~= nil then
|
||||||
|
local menu_x = x
|
||||||
|
if centered then
|
||||||
|
local max_w = 0
|
||||||
|
for _, item in ipairs(items) do
|
||||||
|
local w = print(item.label, 0, -10, 0, false, 1, false)
|
||||||
|
if w > max_w then max_w = w end
|
||||||
|
end
|
||||||
|
menu_x = (Config.screen.width - max_w) / 2
|
||||||
|
end
|
||||||
|
for i, _ in ipairs(items) do
|
||||||
|
if Mouse.zone({ x = menu_x - 8, y = y + (i-1) * 10, w = Config.screen.width, h = 10 }) then
|
||||||
|
return i, true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return selected_item, false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Draws a bordered textbox with scrolling text.
|
--- Draws a bordered textbox with scrolling text.
|
||||||
|
|||||||
@@ -39,4 +39,31 @@ function Util.contains(t, value)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
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.menuitems = AudioTestWindow.generate_menuitems(
|
||||||
AudioTestWindow.list_func, AudioTestWindow.index_func
|
AudioTestWindow.list_func, AudioTestWindow.index_func
|
||||||
)
|
)
|
||||||
elseif Input.menu_confirm() then
|
elseif Input.select() then
|
||||||
AudioTestWindow.menuitems[AudioTestWindow.index_menu].decision()
|
AudioTestWindow.menuitems[AudioTestWindow.index_menu].decision()
|
||||||
elseif Input.menu_back() then
|
elseif Input.back() then
|
||||||
AudioTestWindow.back()
|
AudioTestWindow.back()
|
||||||
end
|
end
|
||||||
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
|
--- @within ContinuedWindow
|
||||||
function ContinuedWindow.update()
|
function ContinuedWindow.update()
|
||||||
ContinuedWindow.timer = ContinuedWindow.timer - 1
|
ContinuedWindow.timer = ContinuedWindow.timer - 1
|
||||||
if ContinuedWindow.timer <= 0 or Input.select() or Input.menu_confirm() then
|
if ContinuedWindow.timer <= 0 or Input.select() or Input.select() then
|
||||||
Window.set_current("menu")
|
Window.set_current("menu")
|
||||||
MenuWindow.refresh_menu_items()
|
MenuWindow.refresh_menu_items()
|
||||||
end
|
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
|
||||||
@@ -52,7 +52,7 @@ function EndWindow.update()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Input.menu_confirm() then
|
if Input.select() then
|
||||||
Audio.sfx_select()
|
Audio.sfx_select()
|
||||||
if Context._end.selection == 1 then
|
if Context._end.selection == 1 then
|
||||||
Context._end.state = "ending"
|
Context._end.state = "ending"
|
||||||
@@ -69,7 +69,7 @@ function EndWindow.update()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif Context._end.state == "ending" then
|
elseif Context._end.state == "ending" then
|
||||||
if Input.menu_confirm() then
|
if Input.select() then
|
||||||
Window.set_current("menu")
|
Window.set_current("menu")
|
||||||
MenuWindow.refresh_menu_items()
|
MenuWindow.refresh_menu_items()
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ end
|
|||||||
--- @within GameWindow
|
--- @within GameWindow
|
||||||
function GameWindow.update()
|
function GameWindow.update()
|
||||||
Focus.update()
|
Focus.update()
|
||||||
if Input.menu_back() then
|
if Input.back() then
|
||||||
Window.set_current("menu")
|
Window.set_current("menu")
|
||||||
MenuWindow.refresh_menu_items()
|
MenuWindow.refresh_menu_items()
|
||||||
return
|
return
|
||||||
@@ -48,14 +48,6 @@ function GameWindow.update()
|
|||||||
if not screen or not screen.update then return end
|
if not screen or not screen.update then return end
|
||||||
screen.update()
|
screen.update()
|
||||||
|
|
||||||
-- Handle current situation updates
|
|
||||||
if Context.game.current_situation then
|
|
||||||
local current_situation_obj = Situation.get_by_id(Context.game.current_situation)
|
|
||||||
if current_situation_obj and type(current_situation_obj.update) == "function" then
|
|
||||||
current_situation_obj.update()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if Context.stat_screen_active then return end
|
if Context.stat_screen_active then return end
|
||||||
|
|
||||||
-- Fetch and filter decisions locally
|
-- Fetch and filter decisions locally
|
||||||
@@ -68,7 +60,7 @@ function GameWindow.update()
|
|||||||
_selected_decision_index = 1
|
_selected_decision_index = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local new_selected_decision_index = Decision.update(
|
local new_selected_decision_index, mouse_confirmed = Decision.update(
|
||||||
_available_decisions,
|
_available_decisions,
|
||||||
_selected_decision_index
|
_selected_decision_index
|
||||||
)
|
)
|
||||||
@@ -77,7 +69,7 @@ function GameWindow.update()
|
|||||||
_selected_decision_index = new_selected_decision_index
|
_selected_decision_index = new_selected_decision_index
|
||||||
end
|
end
|
||||||
|
|
||||||
if Input.select() then
|
if Input.select() or mouse_confirmed then
|
||||||
local selected_decision = _available_decisions[_selected_decision_index]
|
local selected_decision = _available_decisions[_selected_decision_index]
|
||||||
if selected_decision and selected_decision.handle then
|
if selected_decision and selected_decision.handle then
|
||||||
Audio.sfx_select()
|
Audio.sfx_select()
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function BriefIntroWindow.update()
|
|||||||
lines = lines + 1
|
lines = lines + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if BriefIntroWindow.y < -lines * 8 or Input.select() or Input.menu_confirm() then
|
if BriefIntroWindow.y < -lines * 8 or Input.select() or Input.select() then
|
||||||
Window.set_current("menu")
|
Window.set_current("menu")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ end
|
|||||||
--- @within TitleIntroWindow
|
--- @within TitleIntroWindow
|
||||||
function TitleIntroWindow.update()
|
function TitleIntroWindow.update()
|
||||||
TitleIntroWindow.timer = TitleIntroWindow.timer - 1
|
TitleIntroWindow.timer = TitleIntroWindow.timer - 1
|
||||||
if TitleIntroWindow.timer <= 0 or Input.select() or Input.menu_confirm() then
|
if TitleIntroWindow.timer <= 0 or Input.select() or Input.select() then
|
||||||
Window.set_current("intro_ttg")
|
Window.set_current("intro_ttg")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,13 +27,13 @@ function TTGIntroWindow.update()
|
|||||||
TTGIntroWindow.glitch_started = true
|
TTGIntroWindow.glitch_started = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Count menu_back presses during the intro
|
-- Count enter presses during the intro
|
||||||
if Input.menu_back() then
|
if Input.enter() then
|
||||||
TTGIntroWindow.space_count = TTGIntroWindow.space_count + 1
|
TTGIntroWindow.space_count = TTGIntroWindow.space_count + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
TTGIntroWindow.timer = TTGIntroWindow.timer - 1
|
TTGIntroWindow.timer = TTGIntroWindow.timer - 1
|
||||||
if TTGIntroWindow.timer <= 0 or Input.menu_confirm() then
|
if TTGIntroWindow.timer <= 0 or Input.select() then
|
||||||
-- Evaluate exactly 3 presses at the end of the intro
|
-- Evaluate exactly 3 presses at the end of the intro
|
||||||
if TTGIntroWindow.space_count == 3 then
|
if TTGIntroWindow.space_count == 3 then
|
||||||
Context.test_mode = true
|
Context.test_mode = true
|
||||||
|
|||||||
@@ -1,18 +1,62 @@
|
|||||||
--- @section MenuWindow
|
--- @section MenuWindow
|
||||||
local _menu_items = {}
|
local _menu_items = {}
|
||||||
|
local _click_timer = 0
|
||||||
|
local _anim = 0
|
||||||
|
local _menu_max_w = 0
|
||||||
|
local ANIM_SPEED = 2.5
|
||||||
|
local HEADER_H = 28
|
||||||
|
|
||||||
|
--- Calculates the animated x position of the menu block.
|
||||||
|
--- @within MenuWindow
|
||||||
|
--- @return number x The left edge x coordinate for the menu.
|
||||||
|
function MenuWindow.calc_menu_x()
|
||||||
|
local center_start = Config.screen.width / 2
|
||||||
|
local center_end = Config.screen.width * 0.72
|
||||||
|
local center = center_start + _anim * (center_end - center_start)
|
||||||
|
return math.floor(center - _menu_max_w / 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Draws the header with title and separator.
|
||||||
|
--- @within MenuWindow
|
||||||
|
function MenuWindow.draw_header()
|
||||||
|
rect(0, 0, Config.screen.width, HEADER_H, Config.colors.dark_grey)
|
||||||
|
rect(0, HEADER_H - 2, Config.screen.width, 2, Config.colors.light_blue)
|
||||||
|
|
||||||
|
local cx = Config.screen.width / 2
|
||||||
|
local subtitle = "Definitely not an"
|
||||||
|
if Context.test_mode then subtitle = subtitle .. " [TEST]" end
|
||||||
|
local sub_w = print(subtitle, 0, -6, 0, false, 1, true)
|
||||||
|
print(subtitle, math.floor(cx - sub_w / 2) + 1, 5, Config.colors.dark_grey, false, 1, true)
|
||||||
|
print(subtitle, math.floor(cx - sub_w / 2), 4, Config.colors.light_grey, false, 1, true)
|
||||||
|
|
||||||
|
Print.text_center("IMPOSTOR", cx, 12, Config.colors.item, false, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Draws the 4x scaled Norman sprite on the left side of the screen.
|
||||||
|
--- @within MenuWindow
|
||||||
|
function MenuWindow.draw_norman()
|
||||||
|
local nx = math.floor(Config.screen.width * 0.45 / 2) - 32
|
||||||
|
local ny = HEADER_H + math.floor((Config.screen.height - HEADER_H - 96) / 2)
|
||||||
|
spr(272, nx, ny, 0, 4)
|
||||||
|
spr(273, nx + 32, ny, 0, 4)
|
||||||
|
spr(288, nx, ny + 32, 0, 4)
|
||||||
|
spr(289, nx + 32, ny + 32, 0, 4)
|
||||||
|
spr(304, nx, ny + 64, 0, 4)
|
||||||
|
spr(305, nx + 32, ny + 64, 0, 4)
|
||||||
|
end
|
||||||
|
|
||||||
--- Draws the menu window.
|
--- Draws the menu window.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.draw()
|
function MenuWindow.draw()
|
||||||
local title = "Definitely not an Impostor"
|
MenuWindow.draw_header()
|
||||||
if Context.test_mode then
|
|
||||||
title = title .. " (TEST MODE)"
|
if _anim > 0 then
|
||||||
|
MenuWindow.draw_norman()
|
||||||
end
|
end
|
||||||
UI.draw_top_bar(title)
|
|
||||||
|
|
||||||
local menu_h = #_menu_items * 10
|
local menu_h = #_menu_items * 10
|
||||||
local y = 10 + (Config.screen.height - 10 - 10 - menu_h) / 2
|
local y = HEADER_H + math.floor((Config.screen.height - HEADER_H - 10 - menu_h) / 2)
|
||||||
UI.draw_menu(_menu_items, Context.current_menu_item, 0, y, true)
|
UI.draw_menu(_menu_items, Context.current_menu_item, MenuWindow.calc_menu_x(), y, false)
|
||||||
|
|
||||||
local ttg_text = "TTG"
|
local ttg_text = "TTG"
|
||||||
local ttg_w = print(ttg_text, 0, -10, 0, false, 1, false)
|
local ttg_w = print(ttg_text, 0, -10, 0, false, 1, false)
|
||||||
@@ -22,9 +66,32 @@ end
|
|||||||
--- Updates the menu window logic.
|
--- Updates the menu window logic.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.update()
|
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]
|
local selected_item = _menu_items[Context.current_menu_item]
|
||||||
if selected_item and selected_item.decision then
|
if selected_item and selected_item.decision then
|
||||||
Audio.sfx_select()
|
Audio.sfx_select()
|
||||||
@@ -64,11 +131,10 @@ function MenuWindow.exit()
|
|||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Opens the configuration menu.
|
--- Opens the controls screen.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.configuration()
|
function MenuWindow.controls()
|
||||||
ConfigurationWindow.init()
|
Window.set_current("controls")
|
||||||
GameWindow.set_state("configuration")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Opens the audio test menu.
|
--- Opens the audio test menu.
|
||||||
@@ -85,34 +151,42 @@ function MenuWindow.continued()
|
|||||||
GameWindow.set_state("continued")
|
GameWindow.set_state("continued")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Opens the minigame ddr test menu.
|
--- Opens the DDR minigame test.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.ddr_test()
|
function MenuWindow.ddr_test()
|
||||||
AudioTestWindow.init()
|
AudioTestWindow.init()
|
||||||
GameWindow.set_state("minigame_ddr")
|
GameWindow.set_state("minigame_ddr")
|
||||||
MinigameDDRWindow.start("menu", nil)
|
MinigameDDRWindow.start("menu", "generated", { special_mode = "only_nothing" })
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Refreshes menu items.
|
--- Refreshes the list of menu items based on current game state.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.refresh_menu_items()
|
function MenuWindow.refresh_menu_items()
|
||||||
_menu_items = {}
|
_menu_items = {}
|
||||||
if Context.game_in_progress then
|
if Context.game_in_progress then
|
||||||
table.insert(_menu_items, {label = "Resume Game", decision = MenuWindow.resume_game})
|
table.insert(_menu_items, {label = "Resume Game", decision = MenuWindow.resume_game})
|
||||||
table.insert(_menu_items, {label = "Save Game", decision = MenuWindow.save_game})
|
table.insert(_menu_items, {label = "Save Game", decision = MenuWindow.save_game})
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(_menu_items, {label = "New Game", decision = MenuWindow.new_game})
|
table.insert(_menu_items, {label = "New Game", decision = MenuWindow.new_game})
|
||||||
table.insert(_menu_items, {label = "Load Game", decision = MenuWindow.load_game})
|
table.insert(_menu_items, {label = "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
|
if Context.test_mode then
|
||||||
table.insert(_menu_items, {label = "Audio Test", decision = MenuWindow.audio_test})
|
table.insert(_menu_items, {label = "Audio Test", decision = MenuWindow.audio_test})
|
||||||
table.insert(_menu_items, {label = "To Be Continued...", decision = MenuWindow.continued})
|
table.insert(_menu_items, {label = "To Be Continued...", decision = MenuWindow.continued})
|
||||||
table.insert(_menu_items, {label = "DDR Test", decision = MenuWindow.ddr_test})
|
table.insert(_menu_items, {label = "DDR Test", decision = MenuWindow.ddr_test})
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit})
|
table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit})
|
||||||
|
|
||||||
|
_menu_max_w = 0
|
||||||
|
for _, item in ipairs(_menu_items) do
|
||||||
|
local w = print(item.label, 0, -10, 0, false, 1, false)
|
||||||
|
if w > _menu_max_w then _menu_max_w = w end
|
||||||
|
end
|
||||||
|
|
||||||
Context.current_menu_item = 1
|
Context.current_menu_item = 1
|
||||||
|
_click_timer = 0
|
||||||
|
_anim = 0
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
--- Background drawing for DDR minigame.
|
--- Background drawing for DDR minigame.
|
||||||
--- @witin MinigameDDRWindow
|
--- @witin MinigameDDRWindow
|
||||||
function MinigameDDRWindow.draw_background()
|
function MinigameDDRWindow.draw_background()
|
||||||
local img_values = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}
|
local img_values = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}
|
||||||
local img_runs = {213,27,213,27,212,28,212,28,211,29,212,28,212,28,212,28,211,29,211,29,126,16,69,29,136,9,66,29,210,30,80,1,129,30,80,1,78,1,51,29,80,1,78,1,51,29,80,2,77,1,51,28,81,2,76,2,51,28,81,2,76,2,50,29,81,2,76,2,51,28,81,2,76,2,50,29,81,2,76,2,50,28,82,2,75,3,50,28,81,4,74,3,50,28,81,4,74,3,51,27,81,4,74,3,50,27,82,4,74,3,50,27,82,4,74,3,51,26,82,4,73,4,50,27,82,4,73,4,51,25,83,4,73,4,50,26,83,4,2,2,69,4,50,26,83,5,1,2,27,7,35,4,50,26,83,9,23,13,28,1,3,4,50,26,83,9,5,2,15,15,27,2,2,4,50,25,84,9,3,5,14,16,26,3,1,4,51,24,84,9,3,6,13,16,26,8,51,24,85,8,3,5,15,14,27,8,50,25,85,8,26,9,29,8,50,25,85,8,63,9,51,23,86,8,63,9,51,23,86,8,63,9,51,23,86,8,12,3,13,5,30,9,51,23,86,8,12,3,12,7,29,8,52,22,87,8,28,5,30,8,53,21,87,8,63,8,52,22,87,8,63,8,52,22,87,8,62,9,52,21,88,8,62,9,52,21,88,8,62,9,52,21,88,8,62,9,52,21,88,8,62,9,51,22,88,8,62,9,51,21,89,8,62,9,52,20,89,8,62,9,52,20,89,8,62,9,52,20,89,8,62,9,52,20,89,8,62,9,52,19,90,9,61,9,53,18,90,9,61,9,53,18,90,9,61,8,53,19,90,9,61,8,53,18,91,9,61,8,53,18,91,9,60,9,52,19,91,10,59,9,52,19,91,10,59,9,51,20,91,16,1,2,48,11,51,19,93,77,51,19,93,77,52,18,93,77,51,19,93,77,51,19,93,77,50,19,94,76,51,19,94,12,1,63,51,19,94,75,52,19,94,4,12,46,2,9,54,19,94,2,33,24,68,19,220,20,220,19,220,20,220,20,220,20,89,6,125,19,88,9,76,4,43,20,87,11,74,6,42,20,86,12,73,8,39,22,86,69,15,10,37,23,85,82,3,11,36,22,85,98,35,22,84,100,33,23,83,102,31,24,82,104,29,25,81,106,27,26,80,108,26,25,80,110,25,25,79,112,24,25,78,113,24,25,77,115,23,25,77,116,22,24,78,2,11,104,20,25,78,1,65,51,20,25,78,1,115,1,21,23,79,1,115,1,21,23,79,1,115,1,20,24,79,1,115,1,20,24,79,1,115,1,20,24,79,1,74,10,6,1,24,1,21,22,80,1,75,9,4,7,20,1,21,22,80,1,75,9,4,7,20,1,20,23,80,1,76,8,4,7,20,1,21,22,80,1,115,1,22,20,81,1,115,1,23,19,197,1,24,18,197,1,25,17,223,17,224,16,226,13,228,12,228,12,229,11,81,4,145,9,80,9,137,3,3,8,73,3,8,122,21,3,3,7,72,3,129,4,19,4,3,6,71,3,131,4,19,4,3,5,71,2,13,8,5,8,99,4,18,5,4,2,71,3,11,10,5,8,100,3,17,7,4,1,71,2,8,30,97,4,16,8,74,3,136,4,14,10,72,3,138,3,14,11,71,3,10,3,9,3,3,3,3,3,4,2,95,4,13,12,69,3,10,4,8,4,3,3,3,3,3,3,7,4,2,4,2,4,2,4,6,4,2,4,2,4,2,4,2,4,5,4,2,4,2,4,2,4,6,3,12,13,69,2,10,5,8,4,2,4,2,4,3,3,7,4,2,4,2,4,2,4,6,4,2,4,2,4,2,4,2,4,5,4,2,4,2,4,2,4,6,4,11,13,68,3,10,5,1,2,5,4,3,3,2,4,3,3,7,4,2,3,3,4,2,4,6,4,2,4,2,4,2,4,2,4,5,4,2,5,1,4,3,3,7,4,10,13,68,2,11,5,1,2,20,1,5,1,7,3,5,1,6,1,2,1,1,1,9,2,3,3,3,3,3,3,2,1,1,2,6,3,4,2,3,3,5,1,7,4,9,13,68,3,10,6,1,2,33,2,1,1,3,1,4,3,2,9,4,3,3,3,3,3,2,5,1,5,6,2,4,3,4,3,2,3,7,4,8,13,67,3,13,4,3,2,19,1,5,1,5,1,4,3,4,2,4,3,3,2,4,3,3,3,3,3,2,5,2,4,6,3,3,3,4,3,3,2,8,4,7,13,67,3,13,4,17,1,11,2,5,1,4,3,4,2,4,2,4,2,4,3,3,3,4,2,3,4,2,4,6,3,4,3,3,3,3,3,7,4,7,13,66,3,14,4,29,1,12,1,4,1,1,1,4,2,4,2,4,2,4,3,4,3,2,4,2,4,6,3,4,2,4,3,3,3,8,4,6,13,66,2,14,5,83,11,21,1,14,4,7,12,65,3,14,5,31,1,1,1,10,2,5,2,5,1,6,1,5,1,5,2,4,11,8,2,4,2,5,1,5,2,8,4,6,11,66,2,14,6,1,2,8,3,4,2,4,3,4,3,3,3,4,3,3,3,3,4,3,3,4,3,4,2,2,11,10,2,4,3,4,2,4,2,8,5,5,11,65,3,14,6,1,2,1,3,4,3,4,2,4,3,4,3,3,3,4,3,3,3,3,4,3,3,3,4,3,16,10,2,4,3,4,2,4,3,8,4,5,11,64,3,15,9,42,1,4,2,4,3,4,3,4,2,5,16,15,1,12,3,9,4,4,11,64,3,10,2,3,8,31,1,18,2,4,2,19,13,11,2,5,1,6,1,15,4,4,11,63,3,9,4,2,7,1,1,11,1,5,2,5,2,5,1,5,2,4,3,4,3,3,3,5,2,4,3,1,12,2,2,11,3,4,2,5,2,2,4,9,4,4,9,64,2,10,4,2,7,1,2,3,1,4,3,4,3,4,3,5,1,4,3,4,3,3,4,3,3,4,3,4,15,3,2,11,3,5,2,4,9,8,5,4,8,63,3,9,5,2,8,4,2,4,3,4,3,3,4,3,3,4,3,4,3,3,4,3,3,4,3,3,17,2,3,10,3,4,3,3,11,8,5,4,7,62,3,10,4,2,10,30,2,4,3,4,3,3,4,3,3,4,3,3,4,1,12,1,4,10,3,4,4,2,4,3,5,7,5,4,7,62,3,10,3,3,9,76,11,1,4,10,2,4,4,6,1,3,5,8,5,1,9,61,3,9,5,3,8,2,2,46,1,5,2,5,2,10,18,10,3,3,5,5,1,3,6,8,14,61,3,9,5,2,9,1,4,8,3,4,3,4,3,4,3,5,2,4,3,4,3,4,3,5,2,2,13,1,5,10,3,3,6,5,2,1,6,8,13,61,3,10,5,2,13,9,3,4,3,4,3,4,3,11,3,4,3,4,3,9,19,11,2,2,7,4,2,2,7,8,12,60,3,11,5,2,13,58,1,11,20,10,12,3,11,8,12,60,3,24,6,71,20,11,1,8,2,9,5,9,11,59,3,40,4,3,5,2,6,1,35,17,9,45,11,59,3,36,61,16,9,46,10,58,3,37,60,17,10,46,8,58,4,114,10,46,8,58,3,116,9,47,7,57,4,172,6,58,3,174,5,57,5,173,6,55,60,73,52,55,4,118,64,53,4,119,64,53,4,120,63,53,4,120,63,53,6,10,3,104,64,53,187,54,186,55,184,59,180,82,7,25,63,2,5,6,5,16,4,9,14,214,2,238,1,239,3,776}
|
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 = {255,255,255,0,0,0}
|
-- pal = {220,220,220,90,90,90}
|
||||||
-- pal = ffffff000000
|
-- pal = dcdcdc5a5a5a
|
||||||
RLE.draw(img_values, img_runs)
|
RLE.draw(img_values, img_runs)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ function MinigameDDRWindow.init_context()
|
|||||||
local total_width = (4 * arrow_size) + (3 * arrow_spacing)
|
local total_width = (4 * arrow_size) + (3 * arrow_spacing)
|
||||||
local start_x = (Config.screen.width - total_width) / 2
|
local start_x = (Config.screen.width - total_width) / 2
|
||||||
return {
|
return {
|
||||||
|
special_mode = "normal", -- "normal", "only_special", "only_left", "only_nothing"
|
||||||
bar_fill = 0,
|
bar_fill = 0,
|
||||||
max_fill = 100,
|
max_fill = 100,
|
||||||
fill_per_hit = 10,
|
fill_per_hit = 10,
|
||||||
@@ -48,14 +49,92 @@ function MinigameDDRWindow.init_context()
|
|||||||
current_song = nil,
|
current_song = nil,
|
||||||
pattern_index = 1,
|
pattern_index = 1,
|
||||||
use_pattern = false,
|
use_pattern = false,
|
||||||
|
generated_length = 30,
|
||||||
return_window = nil,
|
return_window = nil,
|
||||||
win_timer = 0,
|
win_timer = 0,
|
||||||
on_win = nil,
|
on_win = nil,
|
||||||
special_condition_met = false,
|
|
||||||
total_misses = 0,
|
total_misses = 0,
|
||||||
|
total_hits = 0,
|
||||||
|
special_mode_condition = true,
|
||||||
|
special_mode_counter = 0
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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 was_ok = true
|
||||||
|
if game_context.special_mode == "normal" then
|
||||||
|
was_ok = game_context.special_mode_counter == num_special
|
||||||
|
elseif game_context.special_mode == "only_special" then
|
||||||
|
was_ok = game_context.special_mode_counter == num_special
|
||||||
|
elseif game_context.special_mode == "only_left" then
|
||||||
|
was_ok = game_context.special_mode_counter == num_special
|
||||||
|
end
|
||||||
|
|
||||||
|
game_context.special_mode_condition = game_context.special_mode_condition and was_ok
|
||||||
|
end
|
||||||
|
|
||||||
--- Initializes DDR minigame state.
|
--- Initializes DDR minigame state.
|
||||||
--- @within MinigameDDRWindow
|
--- @within MinigameDDRWindow
|
||||||
--- @param params table Optional parameters for configuration.<br/>
|
--- @param params table Optional parameters for configuration.<br/>
|
||||||
@@ -76,13 +155,22 @@ end
|
|||||||
--- @param[opt] params table Optional parameters for minigame configuration.</br>
|
--- @param[opt] params table Optional parameters for minigame configuration.</br>
|
||||||
function MinigameDDRWindow.start(return_window, song_key, params)
|
function MinigameDDRWindow.start(return_window, song_key, params)
|
||||||
MinigameDDRWindow.init(params)
|
MinigameDDRWindow.init(params)
|
||||||
|
|
||||||
|
Audio.music_play_activity_work()
|
||||||
|
|
||||||
Context.minigame_ddr.return_window = return_window or "game"
|
Context.minigame_ddr.return_window = return_window or "game"
|
||||||
Context.minigame_ddr.debug_song_key = song_key
|
Context.minigame_ddr.debug_song_key = song_key
|
||||||
if song_key and Songs and Songs[song_key] then
|
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.use_pattern = true
|
||||||
Context.minigame_ddr.pattern_index = 1
|
Context.minigame_ddr.pattern_index = 1
|
||||||
Context.minigame_ddr.debug_status = "Pattern loaded: " .. song_key
|
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
|
else
|
||||||
Context.minigame_ddr.use_pattern = false
|
Context.minigame_ddr.use_pattern = false
|
||||||
if song_key then
|
if song_key then
|
||||||
@@ -91,12 +179,19 @@ function MinigameDDRWindow.start(return_window, song_key, params)
|
|||||||
Context.minigame_ddr.debug_status = "Random mode"
|
Context.minigame_ddr.debug_status = "Random mode"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not Context.test_mode then
|
||||||
|
Context.minigame_ddr.debug_status = ""
|
||||||
|
end
|
||||||
|
|
||||||
Window.set_current("minigame_ddr")
|
Window.set_current("minigame_ddr")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Spawns a random arrow.
|
--- Spawns a random arrow.
|
||||||
--- @within MinigameDDRWindow
|
--- @within MinigameDDRWindow
|
||||||
local function spawn_arrow()
|
local function spawn_arrow()
|
||||||
|
trace("random arrow")
|
||||||
|
|
||||||
local mg = Context.minigame_ddr
|
local mg = Context.minigame_ddr
|
||||||
local target = mg.target_arrows[math.random(1, 4)]
|
local target = mg.target_arrows[math.random(1, 4)]
|
||||||
table.insert(mg.arrows, {
|
table.insert(mg.arrows, {
|
||||||
@@ -109,14 +204,16 @@ end
|
|||||||
--- Spawns an arrow in a specific direction.
|
--- Spawns an arrow in a specific direction.
|
||||||
--- @within MinigameDDRWindow
|
--- @within MinigameDDRWindow
|
||||||
--- @param direction string The direction of the arrow ("left", "down", "up", "right").
|
--- @param direction string The direction of the arrow ("left", "down", "up", "right").
|
||||||
local function spawn_arrow_dir(direction)
|
local function spawn_arrow_dir(direction, note, special)
|
||||||
local mg = Context.minigame_ddr
|
local mg = Context.minigame_ddr
|
||||||
for _, target in ipairs(mg.target_arrows) do
|
for _, target in ipairs(mg.target_arrows) do
|
||||||
if target.dir == direction then
|
if target.dir == direction then
|
||||||
table.insert(mg.arrows, {
|
table.insert(mg.arrows, {
|
||||||
dir = direction,
|
dir = direction,
|
||||||
x = target.x,
|
x = target.x,
|
||||||
y = mg.bar_y + mg.bar_height + 10
|
y = mg.bar_y + mg.bar_height + 10,
|
||||||
|
note = note,
|
||||||
|
special = special
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -174,10 +271,10 @@ function MinigameDDRWindow.update()
|
|||||||
if mg.win_timer > 0 then
|
if mg.win_timer > 0 then
|
||||||
mg.win_timer = mg.win_timer - 1
|
mg.win_timer = mg.win_timer - 1
|
||||||
if mg.win_timer == 0 then
|
if mg.win_timer == 0 then
|
||||||
mg.special_condition_met = (mg.total_misses == 0)
|
Audio.music_stop()
|
||||||
Meter.on_minigame_complete()
|
Meter.on_minigame_complete()
|
||||||
if mg.on_win then
|
if mg.on_win then
|
||||||
mg.on_win()
|
mg.on_win(mg)
|
||||||
else
|
else
|
||||||
Meter.show()
|
Meter.show()
|
||||||
Window.set_current(mg.return_window)
|
Window.set_current(mg.return_window)
|
||||||
@@ -187,22 +284,26 @@ function MinigameDDRWindow.update()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if mg.bar_fill >= mg.max_fill then
|
if mg.bar_fill >= mg.max_fill then
|
||||||
mg.win_timer = Config.timing.minigame_win_duration
|
MinigameDDRWindow.on_end(mg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
mg.frame_counter = mg.frame_counter + 1
|
mg.frame_counter = mg.frame_counter + 1
|
||||||
|
|
||||||
if mg.use_pattern and mg.current_song and mg.current_song.end_frame then
|
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
|
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
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if mg.use_pattern and mg.current_song and mg.current_song.pattern then
|
if mg.use_pattern and mg.current_song and mg.current_song.pattern then
|
||||||
local pattern = mg.current_song.pattern
|
local pattern = mg.current_song.pattern
|
||||||
while mg.pattern_index <= #pattern do
|
while mg.pattern_index <= #pattern do
|
||||||
local spawn_entry = pattern[mg.pattern_index]
|
local spawn_entry = pattern[mg.pattern_index]
|
||||||
|
|
||||||
if mg.frame_counter >= spawn_entry.frame then
|
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
|
mg.pattern_index = mg.pattern_index + 1
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
@@ -215,6 +316,8 @@ function MinigameDDRWindow.update()
|
|||||||
mg.arrow_spawn_timer = 0
|
mg.arrow_spawn_timer = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- move arrow downwards
|
||||||
local arrows_to_remove = {}
|
local arrows_to_remove = {}
|
||||||
for i, arrow in ipairs(mg.arrows) do
|
for i, arrow in ipairs(mg.arrows) do
|
||||||
arrow.y = arrow.y + mg.arrow_fall_speed
|
arrow.y = arrow.y + mg.arrow_fall_speed
|
||||||
@@ -227,26 +330,37 @@ function MinigameDDRWindow.update()
|
|||||||
mg.total_misses = mg.total_misses + 1
|
mg.total_misses = mg.total_misses + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- iterate backwards to avoid index shift issues
|
-- iterate backwards to avoid index shift issues
|
||||||
for i = #arrows_to_remove, 1, -1 do
|
for i = #arrows_to_remove, 1, -1 do
|
||||||
table.remove(mg.arrows, arrows_to_remove[i])
|
table.remove(mg.arrows, arrows_to_remove[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
for dir, _ in pairs(mg.input_cooldowns) do
|
for dir, _ in pairs(mg.input_cooldowns) do
|
||||||
if mg.input_cooldowns[dir] > 0 then
|
if mg.input_cooldowns[dir] > 0 then
|
||||||
mg.input_cooldowns[dir] = mg.input_cooldowns[dir] - 1
|
mg.input_cooldowns[dir] = mg.input_cooldowns[dir] - 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for dir, _ in pairs(mg.button_pressed_timers) do
|
for dir, _ in pairs(mg.button_pressed_timers) do
|
||||||
if mg.button_pressed_timers[dir] > 0 then
|
if mg.button_pressed_timers[dir] > 0 then
|
||||||
mg.button_pressed_timers[dir] = mg.button_pressed_timers[dir] - 1
|
mg.button_pressed_timers[dir] = mg.button_pressed_timers[dir] - 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local input_map = {
|
local input_map = {
|
||||||
left = Input.left(),
|
left = Input.left(),
|
||||||
down = Input.down(),
|
down = Input.down(),
|
||||||
up = Input.up(),
|
up = Input.up(),
|
||||||
right = Input.right()
|
right = Input.right()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, target in ipairs(mg.target_arrows) do
|
||||||
|
if Mouse.zone({ x = target.x, y = mg.target_y, w = mg.arrow_size, h = mg.arrow_size }) then
|
||||||
|
input_map[target.dir] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for dir, pressed in pairs(input_map) do
|
for dir, pressed in pairs(input_map) do
|
||||||
if pressed and mg.input_cooldowns[dir] == 0 then
|
if pressed and mg.input_cooldowns[dir] == 0 then
|
||||||
mg.input_cooldowns[dir] = mg.input_cooldown_duration
|
mg.input_cooldowns[dir] = mg.input_cooldown_duration
|
||||||
@@ -254,6 +368,8 @@ function MinigameDDRWindow.update()
|
|||||||
local hit = false
|
local hit = false
|
||||||
for i, arrow in ipairs(mg.arrows) do
|
for i, arrow in ipairs(mg.arrows) do
|
||||||
if arrow.dir == dir and check_hit(arrow) then
|
if arrow.dir == dir and check_hit(arrow) then
|
||||||
|
MinigameDDRWindow.on_arrow_hit_special(arrow, mg)
|
||||||
|
|
||||||
mg.bar_fill = mg.bar_fill + mg.fill_per_hit
|
mg.bar_fill = mg.bar_fill + mg.fill_per_hit
|
||||||
if mg.bar_fill > mg.max_fill then
|
if mg.bar_fill > mg.max_fill then
|
||||||
mg.bar_fill = mg.max_fill
|
mg.bar_fill = mg.max_fill
|
||||||
@@ -315,7 +431,8 @@ function MinigameDDRWindow.draw()
|
|||||||
end
|
end
|
||||||
if mg.arrows then
|
if mg.arrows then
|
||||||
for _, arrow in ipairs(mg.arrows) do
|
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
|
||||||
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("Hit the arrows!", Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_grey)
|
||||||
@@ -324,7 +441,7 @@ function MinigameDDRWindow.draw()
|
|||||||
Print.text_center(mg.debug_status, Config.screen.width / 2, debug_y, Config.colors.item)
|
Print.text_center(mg.debug_status, Config.screen.width / 2, debug_y, Config.colors.item)
|
||||||
debug_y = debug_y + 10
|
debug_y = debug_y + 10
|
||||||
end
|
end
|
||||||
if mg.use_pattern then
|
if mg.use_pattern and Context.test_mode then
|
||||||
Print.text_center(
|
Print.text_center(
|
||||||
"PATTERN MODE - Frame:" .. mg.frame_counter,
|
"PATTERN MODE - Frame:" .. mg.frame_counter,
|
||||||
Config.screen.width / 2,
|
Config.screen.width / 2,
|
||||||
@@ -339,10 +456,16 @@ function MinigameDDRWindow.draw()
|
|||||||
Config.colors.light_blue
|
Config.colors.light_blue
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
else
|
elseif Context.test_mode then
|
||||||
Print.text_center("RANDOM MODE", Config.screen.width / 2, debug_y, Config.colors.blue)
|
Print.text_center("RANDOM MODE", Config.screen.width / 2, debug_y, Config.colors.blue)
|
||||||
end
|
end
|
||||||
if mg.win_timer > 0 then
|
if mg.win_timer > 0 then
|
||||||
Minigame.draw_win_overlay()
|
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
|
||||||
end
|
|
||||||
@@ -83,7 +83,11 @@ function MinigameButtonMashWindow.update()
|
|||||||
return
|
return
|
||||||
end
|
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.bar_fill = mg.bar_fill + mg.fill_per_press
|
||||||
mg.button_pressed_timer = mg.button_press_duration
|
mg.button_pressed_timer = mg.button_press_duration
|
||||||
if mg.bar_fill > mg.target_points then
|
if mg.bar_fill > mg.target_points then
|
||||||
@@ -91,6 +95,7 @@ function MinigameButtonMashWindow.update()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if mg.bar_fill >= mg.target_points then
|
if mg.bar_fill >= mg.target_points then
|
||||||
|
Audio.sfx_select()
|
||||||
mg.win_timer = Config.timing.minigame_win_duration
|
mg.win_timer = Config.timing.minigame_win_duration
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -95,7 +95,9 @@ function MinigameRhythmWindow.update()
|
|||||||
if mg.press_cooldown > 0 then
|
if mg.press_cooldown > 0 then
|
||||||
mg.press_cooldown = mg.press_cooldown - 1
|
mg.press_cooldown = mg.press_cooldown - 1
|
||||||
end
|
end
|
||||||
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.button_pressed_timer = mg.button_press_duration
|
||||||
mg.press_cooldown = mg.press_cooldown_duration
|
mg.press_cooldown = mg.press_cooldown_duration
|
||||||
local target_left = mg.target_center - (mg.target_width / 2)
|
local target_left = mg.target_center - (mg.target_width / 2)
|
||||||
@@ -114,6 +116,7 @@ function MinigameRhythmWindow.update()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if mg.score >= mg.max_score then
|
if mg.score >= mg.max_score then
|
||||||
|
Audio.sfx_select()
|
||||||
mg.win_timer = Config.timing.minigame_win_duration
|
mg.win_timer = Config.timing.minigame_win_duration
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ end
|
|||||||
--- @within PopupWindow
|
--- @within PopupWindow
|
||||||
function PopupWindow.update()
|
function PopupWindow.update()
|
||||||
if Context.popup.show then
|
if Context.popup.show then
|
||||||
if Input.menu_confirm() or Input.menu_back() then
|
if Input.select() or Input.back() then
|
||||||
PopupWindow.hide()
|
PopupWindow.hide()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ Window.register("game", GameWindow)
|
|||||||
PopupWindow = {}
|
PopupWindow = {}
|
||||||
Window.register("popup", PopupWindow)
|
Window.register("popup", PopupWindow)
|
||||||
|
|
||||||
ConfigurationWindow = {}
|
ControlsWindow = {}
|
||||||
Window.register("configuration", ConfigurationWindow)
|
Window.register("controls", ControlsWindow)
|
||||||
|
|
||||||
AudioTestWindow = {}
|
AudioTestWindow = {}
|
||||||
Window.register("audiotest", AudioTestWindow)
|
Window.register("audiotest", AudioTestWindow)
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ function build_markov_model(sequence, order)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function generate_sequence(model_data, length)
|
function generate_sequence(model_data, length)
|
||||||
local order = model.order
|
local order = model_data.order
|
||||||
local model_data = model_data.model
|
local model_data = model_data.model
|
||||||
|
|
||||||
-- random start key
|
-- random start key
|
||||||
|
|||||||
Reference in New Issue
Block a user