Additional collision/avoidance changes for monstos
This commit is contained in:
@@ -55,6 +55,5 @@ public partial class FleeBehavior : Node3D, IBehavior
|
|||||||
var parent = GetParent() as Node3D;
|
var parent = GetParent() as Node3D;
|
||||||
var velocity = parent.GlobalPosition.DirectionTo(nextVelocity) * (float)FleeSpeed * (float)delta;
|
var velocity = parent.GlobalPosition.DirectionTo(nextVelocity) * (float)FleeSpeed * (float)delta;
|
||||||
_navigationAgent.Velocity = velocity;
|
_navigationAgent.Velocity = velocity;
|
||||||
//EmitSignal(SignalName.OnVelocityComputed, velocity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
@@ -19,33 +18,33 @@ public partial class Michael : Enemy2D, IHavePatrolBehavior, IHaveEngagePlayerBe
|
|||||||
|
|
||||||
public void OnReady()
|
public void OnReady()
|
||||||
{
|
{
|
||||||
FollowBehavior.Init(NavigationAgent);
|
FollowBehavior.Init(NavigationAgent);
|
||||||
PatrolBehavior.Init(NavigationAgent);
|
PatrolBehavior.Init(NavigationAgent);
|
||||||
PatrolBehavior.HomePosition = GlobalPosition;
|
PatrolBehavior.HomePosition = GlobalPosition;
|
||||||
PatrolBehavior.OnVelocityComputed += OnVelocityComputed;
|
PatrolBehavior.OnVelocityComputed += OnVelocityComputed;
|
||||||
FollowBehavior.OnVelocityComputed += OnVelocityComputed;
|
FollowBehavior.OnVelocityComputed += OnVelocityComputed;
|
||||||
EngagePlayerBehavior.TakeAction += EngagePlayerBehavior_TakeAction;
|
EngagePlayerBehavior.TakeAction += EngagePlayerBehavior_TakeAction;
|
||||||
EngagePlayerBehavior.AcquireTarget += EngagePlayerBehavior_AcquireTarget;
|
EngagePlayerBehavior.AcquireTarget += EngagePlayerBehavior_AcquireTarget;
|
||||||
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
|
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
|
||||||
PlayerDetector.BodyExited += PlayerDetector_BodyExited;
|
PlayerDetector.BodyExited += PlayerDetector_BodyExited;
|
||||||
SetPhysicsProcess(true);
|
SetPhysicsProcess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
{
|
{
|
||||||
_enemyLogic.Input(new EnemyLogic.Input.Patrol());
|
_enemyLogic.Input(new EnemyLogic.Input.Patrol());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Move() => EnemyModelView.PlayIdleAnimation();
|
public override void Move() => EnemyModelView.PlayIdleAnimation();
|
||||||
|
|
||||||
public new void OnExitTree()
|
public new void OnExitTree()
|
||||||
{
|
{
|
||||||
base.OnExitTree();
|
base.OnExitTree();
|
||||||
PatrolBehavior.OnVelocityComputed -= OnVelocityComputed;
|
PatrolBehavior.OnVelocityComputed -= OnVelocityComputed;
|
||||||
FollowBehavior.OnVelocityComputed -= OnVelocityComputed;
|
FollowBehavior.OnVelocityComputed -= OnVelocityComputed;
|
||||||
EngagePlayerBehavior.TakeAction -= EngagePlayerBehavior_TakeAction;
|
EngagePlayerBehavior.TakeAction -= EngagePlayerBehavior_TakeAction;
|
||||||
EngagePlayerBehavior.AcquireTarget -= EngagePlayerBehavior_AcquireTarget;
|
EngagePlayerBehavior.AcquireTarget -= EngagePlayerBehavior_AcquireTarget;
|
||||||
PlayerDetector.BodyEntered -= PlayerDetector_BodyEntered;
|
PlayerDetector.BodyEntered -= PlayerDetector_BodyEntered;
|
||||||
PlayerDetector.BodyExited -= PlayerDetector_BodyExited;
|
PlayerDetector.BodyExited -= PlayerDetector_BodyExited;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,14 +36,13 @@ public partial class FilthEater : Enemy2D, IHavePatrolBehavior, IHaveEngagePlaye
|
|||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
{
|
{
|
||||||
_enemyLogic.Input(new EnemyLogic.Input.Activate());
|
|
||||||
_enemyLogic.Input(new EnemyLogic.Input.Patrol());
|
_enemyLogic.Input(new EnemyLogic.Input.Patrol());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PerformAction()
|
public override void PerformAction()
|
||||||
{
|
{
|
||||||
var enemyPosition = new Vector3(GlobalPosition.X, _player.GlobalPosition.Y, GlobalPosition.Z);
|
var enemyPosition = new Vector3(GlobalPosition.X, _player.GlobalPosition.Y, GlobalPosition.Z);
|
||||||
if (enemyPosition.DistanceTo(_player.GlobalPosition) > 3)
|
if (enemyPosition.DistanceTo(_player.GlobalPosition) > 1)
|
||||||
EnemyModelView.PlaySecondaryAttackAnimation();
|
EnemyModelView.PlaySecondaryAttackAnimation();
|
||||||
else
|
else
|
||||||
EnemyModelView.PlayPrimaryAttackAnimation();
|
EnemyModelView.PlayPrimaryAttackAnimation();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=16 format=3 uid="uid://bl426uws0i86l"]
|
[gd_scene load_steps=18 format=3 uid="uid://bl426uws0i86l"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://cohal8w5ceneg" path="res://src/enemy/enemy_types/03. filth_eater/FilthEater.cs" id="1_p438s"]
|
[ext_resource type="Script" uid="uid://cohal8w5ceneg" path="res://src/enemy/enemy_types/03. filth_eater/FilthEater.cs" id="1_p438s"]
|
||||||
|
[ext_resource type="Script" uid="uid://bei3s7yr6xkc0" path="res://src/enemy/EnemyLootTable.cs" id="3_g602r"]
|
||||||
[ext_resource type="PackedScene" uid="uid://b6sa6ntu4rbrm" path="res://src/enemy/enemy_types/03. filth_eater/FilthEaterModelView.tscn" id="3_rrwed"]
|
[ext_resource type="PackedScene" uid="uid://b6sa6ntu4rbrm" path="res://src/enemy/enemy_types/03. filth_eater/FilthEaterModelView.tscn" id="3_rrwed"]
|
||||||
[ext_resource type="Script" uid="uid://dlsgyx4i1jmp3" path="res://src/enemy/EnemyLoreInfo.cs" id="4_5eid5"]
|
[ext_resource type="Script" uid="uid://dlsgyx4i1jmp3" path="res://src/enemy/EnemyLoreInfo.cs" id="4_5eid5"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cn4fv2gv6raql" path="res://src/enemy/behaviors/PatrolBehavior.tscn" id="5_pvjvo"]
|
[ext_resource type="PackedScene" uid="uid://cn4fv2gv6raql" path="res://src/enemy/behaviors/PatrolBehavior.tscn" id="5_pvjvo"]
|
||||||
@@ -9,18 +10,12 @@
|
|||||||
[ext_resource type="AudioStream" uid="uid://ba8xendacec6" path="res://src/audio/sfx/item_kyuu_layer_2.ogg" id="7_qbmfg"]
|
[ext_resource type="AudioStream" uid="uid://ba8xendacec6" path="res://src/audio/sfx/item_kyuu_layer_2.ogg" id="7_qbmfg"]
|
||||||
[ext_resource type="AudioStream" uid="uid://b7ycb6qvitpmw" path="res://src/audio/sfx/player_HITENEMY_3.ogg" id="8_m7220"]
|
[ext_resource type="AudioStream" uid="uid://b7ycb6qvitpmw" path="res://src/audio/sfx/player_HITENEMY_3.ogg" id="8_m7220"]
|
||||||
[ext_resource type="AudioStream" uid="uid://bf7adfdd857hw" path="res://src/audio/sfx/enemy_morph.ogg" id="9_g602r"]
|
[ext_resource type="AudioStream" uid="uid://bf7adfdd857hw" path="res://src/audio/sfx/enemy_morph.ogg" id="9_g602r"]
|
||||||
[ext_resource type="AudioStream" uid="uid://6r74nka4oh20" path="res://src/audio/sfx/ENEMY_filth_aggro.ogg" id="11_qbmfg"]
|
[ext_resource type="AudioStream" uid="uid://bn6ns3jxkw03b" path="res://src/audio/sfx/ENEMY_SPROING_death.ogg" id="12_m7220"]
|
||||||
|
|
||||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_jbgmx"]
|
[sub_resource type="Resource" id="Resource_06aiy"]
|
||||||
height = 5.0
|
script = ExtResource("3_g602r")
|
||||||
radius = 1.0
|
Items = []
|
||||||
|
metadata/_custom_type_script = "uid://bei3s7yr6xkc0"
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cwfph"]
|
|
||||||
radius = 2.54294
|
|
||||||
height = 5.08589
|
|
||||||
|
|
||||||
[sub_resource type="SphereShape3D" id="SphereShape3D_0y048"]
|
|
||||||
radius = 2.30121
|
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_fv5vf"]
|
[sub_resource type="Resource" id="Resource_fv5vf"]
|
||||||
script = ExtResource("4_5eid5")
|
script = ExtResource("4_5eid5")
|
||||||
@@ -39,9 +34,19 @@ TertiaryAttackName = ""
|
|||||||
TertiaryAttackType = 0
|
TertiaryAttackType = 0
|
||||||
metadata/_custom_type_script = ExtResource("4_5eid5")
|
metadata/_custom_type_script = ExtResource("4_5eid5")
|
||||||
|
|
||||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_qbmfg"]
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_g602r"]
|
||||||
height = 5.81738
|
height = 5.0
|
||||||
radius = 3.91016
|
radius = 1.0
|
||||||
|
|
||||||
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_06aiy"]
|
||||||
|
radius = 2.5
|
||||||
|
height = 6.0
|
||||||
|
|
||||||
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_ygtll"]
|
||||||
|
radius = 4.0
|
||||||
|
|
||||||
|
[sub_resource type="SphereShape3D" id="SphereShape3D_ebx6c"]
|
||||||
|
radius = 0.552847
|
||||||
|
|
||||||
[node name="FilthEater" type="CharacterBody3D" groups=["enemy"]]
|
[node name="FilthEater" type="CharacterBody3D" groups=["enemy"]]
|
||||||
process_mode = 1
|
process_mode = 1
|
||||||
@@ -49,64 +54,71 @@ collision_layer = 10
|
|||||||
collision_mask = 11
|
collision_mask = 11
|
||||||
axis_lock_linear_y = true
|
axis_lock_linear_y = true
|
||||||
axis_lock_angular_x = true
|
axis_lock_angular_x = true
|
||||||
|
axis_lock_angular_z = true
|
||||||
script = ExtResource("1_p438s")
|
script = ExtResource("1_p438s")
|
||||||
|
_lootTable = SubResource("Resource_06aiy")
|
||||||
[node name="LineOfSight" type="Area3D" parent="."]
|
|
||||||
unique_name_in_owner = true
|
|
||||||
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 2.25757, 0)
|
|
||||||
collision_layer = 2
|
|
||||||
collision_mask = 2
|
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="LineOfSight"]
|
|
||||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, -2)
|
|
||||||
shape = SubResource("CylinderShape3D_jbgmx")
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape3D" parent="."]
|
|
||||||
unique_name_in_owner = true
|
|
||||||
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 2.25757, 0)
|
|
||||||
shape = SubResource("CapsuleShape3D_cwfph")
|
|
||||||
|
|
||||||
[node name="Raycast" type="RayCast3D" parent="."]
|
|
||||||
unique_name_in_owner = true
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.31086, 0)
|
|
||||||
target_position = Vector3(0, 0, -5)
|
|
||||||
collision_mask = 3
|
|
||||||
|
|
||||||
[node name="Collision" type="Area3D" parent="."]
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.25757, 0)
|
|
||||||
collision_layer = 2048
|
|
||||||
collision_mask = 0
|
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Collision"]
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.120117, 0.221246, 0)
|
|
||||||
shape = SubResource("SphereShape3D_0y048")
|
|
||||||
|
|
||||||
[node name="EnemyModelView" parent="." instance=ExtResource("3_rrwed")]
|
[node name="EnemyModelView" parent="." instance=ExtResource("3_rrwed")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.114099, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.114099, 0)
|
||||||
EnemyLoreInfo = SubResource("Resource_fv5vf")
|
EnemyLoreInfo = SubResource("Resource_fv5vf")
|
||||||
|
|
||||||
|
[node name="LineOfSight" type="Area3D" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 1.71715, 0)
|
||||||
|
collision_layer = 2
|
||||||
|
collision_mask = 2
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="LineOfSight"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, -2)
|
||||||
|
shape = SubResource("CylinderShape3D_g602r")
|
||||||
|
|
||||||
|
[node name="Raycast" type="RayCast3D" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 1.71715, 0)
|
||||||
|
target_position = Vector3(0, 0, -5)
|
||||||
|
collision_mask = 3
|
||||||
|
debug_shape_custom_color = Color(1, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="CollisionShape" type="CollisionShape3D" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, -0.0824751, 3.16485, 0)
|
||||||
|
shape = SubResource("CapsuleShape3D_06aiy")
|
||||||
|
|
||||||
[node name="PlayerDetector" type="Area3D" parent="."]
|
[node name="PlayerDetector" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.25757, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.71715, 0)
|
||||||
collision_layer = 0
|
collision_layer = 0
|
||||||
collision_mask = 34
|
collision_mask = 34
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="PlayerDetector"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="PlayerDetector"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.2771, 0)
|
shape = SubResource("CylinderShape3D_ygtll")
|
||||||
shape = SubResource("CylinderShape3D_qbmfg")
|
|
||||||
|
[node name="Collision" type="Area3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.71715, 0)
|
||||||
|
collision_layer = 2048
|
||||||
|
collision_mask = 0
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Collision"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.120117, 0.221246, 0)
|
||||||
|
shape = SubResource("SphereShape3D_ebx6c")
|
||||||
|
|
||||||
[node name="Components" type="Node3D" parent="."]
|
[node name="Components" type="Node3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.25757, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.71715, 0)
|
||||||
|
|
||||||
[node name="PatrolBehavior" parent="Components" instance=ExtResource("5_pvjvo")]
|
[node name="PatrolBehavior" parent="Components" instance=ExtResource("5_pvjvo")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
_patrolRange = 15.0
|
||||||
|
_patrolTime = 20.0
|
||||||
|
|
||||||
[node name="FollowBehavior" parent="Components" instance=ExtResource("6_fccr3")]
|
[node name="FollowBehavior" parent="Components" instance=ExtResource("6_fccr3")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
FollowSpeed = 175.0
|
||||||
|
|
||||||
[node name="EngagePlayerBehavior" parent="Components" instance=ExtResource("7_8l567")]
|
[node name="EngagePlayerBehavior" parent="Components" instance=ExtResource("7_8l567")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
_minimumAttackTime = 1.0
|
||||||
|
_maximumAttackTime = 3.0
|
||||||
_acquireTargetTime = 2.0
|
_acquireTargetTime = 2.0
|
||||||
|
|
||||||
[node name="NavigationAgent" type="NavigationAgent3D" parent="Components"]
|
[node name="NavigationAgent" type="NavigationAgent3D" parent="Components"]
|
||||||
@@ -117,7 +129,7 @@ avoidance_layers = 9
|
|||||||
avoidance_mask = 9
|
avoidance_mask = 9
|
||||||
|
|
||||||
[node name="HitSounds" type="Node3D" parent="."]
|
[node name="HitSounds" type="Node3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.25757, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.71715, 0)
|
||||||
|
|
||||||
[node name="AbsorbSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
|
[node name="AbsorbSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
@@ -136,9 +148,9 @@ bus = &"SFX"
|
|||||||
|
|
||||||
[node name="DieSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
|
[node name="DieSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
stream = ExtResource("12_m7220")
|
||||||
bus = &"SFX"
|
bus = &"SFX"
|
||||||
|
|
||||||
[node name="AggroSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
|
[node name="AggroSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
stream = ExtResource("11_qbmfg")
|
|
||||||
bus = &"SFX"
|
bus = &"SFX"
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
[ext_resource type="AudioStream" uid="uid://bf7adfdd857hw" path="res://src/audio/sfx/enemy_morph.ogg" id="8_a4ku4"]
|
[ext_resource type="AudioStream" uid="uid://bf7adfdd857hw" path="res://src/audio/sfx/enemy_morph.ogg" id="8_a4ku4"]
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cwfph"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cwfph"]
|
||||||
radius = 0.226425
|
radius = 1.0
|
||||||
height = 2.02807
|
height = 3.90429
|
||||||
|
|
||||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_jbgmx"]
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_jbgmx"]
|
||||||
height = 5.0
|
height = 5.0
|
||||||
@@ -52,7 +52,7 @@ script = ExtResource("1_120m2")
|
|||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape3D" parent="."]
|
[node name="CollisionShape" type="CollisionShape3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 1.46013, 0)
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 1.92003, 0)
|
||||||
shape = SubResource("CapsuleShape3D_cwfph")
|
shape = SubResource("CapsuleShape3D_cwfph")
|
||||||
|
|
||||||
[node name="LineOfSight" type="Area3D" parent="."]
|
[node name="LineOfSight" type="Area3D" parent="."]
|
||||||
|
|||||||
@@ -6514,7 +6514,7 @@ tracks/15/keys = {
|
|||||||
"times": PackedFloat32Array(0),
|
"times": PackedFloat32Array(0),
|
||||||
"transitions": PackedFloat32Array(1),
|
"transitions": PackedFloat32Array(1),
|
||||||
"update": 1,
|
"update": 1,
|
||||||
"values": [&"WATER DAMAGE"]
|
"values": [&"EARTH DAMAGE"]
|
||||||
}
|
}
|
||||||
tracks/16/type = "value"
|
tracks/16/type = "value"
|
||||||
tracks/16/imported = false
|
tracks/16/imported = false
|
||||||
@@ -6747,7 +6747,7 @@ frame = 47
|
|||||||
position = Vector2(500, 500)
|
position = Vector2(500, 500)
|
||||||
scale = Vector2(4, 4)
|
scale = Vector2(4, 4)
|
||||||
sprite_frames = SubResource("SpriteFrames_8u7he")
|
sprite_frames = SubResource("SpriteFrames_8u7he")
|
||||||
animation = &"WATER DAMAGE"
|
animation = &"EARTH DAMAGE"
|
||||||
|
|
||||||
[node name="Hitbox" type="Area3D" parent="."]
|
[node name="Hitbox" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|||||||
@@ -51,104 +51,101 @@ public partial class EdenPillar : Enemy3D, IHasPrimaryAttack, IHasSecondaryAttac
|
|||||||
|
|
||||||
public void OnReady()
|
public void OnReady()
|
||||||
{
|
{
|
||||||
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
|
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
|
||||||
LoseTrackOfPlayer.BodyExited += LoseTrackOfPlayer_BodyExited;
|
LoseTrackOfPlayer.BodyExited += LoseTrackOfPlayer_BodyExited;
|
||||||
EngagePlayerBehavior.TakeAction += PerformAction;
|
EngagePlayerBehavior.TakeAction += PerformAction;
|
||||||
HealthComponent.HealthReachedZero += HealthComponent_HealthReachedZero;
|
HealthComponent.HealthReachedZero += HealthComponent_HealthReachedZero;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoseTrackOfPlayer_BodyExited(Node3D body) => EngagePlayerBehavior.Disengage();
|
private void LoseTrackOfPlayer_BodyExited(Node3D body) => EngagePlayerBehavior.Disengage();
|
||||||
|
|
||||||
private void HealthComponent_HealthReachedZero()
|
private void HealthComponent_HealthReachedZero()
|
||||||
{
|
{
|
||||||
StoneRotation.Stop();
|
StoneRotation.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlayerDetector_BodyEntered(Node3D body)
|
private void PlayerDetector_BodyEntered(Node3D body)
|
||||||
{
|
{
|
||||||
EngagePlayerBehavior.Engage();
|
EngagePlayerBehavior.Engage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PerformAction()
|
public override void PerformAction()
|
||||||
{
|
{
|
||||||
var rng = new RandomNumberGenerator();
|
var rng = new RandomNumberGenerator();
|
||||||
var options = new List<Action>() { PrimaryAttack, SecondaryAttack, TertiaryAttack };
|
var options = new List<Action>() { PrimaryAttack, SecondaryAttack, TertiaryAttack };
|
||||||
var selection = rng.RandWeighted([1, 1, 1]);
|
var selection = rng.RandWeighted([1, 1, 1]);
|
||||||
options[(int)selection].Invoke();
|
options[(int)selection].Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrimaryAttack()
|
public void PrimaryAttack()
|
||||||
{
|
{
|
||||||
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_primaryAngle));
|
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_primaryAngle));
|
||||||
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
|
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
|
||||||
StoneRotation.Play();
|
StoneRotation.Play();
|
||||||
var tweener = GetTree().CreateTween();
|
var tweener = GetTree().CreateTween();
|
||||||
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
|
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
|
||||||
tweener.TweenCallback(Callable.From(FirePrimaryShot));
|
tweener.TweenCallback(Callable.From(FirePrimaryShot));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SecondaryAttack()
|
public void SecondaryAttack()
|
||||||
{
|
{
|
||||||
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_secondaryAngle));
|
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_secondaryAngle));
|
||||||
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
|
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
|
||||||
StoneRotation.Play();
|
StoneRotation.Play();
|
||||||
var tweener = GetTree().CreateTween();
|
var tweener = GetTree().CreateTween();
|
||||||
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
|
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
|
||||||
tweener.TweenCallback(Callable.From(FireSecondaryShot));
|
tweener.TweenCallback(Callable.From(FireSecondaryShot));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TertiaryAttack()
|
public void TertiaryAttack()
|
||||||
{
|
{
|
||||||
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_tertiaryAngle));
|
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_tertiaryAngle));
|
||||||
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
|
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
|
||||||
StoneRotation.Play();
|
StoneRotation.Play();
|
||||||
var tweener = GetTree().CreateTween();
|
var tweener = GetTree().CreateTween();
|
||||||
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
|
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
|
||||||
tweener.TweenCallback(Callable.From(FireTertiaryShot));
|
tweener.TweenCallback(Callable.From(FireTertiaryShot));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FirePrimaryShot()
|
private void FirePrimaryShot()
|
||||||
{
|
{
|
||||||
if (HealthComponent.CurrentHP.Value <= 0)
|
if (HealthComponent.CurrentHP.Value <= 0)
|
||||||
return;
|
return;
|
||||||
StoneRotation.Stop();
|
StoneRotation.Stop();
|
||||||
FireSFX.Play();
|
FireSFX.Play();
|
||||||
GD.Print("Fire primary shot");
|
FireProjectile.Fire();
|
||||||
FireProjectile.Fire();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FireSecondaryShot()
|
private void FireSecondaryShot()
|
||||||
{
|
{
|
||||||
if (HealthComponent.CurrentHP.Value <= 0)
|
if (HealthComponent.CurrentHP.Value <= 0)
|
||||||
return;
|
return;
|
||||||
StoneRotation.Stop();
|
StoneRotation.Stop();
|
||||||
FireSFX.Play();
|
FireSFX.Play();
|
||||||
GD.Print("Fire secondary shot");
|
AirProjectile.Fire();
|
||||||
AirProjectile.Fire();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FireTertiaryShot()
|
private void FireTertiaryShot()
|
||||||
{
|
{
|
||||||
if (HealthComponent.CurrentHP.Value <= 0)
|
if (HealthComponent.CurrentHP.Value <= 0)
|
||||||
return;
|
return;
|
||||||
StoneRotation.Stop();
|
StoneRotation.Stop();
|
||||||
FireSFX.Play();
|
FireSFX.Play();
|
||||||
GD.Print("Fire tertiary shot");
|
WaterProjectile.Fire();
|
||||||
WaterProjectile.Fire();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float GetRotationAngle(float angleOffsetInRadians)
|
private float GetRotationAngle(float angleOffsetInRadians)
|
||||||
{
|
{
|
||||||
var target = new Vector3(_player.GlobalPosition.X, Position.Y, _player.GlobalPosition.Z);
|
var target = new Vector3(_player.GlobalPosition.X, Position.Y, _player.GlobalPosition.Z);
|
||||||
_rotation.LookAt(target, Vector3.Up, true);
|
_rotation.LookAt(target, Vector3.Up, true);
|
||||||
_rotation.RotateY(Rotation.Y + angleOffsetInRadians);
|
_rotation.RotateY(Rotation.Y + angleOffsetInRadians);
|
||||||
return _rotation.Rotation.Y;
|
return _rotation.Rotation.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RotateTowardsPlayer(float angle)
|
private void RotateTowardsPlayer(float angle)
|
||||||
{
|
{
|
||||||
if (HealthComponent.CurrentHP.Value <= 0)
|
if (HealthComponent.CurrentHP.Value <= 0)
|
||||||
return;
|
return;
|
||||||
Rotation = new Vector3(Rotation.X, angle, Rotation.Z);
|
Rotation = new Vector3(Rotation.X, angle, Rotation.Z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
|
using Godot;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
using Zennysoft.Ma.Adapter.Entity;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
@@ -16,7 +17,10 @@ public partial class EnemyLogic
|
|||||||
{
|
{
|
||||||
var enemy = Get<IEnemy>();
|
var enemy = Get<IEnemy>();
|
||||||
if (enemy is IHaveEngagePlayerBehavior engagePlayerEnemy)
|
if (enemy is IHaveEngagePlayerBehavior engagePlayerEnemy)
|
||||||
|
{
|
||||||
|
GD.PrintRich($"[color=red]{(enemy as Enemy).EnemyModelView.EnemyLoreInfo.Name}[/color] is engaging the player.");
|
||||||
engagePlayerEnemy.EngagePlayerBehavior.Engage();
|
engagePlayerEnemy.EngagePlayerBehavior.Engage();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
OnDetach(() =>
|
OnDetach(() =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
|
using Godot;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
using Zennysoft.Ma.Adapter.Entity;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
@@ -17,6 +18,7 @@ public partial class EnemyLogic
|
|||||||
var enemy = Get<IEnemy>();
|
var enemy = Get<IEnemy>();
|
||||||
if (enemy is IHaveFollowBehavior followEnemy)
|
if (enemy is IHaveFollowBehavior followEnemy)
|
||||||
{
|
{
|
||||||
|
GD.PrintRich($"[color=red]{(enemy as Enemy).EnemyModelView.EnemyLoreInfo.Name}[/color] is following the player.");
|
||||||
followEnemy.FollowBehavior.StartFollow(followEnemy.NavigationAgent);
|
followEnemy.FollowBehavior.StartFollow(followEnemy.NavigationAgent);
|
||||||
Output(new Output.Move());
|
Output(new Output.Move());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
|
using Godot;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
using Zennysoft.Ma.Adapter.Entity;
|
||||||
using static Zennysoft.Game.Ma.EnemyLogic.Input;
|
using static Zennysoft.Game.Ma.EnemyLogic.Input;
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ public partial class EnemyLogic
|
|||||||
var enemy = Get<IEnemy>();
|
var enemy = Get<IEnemy>();
|
||||||
if (enemy is IHavePatrolBehavior patrolEnemy)
|
if (enemy is IHavePatrolBehavior patrolEnemy)
|
||||||
{
|
{
|
||||||
|
GD.PrintRich($"[color=red]{(enemy as Enemy).EnemyModelView.EnemyLoreInfo.Name}[/color] is patrolling.");
|
||||||
patrolEnemy.PatrolBehavior.StartPatrol();
|
patrolEnemy.PatrolBehavior.StartPatrol();
|
||||||
Output(new Output.Move());
|
Output(new Output.Move());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ public class ItemDatabase
|
|||||||
|
|
||||||
var weights = validItems.Select(x => x.SpawnRate).ToArray();
|
var weights = validItems.Select(x => x.SpawnRate).ToArray();
|
||||||
var index = rng.RandWeighted(weights);
|
var index = rng.RandWeighted(weights);
|
||||||
GD.Print($"Item Spawn Index: {index}, Array Size: {validItems.Length}");
|
|
||||||
var selectedItem = validItems[index];
|
var selectedItem = validItems[index];
|
||||||
return selectedItem;
|
return selectedItem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Chickensoft.Introspection;
|
|||||||
using Godot;
|
using Godot;
|
||||||
using Godot.Collections;
|
using Godot.Collections;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
@@ -41,6 +42,8 @@ public partial class Map : Node3D, IMap
|
|||||||
|
|
||||||
private string _floorToLoad;
|
private string _floorToLoad;
|
||||||
|
|
||||||
|
private Stopwatch _elapsedTime;
|
||||||
|
|
||||||
public override void _EnterTree()
|
public override void _EnterTree()
|
||||||
{
|
{
|
||||||
FloorRoute = [.. BaseRoute];
|
FloorRoute = [.. BaseRoute];
|
||||||
@@ -73,7 +76,8 @@ public partial class Map : Node3D, IMap
|
|||||||
|
|
||||||
public async Task LoadFloor(FloorScene floorToLoad)
|
public async Task LoadFloor(FloorScene floorToLoad)
|
||||||
{
|
{
|
||||||
GD.Print($"Pause for load at {DateTime.Now.Minute}:{DateTime.Now.Second}:{DateTime.Now.Millisecond}");
|
_elapsedTime = new Stopwatch();
|
||||||
|
_elapsedTime.Start();
|
||||||
Game.Pause();
|
Game.Pause();
|
||||||
// Clean up current floor
|
// Clean up current floor
|
||||||
CleanupCurrentFloor();
|
CleanupCurrentFloor();
|
||||||
@@ -85,7 +89,6 @@ public partial class Map : Node3D, IMap
|
|||||||
|
|
||||||
public async Task LoadFloorByPath(string filePath)
|
public async Task LoadFloorByPath(string filePath)
|
||||||
{
|
{
|
||||||
GD.Print($"Pause for load at {DateTime.Now.Minute}:{DateTime.Now.Second}:{DateTime.Now.Millisecond}");
|
|
||||||
Game.Pause();
|
Game.Pause();
|
||||||
// Clean up current floor
|
// Clean up current floor
|
||||||
CleanupCurrentFloor();
|
CleanupCurrentFloor();
|
||||||
@@ -119,14 +122,12 @@ public partial class Map : Node3D, IMap
|
|||||||
{
|
{
|
||||||
SpawnPointCreated?.Invoke((Vector3.Forward, new Vector3(-999, -999, -999)));
|
SpawnPointCreated?.Invoke((Vector3.Forward, new Vector3(-999, -999, -999)));
|
||||||
var newFloor = await LoadSceneFile(filePath);
|
var newFloor = await LoadSceneFile(filePath);
|
||||||
GD.Print($"Floor finished load at {DateTime.Now.Minute}:{DateTime.Now.Second}:{DateTime.Now.Millisecond}");
|
|
||||||
|
|
||||||
// New floor created, remove old floor
|
// New floor created, remove old floor
|
||||||
ClearFloor();
|
ClearFloor();
|
||||||
|
|
||||||
// Setup new floor
|
// Setup new floor
|
||||||
AddChild(newFloor);
|
AddChild(newFloor);
|
||||||
GD.Print($"Floor added at {DateTime.Now.Minute:D2}:{DateTime.Now.Second:D2}:{DateTime.Now.Millisecond}");
|
|
||||||
CurrentFloor = newFloor as IDungeonFloor;
|
CurrentFloor = newFloor as IDungeonFloor;
|
||||||
CurrentFloor.InitializeDungeon();
|
CurrentFloor.InitializeDungeon();
|
||||||
SpawnPointCreated?.Invoke(CurrentFloor.GetPlayerSpawnPoint());
|
SpawnPointCreated?.Invoke(CurrentFloor.GetPlayerSpawnPoint());
|
||||||
@@ -138,7 +139,8 @@ public partial class Map : Node3D, IMap
|
|||||||
SpawnItems();
|
SpawnItems();
|
||||||
CurrentFloor.FloorIsLoaded = true;
|
CurrentFloor.FloorIsLoaded = true;
|
||||||
FloorLoaded?.Invoke();
|
FloorLoaded?.Invoke();
|
||||||
GD.Print($"Floor loaded invoked {DateTime.Now.Minute}:{DateTime.Now.Second}:{DateTime.Now.Millisecond}");
|
_elapsedTime.Stop();
|
||||||
|
GD.Print($"Floor loaded in {_elapsedTime.ElapsedMilliseconds}ms.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CleanupCurrentFloor()
|
private void CleanupCurrentFloor()
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public partial class MonsterRoom : DungeonRoom
|
|||||||
|
|
||||||
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
|
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
|
||||||
|
|
||||||
|
private string _color = "white";
|
||||||
|
|
||||||
public void SpawnEnemies(Array<EnemySpawnRate> spawnTable)
|
public void SpawnEnemies(Array<EnemySpawnRate> spawnTable)
|
||||||
{
|
{
|
||||||
if (spawnTable.Count == 0)
|
if (spawnTable.Count == 0)
|
||||||
@@ -42,6 +44,7 @@ public partial class MonsterRoom : DungeonRoom
|
|||||||
AddChild(instantiatedEnemy);
|
AddChild(instantiatedEnemy);
|
||||||
instantiatedEnemy.GlobalPosition = new Vector3(spawnPoint.GlobalPosition.X, 0f, spawnPoint.GlobalPosition.Z);
|
instantiatedEnemy.GlobalPosition = new Vector3(spawnPoint.GlobalPosition.X, 0f, spawnPoint.GlobalPosition.Z);
|
||||||
ResetPhysicsInterpolation();
|
ResetPhysicsInterpolation();
|
||||||
|
GD.PrintRich($"Spawned [color=red]{selectedEnemy.EnemyType}[/color] at {instantiatedEnemy.GlobalPosition}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,22 +70,34 @@ public partial class MonsterRoom : DungeonRoom
|
|||||||
var rarity = RarityTag.Common;
|
var rarity = RarityTag.Common;
|
||||||
var rarityGroup = rng.Randf();
|
var rarityGroup = rng.Randf();
|
||||||
if (rarityGroup < 0.5f)
|
if (rarityGroup < 0.5f)
|
||||||
|
{
|
||||||
rarity = RarityTag.Common;
|
rarity = RarityTag.Common;
|
||||||
|
_color = "white";
|
||||||
|
}
|
||||||
else if (rarityGroup < 0.85f)
|
else if (rarityGroup < 0.85f)
|
||||||
|
{
|
||||||
rarity = RarityTag.Uncommon;
|
rarity = RarityTag.Uncommon;
|
||||||
|
_color = "green";
|
||||||
|
}
|
||||||
else if (rarityGroup < 0.99f)
|
else if (rarityGroup < 0.99f)
|
||||||
|
{
|
||||||
rarity = RarityTag.Rare;
|
rarity = RarityTag.Rare;
|
||||||
|
_color = "cyan";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
rarity = RarityTag.Legendary;
|
rarity = RarityTag.Legendary;
|
||||||
|
_color = "gold";
|
||||||
|
}
|
||||||
|
|
||||||
spawnableItems = [.. spawnableItems.Where(x => x.RarityTag == rarity)];
|
spawnableItems = [.. spawnableItems.Where(x => x.RarityTag == rarity)];
|
||||||
if (spawnableItems.Count() == 0)
|
if (spawnableItems.Count() == 0)
|
||||||
break;
|
break;
|
||||||
var selectedItem = database.PickItemFromList(spawnableItems) as Node3D;
|
var selectedItem = database.PickItemFromList(spawnableItems) as Node3D;
|
||||||
GD.Print($"Item spawned: {(selectedItem as IBaseInventoryItem).ItemName}");
|
|
||||||
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
|
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
|
||||||
AddChild(duplicated);
|
AddChild(duplicated);
|
||||||
duplicated.Position = new Vector3(spawnPoint.Position.X, 0, spawnPoint.Position.Z);
|
duplicated.Position = new Vector3(spawnPoint.Position.X, 0, spawnPoint.Position.Z);
|
||||||
|
GD.PrintRich($"Item spawned: [b]{(selectedItem as IBaseInventoryItem).ItemName}[/b] at {duplicated.GlobalPosition}. Rolled a {rarityGroup} for a [color={_color}]{rarity}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,3 +263,5 @@ lifetime = 41.19
|
|||||||
local_coords = true
|
local_coords = true
|
||||||
process_material = SubResource("ParticleProcessMaterial_kdgfu")
|
process_material = SubResource("ParticleProcessMaterial_kdgfu")
|
||||||
draw_pass_1 = SubResource("QuadMesh_ec0oy")
|
draw_pass_1 = SubResource("QuadMesh_ec0oy")
|
||||||
|
|
||||||
|
[editable path="Model/A2-Deadend"]
|
||||||
|
|||||||
Reference in New Issue
Block a user