it's michael, what's michael
This commit is contained in:
@@ -2,10 +2,7 @@ using Chickensoft.AutoInject;
|
||||
using Chickensoft.Collections;
|
||||
using Chickensoft.GodotNodeInterfaces;
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
|
||||
@@ -21,8 +18,6 @@ public interface IEnemy : ICharacterBody3D
|
||||
|
||||
public Area3D LineOfSight { get; set; }
|
||||
|
||||
public AnimationPlayer AnimationPlayer { get; set; }
|
||||
|
||||
public Timer AttackTimer { get; set; }
|
||||
}
|
||||
|
||||
@@ -56,10 +51,16 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
[Node] public Timer AttackTimer { get; set; } = default!;
|
||||
|
||||
[Node] public AnimationPlayer AnimationPlayer { get; set; } = default!;
|
||||
[Node] public AnimatedSprite3D AnimatedSprite { get; set; } = default!;
|
||||
|
||||
[Node] public RayCast3D Raycast { get; set; } = default!;
|
||||
|
||||
private const string IDLE_FORWARD = "idle_front_walk";
|
||||
private const string IDLE_LEFT = "idle_left_walk";
|
||||
private const string IDLE_BACK = "idle_back_walk";
|
||||
|
||||
private const string ATTACK_FORWARD = "attack";
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
EnemyLogic = new EnemyLogic();
|
||||
@@ -68,18 +69,6 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
EnemyLogic.Set(GameRepo);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
CurrentHP = new AutoProp<double>(EnemyStatResource.MaximumHP);
|
||||
CurrentHP.Sync += OnHPChanged;
|
||||
LineOfSight.BodyEntered += LineOfSight_BodyEntered;
|
||||
PatrolTimer.Timeout += OnPatrolTimeout;
|
||||
AttackTimer.Timeout += OnAttackTimeout;
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
PatrolTimer.WaitTime = rng.RandfRange(7.0f, 15.0f);
|
||||
}
|
||||
|
||||
private void OnPatrolTimeout()
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
@@ -103,20 +92,20 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
private void LineOfSight_BodyEntered(Node3D body)
|
||||
{
|
||||
var overlappingBodies = LineOfSight.GetOverlappingBodies();
|
||||
foreach (var overlap in overlappingBodies)
|
||||
{
|
||||
Raycast.LookAt(GameRepo.PlayerGlobalPosition.Value, Vector3.Up);
|
||||
Raycast.ForceRaycastUpdate();
|
||||
if (Raycast.IsColliding())
|
||||
{
|
||||
var collider = Raycast.GetCollider();
|
||||
if (collider is IPlayer player)
|
||||
{
|
||||
Raycast.DebugShapeCustomColor = Color.FromString("Purple", Colors.Purple);
|
||||
EnemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
}
|
||||
}
|
||||
}
|
||||
//foreach (var overlap in overlappingBodies)
|
||||
//{
|
||||
// Raycast.LookAt(GameRepo.PlayerGlobalPosition.Value, Vector3.Up);
|
||||
// Raycast.ForceRaycastUpdate();
|
||||
// if (Raycast.IsColliding())
|
||||
// {
|
||||
// var collider = Raycast.GetCollider();
|
||||
// if (collider is IPlayer player)
|
||||
// {
|
||||
// Raycast.DebugShapeCustomColor = Color.FromString("Purple", Colors.Purple);
|
||||
// EnemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
@@ -126,12 +115,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
EnemyBinding
|
||||
.Handle((in EnemyLogic.Output.MovementComputed output) =>
|
||||
{
|
||||
var spriteNode = GetChildren().OfType<AnimatedSprite3D>();
|
||||
|
||||
if (spriteNode.Any())
|
||||
PlayMovementAnimations(spriteNode.Single(), Velocity);
|
||||
|
||||
MoveAndCollide(output.Velocity);
|
||||
MoveAndSlide();
|
||||
})
|
||||
.Handle((in EnemyLogic.Output.Die output) =>
|
||||
{
|
||||
@@ -139,6 +123,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
})
|
||||
.Handle((in EnemyLogic.Output.HitByPlayer output) =>
|
||||
{
|
||||
// TODO: Make this an event to notify game that player hit someone
|
||||
if (GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.SelfDamage))
|
||||
GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - 5);
|
||||
});
|
||||
@@ -146,31 +131,48 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
this.Provide();
|
||||
|
||||
EnemyLogic.Start();
|
||||
|
||||
CurrentHP = new AutoProp<double>(EnemyStatResource.MaximumHP);
|
||||
CurrentHP.Sync += OnHPChanged;
|
||||
LineOfSight.BodyEntered += LineOfSight_BodyEntered;
|
||||
PatrolTimer.Timeout += OnPatrolTimeout;
|
||||
AttackTimer.Timeout += OnAttackTimeout;
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
PatrolTimer.WaitTime = rng.RandfRange(7.0f, 15.0f);
|
||||
}
|
||||
|
||||
public void PlayMovementAnimations(AnimatedSprite3D sprite, Vector3 velocity)
|
||||
private void RotateEnemy(Vector3 cameraDirection)
|
||||
{
|
||||
if (sprite != null && velocity.Length() > 0.2f)
|
||||
{
|
||||
var lookdir = (GlobalPosition).Normalized();
|
||||
var sign = lookdir.Sign();
|
||||
if (lookdir.MaxAxisIndex() == Vector3.Axis.X && sign.X == 1)
|
||||
sprite.Play("walk_right");
|
||||
if (lookdir.MaxAxisIndex() == Vector3.Axis.X && sign.X == -1)
|
||||
sprite.Play("walk_left");
|
||||
if (lookdir.MaxAxisIndex() == Vector3.Axis.Z && sign.Z == 1)
|
||||
sprite.Play("walk_forward");
|
||||
if (lookdir.MaxAxisIndex() == Vector3.Axis.Z && sign.Z == -1)
|
||||
sprite.Play("walk_backward");
|
||||
}
|
||||
if (sprite != null && velocity.IsZeroApprox())
|
||||
sprite.Stop();
|
||||
}
|
||||
var rotateUpperThreshold = 0.85f;
|
||||
var rotateLowerThreshold = 0.3f;
|
||||
|
||||
var enemyForwardDirection = GlobalTransform.Basis.Z;
|
||||
var enemyLeftDirection = GlobalTransform.Basis.X;
|
||||
|
||||
var leftDotProduct = enemyLeftDirection.Dot(cameraDirection);
|
||||
var forwardDotProduct = enemyForwardDirection.Dot(cameraDirection);
|
||||
|
||||
// Check if forward facing. If the dot product is -1, the enemy is facing the camera.
|
||||
if (forwardDotProduct < -rotateUpperThreshold)
|
||||
AnimatedSprite.Play("idle_front_walk");
|
||||
// Check if backward facing. If the dot product is 1, the enemy is facing the same direction as the camera.
|
||||
else if (forwardDotProduct > rotateUpperThreshold)
|
||||
AnimatedSprite.Play("idle_back_walk");
|
||||
else
|
||||
{
|
||||
// If the dot product of the perpendicular dot product is positive (up to 1), the enemy is facing to the left (since it's mirrored).
|
||||
AnimatedSprite.FlipH = leftDotProduct > 0;
|
||||
// Check is side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning.
|
||||
if (Mathf.Abs(forwardDotProduct) < rotateLowerThreshold)
|
||||
AnimatedSprite.Play("idle_left_walk");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
EnemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
RotateEnemy(-GameRepo.PlayerGlobalTransform.Value.Basis.Z);
|
||||
}
|
||||
|
||||
public void OnPlayerHitboxEntered(Area3D body)
|
||||
@@ -195,7 +197,9 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
private void OnHPChanged(double newHP)
|
||||
{
|
||||
if (newHP <= 0)
|
||||
{
|
||||
EnemyLogic.Input(new EnemyLogic.Input.Killed());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReady()
|
||||
|
||||
Reference in New Issue
Block a user