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:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user