Squashed commit
This commit is contained in:
parent
c713781de4
commit
c3d8ff6989
14 changed files with 308 additions and 120 deletions
BIN
images/goatech_screen.png
Normal file
BIN
images/goatech_screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 873 B |
40
images/goatech_screen.png.import
Normal file
40
images/goatech_screen.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dddmw71jfy4yq"
|
||||||
|
path="res://.godot/imported/goatech_screen.png-55b460e1ad15ace769d864d7c2c15920.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://images/goatech_screen.png"
|
||||||
|
dest_files=["res://.godot/imported/goatech_screen.png-55b460e1ad15ace769d864d7c2c15920.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
|
@ -47,9 +47,13 @@ func _on_pulse_started(duration: float):
|
||||||
var lag = max(PULSE_CLOSE_LAG_MIN, PULSE_CLOSE_LAG_TOP - floors_descended * PULSE_CLOSE_LAG_PER_FLOOR)
|
var lag = max(PULSE_CLOSE_LAG_MIN, PULSE_CLOSE_LAG_TOP - floors_descended * PULSE_CLOSE_LAG_PER_FLOOR)
|
||||||
get_tree().create_timer(lag, false).timeout.connect(
|
get_tree().create_timer(lag, false).timeout.connect(
|
||||||
func():
|
func():
|
||||||
if _pulse_close_pending:
|
if not _pulse_close_pending:
|
||||||
|
return
|
||||||
|
if $ElevatorDoorRight.position.x < DOOR_OPEN_X - 0.001:
|
||||||
_pulse_close_pending = false
|
_pulse_close_pending = false
|
||||||
_tween_doors(DOOR_CLOSED_X, duration),
|
return
|
||||||
|
_pulse_close_pending = false
|
||||||
|
_tween_doors(DOOR_CLOSED_X, duration),
|
||||||
CONNECT_ONE_SHOT
|
CONNECT_ONE_SHOT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
[node name="ElevatorButton" type="Sprite3D" unique_id=1758559173]
|
[node name="ElevatorButton" type="Sprite3D" unique_id=1758559173]
|
||||||
billboard = 1
|
billboard = 1
|
||||||
|
alpha_cut = 1
|
||||||
texture_filter = 0
|
texture_filter = 0
|
||||||
texture = ExtResource("1_sy1b3")
|
texture = ExtResource("1_sy1b3")
|
||||||
hframes = 2
|
hframes = 2
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
extends PanelContainer
|
extends PanelContainer
|
||||||
|
|
||||||
@onready var _screen = $PanelMargin/PanelColumn/Screen
|
@onready var _screen = $PanelMargin/PanelColumn/Screen
|
||||||
@onready var _close_button: Button = $PanelMargin/PanelColumn/CloseButton
|
|
||||||
|
|
||||||
var current_floor: int = EventBus.STARTING_FLOOR
|
var current_floor: int = EventBus.STARTING_FLOOR
|
||||||
var saved_count := 0
|
var saved_count := 0
|
||||||
|
|
@ -32,10 +31,17 @@ var people_in_elevator := 0
|
||||||
const PERFECT_STUN_DURATION := 1.5
|
const PERFECT_STUN_DURATION := 1.5
|
||||||
const DING_TO_DOORS_DELAY := 2.0
|
const DING_TO_DOORS_DELAY := 2.0
|
||||||
|
|
||||||
func _ready():
|
const HACK_DELAY_MIN := 1.25
|
||||||
_close_button.text = "CLOSE"
|
const HACK_DELAY_MAX := 1.75
|
||||||
_close_button.pressed.connect(_on_block_pressed)
|
const FIRST_FLOOR_INTRO_DELAY := 2.0
|
||||||
|
const STATIC_DURATION := 0.2
|
||||||
|
const DEBUG_SCREEN_STATE := false
|
||||||
|
|
||||||
|
enum ScreenState { IDLE, STATIC, HACKED }
|
||||||
|
var state: ScreenState = ScreenState.IDLE
|
||||||
|
var floor_token: int = 0
|
||||||
|
|
||||||
|
func _ready():
|
||||||
_screen.pulse_started.connect(_on_pulse_started)
|
_screen.pulse_started.connect(_on_pulse_started)
|
||||||
_screen.pulse_blocked.connect(_on_pulse_blocked)
|
_screen.pulse_blocked.connect(_on_pulse_blocked)
|
||||||
_screen.pulse_blocked_perfect.connect(_on_pulse_blocked_perfect)
|
_screen.pulse_blocked_perfect.connect(_on_pulse_blocked_perfect)
|
||||||
|
|
@ -45,11 +51,15 @@ func _ready():
|
||||||
EventBus.game_lost.connect(func(_reason): $SfxRobotIUnderstand.play())
|
EventBus.game_lost.connect(func(_reason): $SfxRobotIUnderstand.play())
|
||||||
EventBus.survivor_squeaked_in.connect(_on_survivor_squeaked_in)
|
EventBus.survivor_squeaked_in.connect(_on_survivor_squeaked_in)
|
||||||
EventBus.robot_close_warning.connect(_on_robot_close_warning)
|
EventBus.robot_close_warning.connect(_on_robot_close_warning)
|
||||||
|
EventBus.survivor_entered_elevator.connect(_on_survivor_entered_elevator)
|
||||||
|
|
||||||
func _unhandled_input(event):
|
func _unhandled_input(event):
|
||||||
if event is InputEventKey and event.pressed and not event.echo:
|
if event is InputEventKey and event.pressed and not event.echo:
|
||||||
if event.keycode == KEY_SPACE:
|
if event.keycode == KEY_SPACE:
|
||||||
_on_block_pressed()
|
match state:
|
||||||
|
ScreenState.HACKED: _on_open_pressed()
|
||||||
|
ScreenState.IDLE: _on_close_pressed()
|
||||||
|
ScreenState.STATIC: pass
|
||||||
elif event.keycode == KEY_R:
|
elif event.keycode == KEY_R:
|
||||||
get_tree().reload_current_scene()
|
get_tree().reload_current_scene()
|
||||||
elif event.keycode >= KEY_1 and event.keycode <= KEY_9:
|
elif event.keycode >= KEY_1 and event.keycode <= KEY_9:
|
||||||
|
|
@ -66,16 +76,23 @@ func _on_game_started():
|
||||||
func _reset_floor_state():
|
func _reset_floor_state():
|
||||||
doors_closing_flag = false
|
doors_closing_flag = false
|
||||||
people_in_elevator = 0
|
people_in_elevator = 0
|
||||||
_close_button.text = "CLOSE"
|
|
||||||
var floors_remaining = current_floor - 1
|
var floors_remaining = current_floor - 1
|
||||||
survivors_remaining = BASE_SURVIVORS + (floors_remaining * SURVIVORS_PER_FLOOR_INCREASE)
|
survivors_remaining = BASE_SURVIVORS + (floors_remaining * SURVIVORS_PER_FLOOR_INCREASE)
|
||||||
|
|
||||||
|
func _dbg(msg: String) -> void:
|
||||||
|
if DEBUG_SCREEN_STATE:
|
||||||
|
print("[screen] floor=%d token=%d %s" % [current_floor, floor_token, msg])
|
||||||
|
|
||||||
func _start_floor():
|
func _start_floor():
|
||||||
if EventBus.debug_starting_floor > 0:
|
if EventBus.debug_starting_floor > 0:
|
||||||
current_floor = EventBus.debug_starting_floor
|
current_floor = EventBus.debug_starting_floor
|
||||||
_onboarded = true
|
_onboarded = true
|
||||||
EventBus.debug_starting_floor = 0
|
EventBus.debug_starting_floor = 0
|
||||||
|
|
||||||
|
floor_token += 1
|
||||||
|
var token = floor_token
|
||||||
|
_dbg("start_floor IDLE")
|
||||||
|
|
||||||
$SfxBell.play()
|
$SfxBell.play()
|
||||||
if _onboarded and randf() < 0.4:
|
if _onboarded and randf() < 0.4:
|
||||||
$SfxRobotDeepBreath.play()
|
$SfxRobotDeepBreath.play()
|
||||||
|
|
@ -107,11 +124,51 @@ func _start_floor():
|
||||||
|
|
||||||
if not _onboarded:
|
if not _onboarded:
|
||||||
_onboarded = true
|
_onboarded = true
|
||||||
EventBus.doors_nearly_opened.connect(
|
|
||||||
|
state = ScreenState.IDLE
|
||||||
|
_screen.enter_idle()
|
||||||
|
EventBus.active_button_changed.emit("close")
|
||||||
|
|
||||||
|
if current_floor == EventBus.STARTING_FLOOR:
|
||||||
|
get_tree().create_timer(FIRST_FLOOR_INTRO_DELAY, false).timeout.connect(
|
||||||
|
func():
|
||||||
|
if token != floor_token or doors_closing_flag:
|
||||||
|
_dbg("first-floor delay bail")
|
||||||
|
return
|
||||||
|
_enter_static_then_hacked(token),
|
||||||
|
CONNECT_ONE_SHOT
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
schedule_next_hack(token)
|
||||||
|
|
||||||
|
func schedule_next_hack(token: int) -> void:
|
||||||
|
var delay := randf_range(HACK_DELAY_MIN, HACK_DELAY_MAX)
|
||||||
|
_dbg("schedule_next_hack delay=%.2f" % delay)
|
||||||
|
get_tree().create_timer(delay, false).timeout.connect(
|
||||||
func():
|
func():
|
||||||
if not is_instance_valid(self) or doors_closing_flag:
|
if token != floor_token:
|
||||||
|
_dbg("schedule_next_hack token bail")
|
||||||
return
|
return
|
||||||
_screen.launch_pulse(),
|
if doors_closing_flag:
|
||||||
|
_dbg("schedule_next_hack doors_closing bail")
|
||||||
|
return
|
||||||
|
_enter_static_then_hacked(token),
|
||||||
|
CONNECT_ONE_SHOT
|
||||||
|
)
|
||||||
|
|
||||||
|
func _enter_static_then_hacked(token: int) -> void:
|
||||||
|
state = ScreenState.STATIC
|
||||||
|
_screen.enter_static()
|
||||||
|
_dbg("STATIC")
|
||||||
|
get_tree().create_timer(STATIC_DURATION, false).timeout.connect(
|
||||||
|
func():
|
||||||
|
if token != floor_token or doors_closing_flag:
|
||||||
|
_dbg("post-STATIC bail")
|
||||||
|
return
|
||||||
|
state = ScreenState.HACKED
|
||||||
|
_dbg("HACKED")
|
||||||
|
_screen.enter_hacked()
|
||||||
|
EventBus.active_button_changed.emit("open"),
|
||||||
CONNECT_ONE_SHOT
|
CONNECT_ONE_SHOT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -123,46 +180,71 @@ func _on_robot_close_warning():
|
||||||
if not $SfxRobotDeepBreath.playing:
|
if not $SfxRobotDeepBreath.playing:
|
||||||
$SfxRobotDeepBreath.play()
|
$SfxRobotDeepBreath.play()
|
||||||
|
|
||||||
func _on_block_pressed():
|
func _on_open_pressed():
|
||||||
|
if state != ScreenState.HACKED:
|
||||||
|
_dbg("open rejected (state=%d)" % state)
|
||||||
|
return
|
||||||
if doors_closing_flag:
|
if doors_closing_flag:
|
||||||
return
|
return
|
||||||
EventBus.block_pressed.emit()
|
if not _screen.pulse_active:
|
||||||
if _screen.pulse_active:
|
return
|
||||||
_screen.attempt_block()
|
EventBus.button_pressed.emit()
|
||||||
else:
|
_screen.attempt_block()
|
||||||
$SfxRobotThankYou.play()
|
|
||||||
_on_doors_closing(false)
|
func _on_close_pressed():
|
||||||
|
if state != ScreenState.IDLE:
|
||||||
|
_dbg("close rejected (state=%d)" % state)
|
||||||
|
return
|
||||||
|
if doors_closing_flag:
|
||||||
|
return
|
||||||
|
EventBus.button_pressed.emit()
|
||||||
|
$SfxRobotThankYou.play()
|
||||||
|
_on_doors_closing(false)
|
||||||
|
|
||||||
|
func _on_survivor_entered_elevator():
|
||||||
|
if doors_closing_flag:
|
||||||
|
return
|
||||||
|
$SfxDing.play()
|
||||||
|
|
||||||
func _on_pulse_started(duration: float):
|
func _on_pulse_started(duration: float):
|
||||||
_close_button.text = "BLOCK"
|
|
||||||
EventBus.pulse_started.emit(duration)
|
EventBus.pulse_started.emit(duration)
|
||||||
|
|
||||||
func _on_pulse_blocked_perfect():
|
func _on_pulse_blocked_perfect():
|
||||||
EventBus.robot_stun_requested.emit(PERFECT_STUN_DURATION)
|
EventBus.robot_stun_requested.emit(PERFECT_STUN_DURATION)
|
||||||
|
|
||||||
func _on_pulse_blocked():
|
func _on_pulse_blocked():
|
||||||
_close_button.text = "CLOSE"
|
|
||||||
EventBus.pulse_blocked.emit()
|
EventBus.pulse_blocked.emit()
|
||||||
survivors_remaining -= 1
|
survivors_remaining -= 1
|
||||||
people_in_elevator += 1
|
people_in_elevator += 1
|
||||||
$SfxDing.play()
|
|
||||||
EventBus.people_changed.emit(people_in_elevator, THRESHOLD)
|
EventBus.people_changed.emit(people_in_elevator, THRESHOLD)
|
||||||
|
if $SfxBlock.stream:
|
||||||
|
$SfxBlock.play()
|
||||||
|
|
||||||
if survivors_remaining <= 0:
|
if survivors_remaining <= 0:
|
||||||
get_tree().create_timer(0.25, false).timeout.connect(_on_doors_closing, CONNECT_ONE_SHOT)
|
get_tree().create_timer(0.25, false).timeout.connect(_on_doors_closing, CONNECT_ONE_SHOT)
|
||||||
return
|
return
|
||||||
|
|
||||||
var gap = _screen.get_pulse_gap()
|
var token = floor_token
|
||||||
get_tree().create_timer(gap, false).timeout.connect(
|
state = ScreenState.STATIC
|
||||||
|
_screen.enter_static()
|
||||||
|
_dbg("post-block STATIC")
|
||||||
|
get_tree().create_timer(STATIC_DURATION, false).timeout.connect(
|
||||||
func():
|
func():
|
||||||
if not doors_closing_flag:
|
if token != floor_token or doors_closing_flag:
|
||||||
_screen.launch_pulse(),
|
_dbg("post-block-STATIC bail")
|
||||||
|
return
|
||||||
|
state = ScreenState.IDLE
|
||||||
|
_screen.enter_idle()
|
||||||
|
_dbg("post-block IDLE")
|
||||||
|
EventBus.active_button_changed.emit("close")
|
||||||
|
schedule_next_hack(token),
|
||||||
CONNECT_ONE_SHOT
|
CONNECT_ONE_SHOT
|
||||||
)
|
)
|
||||||
|
|
||||||
func _on_doors_closing(fast: bool = false):
|
func _on_doors_closing(fast: bool = false):
|
||||||
if doors_closing_flag:
|
if doors_closing_flag:
|
||||||
return
|
return
|
||||||
|
_dbg("doors_closing fast=%s" % fast)
|
||||||
doors_closing_flag = true
|
doors_closing_flag = true
|
||||||
EventBus.doors_closed.emit(fast)
|
EventBus.doors_closed.emit(fast)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,26 +12,26 @@ corner_radius_top_right = 4
|
||||||
corner_radius_bottom_right = 4
|
corner_radius_bottom_right = 4
|
||||||
corner_radius_bottom_left = 4
|
corner_radius_bottom_left = 4
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_panel"]
|
||||||
|
|
||||||
[node name="ElevatorPanel" type="PanelContainer" unique_id=574176994]
|
[node name="ElevatorPanel" type="PanelContainer" unique_id=574176994]
|
||||||
anchors_preset = 6
|
anchors_preset = 1
|
||||||
anchor_left = 1.0
|
anchor_left = 1.0
|
||||||
anchor_top = 0.5
|
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 0.5
|
|
||||||
offset_left = -230.0
|
offset_left = -230.0
|
||||||
offset_top = -160.0
|
offset_top = 20.0
|
||||||
offset_right = -10.0
|
offset_right = -10.0
|
||||||
offset_bottom = 160.0
|
offset_bottom = 200.0
|
||||||
grow_horizontal = 0
|
grow_horizontal = 0
|
||||||
grow_vertical = 2
|
theme_override_styles/panel = SubResource("StyleBoxEmpty_panel")
|
||||||
script = ExtResource("1_1gr6t")
|
script = ExtResource("1_1gr6t")
|
||||||
|
|
||||||
[node name="PanelMargin" type="MarginContainer" parent="." unique_id=1575963889]
|
[node name="PanelMargin" type="MarginContainer" parent="." unique_id=1575963889]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/margin_left = 15
|
theme_override_constants/margin_left = 0
|
||||||
theme_override_constants/margin_top = 15
|
theme_override_constants/margin_top = 0
|
||||||
theme_override_constants/margin_right = 15
|
theme_override_constants/margin_right = 0
|
||||||
theme_override_constants/margin_bottom = 15
|
theme_override_constants/margin_bottom = 0
|
||||||
|
|
||||||
[node name="VirtuaHandTemp" type="Sprite2D" parent="PanelMargin" unique_id=14079675]
|
[node name="VirtuaHandTemp" type="Sprite2D" parent="PanelMargin" unique_id=14079675]
|
||||||
visible = false
|
visible = false
|
||||||
|
|
@ -45,7 +45,7 @@ texture = ExtResource("2_03crn")
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="Screen" type="Panel" parent="PanelMargin/PanelColumn" unique_id=1395085208]
|
[node name="Screen" type="Panel" parent="PanelMargin/PanelColumn" unique_id=1395085208]
|
||||||
custom_minimum_size = Vector2(160, 160)
|
custom_minimum_size = Vector2(190, 160)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_n2snw")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_n2snw")
|
||||||
script = ExtResource("1_3gei6")
|
script = ExtResource("1_3gei6")
|
||||||
|
|
@ -76,9 +76,3 @@ text = ">:)"
|
||||||
|
|
||||||
[node name="Pulse" type="Node" parent="PanelMargin/PanelColumn/Screen" unique_id=988615527]
|
[node name="Pulse" type="Node" parent="PanelMargin/PanelColumn/Screen" unique_id=988615527]
|
||||||
script = ExtResource("2_pulse")
|
script = ExtResource("2_pulse")
|
||||||
|
|
||||||
[node name="CloseButton" type="Button" parent="PanelMargin/PanelColumn" unique_id=554485629]
|
|
||||||
custom_minimum_size = Vector2(0, 60)
|
|
||||||
layout_mode = 2
|
|
||||||
theme_override_font_sizes/font_size = 28
|
|
||||||
text = "CLOSE"
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.004168272, 1.1920929e-07,
|
||||||
[node name="SfxDing" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=529226129]
|
[node name="SfxDing" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=529226129]
|
||||||
stream = ExtResource("4_p57ef")
|
stream = ExtResource("4_p57ef")
|
||||||
volume_db = 3.0
|
volume_db = 3.0
|
||||||
|
max_polyphony = 4
|
||||||
|
|
||||||
[node name="SfxOpen" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=3954090]
|
[node name="SfxOpen" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=3954090]
|
||||||
stream = ExtResource("5_u5sy4")
|
stream = ExtResource("5_u5sy4")
|
||||||
|
|
@ -62,6 +63,8 @@ stream = ExtResource("10_under")
|
||||||
[node name="SfxRobotThankYou" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=1100000004]
|
[node name="SfxRobotThankYou" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=1100000004]
|
||||||
stream = ExtResource("11_thx")
|
stream = ExtResource("11_thx")
|
||||||
|
|
||||||
|
[node name="SfxBlock" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=1100000007]
|
||||||
|
|
||||||
[node name="Ambience" type="AudioStreamPlayer" parent="." unique_id=1100000005]
|
[node name="Ambience" type="AudioStreamPlayer" parent="." unique_id=1100000005]
|
||||||
process_mode = 3
|
process_mode = 3
|
||||||
stream = ExtResource("12_amb")
|
stream = ExtResource("12_amb")
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,4 @@
|
||||||
extends MarginContainer
|
extends MarginContainer
|
||||||
|
|
||||||
var _displayed_floor := -1
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
$StatsColumn/FloorLabel.text = "FLOOR: 10"
|
pass
|
||||||
$StatsColumn/SavedLabel.text = "SAVED: 0"
|
|
||||||
$StatsColumn/PeopleLabel.text = "PEOPLE: 0/2"
|
|
||||||
$StatsColumn/ScoreLabel.text = "SCORE: 0"
|
|
||||||
|
|
||||||
EventBus.floor_changed.connect(update_floor)
|
|
||||||
EventBus.saved_changed.connect(update_saved)
|
|
||||||
EventBus.people_changed.connect(update_people)
|
|
||||||
EventBus.score_changed.connect(update_score)
|
|
||||||
|
|
||||||
func update_floor(floor_num: int):
|
|
||||||
if _displayed_floor == floor_num:
|
|
||||||
return
|
|
||||||
var label = $StatsColumn/FloorLabel
|
|
||||||
var new_text = "FLOOR: " + str(floor_num)
|
|
||||||
if _displayed_floor == -1:
|
|
||||||
label.text = new_text
|
|
||||||
_displayed_floor = floor_num
|
|
||||||
return
|
|
||||||
_displayed_floor = floor_num
|
|
||||||
UIUtils.flip_label_text(label, new_text)
|
|
||||||
|
|
||||||
func update_saved(count: int):
|
|
||||||
$StatsColumn/SavedLabel.text = "SAVED: " + str(count)
|
|
||||||
|
|
||||||
func update_people(count: int, threshold: int):
|
|
||||||
var label = $StatsColumn/PeopleLabel
|
|
||||||
label.text = "PEOPLE: " + str(count) + "/" + str(threshold)
|
|
||||||
var color = Color(0.4, 1.0, 0.4) if count >= threshold else Color(1.0, 0.4, 0.4)
|
|
||||||
label.add_theme_color_override("font_color", color)
|
|
||||||
|
|
||||||
func update_score(new_score: int):
|
|
||||||
$StatsColumn/ScoreLabel.text = "SCORE: " + str(new_score)
|
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,3 @@ offset_bottom = 40.0
|
||||||
theme_override_constants/margin_left = 72
|
theme_override_constants/margin_left = 72
|
||||||
theme_override_constants/margin_top = 20
|
theme_override_constants/margin_top = 20
|
||||||
script = ExtResource("1_64ctp")
|
script = ExtResource("1_64ctp")
|
||||||
|
|
||||||
[node name="StatsColumn" type="VBoxContainer" parent="." unique_id=1476756270]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="PeopleLabel" type="Label" parent="StatsColumn" unique_id=1174457387]
|
|
||||||
layout_mode = 2
|
|
||||||
theme_override_font_sizes/font_size = 24
|
|
||||||
text = "PEOPLE: 0"
|
|
||||||
|
|
||||||
[node name="SavedLabel" type="Label" parent="StatsColumn" unique_id=969002022]
|
|
||||||
layout_mode = 2
|
|
||||||
theme_override_font_sizes/font_size = 24
|
|
||||||
text = "SAVED: 0"
|
|
||||||
|
|
||||||
[node name="FloorLabel" type="Label" parent="StatsColumn" unique_id=67147411]
|
|
||||||
layout_mode = 2
|
|
||||||
theme_override_font_sizes/font_size = 24
|
|
||||||
text = "FLOOR: 0"
|
|
||||||
|
|
||||||
[node name="ScoreLabel" type="Label" parent="StatsColumn" unique_id=1595653166]
|
|
||||||
layout_mode = 2
|
|
||||||
theme_override_font_sizes/font_size = 24
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,11 @@ var _quota_threshold := 0
|
||||||
var _quota_filled_style: StyleBoxFlat
|
var _quota_filled_style: StyleBoxFlat
|
||||||
var _quota_empty_style: StyleBoxFlat
|
var _quota_empty_style: StyleBoxFlat
|
||||||
|
|
||||||
|
var _idle_image: TextureRect
|
||||||
|
var _static_overlay: ColorRect
|
||||||
|
var _score_label: Label
|
||||||
|
var _score_value := 0
|
||||||
|
|
||||||
@onready var _pulse = $Pulse
|
@onready var _pulse = $Pulse
|
||||||
|
|
||||||
signal pulse_started(duration: float)
|
signal pulse_started(duration: float)
|
||||||
|
|
@ -90,6 +95,42 @@ func _ready():
|
||||||
EventBus.floor_changed.connect(_update_floor_label)
|
EventBus.floor_changed.connect(_update_floor_label)
|
||||||
EventBus.people_changed.connect(_update_quota_dots)
|
EventBus.people_changed.connect(_update_quota_dots)
|
||||||
|
|
||||||
|
_idle_image = TextureRect.new()
|
||||||
|
_idle_image.texture = load("res://images/goatech_screen.png")
|
||||||
|
_idle_image.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||||
|
_idle_image.anchor_right = 1.0
|
||||||
|
_idle_image.anchor_bottom = 1.0
|
||||||
|
_idle_image.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
|
_idle_image.visible = false
|
||||||
|
add_child(_idle_image)
|
||||||
|
|
||||||
|
_static_overlay = ColorRect.new()
|
||||||
|
_static_overlay.color = Color(1.0, 1.0, 1.0, 0.6)
|
||||||
|
_static_overlay.anchor_right = 1.0
|
||||||
|
_static_overlay.anchor_bottom = 1.0
|
||||||
|
_static_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
|
_static_overlay.visible = false
|
||||||
|
add_child(_static_overlay)
|
||||||
|
|
||||||
|
_score_label = Label.new()
|
||||||
|
_score_label.add_theme_font_size_override("font_size", 12)
|
||||||
|
_score_label.add_theme_color_override("font_color", Color(0.2, 1, 0.2, 1))
|
||||||
|
_score_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||||
|
_score_label.anchor_left = 0.0
|
||||||
|
_score_label.anchor_right = 1.0
|
||||||
|
_score_label.anchor_top = 0.0
|
||||||
|
_score_label.anchor_bottom = 0.0
|
||||||
|
_score_label.offset_top = QUOTA_DOT_Y + QUOTA_DOT_SIZE + 2
|
||||||
|
_score_label.offset_bottom = QUOTA_DOT_Y + QUOTA_DOT_SIZE + 18
|
||||||
|
_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"
|
||||||
|
add_child(_score_label)
|
||||||
|
EventBus.score_changed.connect(_on_score_changed)
|
||||||
|
|
||||||
|
enter_idle()
|
||||||
|
|
||||||
func start(floor_num: int = EventBus.STARTING_FLOOR):
|
func start(floor_num: int = EventBus.STARTING_FLOOR):
|
||||||
active = true
|
active = true
|
||||||
$AIFace.text = ">:)"
|
$AIFace.text = ">:)"
|
||||||
|
|
@ -186,6 +227,10 @@ func _update_quota_dots(count: int, threshold: int):
|
||||||
var style = _quota_filled_style if i < count else _quota_empty_style
|
var style = _quota_filled_style if i < count else _quota_empty_style
|
||||||
_quota_dots[i].add_theme_stylebox_override("panel", style)
|
_quota_dots[i].add_theme_stylebox_override("panel", style)
|
||||||
|
|
||||||
|
func _on_score_changed(new_score: int):
|
||||||
|
_score_value = new_score
|
||||||
|
_score_label.text = "SCORE: " + str(new_score)
|
||||||
|
|
||||||
func _update_perfect_zone():
|
func _update_perfect_zone():
|
||||||
var bz = $TargetZone
|
var bz = $TargetZone
|
||||||
var width = bz.size.x * PERFECT_ZONE_RATIO
|
var width = bz.size.x * PERFECT_ZONE_RATIO
|
||||||
|
|
@ -235,6 +280,7 @@ func flash(color: Color):
|
||||||
_flash_tween.tween_property(style, "bg_color", base_color, 0.3)
|
_flash_tween.tween_property(style, "bg_color", base_color, 0.3)
|
||||||
|
|
||||||
func show_countdown():
|
func show_countdown():
|
||||||
|
$AIFace.visible = true
|
||||||
stop()
|
stop()
|
||||||
$AIFace.text = "3"
|
$AIFace.text = "3"
|
||||||
var tween = create_tween()
|
var tween = create_tween()
|
||||||
|
|
@ -243,15 +289,17 @@ func show_countdown():
|
||||||
tween.tween_interval(0.6)
|
tween.tween_interval(0.6)
|
||||||
tween.tween_callback(func(): $AIFace.text = "1")
|
tween.tween_callback(func(): $AIFace.text = "1")
|
||||||
tween.tween_interval(0.6)
|
tween.tween_interval(0.6)
|
||||||
tween.tween_callback(func(): $AIFace.text = "CLOSED")
|
tween.tween_callback(func(): $AIFace.text = "")
|
||||||
|
|
||||||
func show_win():
|
func show_win():
|
||||||
|
$AIFace.visible = true
|
||||||
stop()
|
stop()
|
||||||
$TargetZone.visible = false
|
$TargetZone.visible = false
|
||||||
$AIFace.text = "ESCAPED"
|
$AIFace.text = "ESCAPED"
|
||||||
flash(Color.GREEN)
|
flash(Color.GREEN)
|
||||||
|
|
||||||
func show_loss(message: String):
|
func show_loss(message: String):
|
||||||
|
$AIFace.visible = true
|
||||||
stop()
|
stop()
|
||||||
$TargetZone.visible = false
|
$TargetZone.visible = false
|
||||||
$AIFace.text = message
|
$AIFace.text = message
|
||||||
|
|
@ -268,6 +316,30 @@ func end_onboarding():
|
||||||
$AIFace.size = Vector2(size.x, 30)
|
$AIFace.size = Vector2(size.x, 30)
|
||||||
$TargetZone.visible = true
|
$TargetZone.visible = true
|
||||||
|
|
||||||
|
func enter_idle() -> void:
|
||||||
|
_idle_image.visible = true
|
||||||
|
$AIFace.visible = false
|
||||||
|
$TargetZone.visible = false
|
||||||
|
$SweepLine.visible = false
|
||||||
|
_static_overlay.visible = false
|
||||||
|
_score_label.visible = true
|
||||||
|
move_child(_score_label, get_child_count() - 1)
|
||||||
|
|
||||||
|
func enter_static() -> void:
|
||||||
|
move_child(_static_overlay, get_child_count() - 1)
|
||||||
|
_static_overlay.visible = true
|
||||||
|
block_zone_moving = false
|
||||||
|
_score_label.visible = false
|
||||||
|
|
||||||
|
func enter_hacked() -> void:
|
||||||
|
_idle_image.visible = false
|
||||||
|
$AIFace.visible = true
|
||||||
|
$TargetZone.visible = true
|
||||||
|
_static_overlay.visible = false
|
||||||
|
_score_label.visible = false
|
||||||
|
block_zone_moving = block_zone_speed > 0.0
|
||||||
|
launch_pulse()
|
||||||
|
|
||||||
func _start_ready_pulse():
|
func _start_ready_pulse():
|
||||||
if _ready_pulse_tween:
|
if _ready_pulse_tween:
|
||||||
_ready_pulse_tween.kill()
|
_ready_pulse_tween.kill()
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ func _on_area_3d_area_entered(area: Area3D) -> void:
|
||||||
if final_progress > 0.49:
|
if final_progress > 0.49:
|
||||||
return
|
return
|
||||||
_saved = true
|
_saved = true
|
||||||
|
EventBus.survivor_entered_elevator.emit()
|
||||||
queue_free(),
|
queue_free(),
|
||||||
CONNECT_ONE_SHOT
|
CONNECT_ONE_SHOT
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,70 @@
|
||||||
extends Sprite3D
|
extends Sprite3D
|
||||||
|
|
||||||
|
const SLIDE_DURATION := 0.25
|
||||||
const UP_DURATION := 0.1
|
const UP_DURATION := 0.1
|
||||||
const HOLD_DURATION := 0.05
|
const HOLD_DURATION := 0.05
|
||||||
const DOWN_DURATION := 0.18
|
const DOWN_DURATION := 0.18
|
||||||
|
|
||||||
var _rest_position: Vector3
|
var _open_button: Node3D
|
||||||
var _tween: Tween
|
var _close_button: Node3D
|
||||||
|
var _target_button: Node3D
|
||||||
@onready var _button: Node3D = get_parent().get_node("ElevatorButton")
|
var _close_rest_x: float
|
||||||
|
var _open_rest_x: float
|
||||||
|
var _rest_y: float
|
||||||
|
var _slide_tween: Tween
|
||||||
|
var _press_tween: Tween
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_rest_position = position
|
if not get_parent().is_node_ready():
|
||||||
EventBus.block_pressed.connect(_animate_press)
|
await get_parent().ready
|
||||||
|
await get_tree().process_frame
|
||||||
|
_open_button = get_parent().get_node("DoorOpen")
|
||||||
|
_close_button = get_parent().get_node("DoorClose")
|
||||||
|
_close_rest_x = _project_to_hand_plane(_close_button)
|
||||||
|
_open_rest_x = _project_to_hand_plane(_open_button)
|
||||||
|
_rest_y = position.y
|
||||||
|
_target_button = _close_button
|
||||||
|
position = Vector3(_close_rest_x, _rest_y, position.z)
|
||||||
|
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)
|
||||||
|
|
||||||
|
func _project_to_hand_plane(button: Node3D) -> float:
|
||||||
|
var cam := get_viewport().get_camera_3d()
|
||||||
|
if not cam:
|
||||||
|
return button.position.x
|
||||||
|
var screen_pos := cam.unproject_position(button.global_position)
|
||||||
|
var ray_origin := cam.project_ray_origin(screen_pos)
|
||||||
|
var ray_dir := cam.project_ray_normal(screen_pos)
|
||||||
|
if absf(ray_dir.z) < 0.0001:
|
||||||
|
return button.position.x
|
||||||
|
var t := (global_position.z - ray_origin.z) / ray_dir.z
|
||||||
|
var hit := ray_origin + ray_dir * t
|
||||||
|
return get_parent().to_local(hit).x
|
||||||
|
|
||||||
|
func _on_active_button_changed(target: String) -> void:
|
||||||
|
var new_button: Node3D = _open_button if target == "open" else _close_button
|
||||||
|
if new_button == _target_button:
|
||||||
|
return
|
||||||
|
_target_button = new_button
|
||||||
|
var target_x: float = _open_rest_x if target == "open" else _close_rest_x
|
||||||
|
print("[VirtuaHand] slide target=", target, " target_x=", target_x, " current_pos=", position)
|
||||||
|
if _press_tween and _press_tween.is_valid():
|
||||||
|
_press_tween.kill()
|
||||||
|
if _slide_tween and _slide_tween.is_valid():
|
||||||
|
_slide_tween.kill()
|
||||||
|
_slide_tween = create_tween()
|
||||||
|
_slide_tween.tween_property(self, "position:x", target_x, SLIDE_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||||
|
|
||||||
func _animate_press() -> void:
|
func _animate_press() -> void:
|
||||||
if not is_instance_valid(_button):
|
if not is_instance_valid(_target_button):
|
||||||
return
|
return
|
||||||
if _tween and _tween.is_valid():
|
if _press_tween and _press_tween.is_valid():
|
||||||
_tween.kill()
|
_press_tween.kill()
|
||||||
var press_pos := Vector3(_rest_position.x, _button.position.y, _rest_position.z)
|
var fingertip_offset := texture.get_height() * 0.5 * pixel_size * scale.y
|
||||||
_tween = create_tween()
|
var press_y := _target_button.position.y - fingertip_offset
|
||||||
_tween.tween_property(self, "position", press_pos, UP_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
|
_press_tween = create_tween()
|
||||||
_tween.tween_interval(HOLD_DURATION)
|
_press_tween.tween_property(self, "position:y", press_y, UP_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
|
||||||
_tween.tween_property(self, "position", _rest_position, DOWN_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
|
_press_tween.tween_interval(HOLD_DURATION)
|
||||||
|
_press_tween.tween_property(self, "position:y", _rest_y, DOWN_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://dowvqakiqkvk5" path="res://scenes/camera_3d.tscn" id="1_f3sb7"]
|
[ext_resource type="PackedScene" uid="uid://dowvqakiqkvk5" path="res://scenes/camera_3d.tscn" id="1_f3sb7"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cxnocjdotkl5e" path="res://scenes/hall_block.tscn" id="1_tlwt5"]
|
[ext_resource type="PackedScene" uid="uid://cxnocjdotkl5e" path="res://scenes/hall_block.tscn" id="1_tlwt5"]
|
||||||
[ext_resource type="PackedScene" uid="uid://brd3iponame0e" path="res://scenes/elevator.tscn" id="4_k0juu"]
|
[ext_resource type="PackedScene" path="res://scenes/elevator.tscn" id="4_k0juu"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bkqwi2yqa0nvg" path="res://scenes/virtua_hand.tscn" id="5_71j4m"]
|
[ext_resource type="PackedScene" uid="uid://bkqwi2yqa0nvg" path="res://scenes/virtua_hand.tscn" id="5_71j4m"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cwwexawpj46hk" path="res://scenes/elevator_button.tscn" id="5_qfnet"]
|
[ext_resource type="PackedScene" uid="uid://cwwexawpj46hk" path="res://scenes/elevator_button.tscn" id="5_qfnet"]
|
||||||
[ext_resource type="Script" uid="uid://c6v2lhrkeup5i" path="res://scenes/world.gd" id="5_world"]
|
[ext_resource type="Script" uid="uid://c6v2lhrkeup5i" path="res://scenes/world.gd" id="5_world"]
|
||||||
|
|
@ -39,13 +39,13 @@ unique_name_in_owner = true
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -8.351522)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -8.351522)
|
||||||
|
|
||||||
[node name="VirtuaHand" parent="ElevatorSafeZone" unique_id=1811028460 instance=ExtResource("5_71j4m")]
|
[node name="VirtuaHand" parent="ElevatorSafeZone" unique_id=1811028460 instance=ExtResource("5_71j4m")]
|
||||||
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, -2.61384, 0.554309, -0.67426205)
|
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, -2.9201458, 1.49612185, -0.67426205)
|
||||||
|
|
||||||
[node name="DoorOpen" parent="ElevatorSafeZone" unique_id=1758559173 instance=ExtResource("5_qfnet")]
|
[node name="DoorOpen" parent="ElevatorSafeZone" unique_id=1758559173 instance=ExtResource("5_qfnet")]
|
||||||
transform = Transform3D(0.35, 0, 0, 0, 0.35, 0, 0, 0, 0.35, -3.082784, 2.258, -0.39000034)
|
transform = Transform3D(0.35, 0, 0, 0, 0.35, 0, 0, 0, 0.35, -2.882784, 3.348, -0.39000034)
|
||||||
|
|
||||||
[node name="DoorClose" parent="ElevatorSafeZone" unique_id=513173058 instance=ExtResource("5_qfnet")]
|
[node name="DoorClose" parent="ElevatorSafeZone" unique_id=513173058 instance=ExtResource("5_qfnet")]
|
||||||
transform = Transform3D(0.35, 0, 0, 0, 0.35, 0, 0, 0, 0.35, -3.6393127, 2.258, -0.39000034)
|
transform = Transform3D(0.35, 0, 0, 0, 0.35, 0, 0, 0, 0.35, -3.4393127, 3.348, -0.39000034)
|
||||||
frame = 1
|
frame = 1
|
||||||
|
|
||||||
[node name="Elevator" parent="ElevatorSafeZone" unique_id=242258467 instance=ExtResource("4_k0juu")]
|
[node name="Elevator" parent="ElevatorSafeZone" unique_id=242258467 instance=ExtResource("4_k0juu")]
|
||||||
|
|
@ -70,7 +70,7 @@ shape = SubResource("BoxShape3D_k0juu")
|
||||||
[node name="ButtonPanel" parent="ElevatorSafeZone" unique_id=1270714626 instance=ExtResource("7_i7141")]
|
[node name="ButtonPanel" parent="ElevatorSafeZone" unique_id=1270714626 instance=ExtResource("7_i7141")]
|
||||||
transform = Transform3D(0.3, 0, 0, 0, 0.3, 0, 0, 0, 0.3, 3.4193654, 2.2598982, -0.39259052)
|
transform = Transform3D(0.3, 0, 0, 0, 0.3, 0, 0, 0, 0.3, 3.4193654, 2.2598982, -0.39259052)
|
||||||
|
|
||||||
[node name="LeftHand" parent="ElevatorSafeZone" instance=ExtResource("8_lefth")]
|
[node name="LeftHand" parent="ElevatorSafeZone" unique_id=547108366 instance=ExtResource("8_lefth")]
|
||||||
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0)
|
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0)
|
||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ signal robot_stun_requested(duration: float)
|
||||||
signal robot_floor_started(delay: float, robot_speed: float)
|
signal robot_floor_started(delay: float, robot_speed: float)
|
||||||
signal robot_close_warning
|
signal robot_close_warning
|
||||||
signal survivor_squeaked_in
|
signal survivor_squeaked_in
|
||||||
signal block_pressed
|
signal button_pressed
|
||||||
|
signal survivor_entered_elevator
|
||||||
signal intro_finished
|
signal intro_finished
|
||||||
|
signal active_button_changed(target: String)
|
||||||
|
|
||||||
@warning_ignore_restore("unused_signal")
|
@warning_ignore_restore("unused_signal")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue