From a78cc1801be94e18274aca5c5eacee8d10b452b5 Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Sat, 6 Sep 2025 15:27:37 -0600 Subject: [PATCH] Spook manager uses new spawn logic --- levels/ghost_ship/ambient_drone.gd | 2 +- levels/ghost_ship/ghost_ship_level.tscn | 38 ------ levels/ghost_ship/level/medbay/medbay.tscn | 80 ++++++------ src/player/player.gd | 7 + src/player/player.tscn | 14 +- src/util/scene_tools.gd | 33 +++-- src/world/grunk_beast/grunk_beast.gd | 9 ++ src/world/grunk_beast/grunk_beast.tscn | 17 ++- src/world/mechanics/alarm/gunk_alarm.gd | 2 +- src/world/spook_manager/spook_manager.gd | 144 +++++++++++++++------ src/world/world.gd | 1 + src/world/world.tscn | 1 + utilities/sandbox/sandbox.gd | 8 ++ utilities/sandbox/sandbox.tscn | 5 +- 14 files changed, 221 insertions(+), 140 deletions(-) diff --git a/levels/ghost_ship/ambient_drone.gd b/levels/ghost_ship/ambient_drone.gd index 81b4432..57d03c9 100644 --- a/levels/ghost_ship/ambient_drone.gd +++ b/levels/ghost_ship/ambient_drone.gd @@ -38,7 +38,7 @@ func closest_beast_distance() -> float: return INF var min_dist_sq := INF - var nodes := get_tree().get_nodes_in_group("GrunkBeast") + var nodes := get_tree().get_nodes_in_group(GrunkBeast.GROUP) for node: Node in nodes: var n3d := node as Node3D if is_instance_valid(n3d): diff --git a/levels/ghost_ship/ghost_ship_level.tscn b/levels/ghost_ship/ghost_ship_level.tscn index 126910d..ae7008c 100644 --- a/levels/ghost_ship/ghost_ship_level.tscn +++ b/levels/ghost_ship/ghost_ship_level.tscn @@ -212,44 +212,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -58.5) [node name="LurkPoint11" type="Marker3D" parent="LurkPoints" groups=["LurkPoint"]] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -21.6, -3, -69.3) -[node name="BeastSpawns" type="Node3D" parent="."] - -[node name="BeastSpawnPoint" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 1.5, -48) - -[node name="BeastSpawnPoint2" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -36) - -[node name="BeastSpawnPoint3" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -51) - -[node name="BeastSpawnPoint4" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 1.5, -51) - -[node name="BeastSpawnPoint5" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -66) - -[node name="BeastSpawnPoint6" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12, 1.5, -66) - -[node name="BeastSpawnPoint7" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 1.5, -66) - -[node name="BeastSpawnPoint8" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -78) - -[node name="BeastSpawnPoint9" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -57) - -[node name="BeastSpawnPoint10" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -42) - -[node name="BeastSpawnPoint11" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12, 1.5, -45) - -[node name="BeastSpawnPoint12" type="Marker3D" parent="BeastSpawns" groups=["BeastSpawnPoint"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16.2, -1.5, -57) - [connection signal="activated" from="BeastNav/Airlock/SwitchA1" to="BeastNav/Airlock/SwitchA1" method="disable"] [connection signal="activated" from="BeastNav/Airlock/SwitchA1" to="BeastNav/Corridor1/SwitchA2" method="disable"] [connection signal="activated" from="BeastNav/Airlock/SwitchA1" to="BeastNav/Bulkheads/BulkheadA" method="toggle"] diff --git a/levels/ghost_ship/level/medbay/medbay.tscn b/levels/ghost_ship/level/medbay/medbay.tscn index ec27f4a..6c46579 100644 --- a/levels/ghost_ship/level/medbay/medbay.tscn +++ b/levels/ghost_ship/level/medbay/medbay.tscn @@ -99,7 +99,7 @@ size = Vector3(0.8, 1, 1.5) [sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_dwjsf"] data = PackedVector3Array(-0.4, 0.5, 0.75, 0.4, 0.5, 0.75, -0.4, -0.5, 0.75, 0.4, 0.5, 0.75, 0.4, -0.5, 0.75, -0.4, -0.5, 0.75, 0.4, 0.5, -0.75, -0.4, 0.5, -0.75, 0.4, -0.5, -0.75, -0.4, 0.5, -0.75, -0.4, -0.5, -0.75, 0.4, -0.5, -0.75, 0.4, 0.5, 0.75, 0.4, 0.5, -0.75, 0.4, -0.5, 0.75, 0.4, 0.5, -0.75, 0.4, -0.5, -0.75, 0.4, -0.5, 0.75, -0.4, 0.5, -0.75, -0.4, 0.5, 0.75, -0.4, -0.5, -0.75, -0.4, 0.5, 0.75, -0.4, -0.5, 0.75, -0.4, -0.5, -0.75, 0.4, 0.5, 0.75, -0.4, 0.5, 0.75, 0.4, 0.5, -0.75, -0.4, 0.5, 0.75, -0.4, 0.5, -0.75, 0.4, 0.5, -0.75, -0.4, -0.5, 0.75, 0.4, -0.5, 0.75, -0.4, -0.5, -0.75, 0.4, -0.5, 0.75, 0.4, -0.5, -0.75, -0.4, -0.5, -0.75) -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jnjru"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1syyw"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -125,7 +125,7 @@ _surfaces = [{ }] blend_shape_mode = 0 -[sub_resource type="ArrayMesh" id="ArrayMesh_bnexv"] +[sub_resource type="ArrayMesh" id="ArrayMesh_loej8"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -134,7 +134,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_jnjru"), +"material": SubResource("StandardMaterial3D_1syyw"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -144,7 +144,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_p5an5"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5abrm"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -155,7 +155,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_1syyw"] +[sub_resource type="ArrayMesh" id="ArrayMesh_t0ymk"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -164,7 +164,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_p5an5"), +"material": SubResource("StandardMaterial3D_5abrm"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -174,7 +174,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_loej8"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_glbip"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -185,7 +185,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_5abrm"] +[sub_resource type="ArrayMesh" id="ArrayMesh_nqwfe"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -194,7 +194,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_loej8"), +"material": SubResource("StandardMaterial3D_glbip"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -204,7 +204,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_t0ymk"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_h56f5"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -215,7 +215,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_glbip"] +[sub_resource type="ArrayMesh" id="ArrayMesh_gem8k"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -224,7 +224,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_t0ymk"), +"material": SubResource("StandardMaterial3D_h56f5"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -234,7 +234,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_nqwfe"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_wr3ux"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -245,7 +245,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_h56f5"] +[sub_resource type="ArrayMesh" id="ArrayMesh_a7woh"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -254,7 +254,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_nqwfe"), +"material": SubResource("StandardMaterial3D_wr3ux"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -264,7 +264,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gem8k"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_l1qst"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -275,7 +275,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_wr3ux"] +[sub_resource type="ArrayMesh" id="ArrayMesh_8ifew"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -284,7 +284,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_gem8k"), +"material": SubResource("StandardMaterial3D_l1qst"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -294,7 +294,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_a7woh"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_klyoq"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -305,7 +305,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_l1qst"] +[sub_resource type="ArrayMesh" id="ArrayMesh_jmnef"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -314,7 +314,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_a7woh"), +"material": SubResource("StandardMaterial3D_klyoq"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -324,7 +324,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8ifew"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7ip0j"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -335,7 +335,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_klyoq"] +[sub_resource type="ArrayMesh" id="ArrayMesh_w6w82"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -344,7 +344,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_8ifew"), +"material": SubResource("StandardMaterial3D_7ip0j"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -354,7 +354,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jmnef"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_eorl6"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -365,7 +365,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_7ip0j"] +[sub_resource type="ArrayMesh" id="ArrayMesh_ckuu8"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -374,7 +374,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_jmnef"), +"material": SubResource("StandardMaterial3D_eorl6"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -384,7 +384,7 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_u2hqf") -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_w6w82"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_65pvg"] resource_local_to_scene = true albedo_texture = ExtResource("13_glbip") metallic = 1.0 @@ -395,7 +395,7 @@ normal_texture = ExtResource("15_h56f5") ao_enabled = true texture_filter = 2 -[sub_resource type="ArrayMesh" id="ArrayMesh_eorl6"] +[sub_resource type="ArrayMesh" id="ArrayMesh_n3yb1"] resource_local_to_scene = true _surfaces = [{ "aabb": AABB(-0.375, -0.25, -0.75, 0.75, 0.5, 1.5), @@ -404,7 +404,7 @@ _surfaces = [{ "index_count": 84, "index_data": PackedByteArray("FgANAAwADAANABcAFwANAA4ADgANABgAGAANAA8ADwANABkAGgAHAAIAAgAHABsAEAABABEAEQABABwAHQAAAAYABgAAAAMACQAUAAgACAAUABUAFQAUAAoACgAUAB4AHgAUAAsACwAUAB8AIAATAAUABQATAAQAIQAiACMAIwAiACQAJQASACYAJgASACcAKAApACoAKgApACsALAAtAC4ALgAtAC8A"), "lods": [0.108952, PackedByteArray("DAANAA4ADgANAA8AEAABABEAEAARAAYAEQAAAAYABgAAAAMAEQABAAIAAgABAAcABwASAAIABwATABIAEgATAAUABQATAAQACQAUAAgACAAUABUAFQAUAAoACgAUAAsA"), 0.261829, PackedByteArray("AAABAAIAAQAAAAYABgAAAAMAAgABAAcABwAEAAIAAgAEAAUACAAJAAoACgAJAAsA"), 0.524037, PackedByteArray("AAABAAIAAQAAAAMAAgABAAQAAgAEAAUA")], -"material": SubResource("StandardMaterial3D_w6w82"), +"material": SubResource("StandardMaterial3D_65pvg"), "name": "Cube", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), @@ -1351,7 +1351,7 @@ skeleton = NodePath("") [node name="CrateLong" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -0.749907, 0.25, 4.05009) -mesh = SubResource("ArrayMesh_bnexv") +mesh = SubResource("ArrayMesh_loej8") [node name="PhysCrateLong" parent="Props" instance=ExtResource("19_yvs0w")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.25, -3.6) @@ -1359,39 +1359,39 @@ sleeping = true [node name="CrateLong2" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -0.749907, 0.75, 4.05009) -mesh = SubResource("ArrayMesh_1syyw") +mesh = SubResource("ArrayMesh_t0ymk") [node name="CrateLong3" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(-4.37114e-08, 0.707107, -0.707107, 0, 0.707107, 0.707107, 1, 3.09086e-08, -3.09086e-08, 0.599813, 0.75, 4.05009) -mesh = SubResource("ArrayMesh_5abrm") +mesh = SubResource("ArrayMesh_nqwfe") [node name="CrateLong5" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(1, 0, -7.45058e-08, 0, 1, 0, 7.45058e-08, 0, 1, 3.93256, 0.25, -2.54991) -mesh = SubResource("ArrayMesh_glbip") +mesh = SubResource("ArrayMesh_gem8k") [node name="CrateLong10" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(1, 0, -7.45058e-08, 0, 1, 0, 7.45058e-08, 0, 1, 3.93256, 0.25, -1.04991) -mesh = SubResource("ArrayMesh_h56f5") +mesh = SubResource("ArrayMesh_a7woh") [node name="CrateLong6" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(1, 0, -1.19209e-07, 0, 1, 0, 1.19209e-07, 0, 1, 3.93256, 0.75, -2.54991) -mesh = SubResource("ArrayMesh_wr3ux") +mesh = SubResource("ArrayMesh_8ifew") [node name="CrateLong11" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(1, 0, -1.19209e-07, 0, 1, 0, 1.19209e-07, 0, 1, 3.93256, 0.75, -1.04991) -mesh = SubResource("ArrayMesh_l1qst") +mesh = SubResource("ArrayMesh_jmnef") [node name="CrateLong7" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(1, 0, -1.19209e-07, 0, 1, 0, 1.19209e-07, 0, 1, 3.93256, 1.25, -2.54991) -mesh = SubResource("ArrayMesh_klyoq") +mesh = SubResource("ArrayMesh_w6w82") [node name="CrateLong8" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(1, 0, -1.19209e-07, 0, 1, 0, 1.19209e-07, 0, 1, 3.93256, 1.75, -2.54991) -mesh = SubResource("ArrayMesh_7ip0j") +mesh = SubResource("ArrayMesh_ckuu8") [node name="CrateLong9" parent="Props" instance=ExtResource("12_t0ymk")] transform = Transform3D(1, 0, -1.19209e-07, 0, 1, 0, 1.19209e-07, 0, 1, 3.93256, 2.25, -2.54991) -mesh = SubResource("ArrayMesh_eorl6") +mesh = SubResource("ArrayMesh_n3yb1") [node name="FloatingDust" parent="." instance=ExtResource("17_wr3ux")] transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0, 1.5, -4.5) diff --git a/src/player/player.gd b/src/player/player.gd index 176cc17..8d06794 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -63,6 +63,7 @@ var _was_on_floor := false @onready var sticker_pack: Tool = %StickerPack @onready var hold_component: HoldComponent = %HoldComponent +@onready var spawn_zone_finder: Area3D = %SpawnZoneFinder @onready var crouch_head_area: Area3D = %CrouchHeadArea @onready var crouch_animation: AnimationPlayer = %CrouchAnimation @@ -112,6 +113,12 @@ func get_tool() -> Tool: return tool_mount.get_active() +func get_spawn_zones() -> Array[BeastSpawnZone]: + var zones: Array[BeastSpawnZone] = [] + zones.assign(spawn_zone_finder.get_overlapping_areas()) + return zones + + ## Add the given item to the player's inventory. func add_item(item: Item, amount: int = 1) -> void: inventory[item] = inventory.get(item, 0) + amount diff --git a/src/player/player.tscn b/src/player/player.tscn index a9c1347..f7f0ec8 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=70 format=3 uid="uid://bwe2jdmvinhqd"] +[gd_scene load_steps=71 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"] @@ -176,6 +176,9 @@ 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="SphereShape3D" id="SphereShape3D_utg71"] +radius = 1.0 + [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_s7f0r"] radius = 0.4 height = 1.9 @@ -705,6 +708,15 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.15) cull_mask = 4293918724 size = Vector3(10, 10, 0.2) +[node name="SpawnZoneFinder" type="Area3D" parent="CameraPosition/CameraPivot"] +unique_name_in_owner = true +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, -1) +collision_layer = 0 +collision_mask = 256 + +[node name="CollisionShape3D" type="CollisionShape3D" parent="CameraPosition/CameraPivot/SpawnZoneFinder"] +shape = SubResource("SphereShape3D_utg71") + [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/util/scene_tools.gd b/src/util/scene_tools.gd index e90ed87..9bbd553 100644 --- a/src/util/scene_tools.gd +++ b/src/util/scene_tools.gd @@ -19,23 +19,38 @@ static func closest_in_group(target: Node3D, group_name: String) -> Node3D: return closest +## Get the player's Camera3D instance, or null if there isn't one. +static func get_player_camera() -> Camera3D: + if is_instance_valid(Player.instance): + return Player.instance.get_viewport().get_camera_3d() + return null + + +## Is the player looking in the direction of the given point? +static func player_looking_at(target: Vector3) -> bool: + var camera := get_player_camera() + return camera and camera.is_position_in_frustum(target) + + ## Does the player have an unobstructed line-of-sight to the given point? -static func player_can_see(target: Vector3) -> bool: - if not is_instance_valid(Player.instance): +static func player_has_sight_line(target: Vector3) -> bool: + var camera := get_player_camera() + if not camera: return false - var camera := Player.instance.get_viewport().get_camera_3d() - - if not camera.is_position_in_frustum(target): - return false - - var query := PhysicsRayQueryParameters3D.create(camera.global_position, target, RAY_MASK) - # TODO may need to add an "exceptions" parameter for the source's body + var query := PhysicsRayQueryParameters3D.create( + camera.global_position, target, RAY_MASK, [Player.instance.get_rid()] + ) var raycast := Player.instance.get_world_3d().direct_space_state.intersect_ray(query) # If raycast is empty, view is unoccluded and player has line-of-sight! return not raycast +## Is the player looking at the given point with an unobstructed line-of-sight? +static func player_can_see(target: Vector3) -> bool: + return player_looking_at(target) and player_has_sight_line(target) + + ## Get a random Node3D from the given group which is not currently visible to the player ## ## Returns null is there is no such node, either because the group is empty diff --git a/src/world/grunk_beast/grunk_beast.gd b/src/world/grunk_beast/grunk_beast.gd index 6ec77d0..a13becf 100644 --- a/src/world/grunk_beast/grunk_beast.gd +++ b/src/world/grunk_beast/grunk_beast.gd @@ -2,6 +2,7 @@ class_name GrunkBeast extends CharacterBody3D ## Grunk beast controller #region Constants +const GROUP := "GrunkBeast" const ANGER_KEY := "anger_level" const POI_KEY := "point_of_interest" #endregion @@ -38,6 +39,8 @@ var traversing_link := false @onready var nav_agent: NavigationAgent3D = %NavAgent @onready var nav_probe: NavigationAgent3D = %NavProbe +@onready var spawn_zone_finder: Area3D = %SpawnZoneFinder + @onready var sound_detection_cooldown: Timer = %SoundDetectionCooldown @onready var touch_cooldown: Timer = %TouchCooldown @@ -112,6 +115,12 @@ func start_spawn() -> void: point_of_interest = global_position +func get_spawn_zones() -> Array[BeastSpawnZone]: + var zones: Array[BeastSpawnZone] = [] + zones.assign(spawn_zone_finder.get_overlapping_areas()) + return zones + + func get_speed() -> float: return speed_curve.sample(anger_level) diff --git a/src/world/grunk_beast/grunk_beast.tscn b/src/world/grunk_beast/grunk_beast.tscn index 52a1c5a..fc3bf8c 100644 --- a/src/world/grunk_beast/grunk_beast.tscn +++ b/src/world/grunk_beast/grunk_beast.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=44 format=3 uid="uid://ehf5sg3ahvbf"] +[gd_scene load_steps=45 format=3 uid="uid://ehf5sg3ahvbf"] [ext_resource type="Script" uid="uid://b5loa2u6s5l5c" path="res://src/player/rigid_body_physics.gd" id="2_4alar"] [ext_resource type="PackedScene" uid="uid://brrd33217oplv" path="res://src/world/grunk_beast/shambler/shambler.tscn" id="2_csisu"] @@ -60,16 +60,15 @@ radius = 6.0 [sub_resource type="SphereShape3D" id="SphereShape3D_lak6w"] radius = 10.0 +[sub_resource type="SphereShape3D" id="SphereShape3D_4alar"] +radius = 0.2 + [node name="GrunkBeast" type="CharacterBody3D" groups=["GrunkBeast"]] collision_layer = 100 wall_min_slide_angle = 0.174533 floor_max_angle = 1.0472 script = ExtResource("2_qqnhb") -spawn_on_load = null speed_curve = SubResource("Curve_sm756") -anger_level = null -point_of_interest = null -debug_destroy = null [node name="RigidBodyPhysics" type="Node" parent="."] script = ExtResource("2_4alar") @@ -145,6 +144,14 @@ collision_mask = 8 [node name="CollisionShape3D" type="CollisionShape3D" parent="SniffRange"] shape = SubResource("SphereShape3D_lak6w") +[node name="SpawnZoneFinder" type="Area3D" parent="."] +unique_name_in_owner = true +collision_layer = 0 +collision_mask = 256 + +[node name="CollisionShape3D" type="CollisionShape3D" parent="SpawnZoneFinder"] +shape = SubResource("SphereShape3D_4alar") + [node name="SoundDetectionCooldown" type="Timer" parent="."] unique_name_in_owner = true one_shot = true diff --git a/src/world/mechanics/alarm/gunk_alarm.gd b/src/world/mechanics/alarm/gunk_alarm.gd index 0574d28..e1f6bba 100644 --- a/src/world/mechanics/alarm/gunk_alarm.gd +++ b/src/world/mechanics/alarm/gunk_alarm.gd @@ -25,8 +25,8 @@ func trigger() -> void: if not _busy: _busy = true if World.instance and World.instance.manager: - World.instance.manager.alarm_triggered.emit(self) World.instance.manager.raise_alert(ALERT_DELTA) + World.instance.manager.alarm_triggered.emit(self) animation_player.play("trigger") trigger_animation.play("trigger") alarm_sfx.play() diff --git a/src/world/spook_manager/spook_manager.gd b/src/world/spook_manager/spook_manager.gd index 624fabe..bc20e53 100644 --- a/src/world/spook_manager/spook_manager.gd +++ b/src/world/spook_manager/spook_manager.gd @@ -1,43 +1,101 @@ class_name SpookManager extends Resource ## A strategy for handling horror elements through the level. -const SPAWN_GROUP := "BeastSpawnPoint" -const BEAST_GROUP := "GrunkBeast" -@export var grunkbeast_scene: PackedScene +func _get_best_spawners() -> Array[BeastSpawner]: + var spawners: Array[BeastSpawner] = [] + if is_instance_valid(Player.instance): + # Get all spawners in the spawn zone(s) occupied by the player + var zones: Array[BeastSpawnZone] = Player.instance.get_spawn_zones() + for zone: BeastSpawnZone in zones: + spawners.append_array(zone.get_spawners()) + if spawners: + # Get spawners which player has unobstructed sightline to + var visible_spawners := spawners.filter( + func(s: BeastSpawner) -> bool: + return SceneTools.player_has_sight_line(s.global_position) + ) + if visible_spawners: + # Get spawners the player is currently looking at + var seen_spawners := spawners.filter( + func(s: BeastSpawner) -> bool: + return SceneTools.player_looking_at(s.global_position) + ) + if seen_spawners: + print_debug("Picking from spawners player is looking at") + return seen_spawners + print_debug("Picking from spawners player has unobstructed sightline to") + return visible_spawners + print_debug("Picking from spawners in the player's local spawn zone(s)") + return spawners -var debug_set_alert_level: int: - set = on_alert_raised + # Fallback behavior: just get all spawners + print_debug("Falling back to all world spawners") + spawners.assign(World.instance.get_tree().get_nodes_in_group(BeastSpawner.GROUP)) + return spawners -func _spawn_beast_at_point(spawn_point: Node3D) -> void: - print_debug("Spawning active beast at ", spawn_point.global_position) - var beast: GrunkBeast = grunkbeast_scene.instantiate() - spawn_point.add_child(beast) +func _filter_top_priority(spawners: Array[BeastSpawner]) -> Array[BeastSpawner]: + ## Return only the spawners with the highest priority in the group + var priority_spawners: Array[BeastSpawner] = [] + var top_priority := -1 + for spawner in spawners: + if spawner.spawn_priority > top_priority: + top_priority = spawner.spawn_priority + priority_spawners = [spawner] + elif spawner.spawn_priority == top_priority: + priority_spawners.append(spawner) + return priority_spawners -## Spawn a beast somewhere the player isn't looking. -func spawn_beast() -> void: - var spawn_point := SceneTools.pick_unseen_from_group(SPAWN_GROUP) - if not spawn_point: - print_debug("Couldn't find a hidden spawn point... Picking one at random.") - var nodes := World.instance.get_tree().get_nodes_in_group(SPAWN_GROUP) - if not nodes: - print_debug("Oh that's why. There aren't any spawn points. Complain to a developer.") - return - @warning_ignore("unsafe_cast") - spawn_point = nodes.pick_random() as Node3D +## Spawn a beast at a good spot. +## +## The heuristic used for picking a BeastSpawner prefers higher-priority spawns, spawns the player +## can see, and spawns in the player's current spawn zone(s). +func spawn_beast_near_player() -> void: + print_debug("Trying to spawn an active beast...") + var spawners := _filter_top_priority(_get_best_spawners()) - _spawn_beast_at_point(spawn_point) + if spawners: + var spawner: BeastSpawner = spawners.pick_random() + spawner.do_spawn() + else: + print_debug("There aren't any spawn points on the map. Complain to a developer.") -## Spawn beasts at _every_ spawn point the player can't see. -func spawn_many_beasts() -> void: - var nodes := World.instance.get_tree().get_nodes_in_group(SPAWN_GROUP) - for node: Node in nodes: - var target := node as Node3D - if is_instance_valid(target) and not SceneTools.player_can_see(target.global_position): - _spawn_beast_at_point(target) +## Respawn an existing active beast near the player if there is not already one. +## +## If there's already a beast near the player, nothing happens. +## If there isn't a beast near the player but there are active beasts, one will be despawned and +## respawn near the player. +## If there aren't any active beasts, one will be spawned. +func respawn_beast_near_player() -> void: + var beasts: Array[GrunkBeast] = [] + beasts.assign(World.instance.get_tree().get_nodes_in_group(GrunkBeast.GROUP)) + + # Look for a beast in the same spawn zone(s) as the player + if is_instance_valid(Player.instance): + var local_zones: Array[BeastSpawnZone] = Player.instance.get_spawn_zones() + for beast: GrunkBeast in beasts: + if beast.get_spawn_zones().any(local_zones.has): + # Local beast found -- do not respawn. + # TODO: some kind of reaction? + return + + if beasts: + # Despawn a random beast + var beast: GrunkBeast = beasts.pick_random() + beast.queue_free() + # TODO -- despawn routine? + + # Spawn a new beast + spawn_beast_near_player() + + +func on_alarm_triggered(_source: GunkAlarm) -> void: + # Once alert level has maxed out, spawn a new beast with every alarm! + if World.instance.manager.alert_level >= WorldManager.MAX_ALERT: + spawn_beast_near_player() func on_alert_raised(new_level: int) -> void: @@ -47,38 +105,38 @@ func on_alert_raised(new_level: int) -> void: pass 1: # LEVEL 1: PASSIVE - # Beast avoids the player. - # Set up meet-spook. - # Get closest MeetSpook point to player. - # TODO revise + # This one's a freebie + # The first time this is reached, trigger a story event + # TODO pass 2: # LEVEL 2: AGGRESSIVE - # Beast pursues player on sight. - spawn_beast() + # Spawn a beast near the player + spawn_beast_near_player() 3: # LEVEL 3: PREDATORY - # Beast pursues player relentlessly. - # The logic for this behavior change is handled directly in the GrunkBeast AI. - pass + # Respawn beast near player if there isn't one. + # If there IS a beast near the player, it'll just get angrier. + respawn_beast_near_player() 4: # LEVEL 4: SWARMING - # Many beasts spawn, overwhelming the player. - spawn_many_beasts() + # Try to respawn beast near player again. + # Internal beast logic also gets more aggressive. + respawn_beast_near_player() 5: # LEVEL 5: FUN - # Just kill that fool! - pass # TODO + # From this point on, a NEW beast will spawn near the player with each alarm! + pass func on_alert_cleared() -> void: # Destroy all grunk beasts - for b: Node in World.instance.get_tree().get_nodes_in_group(BEAST_GROUP): + for b: Node in World.instance.get_tree().get_nodes_in_group(GrunkBeast.GROUP): b.queue_free() # And spawn one back in, if needed if World.instance.manager.alert_level >= 2: - spawn_beast() + spawn_beast_near_player() ## Set the state of spooky effects after a level is initialized & any save state is loaded. diff --git a/src/world/world.gd b/src/world/world.gd index a2a7836..34925c1 100644 --- a/src/world/world.gd +++ b/src/world/world.gd @@ -48,6 +48,7 @@ func _ready() -> void: World.instance = self manager.alert_raised.connect(spook_manager.on_alert_raised) manager.alert_cleared.connect(spook_manager.on_alert_cleared) + manager.alarm_triggered.connect(spook_manager.on_alarm_triggered) manager.player_dead.connect(on_player_death) if initial_level: load_level(initial_level) diff --git a/src/world/world.tscn b/src/world/world.tscn index faf7b8c..2be585f 100644 --- a/src/world/world.tscn +++ b/src/world/world.tscn @@ -13,6 +13,7 @@ volume_db = -14.0 [node name="World" type="Node"] script = ExtResource("1_1k4gi") +pause_enabled = null manager = ExtResource("2_5kmgb") spook_manager = ExtResource("3_l0av5") pause_music_effect = SubResource("AudioEffectAmplify_5kmgb") diff --git a/utilities/sandbox/sandbox.gd b/utilities/sandbox/sandbox.gd index 61510e1..f5c28e2 100644 --- a/utilities/sandbox/sandbox.gd +++ b/utilities/sandbox/sandbox.gd @@ -1 +1,9 @@ extends Node + + +func _ready() -> void: + #var untyped_array: Array = ["a", "b", "c", "d"] + var untyped_array: Array = [8, 6, 7, 5] + var typed_array: Array[String] = [] + typed_array.assign(untyped_array) + print(typed_array) diff --git a/utilities/sandbox/sandbox.tscn b/utilities/sandbox/sandbox.tscn index 1dc9457..08c0851 100644 --- a/utilities/sandbox/sandbox.tscn +++ b/utilities/sandbox/sandbox.tscn @@ -17,8 +17,9 @@ script = ExtResource("1_mxso2") [node name="BeehaveTree" type="Node" parent="." node_paths=PackedStringArray("blackboard", "actor")] script = ExtResource("2_fjanr") +enabled = false tick_rate = 5 -blackboard = NodePath("@Node@86400") +blackboard = NodePath("@Node@174947") actor = NodePath("..") metadata/_custom_type_script = "uid://bb0t2ovl7wifo" @@ -60,7 +61,7 @@ script = ExtResource("4_1rbkg") metadata/_custom_type_script = "uid://yar3g43pb3fm" [node name="Arrow" type="Node3D" parent="." node_paths=PackedStringArray("target")] -transform = Transform3D(-0.555686, 0, 0.831392, 0, 1, 0, -0.831392, 0, -0.555686, 0, 0, 0) +transform = Transform3D(-0.555688, 0, 0.831391, 0, 1, 0, -0.831391, 0, -0.555688, 0, 0, 0) script = ExtResource("8_f6f0v") target = NodePath("../ArrowTarget")