fix: plan being considered empty if the last state is still active
This commit is contained in:
parent
d7dadac070
commit
9b27fbaabf
|
@ -7,8 +7,7 @@
|
|||
[sub_resource type="SphereShape3D" id="SphereShape3D_5pqvg"]
|
||||
radius = 15.6018
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_drlm2"]
|
||||
radius = 1.0
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_wwkx3"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ss47r"]
|
||||
albedo_color = Color(1, 0.24, 0.24, 1)
|
||||
|
@ -32,7 +31,7 @@ available_goals_inspector = [ExtResource("1_jwvis"), ExtResource("1_b1qo1")]
|
|||
unique_name_in_owner = true
|
||||
|
||||
[node name="Planner" type="Planner" parent="."]
|
||||
actions_inspector = [3, 2, 4, 5, 1]
|
||||
actions_inspector = [3, 2, 4, 1]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="EntityHealth" type="EntityHealth" parent="."]
|
||||
|
@ -41,7 +40,7 @@ unique_name_in_owner = true
|
|||
|
||||
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
path_desired_distance = 0.5
|
||||
path_desired_distance = 0.1
|
||||
target_desired_distance = 0.2
|
||||
path_height_offset = 0.5
|
||||
avoidance_enabled = true
|
||||
|
@ -77,7 +76,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.31501, 0)
|
|||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.999222, -0.0394342, 0, 0.0394342, 0.999222, 0, 1.013, 0)
|
||||
shape = SubResource("SphereShape3D_drlm2")
|
||||
shape = SubResource("CapsuleShape3D_wwkx3")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
[ext_resource type="AnimationLibrary" uid="uid://crkh5gahl2ci6" path="res://Animation/bean_characters.res" id="1_70627"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_q7mxo"]
|
||||
radius = 0.586696
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_n4q15"]
|
||||
specular_mode = 1
|
||||
|
@ -40,7 +39,7 @@ unique_name_in_owner = true
|
|||
|
||||
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
path_desired_distance = 0.2
|
||||
path_desired_distance = 0.1
|
||||
target_desired_distance = 0.5
|
||||
path_height_offset = 0.5
|
||||
avoidance_enabled = true
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
[ext_resource type="PackedScene" uid="uid://ulvv4o73s48a" path="res://Environments/Models/KenneyTrains/track.glb" id="7_8fuqb"]
|
||||
|
||||
[sub_resource type="NavigationMesh" id="NavigationMesh_8a2j6"]
|
||||
vertices = PackedVector3Array(-5.65381, 0.408736, -1.70065, -5.40381, 0.408736, -2.70065, -8.40381, 0.408736, -2.95065, -9.15381, 0.408736, -1.70065, -8.15381, 0.408736, -6.70065, -9.15381, 0.408736, -9.20065, 6.09619, 0.408736, -6.70065, 6.34619, 0.408736, -4.70065, 9.34619, 0.408736, -4.70065, 9.34619, 0.408736, -9.20065, -7.40381, 4.65874, -5.70065, -7.40381, 4.65874, -3.70065, -1.65381, 4.65874, -3.70065, -1.65381, 4.65874, -5.70065, -0.403809, 4.65874, -5.70065, -0.403809, 4.65874, -3.70065, 5.34619, 4.65874, -3.70065, 5.34619, 4.65874, -5.70065, -7.15381, 0.408736, -5.45065, -7.15381, 0.408736, -3.95065, -1.90381, 0.408736, -3.95065, -1.90381, 0.408736, -5.45065, -0.153809, 0.408736, -5.45065, -0.153809, 0.408736, -3.95065, 5.09619, 0.408736, -3.95065, 5.09619, 0.408736, -5.45065, 1.84619, 0.408736, -2.70065, 2.09619, 0.408736, -1.70065, 4.84619, 0.408736, -1.45065, 6.09619, 0.408736, -2.70065, 4.84619, 0.408736, 0.799349, 3.09619, 0.408736, 1.04935, 3.34619, 0.408736, 5.29935, 7.09619, 0.408736, 5.29935, 7.34619, 0.408736, 8.04935, 9.34619, 0.408736, 8.04935, -3.90381, 0.408736, -1.45065, 0.346191, 0.408736, -1.45065, -3.90381, 0.408736, 0.799349, 0.346191, 0.408736, 0.799349, -5.90381, 0.408736, 1.04935, -5.40381, 0.408736, 5.29935, -29.1538, 0.408736, 1.04935, -29.1538, 0.408736, 3.04935, -27.1538, 0.408736, 3.04935, -26.9038, 0.408736, 1.29935, -12.6538, 0.408736, 1.29935, -7.40381, 0.408736, 5.54935, -12.4038, 0.408736, 4.79935, -12.1538, 0.408736, 8.04935, -7.40381, 0.408736, 8.04935, -26.1538, 4.65874, 2.29935, -26.1538, 4.65874, 4.29935, -20.4038, 4.65874, 4.29935, -20.4038, 4.65874, 2.29935, -19.1538, 4.65874, 2.29935, -19.1538, 4.65874, 4.29935, -13.4038, 4.65874, 4.29935, -13.4038, 4.65874, 2.29935, -25.9038, 0.408736, 2.54935, -25.9038, 0.408736, 4.04935, -20.6538, 0.408736, 4.04935, -20.6538, 0.408736, 2.54935, -18.9038, 0.408736, 2.54935, -18.9038, 0.408736, 4.04935, -13.6538, 0.408736, 4.04935, -13.6538, 0.408736, 2.54935, -12.6538, 0.408736, 5.29935, -26.9038, 0.408736, 5.29935, -29.1538, 0.408736, 8.04935, -6.40381, 4.65874, 6.29935, -6.40381, 4.65874, 8.04935, -0.653809, 4.65874, 8.04935, -0.653809, 4.65874, 6.29935, 0.596191, 4.65874, 6.29935, 0.596191, 4.65874, 8.04935, 6.34619, 4.65874, 8.04935, 6.34619, 4.65874, 6.29935, -6.15381, 0.408736, 6.54935, -6.15381, 0.408736, 8.04935, -0.903809, 0.408736, 8.04935, -0.903809, 0.408736, 6.54935, 0.846191, 0.408736, 6.54935, 0.846191, 0.408736, 8.04935, 6.09619, 0.408736, 8.04935, 6.09619, 0.408736, 6.54935)
|
||||
polygons = [PackedInt32Array(1, 0, 2), PackedInt32Array(2, 0, 3), PackedInt32Array(2, 3, 4), PackedInt32Array(4, 3, 5), PackedInt32Array(7, 6, 8), PackedInt32Array(8, 6, 9), PackedInt32Array(4, 5, 6), PackedInt32Array(6, 5, 9), PackedInt32Array(13, 12, 10), PackedInt32Array(10, 12, 11), PackedInt32Array(17, 16, 14), PackedInt32Array(14, 16, 15), PackedInt32Array(21, 20, 18), PackedInt32Array(18, 20, 19), PackedInt32Array(25, 24, 22), PackedInt32Array(22, 24, 23), PackedInt32Array(27, 26, 28), PackedInt32Array(28, 26, 29), PackedInt32Array(31, 30, 32), PackedInt32Array(32, 30, 33), PackedInt32Array(35, 34, 33), PackedInt32Array(28, 29, 30), PackedInt32Array(30, 29, 8), PackedInt32Array(30, 8, 33), PackedInt32Array(33, 8, 35), PackedInt32Array(29, 7, 8), PackedInt32Array(0, 1, 36), PackedInt32Array(36, 1, 37), PackedInt32Array(37, 1, 26), PackedInt32Array(37, 26, 27), PackedInt32Array(37, 39, 36), PackedInt32Array(36, 39, 38), PackedInt32Array(40, 38, 41), PackedInt32Array(41, 38, 39), PackedInt32Array(41, 39, 31), PackedInt32Array(41, 31, 32), PackedInt32Array(44, 43, 45), PackedInt32Array(45, 43, 42), PackedInt32Array(45, 42, 46), PackedInt32Array(46, 42, 40), PackedInt32Array(41, 47, 40), PackedInt32Array(40, 47, 48), PackedInt32Array(40, 48, 46), PackedInt32Array(50, 49, 47), PackedInt32Array(47, 49, 48), PackedInt32Array(54, 53, 51), PackedInt32Array(51, 53, 52), PackedInt32Array(58, 57, 55), PackedInt32Array(55, 57, 56), PackedInt32Array(62, 61, 59), PackedInt32Array(59, 61, 60), PackedInt32Array(66, 65, 63), PackedInt32Array(63, 65, 64), PackedInt32Array(67, 48, 49), PackedInt32Array(44, 68, 43), PackedInt32Array(43, 68, 69), PackedInt32Array(67, 49, 68), PackedInt32Array(68, 49, 69), PackedInt32Array(73, 72, 70), PackedInt32Array(70, 72, 71), PackedInt32Array(77, 76, 74), PackedInt32Array(74, 76, 75), PackedInt32Array(81, 80, 78), PackedInt32Array(78, 80, 79), PackedInt32Array(85, 84, 82), PackedInt32Array(82, 84, 83)]
|
||||
vertices = PackedVector3Array(-49.9439, 6.15874, -50.0795, -48.4439, 6.15874, -50.0795, -48.6939, 6.15874, -65.8295, -71.1939, 6.15874, -48.8295, -49.9439, 6.15874, -48.5795, -71.1939, 6.15874, -65.8295, 50.0561, 6.15874, -50.0795, 50.0561, 6.15874, -48.3295, 51.8061, 6.15874, -48.5795, 51.8061, 6.15874, -65.8295, -71.1939, 6.15874, 48.6705, -49.9439, 6.15874, 48.4205, 50.0561, 6.15874, 48.1705, 51.8061, 6.15874, 48.4205, 8.05612, 0.408735, -6.32945, 8.05612, 0.408735, -4.57945, 9.05612, 0.408735, -4.57945, 9.05612, 0.408735, -9.07945, -8.69388, 0.408735, -6.07945, -7.19388, 0.408735, -6.07945, -6.69388, 0.408735, -6.82945, -8.69388, 0.408735, -9.07945, 7.55612, 0.408735, -6.82945, 0.0561218, 0.408735, -1.32945, 1.55612, 0.408735, -1.82945, 1.55612, 0.408735, -2.57945, -6.69388, 0.408735, -2.57945, -4.19388, 0.408735, -1.82945, -7.19388, 0.408735, -3.07945, -8.69388, 0.408735, -1.82945, -3.69388, 0.408735, -1.32945, -3.69388, 0.408735, 0.920547, 0.0561218, 0.408735, 0.920547, 2.55612, 0.408735, 4.92055, 2.55612, 0.408735, 1.42055, 0.556122, 0.408735, 1.42055, -5.19388, 0.408735, 1.42055, -5.19388, 0.408735, 4.92055, -5.69388, 4.65874, -5.32945, -5.69388, 4.65874, -4.07945, -0.443878, 4.65874, -4.07945, -0.443878, 4.65874, -5.32945, 1.30612, 4.65874, -5.32945, 1.30612, 4.65874, -4.07945, 6.55612, 4.65874, -4.07945, 6.55612, 4.65874, -5.32945, -5.44388, 0.408735, -5.07945, -5.44388, 0.408735, -4.32945, -0.693878, 0.408735, -4.32945, -0.693878, 0.408735, -5.07945, 1.55612, 0.408735, -5.07945, 1.55612, 0.408735, -4.32945, 6.30612, 0.408735, -4.32945, 6.30612, 0.408735, -5.07945, 8.05612, 0.408735, -3.07945, 9.05612, 0.408735, 7.92055, 7.55612, 0.408735, 5.42055, 7.55612, 0.408735, 7.92055, 4.55612, 0.408735, -1.82945, 7.55612, 0.408735, -2.57945, 5.05612, 0.408735, 0.920547, 5.05612, 0.408735, -1.32945, 4.55612, 0.408735, 1.42055, 7.05612, 0.408735, 4.92055, -27.4439, 0.408735, 4.92055, -27.1939, 0.408735, 1.42055, -28.9439, 0.408735, 1.42055, -28.9439, 0.408735, 7.92055, -12.9439, 0.408735, 7.92055, -12.9439, 0.408735, 5.42055, -26.9439, 0.408735, 5.42055, -7.69388, 0.408735, 7.92055, -7.69388, 0.408735, 6.67055, -8.44388, 0.408735, 6.17055, -12.1939, 0.408735, 4.92055, -8.44388, 0.408735, 1.42055, -12.4439, 0.408735, 1.42055, -25.9439, 4.65874, 2.67055, -25.9439, 4.65874, 3.92055, -20.6939, 4.65874, 3.92055, -20.6939, 4.65874, 2.67055, -18.9439, 4.65874, 2.67055, -18.9439, 4.65874, 3.92055, -13.6939, 4.65874, 3.92055, -13.6939, 4.65874, 2.67055, -25.6939, 0.408735, 2.92055, -25.6939, 0.408735, 3.67055, -20.9439, 0.408735, 3.67055, -20.9439, 0.408735, 2.92055, -18.6939, 0.408735, 2.92055, -18.6939, 0.408735, 3.67055, -13.9439, 0.408735, 3.67055, -13.9439, 0.408735, 2.92055, -6.19388, 4.65874, 6.42055, -6.19388, 4.65874, 7.92055, -0.943878, 4.65874, 7.92055, -0.943878, 4.65874, 6.42055, 0.806122, 4.65874, 6.42055, 0.806122, 4.65874, 7.92055, 6.05612, 4.65874, 7.92055, 6.05612, 4.65874, 6.42055, -5.94388, 0.408735, 6.92055, -5.94388, 0.408735, 7.67055, -1.19388, 0.408735, 7.67055, -1.19388, 0.408735, 6.67055, 1.05612, 0.408735, 6.67055, 1.05612, 0.408735, 7.67055, 5.80612, 0.408735, 7.67055, 5.80612, 0.408735, 6.67055, 50.0561, 6.15874, 49.9205, 51.8061, 6.15874, 67.6705, -48.6939, 6.15874, 67.6705, -48.4439, 6.15874, 49.9205, -49.9439, 6.15874, 49.9205, -71.1939, 6.15874, 67.6705)
|
||||
polygons = [PackedInt32Array(2, 1, 0), PackedInt32Array(0, 4, 3), PackedInt32Array(3, 5, 0), PackedInt32Array(0, 5, 2), PackedInt32Array(7, 6, 8), PackedInt32Array(8, 6, 9), PackedInt32Array(1, 2, 6), PackedInt32Array(6, 2, 9), PackedInt32Array(11, 10, 4), PackedInt32Array(4, 10, 3), PackedInt32Array(7, 8, 12), PackedInt32Array(12, 8, 13), PackedInt32Array(15, 14, 16), PackedInt32Array(16, 14, 17), PackedInt32Array(19, 18, 20), PackedInt32Array(20, 18, 21), PackedInt32Array(22, 20, 17), PackedInt32Array(17, 20, 21), PackedInt32Array(17, 14, 22), PackedInt32Array(24, 23, 25), PackedInt32Array(25, 23, 27), PackedInt32Array(25, 27, 26), PackedInt32Array(19, 28, 18), PackedInt32Array(18, 28, 29), PackedInt32Array(23, 32, 30), PackedInt32Array(30, 32, 31), PackedInt32Array(29, 28, 26), PackedInt32Array(27, 29, 26), PackedInt32Array(35, 34, 33), PackedInt32Array(32, 35, 31), PackedInt32Array(31, 35, 36), PackedInt32Array(36, 35, 37), PackedInt32Array(37, 35, 33), PackedInt32Array(23, 30, 27), PackedInt32Array(41, 40, 38), PackedInt32Array(38, 40, 39), PackedInt32Array(45, 44, 42), PackedInt32Array(42, 44, 43), PackedInt32Array(49, 48, 46), PackedInt32Array(46, 48, 47), PackedInt32Array(53, 52, 50), PackedInt32Array(50, 52, 51), PackedInt32Array(15, 16, 54), PackedInt32Array(54, 16, 55), PackedInt32Array(55, 57, 56), PackedInt32Array(24, 25, 58), PackedInt32Array(58, 25, 59), PackedInt32Array(59, 54, 60), PackedInt32Array(60, 54, 56), PackedInt32Array(56, 54, 55), PackedInt32Array(59, 61, 58), PackedInt32Array(34, 62, 33), PackedInt32Array(33, 62, 63), PackedInt32Array(62, 60, 63), PackedInt32Array(63, 60, 56), PackedInt32Array(60, 61, 59), PackedInt32Array(65, 64, 66), PackedInt32Array(66, 64, 67), PackedInt32Array(69, 68, 70), PackedInt32Array(70, 68, 67), PackedInt32Array(67, 64, 70), PackedInt32Array(72, 71, 73), PackedInt32Array(73, 71, 74), PackedInt32Array(74, 71, 69), PackedInt32Array(69, 71, 68), PackedInt32Array(76, 75, 74), PackedInt32Array(74, 75, 73), PackedInt32Array(80, 79, 77), PackedInt32Array(77, 79, 78), PackedInt32Array(84, 83, 81), PackedInt32Array(81, 83, 82), PackedInt32Array(88, 87, 85), PackedInt32Array(85, 87, 86), PackedInt32Array(92, 91, 89), PackedInt32Array(89, 91, 90), PackedInt32Array(96, 95, 93), PackedInt32Array(93, 95, 94), PackedInt32Array(100, 99, 97), PackedInt32Array(97, 99, 98), PackedInt32Array(102, 101, 103), PackedInt32Array(103, 101, 104), PackedInt32Array(108, 107, 105), PackedInt32Array(105, 107, 106), PackedInt32Array(12, 13, 109), PackedInt32Array(109, 13, 110), PackedInt32Array(112, 109, 111), PackedInt32Array(111, 109, 110), PackedInt32Array(113, 112, 111), PackedInt32Array(10, 11, 113), PackedInt32Array(10, 113, 114), PackedInt32Array(114, 113, 111)]
|
||||
geometry_parsed_geometry_type = 1
|
||||
geometry_collision_mask = 4294967289
|
||||
agent_radius = 0.6
|
||||
|
||||
[sub_resource type="Goal" id="Goal_yju55"]
|
||||
desired_state_dict = {
|
||||
|
@ -54,47 +55,47 @@ game_mode_prototype = ExtResource("1_4nchg")
|
|||
|
||||
[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, 3.57243, 0.408736, -1.56782)
|
||||
transform = Transform3D(0.999999, 0, -0.00101254, 0, 1, 0, 0.00101254, 0, 0.999999, 3.16586, 0.408736, -1.60341)
|
||||
|
||||
[node name="CoverMarker3" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.00101258, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101258, 4.84619, 0.408736, -0.211887)
|
||||
transform = Transform3D(-0.00101258, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101258, 5.05612, 0.408735, -0.198195)
|
||||
|
||||
[node name="CoverMarker4" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, 3.55349, 0.408736, 0.984021)
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, 3.21966, 0.408735, 1.42055)
|
||||
|
||||
[node name="CoverMarker5" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, 1.75757, 0.408736, 0.927656)
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, 1.32541, 0.408735, 1.42055)
|
||||
|
||||
[node name="CoverMarker6" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, 0.346191, 0.408736, -0.0968238)
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, 0.0561218, 0.408735, -0.256456)
|
||||
|
||||
[node name="CoverMarker7" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.999999, 0, -0.00101271, 0, 1, 0, 0.00101271, 0, 0.999999, -5.38549, 0.408736, -1.66232)
|
||||
transform = Transform3D(0.999999, 0, -0.00101271, 0, 1, 0, 0.00101271, 0, 0.999999, -6.17118, 0.408735, -1.82945)
|
||||
|
||||
[node name="CoverMarker8" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, -5.39349, 0.408736, 0.98556)
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, -4.91025, 0.408735, 1.32601)
|
||||
|
||||
[node name="CoverMarker9" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.00101258, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101258, 7.2385, 0.408736, 6.86474)
|
||||
transform = Transform3D(-0.00101258, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101258, 7.55612, 0.408735, 7.19658)
|
||||
|
||||
[node name="CoverMarker16" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, -7.40381, 0.408736, 6.88524)
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, -7.69388, 0.408735, 7.45576)
|
||||
|
||||
[node name="CoverMarker17" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, -27.1371, 0.408736, 3.19975)
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, -27.3177, 0.408735, 3.15346)
|
||||
|
||||
[node name="CoverMarker18" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.00101258, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101258, -12.5116, 0.408736, 3.28973)
|
||||
transform = Transform3D(-0.00101258, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101258, -13.9439, 0.408735, 3.27543)
|
||||
|
||||
[node name="CoverMarker19" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
|
@ -102,7 +103,7 @@ transform = Transform3D(0.999999, 4.37114e-08, -0.00101254, -4.36671e-08, 1, 4.3
|
|||
|
||||
[node name="CoverMarker20" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.999999, 4.37114e-08, 0.00101245, 4.36671e-08, 1, -4.37556e-08, -0.00101245, -4.37114e-08, -0.999999, -15.033, 0.408736, 5.29935)
|
||||
transform = Transform3D(-0.999999, 4.37114e-08, 0.00101245, 4.36671e-08, 1, -4.37556e-08, -0.00101245, -4.37114e-08, -0.999999, -15.033, 0.408735, 5.42055)
|
||||
|
||||
[node name="CoverMarker21" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
|
@ -110,35 +111,31 @@ transform = Transform3D(0.999999, 4.37114e-08, -0.00101254, -4.36671e-08, 1, 4.3
|
|||
|
||||
[node name="CoverMarker22" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.999999, 4.37114e-08, 0.00101245, 4.36671e-08, 1, -4.37556e-08, -0.00101245, -4.37114e-08, -0.999999, -24.9126, 0.408736, 5.29935)
|
||||
transform = Transform3D(-0.999999, 4.37114e-08, 0.00101245, 4.36671e-08, 1, -4.37556e-08, -0.00101245, -4.37114e-08, -0.999999, -24.9126, 0.408735, 5.42055)
|
||||
|
||||
[node name="CoverMarker2" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.999999, 0, -0.00101254, 0, 1, 0, 0.00101254, 0, 0.999999, 1.73439, 0.408736, -1.68834)
|
||||
transform = Transform3D(0.999999, 0, -0.00101254, 0, 1, 0, 0.00101254, 0, 0.999999, 1.95486, 0.408736, -1.68046)
|
||||
|
||||
[node name="CoverMarker10" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.999999, 0, -0.00101254, 0, 1, 0, 0.00101254, 0, 0.999999, 4.21452, 0.408736, -6.70065)
|
||||
transform = Transform3D(0.999999, 0, -0.00101254, 0, 1, 0, 0.00101254, 0, 0.999999, 4.1476, 0.408735, -6.82945)
|
||||
|
||||
[node name="CoverMarker11" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, 4.66545, 0.408736, -2.70065)
|
||||
|
||||
[node name="CoverMarker12" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, -6.83875, 0.408736, -2.82023)
|
||||
transform = Transform3D(-0.999999, 0, 0.00101263, 0, 1, 0, -0.00101263, 0, -0.999999, 4.47796, 0.408735, -2.57945)
|
||||
|
||||
[node name="CoverMarker13" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.999999, 0, -0.00101271, 0, 1, 0, 0.00101271, 0, 0.999999, -6.67478, 0.408736, -6.70065)
|
||||
transform = Transform3D(0.999999, 0, -0.00101271, 0, 1, 0, 0.00101271, 0, 0.999999, -6.57121, 0.408735, -6.82945)
|
||||
|
||||
[node name="CoverMarker14" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, -8.28839, 0.408736, -4.682)
|
||||
transform = Transform3D(0.00101267, 0, 0.999999, 0, 1, 0, -0.999999, 0, 0.00101267, -7.19388, 0.408735, -4.682)
|
||||
|
||||
[node name="CoverMarker15" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
marker_type = 1
|
||||
transform = Transform3D(-0.00101276, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101276, 6.32876, 0.408736, -4.56123)
|
||||
transform = Transform3D(-0.00101276, 0, -0.999999, 0, 1, 0, 0.999999, 0, -0.00101276, 8.05612, 0.408735, -4.59507)
|
||||
|
||||
[node name="GenericMarker" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.44669, 0.408736, 3.42186)
|
||||
|
@ -147,10 +144,10 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.44669, 0.408736, 3.42186)
|
|||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.55474, 0.408736, 3.32429)
|
||||
|
||||
[node name="GenericMarker3" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.82326, 0.408736, -2.82315)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.13664, 0.408735, -1.06315)
|
||||
|
||||
[node name="GenericMarker4" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.17274, 0.408736, -7.57197)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.17274, 0.408735, -7.57197)
|
||||
|
||||
[node name="GenericMarker5" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.210692, 0.408736, -7.8647)
|
||||
|
@ -165,13 +162,13 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9.41558, 0.408736, 3.0966)
|
|||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12.4156, 0.408736, 7.0966)
|
||||
|
||||
[node name="GenericMarker9" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.3762, 0.408736, 7.35681)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.2634, 0.408735, 7.18221)
|
||||
|
||||
[node name="GenericMarker10" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -27.5728, 0.408736, 6.3485)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -27.5644, 0.408735, 6.49595)
|
||||
|
||||
[node name="GenericMarker11" parent="NavRoom" instance=ExtResource("5_ta2oq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -28.1582, 0.408736, 2.25021)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -28.3032, 0.408735, 2.73795)
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = ExtResource("2_jq6bw")
|
||||
|
@ -187,10 +184,10 @@ shadow_blur = 0.1
|
|||
navigation_mesh = SubResource("NavigationMesh_8a2j6")
|
||||
|
||||
[node name="ModernTrain" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
|
||||
transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -4.39772, 0.268182, -4.7114)
|
||||
transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -2.84418, 0.268182, -4.7114)
|
||||
|
||||
[node name="ModernTrain2" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 2.30532, 0.268182, -4.7114)
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.85886, 0.268182, -4.7114)
|
||||
|
||||
[node name="ModernTrain3" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
|
||||
transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -3.38777, 0.268182, 7.24505)
|
||||
|
@ -210,7 +207,7 @@ collision_layer = 7
|
|||
|
||||
[node name="CSGBox3D2" type="CSGBox3D" parent="WorldEnvironment/NavigationRegion3D/brushwork"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9.70088, 2.69981, 0.976042)
|
||||
size = Vector3(52.4059, 6.08215, 28.8534)
|
||||
size = Vector3(124.486, 6.08215, 135.111)
|
||||
|
||||
[node name="CSGBox3D" type="CSGBox3D" parent="WorldEnvironment/NavigationRegion3D/brushwork"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.17791, 5.23133, -5.44301)
|
||||
|
@ -271,6 +268,8 @@ shape = SubResource("BoxShape3D_3h2p0")
|
|||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0515832, 0.0826392, -2.12334)
|
||||
height = 4.0
|
||||
vertices = PackedVector3Array(-1, 0, 3, -1, 0, -3, 1, 0, -3, 1, 0, 3)
|
||||
affect_navigation_mesh = true
|
||||
carve_navigation_mesh = true
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="WorldEnvironment/NavigationRegion3D/UtilityLock"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.136569, 0)
|
||||
|
@ -420,10 +419,10 @@ transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278
|
|||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.12793, 1.8999e-07, -8.60757)
|
||||
|
||||
[node name="Player2" parent="." instance=ExtResource("3_wl7wm")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.7762, 1.8999e-07, -9.13169)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.74312, 1.8999e-07, -8.7408)
|
||||
|
||||
[node name="Tank" parent="." instance=ExtResource("4_0o33v")]
|
||||
transform = Transform3D(-1, 0, 8.9407e-08, 0, 1, 0, -8.9407e-08, 0, -1, 7.84599, -7.63685e-07, 8.12034)
|
||||
transform = Transform3D(-1, 0, 8.9407e-08, 0, 1, 0, -8.9407e-08, 0, -1, 7.88995, -7.63685e-07, 7.79155)
|
||||
|
||||
[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)
|
||||
|
|
|
@ -18,4 +18,3 @@ void CharacterUnit::use_weapon() {
|
|||
this->inventory->get_weapon()->try_use_on(this, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
#ifndef CHARACTER_UNIT_HPP
|
||||
#define CHARACTER_UNIT_HPP
|
||||
|
||||
#include "unit.hpp"
|
||||
#include "inventory.hpp"
|
||||
#include "unit.hpp"
|
||||
|
||||
class CharacterUnit : public Unit {
|
||||
GDCLASS(CharacterUnit, Unit);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
virtual void use_weapon() override;
|
||||
|
||||
private:
|
||||
Inventory *inventory{nullptr};
|
||||
};
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
class CharacterWorldState : public UnitWorldState {
|
||||
GDCLASS(CharacterWorldState, UnitWorldState);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _enter_tree() override;
|
||||
virtual gd::String get_weapon_animation() const override;
|
||||
virtual bool get_is_in_range() const override;
|
||||
|
||||
private:
|
||||
Inventory *inventory{nullptr};
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "enemy_world_state.hpp"
|
||||
#include "entity_health.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "goap/goal.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
#include <cmath>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
void EnemyWorldState::_bind_methods() {
|
||||
#define CLASSNAME EnemyWorldState
|
||||
|
@ -20,33 +20,45 @@ void EnemyWorldState::_ready() {
|
|||
}
|
||||
|
||||
void EnemyWorldState::_process(double) {
|
||||
if(!this->health->is_conscious())
|
||||
return;
|
||||
if(this->select_and_set_target_on_process) {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " requested, select_and_set_target");
|
||||
this->select_and_set_target_on_process = false;
|
||||
this->select_and_set_target();
|
||||
} else if(!this->parent_unit->has_plan()) {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " no plan, select_and_set_target");
|
||||
this->select_and_set_target();
|
||||
}
|
||||
}
|
||||
|
||||
void EnemyWorldState::on_awareness_entered(gd::Node3D *node) {
|
||||
if(Unit *unit{gd::Object::cast_to<Unit>(node)}) {
|
||||
if(Unit * unit{gd::Object::cast_to<Unit>(node)}) {
|
||||
this->add_aware_unit(unit);
|
||||
}
|
||||
}
|
||||
|
||||
void EnemyWorldState::on_awareness_exited(gd::Node3D *node) {
|
||||
if(Unit *unit{gd::Object::cast_to<Unit>(node)})
|
||||
if(Unit * unit{gd::Object::cast_to<Unit>(node)})
|
||||
this->remove_aware_unit(unit);
|
||||
}
|
||||
|
||||
void EnemyWorldState::on_damaged(EntityHealth *, int, Unit *source) {
|
||||
if(source != nullptr && !this->known_enemies.has(source))
|
||||
this->add_aware_unit(source);
|
||||
else if(!this->parent_unit->has_plan())
|
||||
if(!this->parent_unit->has_plan())
|
||||
this->select_and_set_target();
|
||||
}
|
||||
|
||||
Unit *EnemyWorldState::select_target_from_known_with_priority(float *out_priority) {
|
||||
Unit *out{nullptr};
|
||||
*out_priority = -INFINITY;
|
||||
Unit *out{gd::Object::cast_to<Unit>(target_node)};
|
||||
// prioritze current target if it is still valid
|
||||
if(out != nullptr && this->known_enemies.has(out)) {
|
||||
*out_priority = INFINITY;
|
||||
return out;
|
||||
} else {
|
||||
*out_priority = -INFINITY;
|
||||
}
|
||||
for(Unit *unit : this->known_enemies) {
|
||||
if(!this->get_can_see_node(unit))
|
||||
continue;
|
||||
|
@ -101,6 +113,7 @@ void EnemyWorldState::on_aware_unit_death(Unit *, Unit *dead_entity) {
|
|||
}
|
||||
|
||||
void EnemyWorldState::select_and_set_target() {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " select_and_set_target");
|
||||
this->try_set_target(this->select_target_from_known());
|
||||
}
|
||||
|
||||
|
@ -130,14 +143,11 @@ gd::Ref<goap::Goal> EnemyWorldState::get_goal_for_target(Unit *unit) {
|
|||
}
|
||||
|
||||
void EnemyWorldState::try_set_target(Unit *unit) {
|
||||
if(unit == nullptr) {
|
||||
this->target_node = nullptr;
|
||||
this->parent_unit->stop_plan();
|
||||
if(unit == nullptr)
|
||||
return;
|
||||
}
|
||||
gd::Ref<goap::Goal> goal{this->get_goal_for_target(unit)};
|
||||
this->last_goal = goal;
|
||||
if(goal.is_valid())
|
||||
if(goal.is_valid() && goal != this->parent_unit->get_current_goal())
|
||||
this->parent_unit->set_target_goal(unit, goal);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef ENEMY_WORLD_STATE_HPP
|
||||
#define ENEMY_WORLD_STATE_HPP
|
||||
|
||||
#include "unit_world_state.hpp"
|
||||
#include "goap/goal.hpp"
|
||||
#include "unit_world_state.hpp"
|
||||
#include <godot_cpp/classes/area3d.hpp>
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
#include <godot_cpp/variant/array.hpp>
|
||||
|
@ -14,6 +14,7 @@ class EntityHealth;
|
|||
class EnemyWorldState : public UnitWorldState {
|
||||
GDCLASS(EnemyWorldState, UnitWorldState);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
virtual void _process(double) override;
|
||||
|
@ -23,10 +24,11 @@ public:
|
|||
/*! Select the target with the highest priority and return it.
|
||||
* Assigns the priority of found target to out_priority.
|
||||
* \param out_priority Assigned to highest found priority, cannot be nullptr.
|
||||
*/
|
||||
*/
|
||||
Unit *select_target_from_known_with_priority(float *out_priority);
|
||||
//! Shorthand for select_target_from_known_with_priority(nullptr)
|
||||
Unit *select_target_from_known();
|
||||
|
||||
private:
|
||||
void queue_select_and_set_target();
|
||||
void add_aware_unit(Unit *unit);
|
||||
|
@ -38,6 +40,7 @@ private:
|
|||
void try_set_target(Unit *target);
|
||||
void set_available_goals_inspector(gd::Array array);
|
||||
gd::Array get_available_goals_inspector() const;
|
||||
|
||||
private:
|
||||
gd::Callable aware_unit_death{callable_mp(this, &EnemyWorldState::on_aware_unit_death)};
|
||||
gd::Vector<gd::Ref<goap::Goal>> available_goals{};
|
||||
|
|
|
@ -10,22 +10,22 @@ void EntityHealth::_bind_methods() {
|
|||
GDPROPERTY(wounds_max, gd::Variant::INT);
|
||||
|
||||
GDSIGNAL("damage",
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "EntityHealth"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "change"),
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "EntityHealth"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "change"),
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
GDSIGNAL("heal",
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "EntityHealth"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "change"),
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "EntityHealth"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "change"),
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
GDSIGNAL("health_changed",
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "EntityHealth"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "change"));
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "EntityHealth"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "change"));
|
||||
GDSIGNAL("death", gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
GDSIGNAL("unconscious", gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
GDSIGNAL("revived",
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "Unit"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "healed"),
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "health_entity", gd::PROPERTY_HINT_NODE_TYPE, "Unit"),
|
||||
gd::PropertyInfo(gd::Variant::INT, "healed"),
|
||||
gd::PropertyInfo(gd::Variant::OBJECT, "source", gd::PROPERTY_HINT_NODE_TYPE, "Unit"));
|
||||
}
|
||||
|
||||
void EntityHealth::_enter_tree() {
|
||||
|
@ -71,24 +71,20 @@ void EntityHealth::receive_injury(int incoming_amount, Unit *source) {
|
|||
|
||||
float EntityHealth::get_wounds_damage_factor() const {
|
||||
return this->injury_max == 0
|
||||
? 1.f
|
||||
: float(this->injury_current) / float(this->injury_max);
|
||||
? 1.f
|
||||
: float(this->injury_current) / float(this->injury_max);
|
||||
}
|
||||
|
||||
bool EntityHealth::is_conscious() const {
|
||||
return !this->is_dead()
|
||||
&& (this->wounds_current > 0 || this->wounds_max <= 0);
|
||||
return !this->is_dead() && (this->wounds_current > 0 || this->wounds_max <= 0);
|
||||
}
|
||||
|
||||
bool EntityHealth::can_be_revived() const {
|
||||
return this->wounds_current <= 0
|
||||
&& this->injury_current > 0;
|
||||
return this->wounds_current <= 0 && this->injury_current > 0;
|
||||
}
|
||||
|
||||
bool EntityHealth::can_be_healed() const {
|
||||
return this->injury_current > 0
|
||||
&& this->wounds_current > 0
|
||||
&& this->wounds_current < this->wounds_max;
|
||||
return this->injury_current > 0 && this->wounds_current > 0 && this->wounds_current < this->wounds_max;
|
||||
}
|
||||
|
||||
bool EntityHealth::is_dead() const {
|
||||
|
|
|
@ -11,15 +11,18 @@ class Unit;
|
|||
class EntityHealth : public gd::Node {
|
||||
GDCLASS(EntityHealth, gd::Node);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _enter_tree() override;
|
||||
void damaged_by(int amount, Unit *source);
|
||||
void healed_by(int amount, Unit *source);
|
||||
void heal_and_revive(int heal_amount, Unit *source);
|
||||
|
||||
private:
|
||||
void receive_wounds(int incoming_amount, Unit *source);
|
||||
void receive_injury(int incoming_amount, Unit *source);
|
||||
float get_wounds_damage_factor() const;
|
||||
|
||||
public:
|
||||
bool is_conscious() const;
|
||||
bool can_be_revived() const;
|
||||
|
@ -34,6 +37,7 @@ public:
|
|||
void set_wounds_max(int max_health);
|
||||
int get_wounds_max() const;
|
||||
int get_wounds_current() const;
|
||||
|
||||
private:
|
||||
Stats const *stats;
|
||||
// long term health
|
||||
|
|
|
@ -10,10 +10,12 @@ namespace gd = godot;
|
|||
class GoalMarker : public gd::StaticBody3D {
|
||||
GDCLASS(GoalMarker, gd::StaticBody3D);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void destroy_on_forgotten();
|
||||
void set_goal(gd::Ref<goap::Goal> goal);
|
||||
gd::Ref<goap::Goal> get_goal() const;
|
||||
|
||||
private:
|
||||
gd::Ref<goap::Goal> goal{};
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "../goap/action.hpp"
|
||||
#include "../goap/actor_world_state.hpp"
|
||||
#include "../utils/godot_macros.hpp"
|
||||
#include "godot_cpp/variant/utility_functions.hpp"
|
||||
|
||||
namespace goap {
|
||||
void State::_bind_methods() {
|
||||
|
@ -21,11 +22,13 @@ void State::_process(double) {
|
|||
}
|
||||
|
||||
void State::interrupt_state() {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " interrupt_state");
|
||||
this->_end_state();
|
||||
this->queue_free();
|
||||
}
|
||||
|
||||
void State::end_state() {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " end_state");
|
||||
this->interrupt_state();
|
||||
this->emit_signal(this->is_action_done() ? "state_finished" : "state_failed");
|
||||
this->emit_signal("end_state");
|
||||
|
|
|
@ -19,10 +19,14 @@ void Inventory::_ready() {
|
|||
|
||||
Stats Inventory::get_stats() const {
|
||||
Stats stats{};
|
||||
if(this->weapon != nullptr) this->weapon->apply_stats(stats);
|
||||
if(this->utility != nullptr) this->utility->apply_stats(stats);
|
||||
if(this->armour != nullptr) this->armour->apply_stats(stats);
|
||||
if(this->helmet != nullptr) this->helmet->apply_stats(stats);
|
||||
if(this->weapon != nullptr)
|
||||
this->weapon->apply_stats(stats);
|
||||
if(this->utility != nullptr)
|
||||
this->utility->apply_stats(stats);
|
||||
if(this->armour != nullptr)
|
||||
this->armour->apply_stats(stats);
|
||||
if(this->helmet != nullptr)
|
||||
this->helmet->apply_stats(stats);
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#include "utils/godot_macros.hpp"
|
||||
#include <godot_cpp/classes/node.hpp>
|
||||
#include <godot_cpp/classes/ref_counted.hpp>
|
||||
#include <godot_cpp/templates/pair.hpp>
|
||||
#include <godot_cpp/templates/hash_map.hpp>
|
||||
#include <godot_cpp/templates/pair.hpp>
|
||||
|
||||
namespace gd = godot;
|
||||
class Unit;
|
||||
|
@ -15,6 +15,7 @@ class Unit;
|
|||
class Inventory : public gd::Node {
|
||||
GDCLASS(Inventory, gd::Node);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
Stats get_stats() const;
|
||||
|
@ -38,6 +39,7 @@ public:
|
|||
int get_utility_id() const;
|
||||
void set_inventory_inspector(gd::Dictionary dict);
|
||||
gd::Dictionary get_inventory_inspector() const;
|
||||
|
||||
private:
|
||||
Item const *weapon{nullptr};
|
||||
Item const *utility{nullptr};
|
||||
|
|
44
src/item.hpp
44
src/item.hpp
|
@ -1,8 +1,8 @@
|
|||
#ifndef ITEM_HPP
|
||||
#define ITEM_HPP
|
||||
|
||||
#include "stats.hpp"
|
||||
#include "goap/action.hpp"
|
||||
#include "stats.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
#include <godot_cpp/templates/hash_set.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
@ -10,22 +10,22 @@
|
|||
namespace gd = godot;
|
||||
|
||||
GDENUM(ItemCapability,
|
||||
Heal,
|
||||
Revive,
|
||||
WeaponEquip,
|
||||
WeaponRanged,
|
||||
WeaponMelee,
|
||||
ArmourEquip,
|
||||
HeadEquip,
|
||||
UtilityEquip,
|
||||
Consume
|
||||
);
|
||||
Heal,
|
||||
Revive,
|
||||
WeaponEquip,
|
||||
WeaponRanged,
|
||||
WeaponMelee,
|
||||
ArmourEquip,
|
||||
HeadEquip,
|
||||
UtilityEquip,
|
||||
Consume);
|
||||
|
||||
typedef int ItemID;
|
||||
class Unit;
|
||||
|
||||
class Item {
|
||||
friend class ItemDB;
|
||||
friend class ItemDB;
|
||||
|
||||
public:
|
||||
static gd::StringName get_static_class() {
|
||||
gd::UtilityFunctions::push_error("Calling Item::get_static_class() on an Item class that does not implement it. Use ITEM_CLASS(*) macro.");
|
||||
|
@ -45,6 +45,7 @@ public:
|
|||
}
|
||||
Item() = default;
|
||||
virtual ~Item();
|
||||
|
||||
public:
|
||||
virtual bool can_use_on(Unit *used_by, gd::Object *used_on) const;
|
||||
bool try_use_on(Unit *used_by, gd::Object *used_on) const;
|
||||
|
@ -52,22 +53,27 @@ public:
|
|||
bool has_capability(ItemCapability const &capability) const;
|
||||
gd::StringName const &get_animation() const;
|
||||
ItemID get_id() const;
|
||||
|
||||
protected:
|
||||
virtual void use_on(Unit *used_by, gd::Object *used_on) const;
|
||||
|
||||
protected:
|
||||
gd::StringName animation{"RESET"};
|
||||
gd::HashSet<uint32_t> capabilities{};
|
||||
|
||||
private:
|
||||
ItemID id{-1};
|
||||
};
|
||||
|
||||
#define ITEM_CLASS(Class_, DisplayName_, Description_)\
|
||||
friend class ItemDB;\
|
||||
public: \
|
||||
_FORCE_INLINE_ static godot::StringName get_static_class() { return #Class_; }\
|
||||
_FORCE_INLINE_ virtual godot::StringName get_class() const override { return #Class_; }\
|
||||
_FORCE_INLINE_ virtual godot::String get_display_name() const override { return DisplayName_; }\
|
||||
_FORCE_INLINE_ virtual godot::String get_description() const override { return Description_; }\
|
||||
#define ITEM_CLASS(Class_, DisplayName_, Description_) \
|
||||
friend class ItemDB; \
|
||||
\
|
||||
public: \
|
||||
_FORCE_INLINE_ static godot::StringName get_static_class() { return #Class_; } \
|
||||
_FORCE_INLINE_ virtual godot::StringName get_class() const override { return #Class_; } \
|
||||
_FORCE_INLINE_ virtual godot::String get_display_name() const override { return DisplayName_; } \
|
||||
_FORCE_INLINE_ virtual godot::String get_description() const override { return Description_; } \
|
||||
\
|
||||
private:
|
||||
|
||||
#endif // !ITEM_HPP
|
||||
|
|
|
@ -22,7 +22,7 @@ gd::String &ItemDB::StaticData::get_array_hint() {
|
|||
}
|
||||
|
||||
ItemID ItemDB::register_item(Item *item, gd::String item_name) {
|
||||
item->id = ItemDB::data.items.size()+1;
|
||||
item->id = ItemDB::data.items.size() + 1;
|
||||
ItemDB::data.get_hint() += ",";
|
||||
ItemDB::data.get_hint() += item_name;
|
||||
ItemDB::data.get_array_hint() = gd::vformat("%s/%s:%s", gd::Variant::INT, gd::PROPERTY_HINT_ENUM, ItemDB::data.get_hint());
|
||||
|
|
|
@ -14,9 +14,10 @@ class ItemDB {
|
|||
gd::String &get_array_hint();
|
||||
gd::String *array_hint{};
|
||||
gd::String *hint{};
|
||||
gd::Vector<Item*> items{};
|
||||
gd::Vector<Item *> items{};
|
||||
};
|
||||
static ItemID register_item(Item *item, gd::String item_name);
|
||||
|
||||
public:
|
||||
static Item const *get_item(ItemID id);
|
||||
static gd::String const &get_enum_hint();
|
||||
|
@ -27,6 +28,7 @@ public:
|
|||
_FORCE_INLINE_ static ItemID register_item() {
|
||||
return ItemDB::register_item(new TItem(), TItem::get_static_class());
|
||||
}
|
||||
|
||||
private:
|
||||
static StaticData data;
|
||||
};
|
||||
|
|
|
@ -7,19 +7,20 @@
|
|||
namespace gd = godot;
|
||||
|
||||
GDENUM(MarkerType,
|
||||
Generic,
|
||||
Cover,
|
||||
HalfCover
|
||||
);
|
||||
Generic,
|
||||
Cover,
|
||||
HalfCover);
|
||||
|
||||
class NavMarker : public gd::Marker3D {
|
||||
GDCLASS(NavMarker, gd::Marker3D);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _process(double) override;
|
||||
|
||||
void set_marker_type(int type);
|
||||
int get_marker_type() const;
|
||||
|
||||
private:
|
||||
MarkerType type{MarkerType::Generic};
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "nav_room.hpp"
|
||||
#include "nav_marker.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
#include <godot_cpp/classes/global_constants.hpp>
|
||||
#include <cmath>
|
||||
#include <godot_cpp/classes/global_constants.hpp>
|
||||
|
||||
void NavRoom::_bind_methods() {
|
||||
#define CLASSNAME NavRoom
|
||||
|
@ -32,15 +32,15 @@ void NavRoom::_exit_tree() {
|
|||
}
|
||||
|
||||
void NavRoom::on_child_entered(gd::Node *child) {
|
||||
if(NavMarker *marker{gd::Object::cast_to<NavMarker>(child)})
|
||||
if(NavMarker * marker{gd::Object::cast_to<NavMarker>(child)})
|
||||
this->markers.push_back(marker);
|
||||
}
|
||||
|
||||
gd::Vector<NavRoom*> const &NavRoom::get_neighbours() const {
|
||||
gd::Vector<NavRoom *> const &NavRoom::get_neighbours() const {
|
||||
return this->neighbours;
|
||||
}
|
||||
|
||||
gd::Vector<NavMarker*> const &NavRoom::get_markers() const {
|
||||
gd::Vector<NavMarker *> const &NavRoom::get_markers() const {
|
||||
return this->markers;
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,9 @@ gd::Array NavRoom::get_neighbours_inspector() const {
|
|||
|
||||
void NavRoom::set_neighbours_inspector(gd::Array array) {
|
||||
this->neighbours.clear();
|
||||
while(!array.is_empty()) if(NavRoom *room{gd::Object::cast_to<NavRoom>(array.pop_front())})
|
||||
this->neighbours.push_back(room);
|
||||
while(!array.is_empty())
|
||||
if(NavRoom * room{gd::Object::cast_to<NavRoom>(array.pop_front())})
|
||||
this->neighbours.push_back(room);
|
||||
}
|
||||
|
||||
gd::Vector<NavRoom*> NavRoom::rooms{};
|
||||
gd::Vector<NavRoom *> NavRoom::rooms{};
|
||||
|
|
|
@ -11,23 +11,26 @@ class NavMarker;
|
|||
class NavRoom : public gd::Node3D {
|
||||
GDCLASS(NavRoom, gd::Node3D);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static NavRoom *get_closest_room(gd::Vector3 const &closest_to);
|
||||
virtual void _enter_tree() override;
|
||||
virtual void _exit_tree() override;
|
||||
virtual void on_child_entered(gd::Node *child);
|
||||
gd::Vector<NavRoom*> const &get_neighbours() const;
|
||||
gd::Vector<NavMarker*> const &get_markers() const;
|
||||
gd::Vector<NavRoom *> const &get_neighbours() const;
|
||||
gd::Vector<NavMarker *> const &get_markers() const;
|
||||
|
||||
private:
|
||||
void set_neighbours_inspector(gd::Array array);
|
||||
gd::Array get_neighbours_inspector() const;
|
||||
|
||||
private:
|
||||
float radius{1.f};
|
||||
gd::Vector3 centre{0.f, 0.f, 0.f};
|
||||
gd::Vector<NavMarker*> markers{};
|
||||
gd::Vector<NavRoom*> neighbours{};
|
||||
gd::Vector<NavMarker *> markers{};
|
||||
gd::Vector<NavRoom *> neighbours{};
|
||||
|
||||
static gd::Vector<NavRoom*> rooms;
|
||||
static gd::Vector<NavRoom *> rooms;
|
||||
};
|
||||
|
||||
#endif // !NAV_ROOM_HPP
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
#include "character_world_state.hpp"
|
||||
#include "enemy_world_state.hpp"
|
||||
#include "entity_health.hpp"
|
||||
#include "goap/action.hpp"
|
||||
#include "goap/action_db.hpp"
|
||||
#include "goap/actor_world_state.hpp"
|
||||
#include "goap/goal.hpp"
|
||||
#include "goap/planner.hpp"
|
||||
#include "goap/state.hpp"
|
||||
#include "inventory.hpp"
|
||||
#include "item_db.hpp"
|
||||
#include "nav_marker.hpp"
|
||||
|
@ -16,12 +22,6 @@
|
|||
#include "unit.hpp"
|
||||
#include "unit_world_state.hpp"
|
||||
#include "utility_lock.hpp"
|
||||
#include "goap/action.hpp"
|
||||
#include "goap/action_db.hpp"
|
||||
#include "goap/actor_world_state.hpp"
|
||||
#include "goap/goal.hpp"
|
||||
#include "goap/planner.hpp"
|
||||
#include "goap/state.hpp"
|
||||
#include "utils/register_types.hpp"
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
@ -30,9 +30,8 @@
|
|||
|
||||
namespace gd = godot;
|
||||
|
||||
void initialize_gdextension_types(gd::ModuleInitializationLevel p_level)
|
||||
{
|
||||
if (p_level != gd::MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
void initialize_gdextension_types(gd::ModuleInitializationLevel p_level) {
|
||||
if(p_level != gd::MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
utils::godot_cpp_utils_register_types();
|
||||
|
@ -78,15 +77,13 @@ void initialize_gdextension_types(gd::ModuleInitializationLevel p_level)
|
|||
GDREGISTER_RUNTIME_CLASS(RTSPlayer);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// Initialization
|
||||
GDExtensionBool GDE_EXPORT metro_rts_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||
{
|
||||
gd::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
init_obj.register_initializer(initialize_gdextension_types);
|
||||
init_obj.set_minimum_library_initialization_level(gd::MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
extern "C" {
|
||||
// Initialization
|
||||
GDExtensionBool GDE_EXPORT metro_rts_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||
gd::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
init_obj.register_initializer(initialize_gdextension_types);
|
||||
init_obj.set_minimum_library_initialization_level(gd::MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
return init_obj.init();
|
||||
}
|
||||
return init_obj.init();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
#include "rts_actions.hpp"
|
||||
#include "nav_marker.hpp"
|
||||
#include "nav_room.hpp"
|
||||
#include "rts_states.hpp"
|
||||
#include "utility_lock.hpp"
|
||||
#include "goap/actor_world_state.hpp"
|
||||
#include "goap/state.hpp"
|
||||
#include "godot_cpp/classes/object.hpp"
|
||||
#include "nav_marker.hpp"
|
||||
#include "nav_room.hpp"
|
||||
#include "rts_actions.hpp"
|
||||
#include "rts_states.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "unit_world_state.hpp"
|
||||
#include "utility_lock.hpp"
|
||||
#include <cmath>
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
#include <godot_cpp/variant/basis.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
#include <cmath>
|
||||
|
||||
MoveToTarget::MoveToTarget()
|
||||
: Action() {
|
||||
MoveToTarget::MoveToTarget() :
|
||||
Action() {
|
||||
this->required.insert("can_reach_target", true);
|
||||
this->effects.insert("is_at_target", true);
|
||||
}
|
||||
|
||||
|
@ -26,8 +30,8 @@ goap::State *MoveToTarget::get_apply_state(goap::ActorWorldState *context) const
|
|||
return state;
|
||||
}
|
||||
|
||||
UseWeapon::UseWeapon()
|
||||
: Action() {
|
||||
UseWeapon::UseWeapon() :
|
||||
Action() {
|
||||
this->required.insert("can_see_target", true);
|
||||
this->required.insert("is_in_range", true);
|
||||
this->effects.insert("is_target_unconscious", true);
|
||||
|
@ -39,8 +43,8 @@ goap::State *UseWeapon::get_apply_state(goap::ActorWorldState *context) const {
|
|||
return state;
|
||||
}
|
||||
|
||||
FindTarget::FindTarget()
|
||||
: Action() {
|
||||
FindTarget::FindTarget() :
|
||||
Action() {
|
||||
this->require_state_complete = false;
|
||||
this->effects.insert("can_see_target", true);
|
||||
}
|
||||
|
@ -52,10 +56,10 @@ goap::State *FindTarget::get_apply_state(goap::ActorWorldState *context) const {
|
|||
return state;
|
||||
}
|
||||
|
||||
GetInRange::GetInRange()
|
||||
: Action() {
|
||||
GetInRange::GetInRange() :
|
||||
Action() {
|
||||
this->require_state_complete = false;
|
||||
this->required.insert("can_see_target", true);
|
||||
this->effects.insert("can_see_target", true);
|
||||
this->effects.insert("is_in_range", true);
|
||||
}
|
||||
|
||||
|
@ -66,9 +70,8 @@ goap::State *GetInRange::get_apply_state(goap::ActorWorldState *context) const {
|
|||
return state;
|
||||
}
|
||||
|
||||
TankSelfHeal::TankSelfHeal()
|
||||
: Action() {
|
||||
this->required.insert("can_see_target", false);
|
||||
TankSelfHeal::TankSelfHeal() :
|
||||
Action() {
|
||||
this->effects.insert("is_health_safe", true);
|
||||
}
|
||||
|
||||
|
@ -78,8 +81,8 @@ goap::State *TankSelfHeal::get_apply_state(goap::ActorWorldState *) const {
|
|||
return state;
|
||||
}
|
||||
|
||||
TakeCover::TakeCover()
|
||||
: Action () {
|
||||
TakeCover::TakeCover() :
|
||||
Action() {
|
||||
this->effects.insert("can_see_target", false);
|
||||
}
|
||||
|
||||
|
@ -100,6 +103,7 @@ bool TakeCover::procedural_is_possible(goap::ActorWorldState *context) const {
|
|||
}
|
||||
|
||||
goap::State *TakeCover::get_apply_state(goap::ActorWorldState *context) const {
|
||||
UnitWorldState *unit_state{gd::Object::cast_to<UnitWorldState>(context)};
|
||||
// positions of the context and the target to hide from
|
||||
gd::Vector3 const context_position{context->get_world_property("parent_global_position")};
|
||||
gd::Vector3 const target_position{context->get_world_property("target_global_position")};
|
||||
|
@ -110,6 +114,10 @@ goap::State *TakeCover::get_apply_state(goap::ActorWorldState *context) const {
|
|||
NavMarker *best_marker{nullptr}; // marker with the best score found so far
|
||||
float best_score{0.f}; // best score found so far, starts at zero because negative values should not be considered
|
||||
for(NavMarker *marker : room->get_markers()) {
|
||||
bool can_reach{unit_state->can_reach_point(marker->get_global_position())};
|
||||
if(!can_reach) {
|
||||
continue; // skip if unreachable
|
||||
}
|
||||
float const score{this->score_cover_marker(marker, target_position, context_position)};
|
||||
if(score > best_score) {
|
||||
best_score = score;
|
||||
|
@ -128,11 +136,10 @@ goap::State *TakeCover::get_apply_state(goap::ActorWorldState *context) const {
|
|||
bool TakeCover::is_marker_cover_from(NavMarker *marker, gd::Vector3 const &target_position, gd::Vector3 const &context_position) {
|
||||
gd::Vector3 const marker_position{marker->get_global_position()};
|
||||
float const distance_to_target{target_position.distance_to(context_position)};
|
||||
return marker->get_marker_type() == MarkerType::Cover
|
||||
&& marker->get_global_basis().get_column(2).dot(marker_position - target_position) < -2.f;
|
||||
return marker->get_marker_type() == MarkerType::Cover && marker->get_global_basis().get_column(2).dot(marker_position - target_position) < -2.f;
|
||||
}
|
||||
|
||||
float TakeCover::score_cover_marker(class NavMarker* marker, const gd::Vector3& target_position, const gd::Vector3& context_position) const {
|
||||
float TakeCover::score_cover_marker(class NavMarker *marker, const gd::Vector3 &target_position, const gd::Vector3 &context_position) const {
|
||||
if(!TakeCover::is_marker_cover_from(marker, target_position, context_position))
|
||||
return 0.f;
|
||||
gd::Vector3 const marker_position{marker->get_global_position()}; // position of the marker being considered
|
||||
|
@ -173,7 +180,7 @@ goap::State *ActivateLock::get_apply_state(goap::ActorWorldState *context) const
|
|||
}
|
||||
Activate *activate = this->create_state<Activate>();
|
||||
activate->lock = lock;
|
||||
if(Inventory *inventory{unit_context->get_node<Inventory>("%Inventory")})
|
||||
if(Inventory * inventory{unit_context->get_node<Inventory>("%Inventory")})
|
||||
activate->using_item = inventory->get_utility();
|
||||
return activate;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
class MoveToTarget : public goap::Action {
|
||||
GOAP_ACTION(MoveToTarget);
|
||||
|
||||
public:
|
||||
MoveToTarget();
|
||||
virtual goap::State *get_apply_state(goap::ActorWorldState *context) const override;
|
||||
|
@ -13,6 +14,7 @@ public:
|
|||
|
||||
class UseWeapon : public goap::Action {
|
||||
GOAP_ACTION(UseWeapon);
|
||||
|
||||
public:
|
||||
UseWeapon();
|
||||
virtual goap::State *get_apply_state(goap::ActorWorldState *context) const override;
|
||||
|
@ -20,6 +22,7 @@ public:
|
|||
|
||||
class FindTarget : public goap::Action {
|
||||
GOAP_ACTION(FindTarget);
|
||||
|
||||
public:
|
||||
FindTarget();
|
||||
virtual goap::State *get_apply_state(goap::ActorWorldState *context) const override;
|
||||
|
@ -27,6 +30,7 @@ public:
|
|||
|
||||
class GetInRange : public goap::Action {
|
||||
GOAP_ACTION(GetInRange);
|
||||
|
||||
public:
|
||||
GetInRange();
|
||||
virtual goap::State *get_apply_state(goap::ActorWorldState *context) const override;
|
||||
|
@ -34,6 +38,7 @@ public:
|
|||
|
||||
class TankSelfHeal : public goap::Action {
|
||||
GOAP_ACTION(TankSelfHeal);
|
||||
|
||||
public:
|
||||
TankSelfHeal();
|
||||
virtual goap::State *get_apply_state(goap::ActorWorldState *) const override;
|
||||
|
@ -41,10 +46,12 @@ public:
|
|||
|
||||
class TakeCover : public goap::Action {
|
||||
GOAP_ACTION(TakeCover);
|
||||
|
||||
public:
|
||||
TakeCover();
|
||||
virtual bool procedural_is_possible(goap::ActorWorldState *context) const override;
|
||||
virtual goap::State *get_apply_state(goap::ActorWorldState *context) const override;
|
||||
|
||||
private:
|
||||
static bool is_marker_cover_from(class NavMarker *marker, gd::Vector3 const &target_position, gd::Vector3 const &context_position);
|
||||
float score_cover_marker(class NavMarker *marker, gd::Vector3 const &target_position, gd::Vector3 const &context_position) const;
|
||||
|
@ -52,6 +59,7 @@ private:
|
|||
|
||||
class ActivateLock : public goap::Action {
|
||||
GOAP_ACTION(ActivateLock);
|
||||
|
||||
public:
|
||||
ActivateLock();
|
||||
virtual bool procedural_is_possible(goap::ActorWorldState *context) const override;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
class RTSGameMode : public utils::GameMode {
|
||||
GDCLASS(RTSGameMode, utils::GameMode);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "rts_items.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "entity_health.hpp"
|
||||
#include "unit.hpp"
|
||||
|
||||
Medkit::Medkit()
|
||||
: Item() {
|
||||
Medkit::Medkit() :
|
||||
Item() {
|
||||
this->capabilities.insert(ItemCapability::Consume);
|
||||
this->capabilities.insert(ItemCapability::Heal);
|
||||
this->capabilities.insert(ItemCapability::Revive);
|
||||
|
@ -17,38 +17,38 @@ void Medkit::use_on(Unit *used_by, gd::Object *used_on) const {
|
|||
gd::Object::cast_to<Unit>(used_on)->get_entity_health()->healed_by(3, used_by);
|
||||
}
|
||||
|
||||
Handgun::Handgun()
|
||||
: Item() {
|
||||
Handgun::Handgun() :
|
||||
Item() {
|
||||
this->animation = "fire_weapon";
|
||||
this->capabilities.insert(ItemCapability::WeaponEquip);
|
||||
this->capabilities.insert(ItemCapability::WeaponRanged);
|
||||
}
|
||||
|
||||
bool Handgun::can_use_on(Unit *used_by, gd::Object *used_on) const {
|
||||
return gd::Object::cast_to<Unit>(used_on) != nullptr
|
||||
&& used_by->get_world_state()->get_can_see_target();
|
||||
return gd::Object::cast_to<Unit>(used_on) != nullptr && used_by->get_world_state()->get_can_see_target();
|
||||
}
|
||||
|
||||
void Handgun::apply_stats(Stats &stats) const {
|
||||
stats.weapon_range = 10.f;
|
||||
}
|
||||
|
||||
void Handgun::use_on(Unit* used_by, gd::Object* used_on) const {
|
||||
void Handgun::use_on(Unit *used_by, gd::Object *used_on) const {
|
||||
Unit *target{gd::Object::cast_to<Unit>(used_on)};
|
||||
used_by->aim_at(target);
|
||||
EntityHealth *health{target->get_entity_health()};
|
||||
health->damaged_by(4, used_by);
|
||||
gd::Vector3 const owner_position{used_by->get_global_position()};
|
||||
gd::Vector3 const target_position{target->get_global_position()};
|
||||
used_by->look_at(owner_position-(target_position-owner_position));
|
||||
if(owner_position != target_position)
|
||||
used_by->look_at(owner_position - (target_position - owner_position));
|
||||
}
|
||||
|
||||
Lasercutter::Lasercutter()
|
||||
: Item() {
|
||||
Lasercutter::Lasercutter() :
|
||||
Item() {
|
||||
this->capabilities.insert(ItemCapability::UtilityEquip);
|
||||
}
|
||||
|
||||
Welder::Welder()
|
||||
: Item() {
|
||||
Welder::Welder() :
|
||||
Item() {
|
||||
this->capabilities.insert(ItemCapability::UtilityEquip);
|
||||
}
|
||||
|
|
|
@ -5,32 +5,40 @@
|
|||
|
||||
class Medkit : public Item {
|
||||
ITEM_CLASS(Medkit, "Medkit",
|
||||
"Standard emergency home medical kit. Use to manage wounds and stabilize a person.");
|
||||
"Standard emergency home medical kit. Use to manage wounds and stabilize a person.");
|
||||
|
||||
private:
|
||||
Medkit();
|
||||
|
||||
public:
|
||||
virtual bool can_use_on(Unit *used_by, gd::Object *used_on) const override;
|
||||
|
||||
protected:
|
||||
virtual void use_on(Unit *used_by, gd::Object *used_on) const override;
|
||||
};
|
||||
|
||||
class Handgun : public Item {
|
||||
ITEM_CLASS(Handgun, "9mm handgun.",
|
||||
"A standard issue police firearm.");
|
||||
"A standard issue police firearm.");
|
||||
|
||||
private:
|
||||
Handgun();
|
||||
|
||||
public:
|
||||
virtual bool can_use_on(Unit *used_by, gd::Object *used_on) const override;
|
||||
virtual void apply_stats(Stats &stats) const override;
|
||||
|
||||
protected:
|
||||
virtual void use_on(Unit *used_by, gd::Object *used_on) const override;
|
||||
};
|
||||
|
||||
class Lasercutter : public Item {
|
||||
ITEM_CLASS(Lasercutter, "Lasercutter",
|
||||
"A laser cutter, use to clear metal obstacles.");
|
||||
"A laser cutter, use to clear metal obstacles.");
|
||||
|
||||
private:
|
||||
Lasercutter();
|
||||
|
||||
public:
|
||||
// virtual bool can_use_on(Unit *used_by, gd::Object *object) const override;
|
||||
protected:
|
||||
|
@ -39,9 +47,11 @@ protected:
|
|||
|
||||
class Welder : public Item {
|
||||
ITEM_CLASS(Welder, "Welder",
|
||||
"A welder with tanks intended to be carried on a person's back. Use to repair broken metal parts.");
|
||||
"A welder with tanks intended to be carried on a person's back. Use to repair broken metal parts.");
|
||||
|
||||
private:
|
||||
Welder();
|
||||
|
||||
public:
|
||||
// virtual bool can_use_on(Unit *used_by, gd::Object *object) const override;
|
||||
protected:
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <godot_cpp/classes/curve.hpp>
|
||||
#include <godot_cpp/classes/packed_scene.hpp>
|
||||
#include <godot_cpp/classes/physics_direct_space_state3d.hpp>
|
||||
#include <godot_cpp/classes/physics_direct_space_state3d.hpp>
|
||||
#include <godot_cpp/classes/physics_ray_query_parameters3d.hpp>
|
||||
#include <godot_cpp/classes/viewport.hpp>
|
||||
#include <godot_cpp/classes/world3d.hpp>
|
||||
|
@ -127,7 +126,6 @@ bool RTSPlayer::order_activate_object(gd::Node3D *node) {
|
|||
return true;
|
||||
}
|
||||
return unit != nullptr;
|
||||
|
||||
}
|
||||
|
||||
void RTSPlayer::clear_selected_unit() {
|
||||
|
@ -236,4 +234,3 @@ void RTSPlayer::DEBUG_enable_debug(gd::Ref<gd::InputEvent>, float value) {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ class RTSPlayer : public gd::Node3D,
|
|||
public utils::IPlayer {
|
||||
GDCLASS(RTSPlayer, godot::Node3D);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
virtual void _process(double delta_time) override;
|
||||
|
@ -24,6 +25,7 @@ public:
|
|||
virtual void setup_player_input(utils::PlayerInput *input) override;
|
||||
virtual Node *to_node() override;
|
||||
virtual void spawn_at_position(gd::Transform3D const &at) override;
|
||||
|
||||
private:
|
||||
//! process any changes to mouse position
|
||||
void process_mouse();
|
||||
|
@ -61,10 +63,12 @@ private:
|
|||
gd::Ref<gd::PackedScene> get_ground_marker_scene() const;
|
||||
void set_zoom_curve(gd::Ref<gd::Curve> curve);
|
||||
gd::Ref<gd::Curve> get_zoom_curve() const;
|
||||
|
||||
private:
|
||||
gd::Callable const on_selected_unit_destroyed{callable_mp(this, &RTSPlayer::clear_selected_unit)};
|
||||
|
||||
private:
|
||||
Unit* selected_unit{nullptr};
|
||||
Unit *selected_unit{nullptr};
|
||||
|
||||
bool mmb_down{false};
|
||||
bool lmb_down{false};
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#include "unit.hpp"
|
||||
#include "utility_lock.hpp"
|
||||
#include "utils/util_functions.hpp"
|
||||
#include <cmath>
|
||||
#include <godot_cpp/core/math.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
#include <cmath>
|
||||
|
||||
void MoveTo::_bind_methods() {}
|
||||
|
||||
|
@ -114,18 +114,34 @@ void Activate::_end_state() {
|
|||
void Animate::_bind_methods() {}
|
||||
|
||||
void Animate::_ready() {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), ": attempting to play animation ", this->animation);
|
||||
this->anim = this->get_parent()->get_node<gd::AnimationPlayer>("%AnimationPlayer");
|
||||
if(!this->anim->has_animation(this->animation))
|
||||
if(!this->anim->has_animation(this->animation)) {
|
||||
this->end_state();
|
||||
else this->anim->play(this->animation);
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), ": failed to play animation ", this->animation);
|
||||
} else {
|
||||
this->anim->play(this->animation);
|
||||
this->anim->advance(0);
|
||||
this->anim->connect("animation_finished", callable_mp(this, &self_type::_on_animation_finished));
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), ": succeeded playing animation ", this->animation);
|
||||
}
|
||||
}
|
||||
|
||||
void Animate::_process(double) {
|
||||
bool const animation_finished{!this->anim->is_playing() || this->anim->get_current_animation() != this->animation};
|
||||
if(this->is_action_done_interrupt() || animation_finished)
|
||||
if(this->is_action_done_interrupt() || this->is_finished) {
|
||||
gd::UtilityFunctions::print("!!! animation " , this->animation,
|
||||
" is done in ", this->get_path(),
|
||||
" animation finished: ", this->is_finished,
|
||||
" interrupted: ", this->is_action_done_interrupt());
|
||||
this->end_state();
|
||||
}
|
||||
}
|
||||
|
||||
void Animate::_end_state() {
|
||||
this->anim->stop();
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " animation ", this->animation, " stopped");
|
||||
}
|
||||
|
||||
void Animate::_on_animation_finished(gd::String new_anim) {
|
||||
this->is_finished = true;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef RTS_STATES_HPP
|
||||
#define RTS_STATES_HPP
|
||||
|
||||
#include "unit.hpp"
|
||||
#include "goap/state.hpp"
|
||||
#include "unit.hpp"
|
||||
#include <godot_cpp/classes/animation_player.hpp>
|
||||
#include <godot_cpp/classes/navigation_agent3d.hpp>
|
||||
|
||||
|
@ -13,6 +13,7 @@ class UtilityLock;
|
|||
class MoveTo : public goap::State {
|
||||
GDCLASS(MoveTo, goap::State);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
virtual void _end_state() override;
|
||||
|
@ -22,8 +23,10 @@ public:
|
|||
float target_delta_position() const;
|
||||
float distance_to_target() const;
|
||||
double get_repath_interval() const;
|
||||
|
||||
public:
|
||||
gd::Node3D *target_node{nullptr};
|
||||
|
||||
private:
|
||||
gd::Callable nav_velocity_computed{callable_mp(this, &MoveTo::on_velocity_computed)};
|
||||
Unit *parent_unit{nullptr};
|
||||
|
@ -35,12 +38,14 @@ private:
|
|||
class Activate : public goap::State {
|
||||
GDCLASS(Activate, goap::State);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
virtual void _process(double) override;
|
||||
virtual void _end_state() override;
|
||||
UtilityLock *lock{nullptr};
|
||||
Item const *using_item{nullptr};
|
||||
|
||||
private:
|
||||
gd::String animation{};
|
||||
gd::AnimationPlayer *anim{nullptr};
|
||||
|
@ -50,12 +55,16 @@ private:
|
|||
class Animate : public goap::State {
|
||||
GDCLASS(Animate, goap::State);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _ready() override;
|
||||
virtual void _process(double delta_time) override;
|
||||
virtual void _end_state() override;
|
||||
void _on_animation_finished(gd::String new_anim);
|
||||
gd::StringName animation{};
|
||||
|
||||
private:
|
||||
bool is_finished{false};
|
||||
gd::AnimationPlayer *anim{nullptr};
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
class TankUnit : public Unit {
|
||||
GDCLASS(TankUnit, Unit);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void use_weapon() override;
|
||||
};
|
||||
|
|
28
src/unit.cpp
28
src/unit.cpp
|
@ -45,6 +45,7 @@ void Unit::_physics_process(double) {
|
|||
}
|
||||
|
||||
void Unit::stop_plan() {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " stop_plan");
|
||||
this->current_goal.unref();
|
||||
this->current_plan.clear();
|
||||
this->destroy_state();
|
||||
|
@ -71,6 +72,7 @@ void Unit::begin_marker_temporary(GoalMarker *marker) {
|
|||
}
|
||||
|
||||
void Unit::set_target_goal(gd::Node3D *target, gd::Ref<goap::Goal> goal) {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " set_target_goal");
|
||||
this->destroy_state();
|
||||
this->world_state->set_target_node(target);
|
||||
this->begin_goal(goal);
|
||||
|
@ -96,6 +98,7 @@ void Unit::aim_at(gd::Node3D *target) {
|
|||
}
|
||||
|
||||
void Unit::on_unconscious(Unit *damage_source) {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " on_unconscious");
|
||||
this->destroy_state();
|
||||
this->emit_signal("plan_failed");
|
||||
this->anim_player->stop();
|
||||
|
@ -103,6 +106,7 @@ void Unit::on_unconscious(Unit *damage_source) {
|
|||
}
|
||||
|
||||
void Unit::on_death(Unit *damage_source) {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " on_death");
|
||||
this->destroy_state();
|
||||
this->emit_signal("plan_failed");
|
||||
if(this->anim_player->get_current_animation() != gd::StringName("death")) {
|
||||
|
@ -113,13 +117,16 @@ void Unit::on_death(Unit *damage_source) {
|
|||
|
||||
void Unit::on_velocity_computed(gd::Vector3 vel) {
|
||||
gd::Vector3 const pos{this->get_global_position()};
|
||||
if(vel.x == 0 && vel.z == 0)
|
||||
if(vel.x == 0 && vel.z == 0) {
|
||||
this->set_velocity({0.f, 0.f, 0.f});
|
||||
return;
|
||||
}
|
||||
this->set_velocity(vel.normalized() * this->movement_speed);
|
||||
this->look_at(pos - gd::Vector3{vel.x, 0.f, vel.z});
|
||||
}
|
||||
|
||||
void Unit::destroy_state() {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " destroy_state");
|
||||
if(this->state == nullptr)
|
||||
return;
|
||||
if(!this->state->is_queued_for_deletion())
|
||||
|
@ -143,8 +150,14 @@ void Unit::next_action() {
|
|||
if(this->current_plan.is_empty())
|
||||
return;
|
||||
goap::Action const *action{this->current_plan.get(0)};
|
||||
if(action == nullptr || !action->is_possible(this->world_state)) {
|
||||
if(action == nullptr) {
|
||||
gd::UtilityFunctions::push_error("Plan interrupted by invalid action in queue");
|
||||
this->emit_signal("plan_interrupted");
|
||||
return;
|
||||
}
|
||||
if(!action->is_possible(this->world_state)) {
|
||||
this->emit_signal("plan_interrupted");
|
||||
gd::UtilityFunctions::push_error("Plan interrupted because action ", action->get_class(), " is impossible");
|
||||
return;
|
||||
}
|
||||
// get next action and apply state
|
||||
|
@ -193,10 +206,14 @@ int Unit::get_configure_team() const {
|
|||
}
|
||||
|
||||
bool Unit::has_plan() const {
|
||||
return !this->current_plan.is_empty();
|
||||
return !this->current_plan.is_empty() || this->state != nullptr;
|
||||
}
|
||||
|
||||
EntityHealth *Unit::get_entity_health() {
|
||||
gd::Ref<goap::Goal> Unit::get_current_goal() const {
|
||||
return this->current_goal;
|
||||
}
|
||||
|
||||
EntityHealth *Unit::get_entity_health() const {
|
||||
return this->health;
|
||||
}
|
||||
|
||||
|
@ -211,7 +228,8 @@ float Unit::get_movement_speed() const {
|
|||
#ifdef DEBUG_ENABLED
|
||||
gd::String Unit::DEBUG_print_debug_info() {
|
||||
gd::String debug_info{};
|
||||
debug_info += gd::String("health: ") + gd::vformat("%d", this->get_entity_health()->get_wounds_current());
|
||||
debug_info += gd::String("wounds: ") + gd::vformat("%d", this->get_entity_health()->get_wounds_current());
|
||||
debug_info += gd::String("\ninjury: ") + gd::vformat("%d", this->get_entity_health()->get_injury_current());
|
||||
debug_info += "\ngoal: ";
|
||||
if(!this->current_goal.is_valid()) {
|
||||
debug_info += "No goal assigned";
|
||||
|
|
19
src/unit.hpp
19
src/unit.hpp
|
@ -2,9 +2,9 @@
|
|||
#define RTS_UNIT_HPP
|
||||
|
||||
#include "goal_marker.hpp"
|
||||
#include "unit_world_state.hpp"
|
||||
#include "goap/goal.hpp"
|
||||
#include "goap/planner.hpp"
|
||||
#include "unit_world_state.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
#include <godot_cpp/classes/animation_player.hpp>
|
||||
#include <godot_cpp/classes/character_body3d.hpp>
|
||||
|
@ -15,15 +15,15 @@
|
|||
namespace gd = godot;
|
||||
|
||||
GDENUM(UnitTeam,
|
||||
Neutral,
|
||||
Player,
|
||||
Ally,
|
||||
Enemy
|
||||
);
|
||||
Neutral,
|
||||
Player,
|
||||
Ally,
|
||||
Enemy);
|
||||
|
||||
class Unit : public gd::CharacterBody3D {
|
||||
GDCLASS(Unit, gd::CharacterBody3D);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _enter_tree() override;
|
||||
virtual void _physics_process(double) override;
|
||||
|
@ -36,6 +36,7 @@ public:
|
|||
void aim_at(gd::Node3D *node);
|
||||
void on_unconscious(Unit *damage_source);
|
||||
void on_death(Unit *damage_source);
|
||||
|
||||
private:
|
||||
void on_velocity_computed(gd::Vector3 vel);
|
||||
void destroy_state();
|
||||
|
@ -43,18 +44,22 @@ private:
|
|||
void next_action();
|
||||
void replan_goal();
|
||||
void set_goal_and_plan(gd::Ref<goap::Goal> goal);
|
||||
|
||||
public: // getter-setters
|
||||
UnitWorldState *get_world_state() const;
|
||||
UnitTeam get_team() const;
|
||||
void set_configure_team(int value);
|
||||
int get_configure_team() const;
|
||||
bool has_plan() const;
|
||||
EntityHealth *get_entity_health();
|
||||
gd::Ref<goap::Goal> get_current_goal() const;
|
||||
EntityHealth *get_entity_health() const;
|
||||
void set_movement_speed(float speed);
|
||||
float get_movement_speed() const;
|
||||
|
||||
private:
|
||||
gd::Callable on_state_finished{callable_mp(this, &Unit::state_finished)};
|
||||
gd::Callable on_plan_failed{callable_mp(this, &Unit::replan_goal)};
|
||||
|
||||
protected:
|
||||
goap::Plan current_plan{};
|
||||
gd::Ref<goap::Goal> current_goal{};
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#include "unit_world_state.hpp"
|
||||
#include "entity_health.hpp"
|
||||
#include "godot_cpp/classes/navigation_server3d.hpp"
|
||||
#include "godot_cpp/variant/packed_vector3_array.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "utility_lock.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
#include "utils/util_functions.hpp"
|
||||
#include <godot_cpp/classes/physics_direct_space_state3d.hpp>
|
||||
#include <godot_cpp/classes/physics_ray_query_parameters3d.hpp>
|
||||
#include <godot_cpp/classes/world3d.hpp>
|
||||
#include <godot_cpp/classes/physics_direct_space_state3d.hpp>
|
||||
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
|
@ -22,6 +24,7 @@ void UnitWorldState::_bind_methods() {
|
|||
GDFUNCTION(get_is_target_enemy);
|
||||
GDFUNCTION(get_is_target_activated);
|
||||
GDFUNCTION(get_is_in_range);
|
||||
GDFUNCTION(get_can_reach_target);
|
||||
GDFUNCTION(get_is_health_safe);
|
||||
GDFUNCTION(get_parent_global_position);
|
||||
GDFUNCTION(get_target_global_position);
|
||||
|
@ -61,19 +64,19 @@ bool UnitWorldState::get_can_see_node(gd::Node3D *node) const {
|
|||
// construct list for ignored objects including target node and parent unit
|
||||
gd::TypedArray<gd::RID> ignore_list{this->parent_unit->get_rid()};
|
||||
// ignore target if it is a collision object that might obstruct it's own collision test
|
||||
if(gd::CollisionObject3D *as_collision_object{gd::Object::cast_to<gd::CollisionObject3D>(node)})
|
||||
if(gd::CollisionObject3D * as_collision_object{gd::Object::cast_to<gd::CollisionObject3D>(node)})
|
||||
ignore_list.push_back(as_collision_object->get_rid());
|
||||
// construct raycast query from unit's eye node to vision target. Ignoring parent unit and target if applicable
|
||||
gd::Ref<gd::PhysicsRayQueryParameters3D> const query{gd::PhysicsRayQueryParameters3D::create(
|
||||
eyes.origin,
|
||||
target_position,
|
||||
0x1 | 0x4, ignore_list
|
||||
)};
|
||||
eyes.origin,
|
||||
target_position,
|
||||
0x1 | 0x4, ignore_list)};
|
||||
return this->parent_unit->get_world_3d()->get_direct_space_state()->intersect_ray(query).is_empty();
|
||||
}
|
||||
|
||||
bool UnitWorldState::get_is_at_target() const {
|
||||
if(this->target_node == nullptr) return true;
|
||||
if(this->target_node == nullptr)
|
||||
return true;
|
||||
gd::Vector3 const target = this->target_node->get_global_position();
|
||||
gd::Vector3 const current = this->parent_unit->get_global_position();
|
||||
float const min_dist = this->agent->get_target_desired_distance();
|
||||
|
@ -85,7 +88,7 @@ bool UnitWorldState::get_has_target() const {
|
|||
}
|
||||
|
||||
bool UnitWorldState::get_is_target_unconscious() const {
|
||||
if(EntityHealth *health{this->target_node->get_node<EntityHealth>("%EntityHealth")})
|
||||
if(EntityHealth * health{this->target_node->get_node<EntityHealth>("%EntityHealth")})
|
||||
return !health->is_conscious();
|
||||
return false;
|
||||
}
|
||||
|
@ -100,9 +103,7 @@ bool UnitWorldState::get_is_target_enemy() const {
|
|||
}
|
||||
|
||||
bool UnitWorldState::get_is_unit_enemy(Unit *unit) const {
|
||||
return unit != nullptr
|
||||
&& unit->get_team() != UnitTeam::Neutral
|
||||
&& unit->get_team() != this->parent_unit->get_team();
|
||||
return unit != nullptr && unit->get_team() != UnitTeam::Neutral && unit->get_team() != this->parent_unit->get_team();
|
||||
}
|
||||
|
||||
bool UnitWorldState::get_is_target_activated() const {
|
||||
|
@ -111,8 +112,21 @@ bool UnitWorldState::get_is_target_activated() const {
|
|||
}
|
||||
|
||||
bool UnitWorldState::get_is_in_range() const {
|
||||
return this->target_node != nullptr
|
||||
&& this->target_node->get_global_position().distance_squared_to(this->parent_unit->get_global_position()) <= 2.f * 2.f;
|
||||
return this->target_node != nullptr && this->target_node->get_global_position().distance_squared_to(this->parent_unit->get_global_position()) <= 2.f * 2.f;
|
||||
}
|
||||
|
||||
bool UnitWorldState::can_reach_point(gd::Vector3 point) const {
|
||||
gd::NavigationServer3D *server{gd::NavigationServer3D::get_singleton()};
|
||||
godot::PackedVector3Array path{server->map_get_path(this->agent->get_navigation_map(),
|
||||
this->parent_unit->get_global_position(), point, false, 0xF)};
|
||||
gd::Vector3 const endpoint{path[path.size() - 1]};
|
||||
bool const can_reach{!path.is_empty() && gd::Vector2{endpoint.x, endpoint.z}.is_equal_approx({point.x, point.z})};
|
||||
gd::UtilityFunctions::print("target ", point, " reachable from ", this->get_parent_global_position(), ": ", can_reach, ", endpoint ", path[path.size()-1]);
|
||||
return can_reach;
|
||||
}
|
||||
|
||||
bool UnitWorldState::get_can_reach_target() const {
|
||||
return this->can_reach_point(this->get_target_global_position());
|
||||
}
|
||||
|
||||
bool UnitWorldState::get_is_health_safe() const {
|
||||
|
@ -142,7 +156,7 @@ gd::Node3D *UnitWorldState::get_target_node() const {
|
|||
}
|
||||
|
||||
void UnitWorldState::cache_property(gd::String property, gd::Variant value, double auto_invalidate_time) {
|
||||
this->cache[property] = {.value=value, .auto_invalidate_time=auto_invalidate_time};
|
||||
this->cache[property] = {.value = value, .auto_invalidate_time = auto_invalidate_time};
|
||||
}
|
||||
|
||||
void UnitWorldState::target_destroyed(gd::Node3D *target) {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#define UNIT_WORLD_STATE_HPP
|
||||
|
||||
#include "entity_health.hpp"
|
||||
#include "inventory.hpp"
|
||||
#include "goap/actor_world_state.hpp"
|
||||
#include "inventory.hpp"
|
||||
#include <godot_cpp/classes/navigation_agent3d.hpp>
|
||||
#include <godot_cpp/classes/node3d.hpp>
|
||||
|
||||
|
@ -19,6 +19,7 @@ struct CachedWorldProperty {
|
|||
class UnitWorldState : public goap::ActorWorldState {
|
||||
GDCLASS(UnitWorldState, goap::ActorWorldState);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void _enter_tree() override;
|
||||
virtual gd::Variant get_world_property(gd::String property) override;
|
||||
|
@ -34,16 +35,21 @@ public:
|
|||
bool get_is_unit_enemy(Unit *unit) const;
|
||||
bool get_is_target_activated() const;
|
||||
virtual bool get_is_in_range() const;
|
||||
bool can_reach_point(gd::Vector3 point) const;
|
||||
bool get_can_reach_target() const;
|
||||
bool get_is_health_safe() const;
|
||||
gd::Vector3 get_parent_global_position() const;
|
||||
gd::Vector3 get_target_global_position() const;
|
||||
void set_target_node(gd::Node3D *node);
|
||||
gd::Node3D *get_target_node() const;
|
||||
|
||||
private:
|
||||
void cache_property(gd::String property, gd::Variant value, double auto_invalidate_time);
|
||||
void target_destroyed(gd::Node3D *target);
|
||||
|
||||
private:
|
||||
gd::Callable const target_node_exited_tree{callable_mp(this, &UnitWorldState::target_destroyed)};
|
||||
|
||||
protected:
|
||||
Unit *parent_unit{nullptr};
|
||||
EntityHealth *health{nullptr};
|
||||
|
|
|
@ -23,7 +23,8 @@ bool UtilityLock::begin_activate(Item const *with, Unit *by) {
|
|||
this->_begin_activate(with, by);
|
||||
this->emit_signal("begin_activate", with->get_id(), by);
|
||||
return true;
|
||||
} else return false;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UtilityLock::finish_activate(Item const *with, Unit *by) {
|
||||
|
@ -33,7 +34,8 @@ bool UtilityLock::finish_activate(Item const *with, Unit *by) {
|
|||
this->_finish_activate(with, by);
|
||||
this->emit_signal("finish_activate", with->get_id(), by);
|
||||
return true;
|
||||
} else return false;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
void UtilityLock::interrupt_activate() {
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
|
||||
#include "goal_marker.hpp"
|
||||
#include "item.hpp"
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
#include <godot_cpp/templates/hash_set.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
namespace gd = godot;
|
||||
|
||||
class UtilityLock : public GoalMarker {
|
||||
GDCLASS(UtilityLock, GoalMarker)
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum ActivationState {
|
||||
Inactive,
|
||||
|
@ -31,6 +32,7 @@ public:
|
|||
gd::Array get_allowed_items() const;
|
||||
void set_animation_name(gd::String animation);
|
||||
gd::String get_animation_name() const;
|
||||
|
||||
private:
|
||||
gd::HashSet<Item const *> allowed_items{};
|
||||
Unit *user{nullptr};
|
||||
|
|
Loading…
Reference in a new issue