Additional collision/avoidance changes for monstos

This commit is contained in:
2026-06-13 21:42:42 -07:00
parent 7b2483ee74
commit 6620c86f57
14 changed files with 170 additions and 138 deletions
@@ -55,6 +55,5 @@ public partial class FleeBehavior : Node3D, IBehavior
var parent = GetParent() as Node3D;
var velocity = parent.GlobalPosition.DirectionTo(nextVelocity) * (float)FleeSpeed * (float)delta;
_navigationAgent.Velocity = velocity;
//EmitSignal(SignalName.OnVelocityComputed, velocity);
}
}
@@ -1,7 +1,6 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System.Linq;
namespace Zennysoft.Game.Ma;
@@ -19,33 +18,33 @@ public partial class Michael : Enemy2D, IHavePatrolBehavior, IHaveEngagePlayerBe
public void OnReady()
{
FollowBehavior.Init(NavigationAgent);
PatrolBehavior.Init(NavigationAgent);
PatrolBehavior.HomePosition = GlobalPosition;
PatrolBehavior.OnVelocityComputed += OnVelocityComputed;
FollowBehavior.OnVelocityComputed += OnVelocityComputed;
EngagePlayerBehavior.TakeAction += EngagePlayerBehavior_TakeAction;
EngagePlayerBehavior.AcquireTarget += EngagePlayerBehavior_AcquireTarget;
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
PlayerDetector.BodyExited += PlayerDetector_BodyExited;
SetPhysicsProcess(true);
FollowBehavior.Init(NavigationAgent);
PatrolBehavior.Init(NavigationAgent);
PatrolBehavior.HomePosition = GlobalPosition;
PatrolBehavior.OnVelocityComputed += OnVelocityComputed;
FollowBehavior.OnVelocityComputed += OnVelocityComputed;
EngagePlayerBehavior.TakeAction += EngagePlayerBehavior_TakeAction;
EngagePlayerBehavior.AcquireTarget += EngagePlayerBehavior_AcquireTarget;
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
PlayerDetector.BodyExited += PlayerDetector_BodyExited;
SetPhysicsProcess(true);
}
public void OnResolved()
{
_enemyLogic.Input(new EnemyLogic.Input.Patrol());
_enemyLogic.Input(new EnemyLogic.Input.Patrol());
}
public override void Move() => EnemyModelView.PlayIdleAnimation();
public new void OnExitTree()
{
base.OnExitTree();
PatrolBehavior.OnVelocityComputed -= OnVelocityComputed;
FollowBehavior.OnVelocityComputed -= OnVelocityComputed;
EngagePlayerBehavior.TakeAction -= EngagePlayerBehavior_TakeAction;
EngagePlayerBehavior.AcquireTarget -= EngagePlayerBehavior_AcquireTarget;
PlayerDetector.BodyEntered -= PlayerDetector_BodyEntered;
PlayerDetector.BodyExited -= PlayerDetector_BodyExited;
base.OnExitTree();
PatrolBehavior.OnVelocityComputed -= OnVelocityComputed;
FollowBehavior.OnVelocityComputed -= OnVelocityComputed;
EngagePlayerBehavior.TakeAction -= EngagePlayerBehavior_TakeAction;
EngagePlayerBehavior.AcquireTarget -= EngagePlayerBehavior_AcquireTarget;
PlayerDetector.BodyEntered -= PlayerDetector_BodyEntered;
PlayerDetector.BodyExited -= PlayerDetector_BodyExited;
}
}
@@ -36,14 +36,13 @@ public partial class FilthEater : Enemy2D, IHavePatrolBehavior, IHaveEngagePlaye
public void OnResolved()
{
_enemyLogic.Input(new EnemyLogic.Input.Activate());
_enemyLogic.Input(new EnemyLogic.Input.Patrol());
}
public override void PerformAction()
{
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();
else
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://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="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"]
@@ -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://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://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"]
height = 5.0
radius = 1.0
[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_06aiy"]
script = ExtResource("3_g602r")
Items = []
metadata/_custom_type_script = "uid://bei3s7yr6xkc0"
[sub_resource type="Resource" id="Resource_fv5vf"]
script = ExtResource("4_5eid5")
@@ -39,9 +34,19 @@ TertiaryAttackName = ""
TertiaryAttackType = 0
metadata/_custom_type_script = ExtResource("4_5eid5")
[sub_resource type="CylinderShape3D" id="CylinderShape3D_qbmfg"]
height = 5.81738
radius = 3.91016
[sub_resource type="CylinderShape3D" id="CylinderShape3D_g602r"]
height = 5.0
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"]]
process_mode = 1
@@ -49,64 +54,71 @@ collision_layer = 10
collision_mask = 11
axis_lock_linear_y = true
axis_lock_angular_x = true
axis_lock_angular_z = true
script = ExtResource("1_p438s")
[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")
_lootTable = SubResource("Resource_06aiy")
[node name="EnemyModelView" parent="." instance=ExtResource("3_rrwed")]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.114099, 0)
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="."]
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_mask = 34
[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_qbmfg")
shape = SubResource("CylinderShape3D_ygtll")
[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="."]
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")]
unique_name_in_owner = true
_patrolRange = 15.0
_patrolTime = 20.0
[node name="FollowBehavior" parent="Components" instance=ExtResource("6_fccr3")]
unique_name_in_owner = true
FollowSpeed = 175.0
[node name="EngagePlayerBehavior" parent="Components" instance=ExtResource("7_8l567")]
unique_name_in_owner = true
_minimumAttackTime = 1.0
_maximumAttackTime = 3.0
_acquireTargetTime = 2.0
[node name="NavigationAgent" type="NavigationAgent3D" parent="Components"]
@@ -117,7 +129,7 @@ avoidance_layers = 9
avoidance_mask = 9
[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"]
unique_name_in_owner = true
@@ -136,9 +148,9 @@ bus = &"SFX"
[node name="DieSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("12_m7220")
bus = &"SFX"
[node name="AggroSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("11_qbmfg")
bus = &"SFX"
@@ -10,8 +10,8 @@
[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"]
radius = 0.226425
height = 2.02807
radius = 1.0
height = 3.90429
[sub_resource type="CylinderShape3D" id="CylinderShape3D_jbgmx"]
height = 5.0
@@ -52,7 +52,7 @@ script = ExtResource("1_120m2")
[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, 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")
[node name="LineOfSight" type="Area3D" parent="."]
@@ -6514,7 +6514,7 @@ tracks/15/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [&"WATER DAMAGE"]
"values": [&"EARTH DAMAGE"]
}
tracks/16/type = "value"
tracks/16/imported = false
@@ -6747,7 +6747,7 @@ frame = 47
position = Vector2(500, 500)
scale = Vector2(4, 4)
sprite_frames = SubResource("SpriteFrames_8u7he")
animation = &"WATER DAMAGE"
animation = &"EARTH DAMAGE"
[node name="Hitbox" type="Area3D" parent="."]
unique_name_in_owner = true
@@ -51,104 +51,101 @@ public partial class EdenPillar : Enemy3D, IHasPrimaryAttack, IHasSecondaryAttac
public void OnReady()
{
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
LoseTrackOfPlayer.BodyExited += LoseTrackOfPlayer_BodyExited;
EngagePlayerBehavior.TakeAction += PerformAction;
HealthComponent.HealthReachedZero += HealthComponent_HealthReachedZero;
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
LoseTrackOfPlayer.BodyExited += LoseTrackOfPlayer_BodyExited;
EngagePlayerBehavior.TakeAction += PerformAction;
HealthComponent.HealthReachedZero += HealthComponent_HealthReachedZero;
}
private void LoseTrackOfPlayer_BodyExited(Node3D body) => EngagePlayerBehavior.Disengage();
private void HealthComponent_HealthReachedZero()
{
StoneRotation.Stop();
StoneRotation.Stop();
}
private void PlayerDetector_BodyEntered(Node3D body)
{
EngagePlayerBehavior.Engage();
EngagePlayerBehavior.Engage();
}
public override void PerformAction()
{
var rng = new RandomNumberGenerator();
var options = new List<Action>() { PrimaryAttack, SecondaryAttack, TertiaryAttack };
var selection = rng.RandWeighted([1, 1, 1]);
options[(int)selection].Invoke();
var rng = new RandomNumberGenerator();
var options = new List<Action>() { PrimaryAttack, SecondaryAttack, TertiaryAttack };
var selection = rng.RandWeighted([1, 1, 1]);
options[(int)selection].Invoke();
}
public void PrimaryAttack()
{
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_primaryAngle));
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
StoneRotation.Play();
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
tweener.TweenCallback(Callable.From(FirePrimaryShot));
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_primaryAngle));
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
StoneRotation.Play();
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
tweener.TweenCallback(Callable.From(FirePrimaryShot));
}
public void SecondaryAttack()
{
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_secondaryAngle));
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
StoneRotation.Play();
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
tweener.TweenCallback(Callable.From(FireSecondaryShot));
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_secondaryAngle));
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
StoneRotation.Play();
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
tweener.TweenCallback(Callable.From(FireSecondaryShot));
}
public void TertiaryAttack()
{
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_tertiaryAngle));
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
StoneRotation.Play();
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
tweener.TweenCallback(Callable.From(FireTertiaryShot));
var rotationAngle = GetRotationAngle(Mathf.DegToRad(_tertiaryAngle));
if (!StoneRotation.Playing && !Mathf.IsEqualApprox(Rotation.Y, rotationAngle))
StoneRotation.Play();
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Rotation.Y, rotationAngle, 5f);
tweener.TweenCallback(Callable.From(FireTertiaryShot));
}
private void FirePrimaryShot()
{
if (HealthComponent.CurrentHP.Value <= 0)
return;
StoneRotation.Stop();
FireSFX.Play();
GD.Print("Fire primary shot");
FireProjectile.Fire();
if (HealthComponent.CurrentHP.Value <= 0)
return;
StoneRotation.Stop();
FireSFX.Play();
FireProjectile.Fire();
}
private void FireSecondaryShot()
{
if (HealthComponent.CurrentHP.Value <= 0)
return;
StoneRotation.Stop();
FireSFX.Play();
GD.Print("Fire secondary shot");
AirProjectile.Fire();
if (HealthComponent.CurrentHP.Value <= 0)
return;
StoneRotation.Stop();
FireSFX.Play();
AirProjectile.Fire();
}
private void FireTertiaryShot()
{
if (HealthComponent.CurrentHP.Value <= 0)
return;
StoneRotation.Stop();
FireSFX.Play();
GD.Print("Fire tertiary shot");
WaterProjectile.Fire();
if (HealthComponent.CurrentHP.Value <= 0)
return;
StoneRotation.Stop();
FireSFX.Play();
WaterProjectile.Fire();
}
private float GetRotationAngle(float angleOffsetInRadians)
{
var target = new Vector3(_player.GlobalPosition.X, Position.Y, _player.GlobalPosition.Z);
_rotation.LookAt(target, Vector3.Up, true);
_rotation.RotateY(Rotation.Y + angleOffsetInRadians);
return _rotation.Rotation.Y;
var target = new Vector3(_player.GlobalPosition.X, Position.Y, _player.GlobalPosition.Z);
_rotation.LookAt(target, Vector3.Up, true);
_rotation.RotateY(Rotation.Y + angleOffsetInRadians);
return _rotation.Rotation.Y;
}
private void RotateTowardsPlayer(float angle)
{
if (HealthComponent.CurrentHP.Value <= 0)
return;
Rotation = new Vector3(Rotation.X, angle, Rotation.Z);
if (HealthComponent.CurrentHP.Value <= 0)
return;
Rotation = new Vector3(Rotation.X, angle, Rotation.Z);
}
}
@@ -1,4 +1,5 @@
using Chickensoft.Introspection;
using Godot;
using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Game.Ma;
@@ -16,7 +17,10 @@ public partial class EnemyLogic
{
var enemy = Get<IEnemy>();
if (enemy is IHaveEngagePlayerBehavior engagePlayerEnemy)
{
GD.PrintRich($"[color=red]{(enemy as Enemy).EnemyModelView.EnemyLoreInfo.Name}[/color] is engaging the player.");
engagePlayerEnemy.EngagePlayerBehavior.Engage();
}
});
OnDetach(() =>
{
@@ -1,4 +1,5 @@
using Chickensoft.Introspection;
using Godot;
using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Game.Ma;
@@ -17,6 +18,7 @@ public partial class EnemyLogic
var enemy = Get<IEnemy>();
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);
Output(new Output.Move());
}
@@ -1,4 +1,5 @@
using Chickensoft.Introspection;
using Godot;
using Zennysoft.Ma.Adapter.Entity;
using static Zennysoft.Game.Ma.EnemyLogic.Input;
@@ -18,6 +19,7 @@ public partial class EnemyLogic
var enemy = Get<IEnemy>();
if (enemy is IHavePatrolBehavior patrolEnemy)
{
GD.PrintRich($"[color=red]{(enemy as Enemy).EnemyModelView.EnemyLoreInfo.Name}[/color] is patrolling.");
patrolEnemy.PatrolBehavior.StartPatrol();
Output(new Output.Move());
}
@@ -55,7 +55,6 @@ public class ItemDatabase
var weights = validItems.Select(x => x.SpawnRate).ToArray();
var index = rng.RandWeighted(weights);
GD.Print($"Item Spawn Index: {index}, Array Size: {validItems.Length}");
var selectedItem = validItems[index];
return selectedItem;
}
+7 -5
View File
@@ -4,6 +4,7 @@ using Chickensoft.Introspection;
using Godot;
using Godot.Collections;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Zennysoft.Game.Abstractions;
@@ -41,6 +42,8 @@ public partial class Map : Node3D, IMap
private string _floorToLoad;
private Stopwatch _elapsedTime;
public override void _EnterTree()
{
FloorRoute = [.. BaseRoute];
@@ -73,7 +76,8 @@ public partial class Map : Node3D, IMap
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();
// Clean up current floor
CleanupCurrentFloor();
@@ -85,7 +89,6 @@ public partial class Map : Node3D, IMap
public async Task LoadFloorByPath(string filePath)
{
GD.Print($"Pause for load at {DateTime.Now.Minute}:{DateTime.Now.Second}:{DateTime.Now.Millisecond}");
Game.Pause();
// Clean up current floor
CleanupCurrentFloor();
@@ -119,14 +122,12 @@ public partial class Map : Node3D, IMap
{
SpawnPointCreated?.Invoke((Vector3.Forward, new Vector3(-999, -999, -999)));
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
ClearFloor();
// Setup new floor
AddChild(newFloor);
GD.Print($"Floor added at {DateTime.Now.Minute:D2}:{DateTime.Now.Second:D2}:{DateTime.Now.Millisecond}");
CurrentFloor = newFloor as IDungeonFloor;
CurrentFloor.InitializeDungeon();
SpawnPointCreated?.Invoke(CurrentFloor.GetPlayerSpawnPoint());
@@ -138,7 +139,8 @@ public partial class Map : Node3D, IMap
SpawnItems();
CurrentFloor.FloorIsLoaded = true;
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()
@@ -20,6 +20,8 @@ public partial class MonsterRoom : DungeonRoom
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
private string _color = "white";
public void SpawnEnemies(Array<EnemySpawnRate> spawnTable)
{
if (spawnTable.Count == 0)
@@ -42,6 +44,7 @@ public partial class MonsterRoom : DungeonRoom
AddChild(instantiatedEnemy);
instantiatedEnemy.GlobalPosition = new Vector3(spawnPoint.GlobalPosition.X, 0f, spawnPoint.GlobalPosition.Z);
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 rarityGroup = rng.Randf();
if (rarityGroup < 0.5f)
{
rarity = RarityTag.Common;
_color = "white";
}
else if (rarityGroup < 0.85f)
{
rarity = RarityTag.Uncommon;
_color = "green";
}
else if (rarityGroup < 0.99f)
{
rarity = RarityTag.Rare;
_color = "cyan";
}
else
{
rarity = RarityTag.Legendary;
_color = "gold";
}
spawnableItems = [.. spawnableItems.Where(x => x.RarityTag == rarity)];
if (spawnableItems.Count() == 0)
break;
var selectedItem = database.PickItemFromList(spawnableItems) as Node3D;
GD.Print($"Item spawned: {(selectedItem as IBaseInventoryItem).ItemName}");
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
AddChild(duplicated);
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
process_material = SubResource("ParticleProcessMaterial_kdgfu")
draw_pass_1 = SubResource("QuadMesh_ec0oy")
[editable path="Model/A2-Deadend"]