feat(ui): Campaign OP slice OP3 — Options panel shell, open paths, Gameplay tab
Mounts retail's Options panel (LayoutDesc 0x2100002B resolved through host 0x2100006E slot 0x1000018D, gmPanelUI key 10) via the same catalog-import pattern CharacterController already validates, registered through RetailPanelUiController so it shares retail's "one active gmPanelUI child" mutual exclusion with every other sibling panel for free. F11 and the toolbar's options button (0x1000019B, already authoring panel id 10) both now open it; the close button fires the same ToggleOptionsPanel action. OptionPageModel (OptionPage/BoolOptionRow) ports retail's exact Apply/Reset/Defaults/visibility semantics from UIOption_Checkbox/PlayerOptionPage — LED clicks apply live immediately, Apply commits every row unconditionally + flushes the batched blob, Reset reverts only Changed rows, Defaults restores without committing, and tab-switch/window-hide revert uncommitted edits. Wired for all four tabs; this slice registers real rows on none of them (Gameplay authentically has none — a pure button list). UiTabPanel gains an ActivePageChanged event so the page model can hook every tab transition, including the initial default-tab activation. The seven Gameplay-tab buttons: Exit Game reuses the existing graceful window-close path; Exit to Character Selection gets retail's confirmation dialog and byte-verified mid-air refusal but still behaves as Exit Game (AD-74 — no pre-world character-select flow exists); Configure Keyboard and In-Game Help Files are inert this slice (AD-76 for Help — the plugin retail depends on doesn't exist); Urgent Assistance/Report Abuse short-circuit to their own byte-verified failure text through the interface-text seam instead of ShellExecute against a dead URL (AD-75); Use Mouse Turning Settings runs the pure MouseTurningSettingsMacro port, persisting five new CameraTurningSettings preferences and sending PlayerOption.UseMouseTurning — TS-74 records that acdream has no persistent mouse-turning camera mode for the bit to drive yet. Full Release suite: 12,918 passed / 4 skipped / 0 failed (baseline 12,871/4/0 — only new tests added). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
5242de9f15
commit
9d26ecc623
27 changed files with 25696 additions and 8 deletions
|
|
@ -123,4 +123,18 @@ public static class ClientTextRefusals
|
|||
/// refusal lands in the chat transcript, not the SpewBox.
|
||||
/// </summary>
|
||||
public const string TurbineChatUnavailable = "Turbine chat is not available.";
|
||||
|
||||
/// <summary>
|
||||
/// Campaign OP slice OP3 (2026-08-11): retail
|
||||
/// <c>gmGamePlayUI::UseTime @0x004EA3A0</c>'s per-frame end-session drain
|
||||
/// refuses to log off while the player is airborne
|
||||
/// (<c>transient_state & 1</c> — the on-contact/ON_WALKABLE bit) and
|
||||
/// raises this line instead of proceeding to
|
||||
/// <c>CPlayerSystem::LogOffCharacter</c>. Byte-read UTF-16LE off the
|
||||
/// PDB-paired binary at VA <c>0x007C29C0</c> (pushed at
|
||||
/// <c>0x004EA481</c>). Sent via <c>ECM_UI::SendNotice_DisplayStringInfo
|
||||
/// (0x1A, ...)</c> — the SAME <c>RetailLogTextType.ClientLocal</c>
|
||||
/// SpewBox-only channel every other refusal in this file uses.
|
||||
/// </summary>
|
||||
public const string CantLogOffMidAir = "Cannot log off while in mid-air.";
|
||||
}
|
||||
|
|
|
|||
119
src/AcDream.Core/Chat/OptionsPanelText.cs
Normal file
119
src/AcDream.Core/Chat/OptionsPanelText.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
using System.Globalization;
|
||||
|
||||
namespace AcDream.Core.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// Byte-verified retail string literals for the Gameplay Options tab's
|
||||
/// button family (Campaign OP slice OP3, 2026-08-11) —
|
||||
/// <c>docs/research/2026-08-10-keyboard-config-and-gameplay-tab.md</c>
|
||||
/// §4.4 (Use Mouse Turning Settings) and §4.1/§4.2 (Urgent Assistance /
|
||||
/// Report Abuse). Every literal was recovered from the PDB-paired binary
|
||||
/// <c>C:\Users\erikn\Downloads\acclient.exe</c> by a push-imm32 sweep of the
|
||||
/// cited VA range, same discipline as <see cref="ClientTextRefusals"/>.
|
||||
/// </summary>
|
||||
public static class OptionsPanelText
|
||||
{
|
||||
/// <summary>
|
||||
/// <c>gmConfigUI::SetMouseTurningDefaults @0x0049E8F0</c>, format string
|
||||
/// VA <c>0x007A8A70</c>: <c>'Camera Stiffness was changed from %f to the
|
||||
/// mouse turning default of %f.'</c>. <paramref name="from"/>/
|
||||
/// <paramref name="to"/> render with 6 fractional digits, matching
|
||||
/// retail's default <c>printf %f</c> precision.
|
||||
/// </summary>
|
||||
public static string CameraStiffnessChanged(float from, float to) => string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Camera Stiffness was changed from {0} to the mouse turning default of {1}.",
|
||||
from.ToString("F6", CultureInfo.InvariantCulture),
|
||||
to.ToString("F6", CultureInfo.InvariantCulture));
|
||||
|
||||
/// <summary>
|
||||
/// Same site, format string VA <c>0x007A8A20</c>: <c>'Camera Adjustment
|
||||
/// was changed from %f to the mouse turning default of %f.'</c>.
|
||||
/// </summary>
|
||||
public static string CameraAdjustmentChanged(float from, float to) => string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Camera Adjustment was changed from {0} to the mouse turning default of {1}.",
|
||||
from.ToString("F6", CultureInfo.InvariantCulture),
|
||||
to.ToString("F6", CultureInfo.InvariantCulture));
|
||||
|
||||
/// <summary>
|
||||
/// Same site, format string VA <c>0x007A89D0</c>: <c>'Mouse Sensitivity
|
||||
/// was changed from %f to the mouse turning default of %f.'</c>.
|
||||
/// </summary>
|
||||
public static string MouseSensitivityChanged(float from, float to) => string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Mouse Sensitivity was changed from {0} to the mouse turning default of {1}.",
|
||||
from.ToString("F6", CultureInfo.InvariantCulture),
|
||||
to.ToString("F6", CultureInfo.InvariantCulture));
|
||||
|
||||
/// <summary>
|
||||
/// Same site, VA <c>0x007A8980</c>, byte-verified literal (no format
|
||||
/// specifiers — retail hardcodes TRUE/FALSE for this one bool pair):
|
||||
/// <c>'Align To Slope was changed from TRUE to the mouse turning default
|
||||
/// of FALSE.'</c>. Only fires when the current value IS true (the
|
||||
/// macro's own condition, §4.4) so the "from TRUE" half is always
|
||||
/// accurate.
|
||||
/// </summary>
|
||||
public const string AlignToSlopeChanged =
|
||||
"Align To Slope was changed from TRUE to the mouse turning default of FALSE.";
|
||||
|
||||
/// <summary>
|
||||
/// Same site, VA <c>0x007A8928</c>: <c>'Invert Mouselook Axes was
|
||||
/// changed from FALSE to the mouse turning default of TRUE.'</c>. Only
|
||||
/// fires when the current value IS false.
|
||||
/// </summary>
|
||||
public const string InvertMouseLookAxesChanged =
|
||||
"Invert Mouselook Axes was changed from FALSE to the mouse turning default of TRUE.";
|
||||
|
||||
/// <summary>
|
||||
/// Same site, VA <c>0x007A88D0</c>: <c>'Turn to Face Camera was changed
|
||||
/// from FALSE to the mouse turning default of TRUE.'</c>. This is the
|
||||
/// Config-tab UI LABEL for <c>PlayerOption.UseMouseTurning</c> — the
|
||||
/// option itself is named "Use Mouse Turning" in code, "Turn to Face
|
||||
/// Camera" in the string table. Only fires when the current value IS
|
||||
/// false.
|
||||
/// </summary>
|
||||
public const string TurnToFaceCameraChanged =
|
||||
"Turn to Face Camera was changed from FALSE to the mouse turning default of TRUE.";
|
||||
|
||||
/// <summary>
|
||||
/// Urgent Assistance (element <c>0x10000206</c>) /
|
||||
/// Report Abuse (element <c>0x10000207</c>) — retail's
|
||||
/// <c>ShellExecuteA</c> failure <c>MessageBoxA</c> body, byte-verified at
|
||||
/// VA <c>0x007A81E0</c> (Urgent) / <c>0x007A8128</c> (Abuse):
|
||||
/// <c>'An error occurred while trying to launch your web browser. (Error
|
||||
/// code %d)\nThe web site to submit an urgent assistance request /
|
||||
/// abuse report is listed below. Please go there to complete your
|
||||
/// request.\n%s\n'</c>, title <c>"Asheron's Call Error"</c> (VA
|
||||
/// <c>0x00794078</c>).
|
||||
///
|
||||
/// <para>
|
||||
/// D5 adaptation (register row, same commit): acdream never attempts
|
||||
/// <c>ShellExecuteA</c> against the dead <c>support.turbine.com</c>
|
||||
/// endpoint (§0 of the research doc — both EoR buttons already point at
|
||||
/// a URL that is not live today), so there is no real Win32 error code
|
||||
/// to interpolate and the <c>(Error code %d)</c> clause is dropped; the
|
||||
/// trailing <c>%s</c> URL substitution is KEPT verbatim (the byte-verified
|
||||
/// URL below) so the user can still copy it manually, matching retail's
|
||||
/// own intent for that clause. Delivered through the interface-text
|
||||
/// seam (<c>RetailLogTextType.ClientLocal</c>) rather than a native
|
||||
/// <c>MessageBoxA</c> popup — see the register row for the short-circuit.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public const string SupportUrl =
|
||||
"http://support.turbine.com/ics/support/ticketnewwizard.asp?style=classic";
|
||||
|
||||
public static string UrgentAssistanceUnavailable => string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"An error occurred while trying to launch your web browser.\n"
|
||||
+ "The web site to submit an urgent assistance request is listed below. "
|
||||
+ "Please go there to complete your request.\n{0}",
|
||||
SupportUrl);
|
||||
|
||||
public static string ReportAbuseUnavailable => string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"An error occurred while trying to launch your web browser.\n"
|
||||
+ "The web site to submit an abuse report is listed below. "
|
||||
+ "Please go there to complete your request.\n{0}",
|
||||
SupportUrl);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue