Adding new Races, Main Menu -> Lobby flow, and what's needed to set up multiplayer testing.

This commit is contained in:
Matt F 2026-05-17 23:31:02 -07:00
parent 60fa58b07f
commit fdada6f132
29 changed files with 2581 additions and 176 deletions

View file

@ -0,0 +1,75 @@
// Assets/_Project/Scripts/Gameplay/RaceDefinition.cs
using UnityEngine;
using TD.Core;
using TD.Towers;
namespace TD.Gameplay
{
/// <summary>
/// One asset per playable race. Holds the race's identity (the
/// <see cref="RaceId"/> binding for networked selection), the visual + lore
/// content shown in the lobby's race-selection UI, and stub fields for the
/// Phase 1.8 gameplay payload (race-specific builder + tower roster).
/// </summary>
/// <remarks>
/// <para><b>Creating a new race.</b> Right-click in the project window →
/// <c>Create → TD → Race Definition</c>. Fill in the inspector:
/// <list type="bullet">
/// <item><b>Id</b> — pick an unused <see cref="RaceId"/> value (Race1..Race16).</item>
/// <item><b>Display Name</b> — what shows in the grid + detail header.</item>
/// <item><b>Icon</b> — square sprite, ~256x256, drawn in the grid + detail.</item>
/// <item><b>Builder Name / Description</b> — text in the detail panel.</item>
/// <item><b>Lore Text</b> — longer description in the detail panel.</item>
/// <item><b>Builder Prefab / Towers</b> — <i>stubs</i>, wired in Phase 1.8.</item>
/// </list>
/// Then drag the asset into the <c>RaceRegistry</c>'s <c>Definitions</c>
/// array on the scene's <c>RaceRegistry</c> GameObject.</para>
///
/// <para><b>Why <see cref="Id"/> is serialized rather than inferred from the
/// asset name.</b> Race selection is networked via a
/// <see cref="UnityEngine.SerializeField"/>-backed enum on
/// <c>PlayerMatchState</c>. The enum byte value is the wire identity; the
/// asset is just the local lookup. Keeping the binding explicit on the
/// asset prevents accidental drift if assets get renamed.</para>
/// </remarks>
[CreateAssetMenu(fileName = "RaceDefinition", menuName = "TD/Race Definition", order = 5)]
public class RaceDefinition : ScriptableObject
{
[Header("Identity")]
[Tooltip("Enum value used by PlayerMatchState.RaceSelection on the network. " +
"Pick an unused RaceId (Race1..Race16). Each asset must use a unique value.")]
public RaceId Id = RaceId.None;
[Tooltip("Race name shown in the lobby grid and detail panel header.")]
public string DisplayName;
[Tooltip("Square icon shown in the grid cell and as the larger image in the detail panel. " +
"~256x256 PNG works well; the UI scales to fit.")]
public Sprite Icon;
[Header("Builder")]
[Tooltip("Builder name shown in the detail panel (the builder is the in-match avatar " +
"that gates tower placement by proximity).")]
public string BuilderName;
[Tooltip("Short description of the builder shown beneath the name in the detail panel.")]
[TextArea(2, 4)]
public string BuilderDescription;
[Header("Lore")]
[Tooltip("Race lore / background shown in the detail panel. Lorem ipsum is fine " +
"for placeholder races; replace when actual writing is ready.")]
[TextArea(5, 15)]
public string LoreText;
[Header("Gameplay payload (Phase 1.8 — not wired yet)")]
[Tooltip("STUB (Phase 1.8): race-specific builder prefab. Currently every race spawns " +
"the default builder. When Phase 1.8 lands, PlayerBuilderSpawner will pick " +
"the prefab based on the player's RaceSelection.")]
public GameObject BuilderPrefab;
[Tooltip("STUB (Phase 1.8): tower roster available to this race. TowerRegistry will " +
"filter to this list when the active player belongs to this race.")]
public TowerDefinition[] Towers;
}
}