fix: social gate round 2, part 2 - confirmation-dialog sentences + the
refused-drop yellow notice Item 4 (confirmation dialogs missing text + names): the missing retail mechanism was StringTable template substitution - an entry is N+1 literal fragments interleaved with N named variables, composed by StringTable::GetString @0x004300D0 (no-metalanguage branch @0x004303B7). ACE sends the bare player name for types 1/4; retail's OWN CLIENT wraps it. Ported as DatStringResolver.ResolveTemplate (PLAYER hash 0x05506DA2, the exact compute_str_hash space; Chorizite stores the variable hashes directly): - Server-driven type 4 -> ID_Fellowship_FellowshipRequest, type 1 -> ID_Allegiance_AcceptSwearConfirmation, injected into GameplayConfirmationController; null resolve falls back to the bare wire message, never invented English. The 2/3/5/6 " Continue?" family never consults the composer. - Local Swear/Break/Kick: the bind-time fragment-0 latch (which showed the dangling "Do you wish to swear to ") is replaced by click-time ResolveTemplate with the target's name. All five templates verified token-free in the installed DAT - this is NOT a StringTableMetaLanguage port (AD-81's engine caveat stands). Item 5 (refused drop shows nothing; retail shows yellow top-center text): the prevRequest latch was ALREADY ported (InventoryTransactionState); what was missing was the consumer. InventoryTransactionState now raises RequestFailed(request, weenieError) when a 0x00A0 clears the latch; ItemInteractionController composes ServerSaysAttemptFailed @0x0058EAE0's "The <item> can't be <verb>" (verb table + suffix map ported verbatim in Core's InventoryFailureMessages, NAME_PLURAL for merge/split) and routes it as LogTextType 0x1A ClientLocal -> the SpewBox, retail's yellow top-center line. The dispatcher's second leg (@0x0055B342) also runs: outside the 7-code exclusion set, WeenieErrorMessages resolves per-code text/destination; 0x426 AttunedItem has no row in either place beyond the verb line - faithful single-line output. Register: AD-85 narrowed to its numeric-field item, AD-81 amended (the token-free interleave is now ported; meta-token engine + FormatName remain), AD-93 filed (wire-guid-match vs retail's latched-guid preference; no Move/Wield latch kinds). Tests: +2 InventoryTransactionState failure-latch, +5 ResolveTemplate (constructed StringTable fixtures), +1 composer injection, +1 end-to-end refused-drop line. Core 4,697/1 skip, App 4,983/3 skips. Research: docs/research/2026-08-13-confirm-and-weenie-error-display.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
fc62cb6397
commit
67fe754dd6
15 changed files with 1133 additions and 50 deletions
|
|
@ -2858,7 +2858,24 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
// an allegiance member, so the allegiance-profile accessors
|
||||
// above cannot name them).
|
||||
ResolveWorldObjectName: guid => _bindings.Inventory.Objects.Get(guid)?.GetAppropriateName(),
|
||||
ShowConfirmation: (message, completed) => ShowConfirmation(message, completed)),
|
||||
ShowConfirmation: (message, completed) => ShowConfirmation(message, completed),
|
||||
// Swear/Break/Kick confirmation sentences: the 0x23000001
|
||||
// templates' PLAYER slot filled at click time (2026-08-13
|
||||
// confirm/weenie-error research §1.4 — the AD-85 dangling
|
||||
// "Do you wish to swear to " fix).
|
||||
ResolvePlayerTemplate: (key, playerName) =>
|
||||
{
|
||||
lock (_bindings.Assets.DatLock)
|
||||
{
|
||||
return fellowshipStrings.ResolveTemplate(
|
||||
0x23000001u,
|
||||
key,
|
||||
new Dictionary<uint, string>
|
||||
{
|
||||
[Layout.DatStringResolver.PlayerVariable] = playerName,
|
||||
});
|
||||
}
|
||||
}),
|
||||
Friends: _bindings.Social.Friends,
|
||||
Squelch: _bindings.Social.Squelch,
|
||||
TemplateResolver: TemplateResolver,
|
||||
|
|
@ -2978,9 +2995,37 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
}
|
||||
|
||||
DialogFactory = new RetailDialogFactory(Host.Root, CreateLayout);
|
||||
// Types 1/4 carry ACE's bare player name; retail's client wraps it
|
||||
// via the local StringTable templates (single PLAYER variable,
|
||||
// token-free — 2026-08-13 confirm/weenie-error research §1).
|
||||
var confirmationStrings = new DatStringResolver(_bindings.Assets.Dats);
|
||||
string? ComposeConfirmation(uint type, string bareName)
|
||||
{
|
||||
string? key = type switch
|
||||
{
|
||||
// gmAllegianceUI::RecvNotice_SwearAllegiance
|
||||
1u => "ID_Allegiance_AcceptSwearConfirmation",
|
||||
// gmFellowshipUI's incoming FellowshipRequest
|
||||
4u => "ID_Fellowship_FellowshipRequest",
|
||||
_ => null,
|
||||
};
|
||||
if (key is null)
|
||||
return null;
|
||||
lock (_bindings.Assets.DatLock)
|
||||
{
|
||||
return confirmationStrings.ResolveTemplate(
|
||||
0x23000001u,
|
||||
key,
|
||||
new Dictionary<uint, string>
|
||||
{
|
||||
[DatStringResolver.PlayerVariable] = bareName,
|
||||
});
|
||||
}
|
||||
}
|
||||
_gameplayConfirmationController = new GameplayConfirmationController(
|
||||
DialogFactory,
|
||||
_bindings.Confirmations.SendResponse);
|
||||
_bindings.Confirmations.SendResponse,
|
||||
ComposeConfirmation);
|
||||
_itemConfirmationController = new RetailItemConfirmationController(
|
||||
DialogFactory,
|
||||
ItemInteraction);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue