diff --git a/assets b/assets index b960791..d98c81e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b96079177daaf913e8b988e493a7bc773ece00a5 +Subproject commit d98c81e159c1c0ec2d794e7afb2607a709f27120 diff --git a/components/door_component.gd b/components/door_component.gd new file mode 100644 index 0000000..d1428f1 --- /dev/null +++ b/components/door_component.gd @@ -0,0 +1,99 @@ +@tool +extends AnimatableBody3D + + +@export_category('Door') +@export +var interactable: bool = true +@export +var autoclose_time: float = 0.0 +@export +var open_sound: AudioStream +@export +var close_sound: AudioStream + + +@onready +var _timer = $Timer +@onready +var _player = $AudioStreamPlayer3D + +var _anim: AnimationPlayer +var _open = false + + +func _get_configuration_warnings() -> PackedStringArray: + var warns = [] + var animation_found = false + var animation_player: AnimationPlayer + for c in get_children(): + if c is AnimationPlayer: + if animation_found: + warns.append('Multiple AnimationPlayers') + animation_found = true + animation_player = c + if not animation_found: + warns.append('Add an AnimationPlayer') + if animation_found and not animation_player.has_animation('open'): + warns.append('AnimationPlayer missing "open" animation') + return warns + + +func _ready(): + for c in get_children(): + if c is AnimationPlayer: + _anim = c + break + + _anim.animation_finished.connect(_on_anim_finished) + _timer.timeout.connect(_on_close_timer) + + +func _toggle_open(): + # Dont allow closing if the timer is running + if not _timer.is_stopped(): + return + + if not _open: + open() + else: + close() + + +func _on_anim_finished(anim_name): + _open = !_open + + +func _on_close_timer(): + if _open: + _toggle_open() + + +func open(): + if open_sound: + _player.stream = open_sound + _player.play() + _anim.play('open') + if autoclose_time != 0.0: + _timer.start(autoclose_time) + + +func close(): + if close_sound: + _player.stream = close_sound + _player.play() + _anim.play_backwards('open') + + +func activate(should_open: bool): + if should_open: + open() + else: + close() + + +func interact(other): + if not interactable: + return + + _toggle_open() diff --git a/components/door_component.tscn b/components/door_component.tscn new file mode 100644 index 0000000..f809ea0 --- /dev/null +++ b/components/door_component.tscn @@ -0,0 +1,11 @@ +[gd_scene load_steps=2 format=3 uid="uid://3s4o76uxcabo"] + +[ext_resource type="Script" path="res://components/door_component.gd" id="1_vtx8n"] + +[node name="DoorComponent" type="AnimatableBody3D"] +script = ExtResource("1_vtx8n") + +[node name="Timer" type="Timer" parent="."] +one_shot = true + +[node name="AudioStreamPlayer3D" type="AudioStreamPlayer3D" parent="."] diff --git a/components/group_trigger_component.gd b/components/group_trigger_component.gd new file mode 100644 index 0000000..3b6e240 --- /dev/null +++ b/components/group_trigger_component.gd @@ -0,0 +1,21 @@ +extends Area3D + +@export var group: String +var activated_lockout = false + + +signal state_changed(pressed: bool) +signal activated_once() + + +func _on_body_entered(body: Node3D) -> void: + if body.is_in_group(group): + state_changed.emit(true) + if not activated_lockout: + activated_lockout = true + activated_once.emit() + + +func _on_body_exited(body: Node3D) -> void: + if body.is_in_group(group): + state_changed.emit(false) diff --git a/components/group_trigger_component.tscn b/components/group_trigger_component.tscn new file mode 100644 index 0000000..4210d85 --- /dev/null +++ b/components/group_trigger_component.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://dnq81gfo5y4oy"] + +[ext_resource type="Script" path="res://components/group_trigger_component.gd" id="1_8jjbb"] + +[node name="GroupTriggerComponent" type="Area3D"] +script = ExtResource("1_8jjbb") + +[connection signal="body_entered" from="." to="." method="_on_body_entered"] +[connection signal="body_exited" from="." to="." method="_on_body_exited"] diff --git a/project.godot b/project.godot index 447bee5..54fc0f9 100644 --- a/project.godot +++ b/project.godot @@ -11,10 +11,16 @@ config_version=5 [application] config/name="fml-avs" -run/main_scene="res://scenes/devworld.tscn" +run/main_scene="res://scenes/level_pool.tscn" config/features=PackedStringArray("4.3", "Forward Plus") config/icon="res://icon.svg" +[global_group] + +players="" +monitors="" +can_hold="" + [input] move_forward={ diff --git a/scenes/devworld.tscn b/scenes/devworld.tscn index 88dd323..886ad5a 100644 --- a/scenes/devworld.tscn +++ b/scenes/devworld.tscn @@ -1,9 +1,8 @@ -[gd_scene load_steps=8 format=3 uid="uid://vv1rwk4sfpch"] +[gd_scene load_steps=7 format=3 uid="uid://vv1rwk4sfpch"] [ext_resource type="PackedScene" uid="uid://cpo6l8pmxj6wo" path="res://assets/maps/devworld.blend" id="1_pj3hd"] [ext_resource type="PackedScene" uid="uid://cy86jyiy6skvk" path="res://scenes/player.tscn" id="2_b2roh"] [ext_resource type="PackedScene" uid="uid://nnxd1djnxech" path="res://scenes/phys_cube.tscn" id="3_8byy4"] -[ext_resource type="PackedScene" path="res://assets/models/general/mirror.blend" id="4_8rfge"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_2mm68"] sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) @@ -46,10 +45,10 @@ enable_shadows = true [node name="devworld" parent="." instance=ExtResource("1_pj3hd")] -[node name="cameratri" parent="devworld/player" index="1"] +[node name="cameratri" parent="devworld/player" index="0"] visible = false -[node name="cameraframe" parent="devworld/player" index="2"] +[node name="cameraframe" parent="devworld/player" index="1"] visible = false [node name="Point" parent="devworld" index="2"] @@ -61,8 +60,4 @@ transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 5.803, [node name="PhysCube" parent="." instance=ExtResource("3_8byy4")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.348621, 0.889988, -0.509634) -[node name="mirror" parent="." instance=ExtResource("4_8rfge")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.21713, 1.33524, 15.4176) - [editable path="devworld"] -[editable path="mirror"] diff --git a/scenes/level_pool.tscn b/scenes/level_pool.tscn new file mode 100644 index 0000000..54d190d --- /dev/null +++ b/scenes/level_pool.tscn @@ -0,0 +1,210 @@ +[gd_scene load_steps=21 format=4 uid="uid://bbqug1s083mdi"] + +[ext_resource type="PackedScene" uid="uid://ci2uamlnv8swy" path="res://assets/maps/levelpool.blend" id="1_cpckw"] +[ext_resource type="PackedScene" uid="uid://cy86jyiy6skvk" path="res://scenes/player.tscn" id="2_eggmh"] +[ext_resource type="PackedScene" uid="uid://3s4o76uxcabo" path="res://components/door_component.tscn" id="3_clecd"] +[ext_resource type="Texture2D" uid="uid://bj7g1cro2pvlp" path="res://assets/textures/dev/tiles01_black.png" id="4_ngwgs"] +[ext_resource type="AudioStream" uid="uid://cieprqff0h2nm" path="res://assets/sounds/door.wav" id="5_yad6d"] +[ext_resource type="PackedScene" uid="uid://dnq81gfo5y4oy" path="res://components/group_trigger_component.tscn" id="6_f2del"] +[ext_resource type="PackedScene" uid="uid://bfv04lp2tbxtd" path="res://scenes/monitor.tscn" id="6_qd2wd"] +[ext_resource type="AudioStream" uid="uid://d20ver6nfndbt" path="res://assets/sounds/dialog/start_dialog.wav" id="7_r1xli"] +[ext_resource type="AudioStream" uid="uid://dbw14jkekqjrb" path="res://assets/sounds/dialog/win_dialog.wav" id="8_u6ajb"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_soh1s"] +resource_name = "tiles01_black" +cull_mode = 2 +albedo_texture = ExtResource("4_ngwgs") + +[sub_resource type="ArrayMesh" id="ArrayMesh_86pmw"] +_surfaces = [{ +"aabb": AABB(3.69908, -2, -6.30092, 2.60184, 0.5, 2.60184), +"format": 34896613377, +"index_count": 96, +"index_data": PackedByteArray("AgAHAAYAAgADAAcAAAAHAAQAAAADAAcAAAAFAAQAAAABAAUAAQAGAAUAAQACAAYACQAPAAsACQANAA8ACgAPAAsACgAOAA8ACgAMAAgACgAOAAwACAANAAkACAAMAA0ABwANAAYABwAPAA0ABwAOAAQABwAPAA4AAgALAAMAAgAJAAsAAAALAAMAAAAKAAsABQAOAAQABQAMAA4ABgAMAAUABgANAAwAAAAIAAEAAAAKAAgAAQAJAAIAAQAIAAkA"), +"name": "tiles01_black", +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 16, +"vertex_data": PackedByteArray("Y+IAAGPiAACbHQAAY+IAAJsdAACbHQAAY+IAAJsdAAD//wAA//8AAAAAAAD//wAAAAAAAAAAAAD//wAAAAAAAJsd//9j4gAAmx3//5sdAABj4v//Y+IAAGPi//+bHQAAAAD/////AAAAAP//AAAAAP///////wAA/////wAAAAA=") +}] +blend_shape_mode = 0 + +[sub_resource type="ArrayMesh" id="ArrayMesh_4vkxm"] +resource_name = "levelpool_Cube_004" +_surfaces = [{ +"aabb": AABB(3.69908, -2, -6.30092, 2.60184, 0.5, 2.60184), +"attribute_data": PackedByteArray("meXQo5nlmeWZ5ZnlLDbQoyw20KMsNpnlLDbQoyw20KMsNiw2meXQo5nl0KOZ5Sw2meUsNpnl0KP//9Cj///////////HG9CjxxvQo8cb///HG9CjxxvQo8cbxxv//9Cj///Qo///xxv//8cb///Qoyw29XcsNpnlLDb1dyw29XcsNiw2meX1d5nl9XeZ5ZnlmeWZ5Sw29XeZ5fV3meUsNpnlLDaZ5fV3xxv1d8cb///HG/V3xxv1d8cbxxv///V3///1d///////////xxv1d///9Xf//8cb///HG///9Xc="), +"format": 34896613399, +"index_count": 96, +"index_data": PackedByteArray("CAAaABYACAAMABoAAQAZAA8AAQALABkAAgATABAAAgAFABMABQAWABMABQAIABYAIAA1ACcAIAAuADUAJAA2ACgAJAAyADYAIwArAB0AIwAxACsAHQAuACAAHQArAC4AGAAtABUAGAA0AC0AGwAzABEAGwA3ADMABwAmAAoABwAfACYAAwApAA0AAwAlACkAEgAwAA4AEgAqADAAFwAsABQAFwAvACwAAAAcAAQAAAAiABwABgAhAAkABgAeACEA"), +"material": SubResource("StandardMaterial3D_soh1s"), +"name": "tiles01_black", +"primitive": 3, +"uv_scale": Vector4(9.21532, 9.21532, 0, 0), +"vertex_count": 56, +"vertex_data": PackedByteArray("Y+IAAGPiAABj4gAAY+L/v2PiAABj4v8/Y+IAAGPi/7+bHQAAY+IAAJsdAABj4v8/mx0AAGPi/7+bHQAAmx0AgJsdAACbHf8/mx0AAJsd/79j4gAAmx0AgGPiAACbHf+/Y+IAAJsd/z9j4gAAmx3/v///AAD//wCA//8AAP///7///wAA////P///AAD//wAAAAAAAP//AIAAAAAA////PwAAAAD//wAAAAAAAAAAAAAAAAAAAAD/PwAAAAAAAAAA//8AAAAAAAD//wAAAAD/v///AAAAAP8///8AAAAAAACbHf//Y+IAAJsd//9j4v+/mx3//2Pi/7+bHf//mx0AgJsd//+bHf+/mx3//5sd/79j4v//Y+IAAGPi//9j4v+/Y+L//2Pi/z9j4v//Y+L/v2Pi//+bHQCAY+L//5sd/79j4v//mx3/P2Pi//+bHf+/AAD/////AIAAAP//////vwAA/////wAAAAD//wAAAAAAAP//AAD/vwAA//8AAAAA////////AID/////////v/////////8/////////AAD/////AAAAAP////8AAP+//////wAA/z//////AAAAAP///3////9/AAD/f/9/AAD///9/AAD/f/9/AAD/f///AAD/f/9/AAD/f///////fwAA/3//fwAA/3///////38AAP9//z//f/9///8AAP9//z//f////38AAP9//z//f////3////9/AAD/f/8//3////9/////f/9/AAD/f///////f/9/AAD///9/////fwAA/3//fwAA/3///////38AAP9//38AAP9///////9//z//f////3////9//z//f/9///////9/AAD/f/8//3////9/////fwAA/3//P/9/") +}] +blend_shape_mode = 0 +shadow_mesh = SubResource("ArrayMesh_86pmw") + +[sub_resource type="BoxShape3D" id="BoxShape3D_yaaik"] +size = Vector3(4, 5, 1) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gs8og"] +albedo_texture = ExtResource("4_ngwgs") + +[sub_resource type="BoxMesh" id="BoxMesh_ytxur"] +size = Vector3(4, 5, 1) + +[sub_resource type="Animation" id="Animation_lexij"] +resource_name = "open" +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("CollisionShape3D:position:y") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(0, -0.25, 0, 0.5, 0, 4, -0.5, 0, 0.25, 0), +"times": PackedFloat32Array(0, 1) +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_prvv0"] +_data = { +"open": SubResource("Animation_lexij") +} + +[sub_resource type="BoxShape3D" id="BoxShape3D_epqy0"] +size = Vector3(0.3, 0.5, 2.3) + +[sub_resource type="BoxShape3D" id="BoxShape3D_dsbsn"] +size = Vector3(2, 2, 2) + +[sub_resource type="BoxShape3D" id="BoxShape3D_vryv4"] +size = Vector3(4, 4, 1) + +[node name="LevelPool" type="Node3D"] + +[node name="OmniLight3D" type="OmniLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 0) +light_energy = 9.0 +shadow_enabled = true +shadow_blur = 1.695 +omni_range = 162.191 + +[node name="levelpool" parent="." instance=ExtResource("1_cpckw")] + +[node name="Light" parent="levelpool" index="1"] +visible = false +light_energy = 9.0 +shadow_enabled = true +omni_range = 34.554 + +[node name="player" parent="levelpool" index="2"] +visible = false + +[node name="holerim" parent="levelpool" index="4"] +mesh = SubResource("ArrayMesh_4vkxm") + +[node name="Cube_003" parent="levelpool" index="10"] +visible = false + +[node name="Cube_004" parent="levelpool" index="11"] +visible = false + +[node name="monitor012" parent="levelpool" index="12"] +visible = false + +[node name="CollisionShape3D" parent="levelpool/monitor012/@StaticBody3D@17259" index="0"] +disabled = true + +[node name="Player" parent="." instance=ExtResource("2_eggmh")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.012538, 19) + +[node name="EntranceDoor" parent="." instance=ExtResource("3_clecd")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, 11.5) +open_sound = ExtResource("5_yad6d") +close_sound = ExtResource("5_yad6d") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="EntranceDoor"] +shape = SubResource("BoxShape3D_yaaik") + +[node name="CSGMesh3D" type="CSGMesh3D" parent="EntranceDoor/CollisionShape3D"] +material_override = SubResource("StandardMaterial3D_gs8og") +mesh = SubResource("BoxMesh_ytxur") + +[node name="AnimationPlayer" type="AnimationPlayer" parent="EntranceDoor"] +libraries = { +"": SubResource("AnimationLibrary_prvv0") +} + +[node name="ExitDoor" parent="." instance=ExtResource("3_clecd")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -11.5) +interactable = false +open_sound = ExtResource("5_yad6d") +close_sound = ExtResource("5_yad6d") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="ExitDoor"] +shape = SubResource("BoxShape3D_yaaik") + +[node name="CSGMesh3D" type="CSGMesh3D" parent="ExitDoor/CollisionShape3D"] +material_override = SubResource("StandardMaterial3D_gs8og") +mesh = SubResource("BoxMesh_ytxur") + +[node name="AnimationPlayer" type="AnimationPlayer" parent="ExitDoor"] +libraries = { +"": SubResource("AnimationLibrary_prvv0") +} + +[node name="Monitor" parent="." instance=ExtResource("6_qd2wd")] +transform = Transform3D(-0.877007, 0, -0.480477, 0, 1, 0, 0.480477, 0, -0.877007, -4.23016, 0.344398, -2.70049) +script = null + +[node name="HoleRim" type="StaticBody3D" parent="."] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="HoleRim"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.85, 0.25, -4.85) +shape = SubResource("BoxShape3D_epqy0") + +[node name="CollisionShape3D2" type="CollisionShape3D" parent="HoleRim"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.15, 0.25, -5.15) +shape = SubResource("BoxShape3D_epqy0") + +[node name="CollisionShape3D3" type="CollisionShape3D" parent="HoleRim"] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 5.15, 0.25, -3.85) +shape = SubResource("BoxShape3D_epqy0") + +[node name="CollisionShape3D4" type="CollisionShape3D" parent="HoleRim"] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 4.85, 0.25, -6.15) +shape = SubResource("BoxShape3D_epqy0") + +[node name="WinBox" parent="." instance=ExtResource("6_f2del")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, -1, -5) +group = "monitors" + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WinBox"] +shape = SubResource("BoxShape3D_dsbsn") + +[node name="DialogTrigger" parent="." instance=ExtResource("6_f2del")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.05, 10.5) +group = "players" + +[node name="CollisionShape3D" type="CollisionShape3D" parent="DialogTrigger"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0022583, -0.0446777, 0) +shape = SubResource("BoxShape3D_vryv4") + +[node name="Kreb" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.70194, 1.2497, 6.87629) + +[node name="StartDialog" type="AudioStreamPlayer3D" parent="Kreb"] +stream = ExtResource("7_r1xli") + +[node name="WinDialog" type="AudioStreamPlayer3D" parent="Kreb"] +stream = ExtResource("8_u6ajb") + +[connection signal="activated_once" from="WinBox" to="Kreb/WinDialog" method="play" binds= [0.0]] +[connection signal="activated_once" from="DialogTrigger" to="Kreb/StartDialog" method="play" binds= [0]] +[connection signal="finished" from="Kreb/WinDialog" to="ExitDoor" method="open"] + +[editable path="levelpool"] diff --git a/scenes/monitor.tscn b/scenes/monitor.tscn new file mode 100644 index 0000000..fe301a6 --- /dev/null +++ b/scenes/monitor.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://bfv04lp2tbxtd"] + +[ext_resource type="PackedScene" uid="uid://duuedavsf44c7" path="res://assets/models/general/monitor01.blend" id="1_6l6n4"] + +[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_tfpjr"] +points = PackedVector3Array(-12, 6.00235, -12, -11.0016, 0, -12, -12, 6.00235, -7.99922, -12, 30, -12, -11.0016, 0, 12, 10.9992, 0, -12, -12, 30, -7.99922, 12, 30, -12, 10.9992, 0, 12, -11.0016, 3.00117, 12, 12, 6.00235, -12, 12, 30, -7.99922, -8.00157, 25.9975, 12, 10.9992, 3.00117, 12, 12, 6.00235, -7.99922, 7.99922, 25.9975, 12) + +[sub_resource type="BoxShape3D" id="BoxShape3D_wfrja"] +size = Vector3(0.6, 0.75, 0.6) + +[node name="Monitor" type="RigidBody3D" groups=["can_hold", "monitors"]] + +[node name="monitor012" parent="." instance=ExtResource("1_6l6n4")] + +[node name="@StaticBody3D@17265" parent="monitor012" index="1"] +visible = false + +[node name="CollisionShape3D" parent="monitor012/@StaticBody3D@17265" index="0"] +shape = SubResource("ConvexPolygonShape3D_tfpjr") +disabled = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="." groups=["can_hold"]] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.374, 0) +shape = SubResource("BoxShape3D_wfrja") + +[editable path="monitor012"] diff --git a/scenes/player.tscn b/scenes/player.tscn index 226f3be..ef30738 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -6,7 +6,7 @@ [sub_resource type="CapsuleMesh" id="CapsuleMesh_muavk"] -[node name="Player" type="CharacterBody3D"] +[node name="Player" type="CharacterBody3D" groups=["players"]] script = ExtResource("1_ocinr") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] @@ -22,6 +22,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) fov = 90.0 [node name="Ball" type="CSGSphere3D" parent="."] +visible = false radius = 0.1 [node name="Flashlight" type="SpotLight3D" parent="."] @@ -31,3 +32,14 @@ shadow_enabled = true distance_fade_enabled = true spot_range = 23.178 spot_angle = 40.14 + +[node name="CenterContainer" type="CenterContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="ColorRect" type="ColorRect" parent="CenterContainer"] +custom_minimum_size = Vector2(10, 10) +layout_mode = 2 diff --git a/scripts/physics_object.gd b/scripts/physics_object.gd deleted file mode 100644 index dd981b7..0000000 --- a/scripts/physics_object.gd +++ /dev/null @@ -1,25 +0,0 @@ -extends RigidBody3D -# -#const QUAKE = 0.0625 / 2 -#const g = -800 * QUAKE -# -#@export -#var push_force = 400 -#@export -#var max_velocity: float = 1000.0 -# -# -##var is_held = false -##var target_velocity: Vector3 = Vector3(0, 0, 0) -## -## -##func _physics_process(delta): - ##if is_held: - ##linear_velocity = target_velocity * delta - ##else: - ##linear_velocity.y += g * delta -# -# -func can_hold(player): - return true - diff --git a/scripts/player.gd b/scripts/player.gd index b28cdf2..60161c9 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -14,6 +14,8 @@ const SIDE_SPEED = 350 * QUAKE const UP_SPEED = 270 * QUAKE const JUMP_SPEED = 270 * QUAKE +@export +var interact_range: float = 5.0 @export var hold_force = 400 @export @@ -34,183 +36,183 @@ var _flashlight: SpotLight3D = $Flashlight var _paused = false var _noclip = false -var _held_object = null +var _held_object: Object +var _held_object_distance: float func _ready(): - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) func _process(_delta): - # Do this on the render tick so it doesnt jitter at higher FPS - _ball.global_position = _camera.global_position - _camera.global_transform.basis.z * 2.0 + # Do this on the render tick so it doesnt jitter at higher FPS + _ball.global_position = _camera.global_position - _camera.global_transform.basis.z * interact_range func _physics_process(delta): - # Shamelessly stolen code from quake :) + # Shamelessly stolen code from quake :) - var fmove = 0.0 - var smove = 0.0 - var upmove = 0.0 + var fmove = 0.0 + var smove = 0.0 + var upmove = 0.0 - if Input.is_action_pressed("move_forward"): - fmove += -FORWARD_SPEED - if Input.is_action_pressed("move_backward"): - fmove += FORWARD_SPEED - if Input.is_action_pressed("move_left"): - smove += -SIDE_SPEED - if Input.is_action_pressed("move_right"): - smove += SIDE_SPEED - #if Input.is_action_pressed("up"): - # upmove += UP_SPEED - if Input.is_action_pressed("run"): - fmove *= 2.0 - smove *= 2.0 + if Input.is_action_pressed("move_forward"): + fmove += -FORWARD_SPEED + if Input.is_action_pressed("move_backward"): + fmove += FORWARD_SPEED + if Input.is_action_pressed("move_left"): + smove += -SIDE_SPEED + if Input.is_action_pressed("move_right"): + smove += SIDE_SPEED + #if Input.is_action_pressed("up"): + # upmove += UP_SPEED + if Input.is_action_pressed("run"): + fmove *= 2.0 + smove *= 2.0 - var wishvel = Vector3() - var cam_xform: Transform3D = _camera.get_global_transform() - var cam_basis: Basis = cam_xform.basis + var wishvel = Vector3() - wishvel = cam_basis.z * fmove + cam_basis.x * smove + if _noclip: + wishvel = _camera.global_basis.z * fmove + _camera.global_basis.x * smove + else: + wishvel = basis.z * fmove + basis.x * smove - if _noclip: - wishvel.y += upmove + if _noclip: + wishvel.y += upmove - var wishdir = wishvel.normalized() - var wishspeed = wishvel.length() + var wishdir = wishvel.normalized() + var wishspeed = wishvel.length() - if wishspeed > MAX_SPEED: - wishvel *= MAX_SPEED / wishspeed - wishspeed = MAX_SPEED + if wishspeed > MAX_SPEED: + wishvel *= MAX_SPEED / wishspeed + wishspeed = MAX_SPEED - if Input.is_action_just_pressed("jump") and is_on_floor(): - velocity.y += JUMP_SPEED + if Input.is_action_just_pressed("jump") and is_on_floor(): + velocity.y += JUMP_SPEED - var vel = velocity - if _noclip: - vel = wishvel * 2 - elif is_on_floor(): - vel = _apply_friction(vel, delta) - vel = _apply_accel(vel, wishdir, wishspeed, delta) - else: - vel = _apply_air_accel(vel, wishvel, wishspeed, delta) + var vel = velocity + if _noclip: + vel = wishvel * 2 + elif is_on_floor(): + vel = _apply_friction(vel, delta) + vel = _apply_accel(vel, wishdir, wishspeed, delta) + else: + vel = _apply_air_accel(vel, wishvel, wishspeed, delta) - if not _noclip and not is_on_floor(): - vel.y += g * delta + if not _noclip and not is_on_floor(): + vel.y += g * delta - velocity = vel - move_and_slide() - - if _held_object: - _apply_holding_force(delta) + velocity = vel + move_and_slide() + + if _held_object: + _apply_holding_force(delta) func _apply_friction(vel: Vector3, delta: float): - var speed = sqrt(vel.x ** 2 + vel.z ** 2) - if(speed == 0.0): return vel + var speed = sqrt(vel.x ** 2 + vel.z ** 2) + if(speed == 0.0): return vel - # TODO: edge detect friction? - var friction = FRICTION + # TODO: edge detect friction? + var friction = FRICTION - var control = 0.0 - if speed < STOP_SPEED: - control = STOP_SPEED - else: - control = speed + var control = 0.0 + if speed < STOP_SPEED: + control = STOP_SPEED + else: + control = speed - var newspeed = speed - delta * control * friction + var newspeed = speed - delta * control * friction - if newspeed < 0.0: - newspeed = 0.0 - else: - newspeed /= speed + if newspeed < 0.0: + newspeed = 0.0 + else: + newspeed /= speed - return vel * newspeed + return vel * newspeed func _apply_accel(vel: Vector3, wishdir: Vector3, wishspeed: float, delta: float): - var currentspeed = vel.dot(wishdir) - var addspeed = wishspeed - currentspeed - if addspeed <= 0.0: - return vel + var currentspeed = vel.dot(wishdir) + var addspeed = wishspeed - currentspeed + if addspeed <= 0.0: + return vel - var accelspeed = ACCEL * delta * wishspeed - if accelspeed > addspeed: - accelspeed = addspeed + var accelspeed = ACCEL * delta * wishspeed + if accelspeed > addspeed: + accelspeed = addspeed - return vel + accelspeed * wishdir + return vel + accelspeed * wishdir func _apply_air_accel(vel: Vector3, wishvel: Vector3, wishspeed: float, delta: float): - var wishveloc = wishvel.normalized() - var wishspd = wishvel.length() + var wishveloc = wishvel.normalized() + var wishspd = wishvel.length() - if wishspd > MAX_AIR_SPEED: - wishspd = MAX_AIR_SPEED + if wishspd > MAX_AIR_SPEED: + wishspd = MAX_AIR_SPEED - var currentspeed = vel.dot(wishveloc) - var addspeed = wishspd - currentspeed - if addspeed <= 0: - return vel + var currentspeed = vel.dot(wishveloc) + var addspeed = wishspd - currentspeed + if addspeed <= 0: + return vel - var accelspeed = AIR_ACCEL * wishspeed * delta - if accelspeed > addspeed: - accelspeed = addspeed + var accelspeed = AIR_ACCEL * wishspeed * delta + if accelspeed > addspeed: + accelspeed = addspeed - return vel + accelspeed * wishveloc + return vel + accelspeed * wishveloc func _apply_holding_force(delta): - var delta_position = _ball.global_position - _held_object.global_position - var move_speed = min(delta_position.length() * hold_force, max_hold_velocity) - _held_object.linear_velocity = delta_position.normalized() * move_speed * delta + var hold_point = _camera.global_position - _camera.global_transform.basis.z * _held_object_distance + var delta_position = hold_point - _held_object.global_position + var move_speed = min(delta_position.length() * hold_force, max_hold_velocity) + _held_object.linear_velocity = delta_position.normalized() * move_speed * delta func _input(event): - if event.is_action_pressed("pause"): - _paused = not _paused - if _paused: - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) - else: - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + if event.is_action_pressed("pause"): + _paused = not _paused + if _paused: + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + else: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - if _paused: return + if _paused: return - if event.is_action_pressed('noclip'): - _noclip = not _noclip - if _noclip: - _collider.disabled = true - else: - _collider.disabled = false - - if event.is_action_pressed('flashlight'): - _flashlight.visible = not _flashlight.visible + if event.is_action_pressed('noclip'): + _noclip = not _noclip + if _noclip: + _collider.disabled = true + else: + _collider.disabled = false - # Camera - if event is InputEventMouseMotion: - rotation.y += -event.relative.x * 0.005 - _camera.rotation.x += -event.relative.y * 0.005 - _camera.rotation.x = clamp(_camera.rotation.x, deg_to_rad(-90), deg_to_rad(90)) - - # Rotate flashlight - _flashlight.rotation.x = _camera.rotation.x + if event.is_action_pressed('flashlight'): + _flashlight.visible = not _flashlight.visible - if event.is_action_pressed("interact"): - # Handle dropping things - if _held_object: - #_held_object.drop() - _held_object = null - return - - var space_state = get_world_3d().direct_space_state - # use global coordinates, not local to node - var query = PhysicsRayQueryParameters3D.create(_camera.global_position, _ball.global_position) - # Don't collide with ourselves - query.exclude = [self] - var result = space_state.intersect_ray(query) - if result.has('collider'): - print(result) - var other: Node3D = result.collider - if other.has_method('interact'): - other.interact(self) - if other.has_method('can_hold'): - print('Object') - if other.can_hold(self): - print('Can Hold') - _held_object = other - print(_held_object) + # Camera + if event is InputEventMouseMotion: + rotation.y += -event.relative.x * 0.005 + _camera.rotation.x += -event.relative.y * 0.005 + _camera.rotation.x = clamp(_camera.rotation.x, deg_to_rad(-90), deg_to_rad(90)) + + # Rotate flashlight + _flashlight.rotation.x = _camera.rotation.x + + if event.is_action_pressed("interact"): + # Handle dropping things + if _held_object: + #_held_object.drop() + _held_object = null + return + + var space_state = get_world_3d().direct_space_state + # use global coordinates, not local to node + var ray_end = _camera.global_position - _camera.global_transform.basis.z * interact_range + var query = PhysicsRayQueryParameters3D.create(_camera.global_position, ray_end) + # Don't collide with ourselves + query.exclude = [self] + var result = space_state.intersect_ray(query) + if result.has('collider'): + var other: Node3D = result.collider + if other.has_method('interact'): + other.interact(self) + if other.is_in_group('can_hold'): + _held_object = other + _held_object_distance = (Vector3(result.position) - _camera.global_position).length()