Hit shader
This commit is contained in:
@@ -34,6 +34,8 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
[Dependency] IGameRepo GameRepo => this.DependOn<IGameRepo>();
|
||||
|
||||
[Dependency] IGameEventDepot GameEventDepot => this.DependOn<IGameEventDepot>();
|
||||
|
||||
[Export]
|
||||
public EnemyStatResource EnemyStatResource { get; set; } = default!;
|
||||
|
||||
@@ -51,10 +53,12 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
[Node] public Timer AttackTimer { get; set; } = default!;
|
||||
|
||||
[Node] public AnimatedSprite3D AnimatedSprite { get; set; } = default!;
|
||||
[Node] public AnimatedSprite2D AnimatedSprite { get; set; } = default!;
|
||||
|
||||
[Node] public RayCast3D Raycast { get; set; } = default!;
|
||||
|
||||
[Node] public AnimationPlayer AnimationPlayer { 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";
|
||||
@@ -67,17 +71,93 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
EnemyLogic.Set(EnemyStatResource);
|
||||
EnemyLogic.Set(this as IEnemy);
|
||||
EnemyLogic.Set(GameRepo);
|
||||
AnimationPlayer.AnimationFinished += AnimationPlayer_AnimationFinished;
|
||||
}
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
CollisionDetector = CollisionDetectorScene.Instantiate<Area3D>();
|
||||
CollisionDetector.AreaEntered += OnPlayerHitboxEntered;
|
||||
AddChild(CollisionDetector);
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
EnemyBinding = EnemyLogic.Bind();
|
||||
|
||||
EnemyBinding
|
||||
.Handle((in EnemyLogic.Output.MovementComputed output) =>
|
||||
{
|
||||
MoveAndSlide();
|
||||
})
|
||||
.Handle((in EnemyLogic.Output.HitByPlayer output) =>
|
||||
{
|
||||
if (CurrentHP.Value > 0)
|
||||
AnimationPlayer.Play("hit");
|
||||
// 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);
|
||||
})
|
||||
.Handle((in EnemyLogic.Output.Defeated output) =>
|
||||
{
|
||||
AnimationPlayer.Play("defeated");
|
||||
});
|
||||
|
||||
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 OnExitTree()
|
||||
{
|
||||
EnemyLogic.Stop();
|
||||
EnemyBinding.Dispose();
|
||||
}
|
||||
|
||||
private void OnPatrolTimeout()
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomizedSpot = new Vector3(rng.RandfRange(-3.0f, 3.0f), 0, rng.RandfRange(-3.0f, 3.0f));
|
||||
var randomizedSpot = new Vector3(rng.RandfRange(-7.0f, 7.0f), 0, rng.RandfRange(-7.0f, 7.0f));
|
||||
EnemyLogic.Input(new EnemyLogic.Input.PatrolToRandomSpot(GlobalPosition + randomizedSpot));
|
||||
PatrolTimer.WaitTime = rng.RandfRange(7.0f, 15.0f);
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
EnemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
RotateEnemy(-GameRepo.PlayerGlobalTransform.Value.Basis.Z);
|
||||
}
|
||||
|
||||
public void OnPlayerHitboxEntered(Area3D body)
|
||||
{
|
||||
if (body is IHitbox hitBox)
|
||||
{
|
||||
if (CurrentHP.Value > 0)
|
||||
{
|
||||
var isCriticalHit = false;
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var roll = rng.Randf();
|
||||
if (roll <= GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.Luck)
|
||||
isCriticalHit = true;
|
||||
var damage = DamageCalculator.CalculatePlayerDamage(GameRepo.PlayerData.CurrentAttack.Value + GameRepo.PlayerData.BonusAttack, EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats, isCriticalHit);
|
||||
GD.Print($"Enemy Hit for {damage} damage.");
|
||||
EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(damage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAttackTimeout()
|
||||
{
|
||||
if (GlobalPosition.DistanceTo(GameRepo.PlayerGlobalPosition.Value) > 2.5f)
|
||||
@@ -92,54 +172,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());
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
EnemyBinding = EnemyLogic.Bind();
|
||||
|
||||
EnemyBinding
|
||||
.Handle((in EnemyLogic.Output.MovementComputed output) =>
|
||||
foreach (var overlap in overlappingBodies)
|
||||
{
|
||||
Raycast.LookAt(GameRepo.PlayerGlobalPosition.Value, Vector3.Up);
|
||||
Raycast.ForceRaycastUpdate();
|
||||
if (Raycast.IsColliding())
|
||||
{
|
||||
MoveAndSlide();
|
||||
})
|
||||
.Handle((in EnemyLogic.Output.Die output) =>
|
||||
{
|
||||
QueueFree();
|
||||
})
|
||||
.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);
|
||||
});
|
||||
|
||||
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);
|
||||
var collider = Raycast.GetCollider();
|
||||
if (collider is IPlayer player)
|
||||
{
|
||||
Raycast.DebugShapeCustomColor = Color.FromString("Purple", Colors.Purple);
|
||||
EnemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RotateEnemy(Vector3 cameraDirection)
|
||||
@@ -169,58 +215,18 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
EnemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
RotateEnemy(-GameRepo.PlayerGlobalTransform.Value.Basis.Z);
|
||||
}
|
||||
|
||||
public void OnPlayerHitboxEntered(Area3D body)
|
||||
{
|
||||
if (body is IHitbox hitBox)
|
||||
{
|
||||
if (CurrentHP.Value > 0)
|
||||
{
|
||||
var isCriticalHit = false;
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var roll = rng.Randf();
|
||||
if (roll <= GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.Luck)
|
||||
isCriticalHit = true;
|
||||
var damage = DamageCalculator.CalculatePlayerDamage(GameRepo.PlayerData.CurrentAttack.Value + GameRepo.PlayerData.BonusAttack, EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats, isCriticalHit);
|
||||
GD.Print($"Enemy Hit for {damage} damage.");
|
||||
EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(damage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHPChanged(double newHP)
|
||||
{
|
||||
if (newHP <= 0)
|
||||
{
|
||||
EnemyLogic.Input(new EnemyLogic.Input.Killed());
|
||||
EnemyLogic.Input(new EnemyLogic.Input.EnemyDefeated());
|
||||
GameEventDepot.OnEnemyDefeated(EnemyStatResource);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReady()
|
||||
private void AnimationPlayer_AnimationFinished(StringName animName)
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
CollisionDetector = CollisionDetectorScene.Instantiate<Area3D>();
|
||||
CollisionDetector.AreaEntered += OnPlayerHitboxEntered;
|
||||
AddChild(CollisionDetector);
|
||||
}
|
||||
|
||||
public void OnExitTree()
|
||||
{
|
||||
EnemyLogic.Stop();
|
||||
EnemyBinding.Dispose();
|
||||
if (animName == "defeated")
|
||||
QueueFree();
|
||||
}
|
||||
}
|
||||
|
||||
public enum WeaponTag
|
||||
{
|
||||
SelfDamage,
|
||||
IgnoreAffinity,
|
||||
Knockback,
|
||||
BreaksOnChange
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user