Location thumbnails on the map, full-art archive mode, more content
- Map markers now show a tiny thumbnail preview in their tooltip when art exists for that location (same missing-asset-is-fine fallback as character portraits — onerror just removes the broken img). - Two new locations, both free-roam from the start: Möllevångstorget and Malmö universitet (the latter ties into the researcher character's arc). VISITABLE_LOCATION_IDS picks them up automatically since it's derived from the data, not a separate list. - Sällskapet gets a second mode: "Fullständigt arkiv" shows every character's real portrait and bio regardless of story progress (bypassing the usedEventIds lock), and clicking any known portrait opens a lightbox at full size instead of the cropped card thumbnail. - All 9 character portraits are now in and wired (fixed two more filename mismatches along the way: anneli-karin and the rest use hyphens, not underscores, matching what was actually generated). - More content: 2 new location-visit variants each for the two new areas, 6 new Standard events (including a found 1930s photograph that seems to show Lindqvist in a room nobody recognizes), 4 new Kaos events tied to the new locations and existing ones. - Caught and fixed a bug in my own new content before commit: an event's requires.completedEventId pointed at an upgrade id, which can never appear in usedEventIds — switched to a minRitual check that actually gates on the right precondition. Verified: 15/15 tests, clean typecheck and build, and a real headless-browser pass — all 9 map markers present, full-archive mode correctly bypassing locks, and the lightbox opening at full size with a caption. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
aeedf0abb5
commit
899ab72c80
@@ -84,7 +84,11 @@ export function initUI(
|
||||
<button id="characters-close" class="help-close">✕</button>
|
||||
</div>
|
||||
<div class="help-modal-body">
|
||||
<p class="help-flavor" style="margin-bottom:14px;">De som suttit vid bordet. Vissa längre än andra.</p>
|
||||
<div class="archive-toggle" role="group" aria-label="Visningsläge">
|
||||
<button type="button" class="archive-toggle-btn active" data-archive="story">Under spelets gång</button>
|
||||
<button type="button" class="archive-toggle-btn" data-archive="full">Fullständigt arkiv</button>
|
||||
</div>
|
||||
<p class="help-flavor" id="characters-hint" style="margin-bottom:14px;">De som suttit vid bordet. Vissa längre än andra.</p>
|
||||
<div id="characters-grid" class="characters-grid"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -182,6 +186,12 @@ export function initUI(
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="lightbox" class="lightbox">
|
||||
<button id="lightbox-close" class="lightbox-close" aria-label="Stäng">✕</button>
|
||||
<img id="lightbox-img" alt="">
|
||||
<div id="lightbox-caption" class="lightbox-caption"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.getElementById('overlay-btn')!.addEventListener('click', onRestart);
|
||||
@@ -212,6 +222,35 @@ export function initUI(
|
||||
document.getElementById('characters-close')!.addEventListener('click', () => charactersModal.classList.remove('visible'));
|
||||
charactersModal.addEventListener('click', (e) => { if (!charactersInner.contains(e.target as Node)) charactersModal.classList.remove('visible'); });
|
||||
|
||||
document.querySelectorAll<HTMLButtonElement>('.archive-toggle-btn').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.archive-toggle-btn').forEach((b) => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
archiveMode = btn.dataset['archive'] === 'full';
|
||||
document.getElementById('characters-hint')!.textContent = archiveMode
|
||||
? 'Fullständigt arkiv — alla porträtt, oavsett hur långt ni kommit. Klicka för att se dem i fullstorlek.'
|
||||
: 'De som suttit vid bordet. Vissa längre än andra.';
|
||||
renderCharacterGrid(latestState);
|
||||
});
|
||||
});
|
||||
|
||||
const lightbox = document.getElementById('lightbox')!;
|
||||
const lightboxImg = document.getElementById('lightbox-img') as HTMLImageElement;
|
||||
const lightboxCaption = document.getElementById('lightbox-caption')!;
|
||||
document.getElementById('characters-grid')!.addEventListener('click', (e) => {
|
||||
const portrait = (e.target as Element).closest('.character-card:not(.locked) .character-portrait');
|
||||
if (!portrait) return;
|
||||
const card = portrait.closest<HTMLElement>('[data-char]');
|
||||
const img = portrait.querySelector('img');
|
||||
if (!card || !img?.src) return;
|
||||
lightboxImg.src = img.src;
|
||||
lightboxCaption.textContent = card.querySelector('.character-name')?.textContent ?? '';
|
||||
lightbox.classList.add('visible');
|
||||
});
|
||||
document.getElementById('lightbox-close')!.addEventListener('click', () => lightbox.classList.remove('visible'));
|
||||
lightbox.addEventListener('click', (e) => { if (e.target === lightbox) lightbox.classList.remove('visible'); });
|
||||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') lightbox.classList.remove('visible'); });
|
||||
|
||||
// Split the map container: map on top, log below
|
||||
const mapContainer = document.getElementById('map-container')!;
|
||||
mapContainer.style.cssText = 'display:flex;flex-direction:column;overflow:hidden;height:100%;';
|
||||
@@ -228,6 +267,7 @@ export function initUI(
|
||||
}
|
||||
|
||||
let latestState: State | null = null;
|
||||
let archiveMode = false;
|
||||
|
||||
export function renderState(state: State): void {
|
||||
latestState = state;
|
||||
@@ -421,7 +461,7 @@ function renderCharacterGrid(state: State | null): void {
|
||||
const grid = document.getElementById('characters-grid')!;
|
||||
const met = new Set(state?.usedEventIds ?? []);
|
||||
grid.innerHTML = CHARACTERS.map(c => {
|
||||
const known = !c.unlockEventId || met.has(c.unlockEventId);
|
||||
const known = archiveMode || !c.unlockEventId || met.has(c.unlockEventId);
|
||||
if (!known) {
|
||||
return `
|
||||
<div class="character-card locked">
|
||||
|
||||
Reference in New Issue
Block a user