Compare commits

...

3 Commits

Author SHA1 Message Date
3bb1fb7941 glitch
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
ci/woodpecker/pull_request_closed/woodpecker Pipeline failed
2026-03-12 00:58:38 +01:00
24ce240f97 Merge pull request 'feature/end-window' (#31) from feature/end-window into master
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Reviewed-on: #31
2026-03-11 23:45:51 +00:00
5d78cffc99 end window
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
ci/woodpecker/pull_request_closed/woodpecker Pipeline failed
2026-03-12 00:44:26 +01:00
11 changed files with 161 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ logic/logic.day.lua
logic/logic.timer.lua logic/logic.timer.lua
logic/logic.trigger.lua logic/logic.trigger.lua
logic/logic.minigame.lua logic/logic.minigame.lua
logic/logic.glitch.lua
system/system.ui.lua system/system.ui.lua
audio/audio.manager.lua audio/audio.manager.lua
audio/audio.songs.lua audio/audio.songs.lua
@@ -24,6 +25,7 @@ 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
decision/decision.go_to_office.lua decision/decision.go_to_office.lua
decision/decision.go_to_end.lua
decision/decision.go_to_walking_to_home.lua decision/decision.go_to_walking_to_home.lua
decision/decision.go_to_sleep.lua decision/decision.go_to_sleep.lua
decision/decision.do_work.lua decision/decision.do_work.lua
@@ -40,6 +42,7 @@ screen/screen.walking_to_home.lua
screen/screen.work.lua screen/screen.work.lua
window/window.manager.lua window/window.manager.lua
window/window.register.lua window/window.register.lua
window/window.end.lua
window/window.splash.lua window/window.splash.lua
window/window.intro.lua window/window.intro.lua
window/window.menu.lua window/window.menu.lua

View File

@@ -0,0 +1,7 @@
Decision.register({
id = "go_to_end",
label = "Break the cycle",
handle = function()
Window.set_current("end")
end,
})

View File

@@ -2,6 +2,7 @@ Decision.register({
id = "go_to_office", id = "go_to_office",
label = "Go to Office", label = "Go to Office",
handle = function() handle = function()
Glitch.show()
Util.go_to_screen_by_id("office") Util.go_to_screen_by_id("office")
end, end,
}) })

View File

@@ -10,11 +10,11 @@ local _decisions = {}
--- @param[opt] decision.handle function Called when the decision is selected. Defaults to noop. --- @param[opt] decision.handle function Called when the decision is selected. Defaults to noop.
function Decision.register(decision) function Decision.register(decision)
if not decision or not decision.id then if not decision or not decision.id then
PopupWindow.show({"Error: Invalid decision object registered (missing id)!"}) trace("Error: Invalid decision object registered (missing id)!")
return return
end end
if not decision.label then if not decision.label then
PopupWindow.show({"Error: Invalid decision object registered (missing label)!"}) trace("Error: Invalid decision object registered (missing label)!")
return return
end end
@@ -92,7 +92,7 @@ end
function Decision.filter_available(decisions_list) function Decision.filter_available(decisions_list)
local available = {} local available = {}
for _, decision in ipairs(decisions_list) do for _, decision in ipairs(decisions_list) do
if decision and decision.condition() then if decision and (not decision.condition or decision.condition()) then
table.insert(available, decision) table.insert(available, decision)
end end
end end

View File

@@ -42,6 +42,15 @@ function Context.initial_data()
current_situation = nil, current_situation = nil,
}, },
day_count = 1, day_count = 1,
glitch = {
enabled = false,
state = "active",
timer = 0,
},
_end = {
state = "choice",
selection = 1,
},
} }
end end

View File

@@ -14,4 +14,4 @@ Audio = {}
Focus = {} Focus = {}
Day = {} Day = {}
Timer = {} Timer = {}
Trigger = {} Trigger = {}

View File

@@ -0,0 +1,57 @@
Glitch = {}
--- Shows the glitch effect.
--- @within Glitch
function Glitch.show()
if Context and Context.glitch then
Context.glitch.enabled = true
end
end
--- Hides the glitch effect.
--- @within Glitch
function Glitch.hide()
if Context and Context.glitch then
Context.glitch.enabled = false
end
end
--- Draws the glitch effect if active.
--- @within Glitch
function Glitch.draw()
if not Context or not Context.glitch or not Context.glitch.enabled then return end
-- Update state timer
Context.glitch.timer = Context.glitch.timer - 1
if Context.glitch.timer <= 0 then
if Context.glitch.state == "active" then
Context.glitch.state = "waiting"
Context.glitch.timer = math.random(20, 60) -- Time to stay fixed
else
Context.glitch.state = "active"
Context.glitch.timer = math.random(40, 100) -- Time to stay glitchy
end
end
-- Draw stripes only when active
if Context.glitch.state == "active" then
for i = 1, 15 do
local rx = math.random(0, Config.screen.width - 1)
local ry = math.random(0, Config.screen.height - 1)
-- Sample color at the random point
local color = pix(rx, ry)
-- Determine random length for the stripe (2-40)
local length = math.random(2, 40)
-- Draw the vertical stripe
for sy = 0, length - 1 do
local dy = ry + sy
if dy < Config.screen.height then
pix(rx, dy, color)
end
end
end
end
end

View File

@@ -5,6 +5,7 @@ Screen.register({
"go_to_toilet", "go_to_toilet",
"go_to_walking_to_office", "go_to_walking_to_office",
"go_to_sleep", "go_to_sleep",
"go_to_end",
}, },
background = "bedroom" background = "bedroom"
}) })

View File

@@ -27,5 +27,6 @@ function TIC()
if Context.game_in_progress then if Context.game_in_progress then
Meter.draw() Meter.draw()
Timer.draw() Timer.draw()
Glitch.draw()
end end
end end

75
inc/window/window.end.lua Normal file
View File

@@ -0,0 +1,75 @@
--- Draws the end screen window.
--- @within EndWindow
function EndWindow.draw()
cls(Config.colors.black)
if Context._end.state == "choice" then
local lines = {
"This is not a workplace.",
"This is a cycle.",
"And if it is a cycle...",
"it can be broken."
}
local y = 40
for _, line in ipairs(lines) do
Print.text_center(line, Config.screen.width / 2, y, Config.colors.white)
y = y + 10
end
y = y + 20
local yes_color = Context._end.selection == 1 and Config.colors.light_blue or Config.colors.white
local no_color = Context._end.selection == 2 and Config.colors.light_blue or Config.colors.white
local yes_text = (Context._end.selection == 1 and "> YES" or " YES")
local no_text = (Context._end.selection == 2 and "> NO" or " NO")
local centerX = Config.screen.width / 2
Print.text(yes_text, centerX - 40, y, yes_color)
Print.text(no_text, centerX + 10, y, no_color)
elseif Context._end.state == "ending" then
Print.text_center("Game over -- good ending.", Config.screen.width / 2, 50, Config.colors.light_blue)
Print.text_center("Congratulations!", Config.screen.width / 2, 70, Config.colors.white)
Print.text_center("Press Z to return to menu", Config.screen.width / 2, 110, Config.colors.light_grey)
end
end
--- Updates the end screen logic.
--- @within EndWindow
function EndWindow.update()
if Context._end.state == "choice" then
if Input.left() or Input.up() then
if Context._end.selection == 2 then
Audio.sfx_beep()
Context._end.selection = 1
end
elseif Input.right() or Input.down() then
if Context._end.selection == 1 then
Audio.sfx_beep()
Context._end.selection = 2
end
end
if Input.menu_confirm() then
Audio.sfx_select()
if Context._end.selection == 1 then
Context._end.state = "ending"
else
-- NO: increment day and go home
Day.increase()
Context.game.current_screen = "home"
Window.set_current("game")
-- Initialize home screen
local home_screen = Screen.get_by_id("home")
if home_screen and home_screen.init then
home_screen.init()
end
end
end
elseif Context._end.state == "ending" then
if Input.menu_confirm() then
Window.set_current("menu")
MenuWindow.refresh_menu_items()
end
end
end

View File

@@ -30,3 +30,6 @@ Window.register("minigame_ddr", MinigameDDRWindow)
MysteriousManWindow = {} MysteriousManWindow = {}
Window.register("mysterious_man", MysteriousManWindow) Window.register("mysterious_man", MysteriousManWindow)
EndWindow = {}
Window.register("end", EndWindow)