diff --git a/levels/ghost_ship/environment_3.tres b/levels/ghost_ship/environment_3.tres index d3834d3..0d9bd75 100644 --- a/levels/ghost_ship/environment_3.tres +++ b/levels/ghost_ship/environment_3.tres @@ -31,6 +31,7 @@ ssil_radius = 0.4 ssil_intensity = 2.5 ssil_normal_rejection = 0.73 sdfgi_enabled = true +sdfgi_use_occlusion = true sdfgi_read_sky_light = false sdfgi_cascades = 7 glow_enabled = true diff --git a/levels/ghost_ship/ghost_ship.tscn b/levels/ghost_ship/ghost_ship.tscn index 49f5a18..e72097c 100644 --- a/levels/ghost_ship/ghost_ship.tscn +++ b/levels/ghost_ship/ghost_ship.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=22 format=3 uid="uid://bov4ok76woyc"] +[gd_scene load_steps=24 format=3 uid="uid://bov4ok76woyc"] [ext_resource type="PackedScene" uid="uid://crydi5cjgfwe5" path="res://levels/ghost_ship/ghost_ship_level.tscn" id="1_aj2m7"] [ext_resource type="Environment" uid="uid://bkvij3ljl5ox3" path="res://levels/ghost_ship/environment_3.tres" id="1_h081y"] @@ -19,6 +19,7 @@ [ext_resource type="AudioStream" uid="uid://cvwc2r2cmnaim" path="res://assets/sfx/ambient/metal_creak8.wav" id="15_r4ldl"] [ext_resource type="AudioStream" uid="uid://b288km80xeh0" path="res://assets/sfx/grunk/groan1.wav" id="17_law5k"] [ext_resource type="AudioStream" uid="uid://bujyltdunajj4" path="res://assets/sfx/grunk/groan2.wav" id="18_4mbcm"] +[ext_resource type="Script" uid="uid://m8bjl8yr01m6" path="res://src/util/gi_hint.gd" id="20_4mbcm"] [sub_resource type="BoxShape3D" id="BoxShape3D_o7mxe"] size = Vector3(6, 4, 15) @@ -42,6 +43,9 @@ stream_9/weight = 0.2 stream_10/stream = ExtResource("10_h081y") stream_10/weight = 0.2 +[sub_resource type="BoxMesh" id="BoxMesh_law5k"] +size = Vector3(8, 6, 1) + [node name="GhostShip" type="Node3D"] script = ExtResource("1_law5k") id = "ghost_ship" @@ -119,5 +123,12 @@ bus = &"Ambient" interval_mean = 120.0 interval_st_dev = 30.0 +[node name="GIHint" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -27, 2, -43.5) +visible = false +mesh = SubResource("BoxMesh_law5k") +script = ExtResource("20_4mbcm") +frames_to_live = 20000 + [connection signal="body_entered" from="PlayerShipArea" to="AmbientDrone" method="_on_player_enters_ship"] [connection signal="body_exited" from="PlayerShipArea" to="AmbientDrone" method="_on_player_exits_ship"] diff --git a/levels/physics_test/physics_test.tscn b/levels/physics_test/physics_test.tscn new file mode 100644 index 0000000..c70d48f --- /dev/null +++ b/levels/physics_test/physics_test.tscn @@ -0,0 +1,166 @@ +[gd_scene load_steps=16 format=3 uid="uid://c7us4smgk3487"] + +[ext_resource type="Script" uid="uid://68r4ht5ut1ct" path="res://src/game/level.gd" id="1_252gx"] +[ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="1_sumi4"] +[ext_resource type="ArrayMesh" uid="uid://dpr5cgq743f4s" path="res://assets/level/floor/floor_9x9.mesh" id="2_jjage"] +[ext_resource type="Script" uid="uid://040xta01xqxd" path="res://src/props/physics/holdable.gd" id="4_252gx"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_hda7d"] + +[sub_resource type="Sky" id="Sky_pka60"] +sky_material = SubResource("ProceduralSkyMaterial_hda7d") + +[sub_resource type="Environment" id="Environment_nl4kk"] +background_mode = 2 +sky = SubResource("Sky_pka60") + +[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_6j7vt"] + +[sub_resource type="BoxMesh" id="BoxMesh_252gx"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_35l2h"] + +[sub_resource type="BoxMesh" id="BoxMesh_35l2h"] +size = Vector3(2, 2, 2) + +[sub_resource type="BoxShape3D" id="BoxShape3D_sc5il"] +size = Vector3(2, 2, 2) + +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_35l2h"] +bounce = 0.5 + +[sub_resource type="SphereMesh" id="SphereMesh_sc5il"] +radius = 0.15 +height = 0.3 + +[sub_resource type="SphereShape3D" id="SphereShape3D_hyy3g"] +radius = 0.15 + +[node name="PhysicsTest" type="Node3D"] +script = ExtResource("1_252gx") +id = "physics_test" +pretty_name = "Physics Testing Sandbox" + +[node name="Player" parent="." instance=ExtResource("1_sumi4")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.866025, -0.156955, -0.474726, 0.5, 0.271854, 0.82225, 0, -0.949453, 0.31391, 0, 0, 0) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_nl4kk") + +[node name="WorldFloor" type="StaticBody3D" parent="." groups=["PlasticMaterial"]] +collision_layer = 5 + +[node name="MeshInstance3D" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D3" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D4" type="MeshInstance3D" parent="WorldFloor"] +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D5" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9, 0, 0) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D6" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9, 0, 0) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D7" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D8" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18, 0, 0) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D9" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 27, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D10" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 27, 0, 0) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D11" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 36, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D12" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 36, 0, 0) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D13" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D14" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45, 0, 0) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D15" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 54, 0, -9) +mesh = ExtResource("2_jjage") + +[node name="MeshInstance3D16" type="MeshInstance3D" parent="WorldFloor"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 54, 0, 0) +mesh = ExtResource("2_jjage") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldFloor"] +visible = false +shape = SubResource("WorldBoundaryShape3D_6j7vt") + +[node name="MedBox" type="RigidBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 1.2, -6) +collision_layer = 6 +collision_mask = 9 +mass = 10.0 + +[node name="MeshInstance3D" type="MeshInstance3D" parent="MedBox"] +mesh = SubResource("BoxMesh_252gx") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="MedBox"] +shape = SubResource("BoxShape3D_35l2h") + +[node name="Holdable" type="Node" parent="MedBox"] +script = ExtResource("4_252gx") +hold_distance = 2.0 +metadata/_custom_type_script = "uid://040xta01xqxd" + +[node name="BigBox" type="RigidBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10.5, 1.8, -6) +collision_layer = 6 +collision_mask = 9 +mass = 50.0 + +[node name="MeshInstance3D" type="MeshInstance3D" parent="BigBox"] +mesh = SubResource("BoxMesh_35l2h") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="BigBox"] +shape = SubResource("BoxShape3D_sc5il") + +[node name="Ball" type="RigidBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2, -4.8) +collision_layer = 6 +collision_mask = 9 +physics_material_override = SubResource("PhysicsMaterial_35l2h") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Ball"] +mesh = SubResource("SphereMesh_sc5il") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Ball"] +shape = SubResource("SphereShape3D_hyy3g") + +[node name="Holdable" type="Node" parent="Ball"] +script = ExtResource("4_252gx") +metadata/_custom_type_script = "uid://040xta01xqxd" diff --git a/levels/prop_test/prop_test.tscn b/levels/prop_test/prop_test.tscn index a6361de..cc4a53e 100644 --- a/levels/prop_test/prop_test.tscn +++ b/levels/prop_test/prop_test.tscn @@ -73,6 +73,7 @@ game_environment = ExtResource("2_qnhar") debug_environment = ExtResource("3_mvw32") id = "prop_test" pretty_name = "Prop Testing Sandbox" +version = 1 [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(0.866025, -0.156955, -0.474726, 0.5, 0.271854, 0.82225, 0, -0.949453, 0.31391, 0, 0, 0) diff --git a/project.godot b/project.godot index 6208248..d943bb3 100644 --- a/project.godot +++ b/project.godot @@ -211,6 +211,10 @@ locale/translations=PackedStringArray("res://assets/text/text.en.translation") 3d_physics/layer_5="GameSounds" 3d_physics/layer_6="Player Physics" +[physics] + +3d/default_angular_damp=4.0 + [rendering] driver/threads/thread_model=2 diff --git a/src/player/hold_component.gd b/src/player/hold_component.gd new file mode 100644 index 0000000..f55dfd5 --- /dev/null +++ b/src/player/hold_component.gd @@ -0,0 +1,79 @@ +extends Node3D +## Component for managing physics object holding + +## Held object position lerp acceleration. +@export var hold_accel := 20.0 + +## The maximum distance the object may be from the hold point before breaking the hold. +@export var max_distance := 3.0 + +## Temporary linear damping for held objects +@export var hold_damping := 8.0 + +## Temporary collision layer. +@export_flags_3d_physics var hold_collision_layer := 0 + +## Temporary collision mask. +@export_flags_3d_physics var hold_collision_physics := 1 + +## The object currently being held. +var _held_object: RigidBody3D + +var _original_damping: float +var _original_collision_layer: int +var _original_collision_mask: int + +@onready var interact_ray: RayCast3D = %InteractRay +@onready var hold_point: Marker3D = %HoldPoint + + +func attach(prop: RigidBody3D, hold_distance: float) -> void: + hold_point.position = Vector3(0, 0, -hold_distance) + _held_object = prop + + _original_damping = prop.linear_damp + prop.linear_damp = hold_damping + + _original_collision_layer = prop.collision_layer + prop.collision_layer = hold_collision_layer + + _original_collision_mask = prop.collision_mask + prop.collision_mask = hold_collision_physics + + +func drop() -> void: + _held_object.linear_damp = _original_damping + _held_object.collision_layer = _original_collision_layer + _held_object.collision_mask = _original_collision_mask + _held_object = null + + +func holding_object() -> bool: + return !!_held_object + + +func _physics_process(delta: float) -> void: + # Object hold action logic + if Input.is_action_just_pressed("interact"): + if _held_object: + drop() + elif interact_ray.is_colliding(): + var body := interact_ray.get_collider() as RigidBody3D + var hold_component := Holdable.get_component(body) + if hold_component: + attach(body, hold_component.hold_distance) + + # Held object logic + if not _held_object: + return + + var diff := hold_point.global_position - (_held_object.global_position) + if diff.length() > max_distance: + drop() + return + + var weight := 1 - exp(-hold_accel * delta) + _held_object.global_position = _held_object.global_position.lerp( + hold_point.global_position, weight + ) + _held_object.global_basis = _held_object.global_basis.slerp(global_basis, weight) diff --git a/src/player/hold_component.gd.uid b/src/player/hold_component.gd.uid new file mode 100644 index 0000000..9781aba --- /dev/null +++ b/src/player/hold_component.gd.uid @@ -0,0 +1 @@ +uid://pkk1qg3bqjhj diff --git a/src/player/player.gd b/src/player/player.gd index bd0f5f9..3a0f477 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -189,14 +189,14 @@ func _signal_death() -> void: func _physics_process(delta: float) -> void: # Will be null if no valid interactor is selected. - var interactive: Interactive = interact_ray.get_collider() as Interactive + var interactive := interact_ray.get_collider() as Interactive hud.select_interactive(interactive) if interactive: interactive.select() if activity_enabled: # World interaction - if interactive and Input.is_action_just_pressed("interact"): + if Input.is_action_just_pressed("interact") and interactive: interactive.activate() # Tool selection diff --git a/src/player/player.tscn b/src/player/player.tscn index 432c753..fe72962 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=64 format=3 uid="uid://bwe2jdmvinhqd"] +[gd_scene load_steps=66 format=3 uid="uid://bwe2jdmvinhqd"] [ext_resource type="Script" uid="uid://buwh0g1ga2aka" path="res://src/player/player.gd" id="1_npueo"] [ext_resource type="Script" uid="uid://cx1yt0drthpw3" path="res://src/player/camera_controller.gd" id="2_veeqv"] @@ -14,6 +14,7 @@ [ext_resource type="Script" uid="uid://ecrhsueph7at" path="res://src/player/footsteps/footstep_controller.gd" id="9_hja65"] [ext_resource type="Script" uid="uid://brqa2wbtaspw4" path="res://src/player/footsteps/foot_controller.gd" id="9_l271a"] [ext_resource type="AudioStream" uid="uid://di0e1l1l6l3qc" path="res://assets/sfx/footsteps/metal/metal1.wav" id="10_jcdrv"] +[ext_resource type="Script" uid="uid://pkk1qg3bqjhj" path="res://src/player/hold_component.gd" id="11_h0enb"] [ext_resource type="AudioStream" uid="uid://bv00dudic2mvp" path="res://assets/sfx/footsteps/metal/metal3.wav" id="11_hja65"] [ext_resource type="AudioStream" uid="uid://befqnsqlbpca7" path="res://assets/sfx/footsteps/metal/metal5.wav" id="12_5shm8"] [ext_resource type="AudioStream" uid="uid://c6wnc7kqtvujm" path="res://assets/sfx/footsteps/metal/metal7.wav" id="13_5efpn"] @@ -170,6 +171,10 @@ nodes/timescale/node = SubResource("AnimationNodeTimeScale_8ydov") nodes/timescale/position = Vector2(1240, 120) node_connections = [&"blend", 0, &"still_anim", &"blend", 1, &"bob_anim", &"output", 0, &"timescale", &"sfx_add", 0, &"blend", &"sfx_add", 1, &"sfx_anim", &"timescale", 0, &"sfx_add"] +[sub_resource type="SphereMesh" id="SphereMesh_h0enb"] +radius = 0.05 +height = 0.1 + [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_s7f0r"] radius = 0.4 height = 1.9 @@ -676,6 +681,17 @@ parameters/sfx_add/add_amount = 1.0 parameters/timescale/scale = false script = ExtResource("7_x42xx") +[node name="HoldComponent" type="Node3D" parent="CameraPosition/CameraPivot/TransformedPosition/CamRumbler/Camera3D"] +script = ExtResource("11_h0enb") + +[node name="HoldPoint" type="Marker3D" parent="CameraPosition/CameraPivot/TransformedPosition/CamRumbler/Camera3D/HoldComponent"] +unique_name_in_owner = true +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1) + +[node name="DebugHoldPoint" type="MeshInstance3D" parent="CameraPosition/CameraPivot/TransformedPosition/CamRumbler/Camera3D/HoldComponent/HoldPoint"] +mesh = SubResource("SphereMesh_h0enb") +skeleton = NodePath("../..") + [node name="StandingCollider" type="CollisionShape3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0) shape = SubResource("CapsuleShape3D_s7f0r") diff --git a/src/props/overhead_light/overhead_light.tscn b/src/props/overhead_light/overhead_light.tscn index d0a3193..b9b6204 100644 --- a/src/props/overhead_light/overhead_light.tscn +++ b/src/props/overhead_light/overhead_light.tscn @@ -99,12 +99,14 @@ visible = false light_color = Color(1, 0.9825, 0.95, 1) light_energy = 2.0 light_specular = 1.0 +shadow_enabled = true spot_range = 16.0 spot_attenuation = 0.5 -spot_angle = 98.0 +spot_angle = 70.0 spot_angle_attenuation = 1.55871 [node name="MeshInstance3D" type="MeshInstance3D" parent="."] +cast_shadow = 0 gi_mode = 2 mesh = ExtResource("2_210ch") surface_material_override/0 = SubResource("StandardMaterial3D_ljcul") diff --git a/src/props/physics/holdable.gd b/src/props/physics/holdable.gd new file mode 100644 index 0000000..05037cc --- /dev/null +++ b/src/props/physics/holdable.gd @@ -0,0 +1,11 @@ +class_name Holdable extends Node +## Component for holdable elements + +@export var hold_distance := 1.0 + + +static func get_component(o: Object) -> Holdable: + var n := o as Node + if n and n.has_node("Holdable"): + return n.get_node_or_null("Holdable") as Holdable + return null diff --git a/src/props/physics/holdable.gd.uid b/src/props/physics/holdable.gd.uid new file mode 100644 index 0000000..9ad5572 --- /dev/null +++ b/src/props/physics/holdable.gd.uid @@ -0,0 +1 @@ +uid://040xta01xqxd diff --git a/src/util/gi_hint.gd b/src/util/gi_hint.gd new file mode 100644 index 0000000..89569e7 --- /dev/null +++ b/src/util/gi_hint.gd @@ -0,0 +1,12 @@ +extends MeshInstance3D + +@export var frames_to_live := 16 + +var frames_remaining := frames_to_live + + +func _process(_delta: float) -> void: + if frames_remaining <= 0: + queue_free() + + frames_remaining -= 1 diff --git a/src/util/gi_hint.gd.uid b/src/util/gi_hint.gd.uid new file mode 100644 index 0000000..ad8e619 --- /dev/null +++ b/src/util/gi_hint.gd.uid @@ -0,0 +1 @@ +uid://m8bjl8yr01m6 diff --git a/src/world/world.tscn b/src/world/world.tscn index a67352d..9870593 100644 --- a/src/world/world.tscn +++ b/src/world/world.tscn @@ -4,7 +4,7 @@ [ext_resource type="Resource" uid="uid://tgac5tnfx56r" path="res://src/world/world_manager.tres" id="2_5kmgb"] [ext_resource type="PackedScene" uid="uid://byvjsvavbg5xe" path="res://src/ui/menus/pause_menu/pause_menu.tscn" id="2_6fy3g"] [ext_resource type="Resource" uid="uid://0i72bf8ip1lx" path="res://src/world/spook_manager.tres" id="3_l0av5"] -[ext_resource type="PackedScene" uid="uid://bov4ok76woyc" path="res://levels/ghost_ship/ghost_ship.tscn" id="4_5kmgb"] +[ext_resource type="PackedScene" uid="uid://c7us4smgk3487" path="res://levels/physics_test/physics_test.tscn" id="4_5kmgb"] [ext_resource type="PackedScene" uid="uid://c0uitm5cg88h1" path="res://src/ui/menus/kill_screen/kill_screen.tscn" id="6_l0av5"] [ext_resource type="PackedScene" uid="uid://brknr57xc2cp0" path="res://src/ui/elements/save_icon/save_icon.tscn" id="7_5kmgb"]