NO HEALTH BAR. Nothing else in this game does damage, so hit points would be a
survival-horror UI bolted onto a demolition game. Instead: one meter, DREAD, fed by
every way this place gets at you — being stared at, something close behind you, each
loop, and your own coughing. It decays when nothing is happening to you, and every loop
makes it grip harder (DREAD_LOOP_GRIP), so the place gets better at this the longer you
stay.
At 100% you die, and WHICH source pushed it over decides the death, which is what keeps
the three memes legible at the one moment it matters:
STARE "YOU LOOKED TOO LONG / it was still. it was always still. that was never the
safe part." (Slenderman)
REACH "IT WAS ALREADY IN THE ROOM / you were making so much noise."
Sprays. This is the gory one. (the xenomorph)
LOOP "YOU ARE STILL IN THE ROOM / you walked it eleven times. you will walk it
again." Eleven loops and the room simply keeps you. (Blair Witch)
Gore.gd is procedural — seeded blobs that swell on the lens and then bleed downward in
streaks, a wet burst at the camera (physical deaths only; being taken by the static
shouldn't spray), the camera going down to land on its side on the carpet, then the
card. The sequence is deliberately SLOW: a jumpscare is a spike, but a death should take
its time, because the seconds spent watching the lens settle are where it lands. R wakes
you up.
Player.set_frozen() so you can't stroll around during your own death.
Renamed Backrooms' VHS layer to `tape` — `dread` is the meter now, and it was clearer
anyway.
dev/probe_death.gd drives all three deaths and the revive.
Note: the "Parameter material is null" warning only appears under the headless dummy
renderer; windowed runs are clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
71 lines
1.9 KiB
GDScript
71 lines
1.9 KiB
GDScript
extends SceneTree
|
|
|
|
## All three deaths, and that you can get up again.
|
|
## Godot --headless --path game --script dev/probe_death.gd
|
|
|
|
func _initialize() -> void:
|
|
var main: Node = (load("res://main.tscn") as PackedScene).instantiate()
|
|
get_root().add_child(main)
|
|
await process_frame
|
|
main._load_level("backrooms")
|
|
for i in 8:
|
|
await physics_frame
|
|
var br = main.get("_backrooms")
|
|
var player = main.get("_player")
|
|
|
|
# --- 1. STARE: park it in view and don't look away ---
|
|
print("--- stare ---")
|
|
player.global_position = Vector3.ZERO
|
|
player.rotation.y = 0.0
|
|
var placed := false
|
|
for d in [3.0, 4.0, 5.0, 6.0, 8.0]:
|
|
br.entity.global_position = Vector3(0, 0, -d)
|
|
await physics_frame
|
|
await physics_frame
|
|
if br.entity.seen_now:
|
|
placed = true
|
|
break
|
|
print(" sightline: ", placed)
|
|
var ticks := 0
|
|
while not br.dying and ticks < 900:
|
|
br.entity.global_position = Vector3(0, 0, -4) # hold it there
|
|
await physics_frame
|
|
ticks += 1
|
|
print(" dying=%s cause=%s after %.1fs dread=%.2f" % [
|
|
br.dying, br.death_cause, ticks / 60.0, br.dread])
|
|
print(" player frozen: ", player._frozen)
|
|
# let the sequence run
|
|
for i in 300:
|
|
await physics_frame
|
|
print(" card shown: ", br._card_shown)
|
|
|
|
# --- get up ---
|
|
br.revive()
|
|
main._reset()
|
|
for i in 8:
|
|
await physics_frame
|
|
print(" after revive: dying=%s dread=%.2f frozen=%s" % [
|
|
br.dying, br.dread, player._frozen])
|
|
|
|
# --- 2. REACH: a touch while already terrified ---
|
|
print("--- reach ---")
|
|
br.dread = 0.80
|
|
br.entity._cd = 0.0
|
|
br.entity._catch()
|
|
await process_frame
|
|
print(" dying=%s cause=%s" % [br.dying, br.death_cause])
|
|
br.revive()
|
|
main._reset()
|
|
for i in 6:
|
|
await physics_frame
|
|
|
|
# --- 3. LOOP: walk the same room until it keeps you ---
|
|
print("--- loop ---")
|
|
br.loops = 10
|
|
br.dread = 0.0
|
|
player.global_position = Vector3(0, 0, 18.6)
|
|
for i in 8:
|
|
await physics_frame
|
|
print(" loops=%d dying=%s cause=%s" % [br.loops, br.dying, br.death_cause])
|
|
quit()
|