bug(goap): fixed unexpected AI behaviour

- Death now removes entity from awareness
- State failure now causes replan or goal reevaluation
This commit is contained in:
Sara 2024-08-01 14:40:20 +02:00
parent a2240797b8
commit 111485437c
36 changed files with 845 additions and 88 deletions

View file

@ -5,5 +5,6 @@ requirements_dict = {
"is_target_enemy": true "is_target_enemy": true
} }
desired_state_dict = { desired_state_dict = {
"is_health_safe": true,
"is_target_dead": true "is_target_dead": true
} }

BIN
godot/Environments/Models/KenneyTrains/Textures/colormap.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://tbbjaxpu1j3t"
path.bptc="res://.godot/imported/colormap.png-c612b8a2c517baff886ed02b9cf55c78.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://Environments/Models/KenneyTrains/Textures/colormap.png"
dest_files=["res://.godot/imported/colormap.png-c612b8a2c517baff886ed02b9cf55c78.bptc.ctex"]
[params]
compress/mode=2
compress/high_quality=true
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=1
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View file

@ -0,0 +1,7 @@
[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://ct2ljsg8osoho"]
[ext_resource type="Texture2D" uid="uid://tbbjaxpu1j3t" path="res://Environments/Models/KenneyTrains/Textures/colormap.png" id="1_c3vim"]
[resource]
albedo_texture = ExtResource("1_c3vim")
texture_filter = 1

BIN
godot/Environments/Models/KenneyTrains/track-detailed.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://xrtlqanc8yyv"
path="res://.godot/imported/track-detailed.glb-cb63eddaf4863d72bc084f0bae4658df.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/track-detailed.glb"
dest_files=["res://.godot/imported/track-detailed.glb-cb63eddaf4863d72bc084f0bae4658df.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
godot/Environments/Models/KenneyTrains/track-rail.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://4pw4pe5q3ylw"
path="res://.godot/imported/track-rail.glb-cc5ec96fcb9a948b443688344c03452c.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/track-rail.glb"
dest_files=["res://.godot/imported/track-rail.glb-cc5ec96fcb9a948b443688344c03452c.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
godot/Environments/Models/KenneyTrains/track-segment.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://d0hk1u68k3quf"
path="res://.godot/imported/track-segment.glb-dff5b7bbac21060efccec6063b016ffc.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/track-segment.glb"
dest_files=["res://.godot/imported/track-segment.glb-dff5b7bbac21060efccec6063b016ffc.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

View file

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://ioehfjtc1bc5"
path="res://.godot/imported/track-single-detailed.glb-b12f58c0c636fb34acddf50702af90c2.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/track-single-detailed.glb"
dest_files=["res://.godot/imported/track-single-detailed.glb-b12f58c0c636fb34acddf50702af90c2.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
godot/Environments/Models/KenneyTrains/track-single.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://csekns1nwgnhy"
path="res://.godot/imported/track-single.glb-65dcb07e0c0a70b6cf9aaae0d9f61879.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/track-single.glb"
dest_files=["res://.godot/imported/track-single.glb-65dcb07e0c0a70b6cf9aaae0d9f61879.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
godot/Environments/Models/KenneyTrains/track.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://ulvv4o73s48a"
path="res://.godot/imported/track.glb-b36e9cab9a2071a753d5fcc3d5f7285d.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/track.glb"
dest_files=["res://.godot/imported/track.glb-b36e9cab9a2071a753d5fcc3d5f7285d.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=2.5
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

View file

@ -0,0 +1,41 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://byds62lj0osme"
path="res://.godot/imported/train-tram-classic.glb-92ae2316424a784c9bdf16ce430188e4.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/train-tram-classic.glb"
dest_files=["res://.godot/imported/train-tram-classic.glb-92ae2316424a784c9bdf16ce430188e4.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=3
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={
"materials": {
"colormap": {
"use_external/enabled": true,
"use_external/path": "res://Environments/Models/KenneyTrains/kenney_trains.tres"
}
}
}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
godot/Environments/Models/KenneyTrains/train-tram-modern.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,41 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cv3l44qdi8e56"
path="res://.godot/imported/train-tram-modern.glb-9bf861f745e2244367e9dd7d1d088e88.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/train-tram-modern.glb"
dest_files=["res://.godot/imported/train-tram-modern.glb-9bf861f745e2244367e9dd7d1d088e88.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=2.5
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={
"materials": {
"colormap": {
"use_external/enabled": true,
"use_external/path": "res://Environments/Models/KenneyTrains/kenney_trains.tres"
}
}
}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
godot/Environments/Models/KenneyTrains/train-tram-round.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,41 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://b2h6cfcyek7kk"
path="res://.godot/imported/train-tram-round.glb-fda8e6f4aa55231be0f262910c5c1d52.scn"
[deps]
source_file="res://Environments/Models/KenneyTrains/train-tram-round.glb"
dest_files=["res://.godot/imported/train-tram-round.glb-fda8e6f4aa55231be0f262910c5c1d52.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={
"materials": {
"colormap": {
"use_external/enabled": true,
"use_external/path": "res://Environments/Models/KenneyTrains/kenney_trains.tres"
}
}
}
gltf/naming_version=1
gltf/embedded_image_handling=1

View file

@ -0,0 +1,15 @@
[gd_scene load_steps=3 format=3 uid="uid://duuvete30t8sv"]
[ext_resource type="PackedScene" uid="uid://cv3l44qdi8e56" path="res://Environments/Models/KenneyTrains/train-tram-modern.glb" id="1_isbsa"]
[sub_resource type="BoxShape3D" id="BoxShape3D_wbdhh"]
size = Vector3(2.67188, 4.54761, 6.56006)
[node name="ModernTrain" type="StaticBody3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.97447, 0, 4.90353)
[node name="train-tram-modern2" parent="." instance=ExtResource("1_isbsa")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7135, 0.143799)
shape = SubResource("BoxShape3D_wbdhh")

View file

@ -1,9 +1,13 @@
[gd_scene load_steps=9 format=3 uid="uid://ba17jrcaduowj"] [gd_scene load_steps=9 format=3 uid="uid://ba17jrcaduowj"]
[ext_resource type="Goal" uid="uid://b4i4e34046n44" path="res://AI/defeat_enemy_unit.tres" id="1_b1qo1"] [ext_resource type="Goal" uid="uid://b4i4e34046n44" path="res://AI/defeat_enemy_unit.tres" id="1_b1qo1"]
[ext_resource type="Goal" uid="uid://btv8ultseri3q" path="res://AI/maintain_health.tres" id="2_k42dl"]
[ext_resource type="AnimationLibrary" uid="uid://crkh5gahl2ci6" path="res://Animation/bean_characters.res" id="2_lrpu6"] [ext_resource type="AnimationLibrary" uid="uid://crkh5gahl2ci6" path="res://Animation/bean_characters.res" id="2_lrpu6"]
[sub_resource type="Goal" id="Goal_1c3rq"]
desired_state_dict = {
"is_health_safe": true
}
[sub_resource type="SphereShape3D" id="SphereShape3D_5pqvg"] [sub_resource type="SphereShape3D" id="SphereShape3D_5pqvg"]
radius = 8.42531 radius = 8.42531
@ -27,7 +31,7 @@ collision_layer = 6
collision_mask = 0 collision_mask = 0
[node name="ActorWorldState" type="EnemyWorldState" parent="."] [node name="ActorWorldState" type="EnemyWorldState" parent="."]
editor_available_goals = [ExtResource("2_k42dl"), ExtResource("1_b1qo1")] editor_available_goals = [ExtResource("1_b1qo1"), SubResource("Goal_1c3rq")]
unique_name_in_owner = true unique_name_in_owner = true
[node name="Planner" type="Planner" parent="."] [node name="Planner" type="Planner" parent="."]
@ -35,6 +39,8 @@ actions_inspector = [3, 2, 4, 5, 6]
unique_name_in_owner = true unique_name_in_owner = true
[node name="EntityHealth" type="EntityHealth" parent="."] [node name="EntityHealth" type="EntityHealth" parent="."]
injury_max = 20
wounds_max = 20
unique_name_in_owner = true unique_name_in_owner = true
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."] [node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]

View file

@ -1,14 +1,16 @@
[gd_scene load_steps=11 format=3 uid="uid://c62s1jmtgajjk"] [gd_scene load_steps=17 format=3 uid="uid://c62s1jmtgajjk"]
[ext_resource type="PackedScene" uid="uid://dsalxxq3xs842" path="res://rts_game_mode.tscn" id="1_4nchg"] [ext_resource type="PackedScene" uid="uid://dsalxxq3xs842" path="res://rts_game_mode.tscn" id="1_4nchg"]
[ext_resource type="Environment" uid="uid://cnfk8yrvklysq" path="res://Environments/default_environment.tres" id="2_jq6bw"] [ext_resource type="Environment" uid="uid://cnfk8yrvklysq" path="res://Environments/default_environment.tres" id="2_jq6bw"]
[ext_resource type="PackedScene" uid="uid://pme230qx1377" path="res://GameObjects/player_unit.tscn" id="3_wl7wm"] [ext_resource type="PackedScene" uid="uid://pme230qx1377" path="res://GameObjects/player_unit.tscn" id="3_wl7wm"]
[ext_resource type="PackedScene" uid="uid://ba17jrcaduowj" path="res://GameObjects/enemy_unit.tscn" id="4_0o33v"] [ext_resource type="PackedScene" uid="uid://ba17jrcaduowj" path="res://GameObjects/enemy_unit.tscn" id="4_0o33v"]
[ext_resource type="PackedScene" uid="uid://c82s8vpaethtv" path="res://GameObjects/nav_marker.tscn" id="5_ta2oq"] [ext_resource type="PackedScene" uid="uid://c82s8vpaethtv" path="res://GameObjects/nav_marker.tscn" id="5_ta2oq"]
[ext_resource type="PackedScene" uid="uid://duuvete30t8sv" path="res://GameObjects/LevelProps/modern_train.tscn" id="6_favl6"]
[ext_resource type="PackedScene" uid="uid://ulvv4o73s48a" path="res://Environments/Models/KenneyTrains/track.glb" id="7_8fuqb"]
[sub_resource type="NavigationMesh" id="NavigationMesh_8a2j6"] [sub_resource type="NavigationMesh" id="NavigationMesh_8a2j6"]
vertices = PackedVector3Array(0, 0.4, -2, 1.75, 0.4, -3.25, 1.75, 0.4, -9.5, -0.75, 0.4, -0.25, 0, 0.4, -2, 1.75, 0.4, -9.5, -9.5, 0.4, -9.5, -9.5, 0.4, -0.25, 4.5, 0.4, -1.25, 4.5, 0.4, -0.5, 9.5, 0.4, -0.5, 3.25, 0.4, -2.5, 4.5, 0.4, -1.25, 9.5, 0.4, -0.5, 1.75, 0.4, -9.5, 1.75, 0.4, -3.25, 3.25, 0.4, -2.5, 9.5, 0.4, -0.5, 9.5, 0.4, -9.5, 1.75, 3.4, 1, 2.25, 3.4, 1, 3.5, 3.4, -0.5, 2.75, 3.4, -1.5, 1.5, 3.4, -2, 0.25, 3.4, -0.5, 3, 0.4, -0.5, 2.5, 0.4, -1.25, 1.5, 0.4, -1.5, 0.75, 0.4, -0.5, 1.75, 0.4, 0.5, 9.5, 0.4, -0.5, 4.5, 0.4, -0.5, 3.5, 0.4, 1.25, 9.5, 0.4, -0.5, 3.5, 0.4, 1.25, 2, 0.4, 2.25, 2, 0.4, 9.5, 9.5, 0.4, 9.5, 2, 0.4, 9.5, 2, 0.4, 2.25, 0, 0.4, 1, 0, 0.4, 1, -0.75, 0.4, -0.25, -9.5, 0.4, -0.25, -9.5, 0.4, 9.5, 2, 0.4, 9.5) vertices = PackedVector3Array(-29.401, 0.457877, -9.71053, -29.401, 0.457877, -1.21053, -10.901, 0.457877, -1.21053, -10.901, 0.457877, -9.71053, 3.59903, 0.457877, -1.21053, 3.59903, 0.457877, -2.71053, -8.15097, 0.457877, -2.71053, -9.40097, 0.457877, -1.21053, -8.40097, 0.457877, -6.46053, 4.09903, 0.457877, -6.71053, 4.09903, 0.457877, -9.71053, -9.40097, 0.457877, -9.71053, -9.40097, 0.457877, -1.21053, -8.15097, 0.457877, -2.71053, -8.40097, 0.457877, -6.46053, -9.40097, 0.457877, -9.71053, 6.34903, 0.457877, -2.96053, 5.84903, 0.457877, -2.71053, 9.59903, 0.457877, -2.46053, 4.09903, 0.457877, -9.71053, 4.09903, 0.457877, -6.71053, 6.34903, 0.457877, -6.46053, 9.59903, 0.457877, -9.71053, 6.34903, 0.457877, -6.46053, 6.34903, 0.457877, -2.96053, 9.59903, 0.457877, -2.46053, 9.59903, 0.457877, -9.71053, -7.40097, 4.70788, -5.71053, -7.40097, 4.70788, -3.71053, -1.65097, 4.70788, -3.71053, -1.65097, 4.70788, -5.71053, -0.400969, 4.70788, -5.71053, -0.400969, 4.70788, -3.71053, 5.34903, 4.70788, -3.71053, 5.34903, 4.70788, -5.71053, -7.15097, 0.457877, -5.46053, -7.15097, 0.457877, -3.96053, -1.90097, 0.457877, -3.96053, -1.90097, 0.457877, -5.46053, -0.150969, 0.457877, -5.46053, -0.150969, 0.457877, -3.96053, 5.09903, 0.457877, -3.96053, 5.09903, 0.457877, -5.46053, 3.59903, 0.457877, -2.71053, 3.59903, 0.457877, -1.21053, 4.09903, 0.457877, -0.960529, 5.84903, 0.457877, -2.71053, 3.84903, 0.457877, 0.289471, 1.84903, 0.457877, 0.289471, 1.84903, 0.457877, 5.28947, 7.09903, 0.457877, 5.28947, 5.84903, 0.457877, -2.71053, 4.09903, 0.457877, -0.960529, 3.84903, 0.457877, 0.289471, 7.09903, 0.457877, 5.28947, 9.59903, 0.457877, 8.78947, 9.59903, 0.457877, -2.46053, 7.09903, 0.457877, 5.28947, 7.34903, 0.457877, 8.78947, 9.59903, 0.457877, 8.78947, -29.401, 0.457877, 3.78947, -27.151, 0.457877, 3.28947, -26.901, 0.457877, 1.28947, -29.401, 0.457877, 0.289471, -12.651, 0.457877, 1.28947, -5.15097, 0.457877, 0.289471, -29.401, 0.457877, 0.289471, -26.901, 0.457877, 1.28947, -12.401, 0.457877, 5.03947, -12.901, 0.457877, 5.28947, -12.901, 0.457877, 8.78947, -7.40097, 0.457877, 8.78947, -7.40097, 0.457877, 5.53947, -7.40097, 0.457877, 5.53947, -5.15097, 0.457877, 5.28947, -5.15097, 0.457877, 0.289471, -12.651, 0.457877, 1.28947, -12.401, 0.457877, 5.03947, -5.15097, 0.457877, 5.28947, 1.84903, 0.457877, 5.28947, 1.84903, 0.457877, 0.289471, -5.15097, 0.457877, 0.289471, -26.151, 4.70788, 2.28947, -26.151, 4.70788, 4.28947, -20.401, 4.70788, 4.28947, -20.401, 4.70788, 2.28947, -19.151, 4.70788, 2.28947, -19.151, 4.70788, 4.28947, -13.401, 4.70788, 4.28947, -13.401, 4.70788, 2.28947, -25.901, 0.457877, 2.53947, -25.901, 0.457877, 4.03947, -20.651, 0.457877, 4.03947, -20.651, 0.457877, 2.53947, -18.901, 0.457877, 2.53947, -18.901, 0.457877, 4.03947, -13.651, 0.457877, 4.03947, -13.651, 0.457877, 2.53947, -26.901, 0.457877, 5.28947, -27.151, 0.457877, 3.28947, -29.401, 0.457877, 3.78947, -29.401, 0.457877, 8.78947, -12.901, 0.457877, 8.78947, -12.901, 0.457877, 5.28947, -26.901, 0.457877, 5.28947, -29.401, 0.457877, 8.78947, -6.40097, 4.70788, 6.28947, -6.40097, 4.70788, 8.28947, -0.650969, 4.70788, 8.28947, -0.650969, 4.70788, 6.28947, 0.599031, 4.70788, 6.28947, 0.599031, 4.70788, 8.28947, 6.34903, 4.70788, 8.28947, 6.34903, 4.70788, 6.28947, -6.15097, 0.457877, 6.53947, -6.15097, 0.457877, 8.03947, -0.900969, 0.457877, 8.03947, -0.900969, 0.457877, 6.53947, 0.849031, 0.457877, 6.53947, 0.849031, 0.457877, 8.03947, 6.09903, 0.457877, 8.03947, 6.09903, 0.457877, 6.53947)
polygons = [PackedInt32Array(2, 1, 0), PackedInt32Array(4, 3, 5), PackedInt32Array(5, 3, 7), PackedInt32Array(5, 7, 6), PackedInt32Array(10, 9, 8), PackedInt32Array(13, 12, 11), PackedInt32Array(15, 14, 16), PackedInt32Array(16, 14, 18), PackedInt32Array(16, 18, 17), PackedInt32Array(20, 19, 21), PackedInt32Array(21, 19, 22), PackedInt32Array(22, 19, 23), PackedInt32Array(23, 19, 24), PackedInt32Array(26, 25, 27), PackedInt32Array(27, 25, 28), PackedInt32Array(28, 25, 29), PackedInt32Array(32, 31, 30), PackedInt32Array(34, 33, 35), PackedInt32Array(35, 33, 36), PackedInt32Array(36, 33, 37), PackedInt32Array(40, 39, 38), PackedInt32Array(42, 41, 43), PackedInt32Array(43, 41, 44), PackedInt32Array(44, 41, 45)] polygons = [PackedInt32Array(3, 2, 0), PackedInt32Array(0, 2, 1), PackedInt32Array(5, 4, 6), PackedInt32Array(6, 4, 7), PackedInt32Array(9, 8, 10), PackedInt32Array(10, 8, 11), PackedInt32Array(13, 12, 14), PackedInt32Array(14, 12, 15), PackedInt32Array(16, 18, 17), PackedInt32Array(20, 19, 21), PackedInt32Array(21, 19, 22), PackedInt32Array(24, 23, 25), PackedInt32Array(25, 23, 26), PackedInt32Array(30, 29, 27), PackedInt32Array(27, 29, 28), PackedInt32Array(34, 33, 31), PackedInt32Array(31, 33, 32), PackedInt32Array(38, 37, 35), PackedInt32Array(35, 37, 36), PackedInt32Array(42, 41, 39), PackedInt32Array(39, 41, 40), PackedInt32Array(44, 43, 45), PackedInt32Array(45, 43, 46), PackedInt32Array(48, 47, 49), PackedInt32Array(49, 47, 50), PackedInt32Array(52, 51, 53), PackedInt32Array(53, 51, 56), PackedInt32Array(53, 56, 54), PackedInt32Array(54, 56, 55), PackedInt32Array(59, 58, 57), PackedInt32Array(61, 60, 62), PackedInt32Array(62, 60, 63), PackedInt32Array(67, 66, 64), PackedInt32Array(64, 66, 65), PackedInt32Array(69, 68, 70), PackedInt32Array(70, 68, 72), PackedInt32Array(70, 72, 71), PackedInt32Array(74, 73, 75), PackedInt32Array(75, 73, 77), PackedInt32Array(75, 77, 76), PackedInt32Array(81, 80, 78), PackedInt32Array(78, 80, 79), PackedInt32Array(85, 84, 82), PackedInt32Array(82, 84, 83), PackedInt32Array(89, 88, 86), PackedInt32Array(86, 88, 87), PackedInt32Array(93, 92, 90), PackedInt32Array(90, 92, 91), PackedInt32Array(97, 96, 94), PackedInt32Array(94, 96, 95), PackedInt32Array(99, 98, 100), PackedInt32Array(100, 98, 101), PackedInt32Array(103, 102, 104), PackedInt32Array(104, 102, 105), PackedInt32Array(109, 108, 106), PackedInt32Array(106, 108, 107), PackedInt32Array(113, 112, 110), PackedInt32Array(110, 112, 111), PackedInt32Array(117, 116, 114), PackedInt32Array(114, 116, 115), PackedInt32Array(121, 120, 118), PackedInt32Array(118, 120, 119)]
geometry_parsed_geometry_type = 1 geometry_parsed_geometry_type = 1
geometry_collision_mask = 4294967289 geometry_collision_mask = 4294967289
@ -19,83 +21,353 @@ size = Vector3(20, 0.1, 20)
size = Vector2(20, 20) size = Vector2(20, 20)
[sub_resource type="BoxShape3D" id="BoxShape3D_nlgbx"] [sub_resource type="BoxShape3D" id="BoxShape3D_nlgbx"]
size = Vector3(3, 3, 3) size = Vector3(0.445312, 3, 33.2832)
[sub_resource type="BoxMesh" id="BoxMesh_o000f"] [sub_resource type="BoxMesh" id="BoxMesh_o000f"]
size = Vector3(3, 3, 3) size = Vector3(0.445, 5, 33.283)
[sub_resource type="BoxShape3D" id="BoxShape3D_kix0k"]
size = Vector3(0.445312, 3, 9.93888)
[sub_resource type="BoxMesh" id="BoxMesh_u6sgs"]
size = Vector3(0.445, 5, 9.939)
[sub_resource type="BoxShape3D" id="BoxShape3D_ij4pv"]
size = Vector3(0.445312, 3, 40)
[sub_resource type="BoxMesh" id="BoxMesh_4sjak"]
size = Vector3(0.445, 5, 40)
[node name="TestLevel" type="Level3D"] [node name="TestLevel" type="Level3D"]
game_mode_prototype = ExtResource("1_4nchg") game_mode_prototype = ExtResource("1_4nchg")
[node name="NavRoom" type="NavRoom" parent="."]
[node name="CoverMarker" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(0.999999, 0, -0.00101254, 0, 1, 0, 0.00101254, 0, 0.999999, 2.03728, 0.457877, -1.25)
[node name="CoverMarker2" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.999809, 0, 0.0195462, 0, 1, 0, -0.0195462, 0, -0.999809, 2.12204, 0.457877, 0.5)
[node name="CoverMarker3" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.999809, 0, 0.0195462, 0, 1, 0, -0.0195462, 0, -0.999809, 3.86039, 0.457877, -6.70576)
[node name="CoverMarker4" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.999809, 0, 0.0195462, 0, 1, 0, -0.0195462, 0, -0.999809, 3.79568, 0.457877, -2.71053)
[node name="CoverMarker5" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.999809, 0, 0.0195462, 0, 1, 0, -0.0195462, 0, -0.999809, -5.98582, 0.457877, -6.54835)
[node name="CoverMarker7" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.00790617, 0, -0.999969, 0, 1, 0, 0.999969, 0, -0.00790617, 7.44158, 0.457877, 7.07028)
[node name="CoverMarker8" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.0168068, 0, 0.999859, 0, 1, 0, -0.999859, 0, -0.0168068, -7.40097, 0.457877, 6.86448)
[node name="CoverMarker9" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.0168068, 0, 0.999859, 0, 1, 0, -0.999859, 0, -0.0168068, -27.1322, 0.457877, 3.139)
[node name="CoverMarker10" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(0.0017105, 0, -0.999999, 0, 1, 0, 0.999999, 0, 0.0017105, -12.5171, 0.457877, 3.29715)
[node name="CoverMarker11" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.999853, 0, -0.0171558, 0, 1, 0, 0.0171558, 0, -0.999853, -14.3772, 0.457877, 5.28947)
[node name="CoverMarker12" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.999853, 0, -0.0171558, 0, 1, 0, 0.0171558, 0, -0.999853, -24.8171, 0.457877, 5.28947)
[node name="CoverMarker13" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(0.999752, 0, 0.0222512, 0, 1, 0, -0.0222512, 0, 0.999752, -24.8503, 0.457877, 1.28947)
[node name="CoverMarker14" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(0.999752, 0, 0.0222512, 0, 1, 0, -0.0222512, 0, 0.999752, -14.5514, 0.457877, 1.28947)
[node name="CoverMarker6" parent="NavRoom" instance=ExtResource("5_ta2oq")]
marker_type = 1
transform = Transform3D(-0.999809, 0, 0.0195462, 0, 1, 0, -0.0195462, 0, -0.999809, -6.0537, 0.457877, -2.71053)
[node name="GenericMarker" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.26055, 0.457877, 3.19418)
[node name="GenericMarker2" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.32601, 0.457877, 2.9396)
[node name="GenericMarker3" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.90526, 0.457877, 4.00055)
[node name="GenericMarker4" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.4032, 0.457877, -1.47269)
[node name="GenericMarker5" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.09835, 0.457877, -8.09851)
[node name="GenericMarker9" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.39484, 0.457877, -8.36227)
[node name="GenericMarker6" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.37477, 0.457877, -1.84165)
[node name="GenericMarker7" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -23.2121, 0.457877, 7.33733)
[node name="GenericMarker8" parent="NavRoom" instance=ExtResource("5_ta2oq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14.1914, 0.457877, 7.23182)
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] [node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = ExtResource("2_jq6bw") environment = ExtResource("2_jq6bw")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="WorldEnvironment"]
transform = Transform3D(-0.439892, -0.837631, 0.323836, -1.66089e-11, 0.360599, 0.932721, -0.898051, 0.410296, -0.158625, 0, 1.28927, 0)
light_color = Color(1, 0.926667, 0.78, 1)
shadow_enabled = true
shadow_opacity = 0.8
shadow_blur = 0.1
[node name="NavigationRegion3D" type="NavigationRegion3D" parent="WorldEnvironment"] [node name="NavigationRegion3D" type="NavigationRegion3D" parent="WorldEnvironment"]
navigation_mesh = SubResource("NavigationMesh_8a2j6") navigation_mesh = SubResource("NavigationMesh_8a2j6")
[node name="StaticBody3D" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"] [node name="Floor" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"]
collision_layer = 5 collision_layer = 5
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/StaticBody3D"] [node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/Floor"]
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)
shape = SubResource("BoxShape3D_ubt1u") shape = SubResource("BoxShape3D_ubt1u")
[node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/StaticBody3D"] [node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/Floor"]
mesh = SubResource("PlaneMesh_hohcb") mesh = SubResource("PlaneMesh_hohcb")
skeleton = NodePath("../../../..") skeleton = NodePath("../../../..")
[node name="StaticBody3D2" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"] [node name="Floor2" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"]
transform = Transform3D(0.616308, 0, 0.787505, 0, 1, 0, -0.787505, 0, 0.616308, 1.88872, 1.48357, -0.533337) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.901, 0, 0)
collision_layer = 5 collision_layer = 5
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/StaticBody3D2"] [node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/Floor2"]
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)
shape = SubResource("BoxShape3D_ubt1u")
[node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/Floor2"]
mesh = SubResource("PlaneMesh_hohcb")
skeleton = NodePath("../../../..")
[node name="Wall" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.88872, 1.48357, -0.533337)
collision_layer = 5
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/Wall"]
transform = Transform3D(1, 0, -5.22249e-13, 0, 1, 0, 5.22249e-13, 0, 1, -0.0837823, -0.110484, -15.1446)
shape = SubResource("BoxShape3D_nlgbx") shape = SubResource("BoxShape3D_nlgbx")
[node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/StaticBody3D2"] [node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/Wall"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.084, 0.912, -15.145)
mesh = SubResource("BoxMesh_o000f") mesh = SubResource("BoxMesh_o000f")
skeleton = NodePath("../../../..") skeleton = NodePath("../../../..")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="WorldEnvironment"] [node name="Wall2" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"]
transform = Transform3D(-0.030678, -0.932282, 0.36043, 0, 0.360599, 0.932721, -0.999529, 0.028614, -0.0110625, 0, 1.28927, 0) transform = Transform3D(1, 0, 1.06581e-14, 0, 1, 0, -1.06581e-14, 0, 1, -10.0861, 1.48357, -5.24109)
light_color = Color(1, 0.926667, 0.78, 1) collision_layer = 5
[node name="Unit" parent="." instance=ExtResource("3_wl7wm")] [node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/Wall2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.7165, 1.8999e-07, 3.29106) transform = Transform3D(1, 0, -5.22249e-13, 0, 1, 0, 5.22249e-13, 0, 1, -0.0837822, -0.110484, 0)
shape = SubResource("BoxShape3D_kix0k")
[node name="Unit2" parent="." instance=ExtResource("4_0o33v")] [node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/Wall2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.57207, -7.63685e-07, -6.40453) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.084, 0.912, 0)
mesh = SubResource("BoxMesh_u6sgs")
skeleton = NodePath("../../../..")
[node name="NavRoom" type="NavRoom" parent="."] [node name="Wall3" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -9.89315, 1.48357, 9.64855)
collision_layer = 5
[node name="NavMarker" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/Wall3"]
marker_type = 1 transform = Transform3D(1, 0, -5.22249e-13, 0, 1, 0, 5.22249e-13, 0, 1, -0.084, -0.11, 0)
transform = Transform3D(0.80479, 0, -0.593559, 0, 1, 0, 0.593559, 0, 0.80479, 3.65141, 0.4, -2.09859) shape = SubResource("BoxShape3D_ij4pv")
[node name="NavMarker2" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/Wall3"]
marker_type = 1 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.084, 0.912, 0)
transform = Transform3D(0.794658, 0, -0.607057, 0, 1, 0, 0.607057, 0, 0.794658, 3.07483, 0.4, -2.58758) mesh = SubResource("BoxMesh_4sjak")
skeleton = NodePath("../../../..")
[node name="NavMarker3" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="ModernTrain" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
marker_type = 1 transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -4.39772, 0.268182, -4.7114)
transform = Transform3D(-0.784766, 0, 0.619792, 0, 1, 0, -0.619792, 0, -0.784766, 0.723487, 0.4, 1.45218)
[node name="NavMarker4" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="ModernTrain2" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
marker_type = 1 transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 2.30532, 0.268182, -4.7114)
transform = Transform3D(-0.628248, 0, -0.778013, 0, 1, 0, 0.778013, 0, -0.628248, 3.51616, 0.4, 1.22172)
[node name="NavMarker8" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="ModernTrain3" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
marker_type = 1 transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -3.38777, 0.268182, 7.24505)
transform = Transform3D(-0.635135, 0, -0.772401, 0, 1, 0, 0.772401, 0, -0.635135, 3.91311, 0.4, 0.527064)
[node name="NavMarker5" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="ModernTrain4" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
marker_type = 1 transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.31527, 0.268182, 7.24505)
transform = Transform3D(-0.762273, 0, 0.647256, 0, 1, 0, -0.647256, 0, -0.762273, 0.0761999, 0.4, 1.04762)
[node name="NavMarker6" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="ModernTrain5" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
marker_type = 1 transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -23.146, 0.268182, 3.2886)
transform = Transform3D(0.652363, 0, 0.757906, 0, 1, 0, -0.757906, 0, 0.652363, -0.132873, 0.4, -1.68996)
[node name="NavMarker7" parent="NavRoom" instance=ExtResource("5_ta2oq")] [node name="ModernTrain6" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
marker_type = 1 transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -16.443, 0.268182, 3.2886)
transform = Transform3D(0.668508, 0, 0.743705, 0, 1, 0, -0.743705, 0, 0.668508, 0.277942, 0.4, -2.19853)
[node name="Node3D" type="Node3D" parent="WorldEnvironment"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 7.25984)
[node name="track2" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
[node name="track3" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
[node name="track4" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
[node name="track5" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
[node name="track6" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
[node name="track7" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
[node name="track8" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
[node name="track9" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
[node name="Node3D2" type="Node3D" parent="WorldEnvironment"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3.17094)
[node name="track2" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
[node name="track3" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
[node name="track4" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
[node name="track5" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
[node name="track6" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
[node name="track7" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
[node name="track8" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
[node name="track9" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
[node name="Node3D3" type="Node3D" parent="WorldEnvironment"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4.67443)
[node name="track2" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
[node name="track3" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
[node name="track4" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
[node name="track5" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
[node name="track6" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
[node name="track7" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
[node name="track8" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
[node name="track9" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
[node name="Node3D4" type="Node3D" parent="WorldEnvironment"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.8802, 0, 7.25984)
[node name="track2" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
[node name="track3" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
[node name="track4" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
[node name="track5" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
[node name="track6" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
[node name="track7" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
[node name="track8" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
[node name="track9" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
[node name="Node3D5" type="Node3D" parent="WorldEnvironment"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.8802, 0, 3.17094)
[node name="track2" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
[node name="track3" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
[node name="track4" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
[node name="track5" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
[node name="track6" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
[node name="track7" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
[node name="track8" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
[node name="track9" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
[node name="Player" parent="." instance=ExtResource("3_wl7wm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.16025, 1.8999e-07, -2.07711)
[node name="Player2" parent="." instance=ExtResource("3_wl7wm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.28022, 1.8999e-07, -4.279)
[node name="Tank" parent="." instance=ExtResource("4_0o33v")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.70922, -7.63685e-07, 3.72251)
[node name="Tank2" parent="." instance=ExtResource("4_0o33v")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.4143, -7.63685e-07, 5.91707)
[node name="Tank3" parent="." instance=ExtResource("4_0o33v")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -11.0413, -7.63685e-07, 2.86749)
[node name="Tank4" parent="." instance=ExtResource("4_0o33v")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14.4329, -7.63685e-07, 6.82909)

View file

@ -16,32 +16,45 @@ void EnemyWorldState::_bind_methods() {
void EnemyWorldState::_ready() { GDGAMEONLY(); void EnemyWorldState::_ready() { GDGAMEONLY();
this->awareness_area = this->get_node<gd::Area3D>("%AwarenessArea"); this->awareness_area = this->get_node<gd::Area3D>("%AwarenessArea");
this->awareness_area->connect("body_entered", callable_mp(this, &EnemyWorldState::on_awareness_entered)); this->awareness_area->connect("body_entered", callable_mp(this, &EnemyWorldState::on_awareness_entered));
this->awareness_area->connect("body_exited", callable_mp(this, &EnemyWorldState::on_awareness_exited)); // this->awareness_area->connect("body_exited", callable_mp(this, &EnemyWorldState::on_awareness_exited));
this->health = this->get_node<EntityHealth>("%EntityHealth"); this->health = this->get_node<EntityHealth>("%EntityHealth");
this->health->connect("damage", callable_mp(this, &EnemyWorldState::on_damaged)); this->health->connect("damage", callable_mp(this, &EnemyWorldState::on_damaged));
this->parent_unit->connect("plan_interrupted", callable_mp(this, &EnemyWorldState::select_and_set_target));
} }
void EnemyWorldState::on_awareness_entered(gd::Node3D *node) { void EnemyWorldState::on_awareness_entered(gd::Node3D *node) {
Unit *unit{gd::Object::cast_to<Unit>(node)}; Unit *unit{gd::Object::cast_to<Unit>(node)};
if(unit == nullptr) return; if(unit == nullptr)
if(unit == this->parent_unit) return; return;
if(unit == this->parent_unit)
return;
if(unit->get_entity_health()->get_is_dead())
return;
unit->get_entity_health()->connect("death", this->aware_unit_death.bind(unit));
this->known_enemies.push_back(unit); this->known_enemies.push_back(unit);
this->try_set_target(this->select_target_from_known()); this->try_set_target(this->select_target_from_known());
} }
void EnemyWorldState::on_awareness_exited(gd::Node3D *node) { void EnemyWorldState::on_awareness_exited(gd::Node3D *node) {
Unit *unit{gd::Object::cast_to<Unit>(node)}; Unit *unit{gd::Object::cast_to<Unit>(node)};
if(unit == nullptr)
return;
if(this->known_enemies.has(unit)) {
unit->get_entity_health()->disconnect("death", this->aware_unit_death.bind(unit));
this->known_enemies.erase(unit); this->known_enemies.erase(unit);
} }
if(unit == this->target_node) {
this->select_and_set_target();
}
}
void EnemyWorldState::on_damaged(int remaining, int delta, Unit *source) { void EnemyWorldState::on_damaged(int remaining, int delta, Unit *source) {
if(this->parent_unit->has_plan()) if(!this->known_enemies.has(source)) {
return; source->get_entity_health()->connect("death", this->aware_unit_death.bind(source));
float highest_priority{0.f}; this->known_enemies.push_back(source);
Unit *highest_priority_unit{this->select_target_from_known_with_priority(&highest_priority)}; }
float const priority{this->calculate_priority(source)}; if(!this->parent_unit->has_plan())
if(priority >= highest_priority) this->try_set_target(this->select_target_from_known());
this->try_set_target(source);
} }
Unit *EnemyWorldState::select_target_from_known_with_priority(float *out_priority) { Unit *EnemyWorldState::select_target_from_known_with_priority(float *out_priority) {
@ -62,6 +75,14 @@ Unit *EnemyWorldState::select_target_from_known() {
return this->select_target_from_known_with_priority(&dummy); return this->select_target_from_known_with_priority(&dummy);
} }
void EnemyWorldState::on_aware_unit_death(Unit *_, Unit *dead_entity) {
this->on_awareness_exited(dead_entity);
}
void EnemyWorldState::select_and_set_target() {
this->try_set_target(this->select_target_from_known());
}
float EnemyWorldState::calculate_priority(Unit *target) { float EnemyWorldState::calculate_priority(Unit *target) {
return target->get_global_position().distance_squared_to(this->parent_unit->get_global_position()); return target->get_global_position().distance_squared_to(this->parent_unit->get_global_position());
} }
@ -80,6 +101,11 @@ gd::Ref<goap::Goal> EnemyWorldState::get_goal_for_target(Unit *unit) {
} }
void EnemyWorldState::try_set_target(Unit *unit) { void EnemyWorldState::try_set_target(Unit *unit) {
if(unit == nullptr) {
this->target_node = nullptr;
this->parent_unit->stop_plan();
return;
}
gd::Ref<goap::Goal> goal{this->get_goal_for_target(unit)}; gd::Ref<goap::Goal> goal{this->get_goal_for_target(unit)};
if(goal.is_valid()) if(goal.is_valid())
this->parent_unit->set_target_goal(unit, goal); this->parent_unit->set_target_goal(unit, goal);

View file

@ -28,12 +28,15 @@ public:
//! Shorthand for select_target_from_known_with_priority(nullptr) //! Shorthand for select_target_from_known_with_priority(nullptr)
Unit *select_target_from_known(); Unit *select_target_from_known();
private: private:
void select_and_set_target();
void on_aware_unit_death(Unit *_, Unit *dead_entity);
float calculate_priority(Unit *target); float calculate_priority(Unit *target);
gd::Ref<goap::Goal> get_goal_for_target(Unit *unit); gd::Ref<goap::Goal> get_goal_for_target(Unit *unit);
void try_set_target(Unit *target); void try_set_target(Unit *target);
void set_editor_available_goals(gd::Array array); void set_editor_available_goals(gd::Array array);
gd::Array get_editor_available_goals() const; gd::Array get_editor_available_goals() const;
private: private:
gd::Callable aware_unit_death{callable_mp(this, &EnemyWorldState::on_aware_unit_death)};
gd::Vector<gd::Ref<goap::Goal>> available_goals{}; gd::Vector<gd::Ref<goap::Goal>> available_goals{};
gd::Vector<Unit *> known_enemies{}; gd::Vector<Unit *> known_enemies{};

View file

@ -52,6 +52,10 @@ void EntityHealth::healed_by(int amount, Unit *source) {
this->emit_signal("health_changed", this->injury_current, amount); this->emit_signal("health_changed", this->injury_current, amount);
} }
bool EntityHealth::get_is_dead() const {
return this->injury_current <= 0;
}
void EntityHealth::set_injury_max(int max_health) { void EntityHealth::set_injury_max(int max_health) {
this->injury_max = max_health; this->injury_max = max_health;
} }

View file

@ -16,6 +16,7 @@ public:
void damage(int amount); void damage(int amount);
void healed_by(int amount, Unit *source); void healed_by(int amount, Unit *source);
void heal(int amount); void heal(int amount);
bool get_is_dead() const;
void set_injury_max(int max_health); void set_injury_max(int max_health);
int get_injury_max() const; int get_injury_max() const;
int get_injury_current() const; int get_injury_current() const;

View file

@ -4,6 +4,11 @@ namespace goap {
Action::~Action() {} Action::~Action() {}
bool Action::is_possible(ActorWorldState *context) const { bool Action::is_possible(ActorWorldState *context) const {
for(WorldProperty const &prop : this->required) {
if(!context->check_property_match(prop)) {
return false;
}
}
return this->procedural_is_possible(context); return this->procedural_is_possible(context);
} }
@ -17,6 +22,14 @@ bool Action::is_completed(ActorWorldState *context) const {
return this->procedural_is_completed(context); return this->procedural_is_completed(context);
} }
bool Action::procedural_is_possible(ActorWorldState *context) const {
return true;
}
bool Action::procedural_is_completed(ActorWorldState *context) const {
return true;
}
WorldState const &Action::get_required() const { WorldState const &Action::get_required() const {
return this->required; return this->required;
} }
@ -32,12 +45,4 @@ ActionID Action::get_id() const {
bool Action::get_require_state_complete() const { bool Action::get_require_state_complete() const {
return this->require_state_complete; return this->require_state_complete;
} }
bool Action::procedural_is_possible(ActorWorldState *context) const {
return true;
}
bool Action::procedural_is_completed(ActorWorldState *context) const {
return true;
}
} }

View file

@ -38,6 +38,8 @@ public:
bool is_completed(ActorWorldState *context) const; bool is_completed(ActorWorldState *context) const;
bool is_possible(ActorWorldState *context) const; bool is_possible(ActorWorldState *context) const;
virtual bool procedural_is_possible(ActorWorldState *context) const;
virtual bool procedural_is_completed(ActorWorldState *context) const;
WorldState const &get_required() const; WorldState const &get_required() const;
WorldState const &get_effects() const; WorldState const &get_effects() const;
@ -48,8 +50,6 @@ protected:
Action() = default; Action() = default;
template<class TState> template<class TState>
TState *create_state() const; TState *create_state() const;
virtual bool procedural_is_possible(ActorWorldState *context) const;
virtual bool procedural_is_completed(ActorWorldState *context) const;
protected: protected:
WorldState blocking_required{}; WorldState blocking_required{};
WorldState required{}; WorldState required{};

View file

@ -171,7 +171,7 @@ gd::Vector<Action const *> &Planner::get_actions() {
gd::Vector<Action const *> Planner::get_neighbours(WorldStateNode const &from) const { gd::Vector<Action const *> Planner::get_neighbours(WorldStateNode const &from) const {
gd::Vector<Action const *> retval{}; gd::Vector<Action const *> retval{};
for(Action const *action : this->actions) { for(Action const *action : this->actions) {
if(!action->is_possible(from.context) || !this->does_action_contribute(action, from)) if(!action->procedural_is_possible(from.context) || !this->does_action_contribute(action, from))
continue; continue;
retval.push_back(action); retval.push_back(action);
} }

View file

@ -92,16 +92,18 @@ goap::State *TankSelfHeal::get_apply_state(goap::ActorWorldState *context) const
TakeCover::TakeCover() TakeCover::TakeCover()
: Action () { : Action () {
this->require_state_complete = false;
this->effects.insert("can_see_target", false); this->effects.insert("can_see_target", false);
} }
bool TakeCover::procedural_is_possible(goap::ActorWorldState *context) const { bool TakeCover::procedural_is_possible(goap::ActorWorldState *context) const {
// positions of the context and the target
gd::Vector3 const global_position{context->get_world_property("parent_global_position")}; gd::Vector3 const global_position{context->get_world_property("parent_global_position")};
gd::Vector3 const target_position{context->get_world_property("target_global_position")}; gd::Vector3 const target_position{context->get_world_property("target_global_position")};
// if there is no available navigation room, it is not possible to find a cover marker
NavRoom *room{NavRoom::get_closest_room(global_position)}; NavRoom *room{NavRoom::get_closest_room(global_position)};
if(room == nullptr) if(room == nullptr)
return false; return false;
// immediately return true if there is at least one marker that counts as cover from the target
for(NavMarker *marker : room->get_markers()) for(NavMarker *marker : room->get_markers())
if(TakeCover::is_marker_cover_from(marker, target_position)) if(TakeCover::is_marker_cover_from(marker, target_position))
return true; return true;
@ -109,22 +111,30 @@ bool TakeCover::procedural_is_possible(goap::ActorWorldState *context) const {
} }
goap::State *TakeCover::get_apply_state(goap::ActorWorldState *context) const { goap::State *TakeCover::get_apply_state(goap::ActorWorldState *context) const {
MoveTo *state{this->create_state<MoveTo>()}; // positions of the context and the target to hide from
gd::Vector3 const global_position{context->get_world_property("parent_global_position")}; gd::Vector3 const global_position{context->get_world_property("parent_global_position")};
gd::Vector3 const target_position{context->get_world_property("target_global_position")}; gd::Vector3 const target_position{context->get_world_property("target_global_position")};
// find the room this entity is located in
NavRoom *room{NavRoom::get_closest_room(global_position)}; NavRoom *room{NavRoom::get_closest_room(global_position)};
if(room == nullptr) if(room == nullptr)
return nullptr; return nullptr;
float best_score{-INFINITY}; NavMarker *best_marker{nullptr}; // marker with the best score found so far
float best_score{0.f}; // best score found so far
for(NavMarker *marker : room->get_markers()) { for(NavMarker *marker : room->get_markers()) {
gd::Vector3 const marker_position{marker->get_global_position()}; gd::Vector3 const marker_position{marker->get_global_position()}; // position of the marker being considered
float const score{100.f - marker_position.distance_to(global_position)}; float const score{(marker_position.distance_squared_to(target_position) * 1.2f) // score is a comparison between distances to the target and context
- (marker_position.distance_squared_to(global_position) * 0.8f)};
if(score > best_score && TakeCover::is_marker_cover_from(marker, target_position)) { if(score > best_score && TakeCover::is_marker_cover_from(marker, target_position)) {
best_score = score; best_score = score;
state->target_node = marker; best_marker = marker;
gd::UtilityFunctions::print("!!! best cover so far: ", marker->get_path());
} }
} }
// don't bother creating a state if there is no target
if(best_marker == nullptr)
return nullptr;
// create state, set target, and return
MoveTo *state{this->create_state<MoveTo>()};
state->target_node = best_marker;
return state; return state;
} }
@ -132,5 +142,5 @@ bool TakeCover::is_marker_cover_from(NavMarker *marker, gd::Vector3 const &targe
return marker->get_marker_type() == MarkerType::Cover return marker->get_marker_type() == MarkerType::Cover
&& marker->get_global_basis() && marker->get_global_basis()
.get_column(2) .get_column(2)
.dot((marker->get_global_position() - target).normalized()) < -0.7f; .dot(marker->get_global_position() - target) < -2.f;
} }

View file

@ -1,5 +1,6 @@
#include "unit.hpp" #include "unit.hpp"
#include "entity_health.hpp" #include "entity_health.hpp"
#include "goap/action.hpp"
#include "goap/goal.hpp" #include "goap/goal.hpp"
#include "utils/godot_macros.hpp" #include "utils/godot_macros.hpp"
#include <godot_cpp/classes/navigation_agent3d.hpp> #include <godot_cpp/classes/navigation_agent3d.hpp>
@ -10,6 +11,7 @@ void Unit::_bind_methods() {
#define CLASSNAME Unit #define CLASSNAME Unit
GDSIGNAL("goal_finished"); GDSIGNAL("goal_finished");
GDSIGNAL("plan_failed"); GDSIGNAL("plan_failed");
GDSIGNAL("plan_interrupted");
GDPROPERTY_HINTED(configure_team, gd::Variant::INT, gd::PROPERTY_HINT_ENUM, UnitTeam::get_property_hint()); GDPROPERTY_HINTED(configure_team, gd::Variant::INT, gd::PROPERTY_HINT_ENUM, UnitTeam::get_property_hint());
GDFUNCTION(use_weapon); GDFUNCTION(use_weapon);
} }
@ -30,7 +32,7 @@ void Unit::stop_plan() {
if(this->state && !this->state->is_queued_for_deletion()) if(this->state && !this->state->is_queued_for_deletion())
this->destroy_state(); this->destroy_state();
this->state = nullptr; this->state = nullptr;
this->emit_signal("plan_failed"); this->call_deferred("emit_signal", "plan_failed");
} }
void Unit::begin_marker_temporary(GoalMarker *marker) { void Unit::begin_marker_temporary(GoalMarker *marker) {
@ -62,6 +64,8 @@ void Unit::use_weapon() {
gd::Node3D *target{this->world_state->get_target_node()}; gd::Node3D *target{this->world_state->get_target_node()};
if(target == nullptr) if(target == nullptr)
return; return;
if(!this->world_state->get_can_see_target())
return;
this->aim_at(target); this->aim_at(target);
EntityHealth *health{target->get_node<EntityHealth>("EntityHealth")}; EntityHealth *health{target->get_node<EntityHealth>("EntityHealth")};
if(health == nullptr) if(health == nullptr)
@ -100,16 +104,24 @@ int Unit::get_configure_team() const {
} }
bool Unit::has_plan() const { bool Unit::has_plan() const {
return !this->current_plan.size(); return !this->current_plan.is_empty();
}
EntityHealth *Unit::get_entity_health() {
return this->health;
} }
void Unit::set_goal_and_plan(gd::Ref<goap::Goal> goal) { void Unit::set_goal_and_plan(gd::Ref<goap::Goal> goal) {
this->current_goal = goal; this->current_goal = goal;
if(goal.is_null()) {
this->current_plan.clear();
} else {
this->current_plan = this->planner->plan_for_goal(goal); this->current_plan = this->planner->plan_for_goal(goal);
if(this->current_plan.is_empty()) { if(this->current_plan.is_empty()) {
this->current_goal.unref(); this->current_goal.unref();
} }
} }
}
void Unit::destroy_state() { void Unit::destroy_state() {
if(this->state == nullptr || this->state->is_queued_for_deletion() || !this->state->is_inside_tree()) if(this->state == nullptr || this->state->is_queued_for_deletion() || !this->state->is_inside_tree())
@ -128,17 +140,21 @@ void Unit::next_action() {
// cannot perform actions while dead // cannot perform actions while dead
if(this->health->get_injury_current() <= 0) if(this->health->get_injury_current() <= 0)
return; return;
// destroy active state // destroy active state if relevant
if(this->state != nullptr && !this->state->is_queued_for_deletion()) if(this->state != nullptr && !this->state->is_queued_for_deletion())
this->destroy_state(); this->destroy_state();
this->state = nullptr; this->state = nullptr;
if(this->current_plan.is_empty()) if(this->current_plan.is_empty())
return; return;
goap::Action const *action{this->current_plan.get(0)};
if(!action->is_possible(this->world_state)) {
this->call_deferred("emit_signal", "plan_interrupted");
return;
}
// pop next action and apply state // pop next action and apply state
this->state = this->current_plan.get(0)->get_apply_state(this->world_state); this->state = action->get_apply_state(this->world_state);
if(state == nullptr) { if(state == nullptr) {
this->stop_plan(); this->call_deferred("emit_signal", "plan_interrupted");
gd::UtilityFunctions::push_error("Plan failed to be executed, abandoning");
return; return;
} }
this->current_plan.remove_at(0); this->current_plan.remove_at(0);

View file

@ -42,6 +42,7 @@ public:
void set_configure_team(int value); void set_configure_team(int value);
int get_configure_team() const; int get_configure_team() const;
bool has_plan() const; bool has_plan() const;
EntityHealth *get_entity_health();
private: private:
void set_goal_and_plan(gd::Ref<goap::Goal> goal); void set_goal_and_plan(gd::Ref<goap::Goal> goal);
void destroy_state(); void destroy_state();

View file

@ -50,9 +50,7 @@ bool UnitWorldState::get_can_see_target() const {
target_position, target_position,
0x1 | 0x4, ignore_list) 0x1 | 0x4, ignore_list)
}; };
bool const can_see{this->parent_unit->get_world_3d()->get_direct_space_state()->intersect_ray(query).is_empty()}; return this->parent_unit->get_world_3d()->get_direct_space_state()->intersect_ray(query).is_empty();
gd::UtilityFunctions::print(this->parent_unit->get_path(), can_see ? " can see " : " can't see ", this->target_node->get_path());
return can_see;
} }
bool UnitWorldState::get_is_at_target() const { bool UnitWorldState::get_is_at_target() const {