using System; using System.Collections.Generic; using System.IO; using AcDream.App.UI.Layout; using DatReaderWriter; using DatReaderWriter.Options; namespace AcDream.App.Tests.UI.Layout; /// /// 2026-08-17 morning gate finding 3 installed-DAT pins: the map town-hotspot /// template's OWN authored tooltip locator + rollover-highlight mechanism, /// re-derived after the user's retail screenshot (green marker highlight on /// hover, parchment-banner tooltip in a special font) refuted the earlier /// "template authors no locator of its own" recon. Follows /// 's [InstalledDatFact] pattern. /// /// /// The derivation chain (raw-DAT-dumped + MapHousePanelSlotProbeTests): /// m_pMap (0x100001EC) authors P0x47=0x100001F0/ /// P0x48=0x21000026 — the note CONSTRUCTION template /// (gmMapUI::AddMapNote @0x004a1bb0's CreateChildElement args). /// The template's DirectState then authors the note's OWN tooltip popup /// locator P0x47=0x10000398/P0x48=0x21000041, a zero /// per-element tooltip delay (P0x50=0.0), P0x4B TooltipOn, and /// P0x13 RolloverEnabled; its Normal/Normal_rollover /// states are PassToChildren descriptors driving the highlight child /// 0x100001F1 (base 0x100002B7@0x21000042 — a /// four-piece frame of pure-green 0x06004CC9, byte-decoded /// A=FF R=00 G=FF B=00) via per-state P0x3B. /// /// public sealed class MapNoteLiveDatTests { private static string DatDirectory => System.Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR") ?? Path.Combine( System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile), "Documents", "Asheron's Call"); private const uint TemplateLayoutId = 0x21000026u; private const uint TemplateElementId = 0x100001F0u; private const uint HighlightChildId = 0x100001F1u; private const uint MapNoteSkinRootId = 0x10000398u; private const uint TooltipCatalogLayoutId = 0x21000041u; private const uint TooltipTextChildId = 0x10000396u; private const uint MapNoteFontDid = 0x40000015u; private const uint GenericSkinFontDid = 0x40000002u; private const uint GreenFrameSurfaceId = 0x06004CC9u; [InstalledDatFact] public void HotspotTemplate_AuthorsItsOwnPopupLocator_ZeroDelay_AndRollover() { using var dats = new DatCollection(DatDirectory, DatAccessType.Read); ElementInfo? template = LayoutImporter.ImportInfos(dats, TemplateLayoutId, TemplateElementId); Assert.NotNull(template); // The note's own popup locator — NOT the generic shared skin the // pre-fix code hardcoded. Assert.Equal(MapNoteSkinRootId, template!.TooltipRootElementId); Assert.Equal(TooltipCatalogLayoutId, template.TooltipLayoutDid); Assert.True(template.TooltipEnabled); // P0x4B Assert.True(template.TooltipDelaySeconds.HasValue); // P0x50 authored Assert.Equal(0f, template.TooltipDelaySeconds!.Value); // = 0.0 // P0x13 RolloverEnabled — drives UiButtonStateMachine's // NormalRollover request on pointer-over. Assert.True(template.TryGetEffectiveBool(0x13u, out bool rollover) && rollover); // The two PassToChildren cascade descriptors. Assert.True(template.States.TryGetValue(1u, out UiStateInfo? normal)); Assert.True(template.States.TryGetValue(2u, out UiStateInfo? normalRollover)); Assert.Equal("Normal", normal!.Name); Assert.Equal("Normal_rollover", normalRollover!.Name); Assert.True(normal.PassToChildren); Assert.True(normalRollover.PassToChildren); } [InstalledDatFact] public void HotspotTemplate_HighlightChild_FlipsPerStateInvisible_WithGreenFrameMedia() { using var dats = new DatCollection(DatDirectory, DatAccessType.Read); ElementInfo? template = LayoutImporter.ImportInfos(dats, TemplateLayoutId, TemplateElementId); Assert.NotNull(template); ElementInfo highlight = Assert.Single(template!.Children, c => c.Id == HighlightChildId); // Per-state P0x3B: hidden in Normal, shown in Normal_rollover. Assert.True(highlight.States.TryGetValue(1u, out UiStateInfo? normal)); Assert.True(highlight.States.TryGetValue(2u, out UiStateInfo? rollover)); Assert.True(normal!.Properties.TryGetValue(0x3Bu, out var normalInvisible)); Assert.True(rollover!.Properties.TryGetValue(0x3Bu, out var rolloverInvisible)); Assert.Equal(UiPropertyKind.Bool, normalInvisible.Kind); Assert.Equal(UiPropertyKind.Bool, rolloverInvisible.Kind); Assert.True(normalInvisible.BoolValue); Assert.False(rolloverInvisible.BoolValue); // The base-chain frame (0x100002B7@0x21000042): four edge pieces, // every one drawing the pure-green line surface 0x06004CC9. Assert.Equal(4, highlight.Children.Count); foreach (ElementInfo edge in highlight.Children) { Assert.True(edge.StateMedia.TryGetValue("", out var media)); Assert.Equal(GreenFrameSurfaceId, media.File); } } [InstalledDatFact] public void MapNoteSkin_TextChild_FontsTheSpecialFont_UnlikeTheGenericSkins() { using var dats = new DatCollection(DatDirectory, DatAccessType.Read); // The four popup skins in 0x21000041 share structure and the SAME // incorporated text child id — but each skin's child-table merge // gives 0x10000396 its own effective font, and the map-note skin // 0x10000398 is the odd one out (0x40000015 vs 0x40000002) — the // "special/blackletter-style font" of the user's retail screenshot. var fonts = new Dictionary(); foreach (uint skinId in new[] { 0x10000487u, 0x10000395u, 0x10000397u, MapNoteSkinRootId }) { ElementInfo? skin = LayoutImporter.ImportInfos(dats, TooltipCatalogLayoutId, skinId); Assert.NotNull(skin); ElementInfo text = Assert.Single(skin!.Children, c => c.Id == TooltipTextChildId); fonts[skinId] = text.FontDid; } Assert.Equal(MapNoteFontDid, fonts[MapNoteSkinRootId]); Assert.Equal(GenericSkinFontDid, fonts[0x10000487u]); Assert.Equal(GenericSkinFontDid, fonts[0x10000395u]); Assert.Equal(GenericSkinFontDid, fonts[0x10000397u]); } }