Adding major combat changes and features
This commit is contained in:
parent
abcefcd7f1
commit
42ee0bf65d
28 changed files with 1653 additions and 46 deletions
90
Assets/_Project/Scripts/Gameplay/EnemyHealth.cs
Normal file
90
Assets/_Project/Scripts/Gameplay/EnemyHealth.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// Assets/_Project/Scripts/Gameplay/EnemyHealth.cs
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using TD.Core;
|
||||
|
||||
namespace TD.Gameplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Per-enemy HP component. Holds replicated HP and is the single point
|
||||
/// through which all damage flows, so resistance lookups (Phase 1.5+) can
|
||||
/// be added in one place without touching every damage source.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Lives on the enemy prefab root alongside <see cref="EnemyStatus"/> and the
|
||||
/// future <c>EnemyMovement</c> component (Phase 1.5/1.6). HP is server-written
|
||||
/// and replicated to all clients so health bars can render on any peer.
|
||||
///
|
||||
/// <b>Death flow (server-only):</b>
|
||||
/// <c>TakeDamage</c> clamps HP to 0, fires <see cref="OnDied"/>, then calls
|
||||
/// <c>NetworkObject.Despawn</c>. Subscribers must not touch the NetworkObject
|
||||
/// after <c>OnDied</c> returns.
|
||||
/// </remarks>
|
||||
[RequireComponent(typeof(NetworkObject))]
|
||||
public class EnemyHealth : NetworkBehaviour
|
||||
{
|
||||
[SerializeField] private float maxHp = 100f;
|
||||
|
||||
private readonly NetworkVariable<float> hp = new NetworkVariable<float>(
|
||||
0f,
|
||||
NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
|
||||
// ----- Public state -----------------------------------------------
|
||||
|
||||
public float CurrentHp => hp.Value;
|
||||
public float MaxHp => maxHp;
|
||||
public bool IsDead => hp.Value <= 0f;
|
||||
|
||||
// Stub: set by EnemyMovement or spawner in Phase 1.5/1.6.
|
||||
// TowerCombat reads this to honour the GroundedOnly tower flag.
|
||||
public bool IsFlying => false;
|
||||
|
||||
// ----- Events -----------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Fired on the server immediately before the enemy NetworkObject is despawned.
|
||||
/// <see cref="TD.Combat.TowerCombat"/> subscribes to clear its target reference.
|
||||
/// Do not access the NetworkObject after this event returns.
|
||||
/// </summary>
|
||||
public event System.Action<EnemyHealth> OnDied;
|
||||
|
||||
// ----- NGO lifecycle ----------------------------------------------
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer)
|
||||
hp.Value = maxHp;
|
||||
}
|
||||
|
||||
// ----- Server API -------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Applies <paramref name="damage"/> to this enemy. Server-only; no-op on clients.
|
||||
/// <paramref name="type"/> is recorded for future resistance/weakness lookups —
|
||||
/// all damage is full-value until the resistance table is implemented (Phase 1.5+).
|
||||
/// </summary>
|
||||
public void TakeDamage(float damage, DamageType type)
|
||||
{
|
||||
if (!IsServer) return;
|
||||
if (IsDead) return;
|
||||
|
||||
// STUB — resistance table slot:
|
||||
// float modified = ResistanceTable.Apply(damage, type, this);
|
||||
float modified = damage;
|
||||
|
||||
hp.Value = Mathf.Max(0f, hp.Value - modified);
|
||||
|
||||
if (hp.Value <= 0f)
|
||||
HandleDeath();
|
||||
}
|
||||
|
||||
// ----- Private ----------------------------------------------------
|
||||
|
||||
private void HandleDeath()
|
||||
{
|
||||
OnDied?.Invoke(this);
|
||||
NetworkObject.Despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue