generated from krampus/template-godot4
Beast can't spawn right next to player
This commit is contained in:
parent
850127ba85
commit
77c5d46dd5
@ -261,6 +261,7 @@ locale/translations=PackedStringArray("res://assets/text/text.en.translation")
|
|||||||
3d_physics/layer_7="Prop Physics"
|
3d_physics/layer_7="Prop Physics"
|
||||||
3d_physics/layer_8="Beam Passthrough"
|
3d_physics/layer_8="Beam Passthrough"
|
||||||
3d_physics/layer_9="Beast Spawn Zones"
|
3d_physics/layer_9="Beast Spawn Zones"
|
||||||
|
3d_physics/layer_10="Beast Spawn Exclusion"
|
||||||
|
|
||||||
[physics]
|
[physics]
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=71 format=3 uid="uid://bwe2jdmvinhqd"]
|
[gd_scene load_steps=72 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://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"]
|
[ext_resource type="Script" uid="uid://cx1yt0drthpw3" path="res://src/player/camera_controller.gd" id="2_veeqv"]
|
||||||
@ -187,6 +187,9 @@ height = 1.9
|
|||||||
radius = 0.4
|
radius = 0.4
|
||||||
height = 1.2
|
height = 1.2
|
||||||
|
|
||||||
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_utg71"]
|
||||||
|
radius = 1.6
|
||||||
|
|
||||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_8ydov"]
|
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_8ydov"]
|
||||||
random_pitch = 1.1
|
random_pitch = 1.1
|
||||||
streams_count = 6
|
streams_count = 6
|
||||||
@ -716,6 +719,7 @@ collision_mask = 256
|
|||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="CameraPosition/CameraPivot/SpawnZoneFinder"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="CameraPosition/CameraPivot/SpawnZoneFinder"]
|
||||||
shape = SubResource("SphereShape3D_utg71")
|
shape = SubResource("SphereShape3D_utg71")
|
||||||
|
debug_color = Color(0.602755, 0.367301, 1, 0.42)
|
||||||
|
|
||||||
[node name="StandingCollider" type="CollisionShape3D" parent="."]
|
[node name="StandingCollider" type="CollisionShape3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0)
|
||||||
@ -729,6 +733,14 @@ disabled = true
|
|||||||
[node name="PlayerHUD" parent="." instance=ExtResource("5_jvafu")]
|
[node name="PlayerHUD" parent="." instance=ExtResource("5_jvafu")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
||||||
|
[node name="BeastSpawnExclusionZone" type="Area3D" parent="."]
|
||||||
|
collision_layer = 512
|
||||||
|
collision_mask = 0
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="BeastSpawnExclusionZone"]
|
||||||
|
shape = SubResource("CylinderShape3D_utg71")
|
||||||
|
debug_color = Color(0.602755, 0.367301, 1, 0.42)
|
||||||
|
|
||||||
[node name="FootstepController" type="Node3D" parent="."]
|
[node name="FootstepController" type="Node3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
|
||||||
|
@ -2,18 +2,14 @@ class_name BeastSpawnZone extends Area3D
|
|||||||
## An area which contains and manages prioritized BeastSpawners.
|
## An area which contains and manages prioritized BeastSpawners.
|
||||||
|
|
||||||
|
|
||||||
## Return the list of spawners in this area with the highest spawn priority
|
func _ready() -> void:
|
||||||
func get_priority_spawners() -> Array[BeastSpawner]:
|
# Adjust position to very slightly above placement position for raycasts
|
||||||
var spawns: Array[BeastSpawner] = []
|
global_position.y += 0.001
|
||||||
var max_priority: int = -1
|
|
||||||
for spawner: BeastSpawner in get_spawners():
|
|
||||||
if spawner.spawn_priority > max_priority:
|
|
||||||
spawns = [spawner]
|
|
||||||
max_priority = spawner.spawn_priority
|
|
||||||
elif spawner.spawn_priority == max_priority:
|
|
||||||
spawns.append(spawner)
|
|
||||||
|
|
||||||
return spawns
|
|
||||||
|
## Return the list of all non-excluded spawners in this zone
|
||||||
|
func get_valid_spawners() -> Array[BeastSpawner]:
|
||||||
|
return get_spawners().filter(func(s: BeastSpawner) -> bool: return s.can_spawn())
|
||||||
|
|
||||||
|
|
||||||
## Return the list of all spawners in this zone
|
## Return the list of all spawners in this zone
|
||||||
|
@ -6,13 +6,22 @@ const GROUP = "BeastSpawnPoint"
|
|||||||
## Scene to instantiate
|
## Scene to instantiate
|
||||||
@export var beast_scene: PackedScene
|
@export var beast_scene: PackedScene
|
||||||
|
|
||||||
|
## Area for checking spawn exclusion
|
||||||
|
@export var spawn_exclusion_area: Area3D
|
||||||
|
|
||||||
## Spawners with higher priority will be picked first
|
## Spawners with higher priority will be picked first
|
||||||
@export var spawn_priority: int = 0
|
@export var spawn_priority: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
## Create a new GrunkBeast instance
|
||||||
func instantiate() -> GrunkBeast:
|
func instantiate() -> GrunkBeast:
|
||||||
return beast_scene.instantiate()
|
return beast_scene.instantiate()
|
||||||
|
|
||||||
|
|
||||||
|
## Is this spawner able to spawn a beast (e.g. isn't occluded by a spawn excluder)?
|
||||||
|
func can_spawn() -> bool:
|
||||||
|
return (not spawn_exclusion_area.has_overlapping_areas()) if spawn_exclusion_area else true
|
||||||
|
|
||||||
|
|
||||||
func do_spawn() -> void:
|
func do_spawn() -> void:
|
||||||
pass # Implemented in derived type
|
pass # Implemented in derived type
|
||||||
|
@ -1,11 +1,25 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://c8vbjgol5nenc"]
|
[gd_scene load_steps=4 format=3 uid="uid://c8vbjgol5nenc"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://cqildi0gndwp2" path="res://src/world/grunk_beast/beast_spawner/floor_spawner.gd" id="1_hrlgt"]
|
[ext_resource type="Script" uid="uid://cqildi0gndwp2" path="res://src/world/grunk_beast/beast_spawner/floor_spawner.gd" id="1_hrlgt"]
|
||||||
[ext_resource type="PackedScene" uid="uid://ehf5sg3ahvbf" path="res://src/world/grunk_beast/grunk_beast.tscn" id="2_dgp11"]
|
[ext_resource type="PackedScene" uid="uid://ehf5sg3ahvbf" path="res://src/world/grunk_beast/grunk_beast.tscn" id="2_dgp11"]
|
||||||
|
|
||||||
[node name="FloorSpawner" type="Node3D" groups=["BeastSpawnPoint"]]
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_yfsqi"]
|
||||||
|
height = 0.1
|
||||||
|
radius = 1.2
|
||||||
|
|
||||||
|
[node name="FloorSpawner" type="Node3D" node_paths=PackedStringArray("spawn_exclusion_area") groups=["BeastSpawnPoint"]]
|
||||||
script = ExtResource("1_hrlgt")
|
script = ExtResource("1_hrlgt")
|
||||||
beast_scene = ExtResource("2_dgp11")
|
beast_scene = ExtResource("2_dgp11")
|
||||||
|
spawn_exclusion_area = NodePath("SpawnExclusionArea")
|
||||||
spawn_priority = 1
|
spawn_priority = 1
|
||||||
|
|
||||||
[node name="Marker3D" type="Marker3D" parent="."]
|
[node name="Marker3D" type="Marker3D" parent="."]
|
||||||
|
|
||||||
|
[node name="SpawnExclusionArea" type="Area3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0)
|
||||||
|
collision_layer = 0
|
||||||
|
collision_mask = 512
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="SpawnExclusionArea"]
|
||||||
|
shape = SubResource("CylinderShape3D_yfsqi")
|
||||||
|
debug_color = Color(0.602755, 0.367301, 1, 0.42)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=5 format=3 uid="uid://5vh7mnjavlle"]
|
[gd_scene load_steps=6 format=3 uid="uid://5vh7mnjavlle"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://cqildi0gndwp2" path="res://src/world/grunk_beast/beast_spawner/floor_spawner.gd" id="1_42oks"]
|
[ext_resource type="Script" uid="uid://cqildi0gndwp2" path="res://src/world/grunk_beast/beast_spawner/floor_spawner.gd" id="1_42oks"]
|
||||||
[ext_resource type="PackedScene" uid="uid://ehf5sg3ahvbf" path="res://src/world/grunk_beast/grunk_beast.tscn" id="2_e5rh0"]
|
[ext_resource type="PackedScene" uid="uid://ehf5sg3ahvbf" path="res://src/world/grunk_beast/grunk_beast.tscn" id="2_e5rh0"]
|
||||||
@ -12,9 +12,14 @@ top_radius = 1.2
|
|||||||
bottom_radius = 1.2
|
bottom_radius = 1.2
|
||||||
height = 0.02
|
height = 0.02
|
||||||
|
|
||||||
[node name="TransientFloorSpawner" type="Node3D" groups=["BeastSpawnPoint"]]
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_e5rh0"]
|
||||||
|
height = 0.1
|
||||||
|
radius = 1.2
|
||||||
|
|
||||||
|
[node name="TransientFloorSpawner" type="Node3D" node_paths=PackedStringArray("spawn_exclusion_area") groups=["BeastSpawnPoint"]]
|
||||||
script = ExtResource("1_42oks")
|
script = ExtResource("1_42oks")
|
||||||
beast_scene = ExtResource("2_e5rh0")
|
beast_scene = ExtResource("2_e5rh0")
|
||||||
|
spawn_exclusion_area = NodePath("SpawnExclusionArea")
|
||||||
spawn_priority = 10
|
spawn_priority = 10
|
||||||
metadata/_custom_type_script = "uid://cqildi0gndwp2"
|
metadata/_custom_type_script = "uid://cqildi0gndwp2"
|
||||||
|
|
||||||
@ -29,4 +34,13 @@ debug_color = Color(0.980392, 0.854902, 0, 1)
|
|||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Area3D"]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="Area3D"]
|
||||||
mesh = SubResource("CylinderMesh_e5rh0")
|
mesh = SubResource("CylinderMesh_e5rh0")
|
||||||
|
|
||||||
|
[node name="SpawnExclusionArea" type="Area3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0)
|
||||||
|
collision_layer = 0
|
||||||
|
collision_mask = 512
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="SpawnExclusionArea"]
|
||||||
|
shape = SubResource("CylinderShape3D_e5rh0")
|
||||||
|
debug_color = Color(0.602755, 0.367301, 1, 0.42)
|
||||||
|
|
||||||
[connection signal="area_entered" from="Area3D" to="." method="queue_free" unbinds=1]
|
[connection signal="area_entered" from="Area3D" to="." method="queue_free" unbinds=1]
|
||||||
|
@ -30,6 +30,7 @@ func _ready() -> void:
|
|||||||
animation_player.speed_scale = time_scale_factor
|
animation_player.speed_scale = time_scale_factor
|
||||||
_sync_pivot_to_root()
|
_sync_pivot_to_root()
|
||||||
_update_transform()
|
_update_transform()
|
||||||
|
tree_exiting.connect(_end_player_rumble)
|
||||||
|
|
||||||
|
|
||||||
func _start_player_rumble() -> void:
|
func _start_player_rumble() -> void:
|
||||||
|
@ -8,7 +8,7 @@ func _get_best_spawners() -> Array[BeastSpawner]:
|
|||||||
# Get all spawners in the spawn zone(s) occupied by the player
|
# Get all spawners in the spawn zone(s) occupied by the player
|
||||||
var zones: Array[BeastSpawnZone] = Player.instance.get_spawn_zones()
|
var zones: Array[BeastSpawnZone] = Player.instance.get_spawn_zones()
|
||||||
for zone: BeastSpawnZone in zones:
|
for zone: BeastSpawnZone in zones:
|
||||||
spawners.append_array(zone.get_spawners())
|
spawners.append_array(zone.get_valid_spawners())
|
||||||
if spawners:
|
if spawners:
|
||||||
# Get spawners which player has unobstructed sightline to
|
# Get spawners which player has unobstructed sightline to
|
||||||
var visible_spawners := spawners.filter(
|
var visible_spawners := spawners.filter(
|
||||||
@ -32,7 +32,8 @@ func _get_best_spawners() -> Array[BeastSpawner]:
|
|||||||
# Fallback behavior: just get all spawners
|
# Fallback behavior: just get all spawners
|
||||||
print_debug("Falling back to all world spawners")
|
print_debug("Falling back to all world spawners")
|
||||||
spawners.assign(World.instance.get_tree().get_nodes_in_group(BeastSpawner.GROUP))
|
spawners.assign(World.instance.get_tree().get_nodes_in_group(BeastSpawner.GROUP))
|
||||||
return spawners
|
# Filter only valid spawners
|
||||||
|
return spawners.filter(func(s: BeastSpawner) -> bool: return s.can_spawn())
|
||||||
|
|
||||||
|
|
||||||
func _filter_top_priority(spawners: Array[BeastSpawner]) -> Array[BeastSpawner]:
|
func _filter_top_priority(spawners: Array[BeastSpawner]) -> Array[BeastSpawner]:
|
||||||
|
@ -86,4 +86,6 @@ When it's time to spawn a beast, we select a spawn point as follows:
|
|||||||
- If the player cannot see any spawn points for this zone, use the highest-priority priority spawn.
|
- If the player cannot see any spawn points for this zone, use the highest-priority priority spawn.
|
||||||
- If there are no priority spawns for this zone, use the default spawn with the highest priority.
|
- If there are no priority spawns for this zone, use the default spawn with the highest priority.
|
||||||
- If the player is not in a spawn zone or the spawn zone has no default spawns, use a randomly-select map-default spawn.
|
- If the player is not in a spawn zone or the spawn zone has no default spawns, use a randomly-select map-default spawn.
|
||||||
- If there are no map-default spawns, log an error and do not spawn a beast.
|
- If there are no map-default spawns, log an error and do not spawn a beast.
|
||||||
|
|
||||||
|
**ADDITIONALLY:** A spawn point touching the player will never be used.
|
Loading…
x
Reference in New Issue
Block a user