M6.6: StepReview signing + hybrid math revision

- New Step VIII (Review): name input and Confirm button that
  saves the finalized character to user://character.tres.
- Hybrid lineage rules simplified per project decision: drop
  the "no-stack on overlap, take +1 free elsewhere" rule from
  theriapolis-rpg-clades.md. Hybrids now pick one ability mod
  from each parent clade and they sum if they overlap.
  Removes HybridFreeAbility, the free-bonus picker row, and the
  overlap special case from AbilityCalc + WizardValidation.
- StepClade bonus rows now mutate in place (sync ButtonPressed)
  instead of tearing down on every Refresh — the old path freed
  the very button mid-Pressed-signal, leaving stale buttons next
  to the new ones.
- StepSkills drops the redundant "Calling: X · History: Y" meta
  line; both are already shown in the Aside summary.
- Aside hybrid section adds dual-species traits and the
  universal-hybrid detriment pills.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Christopher Wiebe
2026-05-03 20:51:55 -07:00
parent 0e5d4b7425
commit bb986d49f9
8 changed files with 364 additions and 31 deletions
+4 -12
View File
@@ -23,7 +23,6 @@ public partial class StepSkills : VBoxContainer, IStep
{
private CharacterDraft _draft = null!;
private Label _countLabel = null!;
private Label _classBgLabel = null!;
private GridContainer _groupsGrid = null!;
public void Bind(CharacterDraft draft)
@@ -52,15 +51,8 @@ public partial class StepSkills : VBoxContainer, IStep
AutowrapMode = TextServer.AutowrapMode.WordSmart,
});
var meta = new HBoxContainer();
meta.AddThemeConstantOverride("separation", 24);
AddChild(meta);
_countLabel = new Label { Text = "0 / 0 chosen" };
meta.AddChild(_countLabel);
var spacer = new Control { SizeFlagsHorizontal = SizeFlags.ExpandFill };
meta.AddChild(spacer);
_classBgLabel = new Label { Text = "" };
meta.AddChild(_classBgLabel);
AddChild(_countLabel);
_groupsGrid = new GridContainer
{
@@ -86,9 +78,9 @@ public partial class StepSkills : VBoxContainer, IStep
var classOptions = new HashSet<string>(cls?.SkillOptions ?? System.Array.Empty<string>());
var chosen = new HashSet<string>(_draft.ChosenSkills);
_countLabel.Text = $"{chosen.Count} / {required} chosen +{lockedFromBg.Count} sealed by background";
_classBgLabel.Text = (cls is null ? "Pick a calling first." :
$"Calling: {cls.Name} · History: {bg?.Name ?? ""}").ToUpperInvariant();
_countLabel.Text = cls is null
? "Pick a calling first."
: $"{chosen.Count} / {required} chosen +{lockedFromBg.Count} sealed by background";
foreach (var c in _groupsGrid.GetChildren()) c.QueueFree();