fix(ui): restore retail skill training confirmation

Route untrained-skill promotion through DialogFactory with retail's exact prompt and stored skill/credit properties. Defer the character-sheet refresh until accept or reject completes while leaving trained-skill XP raises immediate.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 17:57:29 +02:00
parent 66bdae7a83
commit 85980fe13f
7 changed files with 341 additions and 14 deletions

View file

@ -142,6 +142,7 @@ public sealed class RetailUiRuntime : IDisposable
private readonly RetailUiAutomationScriptRunner? _automation;
private GameplayConfirmationController? _gameplayConfirmationController;
private RetailItemConfirmationController? _itemConfirmationController;
private RetailSkillTrainingConfirmationController? _skillTrainingConfirmationController;
private bool _disposed;
private RetailUiRuntime(RetailUiRuntimeBindings bindings)
@ -707,6 +708,8 @@ public sealed class RetailUiRuntime : IDisposable
_itemConfirmationController = new RetailItemConfirmationController(
DialogFactory,
ItemInteraction);
_skillTrainingConfirmationController =
new RetailSkillTrainingConfirmationController(DialogFactory);
Console.WriteLine(
$"[UI] retail DialogFactory from LayoutDesc 0x{layoutId:X8}; confirmation root 0x15.");
}
@ -806,7 +809,7 @@ public sealed class RetailUiRuntime : IDisposable
_bindings.Assets.DefaultFont,
_bindings.Assets.ResolveFont(0x40000001u) ?? _bindings.Assets.DefaultFont,
_bindings.Assets.ResolveSprite,
provider.HandleRaiseRequest,
(request, completed) => HandleCharacterRaise(provider, request, completed),
() => CloseWindow(WindowNames.Character));
RetailWindowFrame.Mount(Host.Root, layout.Root, _bindings.Assets.ResolveSprite,
new RetailWindowFrame.Options
@ -826,6 +829,30 @@ public sealed class RetailUiRuntime : IDisposable
Console.WriteLine("[D.2b-C] retail character window from LayoutDesc importer (0x2100002E).");
}
private void HandleCharacterRaise(
CharacterSheetProvider provider,
CharacterStatController.RaiseRequest request,
Action completed)
{
if (request.Kind != CharacterStatController.RaiseTargetKind.TrainSkill)
{
provider.HandleRaiseRequest(request);
completed();
return;
}
RetailSkillTrainingConfirmationController confirmations =
_skillTrainingConfirmationController
?? throw new InvalidOperationException(
"The retail dialog factory must be mounted before the character panel.");
confirmations.Request(
request,
provider.BuildSheet(),
provider.HandleRaiseRequest,
completed);
}
private void MountPlugins()
{
if (_bindings.Plugins is null) return;