Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md). All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using Theriapolis.Core.Data;
|
||||
using Theriapolis.Game.CodexUI.Core;
|
||||
using Theriapolis.Game.CodexUI.Screens;
|
||||
using Theriapolis.Game.CodexUI.Widgets;
|
||||
using Theriapolis.Game.UI;
|
||||
|
||||
namespace Theriapolis.Game.CodexUI.Steps;
|
||||
|
||||
/// <summary>
|
||||
/// Step II — Species. Card grid filtered to the selected clade. Each card
|
||||
/// shows name + size + base speed + ability mods + traits.
|
||||
/// </summary>
|
||||
public static class StepSpecies
|
||||
{
|
||||
public static CodexWidget Build(CodexCharacterCreationScreen s, CodexAtlas atlas, CodexHoverPopover popover)
|
||||
{
|
||||
var col = new Column { Spacing = 14 };
|
||||
col.Add(StepCommon.PageIntro(
|
||||
$"Folio II — Of Lineage within {s.Clade?.Name ?? "—"}",
|
||||
"Choose your Species",
|
||||
"Within every clade are kindreds — different statures, ranges, and inheritances. The species refines what the clade began."));
|
||||
|
||||
var grid = new Grid { Columns = 3 };
|
||||
foreach (var sp in s.AllSpecies.Where(x => s.Clade is null || x.CladeId == s.Clade.Id))
|
||||
grid.Add(BuildCard(s, atlas, popover, sp));
|
||||
col.Add(grid);
|
||||
return col;
|
||||
}
|
||||
|
||||
private static CodexWidget BuildCard(CodexCharacterCreationScreen s, CodexAtlas atlas, CodexHoverPopover popover, SpeciesDef sp)
|
||||
{
|
||||
var content = new Column { Spacing = 8 };
|
||||
content.Add(new CodexLabel(sp.Name, CodexFonts.DisplayMedium, CodexColors.Ink));
|
||||
content.Add(new CodexLabel($"{CodexCopy.SizeLabel(sp.Size).ToUpperInvariant()} · {sp.BaseSpeedFt} FT.",
|
||||
CodexFonts.MonoTagSmall, CodexColors.InkMute));
|
||||
|
||||
if (sp.AbilityMods.Count > 0)
|
||||
{
|
||||
var mods = new WrapRow();
|
||||
foreach (var kv in sp.AbilityMods) mods.Add(new ModChipMini(atlas, kv.Key, kv.Value));
|
||||
content.Add(mods);
|
||||
}
|
||||
|
||||
if (sp.Traits.Length > 0 || sp.Detriments.Length > 0)
|
||||
{
|
||||
var traits = new WrapRow();
|
||||
foreach (var t in sp.Traits) traits.Add(new HoverableChip(atlas, popover, t.Name, t.Name, t.Description, null, ChipKind.Trait));
|
||||
foreach (var t in sp.Detriments) traits.Add(new HoverableChip(atlas, popover, t.Name, t.Name, t.Description, "DETRIMENT", ChipKind.TraitDetriment));
|
||||
content.Add(traits);
|
||||
}
|
||||
|
||||
return new CodexCard(atlas, content, s.Species == sp,
|
||||
onClick: () => { s.Species = sp; s.InvalidateLayout(); });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user