Back to Black Site Map Editor
SOURCE / PINNED RELEASE

Made of little things.

Black Site Map Editor

Release
32a57733b7e9…
Author-recorded commit
3f54890f542f…
License
LICENSE
Author’s source reference
nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.shakespeare.diy%2F/black-site-map-editor

Archive hash verified: 7a4b1abbac7db5b0…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

src/help-tutorial.ts
import { html, type TemplateResult } from 'lit';
import { MAP_COLORS } from './map-renderer';

export type TutorialStep = { id: string; title: string; body: TemplateResult };

// Markup helpers. Labels match the editor's own buttons so players can find them.
const ui = (label: string) => html`<span class="ui-chip">${label}</span>`;
const key = (...keys: string[]) => keys.map((k, i) => html`${i ? '+' : ''}<kbd>${k}</kbd>`);
const tip = (content: unknown) => html`<p class="notice">${content}</p>`;
const marker = (color: string, letter: string, label: TemplateResult) =>
    html`<li>
        <span class="help-marker" style="--marker:${color}">${letter}</span><span>${label}</span>
    </li>`;

export const tutorialSteps: TutorialStep[] = [
    {
        id: 'welcome',
        title: 'Welcome',
        body: html` <p>
                This editor builds maps for Black Site: the ground, buildings, cover, guards and
                loot that players fight through.
            </p>
            <ul>
                <li><b>Centre:</b> your map. Everything you place appears here.</li>
                <li>
                    <b>Left:</b> the map tools, grouped into Terrain, Structures, Cover &amp;
                    supplies and Mission.
                </li>
                <li><b>Right:</b> details for the object you selected, plus the Map Check.</li>
                <li>
                    <b>Top bar:</b> ${ui('New')} ${ui('Maps')} ${ui('Settings')} ${ui('Undo')}
                    ${ui('Redo')} ${ui('Save draft')} ${ui('Publish')}.
                </li>
            </ul>
            ${tip(html`On a phone, the ${ui('Map')} ${ui('Tools')} ${ui('Details')} tabs switch between these areas.`)}
            <p>
                Use ${ui('Next')} to walk through the basics, or jump to any step from the list.
            </p>`,
    },
    {
        id: 'navigate',
        title: 'Moving around',
        body: html` <ul>
                <li>
                    ${ui('−')} and ${ui('+')} zoom out and in. The mouse wheel zooms towards the
                    pointer.
                </li>
                <li>${ui('Fit')} shows the whole map again.</li>
                <li>
                    Choose ${ui('Pan map')} and drag to slide the map. With a mouse, you can also
                    drag with the right or middle button using any tool.
                </li>
                <li>${ui('Grid')} shows or hides the tile grid.</li>
            </ul>
            ${tip('The bottom-right corner of the map toolbar shows the tile under your pointer and the map size.')}`,
    },
    {
        id: 'terrain',
        title: 'Ground & terrain',
        body: html` <p>Terrain shapes where players can walk and how the map looks.</p>
            <ul>
                <li>${ui('Water')} blocks movement. Use it for rivers, harbours and moats.</li>
                <li>${ui('Pavement')} lays hard ground for yards and lots.</li>
                <li>${ui('Road')} draws roads in the map's road colour.</li>
                <li>Anything you leave unpainted is open ground in the map's terrain style.</li>
            </ul>
            <p>
                <b>To paint:</b> pick a tool, press on the map and drag. A gold box previews the
                rectangle you are drawing. Let go to place it.
            </p>
            ${tip('Change the base terrain, ground colour and road colour in Settings.')}`,
    },
    {
        id: 'structures',
        title: 'Structures',
        body: html` <ul>
                <li>${ui('Wall')} draws solid walls that block movement.</li>
                <li>
                    ${ui('Building')} drags out a building with a floor, outer walls and one door.
                    Buildings are at least 3 × 3 tiles.
                </li>
            </ul>
            <p>
                <b>Doors and rooms:</b> first select a building with ${ui('Select / move')}. Then:
            </p>
            <ul>
                <li>
                    ${ui('Building door')} adds another door on that building's <b>outside edge</b>.
                </li>
                <li>${ui('Interior wall')} splits the inside into rooms.</li>
            </ul>
            ${tip('If a door will not place, check that it sits on the outer wall of the selected building.')}`,
    },
    {
        id: 'cover',
        title: 'Cover & supplies',
        body: html` <p>Cover blocks movement and gives players something to hide behind.</p>
            <ul>
                <li>
                    ${ui('Container')}: shipping containers. Pick their colour with
                    <b>Container color</b> in the tool panel before drawing.
                </li>
                <li>${ui('Tank (3×3)')}: a round storage tank. Click once to place it.</li>
                <li>
                    ${ui('Pipe')} ${ui('Crate')} ${ui('Wreck')} ${ui('Sandbag')}: smaller cover.
                    Drag to fill an area.
                </li>
            </ul>`,
    },
    {
        id: 'mission',
        title: 'Mission setup',
        body: html` <p>
                These markers set the map's mission: where players start, where they escape, and
                what stands in the way.
            </p>
            <ul class="help-legend">
                ${marker(MAP_COLORS.insertion, 'I', html`<b>Insertion</b>: where players start. ${ui('Insertion')} moves it.`)}
                ${marker(MAP_COLORS.exfil, 'H', html`<b>Extraction</b>: where players escape. ${ui('Extraction')} moves it.`)}
                ${marker(MAP_COLORS.enemy, 'E', html`<b>Guard</b>: an enemy standing watch. Tick <b>Patrolling guards</b> first to place patrols (shown as P).`)}
                ${marker(MAP_COLORS.cache, 'C', html`<b>Loot cache</b>: pick <b>Cache contents</b> first: random loot, a weapon cache (shown as W) or starter supplies.`)}
            </ul>
            ${tip('Every map has exactly one insertion and one extraction. You can move them, but not delete them.')}`,
    },
    {
        id: 'editing',
        title: 'Selecting & editing',
        body: html` <ul>
            <li>
                Choose ${ui('Select / move')} and click an object to select it. It gets a gold
                outline.
            </li>
            <li>
                Drag a selected object to move it, or use the arrow keys (hold Shift to move 5
                tiles).
            </li>
            <li>
                The <b>Selected object</b> panel shows plain settings for it. Change them, then
                press ${ui('Apply changes')}.
            </li>
            <li>${ui('Move selected')} shifts it by an exact number of tiles across and down.</li>
            <li>
                ${ui('Delete')} or ${key('Delete')} removes it. ${ui('Erase object')} removes
                whatever you click.
            </li>
            <li>
                <b>Objects &amp; layers</b> lists every object of one type, so you can find small or
                hidden ones.
            </li>
        </ul>`,
    },
    {
        id: 'check',
        title: 'Undo & route check',
        body: html` <ul>
                <li>
                    ${ui('Undo')} (${key('Ctrl', 'Z')}) and ${ui('Redo')}
                    (${key('Ctrl', 'Shift', 'Z')}) step back and forward through your changes.
                </li>
                <li>
                    ${ui('Check route')} makes sure players can walk from insertion to extraction.
                </li>
            </ul>
            <p>
                The result appears under <b>Map check</b> on the right. If something is wrong, it
                tells you what to fix, for example:
            </p>
            <ul>
                <li>
                    <i>Clear a path from insertion to extraction.</i> Open a gap in walls or water.
                </li>
                <li>
                    <i>Move insertion, extraction, guards or caches onto open ground.</i> A marker
                    is sitting on a wall or in water.
                </li>
            </ul>
            ${tip('A map must pass the route check before it can be published.')}`,
    },
    {
        id: 'settings',
        title: 'Map settings',
        body: html` <p>${ui('Settings')} holds everything about the map as a whole:</p>
            <ul>
                <li>
                    <b>Map name</b> and <b>Briefing</b>: what players see when choosing the map.
                </li>
                <li>
                    <b>Width</b> and <b>Height</b>, then ${ui('Resize grid')}. Move objects inside
                    the new size first.
                </li>
                <li><b>Terrain</b>, <b>Ground</b> and <b>Road</b> colours, and road markings.</li>
                <li>
                    <b>Extra scenery &amp; enemies</b>: random buildings, clutter and extra guards
                    and caches added each time the game starts.
                </li>
                <li>
                    <b>Map files</b>: ${ui('Download map')} saves a backup file, and you can open a
                    map file from your device.
                </li>
            </ul>`,
    },
    {
        id: 'saving',
        title: 'Saving your work',
        body: html` <ul>
                <li>
                    ${ui('Save draft')} keeps your work in progress inside the host. A
                    <b>*</b> after the map name means there are unsaved changes.
                </li>
                <li>
                    To come back later, open ${ui('Maps')} and choose ${ui('Open saved draft')}.
                </li>
                <li>
                    Drafts are kept separately for each account, so switching accounts shows that
                    account's draft.
                </li>
            </ul>
            ${tip('If saving drafts is unavailable in your host, use Settings → Map files → Download map to keep a backup.')}`,
    },
    {
        id: 'publishing',
        title: 'Publishing',
        body: html` <ol>
                <li>Sign in through the host. The editor never sees your private keys.</li>
                <li>Run ${ui('Check route')} and fix any problems.</li>
                <li>
                    Press ${ui('Publish')}. For a map you already published, the button reads
                    ${ui('Update map')}.
                </li>
                <li>Confirm. Your host may ask you to approve sharing.</li>
            </ol>
            <p>
                Published maps are public. Other players can find them in the game and in this
                editor.
            </p>
            ${tip('Settings → Sharing & credits lets you add notes, credits and tags before you publish.')}`,
    },
    {
        id: 'library',
        title: 'Maps & remixing',
        body: html` <p>${ui('Maps')} opens the maps library:</p>
            <ul>
                <li>
                    ${ui('My maps')}: your published maps. ${ui('Edit')} opens one for changes;
                    ${ui('Delete')} removes it from your published maps.
                </li>
                <li>${ui('Community')}: maps by other players.</li>
                <li>
                    ${ui('Built-in templates')}: the game's own maps, ready to use as a starting
                    point.
                </li>
            </ul>
            <p>
                <b>Remix</b> makes your own copy of any map. Remixes always credit the original
                creator, and publishing one never changes their map.
            </p>
            ${tip("You can only edit maps you published yourself. For anyone else's map, use Remix.")}`,
    },
    {
        id: 'reference',
        title: 'Quick reference',
        body: html` <table class="help-table">
                <tr>
                    <th>Action</th>
                    <th>Mouse &amp; keys</th>
                    <th>Touch</th>
                </tr>
                <tr>
                    <td>Draw a rectangle</td>
                    <td>Drag with a tool</td>
                    <td>Drag with a tool</td>
                </tr>
                <tr>
                    <td>Pan</td>
                    <td>Right or middle drag, or Pan map</td>
                    <td>Pan map, then drag</td>
                </tr>
                <tr>
                    <td>Zoom</td>
                    <td>Mouse wheel, − / +</td>
                    <td>− / + buttons</td>
                </tr>
                <tr>
                    <td>Show whole map</td>
                    <td>Fit</td>
                    <td>Fit</td>
                </tr>
                <tr>
                    <td>Move selected</td>
                    <td>
                        Drag, or ${key('←')}${key('↑')}${key('↓')}${key('→')} (${key('Shift')} for 5
                        tiles)
                    </td>
                    <td>Drag, or Move selected</td>
                </tr>
                <tr>
                    <td>Delete selected</td>
                    <td>${key('Delete')}</td>
                    <td>Delete button</td>
                </tr>
                <tr>
                    <td>Undo / redo</td>
                    <td>${key('Ctrl', 'Z')} / ${key('Ctrl', 'Shift', 'Z')}</td>
                    <td>Undo / Redo</td>
                </tr>
                <tr>
                    <td>Open this help</td>
                    <td>${key('F1')}</td>
                    <td>Help</td>
                </tr>
                <tr>
                    <td>All keyboard shortcuts</td>
                    <td>${key('Shift', '?')}</td>
                    <td></td>
                </tr>
            </table>
            ${tip('Every tool also has a single-letter key. Hover a tool to see it, or press Shift + ? for the full list. Your host may change these keys.')}`,
    },
];