using AcDream.Content;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Types;
namespace AcDream.App.UI.Layout;
///
/// Campaign OP slice OP5: reads the Chat tab's two opacity-slider defaults from the
/// installed DAT's DBProperties collection — retail
/// UIOption::InqDefaultGameplayOptionProperty @0x004ef8d0's
/// m_propName-bound path, the ONE genuine consumer of that mechanism (the
/// Character tab's 49/50 checkboxes are PlayerOption-bound, not
/// m_propName-bound — see 's own
/// U1 trace for why THAT tab does not use this seam).
///
///
/// Byte-verified recipe (DBCache::GetDIDFromEnum @0x00413940): the outer call
/// site is GetDIDFromEnumStatic(&ret, 0x16, 2) — outer arg2 (0x16)
/// feeds the inner function's arg3 (the SUB-MAP lookup key), outer arg3 (2)
/// feeds arg4 (the MASTER-MAP lookup key FIRST). So:
/// master.ClientEnumToID[2] → subMapDid; subMap.ClientEnumToID[0x16] → DID —
/// i.e. 's own (enumValue, enumCategory)
/// parameter order is (0x16, 2), matching
/// RetailUiRuntime.cs's existing Resolve(dats, 2u, 5u) convention
/// (enumCategory selects the master-map submap FIRST, enumValue indexes it SECOND).
/// Empirically confirmed against the installed DATs: resolves to DID
/// 0x78000001, a 3-entry DBProperties —
/// 0x1000007F (Bitfield64, the Chat filter blocks' shared
/// m_propName — NOT a per-window default; the five blocks' actual defaults are
/// the literal constants gmChatOptionsUI::InitOptions authors per window,
/// ported verbatim in ChatWindowState/),
/// 0x10000080 (Float, 0.5 — Option_DefaultOpacity_Property),
/// 0x10000081 (Float, 1.0 — Option_ActiveOpacity_Property).
///
///
public static class ChatOptionsDatDefaults
{
/// DAT enum-category key for the FIRST (master-map) lookup — see the
/// class doc's byte-verified recipe.
private const uint EnumCategory = 2u;
/// DAT enum-value key for the SECOND (sub-map) lookup.
private const uint EnumValue = 0x16u;
/// Option_DefaultOpacity_Property — the unfocused-window opacity
/// slider's m_propName.
public const uint DefaultOpacityPropertyId = 0x10000080u;
/// Option_ActiveOpacity_Property — the focused-window opacity
/// slider's m_propName.
public const uint ActiveOpacityPropertyId = 0x10000081u;
/// Retail base-constructor fallback (ChatInterface::ChatInterface
/// @0x004F4550) — used only when the DAT read fails (missing DAT entry,
/// corrupt install); the live installed DAT resolves to these exact values today.
public const float FallbackDefaultOpacity = 0.5f;
public const float FallbackActiveOpacity = 1.0f;
///
/// Resolves the two slider defaults from the live DAT. Returns
/// (with both out params set to the retail-constructor
/// fallback) if the DID does not resolve, the DBProperties object is
/// missing, or either property is absent/not a Float — matching this
/// codebase's "degrade to a documented fallback, never invent a value" discipline.
///
public static bool TryRead(
IDatReaderWriter dats, out float defaultOpacity, out float activeOpacity)
{
defaultOpacity = FallbackDefaultOpacity;
activeOpacity = FallbackActiveOpacity;
uint did = RetailDataIdResolver.Resolve(dats, EnumValue, EnumCategory);
if (did == 0u || !dats.Portal.TryGet(did, out DBProperties? props) || props is null)
return false;
bool ok = true;
if (props.Properties.TryGetValue(DefaultOpacityPropertyId, out BaseProperty? d)
&& d is FloatBaseProperty defaultProp)
defaultOpacity = defaultProp.Value;
else
ok = false;
if (props.Properties.TryGetValue(ActiveOpacityPropertyId, out BaseProperty? a)
&& a is FloatBaseProperty activeProp)
activeOpacity = activeProp.Value;
else
ok = false;
return ok;
}
}