diff --git a/project.godot b/project.godot index 18b1fc2..99c20b2 100644 --- a/project.godot +++ b/project.godot @@ -18,6 +18,7 @@ config/icon="res://icon.svg" [autoload] EventBus="*uid://hxpxcxvxcisu" +Strings="*res://scripts/strings.gd" [input] diff --git a/scenes/elevator_panel.gd b/scenes/elevator_panel.gd index 1d1fbf6..bf9fd00 100644 --- a/scenes/elevator_panel.gd +++ b/scenes/elevator_panel.gd @@ -249,8 +249,8 @@ 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 diff --git a/scenes/end_screen.gd b/scenes/end_screen.gd index badc443..d927024 100644 --- a/scenes/end_screen.gd +++ b/scenes/end_screen.gd @@ -3,32 +3,41 @@ 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 +func _on_game_lost(_reason: String): + $Center/Card/Margin/Column/Headline.text = Strings.END_LOSS_HEADLINE _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) @@ -36,23 +45,41 @@ func _apply_loss_palette(): $Dim.color = Color(0.18, 0.05, 0.05, 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", 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 _show(): - $Center/Card/Margin/Column/ScoreLabel.text = "Score: %d" % _score - $Center/Card/Margin/Column/SavedLabel.text = "Survivors saved: %d" % _saved - visible = true +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 + + 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 func _on_restart_pressed(): get_tree().reload_current_scene() diff --git a/scenes/end_screen.tscn b/scenes/end_screen.tscn index cf43acc..61f61b2 100644 --- a/scenes/end_screen.tscn +++ b/scenes/end_screen.tscn @@ -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") @@ -29,6 +14,14 @@ anchor_bottom = 1.0 mouse_filter = 2 color = Color(0.05, 0.18, 0.05, 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 anchor_right = 1.0 @@ -64,18 +57,7 @@ horizontal_alignment = 1 theme_override_colors/font_color = Color(0.7, 0.95, 0.7, 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) diff --git a/scenes/muzak.gd b/scenes/muzak.gd index 871f116..7e82fdb 100644 --- a/scenes/muzak.gd +++ b/scenes/muzak.gd @@ -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() diff --git a/scenes/pause_menu.gd b/scenes/pause_menu.gd index 3533718..398066c 100644 --- a/scenes/pause_menu.gd +++ b/scenes/pause_menu.gd @@ -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: - _on_resume_pressed() - get_viewport().set_input_as_handled() + 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 diff --git a/scenes/pause_menu.tscn b/scenes/pause_menu.tscn index c3f6ba4..f037c51 100644 --- a/scenes/pause_menu.tscn +++ b/scenes/pause_menu.tscn @@ -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 @@ -53,28 +37,14 @@ horizontal_alignment = 1 theme_override_colors/font_color = Color(0.2, 1, 0.2, 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_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.7, 0.95, 0.7, 1) +theme_override_font_sizes/font_size = 20 diff --git a/scenes/robot.gd b/scenes/robot.gd index 8beffe8..1f3fa8b 100644 --- a/scenes/robot.gd +++ b/scenes/robot.gd @@ -61,7 +61,7 @@ func _on_area_3d_area_entered(area: Area3D) -> void: var safety = safety_zone if area == safety and doors_open: robot_win = true - EventBus.game_lost.emit("ROBOT GOT IN") + EventBus.game_lost.emit(Strings.LOSS_ROBOT) func stalking_check(): if safety_zone == null: diff --git a/scenes/screen.gd b/scenes/screen.gd index 66a949f..b508fb6 100644 --- a/scenes/screen.gd +++ b/scenes/screen.gd @@ -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): diff --git a/scenes/title_screen.gd b/scenes/title_screen.gd index 066f57b..caa7446 100644 --- a/scenes/title_screen.gd +++ b/scenes/title_screen.gd @@ -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 diff --git a/scenes/virtua_hand.gd b/scenes/virtua_hand.gd index b99a984..e501bc0 100644 --- a/scenes/virtua_hand.gd +++ b/scenes/virtua_hand.gd @@ -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() diff --git a/scripts/strings.gd b/scripts/strings.gd new file mode 100644 index 0000000..fa02ac6 --- /dev/null +++ b/scripts/strings.gd @@ -0,0 +1,31 @@ +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 := "HR WILL HEAR ABOUT THIS" +const LOSS_ROBOT := "I'M IN. — robot" diff --git a/scripts/strings.gd.uid b/scripts/strings.gd.uid new file mode 100644 index 0000000..83ac1bc --- /dev/null +++ b/scripts/strings.gd.uid @@ -0,0 +1 @@ +uid://d3q720oivpuq5