Major updates to the HUD and selectable objects

This commit is contained in:
Matt F 2026-05-11 23:57:35 -07:00
parent 5bc757b385
commit c100db52e5
23 changed files with 1615 additions and 614 deletions

View file

@ -46,7 +46,7 @@ namespace TD.Gameplay
/// traversal.</para>
/// </remarks>
[RequireComponent(typeof(NetworkObject))]
public class Builder : NetworkBehaviour, IMinimapEntity
public class Builder : NetworkBehaviour, IMinimapEntity, ISelectable
{
// ----- Static registry --------------------------------------------
@ -156,6 +156,8 @@ namespace TD.Gameplay
/// <summary>Maximum jobs allowed in the queue.</summary>
public int MaxQueueDepth => settings.maxQueueDepth;
// ----- ISelectable ------------------------------------------------
/// <summary>Display name shown in the HUD portrait. Stub until MatchState provides player names.</summary>
public string DisplayName
{
@ -167,6 +169,15 @@ namespace TD.Gameplay
}
}
public SelectableKind Kind => SelectableKind.Builder;
public Transform SelectionTransform => transform;
// Builders are point units; the visible silhouette is roughly 1 unit wide.
// 0.6 puts a small visible gap between the silhouette and the ring.
// Bump up if BuilderSettings later exposes a width or selection radius.
public float SelectionRadius => 0.6f;
/// <summary>True if a tile is currently part of any queued or constructing job.</summary>
/// <remarks>
/// Used by <c>TowerPlacementManager</c> to reject placement on tiles already
@ -232,6 +243,14 @@ namespace TD.Gameplay
s_byClientId.Remove(OwnerClientId);
MinimapEntityRegistry.Deregister(this);
// Clear local selection if THIS builder was selected. Without this,
// SelectionState (and any subscriber holding our reference — HUD,
// SelectionVisualizer) keeps pointing at a soon-to-be-destroyed Unity
// object and throws MissingReferenceException on the next access.
// Local-only state, so safe to touch from any peer.
if (SelectionState.Instance != null && SelectionState.Instance.IsSelected(this))
SelectionState.Instance.Clear();
// Server-only cleanup: despawn any remaining build-site visuals so they
// don't leak when a player disconnects mid-construction.
if (IsServer)
@ -980,7 +999,30 @@ namespace TD.Gameplay
jobs.RemoveAt(0);
}
// Cancels the job at index i. Used for cancel-all and any future targeted cancel.
/// <summary>
/// Server-only: cancel the job in this builder's queue whose anchor matches
/// <paramref name="targetAnchor"/>. Refunds gold, frees the footprint tiles
/// (restoring walkability if the stage was blocking), and despawns the
/// build-site visual. Returns true if a matching job was found and
/// cancelled. Used by <see cref="BuildSiteVisual.RequestCancelRpc"/> so the
/// player can cancel a specific in-progress build from the HUD without
/// affecting other queued/constructing builds.
/// </summary>
public bool ServerCancelJobAtAnchor(Vector2Int targetAnchor)
{
if (!IsServer) return false;
for (int i = 0; i < jobs.Count; i++)
{
if (jobs[i].Anchor == targetAnchor)
{
ServerCancelJobAt(i);
return true;
}
}
return false;
}
// Cancels the job at index i. Used for cancel-all and targeted cancel paths.
private void ServerCancelJobAt(int index)
{
if (index < 0 || index >= jobs.Count) return;