hitting is now an ability
This commit is contained in:
@@ -1,22 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Gamesmiths.Forge.Abilities;
|
||||
using Gamesmiths.Forge.Attributes;
|
||||
using Gamesmiths.Forge.Core;
|
||||
using Gamesmiths.Forge.Cues;
|
||||
using Gamesmiths.Forge.Effects;
|
||||
using Gamesmiths.Forge.Events;
|
||||
using Gamesmiths.Forge.Godot.Core;
|
||||
using Gamesmiths.Forge.Godot.Nodes;
|
||||
using Gamesmiths.Forge.Godot.Resources.Abilities;
|
||||
using Gamesmiths.Forge.Statescript;
|
||||
using Gamesmiths.Forge.Tags;
|
||||
using Godot;
|
||||
using Movementtests.interfaces;
|
||||
using Movementtests.scenes.enemies;
|
||||
using Movementtests.scenes.player_controller.scripts;
|
||||
using Movementtests.systems;
|
||||
using Movementtests.tools;
|
||||
using Node = Godot.Node;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_beetle.png"), Meta(typeof(IAutoNode))]
|
||||
@@ -42,14 +40,21 @@ public partial class Enemy : CharacterBody3D,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Signals
|
||||
|
||||
// Signals and events
|
||||
public event Action<IDamageable, DamageRecord> DamageTaken = null!;
|
||||
public event Action<IHealthable, HealthChangedRecord> HealthChanged = null!;
|
||||
public event Action<IHealthable> HealthDepleted = null!;
|
||||
public event Action<IHealthable, HealthChangedRecord> HealthChanged = null!;
|
||||
public event Action<IHealthable> HealthDepleted = null!;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inspector
|
||||
|
||||
// Public export components
|
||||
[Export]
|
||||
public Node3D? Target { get; set; }
|
||||
[Export] public required ForgeAbilityData HitAbility { get; set; }
|
||||
|
||||
[Export]
|
||||
public float EnemyHeight { get; set; } = 1f;
|
||||
@@ -72,8 +77,10 @@ public partial class Enemy : CharacterBody3D,
|
||||
|
||||
[ExportGroup("Movement")]
|
||||
[Export]
|
||||
public RMovement? RMovement { get; set; }
|
||||
public IMoveable CMovement { get; set; } = null!;
|
||||
public required RMovement RMovement { get; set; }
|
||||
public required IMoveable CMovement { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
// Public stuff
|
||||
public float CurrentHealth
|
||||
@@ -81,45 +88,48 @@ public partial class Enemy : CharacterBody3D,
|
||||
get => CHealth.CurrentHealth;
|
||||
set => CHealth.CurrentHealth = value;
|
||||
}
|
||||
|
||||
|
||||
#region IForgeEntity
|
||||
|
||||
// Perfectly forward the IForgeEntity interface to the ForgeEntity component
|
||||
public EntityAttributes Attributes
|
||||
{
|
||||
get => _forgeEntity.Attributes;
|
||||
set => _forgeEntity.Attributes = value;
|
||||
get => ForgeEntity.Attributes;
|
||||
set => ForgeEntity.Attributes = value;
|
||||
}
|
||||
public EntityTags Tags
|
||||
{
|
||||
get => _forgeEntity.Tags;
|
||||
set => _forgeEntity.Tags = value;
|
||||
get => ForgeEntity.Tags;
|
||||
set => ForgeEntity.Tags = value;
|
||||
}
|
||||
public EffectsManager EffectsManager
|
||||
{
|
||||
get => _forgeEntity.EffectsManager;
|
||||
set => _forgeEntity.EffectsManager = value;
|
||||
get => ForgeEntity.EffectsManager;
|
||||
set => ForgeEntity.EffectsManager = value;
|
||||
}
|
||||
public EntityAbilities Abilities
|
||||
{
|
||||
get => _forgeEntity.Abilities;
|
||||
set => _forgeEntity.Abilities = value;
|
||||
get => ForgeEntity.Abilities;
|
||||
set => ForgeEntity.Abilities = value;
|
||||
}
|
||||
public EventManager Events
|
||||
{
|
||||
get => _forgeEntity.Events;
|
||||
set => _forgeEntity.Events = value;
|
||||
get => ForgeEntity.Events;
|
||||
set => ForgeEntity.Events = value;
|
||||
}
|
||||
|
||||
[Export] public ForgeAbilityData? HitAbility;
|
||||
|
||||
#endregion
|
||||
|
||||
public Variables SharedVariables { get; }
|
||||
|
||||
// Private stuff
|
||||
private Area3D _damageBox = null!;
|
||||
internal Node3D _target = null!;
|
||||
private ResourceBar _resourceBar = null!;
|
||||
private ForgeEntity _forgeEntity;
|
||||
[Node("DamageBox")] public required Area3D DamageBox { get; set;}
|
||||
[Node("CTarget")] public required Node3D TargetComponent { get; set;}
|
||||
[Node("CHealthBar")] public required CHealthbar HealthBarWrapper { get; set;}
|
||||
[Node("ForgeEntity")] public required ForgeEntity ForgeEntity { get; set;}
|
||||
|
||||
private AbilityHandle? _hitAbilityHandle;
|
||||
private EntityAttribute _healthAttribute;
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
@@ -129,39 +139,38 @@ public partial class Enemy : CharacterBody3D,
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_damageBox = GetNode<Area3D>("DamageBox");
|
||||
_target = GetNode<Node3D>("CTarget");
|
||||
_forgeEntity = GetNode<ForgeEntity>("ForgeEntity");
|
||||
CMovement = GetNode<Node>("CMovement") as IMoveable ?? throw new Exception("Movement component not found");
|
||||
CMovement.RMovement = RMovement;
|
||||
_healthAttribute = Attributes["EnemyAttributeSet.Health"];
|
||||
|
||||
CDamageable = (GetNode<Node>("CDamageable") as IDamageable)!;
|
||||
CMovement = (GetNode<Node>("CMovement") as IMoveable)!;
|
||||
CHealth = (GetNode<Node>("CHealth") as IHealthable)!;
|
||||
CKnockback = (GetNode<Node>("CKnockback") as IKnockbackable)!;
|
||||
|
||||
_resourceBar = GetNode<CHealthbar>("CHealthBar").ResourceBar;
|
||||
|
||||
CMovement.RMovement = RMovement;
|
||||
CHealth.RHealth = RHealth;
|
||||
CHealth.CurrentHealth = RHealth.StartingHealth;
|
||||
CKnockback.RKnockback = RKnockback;
|
||||
|
||||
if (HitAbility != null)
|
||||
_hitAbilityHandle = Abilities.GrantAbilityPermanently(HitAbility.GetAbilityData(), 1, LevelComparison.None, this);
|
||||
_hitAbilityHandle = Abilities.GrantAbilityPermanently(HitAbility.GetAbilityData(), 1, LevelComparison.None, this);
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
HealthBarWrapper.ResourceBar.Init(_healthAttribute);
|
||||
// CuesManager.RegisterCue(Tag.RequestTag(TagsManager, "cues.enemy.health"), HealthBarWrapper.ResourceBar);
|
||||
|
||||
Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.hit"),
|
||||
data => {GD.Print("Hit!");});
|
||||
Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.damage"), OnDamageReceived);
|
||||
Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.death"), OnDeath);
|
||||
}
|
||||
|
||||
public void SetupSignals()
|
||||
{
|
||||
// Anonymous function call to erase return values of ReduceHealth
|
||||
CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
|
||||
CDamageable.DamageTaken += (_, record) => RegisterKnockback(new KnockbackRecord(record));
|
||||
CHealth.HealthDepleted += Kill;
|
||||
HealthChanged += (_, record) => _resourceBar.SetValue(record.CurrentHealth);
|
||||
// CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
|
||||
// CDamageable.DamageTaken += (_, record) => RegisterKnockback(new KnockbackRecord(record));
|
||||
// CHealth.HealthDepleted += Kill;
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
@@ -188,7 +197,7 @@ public partial class Enemy : CharacterBody3D,
|
||||
{
|
||||
if (IsStunned || _hitAbilityHandle == null) return;
|
||||
|
||||
var bodies = _damageBox.GetOverlappingBodies();
|
||||
var bodies = DamageBox.GetOverlappingBodies();
|
||||
foreach (var body in bodies)
|
||||
{
|
||||
if (body is not IForgeEntity forgeEntity) continue;
|
||||
@@ -196,16 +205,40 @@ public partial class Enemy : CharacterBody3D,
|
||||
if (!canActivate) return;
|
||||
|
||||
_hitAbilityHandle.Activate(out var _, forgeEntity);
|
||||
|
||||
// if(body is IDamageable spawnable)
|
||||
// spawnable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 ComputeVelocity(MovementInputs inputs)
|
||||
{
|
||||
if (CMovement is null) return Vector3.Zero;
|
||||
return CMovement.ComputeVelocity(inputs);
|
||||
return CMovement is null ? Vector3.Zero : CMovement.ComputeVelocity(inputs);
|
||||
}
|
||||
|
||||
public void OnDamageReceived(EventData data)
|
||||
{
|
||||
var newHealth = _healthAttribute.CurrentValue + data.EventMagnitude;
|
||||
if (newHealth > _healthAttribute.Min) return;
|
||||
|
||||
Events.Raise(new EventData
|
||||
{
|
||||
EventTags = Tag.RequestTag(TagsManager, "events.combat.death").GetSingleTagContainer()!,
|
||||
Source = data.Source,
|
||||
Target = data.Target
|
||||
});
|
||||
}
|
||||
|
||||
public void OnDeath(EventData data)
|
||||
{
|
||||
// Remove weapon that might be planted there
|
||||
foreach (var child in GetChildren())
|
||||
{
|
||||
if (child is not WeaponSystem system) continue;
|
||||
CallDeferred(Node.MethodName.RemoveChild, system);
|
||||
GetTree().GetRoot().CallDeferred(Node.MethodName.AddChild, system);
|
||||
system.CallDeferred(Node3D.MethodName.SetGlobalPosition, GlobalPosition + Vector3.Up*EnemyHeight);
|
||||
system.CallDeferred(WeaponSystem.MethodName.RethrowWeapon);
|
||||
}
|
||||
|
||||
CallDeferred(Node.MethodName.QueueFree);
|
||||
}
|
||||
|
||||
public DamageRecord TakeDamage(DamageRecord damageRecord)
|
||||
@@ -267,7 +300,7 @@ public partial class Enemy : CharacterBody3D,
|
||||
|
||||
public Vector3 GetTargetGlobalPosition()
|
||||
{
|
||||
return _target == null ? GlobalPosition : _target.GlobalPosition;
|
||||
return TargetComponent == null ? GlobalPosition : TargetComponent.GlobalPosition;
|
||||
}
|
||||
|
||||
// Stun management
|
||||
|
||||
Reference in New Issue
Block a user