extends Node class_name CubicleHell ## CUBICLE HELL — the mode the game is actually about. ## ## You work a shift. The work is designed to provoke you. The meter fills. You snap, and ## for half a minute you are physically unable to go back to your desk until you've ## broken enough things. Then you sit back down and try to earn the rest of your day. ## ## THE SCORE IS YOUR PAYSLIP: ## ## NET = WAGES (tasks completed) − DAMAGES (everything you broke) ## ## Rage drains a flat amount per object destroyed, but each object bills at its own ## value — so the play during a meltdown is to smash a lot of cheap rubbish quickly ## rather than put a sledgehammer through a filing cabinet. You don't get to choose ## whether you lose your temper. You choose how much it costs. ## ## FURY is a separate, non-monetary stat: things broken while actually melting down. ## It exists because "I ended the shift owing them money" should still be a brag. ## ## Godot 4.7 GDScript 2.0. @export var shift_time: float = 300.0 ## a five-minute shift var rage: Rage var tasks: Tasks var time_left: float = 0.0 var running: bool = false var damages: int = 0 ## $ of property destroyed var fury: int = 0 ## objects broken during a meltdown var meltdowns: int = 0 var result: String = "" signal shift_ended() func setup(r: Rage, t: Tasks) -> void: rage = r tasks = t if rage != null: rage.snapped.connect(_on_snapped) func begin() -> void: running = true time_left = shift_time damages = 0 fury = 0 meltdowns = 0 result = "" func _on_snapped() -> void: meltdowns += 1 # you cannot keep filling in the spreadsheet while you're kicking the printer if tasks != null: tasks.eject() ## Main calls this for every object destroyed, with what it was worth. func on_smashed(value: int) -> void: if not running: return damages += value if rage != null and rage.is_meltdown(): fury += 1 func wages() -> int: return tasks.wages if tasks != null else 0 func net() -> int: return wages() - damages func _process(dt: float) -> void: if not running: return time_left -= dt if time_left <= 0.0: time_left = 0.0 _end() func _end() -> void: running = false var n := net() if n >= 600: result = "EMPLOYEE OF THE MONTH" elif n >= 0: result = "SATISFACTORY" elif n >= -900: result = "A LETTER WILL BE PLACED ON YOUR FILE" else: result = "SECURITY WILL ESCORT YOU OUT" shift_ended.emit() ## The line the HUD shows while the shift runs. func hud_line() -> String: if not running: return "SHIFT OVER — %s · net $%d (M cycles mode · R new shift)" % [result, net()] var m := int(time_left) / 60 var s := int(time_left) % 60 return "CUBICLE HELL %d:%02d · pay $%d damages $%d · %d meltdown%s" % [ m, s, wages(), damages, meltdowns, "" if meltdowns == 1 else "s"] ## End-of-shift payslip, as lines. func payslip() -> PackedStringArray: var out := PackedStringArray() out.append("MONSTER ROBOT PARTY · PAYSLIP") out.append("") out.append("%-26s %8d" % ["Tasks completed", tasks.tasks_done if tasks else 0]) out.append("%-26s %8d" % ["Tasks fumbled", tasks.tasks_fumbled if tasks else 0]) out.append("%-26s %8s" % ["Gross wages", "$%d" % wages()]) out.append("") out.append("%-26s %8d" % ["Meltdowns", meltdowns]) out.append("%-26s %8d" % ["Objects destroyed in rage", fury]) out.append("%-26s %8s" % ["Deductions (damages)", "-$%d" % damages]) out.append("--------------------------------------") out.append("%-26s %8s" % ["NET", "$%d" % net()]) out.append("") out.append(result) return out