feat: added game over screen, fixed bar filling on ddr, applied tamagochi logic to game
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
This commit is contained in:
@@ -38,6 +38,7 @@ globals = {
|
||||
"MysteriousManScreen",
|
||||
"DiscussionWindow",
|
||||
"EndWindow",
|
||||
"GameOverWindow",
|
||||
"mset",
|
||||
"mget",
|
||||
"btnp",
|
||||
|
||||
@@ -66,6 +66,7 @@ screen/screen.work.lua
|
||||
screen/screen.mysterious_man.lua
|
||||
window/window.manager.lua
|
||||
window/window.register.lua
|
||||
window/window.gameover.lua
|
||||
window/window.end.lua
|
||||
window/window.intro.title.lua
|
||||
window/window.intro.ttg.lua
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
local function apply_home_toilet_meter_delta()
|
||||
local max = Meter.get_max()
|
||||
Meter.add("bm", -math.floor(max * 0.15))
|
||||
Meter.add("ism", -math.floor(max * 0.10))
|
||||
Meter.add("wpm", math.floor(max * 0.05))
|
||||
end
|
||||
|
||||
Decision.register({
|
||||
id = "go_to_toilet",
|
||||
label = "Go to Toilet",
|
||||
handle = function()
|
||||
if not Context.have_done_work_today and not Context.toilet_meters_today_morning then
|
||||
apply_home_toilet_meter_delta()
|
||||
Context.toilet_meters_today_morning = true
|
||||
elseif Context.have_been_to_office
|
||||
and Context.have_done_work_today
|
||||
and not Context.toilet_meters_today_evening then
|
||||
apply_home_toilet_meter_delta()
|
||||
Context.toilet_meters_today_evening = true
|
||||
end
|
||||
Util.go_to_screen_by_id("toilet")
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Discussion.register({
|
||||
id = "coworker_disc_0",
|
||||
on_end = Meter.apply_coworker_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Good morning Normal, enjoying your coffee as usual, huh?",
|
||||
@@ -18,6 +19,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_1",
|
||||
on_end = Meter.apply_coworker_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Norman, you look confused, what's up?",
|
||||
@@ -36,6 +38,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_asc_1",
|
||||
on_end = Meter.apply_coworker_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Normann you look weird and unfocused. You are usually locked in and not like this, what's up?",
|
||||
@@ -54,6 +57,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_2",
|
||||
on_end = Meter.apply_coworker_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Hey Norman, do you have new socks on? That's a weird color!",
|
||||
@@ -79,6 +83,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_asc_2",
|
||||
on_end = Meter.apply_coworker_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Normann, are you ok? You were doing weird things while typing?",
|
||||
@@ -97,6 +102,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "coworker_disc_3",
|
||||
on_end = Meter.apply_coworker_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "You look so happy, did you catch a bull or something?",
|
||||
@@ -120,6 +126,7 @@ Discussion.register({
|
||||
})
|
||||
Discussion.register({
|
||||
id = "coworker_disc_asc_3",
|
||||
on_end = Meter.apply_coworker_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Normal, you should take a break, you don't live up to your name today",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Discussion.register({
|
||||
id = "sumphore_disc_asc_1",
|
||||
on_end = Meter.apply_sumphore_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Are you still seeking the ox?",
|
||||
@@ -19,6 +20,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "sumphore_disc_asc_2",
|
||||
on_end = Meter.apply_sumphore_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "How's work? Your face looks strange",
|
||||
@@ -61,6 +63,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "sumphore_disc_asc_3",
|
||||
on_end = Meter.apply_sumphore_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Do you think it's work you're doing?",
|
||||
@@ -88,6 +91,7 @@ Discussion.register({
|
||||
|
||||
Discussion.register({
|
||||
id = "homeless_guy",
|
||||
on_end = Meter.apply_sumphore_discussion_reward,
|
||||
steps = {
|
||||
{
|
||||
question = "Sup bro, how are you?",
|
||||
|
||||
@@ -23,6 +23,10 @@ Context = {}
|
||||
--- * have_met_sumphore (boolean) Whether the player has talked to the homeless guy.<br/>
|
||||
--- * have_been_to_office (boolean) Whether the player has been to the office.<br/>
|
||||
--- * have_done_work_today (boolean) Whether the player has done work today.<br/>
|
||||
--- * toilet_meters_today_morning (boolean) Whether the home (before work) toilet meter delta was already applied this day.<br/>
|
||||
--- * toilet_meters_today_evening (boolean) Whether the home (after work) toilet meter delta was already applied this day.<br/>
|
||||
--- * coworker_discussion_meter_applied_today (boolean) Whether the daily coworker discussion meter roll was already applied this day.<br/>
|
||||
--- * sumphore_discussion_meter_applied_today (boolean) Whether the daily sumphore discussion meter roll was already applied this day.<br/>
|
||||
--- * game (table) Current game progress state. Contains: `current_screen` (string) active screen ID<br/>
|
||||
function Context.initial_data()
|
||||
return {
|
||||
@@ -45,6 +49,10 @@ function Context.initial_data()
|
||||
home_norman_visible = false,
|
||||
have_been_to_office = false,
|
||||
have_done_work_today = false,
|
||||
toilet_meters_today_morning = false,
|
||||
toilet_meters_today_evening = false,
|
||||
coworker_discussion_meter_applied_today = false,
|
||||
sumphore_discussion_meter_applied_today = false,
|
||||
should_ascend = false,
|
||||
have_met_sumphore = false,
|
||||
office_sprites = {},
|
||||
@@ -124,6 +132,7 @@ function Context.new_game()
|
||||
target_points = 100,
|
||||
instruction_text = "Wake up Norman!",
|
||||
show_progress_text = false,
|
||||
meter_on_complete = Meter.apply_wakeup_reward,
|
||||
on_win = function()
|
||||
Audio.music_play_room_work()
|
||||
Meter.show()
|
||||
|
||||
@@ -8,6 +8,10 @@ function Day.increase()
|
||||
if Context.day_count == 3 then
|
||||
Context.should_ascend = true
|
||||
end
|
||||
if Context.day_count >= 100 and not Ascension.is_complete() then
|
||||
GameOverWindow.show("days")
|
||||
return
|
||||
end
|
||||
for _, handler in ipairs(_day_increase_handlers) do
|
||||
handler()
|
||||
end
|
||||
@@ -27,6 +31,13 @@ Day.register_handler(function()
|
||||
m.bm = math.max(0, m.bm - METER_DECAY_PER_DAY)
|
||||
end)
|
||||
|
||||
Day.register_handler(function()
|
||||
Context.toilet_meters_today_morning = false
|
||||
Context.toilet_meters_today_evening = false
|
||||
Context.coworker_discussion_meter_applied_today = false
|
||||
Context.sumphore_discussion_meter_applied_today = false
|
||||
end)
|
||||
|
||||
Day.register_handler(function()
|
||||
if Context.should_ascend then
|
||||
Ascension.increase()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
--- @section Meter
|
||||
local METER_MAX = 1000
|
||||
local METER_DEFAULT = 500
|
||||
local BM_METER_DEFAULT = 200
|
||||
local ISM_METER_DEFAULT = 500
|
||||
local WPM_METER_DEFAULT = 200
|
||||
local METER_GAIN_PER_CHORE = 100
|
||||
local METER_DECAY_PER_DAY = 20
|
||||
local COMBO_BASE_BONUS = 0.02
|
||||
@@ -26,9 +28,9 @@ Meter.COLOR_CONTOUR = Config.colors.white
|
||||
--- * hidden (boolean) Whether meters are hidden.
|
||||
function Meter.get_initial()
|
||||
return {
|
||||
ism = METER_DEFAULT,
|
||||
wpm = METER_DEFAULT,
|
||||
bm = METER_DEFAULT,
|
||||
ism = ISM_METER_DEFAULT,
|
||||
wpm = WPM_METER_DEFAULT,
|
||||
bm = BM_METER_DEFAULT,
|
||||
combo = 0,
|
||||
combo_timer = 0,
|
||||
hidden = false,
|
||||
@@ -103,22 +105,129 @@ function Meter.add(key, amount)
|
||||
if not Context or not Context.meters then return end
|
||||
local m = Context.meters
|
||||
if m[key] ~= nil then
|
||||
m[key] = math.min(METER_MAX, m[key] + amount)
|
||||
if amount > 0 and (key == "ism" or key == "bm") and m[key] >= METER_MAX then
|
||||
GameOverWindow.show(key)
|
||||
return
|
||||
end
|
||||
m[key] = math.max(0, math.min(METER_MAX, m[key] + amount))
|
||||
end
|
||||
end
|
||||
|
||||
--- Called on minigame completion.
|
||||
--- @within Meter
|
||||
function Meter.on_minigame_complete()
|
||||
--- @param is_work boolean If true (work-style minigame), apply combo to WPM/ISM/BM and advance combo. DDR uses `Meter.apply_ddr_reward` instead. Otherwise flat equal gain, combo unchanged.
|
||||
function Meter.on_minigame_complete(is_work)
|
||||
local m = Context.meters
|
||||
local gain = math.floor(METER_GAIN_PER_CHORE * Meter.get_combo_multiplier())
|
||||
Meter.add("wpm", gain)
|
||||
Meter.add("ism", gain)
|
||||
Meter.add("bm", gain)
|
||||
if is_work then
|
||||
local mult = Meter.get_combo_multiplier()
|
||||
local wpm_delta = math.floor(METER_GAIN_PER_CHORE / mult)
|
||||
local ism_bm_delta = math.floor(METER_GAIN_PER_CHORE * mult)
|
||||
Meter.add("wpm", wpm_delta)
|
||||
Meter.add("ism", ism_bm_delta)
|
||||
Meter.add("bm", ism_bm_delta)
|
||||
m.combo = m.combo + 1
|
||||
m.combo_timer = 0
|
||||
else
|
||||
local flat = METER_GAIN_PER_CHORE
|
||||
Meter.add("wpm", flat)
|
||||
Meter.add("ism", flat)
|
||||
Meter.add("bm", flat)
|
||||
end
|
||||
end
|
||||
|
||||
--- Meter changes after DDR: uses max-meter percentages; combo advances like other work minigames.
|
||||
--- 0 mistakes: WPM −10%, ISM +5%, BM +5%. 1–3: WPM −5%, ISM +10%, BM +10%. More than 3: WPM unchanged, ISM +10%, BM +10%.
|
||||
--- @within Meter
|
||||
--- @param mistake_count number Total mistakes (missed arrows, wrong inputs, and special-mode rule violations).
|
||||
function Meter.apply_ddr_reward(mistake_count)
|
||||
if not Context or not Context.meters then return end
|
||||
local max = Meter.get_max()
|
||||
local m = Context.meters
|
||||
local wpm_pct, ism_pct, bm_pct
|
||||
if mistake_count == 0 then
|
||||
wpm_pct, ism_pct, bm_pct = -0.10, 0.05, 0.05
|
||||
elseif mistake_count <= 3 then
|
||||
wpm_pct, ism_pct, bm_pct = -0.05, 0.10, 0.10
|
||||
else
|
||||
wpm_pct, ism_pct, bm_pct = 0, 0.10, 0.10
|
||||
end
|
||||
if wpm_pct ~= 0 then
|
||||
Meter.add("wpm", math.floor(max * wpm_pct))
|
||||
end
|
||||
if ism_pct ~= 0 then
|
||||
Meter.add("ism", math.floor(max * ism_pct))
|
||||
end
|
||||
if bm_pct ~= 0 then
|
||||
Meter.add("bm", math.floor(max * bm_pct))
|
||||
end
|
||||
m.combo = m.combo + 1
|
||||
m.combo_timer = 0
|
||||
end
|
||||
|
||||
--- Meter changes for the wake-up button mash: faster completion is better for WPM.
|
||||
--- Perfect: under 2s — WPM +20%. Good: 2–3s — WPM +10%, ISM +5%, BM +5%. Bad: over 3s — WPM −5%, ISM +10%, BM +10%.
|
||||
--- @within Meter
|
||||
--- @param elapsed_sec number Seconds from minigame start until the bar was filled.
|
||||
function Meter.apply_wakeup_reward(elapsed_sec)
|
||||
if not Context or not Context.meters then return end
|
||||
local max = Meter.get_max()
|
||||
local wpm_pct, ism_pct, bm_pct
|
||||
if elapsed_sec < 2 then
|
||||
wpm_pct, ism_pct, bm_pct = 0.20, 0, 0
|
||||
elseif elapsed_sec <= 3 then
|
||||
wpm_pct, ism_pct, bm_pct = 0.10, 0.05, 0.05
|
||||
else
|
||||
wpm_pct, ism_pct, bm_pct = -0.05, 0.10, 0.10
|
||||
end
|
||||
if wpm_pct ~= 0 then
|
||||
Meter.add("wpm", math.floor(max * wpm_pct))
|
||||
end
|
||||
if ism_pct ~= 0 then
|
||||
Meter.add("ism", math.floor(max * ism_pct))
|
||||
end
|
||||
if bm_pct ~= 0 then
|
||||
Meter.add("bm", math.floor(max * bm_pct))
|
||||
end
|
||||
end
|
||||
|
||||
--- Random single meter shift after finishing a coworker discussion: ISM +10%, WPM −10%, or BM +10%.
|
||||
--- @within Meter
|
||||
function Meter.apply_coworker_discussion_reward()
|
||||
if not Context or not Context.meters then return end
|
||||
if Context.coworker_discussion_meter_applied_today then return end
|
||||
local max = Meter.get_max()
|
||||
local delta = math.floor(max * 0.10)
|
||||
local roll = math.random(1, 3)
|
||||
if roll == 1 then
|
||||
Meter.add("ism", delta)
|
||||
elseif roll == 2 then
|
||||
Meter.add("wpm", -delta)
|
||||
else
|
||||
Meter.add("bm", delta)
|
||||
end
|
||||
Context.coworker_discussion_meter_applied_today = true
|
||||
end
|
||||
|
||||
--- After finishing a sumphore discussion: reduce whichever of ISM / WPM / BM is highest by 10% of max (stable tie to ISM, then WPM, then BM).
|
||||
--- @within Meter
|
||||
function Meter.apply_sumphore_discussion_reward()
|
||||
if not Context or not Context.meters then return end
|
||||
if Context.sumphore_discussion_meter_applied_today then return end
|
||||
local m = Context.meters
|
||||
local max = Meter.get_max()
|
||||
local delta = math.floor(max * 0.10)
|
||||
local biggest_val_key = "ism"
|
||||
local biggest_val = m.ism
|
||||
for _, key in ipairs({ "wpm", "bm" }) do
|
||||
if m[key] > biggest_val then
|
||||
biggest_val = m[key]
|
||||
biggest_val_key = key
|
||||
end
|
||||
end
|
||||
Meter.add(biggest_val_key, -delta)
|
||||
Context.sumphore_discussion_meter_applied_today = true
|
||||
end
|
||||
|
||||
--- Draws meters.
|
||||
--- @within Meter
|
||||
function Meter.draw()
|
||||
|
||||
@@ -132,6 +132,7 @@ function MysteriousManScreen.wake_up()
|
||||
target_points = 100,
|
||||
instruction_text = "Wake up Norman!",
|
||||
show_progress_text = false,
|
||||
meter_on_complete = Meter.apply_wakeup_reward,
|
||||
on_win = function()
|
||||
Audio.music_play_wakingup()
|
||||
Meter.show()
|
||||
|
||||
@@ -51,8 +51,8 @@ Screen.register({
|
||||
local decay_pct = Meter.get_decay_percentage()
|
||||
local decay_text = string.format("-%d%%", decay_pct)
|
||||
local combo_mult = Meter.get_combo_multiplier()
|
||||
local combo_pct = math.floor((combo_mult - 1) * 100)
|
||||
local mult_text = string.format("+%d%%", combo_pct)
|
||||
local ism_bm_combo_pct = math.floor((combo_mult - 1) * 100)
|
||||
local wpm_combo_pct = math.floor((1 / combo_mult - 1) * 100 + 0.5)
|
||||
local meter_start_y = text_y + 10
|
||||
|
||||
local meter_list = {
|
||||
@@ -73,6 +73,12 @@ Screen.register({
|
||||
rect(bar_x, bar_y, fill_w, bar_h, meter.color)
|
||||
end
|
||||
|
||||
local mult_text
|
||||
if meter.key == "wpm" then
|
||||
mult_text = string.format("%+d%%", wpm_combo_pct)
|
||||
else
|
||||
mult_text = string.format("+%d%%", ism_bm_combo_pct)
|
||||
end
|
||||
local decay_w = print(decay_text, 0, -6, 0, false, 1)
|
||||
Print.text_contour(decay_text, bar_x - decay_w - 4, bar_y, Config.colors.light_blue, false, 1, Config.colors.white)
|
||||
Print.text_contour(mult_text, bar_x + bar_w + 4, bar_y, Config.colors.light_blue, false, 1, Config.colors.white)
|
||||
|
||||
59
inc/window/window.gameover.lua
Normal file
59
inc/window/window.gameover.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
--- @section GameOverWindow
|
||||
local GAME_OVER_ART = [[
|
||||
_###_ __#__ #___# #####
|
||||
#____ _#_#_ ##_## #____
|
||||
#_### ##### #_#_# ####_
|
||||
#___# #___# #___# #____
|
||||
_###_ #___# #___# #####
|
||||
|
||||
_###_ #___# ##### ####_
|
||||
#___# #___# #____ #___#
|
||||
#___# _#_#_ ####_ ####_
|
||||
#___# __#__ #____ #_#__
|
||||
_###_ __#__ ##### #__##
|
||||
]]
|
||||
|
||||
local REASON_MESSAGES = {
|
||||
ism = "Your impostor syndrome consumed you.",
|
||||
bm = "You burned out like a cheap candle.",
|
||||
days = "100 days passed. The cycle never broke.",
|
||||
}
|
||||
|
||||
--- Shows the game over screen.
|
||||
--- @within GameOverWindow
|
||||
--- @param reason string One of "ism", "bm", "days".
|
||||
function GameOverWindow.show(reason)
|
||||
GameOverWindow.reason = reason
|
||||
Context.game_in_progress = false
|
||||
Glitch.show()
|
||||
Window.set_current("game_over")
|
||||
end
|
||||
|
||||
--- Draws the game over screen.
|
||||
--- @within GameOverWindow
|
||||
function GameOverWindow.draw()
|
||||
cls(Config.colors.black)
|
||||
|
||||
local cx = Config.screen.width / 2
|
||||
local bounds = AsciiArt.draw(GAME_OVER_ART, {
|
||||
char_w = 4,
|
||||
char_h = 6,
|
||||
line_gap = 1,
|
||||
word_gap = 10,
|
||||
color = Config.colors.red,
|
||||
})
|
||||
|
||||
local msg = REASON_MESSAGES[GameOverWindow.reason] or ""
|
||||
Print.text_center(msg, cx, bounds.bottom + 8, Config.colors.white)
|
||||
Print.text_center("Press Z to restart", cx, Config.screen.height - 10, Config.colors.light_grey)
|
||||
end
|
||||
|
||||
--- Updates the game over screen logic.
|
||||
--- @within GameOverWindow
|
||||
function GameOverWindow.update()
|
||||
if Input.select() then
|
||||
Context.reset()
|
||||
MenuWindow.refresh_menu_items()
|
||||
Window.set_current("menu")
|
||||
end
|
||||
end
|
||||
@@ -130,6 +130,7 @@ function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context)
|
||||
Audio.sfx_arrowhit(arrow.note)
|
||||
game_context.special_mode_counter = game_context.special_mode_counter + 1
|
||||
else
|
||||
game_context.total_misses = game_context.total_misses + 1
|
||||
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||
game_context.special_mode_condition = false
|
||||
end
|
||||
@@ -141,10 +142,12 @@ function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context)
|
||||
game_context.bar_fill = game_context.bar_fill - game_context.fill_per_hit
|
||||
end
|
||||
else
|
||||
game_context.total_misses = game_context.total_misses + 1
|
||||
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||
game_context.special_mode_condition = false
|
||||
end
|
||||
elseif special_mode == "only_nothing" then
|
||||
game_context.total_misses = game_context.total_misses + 1
|
||||
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||
game_context.special_mode_condition = false
|
||||
end
|
||||
@@ -173,6 +176,9 @@ function MinigameDDRWindow.on_end(game_context)
|
||||
end
|
||||
|
||||
game_context.special_mode_condition = game_context.special_mode_condition and was_ok
|
||||
if game_context.special_mode_condition and sm ~= "normal" then
|
||||
game_context.bar_fill = game_context.max_fill
|
||||
end
|
||||
end
|
||||
|
||||
--- Initializes DDR minigame state.
|
||||
@@ -336,7 +342,8 @@ function MinigameDDRWindow.update()
|
||||
mg.win_timer = mg.win_timer - 1
|
||||
if mg.win_timer == 0 then
|
||||
Audio.music_stop()
|
||||
Meter.on_minigame_complete()
|
||||
Meter.apply_ddr_reward(mg.total_misses)
|
||||
if not Context.game_in_progress then return end
|
||||
if mg.on_win then
|
||||
mg.on_win(mg)
|
||||
else
|
||||
|
||||
@@ -1,6 +1,35 @@
|
||||
--- @section MinigameButtonMashWindow
|
||||
|
||||
---@class MinigameButtonMashState
|
||||
---@field bar_fill number
|
||||
---@field target_points number
|
||||
---@field fill_per_press number
|
||||
---@field base_degradation number
|
||||
---@field degradation_multiplier number
|
||||
---@field button_pressed_timer number
|
||||
---@field button_press_duration number
|
||||
---@field instruction_text string
|
||||
---@field show_progress_text boolean
|
||||
---@field return_window string?
|
||||
---@field bar_x number
|
||||
---@field bar_y number
|
||||
---@field bar_width number
|
||||
---@field bar_height number
|
||||
---@field button_x number
|
||||
---@field button_y number
|
||||
---@field button_size number
|
||||
---@field focus_center_x number?
|
||||
---@field focus_center_y number?
|
||||
---@field focus_initial_radius number
|
||||
---@field win_timer number
|
||||
---@field on_win (fun())?
|
||||
---@field meter_on_complete (fun(elapsed_sec: number))?
|
||||
---@field start_ms number?
|
||||
---@field elapsed_sec number?
|
||||
|
||||
--- Gets initial button mash minigame configuration.
|
||||
--- @within MinigameButtonMashWindow
|
||||
--- @return result table The default button mash minigame configuration.
|
||||
---@return MinigameButtonMashState
|
||||
function MinigameButtonMashWindow.init_context()
|
||||
return {
|
||||
bar_fill = 0,
|
||||
@@ -24,7 +53,11 @@ function MinigameButtonMashWindow.init_context()
|
||||
focus_center_y = nil,
|
||||
focus_initial_radius = 0,
|
||||
win_timer = 0,
|
||||
on_win = nil
|
||||
on_win = nil,
|
||||
--- If set, called with elapsed_sec instead of Meter.on_minigame_complete()
|
||||
meter_on_complete = nil,
|
||||
start_ms = nil,
|
||||
elapsed_sec = nil,
|
||||
}
|
||||
end
|
||||
|
||||
@@ -51,8 +84,10 @@ end
|
||||
function MinigameButtonMashWindow.start(return_window, params)
|
||||
Audio.music_stop()
|
||||
MinigameButtonMashWindow.init(params)
|
||||
---@type MinigameButtonMashState
|
||||
local mg = Context.minigame_button_mash
|
||||
mg.return_window = return_window or "game"
|
||||
mg.start_ms = time()
|
||||
if mg.focus_center_x then
|
||||
Focus.start_driven(mg.focus_center_x, mg.focus_center_y, {
|
||||
initial_radius = mg.focus_initial_radius
|
||||
@@ -64,12 +99,18 @@ end
|
||||
--- Updates button mash minigame logic.
|
||||
--- @within MinigameButtonMashWindow
|
||||
function MinigameButtonMashWindow.update()
|
||||
---@type MinigameButtonMashState
|
||||
local mg = Context.minigame_button_mash
|
||||
|
||||
if mg.win_timer > 0 then
|
||||
mg.win_timer = mg.win_timer - 1
|
||||
if mg.win_timer == 0 then
|
||||
Meter.on_minigame_complete()
|
||||
if mg.meter_on_complete then
|
||||
mg.meter_on_complete(mg.elapsed_sec or 0)
|
||||
else
|
||||
Meter.on_minigame_complete(false)
|
||||
end
|
||||
if not Context.game_in_progress then return end
|
||||
if mg.focus_center_x then Focus.stop() end
|
||||
Context.home_norman_visible = true
|
||||
Context.have_done_work_today = false
|
||||
@@ -97,6 +138,7 @@ function MinigameButtonMashWindow.update()
|
||||
end
|
||||
if mg.bar_fill >= mg.target_points then
|
||||
Audio.sfx_select()
|
||||
mg.elapsed_sec = (time() - mg.start_ms) / 1000
|
||||
mg.win_timer = Config.timing.minigame_win_duration
|
||||
return
|
||||
end
|
||||
@@ -116,6 +158,7 @@ end
|
||||
--- Draws button mash minigame.
|
||||
--- @within MinigameButtonMashWindow
|
||||
function MinigameButtonMashWindow.draw()
|
||||
---@type MinigameButtonMashState
|
||||
local mg = Context.minigame_button_mash
|
||||
if mg.return_window == "game" then
|
||||
GameWindow.draw_with_underlay(function()
|
||||
|
||||
@@ -73,7 +73,8 @@ function MinigameRhythmWindow.update()
|
||||
if mg.win_timer > 0 then
|
||||
mg.win_timer = mg.win_timer - 1
|
||||
if mg.win_timer == 0 then
|
||||
Meter.on_minigame_complete()
|
||||
Meter.on_minigame_complete(false)
|
||||
if not Context.game_in_progress then return end
|
||||
if mg.focus_center_x then Focus.stop() end
|
||||
if mg.on_win then
|
||||
mg.on_win()
|
||||
|
||||
@@ -31,6 +31,9 @@ Window.register("minigame_rhythm", MinigameRhythmWindow)
|
||||
MinigameDDRWindow = {}
|
||||
Window.register("minigame_ddr", MinigameDDRWindow)
|
||||
|
||||
GameOverWindow = {}
|
||||
Window.register("game_over", GameOverWindow)
|
||||
|
||||
EndWindow = {}
|
||||
Window.register("end", EndWindow)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user