This commit is contained in:
Henry Faber 2026-05-18 00:01:15 +01:00
commit 0404906ee1
19 changed files with 238 additions and 156 deletions

View file

@ -18,6 +18,7 @@ config/icon="res://icon.svg"
[autoload]
EventBus="*uid://hxpxcxvxcisu"
Strings="*res://scripts/strings.gd"
[input]

View file

@ -45,7 +45,9 @@ func _ready():
_screen.pulse_started.connect(_on_pulse_started)
_screen.pulse_blocked.connect(_on_pulse_blocked)
_screen.pulse_blocked_perfect.connect(_on_pulse_blocked_perfect)
_screen.doors_closing.connect(func(): _on_doors_closing(true))
_screen.doors_closing.connect(func():
$SfxHacked.play()
_on_doors_closing(true))
EventBus.game_started.connect(_on_game_started)
EventBus.game_lost.connect(func(_reason): $SfxRobotIUnderstand.play())
@ -167,6 +169,7 @@ func _enter_static_then_hacked(token: int) -> void:
return
state = ScreenState.HACKED
_dbg("HACKED")
$SfxHacked.play()
_screen.enter_hacked()
EventBus.active_button_changed.emit("open"),
CONNECT_ONE_SHOT
@ -217,6 +220,10 @@ func _on_pulse_blocked():
survivors_remaining -= 1
people_in_elevator += 1
EventBus.people_changed.emit(people_in_elevator, THRESHOLD)
score += POINTS_PER_PERSON
if people_in_elevator > THRESHOLD:
score += POINTS_PER_PERSON
EventBus.score_changed.emit(score)
if $SfxBlock.stream:
$SfxBlock.play()
@ -249,16 +256,11 @@ func _on_doors_closing(fast: bool = false):
EventBus.doors_closed.emit(fast)
if people_in_elevator < THRESHOLD:
_screen.show_loss("TOO FEW")
EventBus.game_lost.emit("TOO FEW")
_screen.show_loss("")
EventBus.game_lost.emit(Strings.LOSS_TOO_FEW)
return
var base_points = people_in_elevator * POINTS_PER_PERSON
var bonus = max(0, people_in_elevator - THRESHOLD) * POINTS_PER_PERSON
score += base_points + bonus
saved_count += people_in_elevator
EventBus.score_changed.emit(score)
EventBus.saved_changed.emit(saved_count)
current_floor -= 1

View file

@ -3,56 +3,89 @@ extends CanvasLayer
var _score := 0
var _saved := 0
var _lost := false
var _ready_for_input := false
func _ready():
visible = false
EventBus.game_won.connect(_on_game_won)
EventBus.game_lost.connect(_on_game_lost)
EventBus.score_changed.connect(func(s): _score = s)
EventBus.saved_changed.connect(func(s): _saved = s)
$Center/Card/Margin/Column/RestartButton.pressed.connect(_on_restart_pressed)
$Center/Card/Margin/Column/SpaceHint.text = Strings.END_SPACE_HINT
$Dim.modulate.a = 0.0
$BlackFade.modulate.a = 0.0
$Center.modulate.a = 0.0
$Center/Card/Margin/Column/Headline.modulate.a = 0.0
$Center/Card/Margin/Column/ScoreLabel.modulate.a = 0.0
$Center/Card/Margin/Column/SavedLabel.modulate.a = 0.0
$Center/Card/Margin/Column/SpaceHint.modulate.a = 0.0
visible = true
func _unhandled_input(event):
if visible and _lost and event is InputEventKey and event.pressed and not event.echo and event.keycode == KEY_SPACE:
if _ready_for_input and event is InputEventKey and event.pressed and not event.echo and event.keycode == KEY_SPACE:
get_viewport().set_input_as_handled()
_on_restart_pressed()
func _on_game_won():
$Center/Card/Margin/Column/Headline.text = "YOU ESCAPED"
$Center/Card/Margin/Column/Headline.text = Strings.END_WIN_HEADLINE
_lost = false
$Center/Card/Margin/Column/SpaceHint.visible = false
_show()
_run_intro_sequence()
func _on_game_lost(reason: String):
$Center/Card/Margin/Column/Headline.text = reason
_lost = true
$Center/Card/Margin/Column/SpaceHint.visible = true
_apply_loss_palette()
_show()
_run_intro_sequence()
func _apply_loss_palette():
var border := Color(1, 0.3, 0.3, 1)
var subtle := Color(0.95, 0.7, 0.7, 1)
var headline := Color(0.949, 0.227, 0.541, 1)
var body := Color(0.851, 0.541, 0.659, 1)
var hint := Color(0.941, 0.761, 0.831, 1)
$Dim.color = Color(0.18, 0.05, 0.05, 1)
$Dim.color = Color(0.078, 0.031, 0.18, 1)
var button = $Center/Card/Margin/Column/RestartButton
var button_style := (button.get_theme_stylebox("normal") as StyleBoxFlat).duplicate() as StyleBoxFlat
if button_style:
button_style.border_color = border
button_style.bg_color = Color(0.3, 0.1, 0.1, 1)
for state in ["normal", "hover", "pressed", "focus"]:
button.add_theme_stylebox_override(state, button_style)
button.add_theme_color_override("font_color", border)
$Center/Card/Margin/Column/Headline.add_theme_color_override("font_color", headline)
$Center/Card/Margin/Column/ScoreLabel.add_theme_color_override("font_color", body)
$Center/Card/Margin/Column/SavedLabel.add_theme_color_override("font_color", body)
$Center/Card/Margin/Column/SpaceHint.add_theme_color_override("font_color", hint)
$Center/Card/Margin/Column/Headline.add_theme_color_override("font_color", border)
$Center/Card/Margin/Column/ScoreLabel.add_theme_color_override("font_color", subtle)
$Center/Card/Margin/Column/SavedLabel.add_theme_color_override("font_color", subtle)
func _run_intro_sequence() -> void:
$Center/Card/Margin/Column/ScoreLabel.text = Strings.END_SCORE_FMT % _score
$Center/Card/Margin/Column/SavedLabel.text = Strings.END_SAVED_FMT % _saved
func _show():
$Center/Card/Margin/Column/ScoreLabel.text = "Score: %d" % _score
$Center/Card/Margin/Column/SavedLabel.text = "Survivors saved: %d" % _saved
visible = true
await get_tree().create_timer(0.8, false).timeout
var fade_tween := create_tween()
fade_tween.tween_property($BlackFade, "modulate:a", 1.0, 1.2)
await fade_tween.finished
$Dim.modulate.a = 1.0
$Center.modulate.a = 1.0
var headline_tween := create_tween()
headline_tween.tween_property($Center/Card/Margin/Column/Headline, "modulate:a", 1.0, 0.4)
await headline_tween.finished
await get_tree().create_timer(0.2, false).timeout
var labels_tween := create_tween()
labels_tween.tween_property($Center/Card/Margin/Column/ScoreLabel, "modulate:a", 1.0, 0.4)
labels_tween.parallel().tween_property($Center/Card/Margin/Column/SavedLabel, "modulate:a", 1.0, 0.4)
await labels_tween.finished
await get_tree().create_timer(0.2, false).timeout
var hint_tween := create_tween()
hint_tween.tween_property($Center/Card/Margin/Column/SpaceHint, "modulate:a", 1.0, 0.4)
await hint_tween.finished
_ready_for_input = true
var flash_tween := create_tween().set_loops()
flash_tween.tween_property($Center/Card/Margin/Column/SpaceHint, "modulate:a", 0.2, 0.6).set_trans(Tween.TRANS_SINE)
flash_tween.tween_property($Center/Card/Margin/Column/SpaceHint, "modulate:a", 1.0, 0.6).set_trans(Tween.TRANS_SINE)
func _on_restart_pressed():
get_tree().reload_current_scene()

View file

@ -1,24 +1,9 @@
[gd_scene load_steps=3 format=3]
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://scenes/end_screen.gd" id="1"]
[sub_resource type="StyleBoxFlat" id="ButtonStyle"]
bg_color = Color(0.1, 0.3, 0.1, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.2, 1, 0.2, 1)
corner_radius_top_left = 4
corner_radius_top_right = 4
corner_radius_bottom_right = 4
corner_radius_bottom_left = 4
content_margin_left = 24
content_margin_right = 24
content_margin_top = 12
content_margin_bottom = 12
[node name="EndScreen" type="CanvasLayer"]
process_mode = 3
layer = 10
script = ExtResource("1")
@ -27,7 +12,15 @@ anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
color = Color(0.05, 0.18, 0.05, 1)
color = Color(0.102, 0.251, 0.278, 1)
[node name="BlackFade" type="ColorRect" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
modulate = Color(1, 1, 1, 0)
color = Color(0, 0, 0, 1)
[node name="Center" type="CenterContainer" parent="."]
anchors_preset = 15
@ -49,34 +42,23 @@ theme_override_constants/separation = 24
[node name="Headline" type="Label" parent="Center/Card/Margin/Column"]
text = "YOU ESCAPED"
horizontal_alignment = 1
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
theme_override_colors/font_color = Color(0.553, 0.91, 1, 1)
theme_override_font_sizes/font_size = 56
[node name="ScoreLabel" type="Label" parent="Center/Card/Margin/Column"]
text = "Score: 0"
horizontal_alignment = 1
theme_override_colors/font_color = Color(0.7, 0.95, 0.7, 1)
theme_override_colors/font_color = Color(0.659, 1, 0.8, 1)
theme_override_font_sizes/font_size = 28
[node name="SavedLabel" type="Label" parent="Center/Card/Margin/Column"]
text = "Survivors saved: 0"
horizontal_alignment = 1
theme_override_colors/font_color = Color(0.7, 0.95, 0.7, 1)
theme_override_colors/font_color = Color(0.659, 1, 0.8, 1)
theme_override_font_sizes/font_size = 28
[node name="RestartButton" type="Button" parent="Center/Card/Margin/Column"]
text = "RESTART"
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
theme_override_colors/font_hover_color = Color(0.5, 1, 0.5, 1)
theme_override_font_sizes/font_size = 24
theme_override_styles/normal = SubResource("ButtonStyle")
theme_override_styles/hover = SubResource("ButtonStyle")
theme_override_styles/pressed = SubResource("ButtonStyle")
theme_override_styles/focus = SubResource("ButtonStyle")
[node name="SpaceHint" type="Label" parent="Center/Card/Margin/Column"]
visible = false
text = "Space to Restart"
horizontal_alignment = 1
theme_override_colors/font_color = Color(0.95, 0.7, 0.7, 1)
theme_override_colors/font_color = Color(0.961, 1, 0.851, 1)
theme_override_font_sizes/font_size = 20

View file

@ -14,11 +14,13 @@
[ext_resource type="PackedScene" path="res://scenes/end_screen.tscn" id="10_endsc"]
[ext_resource type="AudioStream" uid="uid://dln0g1bnjh1of" path="res://audio/Robot - I Understand.wav" id="10_under"]
[ext_resource type="AudioStream" uid="uid://bwovhu6jfk0vt" path="res://audio/Robot - Thank You.wav" id="11_thx"]
[ext_resource type="PackedScene" uid="uid://sgakdvtoblmd" path="res://scenes/title_screen.tscn" id="11_title"]
[ext_resource type="PackedScene" uid="uid://bbw2sfptheq4u" path="res://scenes/start_screen.tscn" id="11_title"]
[ext_resource type="AudioStream" uid="uid://b3d6rntbosvc6" path="res://audio/Ambience.wav" id="12_amb"]
[ext_resource type="PackedScene" path="res://scenes/pause_menu.tscn" id="12_pause"]
[ext_resource type="AudioStream" uid="uid://cnfmytsyo8biq" path="res://audio/RoboZacSpeaker.wav" id="13_muzak"]
[ext_resource type="Script" uid="uid://deyjxii7yykjv" path="res://scenes/muzak.gd" id="14_muzak_s"]
[ext_resource type="AudioStream" uid="uid://6u5g67ptqsp4" path="res://audio/block.wav" id="15_block"]
[ext_resource type="AudioStream" uid="uid://cyjww14gef86j" path="res://audio/hacked.wav" id="16_hacked"]
[node name="Game" type="Node3D" unique_id=1456297160]
script = ExtResource("1_lbhrr")
@ -64,6 +66,12 @@ stream = ExtResource("10_under")
stream = ExtResource("11_thx")
[node name="SfxBlock" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=1100000007]
stream = ExtResource("15_block")
max_polyphony = 4
[node name="SfxHacked" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=1100000008]
stream = ExtResource("16_hacked")
max_polyphony = 4
[node name="Ambience" type="AudioStreamPlayer" parent="." unique_id=1100000005]
process_mode = 3
@ -80,7 +88,11 @@ script = ExtResource("14_muzak_s")
[node name="EndScreen" parent="." unique_id=993175156 instance=ExtResource("10_endsc")]
[node name="TitleScreen" parent="." unique_id=1656317143 instance=ExtResource("11_title")]
[node name="TitleScreen" type="CanvasLayer" parent="." unique_id=1656317143]
process_mode = 3
layer = 20
[node name="StartScreen" parent="TitleScreen" instance=ExtResource("11_title")]
[node name="PauseMenu" parent="." unique_id=1244164419 instance=ExtResource("12_pause")]

View file

@ -119,6 +119,7 @@ func _update_intro_progress(progress: float) -> void:
func _light_button(index: int) -> void:
var sprite: Sprite3D = _buttons[index].get_node("ButtonSprite")
sprite.frame = index + 10
$SfxFloorSelect.play()
func _set_all_lit(lit: bool) -> void:
for i in range(_buttons.size()):

View file

@ -2,6 +2,7 @@
[ext_resource type="Texture2D" path="res://images/virtua_hand_left.png" id="1_lhand"]
[ext_resource type="Script" path="res://scenes/left_hand.gd" id="2_lhscr"]
[ext_resource type="AudioStream" uid="uid://cxvu4rxkgxekb" path="res://audio/floor_select.wav" id="3_fsel"]
[node name="LeftHand" type="Sprite3D"]
billboard = 1
@ -9,3 +10,7 @@ texture_filter = 0
alpha_cut = 1
texture = ExtResource("1_lhand")
script = ExtResource("2_lhscr")
[node name="SfxFloorSelect" type="AudioStreamPlayer3D" parent="."]
stream = ExtResource("3_fsel")
max_polyphony = 16

View file

@ -26,7 +26,6 @@ func _ready() -> void:
_barks.append(n)
EventBus.game_started.connect(_on_game_started)
EventBus.game_won.connect(_on_game_ended)
EventBus.game_lost.connect(_on_game_lost)
func _process(_delta: float) -> void:
if not playing:
@ -59,6 +58,3 @@ func _on_game_started() -> void:
func _on_game_ended() -> void:
stop()
func _on_game_lost(_reason) -> void:
stop()

View file

@ -8,8 +8,10 @@ func _ready():
EventBus.game_started.connect(func(): _in_play = true)
EventBus.game_won.connect(func(): _in_play = false)
EventBus.game_lost.connect(func(_reason: String): _in_play = false)
$Center/Card/Margin/Column/ResumeButton.pressed.connect(_on_resume_pressed)
$Center/Card/Margin/Column/RestartButton.pressed.connect(_on_restart_pressed)
$Center/Card/Margin/Column/Title.text = Strings.PAUSE_TITLE
$Center/Card/Margin/Column/SpaceHint.text = Strings.PAUSE_SPACE_HINT
$Center/Card/Margin/Column/RestartHint.text = Strings.PAUSE_R_HINT
func _unhandled_input(event):
if not _in_play:
@ -18,9 +20,13 @@ func _unhandled_input(event):
_toggle()
get_viewport().set_input_as_handled()
return
if get_tree().paused and event is InputEventKey and event.pressed and not event.echo and event.keycode == KEY_SPACE:
if get_tree().paused and event is InputEventKey and event.pressed and not event.echo:
if event.keycode == KEY_SPACE:
_on_resume_pressed()
get_viewport().set_input_as_handled()
elif event.keycode == KEY_R:
_on_restart_pressed()
get_viewport().set_input_as_handled()
func _toggle():
var paused := not get_tree().paused

View file

@ -1,23 +1,7 @@
[gd_scene load_steps=3 format=3]
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://scenes/pause_menu.gd" id="1"]
[sub_resource type="StyleBoxFlat" id="ButtonStyle"]
bg_color = Color(0.1, 0.3, 0.1, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.2, 1, 0.2, 1)
corner_radius_top_left = 4
corner_radius_top_right = 4
corner_radius_bottom_right = 4
corner_radius_bottom_left = 4
content_margin_left = 24
content_margin_right = 24
content_margin_top = 12
content_margin_bottom = 12
[node name="PauseMenu" type="CanvasLayer"]
layer = 25
process_mode = 3
@ -28,7 +12,7 @@ anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
color = Color(0.05, 0.18, 0.05, 1)
color = Color(0.102, 0.251, 0.278, 1)
[node name="Center" type="CenterContainer" parent="."]
anchors_preset = 15
@ -50,31 +34,17 @@ theme_override_constants/separation = 24
[node name="Title" type="Label" parent="Center/Card/Margin/Column"]
text = "PAUSED"
horizontal_alignment = 1
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
theme_override_colors/font_color = Color(0.553, 0.91, 1, 1)
theme_override_font_sizes/font_size = 56
[node name="ResumeButton" type="Button" parent="Center/Card/Margin/Column"]
text = "RESUME"
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
theme_override_colors/font_hover_color = Color(0.5, 1, 0.5, 1)
theme_override_font_sizes/font_size = 24
theme_override_styles/normal = SubResource("ButtonStyle")
theme_override_styles/hover = SubResource("ButtonStyle")
theme_override_styles/pressed = SubResource("ButtonStyle")
theme_override_styles/focus = SubResource("ButtonStyle")
[node name="RestartButton" type="Button" parent="Center/Card/Margin/Column"]
text = "RESTART"
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
theme_override_colors/font_hover_color = Color(0.5, 1, 0.5, 1)
theme_override_font_sizes/font_size = 24
theme_override_styles/normal = SubResource("ButtonStyle")
theme_override_styles/hover = SubResource("ButtonStyle")
theme_override_styles/pressed = SubResource("ButtonStyle")
theme_override_styles/focus = SubResource("ButtonStyle")
[node name="SpaceHint" type="Label" parent="Center/Card/Margin/Column"]
text = "Space to Resume"
horizontal_alignment = 1
theme_override_colors/font_color = Color(0.7, 0.95, 0.7, 1)
theme_override_colors/font_color = Color(0.659, 1, 0.8, 1)
theme_override_font_sizes/font_size = 20
[node name="RestartHint" type="Label" parent="Center/Card/Margin/Column"]
text = "R to Restart"
horizontal_alignment = 1
theme_override_colors/font_color = Color(0.659, 1, 0.8, 1)
theme_override_font_sizes/font_size = 20

View file

@ -2,15 +2,16 @@ extends CharacterBody3D
const STALK_DARK_DISTANCE := 19.0
const STALK_ILLUMINATE_DISTANCE := 15.0
const WALK_IN_DURATION := 1.5
var robot_ready: bool = false
var robot_win: bool = false
var speed: float = 1.0
var doors_open: bool = true
var stun_remaining: float = 0.0
var _stalking_close: bool = false
var _walk_in_remaining: float = 0.0
var _game_lost_emitted: bool = false
var _delay_remaining: float = 0.0
var _spawn_transform: Transform3D
var safety_zone: Area3D
@ -30,21 +31,19 @@ func _on_floor_started(delay: float, new_speed: float) -> void:
velocity = Vector3.ZERO
stun_remaining = 0.0
speed = new_speed
_delay_remaining = delay
robot_ready = false
func _physics_process(delta):
stalking_check()
if robot_win:
return
if not robot_ready:
if _delay_remaining > 0.0:
_delay_remaining -= delta
if _delay_remaining <= 0.0:
robot_ready = true
velocity = Vector3(0, 0, -speed)
move_and_slide()
if not _game_lost_emitted:
_walk_in_remaining -= delta
if _walk_in_remaining <= 0.0:
_game_lost_emitted = true
EventBus.game_lost.emit(Strings.LOSS_ROBOT)
return
if stun_remaining > 0.0:
@ -59,13 +58,11 @@ func _physics_process(delta):
func _on_area_3d_area_entered(area: Area3D) -> void:
var safety = safety_zone
if area == safety and doors_open:
if area == safety and doors_open and not robot_win:
robot_win = true
EventBus.game_lost.emit("ROBOT GOT IN")
_walk_in_remaining = WALK_IN_DURATION
func stalking_check():
if safety_zone == null:
return
var robot_position = self.global_transform.origin
var elevator = safety_zone.global_transform.origin
@ -84,5 +81,5 @@ func stalking_check():
func illuminate():
var tween = create_tween().parallel()
tween.tween_property($Sprite3D, "modulate",Color(255,255,255), 5)
tween.tween_property($Sprite3D, "modulate",Color(1,1,1), 5)

View file

@ -72,7 +72,7 @@ func _ready():
face.position = Vector2(0, 0)
face.size = Vector2(size.x, 30)
face.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
face.text = ">:)"
face.text = Strings.SCREEN_FACE_IDLE
face.pivot_offset = face.size / 2
_pulse.configure(sl, bz, _perfect_zone, size.x)
@ -125,7 +125,7 @@ func _ready():
_score_label.offset_right = -QUOTA_DOT_RIGHT_MARGIN
_score_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
_score_label.visible = false
_score_label.text = "SCORE: 0"
_score_label.text = Strings.SCREEN_SCORE_FMT % 0
add_child(_score_label)
EventBus.score_changed.connect(_on_score_changed)
@ -133,7 +133,7 @@ func _ready():
func start(floor_num: int = EventBus.STARTING_FLOOR):
active = true
$AIFace.text = ">:)"
$AIFace.text = Strings.SCREEN_FACE_IDLE
$TargetZone.visible = true
block_zone_moving = false
_pulse.start_floor(floor_num)
@ -153,7 +153,7 @@ func stop():
func launch_pulse():
if not active:
return
$AIFace.text = ">:)"
$AIFace.text = Strings.SCREEN_FACE_IDLE
_start_ready_pulse()
_pulse.launch()
@ -178,7 +178,7 @@ var _displayed_floor := -1
func _update_floor_label(floor_num: int):
if _displayed_floor == floor_num:
return
var new_text = "FL " + str(floor_num)
var new_text = Strings.SCREEN_FLOOR_FMT % floor_num
if _displayed_floor == -1:
_floor_label.text = new_text
_displayed_floor = floor_num
@ -229,7 +229,7 @@ func _update_quota_dots(count: int, threshold: int):
func _on_score_changed(new_score: int):
_score_value = new_score
_score_label.text = "SCORE: " + str(new_score)
_score_label.text = Strings.SCREEN_SCORE_FMT % new_score
func _update_perfect_zone():
var bz = $TargetZone
@ -254,7 +254,7 @@ func _on_pulse_started(duration: float):
pulse_started.emit(duration)
func _on_pulse_blocked():
$AIFace.text = ">:("
$AIFace.text = Strings.SCREEN_FACE_BLOCKED
_punch_face(1.4, 4.0)
flash(Color.GREEN)
pulse_blocked.emit()
@ -263,7 +263,7 @@ func _on_pulse_blocked_perfect():
pulse_blocked_perfect.emit()
func _on_pulse_escaped():
$AIFace.text = ":D"
$AIFace.text = Strings.SCREEN_FACE_ESCAPED
_punch_face(1.5, 0.0)
flash(Color.RED)
active = false
@ -282,12 +282,12 @@ func flash(color: Color):
func show_countdown():
$AIFace.visible = true
stop()
$AIFace.text = "3"
$AIFace.text = Strings.SCREEN_COUNTDOWN_3
var tween = create_tween()
tween.tween_interval(0.6)
tween.tween_callback(func(): $AIFace.text = "2")
tween.tween_callback(func(): $AIFace.text = Strings.SCREEN_COUNTDOWN_2)
tween.tween_interval(0.6)
tween.tween_callback(func(): $AIFace.text = "1")
tween.tween_callback(func(): $AIFace.text = Strings.SCREEN_COUNTDOWN_1)
tween.tween_interval(0.6)
tween.tween_callback(func(): $AIFace.text = "")
@ -295,7 +295,7 @@ func show_win():
$AIFace.visible = true
stop()
$TargetZone.visible = false
$AIFace.text = "ESCAPED"
$AIFace.text = Strings.SCREEN_WIN_TEXT
flash(Color.GREEN)
func show_loss(message: String):

View file

@ -1 +1,26 @@
extends Control
func _ready():
if EventBus.debug_starting_floor > 0:
call_deferred("_start")
return
get_tree().paused = true
func _unhandled_input(event):
if event is InputEventKey and event.pressed and not event.echo:
if event.keycode == KEY_SPACE or event.keycode == KEY_ENTER:
get_viewport().set_input_as_handled()
_start()
elif event.keycode >= KEY_1 and event.keycode <= KEY_9:
EventBus.debug_starting_floor = event.keycode - KEY_0
get_viewport().set_input_as_handled()
_start()
elif event.keycode == KEY_0:
EventBus.debug_starting_floor = EventBus.STARTING_FLOOR
get_viewport().set_input_as_handled()
_start()
func _start():
get_tree().paused = false
EventBus.game_started.emit()
get_parent().queue_free()

View file

@ -1,6 +1,9 @@
extends CanvasLayer
func _ready():
$Center/Card/Margin/Column/Title.text = Strings.TITLE
$Center/Card/Margin/Column/Prompt.text = Strings.TITLE_PRESS_START
if EventBus.debug_starting_floor > 0:
call_deferred("_start")
return

View file

@ -12,7 +12,7 @@ anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
color = Color(0.05, 0.18, 0.05, 1)
color = Color(0.102, 0.251, 0.278, 1)
[node name="Center" type="CenterContainer" parent="." unique_id=9544562]
anchors_preset = 15
@ -35,7 +35,7 @@ theme_override_constants/separation = 24
[node name="Title" type="Label" parent="Center/Card/Margin/Column" unique_id=358683873]
layout_mode = 2
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
theme_override_colors/font_color = Color(0.553, 0.91, 1, 1)
theme_override_font_sizes/font_size = 48
text = "AGENTIC INCIDENT
(A.I.)"
@ -43,7 +43,7 @@ horizontal_alignment = 1
[node name="Prompt" type="Label" parent="Center/Card/Margin/Column" unique_id=366312976]
layout_mode = 2
theme_override_colors/font_color = Color(0.5, 1, 0.5, 1)
theme_override_colors/font_color = Color(0.659, 1, 0.8, 1)
theme_override_font_sizes/font_size = 28
text = "PRESS SPACE TO START"
horizontal_alignment = 1

View file

@ -4,6 +4,8 @@ const SLIDE_DURATION := 0.25
const UP_DURATION := 0.1
const HOLD_DURATION := 0.05
const DOWN_DURATION := 0.18
const ENTRY_OFFSET := 0.5
const ENTRY_DURATION := 0.5
var _open_button: Node3D
var _close_button: Node3D
@ -25,10 +27,19 @@ func _ready() -> void:
_rest_y = position.y
_target_button = _close_button
position = Vector3(_close_rest_x, _rest_y, position.z)
visible = false
print("[VirtuaHand] close_x=", _close_rest_x, " open_x=", _open_rest_x, " hand_pos=", position)
EventBus.button_pressed.connect(_animate_press)
EventBus.active_button_changed.connect(_on_active_button_changed)
EventBus.intro_finished.connect(_on_intro_finished)
func _on_intro_finished() -> void:
var sprite_height := texture.get_height() * pixel_size * scale.y
position.y = _rest_y - sprite_height - ENTRY_OFFSET
visible = true
var entry_tween := create_tween()
entry_tween.tween_property(self, "position:y", _rest_y, ENTRY_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
func _project_to_hand_plane(button: Node3D) -> float:
var cam := get_viewport().get_camera_3d()

View file

@ -20,10 +20,10 @@ func _ready() -> void:
_wall_display.modulate = WALL_DISPLAY_COLOR
_wall_display.text = str(_current_floor)
EventBus.doors_closed.connect(_on_doors_closed)
EventBus.doors_fully_closed.connect(_free_robot)
EventBus.doors_fully_closed.connect(_free_robot_unless_winning)
EventBus.doors_opened.connect(_on_doors_opened)
EventBus.floor_changed.connect(_on_floor_changed)
EventBus.game_lost.connect(func(_reason: String): _free_robot())
EventBus.game_lost.connect(func(_reason: String): _free_robot_unless_winning())
EventBus.game_won.connect(_free_robot)
func _collect_dim_targets() -> void:
@ -62,6 +62,11 @@ func _free_robot() -> void:
_robot.queue_free()
_robot = null
func _free_robot_unless_winning() -> void:
if is_instance_valid(_robot) and _robot.robot_win:
return
_free_robot()
func _on_floor_changed(new_floor: int) -> void:
_current_floor = new_floor
_wall_display.text = str(new_floor)

32
scripts/strings.gd Normal file
View file

@ -0,0 +1,32 @@
extends Node
const TITLE := "AGENTIC INCIDENT
(A.I.)"
const TITLE_PRESS_START := "PRESS SPACE TO COMPLY"
const PAUSE_TITLE := "ON A BREAK"
const PAUSE_RESUME := "RESUME"
const PAUSE_RESTART := "REBOOT"
const PAUSE_SPACE_HINT := "Space to clock back in"
const PAUSE_R_HINT := "R to Restart"
const END_WIN_HEADLINE := "THANKS FOR RIDING GOATECH"
const END_LOSS_HEADLINE := "INCIDENT CLOSED"
const END_SCORE_FMT := "SCORE: %d"
const END_SAVED_FMT := "Headcount preserved: %d"
const END_RESTART := "RESTART"
const END_SPACE_HINT := "Space to REBOOT."
const SCREEN_FACE_IDLE := ">:)"
const SCREEN_FACE_BLOCKED := ">:("
const SCREEN_FACE_ESCAPED := ":D"
const SCREEN_WIN_TEXT := "ADEQUATE"
const SCREEN_FLOOR_FMT := "FL %d"
const SCREEN_SCORE_FMT := "SCORE: %d"
const SCREEN_COUNTDOWN_3 := "3"
const SCREEN_COUNTDOWN_2 := "2"
const SCREEN_COUNTDOWN_1 := "1"
const LOSS_TOO_FEW := "INCIDENT CLOSED
- HR WILL HEAR ABOUT THIS -"
const LOSS_ROBOT := "I'M IN. robot"

1
scripts/strings.gd.uid Normal file
View file

@ -0,0 +1 @@
uid://d3q720oivpuq5