enemies spawn held in place

This commit is contained in:
Ian Woods 2026-06-23 22:21:32 -07:00
parent 54f11d91ff
commit ff921080db
4 changed files with 75 additions and 26 deletions

View file

@ -66,6 +66,7 @@ namespace TD.Gameplay
private float pendingMaxHp = 100f;
private int pendingLivesCost = 1;
private bool pendingIsFlying;
private bool pendingIsHeld;
private bool hasPendingInit;
// ----- Server-local runtime state -------------------------------------
@ -97,11 +98,17 @@ namespace TD.Gameplay
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
private readonly NetworkVariable<bool> isHeld = new NetworkVariable<bool>(
false,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
// ----- Public state ---------------------------------------------------
public float CurrentHp => hp.Value;
public float MaxHp { get; private set; } = 100f;
public bool IsDead => hp.Value <= 0f;
public bool IsHeld => isHeld.Value;
/// <summary>
/// True if this enemy flies over tower footprints.
@ -126,11 +133,12 @@ namespace TD.Gameplay
/// and before <c>NetworkObject.Spawn()</c>. Mirrors the
/// <c>TowerInstance.InitializeServer</c> pattern.
/// </summary>
public void InitializeServer(float maxHp, int livesCost, bool flying)
public void InitializeServer(float maxHp, int livesCost, bool flying, bool held = false)
{
pendingMaxHp = maxHp;
pendingLivesCost = livesCost;
pendingIsFlying = flying;
pendingIsHeld = held;
hasPendingInit = true;
// Cache locally on the server immediately — clients resolve via NV.
@ -146,12 +154,19 @@ namespace TD.Gameplay
{
hp.Value = pendingMaxHp;
isFlying.Value = pendingIsFlying;
isHeld.Value = pendingIsHeld;
hasPendingInit = false;
}
// Non-server clients resolve MaxHp from the replicated hp initial value.
if (!IsServer)
MaxHp = hp.Value;
// Apply initial held state on all peers and watch for future changes.
// isHeld.OnValueChanged doesn't fire for the initial replication, so we
// apply it explicitly here as well.
ApplyHeldState(isHeld.Value);
isHeld.OnValueChanged += (_, current) => ApplyHeldState(current);
}
public override void OnNetworkDespawn()
@ -166,6 +181,23 @@ namespace TD.Gameplay
// ----- Server API -----------------------------------------------------
/// <summary>
/// Sets whether this enemy is held. Held enemies are untargetable and do not
/// move. Server-only; the NetworkVariable replicates the change to all peers.
/// </summary>
public void SetHeld(bool held)
{
if (!IsServer) return;
isHeld.Value = held;
}
private void ApplyHeldState(bool held)
{
if (IsDead) return;
foreach (var col in GetComponentsInChildren<Collider>())
col.enabled = !held;
}
/// <summary>
/// Applies damage to this enemy. Server-only; silently no-ops on clients.
/// <paramref name="type"/> is accepted for future resistance lookups (Phase 1.5+).