Fix area overlays not showing interactable elements on map image

Three issues prevented the interactive map from fully showing
draggable/editable entity markers:

1. overflow: hidden on .map-area-section clipped markers and popups
   at the edges of the map image, making them invisible/unclickable.
   Moved border-radius clipping to the header element instead.

2. coord_events (step triggers) were missing from both the legend
   and the interactive map markers despite having x/y positions.
   Added trigger markers with edit/delete popup actions.

3. Trainers had their own marker color (red) but were lumped with
   NPCs in the legend. Split them into a separate legend entry.

https://claude.ai/code/session_01MLsBVj2fWq11mhAQy2ewMm
This commit is contained in:
Claude 2026-03-21 19:15:16 +00:00
parent 3ff231e006
commit 2a1d8368d6
No known key found for this signature in database
3 changed files with 22 additions and 4 deletions

View File

@ -2564,9 +2564,11 @@ function buildMapPreviewSection(map) {
const dirName = map._dirName;
// Collect all plottable entities
const npcs = (map.object_events || []).filter(e =>
const allPeople = (map.object_events || []).filter(e =>
!(e.graphics_id || '').includes('ITEM_BALL') && !(e.graphics_id || '').includes('BERRY_TREE')
);
const trainers = allPeople.filter(e => e.trainer_type && e.trainer_type !== 'TRAINER_TYPE_NONE');
const npcs = allPeople.filter(e => !e.trainer_type || e.trainer_type === 'TRAINER_TYPE_NONE');
const itemBalls = getMapItemBalls(map);
const hiddenItems = getMapHiddenItems(map);
const warps = map.warp_events || [];
@ -2576,10 +2578,12 @@ function buildMapPreviewSection(map) {
// Legend items
const legendItems = [];
if (npcs.length) legendItems.push(`<span class="imap-legend-item"><span class="imap-legend-dot imap-dot-npc"></span> NPCs (${npcs.length})</span>`);
if (trainers.length) legendItems.push(`<span class="imap-legend-item"><span class="imap-legend-dot imap-dot-trainer"></span> Trainers (${trainers.length})</span>`);
if (itemBalls.length) legendItems.push(`<span class="imap-legend-item"><span class="imap-legend-dot imap-dot-item"></span> Items (${itemBalls.length})</span>`);
if (hiddenItems.length) legendItems.push(`<span class="imap-legend-item"><span class="imap-legend-dot imap-dot-hidden"></span> Hidden (${hiddenItems.length})</span>`);
if (warps.length) legendItems.push(`<span class="imap-legend-item"><span class="imap-legend-dot imap-dot-warp"></span> Doors (${warps.length})</span>`);
if (signs.length) legendItems.push(`<span class="imap-legend-item"><span class="imap-legend-dot imap-dot-sign"></span> Signs (${signs.length})</span>`);
if (coordEvents.length) legendItems.push(`<span class="imap-legend-item"><span class="imap-legend-dot imap-dot-trigger"></span> Triggers (${coordEvents.length})</span>`);
return `
<div class="map-area-section">
@ -2658,6 +2662,12 @@ function initInteractiveMap(map) {
entities.push({ type: 'warp', x: evt.x, y: evt.y, warpIdx: i, evt, label: dest || 'Warp' });
});
// Coord events (step triggers)
(map.coord_events || []).forEach((evt, i) => {
const scriptShort = (evt.script || '').split('_EventScript_').pop().replace(/_/g, ' ');
entities.push({ type: 'trigger', x: evt.x, y: evt.y, coordIdx: i, evt, label: scriptShort || 'Trigger' });
});
for (const ent of entities) {
const marker = document.createElement('div');
marker.className = `imap-marker imap-marker-${ent.type}`;
@ -2673,7 +2683,7 @@ function initInteractiveMap(map) {
marker.dataset.y = ent.y;
// Icon inside marker
const icons = { npc: '\u263A', trainer: '\u2694', item: '\u2666', hidden: '\u2733', warp: '\uD83D\uDEAA', sign: '\uD83D\uDCCB' };
const icons = { npc: '\u263A', trainer: '\u2694', item: '\u2666', hidden: '\u2733', warp: '\uD83D\uDEAA', sign: '\uD83D\uDCCB', trigger: '\u25CE' };
marker.innerHTML = icons[ent.type] || '\u2022';
// Click to open edit menu
@ -2795,6 +2805,11 @@ function openMarkerMenu(entity, map, markerEl) {
`;
} else if (entity.type === 'sign') {
buttonsHtml = `<span style="font-size:11px;color:var(--text-dim)">Sign at (${entity.x}, ${entity.y})</span>`;
} else if (entity.type === 'trigger') {
buttonsHtml = `
<button class="btn btn-sm" onclick="editCoordEvent('${escAttr(dirName)}', ${entity.coordIdx}); this.closest('.imap-popup').remove()">Edit</button>
<button class="btn btn-sm btn-danger" onclick="deleteCoordEvent('${escAttr(dirName)}', ${entity.coordIdx}); this.closest('.imap-popup').remove()">Delete</button>
`;
}
popup.innerHTML = `

View File

@ -815,12 +815,12 @@ tbody tr:last-child td { border-bottom: none; }
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
}
.map-area-section-header {
padding: 14px 20px;
background: var(--bg-hover);
border-bottom: 1px solid var(--border);
border-radius: var(--radius) var(--radius) 0 0;
display: flex;
align-items: center;
justify-content: space-between;
@ -1843,6 +1843,7 @@ tbody tr:last-child td { border-bottom: none; }
.imap-marker-hidden { background: var(--purple); color: #fff; }
.imap-marker-warp { background: var(--cyan); color: #fff; font-size: 9px; }
.imap-marker-sign { background: var(--orange); color: #fff; font-size: 9px; }
.imap-marker-trigger { background: var(--green, #4caf50); color: #fff; font-size: 9px; }
.imap-legend {
display: flex;
@ -1869,6 +1870,7 @@ tbody tr:last-child td { border-bottom: none; }
.imap-dot-warp { background: var(--cyan); }
.imap-dot-sign { background: var(--orange); }
.imap-dot-trainer { background: var(--red); }
.imap-dot-trigger { background: var(--green, #4caf50); }
.imap-hint {
text-align: center;

View File

@ -153,8 +153,9 @@ const markerInfo = await page.evaluate((dir) => {
).length;
const warps = (map.warp_events || []).length;
const bgs = (map.bg_events || []).length;
const coords = (map.coord_events || []).length;
const markerEls = document.querySelectorAll('.imap-marker');
return { expected: npcs + warps + bgs, actual: markerEls.length };
return { expected: npcs + warps + bgs + coords, actual: markerEls.length };
}, testMapDir);
assert(markerInfo.actual === markerInfo.expected, `Marker count matches entities (${markerInfo.actual}/${markerInfo.expected})`);