Updating HUD, Gold Config, and finishing off Play flow for 9player map.
This commit is contained in:
parent
a7be12fa9b
commit
3dcc0e7edd
28 changed files with 2272 additions and 9601 deletions
|
|
@ -52,6 +52,7 @@ namespace TD.Gameplay
|
|||
|
||||
private float pendingMoveSpeed;
|
||||
private Vector2Int pendingSpawnerTile;
|
||||
private PlayerSlot pendingOwnerSlot;
|
||||
private bool hasPendingInit;
|
||||
|
||||
// ----- Server-local runtime state -------------------------------------
|
||||
|
|
@ -59,6 +60,16 @@ namespace TD.Gameplay
|
|||
private float moveSpeed;
|
||||
private List<Vector2Int> remainingPath = new List<Vector2Int>();
|
||||
private PlayerSlot currentZone = PlayerSlot.None;
|
||||
// Zone the enemy was spawned in — i.e., which player "owns" this enemy as part
|
||||
// of their wave. Used so OnZoneLeaked fires only when the enemy escapes that
|
||||
// origin zone (not when it transits through any subsequent zone on its way to
|
||||
// the goal). Without this, every zone crossing was counted as a leak; only
|
||||
// the originating player should be credited a leak per the design.
|
||||
private PlayerSlot originZone = PlayerSlot.None;
|
||||
// Latches once the enemy has crossed its origin zone's leak volume, so we
|
||||
// never double-count a leak if the enemy re-enters its origin (rare but
|
||||
// possible if pathing is dynamic).
|
||||
private bool hasLeakedOriginZone;
|
||||
private EnemyStatus status;
|
||||
private bool hasReachedGoal;
|
||||
private bool wasStuck; // dedupes the "no path" warning
|
||||
|
|
@ -66,10 +77,11 @@ namespace TD.Gameplay
|
|||
// ----- Events ---------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Fired on the server when this enemy crosses from one player zone into another
|
||||
/// (or from a neutral zone into a player zone). The argument is the zone being
|
||||
/// LEFT — the zone that should be debited a life.
|
||||
/// <c>WaveManager</c> subscribes to deduct from the correct player's life pool.
|
||||
/// Fired on the server EXACTLY ONCE per enemy, when it crosses out of its
|
||||
/// origin zone (the zone it spawned in) into another zone. The argument is the
|
||||
/// origin zone — the player who "owns" this enemy and should be credited a
|
||||
/// leak. Transit through subsequent zones does NOT fire this event.
|
||||
/// <c>WaveManager</c> subscribes to increment the per-player leak counter.
|
||||
/// </summary>
|
||||
public event System.Action<PlayerSlot> OnZoneLeaked;
|
||||
|
||||
|
|
@ -87,12 +99,18 @@ namespace TD.Gameplay
|
|||
/// Called by <c>WaveManager</c> on the server after <c>Instantiate</c> and
|
||||
/// before <c>NetworkObject.Spawn()</c>. <paramref name="speed"/> comes from
|
||||
/// <see cref="EnemyDefinition.MoveSpeed"/>; <paramref name="spawnerTile"/> is
|
||||
/// the tile the enemy spawns on (used as the A* start node).
|
||||
/// the tile the enemy spawns on (used as the A* start node);
|
||||
/// <paramref name="ownerSlot"/> identifies which player "owns" this enemy
|
||||
/// for leak-attribution (the slot whose <c>PlayerZoneData</c> contained the
|
||||
/// spawner). It is NOT derived from the spawner tile's owner because spawner
|
||||
/// tiles sit inside <c>SpawnerVolume</c>, not <c>PlayerZoneVolume</c>, so
|
||||
/// their owner-grid entry is <see cref="PlayerSlot.None"/>.
|
||||
/// </summary>
|
||||
public void InitializeServer(float speed, Vector2Int spawnerTile)
|
||||
public void InitializeServer(float speed, Vector2Int spawnerTile, PlayerSlot ownerSlot)
|
||||
{
|
||||
pendingMoveSpeed = speed;
|
||||
pendingSpawnerTile = spawnerTile;
|
||||
pendingOwnerSlot = ownerSlot;
|
||||
hasPendingInit = true;
|
||||
}
|
||||
|
||||
|
|
@ -113,11 +131,21 @@ namespace TD.Gameplay
|
|||
|
||||
moveSpeed = pendingMoveSpeed;
|
||||
|
||||
// Resolve starting zone from the spawner tile.
|
||||
// Resolve starting zone from the spawner tile. This is what the enemy
|
||||
// observes as "the zone I am currently in." For SpawnerVolume tiles that
|
||||
// sit outside any PlayerZoneVolume (the common case) this is None — the
|
||||
// enemy will transition to its owner's zone on the first waypoint inside
|
||||
// that PlayerZoneVolume.
|
||||
var loader = LevelLoader.Instance;
|
||||
if (loader != null)
|
||||
currentZone = loader.GetOwner(pendingSpawnerTile);
|
||||
|
||||
// Origin zone is the player who "owns" this enemy for leak attribution.
|
||||
// WaveManager passes it in (zone.Owner) because the spawner tile's owner-
|
||||
// grid entry is unreliable (typically None — see InitializeServer remarks).
|
||||
originZone = pendingOwnerSlot;
|
||||
hasLeakedOriginZone = false;
|
||||
|
||||
// Compute the initial path from the spawn tile to the nearest goal.
|
||||
ComputeAndStorePath(pendingSpawnerTile);
|
||||
|
||||
|
|
@ -194,9 +222,18 @@ namespace TD.Gameplay
|
|||
PlayerSlot newZone = loader.GetOwner(tile);
|
||||
if (newZone == currentZone) return;
|
||||
|
||||
// The enemy is leaving currentZone — debit that player's life pool.
|
||||
if (currentZone != PlayerSlot.None)
|
||||
OnZoneLeaked?.Invoke(currentZone);
|
||||
// The enemy is crossing a zone boundary. Only fire OnZoneLeaked if it's
|
||||
// the FIRST time this enemy escapes its ORIGIN zone — that's the
|
||||
// "I failed to stop it in my own maze" event the leak counter tracks.
|
||||
// Subsequent transit through other zones is just routing toward the goal
|
||||
// and doesn't credit any player a leak.
|
||||
if (!hasLeakedOriginZone
|
||||
&& currentZone == originZone
|
||||
&& currentZone != PlayerSlot.None)
|
||||
{
|
||||
hasLeakedOriginZone = true;
|
||||
OnZoneLeaked?.Invoke(originZone);
|
||||
}
|
||||
|
||||
currentZone = newZone;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue