Compare commits

...

18 Commits

Author SHA1 Message Date
tiger tiger tiger d5e23b80a0 wip: new action prompt and Interactable 2026-01-15 13:04:52 +01:00
tiger tiger tiger d44336241c fix: sorting function was not according to spec 2026-01-15 11:01:50 +01:00
tiger tiger tiger c736c60cd1 refactor: remove deprecated signals and is_board 2026-01-12 23:00:29 +01:00
tiger tiger tiger 11994f7f27 fix: cardboard can now be opened. 2026-01-12 22:50:49 +01:00
tiger tiger tiger cc04eea1a8 fix: cardboard can now be clicked, still needs a 'play' methid 2026-01-12 22:35:12 +01:00
tiger tiger tiger d29b1d8e78 fix: test manual scroll enable on draven and voice 2026-01-12 21:49:17 +01:00
tiger tiger tiger a91830d28b fix: skip buttons (sorta) work via mouse now. 2026-01-12 21:43:48 +01:00
tiger tiger tiger b64def36e4 fix: misunderstood; reinstated accidentally deleted paragraph length data 2026-01-12 21:00:24 +01:00
tiger tiger tiger 1254024054 chg: removed self-healing warning 2026-01-12 20:57:21 +01:00
tiger tiger tiger c046e2cc4e fix: storyplayables were destroying their own serialized text, meaning everything I touched lost its packedstringarrays. 2026-01-12 20:54:28 +01:00
tiger tiger tiger 69d485286b chore: rename scnees folder to scenes 2026-01-12 20:16:48 +01:00
tiger tiger tiger fa5574128d fix: player crouching on leaving bed. fix: errors in linerenderer due to zero magnitude axis. 2026-01-12 20:00:52 +01:00
tiger tiger tiger e0c87d6905 fix: player controller cleanup 2026-01-12 19:42:14 +01:00
tiger tiger tiger f9e24fd09d fix: climb_volume now automatically crouches the player. 2026-01-12 19:31:11 +01:00
tiger tiger tiger dbfe0cfdd0 refactor: remove deprecated sequencing calls 2026-01-12 19:27:01 +01:00
tiger tiger tiger a0272ec3f2 fix: removed a super annoying half second wait. 2026-01-12 19:24:26 +01:00
tiger tiger tiger a5d1e46466 fix + tests: Player tests for crouching and raiser, raiser now is AnimatableBody3D, player raising and crouching much stabilized. 2026-01-12 19:21:21 +01:00
tiger tiger tiger 57b645b7ad refactor: focus system 2026-01-12 18:39:34 +01:00
52 changed files with 1181 additions and 425 deletions

View File

@ -159,6 +159,8 @@ func corner(surface: SurfaceTool, center:Vector3, start:Vector3, end:Vector3, ca
var angle:float = offset.angle_to(end - center)
for i in range(1, cap_resolution):
if (axis.length() < 0.1): continue #catch null vectors
axis = axis.normalized()
vertex_array[i] = center + offset.rotated(axis, lerp(0.0, angle, float(i) / cap_resolution));
for i in range(1, cap_resolution + 1):

View File

@ -15,7 +15,7 @@ func _ready() -> void:
func start_room():
save_game = State.save_game
%PlayerController.has_stage = true
Scenes.player_enable.emit(true)
on_first_station()
var left_first_station: bool = false

View File

@ -19,7 +19,7 @@ func start_room():
save_room())
%PlayerController.process_mode = Node.PROCESS_MODE_INHERIT
ini_room.emit()
%PlayerController.has_stage = true
Scenes.player_enable.emit(true)
func _ready():
id = State.rooms.ADULTHOOD

View File

@ -921,7 +921,6 @@ size = Vector2i(400, 350)
render_target_update_mode = 4
[node name="CollectableUi" parent="BoardTrigger/UiWrapper/UiSprite/SubViewport" instance=ExtResource("5_ln5pp")]
is_board = true
[node name="HoverDetect" type="CollisionShape3D" parent="BoardTrigger"]
transform = Transform3D(1, 0, 2.9802656e-08, 0, 1, 0, -2.9802656e-08, 0, 1, 0, -0.015731215, 0)
@ -936,4 +935,3 @@ shape = SubResource("CapsuleShape3D_80jyn")
[connection signal="input_event" from="Collectables/AutismMemento/UiWrapper" to="Collectables/AutismMemento/UiWrapper" method="_on_input_event"]
[connection signal="input_event" from="Collectables/UniversityMemento/UiWrapper" to="Collectables/UniversityMemento/UiWrapper" method="_on_input_event"]
[connection signal="input_event" from="BoardTrigger/UiWrapper" to="BoardTrigger/UiWrapper" method="_on_input_event"]
[connection signal="open_board" from="BoardTrigger/UiWrapper/UiSprite/SubViewport/CollectableUi" to="UI/Board" method="claim_focus"]

View File

@ -0,0 +1,25 @@
extends AnimatableBody3D
@onready var start_position:Vector3 = position
var risen:bool = false
var raiser : Tween
func raise(body) -> void:
if body is not PlayerController:
push_warning("Unexpected body in raiser trigger", body)
return
if risen:
position = start_position
if raiser and raiser.is_valid():
raiser.kill()
raiser = create_tween()
raiser.tween_property(self, "position", start_position + Vector3(0,1.1,0), 1)
risen = true
func reset(_discard) -> void:
risen = false
position = start_position

View File

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

View File

@ -1,15 +1 @@
class_name CrouchVolume extends Area3D
func ready():
body_entered.connect(notify_player_entry)
body_exited.connect(notify_player_exit)
func notify_player_entry(body: RigidBody3D):
print_debug("Player entered Crouch area.")
if body is PlayerController:
body.inside_crouch_volume.append(self)
func notify_player_exit(body: RigidBody3D):
if body is PlayerController:
body.inside_crouch_volume.erase(self)
body.crouched = false

View File

@ -1,7 +1,6 @@
class_name InteractiveSprite extends Area3D
@export var interaction_ui: PackedScene = null
@export var is_board: bool = false
@onready var pass_to_actor: = $UiWrapper/UiSprite/SubViewport/CollectableUi
@onready var wrapper := $UiWrapper
@ -42,13 +41,14 @@ func _ready():
%CanvasLayer.add_child(interaction_ui.instantiate())
ui.canvas_layer = %CanvasLayer
# Find and wire the StoryPlayable if not already set
# Find and wire the interaction UI (StoryPlayable or CardBoard)
for child in %CanvasLayer.get_children():
if child is StoryPlayable:
ui.story_playable = child
break
if child is CardBoard:
ui.is_board = true
ui.interaction_ui = child
break
elif child is Control:
ui.interaction_ui = child
break
# Connect playback_finished to restore player control
ui.playback_finished.connect(_on_playback_finished)
@ -78,13 +78,8 @@ func collapse():
revealed = false
func _on_playback_finished():
# Restore player controller control using the room's unique node reference
var player_controller := owner.get_node_or_null("%PlayerController") as PlayerController
if player_controller and "has_stage" in player_controller:
player_controller.has_stage = true
else:
# Fallback: ensure mouse is visible if we can't find player controller
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
# Restore player control via central signal
Scenes.player_enable.emit(true)
func handle(event: InputEvent):
viewport.push_input(event)

View File

@ -511,6 +511,8 @@ grow_vertical = 2
script = ExtResource("1_40hhx")
scene_id = 1
progress = 17.0
story_array = PackedStringArray("Oh, my old mask. I have so many good memories about theatre club. ", "I would stand on my bed for entire afternoons, weeks on end, practicing my lines. Pretending to be on the big stage ... ", "my mom would get mad at me, when she had to call me three or four times for dinner. ", "I just … didn\'t like the interruptions. We both were often mad at each other.", "Dinner was difficult.", "I just couldn\'t bring myself to eat, because I couldn\'t deal with the bread and my mom.", "She was always so worried.", " Lisa, you forgot your homework, Lisa why won\'t you play with the other girls,\"", "\"Lisa why didn\'t Steffi invite you to her birthday, Lisa this, Lisa that.", "But I was fine! She just wouldn\'t listen.", "Yes, I didn\'t do homework, but my teachers didn\'t mind it as much with me ", "- which the other kids wouldn\'t shut up about. But like …", "they also made fun of me reading school books and talking to my teachers during breaks.", "But at least I could fucking talk to teachers and they had stuff to say.", "Mr Thomas probably even understood me better than my own mom.", "He said I was gifted. He said I just didn\'t need homework for good grades.", "And he also made sure to always include extra credits. So my silly slip-ups wouldn\'t get me a B.")
paragraph_lengths = PackedInt32Array(3, 4, 6, 9, 12, 13, 14, 16)
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 2

View File

@ -449,6 +449,8 @@ offset_right = -875.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_o2rjr")
story_array = PackedStringArray("Moonlight trickled down through clouds and twigs as Dräven tapped through the night.", "He had been searching for a while and he knew a special someone must be hiding in the thicket.", "When a familiar smell first led him to a few bronce hairs as fluffy as his tail, he didn\'t think much of it.", "But then he saw paw-prints, that matched his own where he had not been. Would he finally find someone of his kind?", "He was sure of it, as the familiar scent has never been stronger than tonight.", "When suddenly: Was that chatter?", "His wings rustled with joy over the familiar voice and Dräven decided to get a better look.", "A few flaps and leaps brought him up a tree, to get a glimpse of his soon to be friend.", "But all he saw was a fox.", "He didn\'t even want to bother it anymore.", "It would just scream and laugh at his wings of leafs, just like the trees crackled at his paws, that were no roots.", "With a small whimper, Dräven spread his wings, and slid away to at least find comfort by seeing his reflection in the nearby lake.", "It took him a while to notice, how there was a sudden silence when the clouds broke: ", "Northern lights danced through the sky to form wings, that met at a sleek body made of stars and clouds.", "The whole forest held its breath as it stared into eyes of moonlight gazing down.", "Dräven was moved to tears when he gazed back at it. He was sad for the dragon that was of the moon and the stars and the skies.", "It must feel so lost in the universe.", "But his tears were of joy: It was the first time Dräven saw another creature of many kinds.")
paragraph_lengths = PackedInt32Array(2, 4, 5, 6, 8, 9, 12, 14, 17)
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 2
@ -494,7 +496,6 @@ custom_minimum_size = Vector2(0, 700)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 2
mouse_filter = 2
horizontal_scroll_mode = 0
vertical_scroll_mode = 3

View File

@ -823,6 +823,8 @@ grow_vertical = 2
script = ExtResource("1_aby4n")
scene_id = 3
progress = 17.0
story_array = PackedStringArray("Why do i still have this junk lying around? its not like I want to do ju jutsu ever again. I just fucked it.", "I mean I did enjoy it while it lasted. Being able to properly hit people was great.", "It gave me the confidence to intimidate students, that were begging to get folded and - as I only once actually got to do that - it also was a great vent for anger. ", "I mean my tits just about killed me during warmup and the changing room really didn\'t need mirrors - thank you I know my hips are fat and disgusting - but at least there was Lukas.", "He was such a huge nerd. He studied math in his third semester and could talk for hours about his passion.", "Also: my math grades pretty much leaped for my final year in high school thanks to him.", "He also helped me so much with jiu jitsu, as he properly floored me when I slipped up. ", "So Fighting for wins with him was actually rewarding even tho more often than not I ended up having to tap out.", "We also had my first proper kiss. I thought I loved him. But now?", "He was weird that evening. Even more huggy and hyperactive than usual.", "We were under my bed, reading my secret comic stash when I got tired of the floor and told him we should go upstairs.", "We had a play fight on my mattress. I\'ve never seen him fight like this.", "His fingers Curled across my Skin without grabbing me, like he would normally do. And he let me win", "… with this smirk on his face.", "I rolled over exhausted when suddenly he sat on top of me, a pearl of sweat dropped from his nose on my throat.", "He started undoing his shirt.", "Do you have condoms?", "Yes, of course everybody has Why did he ask that?", "I saw my body lying on the bed, getting undressed. I was drifting away, towards the stars.", "My body didn\'t move. It didn\'t say a word when the butterflies tried to escape from its stomach as he kissed it.", "I … observed him from afar. He … didn\'t seem to notice, that I had left.", "That I didn\'t return to kiss him goodbye. That I didn\'t hug him when he went home.", "My hands knocked on my brothers door. He let me lie on his carpet.", "I slowly returned.", "\"How did it go?, Fabian asked.", "\"It was moist”, I said.", "“That usually helps.”", "He laughed awkwardly. I just wanted to also laugh, but curled into a ball and cried.", "It took him a while to say something. “I … you … it\'s fine Lisa. I know it hurts the first time.”", "He gently stroked the back I was curling towards him.", "That was good. He was a sweet angel. Why must he be so bad at comforting?")
paragraph_lengths = PackedInt32Array(3, 6, 8, 9, 10, 12, 15, 16, 17, 18, 20, 22, 24, 25, 26, 27, 28, 29, 31, 32, 33, 32, 31, 30)
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 2

View File

@ -662,7 +662,8 @@ grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_543ki")
scene_id = 2
progress = 17.0
story_array = PackedStringArray("My secret comic stash. I remember playing Clue-Men with the boys.", "I had a voice for every character in that comic. But more often than not I played him: Agent Q.", "Going under the radar, putting in precise work to save the world.", "Not having to deal with being a girl.", "Boys were so much easier. They like cars, bikes, guns and agents.", "They don\'t talk behind your back. They don\'t think everything is about relationships.", "Girls don\'t get that. I knew they talked behind my back about me only “pretending” to like boy stuff, so Id get laid ", "… I mean, maybe they were right?", "Like I won\'t deny I was probably the first girl in my class to see a dick.", "But like - thats what the boys do, right?", "At least it has gotten better after me and Jojo became friends.", "I still remember how that happend. I did a voice acting workshop in art class.", "Being allowed to share my technique in front of everyone was just :D", "I mean next to nobody put in any effort. But Jojo did.", "When our Mr Funny then decided to ape her attempts instead of just minding his own, I pretty much exploded.", "After this, we suddenly were besties. And my class finally started to just leave me be. ", "Maybe because I for once was friends with another girl. Maybe because I scared them. Maybe both.")
paragraph_lengths = PackedInt32Array(1, 2, 5, 7, 9, 10, 13, 14, 16)
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 2
@ -723,12 +724,12 @@ render_target_update_mode = 3
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.21953, 3.52719, 0)
[node name="YouthSpecialMeshesComicBook1" type="MeshInstance3D" parent="PanelContainer/StartFrame/TextureRect/SubViewport/Node3D"]
transform = Transform3D(-0.09237667, -0.07749741, -0.992704, 0.085104756, 0.9927039, -0.08541691, 0.992081, -0.0923743, -0.08510727, -0.045, -0.111, 0.033)
transform = Transform3D(-0.09237667, -0.0774974, -0.992704, 0.085104756, 0.9927038, -0.08541691, 0.992081, -0.092374295, -0.08510727, -0.045, -0.111, 0.033)
mesh = ExtResource("3_ho85h")
skeleton = NodePath("../..")
[node name="YouthSpecialMeshesComicBook2" type="MeshInstance3D" parent="PanelContainer/StartFrame/TextureRect/SubViewport/Node3D"]
transform = Transform3D(-0.4210099, 0.12640645, -0.7739451, 0.15260528, 0.785327, 0.07756861, 0.78067994, -0.085344404, -0.4325408, 0.02, -0.055, -0.02)
transform = Transform3D(-0.4210099, 0.12640648, -0.7739451, 0.15260528, 0.78532714, 0.07756861, 0.78067994, -0.08534441, -0.4325408, 0.02, -0.055, -0.02)
mesh = ExtResource("4_kn83e")
skeleton = NodePath("../..")
@ -775,7 +776,6 @@ custom_minimum_size = Vector2(0, 700)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 2
mouse_filter = 2
horizontal_scroll_mode = 0
vertical_scroll_mode = 3

View File

@ -1,15 +1,17 @@
class_name YouthRoom
extends RoomTemplate
## Used by the stage system when this room takes stage for intro playback
# var has_stage: bool = false # Reminder, do not uncomment, this field is inherited from RoomTemplate!
## Used by the room system when this room becomes active
# var is_active: bool = false # Reminder, do not uncomment, this field is inherited from RoomTemplate!
@onready var board_trigger: InteractiveSprite = %MindBoard
@onready var door_trigger: InteractiveSprite = %Door
@onready var card_board: CardBoard = %Board
@onready var card_picker: CardPicker = %Picker
@onready var ui: Control = %UI
# Is populated by child cardboard instead of onready.
var card_board: CardBoard
func start_room():
%UI.show()
$logic/PlayerController.process_mode = Node.PROCESS_MODE_INHERIT
@ -21,7 +23,7 @@ func start_room():
%LightAnimation.lights_on()
# Give player control after intro (or immediately if repeating)
%PlayerController.has_stage = true
Scenes.player_enable.emit(true)
func _play_intro_scene() -> void:
@ -42,26 +44,29 @@ func _play_intro_scene() -> void:
func get_ready():
await get_tree().process_frame
pull_save_state(State.save_game)
card_board.initialise_from_save(save_game)
card_board.board_completed.connect(func():
save_game.is_childhood_board_complete = true
save_room())
# Scene registration is now handled by youth_room_scene_player
card_picker.cards_picked.connect(card_board.populate_board)
ui.hide()
$sfx/distant_rain.play()
$"sfx/rain on window".play()
self.show()
await get_tree().process_frame
func _ready():
printt(_ready, name)
super._ready()
id = State.rooms.YOUTH
Scenes.scene_finished.connect(_on_scene_finished)
card_picker.cards_picked.connect(card_board.populate_board)
func pull_save_state(save: SaveGame) -> void:
@ -99,4 +104,3 @@ func unload():
func play_chest_animation(_id):
$AnimationPlayer.play("intro")
await $AnimationPlayer.animation_finished
Scenes.continue_sequence(self)

View File

@ -5,6 +5,7 @@
[ext_resource type="PackedScene" uid="uid://mkccbig41bqb" path="res://logic-scenes/player_controller/player_controller.tscn" id="3_foj4y"]
[ext_resource type="AudioStream" uid="uid://bbpo1hu35yer8" path="res://base-environments/youth_room/import/sounds/thunder.mp3" id="3_wcypa"]
[ext_resource type="Script" uid="uid://c281w7earok6w" path="res://base-environments/youth_room/crouch_volume.gd" id="3_x3dlb"]
[ext_resource type="Script" uid="uid://hji6r2e8mcqo" path="res://base-environments/youth_room/climb_volume.gd" id="4_dqyng"]
[ext_resource type="PackedScene" uid="uid://bnskiyx1sksww" path="res://logic-scenes/board/physics-board.tscn" id="4_gyjxx"]
[ext_resource type="AudioStream" uid="uid://1tvopjmo6dp2" path="res://base-environments/youth_room/audio/Azure Studios - mgd-723687677.mp3" id="5_fe1yj"]
[ext_resource type="PackedScene" uid="uid://citwb7f4dl3l1" path="res://thank-you.tscn" id="5_kts6y"]
@ -16,14 +17,14 @@
[ext_resource type="AudioStream" uid="uid://cho5neuxkvpyh" path="res://base-environments/youth_room/audio/Voice Loop.wav" id="10_wwwdq"]
[ext_resource type="Script" uid="uid://c1oub0cs7cph6" path="res://dev-util/stereo-switch.gd" id="10_ypa88"]
[ext_resource type="PackedScene" uid="uid://g2a27jwdapai" path="res://logic-scenes/card_burner/card_burner.tscn" id="11_5bsh1"]
[ext_resource type="PackedScene" uid="uid://c3l8tm8ku50vt" path="res://base-environments/youth_room/scnees/childhood.tscn" id="12_viwxf"]
[ext_resource type="PackedScene" uid="uid://23bshas7sk6h" path="res://base-environments/youth_room/scnees/jui_jutsu.tscn" id="12_x3dlb"]
[ext_resource type="PackedScene" uid="uid://c3l8tm8ku50vt" path="res://base-environments/youth_room/scenes/childhood.tscn" id="12_viwxf"]
[ext_resource type="PackedScene" uid="uid://23bshas7sk6h" path="res://base-environments/youth_room/scenes/jui_jutsu.tscn" id="12_x3dlb"]
[ext_resource type="Script" uid="uid://c3xbkwm4x3es7" path="res://base-environments/youth_room/youth_room_scene_player.gd" id="13_5bsh1"]
[ext_resource type="Texture2D" uid="uid://d005qvnbnishb" path="res://import/interface-elements/cursor_grab.png" id="13_lqj71"]
[ext_resource type="PackedScene" uid="uid://cj1ccdk0686ke" path="res://base-environments/youth_room/scnees/voice_training.tscn" id="13_v3447"]
[ext_resource type="PackedScene" uid="uid://cj1ccdk0686ke" path="res://base-environments/youth_room/scenes/voice_training.tscn" id="13_v3447"]
[ext_resource type="Material" uid="uid://cvm8e6vek3bne" path="res://base-environments/youth_room/import/materials/starlight_shader.material" id="17_ea6x8"]
[ext_resource type="PackedScene" uid="uid://brk4hjdf2x81a" path="res://logic-scenes/card_picker/card_picker.tscn" id="19_a4n1o"]
[ext_resource type="PackedScene" uid="uid://cgwuoc1jfi7w6" path="res://base-environments/youth_room/scnees/draven.tscn" id="19_d3c7p"]
[ext_resource type="PackedScene" uid="uid://cgwuoc1jfi7w6" path="res://base-environments/youth_room/scenes/draven.tscn" id="19_d3c7p"]
[ext_resource type="ArrayMesh" uid="uid://bfc3d4g40n0wy" path="res://logic-scenes/collectable/import/old-mask.res" id="19_jr2bb"]
[ext_resource type="PackedScene" uid="uid://dwtxjvprjyx8p" path="res://base-environments/youth_room/lava-lamp.tscn" id="21_0k2gr"]
[ext_resource type="AudioStream" uid="uid://bghjiqkyehs1p" path="res://base-environments/youth_room/import/sounds/rain and thunder.mp3" id="22_xrkbj"]
@ -92,7 +93,7 @@ size = Vector3(0.851473, 0.8852539, 0.428864)
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_f1g8m"]
radius = 0.156739
height = 1.0
height = 1.527832
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_kewqg"]
radius = 0.787239
@ -110,25 +111,6 @@ height = 3.78697
radius = 1.73984
height = 5.43669
[sub_resource type="GDScript" id="GDScript_uyt24"]
script/source = "extends StaticBody3D
var risen:bool = false
var start_position:Vector3 = position
func raise(entering_player):
if not entering_player.on_crouch_cooldown:
if risen:
position = start_position
var raiser = create_tween()
raiser.tween_property(self, \"position\", position + Vector3(0,1.1,0), 1)
risen = true
func reset(_discard):
risen = false
position = start_position
"
[sub_resource type="BoxShape3D" id="BoxShape3D_gim5a"]
size = Vector3(1.63347, 0.305693, 0.775269)
@ -1534,7 +1516,6 @@ script = ExtResource("1_aitp0")
[node name="PlayerController" parent="logic" groups=["camera_owner"] instance=ExtResource("3_foj4y")]
unique_name_in_owner = true
process_mode = 4
transform = Transform3D(0.686123, 0, 0.727485, 0, 1, 0, -0.727485, 0, 0.686123, 0.63, 0, 0.925)
[node name="Collision" type="Node3D" parent="logic"]
@ -1639,11 +1620,13 @@ shape = SubResource("BoxShape3D_ychlh")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.84538, 0, 0.803611)
[node name="ladder_trigger" type="Area3D" parent="logic/Bed and Ladders"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.3045067, 0)
collision_layer = 2
collision_mask = 2
script = ExtResource("3_x3dlb")
[node name="CollisionShape3D" type="CollisionShape3D" parent="logic/Bed and Ladders/ladder_trigger"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.170028, 0.244833, -0.0455775)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.17002809, 0.508749, -0.045577526)
shape = SubResource("CapsuleShape3D_f1g8m")
[node name="bed_duck" type="Area3D" parent="logic/Bed and Ladders"]
@ -1652,7 +1635,7 @@ collision_mask = 2
script = ExtResource("3_x3dlb")
[node name="CollisionShape3D" type="CollisionShape3D" parent="logic/Bed and Ladders/bed_duck"]
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0.916567, 1.64525, -1.14479)
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0.9784893, 1.2551697, -1.14479)
shape = SubResource("CapsuleShape3D_kewqg")
[node name="bed_enter" type="Area3D" parent="logic/Bed and Ladders"]
@ -1683,9 +1666,9 @@ collision_mask = 2
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0, 0, 0)
shape = SubResource("CapsuleShape3D_n20ff")
[node name="ladder" type="StaticBody3D" parent="logic/Bed and Ladders"]
[node name="ladder" type="AnimatableBody3D" parent="logic/Bed and Ladders"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0699199, 0, -0.082733)
script = SubResource("GDScript_uyt24")
script = ExtResource("4_dqyng")
[node name="CollisionShape3D" type="CollisionShape3D" parent="logic/Bed and Ladders/ladder"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.336261, -0.199846, 0.0549462)
@ -1728,11 +1711,6 @@ unique_name_in_owner = true
visible = false
layout_mode = 1
[node name="Board" parent="logic/UI" instance=ExtResource("4_gyjxx")]
unique_name_in_owner = true
visible = false
layout_mode = 1
[node name="ending" parent="logic/UI" instance=ExtResource("5_kts6y")]
visible = false
layout_mode = 1
@ -2176,6 +2154,7 @@ data = ExtResource("40_ea6x8")
[connection signal="ui_exited" from="logic/PlayerController" to="SceneUI" method="hide"]
[connection signal="body_entered" from="logic/Bed and Ladders/ladder_trigger" to="logic/PlayerController" method="_on_bed_enter"]
[connection signal="body_entered" from="logic/Bed and Ladders/ladder_trigger" to="logic/Bed and Ladders/ladder" method="raise"]
[connection signal="body_exited" from="logic/Bed and Ladders/ladder_trigger" to="logic/Bed and Ladders/ladder" method="reset"]
[connection signal="body_exited" from="logic/Bed and Ladders/bed_duck" to="logic/Bed and Ladders/ladder" method="reset"]
[connection signal="body_entered" from="logic/Bed and Ladders/bed_enter" to="logic/PlayerController" method="_on_bed_enter"]
[connection signal="body_exited" from="logic/Bed and Ladders/reset_failover" to="logic/PlayerController" method="_on_bed_exit"]

View File

@ -181,8 +181,8 @@ func is_out_of_bounds(card: Card, rect: Rect2):
return true
return false
func get_cards_by_scene_id(id: int) -> Array:
var output:Array
func get_cards_by_scene_id(id: int) -> Array[Card]:
var output:Array[Card]
for card_name in source_dicts[id].keys():
var card := card_prefab.instantiate() as Card

View File

@ -3,10 +3,10 @@ class_name RoomTemplate extends Node3D
var initialised: bool = false
var id: State.rooms = State.rooms.NULL
var has_stage: bool:
var is_active: bool:
set(value):
has_stage = value
if has_stage and not initialised:
is_active = value
if is_active and not initialised:
start_room()
@ -19,7 +19,7 @@ func _ready() -> void:
State.current_room = id
func disable()-> void:
has_stage = false
is_active = false
set_process_input(false)
set_process(false)

BIN
src/import/fonts/icon.ttf Normal file

Binary file not shown.

View File

@ -0,0 +1,42 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://qalmecrbkxyp"
path="res://.godot/imported/icon.ttf-471e3d4049bc0d87ff29f9da68806481.fontdata"
[deps]
source_file="res://import/fonts/icon.ttf"
dest_files=["res://.godot/imported/icon.ttf-471e3d4049bc0d87ff29f9da68806481.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=true
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[{
"chars": [],
"glyphs": [],
"name": "New Configuration",
"size": Vector2i(16, 0),
&"variation_embolden": 0.0
}]
language_support={}
script_support={}
opentype_features={}

File diff suppressed because one or more lines are too long

View File

@ -3,19 +3,21 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bxpunr1whf5o1"
path="res://.godot/imported/top_corner.png-2131e6fb02a65e1fd9265d84564f46b9.ctex"
path.s3tc="res://.godot/imported/top_corner.png-2131e6fb02a65e1fd9265d84564f46b9.s3tc.ctex"
path.etc2="res://.godot/imported/top_corner.png-2131e6fb02a65e1fd9265d84564f46b9.etc2.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://import/interface-elements/top_corner.png"
dest_files=["res://.godot/imported/top_corner.png-2131e6fb02a65e1fd9265d84564f46b9.ctex"]
dest_files=["res://.godot/imported/top_corner.png-2131e6fb02a65e1fd9265d84564f46b9.s3tc.ctex", "res://.godot/imported/top_corner.png-2131e6fb02a65e1fd9265d84564f46b9.etc2.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
@ -23,7 +25,7 @@ compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
@ -37,4 +39,4 @@ 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
detect_3d/compress_to=0

View File

@ -25,16 +25,17 @@ var focus_stickies:bool = true:
else:
current_dropzone_id = current_dropzone_id
var has_stage := false:
var focused := false:
set(focus):
var was_focused := focused
if focus:
has_stage = true
focused = true
get_tree().call_group("interactables", "collapse")
current_dropzone_id = 0
current_sticky_note_id = 0
focus_stickies = true
else:
has_stage = false
focused = false
if is_node_ready():
if focus:
process_mode = Node.PROCESS_MODE_INHERIT
@ -43,7 +44,10 @@ var has_stage := false:
for sticky in dropzone.get_children():
if sticky is StickyNote:
sticky.is_dragged = false
visible = has_stage
visible = focused
# Emit closed signal when transitioning from focused to unfocused
if was_focused and not focused:
closed.emit()
@onready var dropzone := $HBoxContainer/dropzone
@ -131,9 +135,13 @@ var last_save_dict: Dictionary
var text_recovery: Dictionary
signal board_completed
signal closed
# Called when the node enters the scene tree for the first time.
func _ready():
print("Board Ready!", self, "room", State.room)
State.room.card_board = self
var size_reference := StickyNotePanel.new()
dropzone_size = get_viewport_rect().size - Vector2(dropzone_padding + size_reference.minimum_size.x, dropzone_padding)
@ -144,7 +152,7 @@ func _ready():
populate_board(["c_comic_heroes", 'c_teasing', "p_agent_q", "p_good_intended"])
populate_board(["c_out_of_world", 'c_confusion', "p_outer_conflict", "p_unique"])
has_stage = has_stage
focused = focused
get_viewport().gui_focus_changed.connect(reclaim_lost_focus)
@ -157,12 +165,12 @@ func _ready():
func reclaim_lost_focus(_thief):
if has_stage:
if focused:
grab_focus()
#func _process(delta):
# # drops dragged area when Mouse is no longer pressed.
# if has_stage and !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) and current_context == DRAG:
# if focused and !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) and current_context == DRAG:
# currently_active_node.is_dragged = false
## Will be used later to spawn Cards and Post-Its and remember them in the dictionary
@ -408,10 +416,10 @@ func insert_area(parent: Control, node: Area2D):
# Takes the inputs for control inputs
func _input(event) -> void:
if not has_stage or not is_instance_valid(currently_active_node): return
if not focused or not is_instance_valid(currently_active_node): return
if event.is_action_pressed("ui_cancel"):
has_stage = false
focused = false
get_viewport().set_input_as_handled()
if event is InputEventMouse:
@ -571,7 +579,14 @@ func on_scene_skipped(i: int):
mementos_collected += i # FIXME: sometimes -1 is passed here, why?
func claim_focus():
has_stage = true
focused = true
## Awaitable function to show the board and wait until user closes it
func play() -> void:
focused = true
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
await closed
func find_first_free_card() -> int:
for i in range(dropzone.get_child_count()):

View File

@ -46,7 +46,6 @@ var transfor_arr: Array[Transform2D] = [
@export var highlighted: bool = false:
set(highlight):
if highlight != highlighted:
printt(self, highlight)
highlighted = highlight
if is_inside_tree() and is_node_ready():
@ -231,7 +230,7 @@ func _move_card():
position += (get_viewport().get_mouse_position() - position) - mouse_offset
func has_sticky_note_attached() -> bool:
return get_child_count(false) > 0
return get_attached_sticky_note() != null
func get_attached_sticky_note() -> StickyNote:
for child in get_children(false):
@ -264,8 +263,7 @@ func attach_sticky_note(sticky_note: StickyNote) -> bool:
return true
func remove_sticky_note() -> StickyNote:
if not is_instance_valid(current_sticky_note): return null
var former_child:StickyNote = current_sticky_note
var former_child:StickyNote = get_attached_sticky_note()
current_sticky_note = null
former_child.reparent(get_parent())
former_child.owner = self.owner

View File

@ -1,9 +1,9 @@
class_name CardBurner extends CenterContainer
var has_stage: bool = false:
var focused: bool = false:
set(focus):
if is_node_ready():
if not focus == has_stage:
if not focus == focused:
if focus:
process_mode = Node.PROCESS_MODE_INHERIT
self.show()
@ -13,7 +13,7 @@ var has_stage: bool = false:
else:
self.hide()
process_mode = Node.PROCESS_MODE_DISABLED
has_stage = focus
focused = focus
@onready var cursor: CandleCursor = %CandleCursor
@onready var ancors: Array[Control] = [%Ancor1, %Ancor2, %Ancor3, %Ancor4]
@ -45,8 +45,6 @@ func burn_cards(_id: int, _repeat: bool = false) -> void:
$AnimationPlayer.play("vanish")
await $AnimationPlayer.animation_finished
Scenes.finish_sequence(self)
signal card_burned
func handle_hover(to_handle: Area2D):
@ -59,7 +57,7 @@ func handle_mouse_button(event: InputEventMouseButton, card: Card):
card.burn_state = Card.burned.BURNING
func _input(event: InputEvent) -> void:
if has_stage:
if focused:
if event.is_action_pressed("ui_up"):
handle_direction_input(Vector2.UP)
elif event.is_action_pressed("ui_down"):

View File

@ -67,7 +67,7 @@ func reset():
for player in anim_players: player.play("reveal")
func fill_card_slots(id: int):
var new_cards := HardCards.get_cards_by_scene_id(id)
var new_cards : Array[Card] = HardCards.get_cards_by_scene_id(id)
for i in range(new_cards.size()):
$cards.get_child(i).remove_child($cards.get_child(i).get_child(1))
@ -208,20 +208,22 @@ func transition():
fill_post_slots()
await anim_players[0].animation_finished
if selection_state != POSTS:
show_posts()
elif selection_state == POSTS_SELECTED:
var out_str:Array[StringName] = []
for card in output:
out_str.append(card.text if card.text != "" else "c_void")
cards_picked.emit(out_str)
selection_state = DONE
Scenes.finish_sequence(self)
func show_posts():
for player:AnimationPlayer in anim_players:
player.play("RESET")
await get_tree().create_timer(.5).timeout
selection_state = POSTS
@ -239,6 +241,7 @@ func pick_cards(id: Scenes.id, repeat: bool):
current_scene_id = id
print_debug("Reached actor %s in sequence %s. Is%s repeating." % [name, Scenes.id.keys()[id], " not" if repeat else ""])
if not repeat:
hide()
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
fill_card_slots(id)
reset()

View File

@ -3,7 +3,6 @@ class_name CollectableUi
@onready var canvas_layer: CanvasLayer = %CanvasLayer
signal open_board
signal exit_room
signal playback_finished
@ -15,14 +14,14 @@ signal scene_skipped(i: int)
## The StoryPlayable to play when this memento is collected.
## Auto-discovered from the owner's %CanvasLayer, or can be set manually.
var story_playable: StoryPlayable
var interaction_ui: Control
@export var scene: Scenes.id = Scenes.id.YOUTH_DRAVEN:
set(id):
scene = id
if is_inside_tree() and not is_board:
if is_inside_tree():
match id:
Scenes.id.YOUTH_DRAVEN:
# FIXME: this explicit translation should not be nessecary
@ -69,24 +68,21 @@ var story_playable: StoryPlayable
is_collected = value
if is_inside_tree():
collected_box.button_pressed = value
if is_collected and not is_board:
if is_collected:
%CollectLabel.text = "listen again"
else:
if not is_board:
%CollectLabel.text = "MementoLabel_collect"
else:
%CollectLabel.text = "find connections"
@onready var collected_box: CheckBox = %CheckBox
@export var title_override: String = "":
set(value):
title_override = value
if is_inside_tree() and not is_board:
if is_inside_tree():
title_label.text = value
@onready var title_label: Label = %TitleLabel
@export var subtitle_override: String = "":
set(value):
subtitle_override = value
if is_inside_tree() and not is_board:
if is_inside_tree():
cn_label.text = value
@onready var cn_label: RichTextLabel = %ContentNoteLabel
@onready var animation_player: AnimationPlayer = %AnimationPlayer
@ -104,28 +100,6 @@ var story_playable: StoryPlayable
return
@export var was_skipped: bool = false
@export var is_board:bool = false:
set(board):
is_board = board
if is_inside_tree():
if board:
if title_override == "": title_label.text = "Mind Board"
collected_box.hide()
# Not room agnostic yet!
if not Engine.is_editor_hint():
match Scenes.get_completed_total():
1:
if subtitle_override == "": cn_label.text = "Find all three Mementos to collect all thoughts."
2:
if subtitle_override == "": cn_label.text = "Find two more Mementos to get all cards."
3:
if subtitle_override == "": cn_label.text = "Find the last remaining Memento."
4:
if subtitle_override == "": cn_label.text = "Use this to find a Frame of Mind."
else:
scene = scene
collected_box.show()
@export var is_exit:bool = false:
set(exit):
is_exit = exit
@ -150,13 +124,12 @@ func _on_context_updated() -> void:
%SkipButton.visible = State.allow_skipping
%SummaryButton.visible = State.provide_summaries
%ReadStory.visible = is_collected
%OptionPrompt.visible = State.allow_skipping or State.provide_summaries or is_collected and not is_board
%OptionsLabel.visible = State.allow_skipping or State.provide_summaries or is_collected and not is_board
%OptionPrompt.visible = State.allow_skipping or State.provide_summaries or is_collected
%OptionsLabel.visible = State.allow_skipping or State.provide_summaries or is_collected
cn_label.visible = true if State.show_content_notes else false
func update_state() -> void:
scene = scene
is_board = is_board
is_exit = is_exit
_on_context_updated()
@ -173,14 +146,11 @@ func try_reveal() -> bool:
func _input(event: InputEvent) -> void:
if not visible: return
if event.is_action_pressed("collect_memento_ui"):
if not is_board:
collect_memento()
get_viewport().set_input_as_handled()
else:
if is_board:
open_board.emit()
if is_exit:
exit_room.emit()
else:
collect_memento()
get_viewport().set_input_as_handled()
elif event.is_action_pressed("option_memento_ui"):
is_expanded = true
get_viewport().set_input_as_handled()
@ -199,14 +169,7 @@ func collect_memento() -> void:
# Hide the collectable UI
vanish()
# Check if we have a story_playable to play
if story_playable == null:
push_warning("CollectableUi for scene %s has no story_playable assigned" % Scenes.id.keys()[scene])
if was_skipped:
scene_skipped.emit(-1)
is_collected = true
playback_finished.emit()
return
# Signal that a scene is starting (for music, etc.)
Scenes.begin_sequence(scene)
@ -219,11 +182,12 @@ func collect_memento() -> void:
canvas_layer.show()
# Play the story
await story_playable.play()
await interaction_ui.play()
if interaction_ui is StoryPlayable:
# Pick the cards
var picker := State.room.get_node("%Picker") as CardPicker
await picker.pick_cards(story_playable.scene_id, false)
await picker.pick_cards(interaction_ui.scene_id, false)
# Hide the CanvasLayer when done
canvas_layer.hide()

View File

@ -3,19 +3,21 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://epjksqlw8frf"
path="res://.godot/imported/decorative_paper.png-25372057da2dbe1a5e49c03959a73421.ctex"
path.s3tc="res://.godot/imported/decorative_paper.png-25372057da2dbe1a5e49c03959a73421.s3tc.ctex"
path.etc2="res://.godot/imported/decorative_paper.png-25372057da2dbe1a5e49c03959a73421.etc2.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://logic-scenes/collectable/decorative_paper.png"
dest_files=["res://.godot/imported/decorative_paper.png-25372057da2dbe1a5e49c03959a73421.ctex"]
dest_files=["res://.godot/imported/decorative_paper.png-25372057da2dbe1a5e49c03959a73421.s3tc.ctex", "res://.godot/imported/decorative_paper.png-25372057da2dbe1a5e49c03959a73421.etc2.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
@ -23,7 +25,7 @@ compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
@ -37,4 +39,4 @@ 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
detect_3d/compress_to=0

View File

@ -0,0 +1,49 @@
class_name Interactable extends Node3D
@export var interaction_ui: PackedScene = null
@onready var view: Node3D = $View
@onready var frame: Sprite3D = $Frame
var shown : bool = false
var hover : bool = false
var collected : bool = false
var tween: Tween = null
func _ready() -> void:
view.scale = Vector3.ZERO
frame.modulate.a = 0
func _process(_delta: float) -> void:
_process_hover()
_process_billboard()
func _process_billboard() -> void:
if shown:
var player_view := State.player_view
look_at(player_view.global_position, Vector3.UP, true)
func _process_hover() -> void:
if hover and not shown:
shown = true
view.scale = Vector3.ZERO
frame.modulate = Color.TRANSPARENT
view.rotation.z = -PI*0.5 # Godot angle wrapping is ... something
if tween: tween.kill()
tween = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
tween.parallel().tween_property(view, "scale", Vector3.ONE, 1.0).set_delay(0.5)
tween.parallel().tween_property(view, "rotation:z", 0, 0.8).set_delay(0.5)
tween.parallel().tween_property(frame, "modulate:a", 1.0, 2.0)
elif not hover and shown:
shown = false
if tween: tween.kill()
tween = create_tween().set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_BACK)
tween.parallel().tween_property(view, "scale", Vector3.ZERO, 0.3)
tween.parallel().tween_property(frame, "modulate:a", 0, 0.6)
func _input(event: InputEvent) -> void:
if hover and shown and event is InputEventMouseButton and event.is_action_pressed("ui_select"):
collected = true

View File

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

View File

@ -0,0 +1,78 @@
[gd_scene load_steps=8 format=3 uid="uid://dreokijo757l1"]
[ext_resource type="Script" uid="uid://bp6s7vhdd6btk" path="res://logic-scenes/interactable/interactable.gd" id="1_ih54h"]
[ext_resource type="Texture2D" uid="uid://d0ucjqi8tx6vt" path="res://import/interface-elements/frame.png" id="2_khok5"]
[ext_resource type="Texture2D" uid="uid://epjksqlw8frf" path="res://logic-scenes/collectable/decorative_paper.png" id="3_cjk23"]
[ext_resource type="FontFile" uid="uid://c084lmfai0iig" path="res://import/fonts/ArchitectsDaughter-Regular.ttf" id="4_dujq2"]
[ext_resource type="FontFile" uid="uid://qalmecrbkxyp" path="res://import/fonts/icon.ttf" id="5_wl31y"]
[ext_resource type="PackedScene" uid="uid://bdnesuqroi7ss" path="res://vfx/collectable_particles.tscn" id="6_a6wx8"]
[sub_resource type="SphereShape3D" id="SphereShape3D_3rbj1"]
radius = 0.3
[node name="Interactable" type="Node3D"]
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, 0, 0, 0)
script = ExtResource("1_ih54h")
metadata/_custom_type_script = "uid://bp6s7vhdd6btk"
[node name="Frame" type="Sprite3D" parent="."]
transform = Transform3D(0.9928179, -0.11963433, 6.278711e-10, 0.11963433, 0.9928179, -1.04587645e-08, 6.27864e-10, 1.0458765e-08, 1, -0.15, 0.05, 0.1)
pixel_size = 0.0005
no_depth_test = true
render_priority = 100
texture = ExtResource("2_khok5")
[node name="View" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0)
[node name="Sprite3D" type="Sprite3D" parent="View"]
pixel_size = 0.0007
no_depth_test = true
render_priority = 50
texture = ExtResource("3_cjk23")
[node name="Caption" type="Label3D" parent="View"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.03170359, 0)
double_sided = false
no_depth_test = true
render_priority = 75
modulate = Color(0.21239993, 0.12440842, 0.055158928, 1)
text = "lorem ipsum
dolor git amend"
font = ExtResource("4_dujq2")
font_size = 10
outline_size = 0
[node name="Icon" type="Label3D" parent="View"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.13325092, -0.084207475, 0)
double_sided = false
no_depth_test = true
render_priority = 75
modulate = Color(0.21239993, 0.12440842, 0.055158928, 1)
text = "xbox_button_a "
font = ExtResource("5_wl31y")
font_size = 10
outline_size = 0
[node name="Prompt" type="Label3D" parent="View/Icon"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0353532, 0, 0)
double_sided = false
no_depth_test = true
render_priority = 75
modulate = Color(0.2901961, 0.18039216, 0.08627451, 0.8901961)
text = "Action Prompt"
font = ExtResource("4_dujq2")
font_size = 8
outline_size = 0
horizontal_alignment = 0
[node name="Area3D" type="Area3D" parent="."]
collision_layer = 16
collision_mask = 16
[node name="CollisionShape3D" type="CollisionShape3D" parent="Area3D"]
shape = SubResource("SphereShape3D_3rbj1")
[node name="collectable_particles" parent="." instance=ExtResource("6_a6wx8")]
[node name="CanvasLayer" type="CanvasLayer" parent="."]

View File

@ -12,14 +12,14 @@ signal emit_thunder
#TODO properly implement animation taking stage, as it should do, disabling processing when it does not have stage.
var max_lines: float = 0
@export var story_array: PackedStringArray = []:
@export var story_array: PackedStringArray:
set(str_array):
story_array = str_array
_rebuild()
@export var paragraph_lengths: PackedInt32Array = [1]
@export var paragraph_lengths: PackedInt32Array
@export var progress: float = 0:
var progress: float = 0:
set(value):
progress = value
if is_node_ready() and not all_text_revealed:
@ -71,13 +71,13 @@ var substring_sizes: Array[int]
func _ready() -> void:
print_debug("StoryPlayable.gd: %s._ready()" % self.name)
hide()
animation_player.play("RESET")
State.settings_changed.connect(func(): story_array = story_array)
skip_control = %SkipControl
if skip_control is SkipControl and not Engine.is_editor_hint():
skip_control.skip.connect(skip_text)
if get_tree().root.get_child(-1) == self:
play()
# Clunky rebuild...
story_array = story_array
progress = progress
@ -123,9 +123,13 @@ func try_scroll():
func play():
print_debug("StoryPlayable.gd: %s.play()" % self.name)
# There's an ugly glitch here.
hide()
animation_player.play("RESET")
await animation_player.animation_finished
# Show ourselves before playing
get_parent().show() # Canvaslayer!
show()
get_parent().show() # Ensure visible Canvaslayer!
scroll_target = 0
@ -139,8 +143,15 @@ func play():
_:
animation_player.queue("en")
if name == "draven":
# Wait and get ready.
await get_tree().process_frame
show()
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
# Don't know how to do this.
#%StoryScroll.grab_focus()
if name == "draven":
await get_tree().process_frame
$AnimationPlayer/Music.play()
@ -180,13 +191,6 @@ var scroll_target: float = 0:
set(value):
scroll_target = clampf(value, 0, label.size.y - scroll_container.size.y+10)
# We no longer run these as tools ~~tiger
#func _process(delta: float) -> void:
# FIXME: maybe change this to has stage?
# if visible and not Engine.is_editor_hint():
# if scroll_container.scroll_vertical != scroll_target:
# scroll_container.scroll_vertical += int((scroll_target-scroll_container.scroll_vertical)*delta*6)
var intro_triggered:= false
func trigger_intro():
if not intro_triggered:

View File

@ -1,33 +1,34 @@
class_name PlayerController extends RigidBody3D
var has_stage: bool = false:
set(on_stage):
print_debug("%s player controller take stage" % "True: " if on_stage else "false")
if has_stage != on_stage:
if on_stage:
has_stage = true
@export var enabled: bool = false:
set(value):
if enabled == value:
return
enabled = value
if is_node_ready():
_apply_enabled_state()
func _apply_enabled_state() -> void:
# Kill any existing jitter tween to prevent stacking
if jitter_tween and jitter_tween.is_valid():
jitter_tween.kill()
if enabled:
camera.make_current()
get_viewport().gui_release_focus()
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
var jitter_tween: Tween = create_tween()
jitter_tween.tween_property(self, "jitter_strength", 1, 1)
if has_entered: emit_signal("ui_exited")
elif has_stage:
await ready
camera.make_current()
jitter_strength = 1
jitter_tween = create_tween()
jitter_tween.tween_property(self, "jitter_strength", 1.0, 1.0)
if has_entered:
ui_exited.emit()
else:
if is_node_ready() and has_stage:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
var jitter_tween: Tween = create_tween()
jitter_tween.tween_property(self, "jitter_strength", 0, 0.5)
if has_entered: emit_signal("ui_exited")
else:
jitter_strength = 0
has_stage = false
print_debug("player controller %s take stage" % "did" if has_stage else "didn't")
sleeping = has_stage
jitter_tween = create_tween()
jitter_tween.tween_property(self, "jitter_strength", 0.0, 0.5)
if has_entered:
ui_exited.emit()
sleeping = not enabled
@export var mouse_sensitivity: Vector2 = Vector2(6, 5)
@ -46,7 +47,9 @@ var has_stage: bool = false:
@export var angular_jitter_speed:Vector3 = Vector3(2, 1, 1)
@export var location_jitter:Vector3 = Vector3(0.05, 0.05, 0.05)
@export var location_jitter_speed:Vector3 = Vector3(2, 0.3, 1)
var jitter_strength: float = 0
var jitter_tween: Tween = null
var loc_noise_spot: Vector3 = Vector3.ZERO
var rot_noise_spot: Vector3 = Vector3.ZERO
@ -57,11 +60,11 @@ var current_mouse_rotation: Vector2 = Vector2.ZERO
var noise: Noise = FastNoiseLite.new()
var crouched:bool = false:
set(set_crouching):
if is_node_ready():
if !is_node_ready(): return
if set_crouching and not crouched:
if State.reduce_motion:# or true:
if State.reduce_motion:
$PlayerAnimationPlayer.play("reduced_crouch")
elif trigger_slow_crouch:# or true:
elif trigger_slow_crouch:
$PlayerAnimationPlayer.play("crouch")
trigger_slow_crouch = false
else:
@ -69,15 +72,14 @@ var crouched:bool = false:
crouched = set_crouching
elif (not set_crouching and crouched) and not crouch_held:
if can_stand_up():
if State.reduce_motion:# or true:
if State.reduce_motion:
$PlayerAnimationPlayer.play("reduced_stand_up")
elif trigger_slow_crouch:# or true:
elif trigger_slow_crouch:
$PlayerAnimationPlayer.play("stand_up")
trigger_slow_crouch = false
else:
$PlayerAnimationPlayer.play("fast_stand_up")
crouched = set_crouching
var on_crouch_cooldown:bool = false
@onready var yaw: Node3D = $Yaw
@onready var pitch: Node3D = $Yaw/Pitch
@ -101,26 +103,36 @@ signal ui_entered
signal ui_exited
func _ready():
State.player = self
State.player_view = %Camera3D
_handle_jitter(0)
pitch.rotation_degrees.x = initial_pitch
ui_prober.area_entered.connect(_on_ray_entered)
ui_prober.area_exited.connect(_on_ray_exited)
$CrouchDetector.area_exited.connect(exit_crouch)
pitch.rotation_degrees.x = initial_pitch
crouched = false
func _process(_delta):
if has_entered:
if focus_ray.get_collider() == null:
pass
#emit_signal("ui_exited")
#dhas_entered = false
if Input.is_action_just_pressed("ui_accept"):
# Pass focus to the collider if it has has_stage property
var collider := focus_ray.get_collider()
if collider and "has_stage" in collider:
has_stage = false
collider.has_stage = true
else:
$CrouchDetector.area_entered.connect(enter_crouch)
$CrouchDetector.area_exited.connect(exit_crouch)
# Connect to central player enable signal.
# Guard for standalone test scenes without autoloads.
if get_node_or_null("/root/Scenes"):
Scenes.player_enable.connect(_on_player_enable)
# Apply exported enabled state now that nodes are ready
_apply_enabled_state()
func _on_player_enable(enable: bool) -> void:
enabled = enable
func _process(_delta) -> void:
if not enabled:
return
if not has_entered:
camera.fov = base_fov / (1 + Input.get_action_raw_strength("zoom_in_controller"))
var has_entered:bool = false:
@ -136,30 +148,25 @@ var has_entered:bool = false:
var delay_passed:bool = false
func _on_ray_entered(_area):
if not has_entered:
var collision_object := focus_ray.get_collider()
if collision_object is InteractiveSprite:
var parent := _area.get_parent() as Interactable
assert(parent != null, "Ray entered non-interactable area!")
printt("ray entered", parent.name, parent)
parent.hover = true
Input.set_default_cursor_shape(Input.CURSOR_POINTING_HAND)
has_entered = collision_object.try_reveal(self)
await get_tree().create_timer(1.0).timeout
if focus_ray.get_collider() is InteractiveSprite:
delay_passed = true
else:
has_entered = false
else:
print_debug("You are standing in front of a wall")
func _on_ray_exited(area):
if delay_passed and area is InteractiveSprite:
has_entered = false
func _on_ray_exited(_area):
var parent := _area.get_parent() as Interactable
printt("ray exited", parent.name, parent)
parent.hover = false
Input.set_default_cursor_shape(Input.CURSOR_ARROW)
func _physics_process(delta:float):
if has_stage or true:
func _physics_process(delta: float):
if enabled:
_handle_movement(delta)
_handle_rotation(delta)
if jitter_strength > 0 and not State.reduce_motion: _handle_jitter(delta)
if jitter_strength > 0 and not State.reduce_motion:
_handle_jitter(delta)
func _handle_movement(delta:float):
var input:Vector2 = Vector2(Input.get_action_strength("player_right") - Input.get_action_strength("player_left"),
@ -228,14 +235,16 @@ func _handle_mouse_input(event:InputEventMouseMotion):
var trigger_slow_crouch: bool = false
var crouch_held: bool = false
var crouch_toggled: bool = false
var cround_start_time: float = 0
var crouch_start_time: float = 0
func _input(event: InputEvent) -> void:
if not enabled:
return
func _input(event:InputEvent) -> void:
if Scenes.current_sequence != -1: return
if has_stage and Scenes.current_sequence == -1 or true:
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
_handle_mouse_input(event)
get_viewport().set_input_as_handled()
if event is InputEventMouseButton and event.pressed:
if Input.is_action_just_pressed("zoom_in_mouse"):
zoomed = true
@ -250,37 +259,23 @@ func _input(event:InputEvent) -> void:
get_viewport().set_input_as_handled()
if event.is_action_pressed("crouch"):
# Remember how long the key is held to tell apart toggle and hold behaviour.
cround_start_time = Time.get_unix_time_from_system()
crouch_start_time = Time.get_unix_time_from_system()
if crouch_toggled:
cround_start_time = 0
#Causes the next release action to 100% stand up the player...
crouch_start_time = 0
else:
crouch_held = true
crouched = true
elif event.is_action_released("crouch"):
crouch_held = false
# Toggles crouch in case the player just pressed the button indicating they want to toggle crouch.
if Time.get_unix_time_from_system() > cround_start_time + 0.5:
if Time.get_unix_time_from_system() > crouch_start_time + 0.5:
if crouched and can_stand_up():
crouch_toggled = false
crouched = false
else:
crouch_toggled = true
func play_scene(_id: int, _repeat: bool):
pass
#if id == Scenes.id.YOUTH_DRAVEN:
# var rotation_tween := create_tween()
func scene_finished(_id, repeat: bool):
if repeat:
has_stage = true
func _on_bed_enter(_body):
if not (crouched or on_crouch_cooldown):
if not crouched:
trigger_slow_crouch = true
crouched = true
@ -289,10 +284,6 @@ func _on_bed_exit(_body):
trigger_slow_crouch = true
crouched = false
on_crouch_cooldown = true
await get_tree().create_timer(1.0).timeout
on_crouch_cooldown = false
var inside_crouch_volume: Array[CrouchVolume] = []
#returns true, if the player character can stand upright.
@ -302,6 +293,11 @@ func can_stand_up() -> bool:
return false
return true
func enter_crouch(body):
if body is CrouchVolume:
crouched = true
func exit_crouch(body):
if body is Area3D:
if body is CrouchVolume:
crouched = false

View File

@ -624,13 +624,14 @@ transform = Transform3D(1, 0, 0, 0, 0.642787, -0.766044, 0, 0.766044, 0.642787,
[node name="Mount" type="Node3D" parent="Yaw/Pitch"]
[node name="Camera3D" type="Camera3D" parent="Yaw/Pitch/Mount"]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.202, 0.157)
cull_mask = 3
current = true
[node name="RayCast3D" type="RayCast3D" parent="Yaw/Pitch/Mount/Camera3D"]
target_position = Vector3(0, 0, -1.5)
collision_mask = 17
collision_mask = 16
collide_with_areas = true
[node name="UiProber" type="Area3D" parent="Yaw/Pitch/Mount/Camera3D"]

View File

@ -88,11 +88,10 @@ func _on_allow_skipping_toggled(button_pressed):
State.allow_skipping = button_pressed
func hide():
get_parent().get_child(0).get_ready()
var child_tween = create_tween()
var child_tween := create_tween()
child_tween.tween_property($CenterContainer, "modulate", Color(1, 1, 1, 0), .5)
await child_tween.finished
var self_tween = create_tween()
var self_tween := create_tween()
self_tween.tween_property(self, "modulate", Color(1, 1, 1, 0), .5)
await self_tween.finished
self.visible = false

View File

@ -13,6 +13,9 @@ signal environment_settings_changed
signal theme_changed
var current_main_theme:Theme = preload("res://logic-scenes/themes/handwriting.theme")
var player : PlayerController
var player_view : Camera3D
func set_theme(new_theme:Theme):
current_main_theme = new_theme
theme_changed.emit(new_theme)
@ -277,7 +280,7 @@ func leave_stage(actor:Object) -> void:
# Currently focused element loses focus, but remains in stack.
func free_focus():
if focus_locked: return false
if stage_list.size() > 0: stage_list.front().has_stage = false
if stage_list.size() > 0: stage_list.front().focused = false
func reset_focus():
stage_list = [stage_list[-1]]

View File

@ -91,8 +91,8 @@ func _load_room(next_path: String) -> bool:
ResourceLoader.THREAD_LOAD_LOADED:
var next_scene := ResourceLoader.load_threaded_get(youth_room_path) as PackedScene
State.room = next_scene.instantiate() as RoomTemplate
await get_tree().process_frame
get_tree().root.add_child(State.room)
await get_tree().process_frame
await State.room.get_ready()
%Loading.stop()
await curtain.hide()

View File

@ -28,10 +28,9 @@ enum id {
ADULT_BURNOUT
}
signal player_enable(enabled: bool);
signal scene_starting(scene_id: id, is_repeating: bool)
signal scene_finished(scene_id: id, is_repeating: bool)
signal player_enable(enabled: bool)
func _ready() -> void:
pass
@ -40,6 +39,9 @@ func _ready() -> void:
func begin_sequence(scene_id: id) -> void:
print_debug(">>> Scenes.begin_sequence(%s)" % id.keys()[scene_id])
# Disable player movement during cutscenes
player_enable.emit(false)
current_sequence = scene_id
started_sequences = started_sequences | (1 << scene_id)
@ -60,21 +62,8 @@ func end_sequence(scene_id: id) -> void:
if current_sequence == scene_id:
current_sequence = -1
# Legacy support - redirects to begin_sequence
func start_sequence(scene_id: id) -> void:
push_warning("start_sequence is deprecated. CollectableUi should call begin_sequence directly.")
begin_sequence(scene_id)
# Legacy support - redirects to end_sequence
func finish_sequence(_actor: Object) -> void:
push_warning("finish_sequence is deprecated. CollectableUi should call end_sequence directly.")
if current_sequence != -1 and current_sequence < id.size():
end_sequence(id.values()[current_sequence])
# Legacy alias
func end_current_sequence() -> void:
if current_sequence != -1 and current_sequence < id.size():
end_sequence(id.values()[current_sequence])
# Re-enable player movement after cutscene
player_enable.emit(true)
# Legacy support - no longer needed
func continue_sequence(_former_actor: Object) -> void:
@ -84,9 +73,6 @@ func continue_sequence(_former_actor: Object) -> void:
func sign_up_for_sequence(_callable: Callable, _sequence_id: id, _index: int = 0) -> void:
push_warning("sign_up_for_sequence is deprecated. CollectableUi now manages playback directly.")
# Legacy support - no longer needed
func register_scene_actor(_scene_id: id, _callable: Callable) -> void:
push_warning("register_scene_actor is deprecated. CollectableUi now manages playback directly.")
func is_sequence_repeating(index: int) -> bool:
return completed_sequences & (1 << index) > 0
@ -95,6 +81,7 @@ func is_sequence_unlocked(index: id) -> bool:
return (1 << int(index)) & enabled_sequences > 0
func get_completed_total() -> int:
# https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
var i: int = completed_sequences - ((completed_sequences >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
i = (i + (i >> 4)) & 0x0F0F0F0F;

View File

@ -10,18 +10,18 @@ func _ready() -> void:
pass_to_actor = get_child(current_tab)
func _on_tab_changed(tab_id: int):
# Transfer has_stage to the new tab's child
# Transfer focused to the new tab's child
for child in get_children():
if "has_stage" in child:
child.has_stage = false
if "focused" in child:
child.focused = false
var new_child = get_child(tab_id)
if "has_stage" in new_child:
new_child.has_stage = true
if "focused" in new_child:
new_child.focused = true
pass_to_actor = new_child
func _on_stage_left():
await get_tree().process_frame
if not pass_to_actor.has_stage:
if not pass_to_actor.focused:
get_parent().vanish()

View File

@ -0,0 +1,344 @@
[gd_scene load_steps=16 format=3 uid="uid://d0x27tf7y5keu"]
[ext_resource type="PackedScene" uid="uid://mkccbig41bqb" path="res://logic-scenes/player_controller/player_controller.tscn" id="1_oayv8"]
[ext_resource type="PackedScene" uid="uid://dreokijo757l1" path="res://logic-scenes/interactable/interactable.tscn" id="2_nl0nc"]
[ext_resource type="PackedScene" uid="uid://bw47g00bi710i" path="res://base-environments/youth_room/youth_room_visuals.tscn" id="5_3rbj1"]
[ext_resource type="PackedScene" uid="uid://dwtxjvprjyx8p" path="res://base-environments/youth_room/lava-lamp.tscn" id="6_ggen3"]
[sub_resource type="PlaneMesh" id="PlaneMesh_cv7g8"]
size = Vector2(50, 50)
[sub_resource type="SphereMesh" id="SphereMesh_7dqkp"]
radius = 5.0
height = 10.0
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_nl0nc"]
[sub_resource type="GDScript" id="GDScript_06xif"]
script/source = "extends SpotLight3D
@export var strength:float = 0.3
@export var speed:float = 5
var noise = FastNoiseLite.new()
var spot:float = randf()
var base_energy = light_energy
@export var lit: bool = false
@onready var secondary_light: OmniLight3D = $desk_secondary
var litnes: float = float(lit)
func _ready():
if not lit: light_energy = 0
func _process(delta):
spot += speed*delta
light_energy = base_energy * (1 + noise.get_noise_1d(spot) * strength) * litnes
secondary_light.light_energy = light_energy/16
func switch_on():
var tween:Tween = create_tween()
tween.tween_property(self, \"litnes\", 1, 10)
func switch_off():
var tween:Tween = create_tween()
tween.tween_property(self, \"litnes\", 0, 1)
"
[sub_resource type="Animation" id="Animation_hqls1"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("OmniLight3D2:light_energy")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [1.0]
}
[sub_resource type="Animation" id="Animation_hxk3n"]
resource_name = "light_up"
length = 10.0
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("OmniLight3D2:light_energy")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 10),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0.0, 1.0]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("desk_light")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"switch_on"
}]
}
[sub_resource type="Animation" id="Animation_wa80i"]
resource_name = "lights_out"
length = 2.0
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("OmniLight3D2:light_energy")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 2),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [1.0, 0.0]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("desk_light")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"switch_off"
}]
}
[sub_resource type="Animation" id="Animation_upogh"]
resource_name = "menu"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("OmniLight3D2:light_energy")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_k8op5"]
_data = {
&"RESET": SubResource("Animation_hqls1"),
&"light_up": SubResource("Animation_hxk3n"),
&"lights_out": SubResource("Animation_wa80i"),
&"menu": SubResource("Animation_upogh")
}
[sub_resource type="GDScript" id="GDScript_dwmnt"]
script/source = "extends AnimationPlayer
func _ready() -> void:
Scenes.scene_finished.connect(lights_on)
Scenes.scene_starting.connect(lights_off)
func lights_off(id: int = -1, _repeat: bool = false):
if id == Scenes.id.YOUTH_VOICE_TRAINING:
await get_tree().create_timer(10).timeout
queue(\"lights_out\")
func lights_on(_id: int = -1, _repeat: bool = false):
queue(\"light_up\")
"
[sub_resource type="GDScript" id="GDScript_2qjvc"]
script/source = "extends SpotLight3D
@export var flicker_strength:float = 0.7
@export var speed:float = 4
var noise = FastNoiseLite.new()
var light_spot:float = randf()
var base_energy = light_energy
func _process(delta):
light_spot += speed*delta
light_energy = base_energy * (1 + noise.get_noise_1d(light_spot) * flicker_strength)
"
[node name="InteractableTests" type="Node"]
[node name="PlayerController" parent="." groups=["camera_owner"] instance=ExtResource("1_oayv8")]
unique_name_in_owner = true
transform = Transform3D(0.686123, 0, 0.727485, 0, 1, 0, -0.727485, 0, 0.686123, 0.63, 0, 0.925)
enabled = true
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0049040318, -0.36189413, 0.003689289)
mesh = SubResource("PlaneMesh_cv7g8")
[node name="OmniLight3D" type="OmniLight3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.221635, 0)
omni_range = 9.435307
[node name="MeshInstance3D2" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5455923, 4.7683716e-07, -5.57273)
mesh = SubResource("SphereMesh_7dqkp")
[node name="StaticBody3D" type="StaticBody3D" parent="."]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("WorldBoundaryShape3D_nl0nc")
[node name="Interactable" parent="." instance=ExtResource("2_nl0nc")]
transform = Transform3D(-1, 0, 1.509958e-07, 0, 1, 0, -1.509958e-07, 0, -1, 0.0017054975, 0.59263134, 2.5304449)
[node name="visuals" parent="." instance=ExtResource("5_3rbj1")]
[node name="Shadow" type="CSGCombiner3D" parent="visuals"]
cast_shadow = 3
calculate_tangents = false
[node name="CSGBox3D" type="CSGBox3D" parent="visuals/Shadow"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.34613, 1.23087, 2.97923)
size = Vector3(5.26758, 2.69583, 0.137207)
[node name="CSGBox3D2" type="CSGBox3D" parent="visuals/Shadow"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.441227, 2.48778, 0.766643)
size = Vector3(3.47876, 0.182022, 4.56238)
[node name="CSGBox3D6" type="CSGBox3D" parent="visuals/Shadow"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.21313, 1.23861, 0.766643)
size = Vector3(0.170044, 2.68037, 4.56238)
[node name="CSGBox3D4" type="CSGBox3D" parent="visuals/Shadow"]
transform = Transform3D(0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, 0, 1, 3.1589, 1.73312, 0.766643)
size = Vector3(2.57013, 0.182022, 4.56238)
[node name="CSGBox3D5" type="CSGBox3D" parent="visuals/Shadow"]
transform = Transform3D(0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, 0, 1, 3.09781, 1.7764, -0.332882)
operation = 2
size = Vector3(1.25306, 0.312046, 0.893661)
[node name="CSGBox3D3" type="CSGBox3D" parent="visuals/Shadow"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.977913, 1.52551, 2.97298)
operation = 2
calculate_tangents = false
flip_faces = true
size = Vector3(1.74371, 1.18614, 0.271545)
[node name="OmniLight3D" type="OmniLight3D" parent="visuals"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.73188, 2.33544, 4.04756)
visible = false
light_energy = 3.0
light_size = 2.0
light_specular = 0.2
light_bake_mode = 0
shadow_enabled = true
shadow_caster_mask = 4293918721
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="visuals"]
transform = Transform3D(0.82167387, 0.44718716, -0.35337743, -0.41379577, 0.8944143, 0.16969287, 0.39195043, 0.0067938697, 0.9199613, 0.866179, 2.88055, 4.51936)
visible = false
light_color = Color(0.81982, 0.935491, 0.980381, 1)
light_energy = 20.0
light_angular_distance = 2.0
light_bake_mode = 0
shadow_enabled = true
directional_shadow_mode = 1
sky_mode = 1
[node name="lights" type="Node3D" parent="visuals"]
[node name="desk_light" type="SpotLight3D" parent="visuals/lights"]
transform = Transform3D(1, 0, 0, 0, 0.30009, 0.953911, 0, -0.953911, 0.30009, -0.599038, 1.39757, 1.64821)
layers = 2
light_color = Color(0.94902, 0.737255, 0.627451, 1)
light_energy = 8.0
light_size = 0.1
shadow_enabled = true
shadow_bias = 0.002
spot_range = 2.47523
spot_angle = 58.1539
spot_angle_attenuation = 0.812252
script = SubResource("GDScript_06xif")
[node name="desk_secondary" type="OmniLight3D" parent="visuals/lights/desk_light"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 2.98023e-08, 1, 0.221273, 0.0654936, -0.292101)
light_color = Color(0.952941, 0.662745, 0.54902, 1)
light_energy = 0.5
light_size = 0.499
light_specular = 0.0
light_cull_mask = 4293918721
shadow_enabled = true
shadow_bias = 0.01
shadow_normal_bias = 5.78
omni_attenuation = 1.51572
[node name="shade_light" type="OmniLight3D" parent="visuals/lights/desk_light"]
light_color = Color(0.94902, 0.737255, 0.627451, 1)
light_energy = 0.5
light_cull_mask = 4293918721
omni_range = 0.147682
[node name="OmniLight3D2" type="OmniLight3D" parent="visuals/lights"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.10614, 0.582081, 0.161548)
light_color = Color(0.894118, 0.87451, 0.686275, 1)
light_size = 0.2
light_specular = 0.1
light_bake_mode = 1
light_cull_mask = 4293918721
shadow_enabled = true
omni_range = 2.0
omni_attenuation = 0.450626
[node name="OmniLight3D4" type="OmniLight3D" parent="visuals/lights"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.47143, 1.6968, -0.548992)
layers = 32769
light_color = Color(0.894118, 0.87451, 0.686275, 1)
light_energy = 0.1
light_size = 0.3
light_specular = 0.0
light_cull_mask = 4293918721
shadow_enabled = true
omni_range = 1.3534
omni_attenuation = 1.41421
[node name="LightAnimation" type="AnimationPlayer" parent="visuals/lights" groups=["scene_actors"]]
unique_name_in_owner = true
libraries = {
&"": SubResource("AnimationLibrary_k8op5")
}
autoplay = "menu"
script = SubResource("GDScript_dwmnt")
[node name="vfx" type="Node3D" parent="visuals"]
[node name="lava-lamp" parent="visuals/vfx" instance=ExtResource("6_ggen3")]
transform = Transform3D(0.488743, 0, -0.872428, 0, 1, 0, 0.872428, 0, 0.488743, 3.1041, 0.962981, 2.21157)
skeleton = NodePath("")
[node name="ReflectionProbe" type="ReflectionProbe" parent="visuals/vfx/lava-lamp"]
transform = Transform3D(0.866853, 0, -0.498563, 0, 1, 0, 0.498563, 0, 0.866853, -0.0356357, 0.0416123, 0.020328)
max_distance = 7.0
size = Vector3(2, 2, 2)
[node name="OmniLight3D" type="SpotLight3D" parent="visuals/vfx/lava-lamp"]
transform = Transform3D(0.9999999, 0, 0, 0, -4.3711395e-08, -1, 0, 0.9999999, -4.3711385e-08, 0.011304617, 0.187006, -0.0021249056)
light_color = Color(0.21945003, 0.45, 0.189, 1)
light_size = 0.05
light_specular = 0.3
light_bake_mode = 1
light_cull_mask = 4293918721
spot_range = 1.5
spot_attenuation = 1.2
spot_angle = 137.58
spot_angle_attenuation = 1.6358016
script = SubResource("GDScript_2qjvc")

View File

@ -1,13 +1,22 @@
[gd_scene load_steps=7 format=3 uid="uid://cjb4gu40l3jah"]
[gd_scene load_steps=17 format=3 uid="uid://bystjfm61jw7t"]
[ext_resource type="Script" uid="uid://c281w7earok6w" path="res://base-environments/youth_room/crouch_volume.gd" id="1_ki2be"]
[ext_resource type="PackedScene" uid="uid://mkccbig41bqb" path="res://logic-scenes/player_controller/player_controller.tscn" id="2_rmwd0"]
[ext_resource type="Script" uid="uid://hji6r2e8mcqo" path="res://base-environments/youth_room/climb_volume.gd" id="3_rmwd0"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ki2be"]
radius = 1.14469
height = 3.78697
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_ki2be"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ki2be"]
transparency = 1
blend_mode = 1
albedo_color = Color(0.48962224, 0.48962224, 0.48962218, 1)
[sub_resource type="CapsuleMesh" id="CapsuleMesh_ki2be"]
material = SubResource("StandardMaterial3D_ki2be")
radius = 1.145
height = 3.787
[sub_resource type="PlaneMesh" id="PlaneMesh_ki2be"]
size = Vector2(50, 50)
@ -16,6 +25,34 @@ size = Vector2(50, 50)
radius = 5.0
height = 10.0
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_ki2be"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_8344t"]
radius = 0.156739
height = 1.0
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_wlply"]
radius = 0.787239
height = 4.07459
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_55bee"]
radius = 1.0352
height = 2.3319
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_317jd"]
radius = 1.14469
height = 3.78697
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_coixd"]
radius = 1.73984
height = 5.43669
[sub_resource type="BoxShape3D" id="BoxShape3D_j8gbq"]
size = Vector3(1.63347, 0.305693, 0.775269)
[sub_resource type="BoxShape3D" id="BoxShape3D_akpqw"]
size = Vector3(0.244565, 1, 0.245859)
[node name="CharacterTests" type="Node3D"]
[node name="bed_crouch" type="Area3D" parent="."]
@ -28,7 +65,9 @@ script = ExtResource("1_ki2be")
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0.107988, 1.56575e-08, -0.358201)
shape = SubResource("CapsuleShape3D_ki2be")
[node name="MeshInstance3D" type="MeshInstance3D" parent="bed_crouch"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="bed_crouch/CollisionShape3D"]
mesh = SubResource("CapsuleMesh_ki2be")
skeleton = NodePath("../..")
[node name="Label3D" type="Label3D" parent="bed_crouch"]
transform = Transform3D(1, 0, 0, 0, 0.27838773, 0.96046877, 0, -0.96046877, 0.27838773, 0, 0.29873586, 0)
@ -36,21 +75,90 @@ text = "CROUCH VOLUME"
[node name="PlayerController" parent="." groups=["camera_owner"] instance=ExtResource("2_rmwd0")]
unique_name_in_owner = true
process_mode = 4
transform = Transform3D(0.686123, 0, 0.727485, 0, 1, 0, -0.727485, 0, 0.686123, 0.63, 0, 0.925)
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
[node name="CollisionShape3D" type="CollisionShape3D" parent="CollisionShape3D"]
shape = SubResource("WorldBoundaryShape3D_ki2be")
enabled = true
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0049040318, -0.008946419, 0.003689289)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0049040318, -0.36189413, 0.003689289)
mesh = SubResource("PlaneMesh_ki2be")
[node name="OmniLight3D" type="OmniLight3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.221635, 0)
omni_range = 9.435307
[node name="MeshInstance3D2" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5455923, 4.7683716e-07, -5.57273)
mesh = SubResource("SphereMesh_ki2be")
[node name="StaticBody3D" type="StaticBody3D" parent="."]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("WorldBoundaryShape3D_ki2be")
[node name="Bed and Ladders" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.1783472, 4.7683716e-07, 5.135357)
[node name="ladder_trigger" type="Area3D" parent="Bed and Ladders"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.19478047, 0, 0)
collision_layer = 2
collision_mask = 2
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bed and Ladders/ladder_trigger"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.170028, 0.244833, -0.0455775)
shape = SubResource("CapsuleShape3D_8344t")
[node name="bed_duck" type="Area3D" parent="Bed and Ladders"]
collision_layer = 2
collision_mask = 2
script = ExtResource("1_ki2be")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bed and Ladders/bed_duck"]
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0.916567, 1.64525, -1.14479)
shape = SubResource("CapsuleShape3D_wlply")
[node name="bed_enter" type="Area3D" parent="Bed and Ladders"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.35717, 0, -0.255744)
collision_layer = 2
collision_mask = 2
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bed and Ladders/bed_enter"]
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0, 0, 0)
shape = SubResource("CapsuleShape3D_55bee")
[node name="bed_crouch" type="Area3D" parent="Bed and Ladders"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.24356, 0, -0.796765)
collision_layer = 2
collision_mask = 2
script = ExtResource("1_ki2be")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bed and Ladders/bed_crouch"]
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0.107988, 1.56575e-08, -0.358201)
shape = SubResource("CapsuleShape3D_317jd")
[node name="reset_failover" type="Area3D" parent="Bed and Ladders"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.24356, 0, -0.531366)
collision_layer = 2
collision_mask = 2
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bed and Ladders/reset_failover"]
transform = Transform3D(0.995341, 0.096419, 0, 4.21461e-09, -4.35077e-08, -1, -0.096419, 0.995341, -4.37114e-08, 0, 0, 0)
shape = SubResource("CapsuleShape3D_coixd")
[node name="ladder" type="AnimatableBody3D" parent="Bed and Ladders"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0699199, 0, -0.082733)
script = ExtResource("3_rmwd0")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Bed and Ladders/ladder"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.336261, -0.199846, 0.0549462)
shape = SubResource("BoxShape3D_j8gbq")
[node name="CollisionShape3D2" type="CollisionShape3D" parent="Bed and Ladders/ladder"]
transform = Transform3D(0.833085, 0, -0.553144, 0, 1, 0, 0.553144, 0, 0.833085, 0.0114179, 0, -0.412249)
shape = SubResource("BoxShape3D_akpqw")
[node name="CollisionShape3D3" type="CollisionShape3D" parent="Bed and Ladders/ladder"]
transform = Transform3D(0.707304, 0, 0.706909, 0, 1, 0, -0.706909, 0, 0.707304, 0.240986, 0, 0.539403)
shape = SubResource("BoxShape3D_akpqw")
[connection signal="body_entered" from="Bed and Ladders/ladder_trigger" to="Bed and Ladders/ladder" method="raise"]
[connection signal="body_exited" from="Bed and Ladders/bed_duck" to="Bed and Ladders/ladder" method="reset"]

View File

@ -0,0 +1,23 @@
[gd_scene load_steps=2 format=3 uid="uid://dhpp80u62rt5t"]
[ext_resource type="PackedScene" uid="uid://cgwuoc1jfi7w6" path="res://base-environments/youth_room/scenes/draven.tscn" id="1_jpubi"]
[node name="StoryTests" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="draven" parent="." instance=ExtResource("1_jpubi")]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -465.0
offset_top = -460.0
offset_right = 465.0
offset_bottom = 460.0

View File

@ -1,11 +1,11 @@
extends Panel
@onready var has_stage = true:
@onready var focused = true:
set(focus):
if focus:
has_stage = State.request_focus(self)
focused = State.request_focus(self)
else:
has_stage = false
focused = false
State.drop_own_focus(self)
func _ready():

View File

@ -4,10 +4,10 @@ class_name AccessibilitySettings
signal changed
signal leave_stage
var has_stage:bool = false:
set(stage):
has_stage = stage
is_active = has_stage
var focused:bool = false:
set(focus):
focused = focus
is_active = focused
# used to override state management in case menu is being used while game is paused.
var is_active:bool = false:
@ -18,7 +18,7 @@ var is_active:bool = false:
leave_stage.emit()
is_active = active
if (is_active and not has_stage) and not get_tree().paused:
if (is_active and not focused) and not get_tree().paused:
push_warning("%s has been set active but not been given the stage while the tree is unpaused!")
@export var is_in_beginning: bool = false

View File

@ -3,12 +3,12 @@ extends VBoxContainer
signal changed
signal leave_stage
var has_stage:bool = false:
set(stage):
has_stage = stage
var focused:bool = false:
set(focus):
focused = focus
if is_node_ready():
%MusicPreview.playing = has_stage
if has_stage:
%MusicPreview.playing = focused
if focused:
music_mute_switch.grab_focus()
@ -86,5 +86,5 @@ func _on_exit_button_pressed() -> void:
State.save_settings()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel") and has_stage:
if event.is_action_pressed("ui_cancel") and focused:
leave_stage.emit()

View File

@ -4,10 +4,10 @@ signal changed
var has_unsaved_changes: bool = false
signal leave_stage
var has_stage:bool = false:
set(stage):
has_stage = stage
if is_node_ready() and has_stage:
var focused:bool = false:
set(focus):
focused = focus
if is_node_ready() and focused:
%ExpandButton.grab_focus()
@export var is_in_beginning: bool = false
@ -47,5 +47,5 @@ func _on_exit_button_pressed() -> void:
leave_stage.emit()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel") and has_stage:
if event.is_action_pressed("ui_cancel") and focused:
leave_stage.emit()

View File

@ -3,10 +3,10 @@ extends VBoxContainer
signal changed
signal leave_stage
var has_stage:bool = false:
set(stage):
has_stage = stage
if is_node_ready() and has_stage:
var focused:bool = false:
set(focus):
focused = focus
if is_node_ready() and focused:
y_switch_gamepad.grab_focus()
var current_music_decay:float = 0
@ -39,5 +39,5 @@ func _on_exit_button_pressed() -> void:
State.save_settings()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel") and has_stage:
if event.is_action_pressed("ui_cancel") and focused:
leave_stage.emit()

View File

@ -2,11 +2,11 @@ extends VBoxContainer
signal leave_stage
var has_stage:bool = false:
set(stage):
has_stage = stage
var focused:bool = false:
set(focus):
focused = focus
if is_node_ready():
if has_stage:
if focused:
steam_optout.grab_focus()
var current_music_decay:float = 0
@ -41,7 +41,7 @@ func _on_exit_button_pressed() -> void:
State.save_settings()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel") and has_stage:
if event.is_action_pressed("ui_cancel") and focused:
leave_stage.emit()
func reset_all_stats():

View File

@ -50,12 +50,7 @@ func _load_games():
func _sort_saves() -> void:
saves.sort_custom(func(a: SaveGame, b: SaveGame) -> int:
if a.last_saved > b.last_saved:
return -1
elif a.last_saved < b.last_saved:
return 1
else:
return 0
return a.last_saved < b.last_saved
)
func _rebuild_buttons() -> void:

View File

@ -5,9 +5,9 @@ signal changed
signal leave_stage
var has_unsaved_changes:= false
var has_stage:bool = false:
set(stage):
has_stage = stage
var focused:bool = false:
set(focus):
focused = focus
match preset_selected:
1: %PerformancePreset.grab_focus()
2: %BalancedPreset.grab_focus()
@ -286,5 +286,5 @@ func select_id_to_window_mode(item_id) -> DisplayServer.WindowMode:
return item_id + 2 if item_id != 0 else 0
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel") and has_stage:
if event.is_action_pressed("ui_cancel") and focused:
_on_exit_button_pressed()

View File

@ -35,7 +35,7 @@ var aborted
var is_auto_proceeding: bool = false:
set(value):
if is_auto_proceeding and not value:
var tween = get_tree().create_tween()
var tween := get_tree().create_tween()
tween.set_ease(Tween.EASE_IN)
tween.set_trans(Tween.TRANS_QUAD)
tween.tween_property(progress, "value", 0.0, 0.3)
@ -112,12 +112,27 @@ func _input(event: InputEvent) -> void:
aborted = true
get_viewport().set_input_as_handled()
func _on_skip_button_button_up():
if not is_auto_proceeding:
pressed = false
time_pressed = 0
progress.value = 0
func _on_skip_button_button_down():
if not (is_auto_proceeding):
pressed = true
if not aborted and is_auto_proceeding:
pressed = false
time_pressed = 0
is_auto_proceeding = false
aborted = true
func _on_skip_button_toggled(button_pressed):
if button_pressed:
pressed = true
else:
pressed = false
time_pressed = 0
func start_proceed_countdown():
text_revealed = true

View File

@ -17,12 +17,12 @@ corner_radius_bottom_left = 5
expand_margin_top = 5.0
expand_margin_bottom = 5.0
[sub_resource type="InputEventKey" id="InputEventKey_7em4l"]
[sub_resource type="InputEventKey" id="InputEventKey_4wxxu"]
device = -1
physical_keycode = 88
unicode = 120
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_hb4jw"]
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_qghsb"]
device = -1
button_index = 2
pressed = true
@ -296,11 +296,13 @@ stretch_mode = 5
script = ExtResource("2_ev8gx")
action = "skip"
icon = 0
events = Array[InputEvent]([null, SubResource("InputEventKey_7em4l"), SubResource("InputEventJoypadButton_hb4jw")])
events = Array[InputEvent]([null, SubResource("InputEventKey_4wxxu"), SubResource("InputEventJoypadButton_qghsb")])
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_f8gbl")
}
[connection signal="button_down" from="SkipButton" to="." method="_on_skip_button_button_down"]
[connection signal="button_up" from="SkipButton" to="." method="_on_skip_button_button_up"]
[connection signal="toggled" from="SkipButton" to="." method="_on_skip_button_toggled"]