@jjlmoya/utils-tabletop 1.29.0 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/index.ts +2 -0
- package/src/entries.ts +4 -0
- package/src/tests/locale_completeness.test.ts +2 -9
- package/src/tests/tool_validation.test.ts +1 -2
- package/src/tool/rpg-settlement-exploration-map-generator/.keep +1 -0
- package/src/tool/rpg-settlement-exploration-map-generator/bibliography.astro +11 -0
- package/src/tool/rpg-settlement-exploration-map-generator/bibliography.ts +7 -0
- package/src/tool/rpg-settlement-exploration-map-generator/component.astro +66 -0
- package/src/tool/rpg-settlement-exploration-map-generator/controller.ts +231 -0
- package/src/tool/rpg-settlement-exploration-map-generator/dom-views.ts +174 -0
- package/src/tool/rpg-settlement-exploration-map-generator/editor.ts +85 -0
- package/src/tool/rpg-settlement-exploration-map-generator/entry.ts +27 -0
- package/src/tool/rpg-settlement-exploration-map-generator/evaluator.ts +8 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/de.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/en.ts +63 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/es.ts +233 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/fr.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/id.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/it.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/ja.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/ko.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/nl.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/pl.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/pt.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/ru.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/sv.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/tr.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/i18n/zh.ts +152 -0
- package/src/tool/rpg-settlement-exploration-map-generator/index.ts +4 -0
- package/src/tool/rpg-settlement-exploration-map-generator/logic.test.ts +65 -0
- package/src/tool/rpg-settlement-exploration-map-generator/logic.ts +288 -0
- package/src/tool/rpg-settlement-exploration-map-generator/rpg-settlement-exploration-map-generator.css +885 -0
- package/src/tool/rpg-settlement-exploration-map-generator/seo.astro +11 -0
- package/src/tool/rpg-settlement-exploration-map-generator/storage.test.ts +12 -0
- package/src/tool/rpg-settlement-exploration-map-generator/storage.ts +24 -0
- package/src/tool/rpg-settlement-exploration-map-generator/ui.ts +81 -0
- package/src/tools.ts +2 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { EditTool } from './logic';
|
|
2
|
+
|
|
3
|
+
interface CellPoint {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type EditHandler = (point: CellPoint, tool: EditTool) => void;
|
|
9
|
+
|
|
10
|
+
function svgCell(event: MouseEvent, svg: SVGSVGElement): CellPoint | null {
|
|
11
|
+
const point = svg.createSVGPoint();
|
|
12
|
+
point.x = event.clientX;
|
|
13
|
+
point.y = event.clientY;
|
|
14
|
+
const matrix = svg.getScreenCTM();
|
|
15
|
+
if (!matrix) return null;
|
|
16
|
+
const local = point.matrixTransform(matrix.inverse());
|
|
17
|
+
return { x: Math.floor(local.x), y: Math.floor(local.y) };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function openContextMenu(root: HTMLElement, menu: HTMLElement, event: MouseEvent): CellPoint | null {
|
|
21
|
+
const svg = (event.target as Element).closest<SVGSVGElement>('[data-settlement-map]');
|
|
22
|
+
if (!svg || !root.querySelector<HTMLElement>('.rsm-map-frame')) return null;
|
|
23
|
+
const cell = svgCell(event, svg);
|
|
24
|
+
if (!cell) return null;
|
|
25
|
+
const edge = 8;
|
|
26
|
+
const gap = 6;
|
|
27
|
+
menu.hidden = false;
|
|
28
|
+
const menuBounds = menu.getBoundingClientRect();
|
|
29
|
+
const left = Math.min(Math.max(edge, event.clientX), window.innerWidth - menuBounds.width - edge);
|
|
30
|
+
const opensBelow = event.clientY + gap + menuBounds.height <= window.innerHeight - edge;
|
|
31
|
+
const preferredTop = opensBelow ? event.clientY + gap : event.clientY - menuBounds.height - gap;
|
|
32
|
+
const top = Math.min(Math.max(edge, preferredTop), window.innerHeight - menuBounds.height - edge);
|
|
33
|
+
menu.style.left = `${left}px`;
|
|
34
|
+
menu.style.top = `${top}px`;
|
|
35
|
+
menu.querySelector<HTMLButtonElement>('button')?.focus();
|
|
36
|
+
return cell;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface PointerOptions {
|
|
40
|
+
host: HTMLElement;
|
|
41
|
+
root: HTMLElement;
|
|
42
|
+
menu: HTMLElement;
|
|
43
|
+
flags: PointerFlags;
|
|
44
|
+
onOpen: (cell: CellPoint | null) => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function bindPointerEvents(opts: PointerOptions): void {
|
|
48
|
+
let timer: number | undefined;
|
|
49
|
+
opts.host.addEventListener('pointerdown', (event) => {
|
|
50
|
+
if (event.pointerType === 'mouse') return;
|
|
51
|
+
timer = window.setTimeout(() => {
|
|
52
|
+
opts.flags.ignoreNextContext = true;
|
|
53
|
+
opts.flags.ignoreNextClick = true;
|
|
54
|
+
opts.onOpen(openContextMenu(opts.root, opts.menu, event));
|
|
55
|
+
}, 520);
|
|
56
|
+
});
|
|
57
|
+
const cancel = () => { if (timer) window.clearTimeout(timer); timer = undefined; };
|
|
58
|
+
opts.host.addEventListener('pointerup', cancel);
|
|
59
|
+
opts.host.addEventListener('pointercancel', cancel);
|
|
60
|
+
opts.host.addEventListener('pointerleave', cancel);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function bindContextEditor(root: HTMLElement, onEdit: EditHandler): void {
|
|
64
|
+
const host = root.querySelector<HTMLElement>('[data-map-host]');
|
|
65
|
+
const menu = root.querySelector<HTMLElement>('[data-context-menu]');
|
|
66
|
+
if (!host || !menu) return;
|
|
67
|
+
let selected: CellPoint | null = null;
|
|
68
|
+
const flags: PointerFlags = { ignoreNextContext: false, ignoreNextClick: false };
|
|
69
|
+
host.addEventListener('contextmenu', (event) => {
|
|
70
|
+
event.preventDefault();
|
|
71
|
+
if (flags.ignoreNextContext) { flags.ignoreNextContext = false; return; }
|
|
72
|
+
selected = openContextMenu(root, menu, event);
|
|
73
|
+
});
|
|
74
|
+
bindPointerEvents({ host, root, menu, flags, onOpen: (cell) => { selected = cell; } });
|
|
75
|
+
menu.querySelectorAll<HTMLButtonElement>('[data-context-tool]').forEach((btn) => btn.addEventListener('click', () => {
|
|
76
|
+
if (selected) onEdit(selected, btn.dataset.contextTool as EditTool);
|
|
77
|
+
menu.hidden = true;
|
|
78
|
+
}));
|
|
79
|
+
document.addEventListener('click', (event) => {
|
|
80
|
+
if (flags.ignoreNextClick) { flags.ignoreNextClick = false; return; }
|
|
81
|
+
if (!menu.contains(event.target as Node)) menu.hidden = true;
|
|
82
|
+
});
|
|
83
|
+
window.addEventListener('resize', () => { menu.hidden = true; });
|
|
84
|
+
window.addEventListener('scroll', () => { menu.hidden = true; }, true);
|
|
85
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TabletopToolEntry, ToolLocaleContent } from '../../types';
|
|
2
|
+
import type { SettlementMapUI } from './ui';
|
|
3
|
+
|
|
4
|
+
export type { SettlementMapUI } from './ui';
|
|
5
|
+
export type SettlementMapLocaleContent = ToolLocaleContent<SettlementMapUI>;
|
|
6
|
+
|
|
7
|
+
export const rpgSettlementExplorationMapGenerator: TabletopToolEntry<SettlementMapUI> = {
|
|
8
|
+
id: 'rpg-settlement-exploration-map-generator',
|
|
9
|
+
icons: { bg: 'mdi:map-marker-radius-outline', fg: 'mdi:home-city-outline' },
|
|
10
|
+
i18n: {
|
|
11
|
+
de: () => import('./i18n/de').then((module) => module.content),
|
|
12
|
+
en: () => import('./i18n/en').then((module) => module.content),
|
|
13
|
+
es: () => import('./i18n/es').then((module) => module.content),
|
|
14
|
+
fr: () => import('./i18n/fr').then((module) => module.content),
|
|
15
|
+
'id': () => import('./i18n/id').then((module) => module.content),
|
|
16
|
+
it: () => import('./i18n/it').then((module) => module.content),
|
|
17
|
+
ja: () => import('./i18n/ja').then((module) => module.content),
|
|
18
|
+
ko: () => import('./i18n/ko').then((module) => module.content),
|
|
19
|
+
nl: () => import('./i18n/nl').then((module) => module.content),
|
|
20
|
+
pl: () => import('./i18n/pl').then((module) => module.content),
|
|
21
|
+
pt: () => import('./i18n/pt').then((module) => module.content),
|
|
22
|
+
ru: () => import('./i18n/ru').then((module) => module.content),
|
|
23
|
+
sv: () => import('./i18n/sv').then((module) => module.content),
|
|
24
|
+
tr: () => import('./i18n/tr').then((module) => module.content),
|
|
25
|
+
zh: () => import('./i18n/zh').then((module) => module.content),
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SettlementMap } from './logic';
|
|
2
|
+
import type { SettlementMapUI } from './ui';
|
|
3
|
+
|
|
4
|
+
export interface SettlementEvaluation { buildingCount: number; pathCount: number; serviceCount: number; waterCount: number; badge: string; terrainLabel: string }
|
|
5
|
+
|
|
6
|
+
export function evaluateSettlement(map: SettlementMap, ui: SettlementMapUI): SettlementEvaluation {
|
|
7
|
+
return { buildingCount: map.buildings.length, pathCount: map.paths.length, serviceCount: map.buildings.filter((building) => building.service).length, waterCount: map.water.length, badge: ui.readyBadge, terrainLabel: ui[map.config.environment] ?? map.config.environment };
|
|
8
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
2
|
+
import { bibliography } from '../bibliography';
|
|
3
|
+
import type { SettlementMapLocaleContent, SettlementMapUI } from '../entry';
|
|
4
|
+
|
|
5
|
+
const ui: SettlementMapUI = {
|
|
6
|
+
intro: 'Gestalten Sie eine erkundbare Siedlungskarte für Ihre Rollenspiele. Wählen Sie Landschaft, Siedlungstyp und Baustil und passen Sie Zellen per Rechtsklick an.',
|
|
7
|
+
seedLabel: 'Startwert und Dorfname',
|
|
8
|
+
seedHint: 'Der Startwert erzeugt ein deterministisches Layout für Straßen und Gebäude.',
|
|
9
|
+
randomSeed: 'Neuer Name',
|
|
10
|
+
environmentLabel: 'Landschaft',
|
|
11
|
+
forest: 'Wald',
|
|
12
|
+
plains: 'Ebene',
|
|
13
|
+
coast: 'Küste',
|
|
14
|
+
river: 'Fluss',
|
|
15
|
+
mountain: 'Gebirge',
|
|
16
|
+
styleLabel: 'Architekturstil',
|
|
17
|
+
styleHint: 'Ändert Dächer, Materialien, Fassaden und regionale Vegetation.',
|
|
18
|
+
styleTimber: 'Fachwerk',
|
|
19
|
+
styleStone: 'Stein',
|
|
20
|
+
styleCoastal: 'Küstenstil',
|
|
21
|
+
styleHighland: 'Hochland',
|
|
22
|
+
styleMedieval: 'Mittelalter',
|
|
23
|
+
styleEdo: 'Edo',
|
|
24
|
+
styleSahelian: 'Sahel',
|
|
25
|
+
sizeLabel: 'Siedlungsgröße',
|
|
26
|
+
hamlet: 'Weiler',
|
|
27
|
+
hamletHint: 'Kleine Raststätte',
|
|
28
|
+
village: 'Dorf',
|
|
29
|
+
villageHint: 'Lokaler Stützpunkt',
|
|
30
|
+
town: 'Stadt',
|
|
31
|
+
townHint: 'Belebter Knotenpunkt',
|
|
32
|
+
homesLabel: 'Wohnhäuser',
|
|
33
|
+
homesHint: 'Passen Sie die Anzahl der Häuser an die gewählte Grundfläche an.',
|
|
34
|
+
servicesLabel: 'Gebäude und Orte',
|
|
35
|
+
serviceListHint: 'Wählen Sie Vorlagen oder fügen Sie eigene Wahrzeichen hinzu.',
|
|
36
|
+
newServicePlaceholder: 'Ort oder Dienst hinzufügen',
|
|
37
|
+
addService: 'Hinzufügen',
|
|
38
|
+
removeService: 'Entfernen',
|
|
39
|
+
serviceTavern: 'Taverne',
|
|
40
|
+
serviceSmithy: 'Schmiede',
|
|
41
|
+
serviceTemple: 'Tempel',
|
|
42
|
+
serviceMarket: 'Markt',
|
|
43
|
+
serviceStable: 'Stallung',
|
|
44
|
+
serviceHall: 'Rathaus',
|
|
45
|
+
generate: 'Karte neu erzeugen',
|
|
46
|
+
mapRegionLabel: 'Bearbeitbare RPG Siedlungskarte',
|
|
47
|
+
mapSummary: 'Siedlungsplan',
|
|
48
|
+
buildings: 'Gebäude',
|
|
49
|
+
paths: 'Wege',
|
|
50
|
+
services: 'Dienste',
|
|
51
|
+
terrain: 'Wasser',
|
|
52
|
+
legendLabel: 'Kartenlegende',
|
|
53
|
+
legendHome: 'Haus',
|
|
54
|
+
legendService: 'Dienst',
|
|
55
|
+
legendPath: 'Weg',
|
|
56
|
+
legendWater: 'Wasser',
|
|
57
|
+
legendWild: 'Wald',
|
|
58
|
+
editLabel: 'Direkte Kartenbearbeitung',
|
|
59
|
+
toolSelect: 'Inspektion',
|
|
60
|
+
toolBuilding: 'Gebäude',
|
|
61
|
+
toolPath: 'Weg',
|
|
62
|
+
toolWater: 'Wasser',
|
|
63
|
+
toolTree: 'Baum',
|
|
64
|
+
toolErase: 'Löschen',
|
|
65
|
+
serviceSelectLabel: 'Neues Gebäudesymbol',
|
|
66
|
+
clickHint: 'Rechtsklick oder langes Drücken zum Bearbeiten einer Zelle.',
|
|
67
|
+
selectedHint: 'Zelle ausgewählt bei',
|
|
68
|
+
shareLink: 'Link kopieren',
|
|
69
|
+
linkCopied: 'Link in Zwischenablage kopiert',
|
|
70
|
+
exportPng: 'PNG',
|
|
71
|
+
exportSvg: 'SVG',
|
|
72
|
+
exportJson: 'JSON speichern',
|
|
73
|
+
importJson: 'JSON öffnen',
|
|
74
|
+
importError: 'Datei ist keine gültige Siedlungskarte.',
|
|
75
|
+
mapData: 'Kartendaten',
|
|
76
|
+
readyBadge: 'Bereit zur Erkundung',
|
|
77
|
+
serviceNone: 'Kein Symbol',
|
|
78
|
+
contextMenuLabel: 'Zellenaktionen',
|
|
79
|
+
contextInspect: 'Zelle prüfen',
|
|
80
|
+
contextBuilding: 'Gebäude bauen',
|
|
81
|
+
contextPath: 'Weg anlegen',
|
|
82
|
+
contextWater: 'Wasser zeichnen',
|
|
83
|
+
contextTree: 'Baum pflanzen',
|
|
84
|
+
contextErase: 'Zelle leeren',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const faq = [
|
|
88
|
+
{ question: 'Was erzeugt dieser RPG Siedlungskartengenerator?', answer: 'Er erstellt reproduzierbare Übersichtskarten für Weiler, Dörfer und Städte mit Gebäuden, Wegen, Gewässern und Wahrzeichen für Pen and Paper Rollenspiele.' },
|
|
89
|
+
{ question: 'Verändert der Startwert das Layout tatsächlich?', answer: 'Ja. Der Startwert steuert die Anordnung von Straßen und Häusern deterministisch. Der gleiche Wert erzeugt exakt dieselbe Startkarte.' },
|
|
90
|
+
{ question: 'Welche Siedlungsgrößen stehen zur Auswahl?', answer: 'Weiler, Dorf und Stadt bieten unterschiedliche Maße und Gebäudezahlen.' },
|
|
91
|
+
{ question: 'Kann der Baustil angepasst werden?', answer: 'Ja. Zur Wahl stehen Mittelalter, Edo, Sahel, Fachwerk, Stein, Küstenstil und Hochland.' },
|
|
92
|
+
{ question: 'Kann die Landschaft gewählt werden?', answer: 'Ja. Sie können Wald, Ebene, Küste, Fluss oder Gebirge festlegen.' },
|
|
93
|
+
{ question: 'Wie werden wichtige Gebäude platziert?', answer: 'Dienste wie Taverne, Schmiede oder Rathaus werden mit gewichteter Logik im Zentrum oder am Rand platziert.' },
|
|
94
|
+
{ question: 'Können eigene Wahrzeichen hinzugefügt werden?', answer: 'Ja. Eigene Orte können ergänzt und im Browser sowie in Freigabelinks gespeichert werden.' },
|
|
95
|
+
{ question: 'Kann die Karte direkt bearbeitet werden?', answer: 'Ja. Per Rechtsklick oder langem Drücken lässt sich jede Zelle anpassen oder löschen.' },
|
|
96
|
+
{ question: 'Wie verhalten sich Wege und Wasser beim Bearbeiten?', answer: 'Wege verbinden sich automatisch an Kreuzungen und Wasserzellen fügen sich zu Flüssen oder Seen zusammen.' },
|
|
97
|
+
{ question: 'Wie kann eine Karte geteilt werden?', answer: 'Über den Freigabelink oder als JSON Datei bleibt die Karte vollständig bearbeitbar.' },
|
|
98
|
+
{ question: 'Welche Exportformate sind am besten geeignet?', answer: 'PNG für schnelle Bilder, SVG für Druck und Vektoren sowie JSON für vollständige Speicherung.' },
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const howTo = [
|
|
102
|
+
{ name: 'Startwert wählen', text: 'Nutzen Sie den zufälligen Namen oder geben Sie einen eigenen Begriff ein.' },
|
|
103
|
+
{ name: 'Umgebung und Stil festlegen', text: 'Wählen Sie Landschaft und Architekturstil passend zur Spielwelt.' },
|
|
104
|
+
{ name: 'Größe bestimmen', text: 'Wählen Sie zwischen Weiler, Dorf und Stadt.' },
|
|
105
|
+
{ name: 'Orte platzieren', text: 'Aktivieren Sie wichtige Vorlagen oder fügen Sie eigene Wahrzeichen hinzu.' },
|
|
106
|
+
{ name: 'Karte anpassen', text: 'Bearbeiten Sie einzelne Zellen direkt über das Kontextmenü.' },
|
|
107
|
+
{ name: 'Speichern und teilen', text: 'Nutzen Sie den Freigabelink oder exportieren Sie als PNG, SVG oder JSON.' },
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
const faqSchema: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
|
|
111
|
+
const appSchema: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'RPG Siedlungskarten Generator', operatingSystem: 'All', applicationCategory: 'GameApplication', description: 'Karten-Generator für Rollenspielsiedlungen mit deterministischen Werten und Bearbeitungsmodus.' };
|
|
112
|
+
const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: 'Wie man eine RPG Siedlungskarte erstellt', step: howTo.map((item) => ({ '@type': 'HowToStep', name: item.name, text: item.text })) };
|
|
113
|
+
|
|
114
|
+
const schemas: WithContext<SoftwareApplication | FAQPage | HowTo>[] = [faqSchema, appSchema, howToSchema];
|
|
115
|
+
|
|
116
|
+
export const content: SettlementMapLocaleContent = {
|
|
117
|
+
slug: 'rpg-siedlungs-erkundungskarten-generator',
|
|
118
|
+
title: 'RPG Siedlungskarten Generator für Rollenspiele',
|
|
119
|
+
description: 'Erstellen Sie RPG Siedlungskarten für Weiler, Dörfer und Städte mit verschiedenen Baustilen, Umgebungen und Zelleneditor.',
|
|
120
|
+
ui,
|
|
121
|
+
seo: [
|
|
122
|
+
{ type: 'title', text: 'Lebendige Siedlungskarten für Rollenspiele Erzeugen', level: 2 },
|
|
123
|
+
{ type: 'paragraph', html: 'Erschaffen Sie Siedlungen, die Ihren Spielern echte Orte zum Erkunden bieten und nicht nur eine Ansammlung isolierter Häuser darstellen. Dieser browserbasierte Kartengenerator für Pen-and-Paper-Rollenspiele erstellt Übersichtskarten, auf denen Wohngebäude, Straßennetze, Marktplätze, Gewässer und Baumgruppen harmonisch zusammenwirken. Nutzen Sie das Werkzeug für spontane Zwischenstopps im Dorf, von Fraktionen geprägte Städte, abgelegene Weiler oder als ersten Entwurf für Orte, die Sie im Laufe einer Kampagne weiterentwickeln möchten.' },
|
|
124
|
+
{ type: 'title', text: 'Deterministische Startwerte für Wiederholbare Karten', level: 2 },
|
|
125
|
+
{ type: 'paragraph', html: 'Jede erzeugte Siedlung basiert auf einem einprägsamen Namens-Startwert. Dieser Wert steuert deterministisch das gesamte Layout, einschließlich Straßenführung, Gebäudeabständen, Dienstzuweisungen und der umgebenden Vegetation. Wenn Sie denselben Startwert und dieselben Optionen erneut eingeben, wird die exakt gleiche Karte rekonstruiert, was sich hervorragend für Spielleiternotizen und spätere Spielrunden eignet.' },
|
|
126
|
+
{ type: 'list', items: ['Unterschiedliche Startwerte erzeugen neue Siedlungsmuster innerhalb des gewählten Typs.', 'Das Ergebnis bleibt vollständig reproduzierbar statt unkontrolliert zufällig zu sein.', 'Die Siedlung behält ihre charakteristische Struktur als Weiler, Dorf oder Stadt bei.', 'Der gleiche Startwert kann als stabile Basis für die gemeinsame Kampagnenplanung geteilt werden.'] },
|
|
127
|
+
{ type: 'title', text: 'Unterschiedliche Maßstäbe vom Weiler bis zur Stadt', level: 2 },
|
|
128
|
+
{ type: 'paragraph', html: 'Der Größenwähler ist keine bloße optische Skalierung. Weiler, Dörfer und Städte nutzen unterschiedliche Bauarten, Dichten und Erwartungen an Dienstleistungen. Ein Weiler bleibt mit unter zehn Häusern überschaubar, während eine Stadt Raum für längere Wege, mehr Gebäude und eine ausgeprägte zentrale Struktur bietet.' },
|
|
129
|
+
{ type: 'table', headers: ['Grundfläche', 'Häuserzahl', 'Charakter', 'Bester Einsatz in der Kampagne'], rows: [['Weiler', '3 bis 18', 'Klein, spärlich und auf einen Blick erfassbar', 'Rastort am Wegesrand oder isolierte Gemeinschaft'], ['Dorf', '4 bis 28', 'Lokales Zentrum mit Wegen und Wahrzeichen', 'Wiederkehrende Heimatbasis oder Fraktionsknoten'], ['Stadt', '6 bis 42', 'Breites Netzwerk mit vielen Diensten und Wegen', 'Regionales Handelszentrum oder Ermittlungsort']] },
|
|
130
|
+
{ type: 'title', text: 'Sieben Ausprägbare Architekturstile', level: 2 },
|
|
131
|
+
{ type: 'paragraph', html: 'Verleihen Sie der Siedlung vor der Platzierung von Details eine eigene Identität. Fachwerk, Stein, Küstenstil, Hochland, Mittelalter, Edo und Sahel verändern Dächer, Wandfarben, Fenster, Türen und Strukturen. Auch die Baumarten passen sich der Region an, von Palmen an der Küste bis hin zu Nadelbäumen im Hochland.' },
|
|
132
|
+
{ type: 'list', items: ['Mittelalter und Fachwerk passen zu Märchen dörfern und Waldgemeinschaften.', 'Stein und Hochland eignen sich für rauere, befestigte oder bergelegene Orte.', 'Küstenstil bringt eine maritime Note mit passender Küstenvegetation ein.', 'Edo verleiht Straßen und Häusern eine historische ostasiatische Silhouette.', 'Sahel bietet trockenen Regionen eine authentische Architektur und Farbpalette.'] },
|
|
133
|
+
{ type: 'title', text: 'Intelligente Verteilung Wichtiger Gebäude', level: 2 },
|
|
134
|
+
{ type: 'paragraph', html: 'Wichtige Orte wie Taverne, Schmiede, Tempel, Markt, Stallung und Rathaus werden mit gewichteter Logik platziert. Öffentliche Gebäude neigen zum Zentrum, während Ställe und Schmieden eher an den Außenwegen liegen. Zudem können Sie eigene Wahrzeichen definieren, die mit vollständigem Namen auf Schildern über den Dächern angezeigt werden.' },
|
|
135
|
+
{ type: 'title', text: 'Die Landschaft als Teil der Geschichte', level: 2 },
|
|
136
|
+
{ type: 'paragraph', html: 'Wählen Sie Wald, Ebene, Küste, Fluss oder Gebirge und betten Sie die Siedlung in diese Umgebung ein. Das Gelände verleiht dem Ort Kontext: Ein Fluss kann die Anreise prägen, während ein dichter Wald verborgene Pfade verbergen kann.' },
|
|
137
|
+
{ type: 'title', text: 'Direkte Bearbeitung Zelle für Zelle', level: 2 },
|
|
138
|
+
{ type: 'paragraph', html: 'Die erzeugte Karte ist ein starker Ausgangspunkt, den Sie über das Kontextmenü per Rechtsklick oder langem Drücken individuell anpassen können. Fügen Sie Gebäude, Wege, Wasserstellen oder Bäume hinzu oder löschen Sie unerwünschte Elemente direkt auf der Karte.' },
|
|
139
|
+
{ type: 'list', items: ['Fügen Sie fehlende Häuser, Brücken oder Wachtürme hinzu.', 'Passen Sie Wege ohne externe Zeichenprogramme direkt im Browser an.', 'Behalten Sie manuelle Änderungen im gleichen Kartenstatus bei.', 'Funktioniert nahtlos auf PCs sowie Touch-Geräten.'] },
|
|
140
|
+
{ type: 'title', text: 'Reaktive Wege und Wasserflächen', level: 2 },
|
|
141
|
+
{ type: 'paragraph', html: 'Wege bilden saubere Kreuzungen, wenn mehrere Pfade aufeinandertreffen. Das Zeichnen von Wasser ist ebenfalls reaktiv: Benachbarte Wasserzellen verbinden sich automatisch zu Flüssen, Teichen oder größeren Seen.' },
|
|
142
|
+
{ type: 'title', text: 'Teilen und Wiederverwenden von Karten', level: 2 },
|
|
143
|
+
{ type: 'paragraph', html: 'Kopieren Sie den Freigabelink, um die vollständige bearbeitbare Karte an Mitspieler oder Spielleiter zu senden. Alle Einstellungen, Gebäude, Wege und manuellen Änderungen bleiben dabei erhalten. Alternativ lässt sich der Zustand als JSON sichern.' },
|
|
144
|
+
{ type: 'title', text: 'Exportformate für Jeden Einsatzzweck', level: 2 },
|
|
145
|
+
{ type: 'table', headers: ['Format', 'Geeignet für', 'Erhaltene Inhalte'], rows: [['PNG', 'Virtuelle Spieltische und schnelle Handouts', 'Sofort anzeigbares Bild der aktuellen Karte'], ['SVG', 'Druck und Vektorbearbeitung', 'Scharfe skaliersbare Vektorgrafik für große Pläne'], ['JSON', 'Kampagnenarchive und spätere Editiermodi', 'Vollständiger bearbeitbarer Zustand der Siedlung']] },
|
|
146
|
+
{ type: 'tip', title: 'Praktischer Ablauf für den Spielabend', html: 'Wählen Sie zuerst Startwert, Grundfläche und Stil. Fügen Sie wichtige Wahrzeichen hinzu und verfeinern Sie die Karte anschließend mit dem Zelleneditor vor Beginn der Spielrunde.' },
|
|
147
|
+
],
|
|
148
|
+
faq,
|
|
149
|
+
bibliography,
|
|
150
|
+
howTo,
|
|
151
|
+
schemas,
|
|
152
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
2
|
+
import { bibliography } from '../bibliography';
|
|
3
|
+
import type { SettlementMapLocaleContent, SettlementMapUI } from '../entry';
|
|
4
|
+
|
|
5
|
+
const ui: SettlementMapUI = {
|
|
6
|
+
intro: 'Lay out a place worth exploring. Pick the landscape, settlement type, and building character, then correct the generated map with a right click or long press.', seedLabel: 'Village name seed', seedHint: 'The seed chooses a different deterministic layout pattern within the selected settlement type.', randomSeed: 'Create a new village name', environmentLabel: 'Landscape', forest: 'Forest', plains: 'Plains', coast: 'Coast', river: 'River', mountain: 'Mountain', styleLabel: 'Village character', styleHint: 'Choose an architectural identity: era, geography, roofs, materials, and details all change.', styleTimber: 'Timber', styleStone: 'Stone', styleCoastal: 'Coastal', styleHighland: 'Highland', styleMedieval: 'Medieval', styleEdo: 'Edo', styleSahelian: 'Sahelian', sizeLabel: 'Settlement footprint', hamlet: 'Hamlet', hamletHint: 'Small stop', village: 'Village', villageHint: 'Local base', town: 'Town', townHint: 'Busy hub', homesLabel: 'Homes', homesHint: 'Each footprint has its own starting size and core services. Fine tune the homes after choosing one.', servicesLabel: 'Services to place', serviceListHint: 'Choose presets or add a named landmark for this settlement. Custom services stay in this browser.', newServicePlaceholder: 'Add a service or landmark', addService: 'Add', removeService: 'Remove', serviceTavern: 'Tavern', serviceSmithy: 'Smithy', serviceTemple: 'Temple', serviceMarket: 'Market', serviceStable: 'Stable', serviceHall: 'Hall', generate: 'Regenerate map', mapRegionLabel: 'Editable RPG settlement map', mapSummary: 'Village plan', buildings: 'Buildings', paths: 'Paths', services: 'Services', terrain: 'Water cells', legendLabel: 'Map legend', legendHome: 'Home', legendService: 'Service mark', legendPath: 'Road', legendWater: 'Water', legendWild: 'Trees', editLabel: 'Edit the map directly', toolSelect: 'Inspect', toolBuilding: 'Building', toolPath: 'Road', toolWater: 'Water', toolTree: 'Tree', toolErase: 'Erase', serviceSelectLabel: 'New building mark', clickHint: 'Right click or long press the plan to edit a cell.', selectedHint: 'Cell selected at', shareLink: 'Copy share link', linkCopied: 'Share link copied', exportPng: 'PNG', exportSvg: 'SVG', exportJson: 'Save JSON', importJson: 'Open JSON', importError: 'That file is not a valid settlement map.', mapData: 'Map data', readyBadge: 'Ready to explore', serviceNone: 'No mark', contextMenuLabel: 'Map cell actions', contextInspect: 'Inspect cell', contextBuilding: 'Add building', contextPath: 'Add road', contextWater: 'Add water', contextTree: 'Add tree', contextErase: 'Erase cell',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const faq = [
|
|
10
|
+
{ question: 'What does this RPG settlement map generator create?', answer: 'It creates a reproducible overhead exploration map for a hamlet, village, or town. The map combines a settlement footprint with homes, roads, services, plazas, water, trees, and the surrounding landscape, so the place feels like part of a wider region instead of a disconnected pile of buildings. It is designed for RPG worldbuilding, campaign preparation, travel scenes, clues, factions, and points of interest rather than tactical combat grids.' },
|
|
11
|
+
{ question: 'Does the seed really change the settlement layout?', answer: 'Yes. The seed is not only a name. It drives a deterministic layout variant inside the selected settlement type, so two seeds can produce different road patterns, house positions, spacing, service assignments, and wild growth while still respecting the urban grammar of a hamlet, village, or town. Reusing the same seed and settings rebuilds the same starting map.' },
|
|
12
|
+
{ question: 'Which settlement sizes are available?', answer: 'Hamlet, village, and town each have a different footprint and starting logic. Hamlets support small communities, villages create a more developed local base, and towns make room for denser routes, more services, and broader exploration. The home count reacts to the selected footprint, while still allowing a smaller or larger result within that type range.' },
|
|
13
|
+
{ question: 'Can I choose the architectural style of the settlement?', answer: 'Yes. Choose Timber, Stone, Coastal, Highland, Medieval, Edo, or Sahelian. The style changes the visual language of houses, including roof shape, wall treatment, doors, windows, texture, colour accents, and the way nearby trees are drawn. It gives the same settlement generator a different regional or historical identity.' },
|
|
14
|
+
{ question: 'Can I choose the landscape around the settlement?', answer: 'Yes. Choose forest, plains, coast, river, or mountain. The landscape remains the visual context around the settlement and influences water, vegetation, and terrain details, so the village does not always become the only thing on the map. Forest and wild growth can occupy the surrounding space while the settlement stays readable at the centre.' },
|
|
15
|
+
{ question: 'How are services placed?', answer: 'Built-in services include Tavern, Smithy, Temple, Market, Stable, and Hall, and you can add named custom services or landmarks. The generator assigns them with deterministic weights instead of always attaching them to the first few houses: Hall and similar civic services tend toward the centre, while Stable and Smithy tend toward the edge and outer roads, with controlled variation so every settlement does not follow the exact same pattern. Service labels use the full name and appear on readable signs above the building.' },
|
|
16
|
+
{ question: 'Can I add my own services and keep them in a shared map?', answer: 'Yes. Add a custom service or landmark to the dynamic list and it is saved in local storage for later maps. Custom entries can be removed whenever you want, while the built-in service presets remain available. When you copy a share link or save JSON, the custom service catalog and the marks already placed on the map travel with the settlement.' },
|
|
17
|
+
{ question: 'Can I edit the generated RPG map directly?', answer: 'Yes. Right-click a map cell on desktop or long-press it on touch devices to open the contextual editor. From there you can inspect the cell, add a building, draw a road, paint water, add a tree, or erase it. The contextual menu repositions itself when it would otherwise be clipped by the map or viewport.' },
|
|
18
|
+
{ question: 'How do roads and water behave when I edit them?', answer: 'Roads are built as a connected graph with clean junctions, including places where three or four paths meet. Painting water affects the exact selected cell. Adjacent water cells join visually into a river, a small pond, or a broader lake shape as the component grows, so manual edits respond to their neighbours instead of leaving isolated marks.' },
|
|
19
|
+
{ question: 'How can I share or reproduce a settlement for another session?', answer: 'Copy the share link to send a complete editable settlement to another person. It preserves the seed, landscape, footprint, home count, architectural style, selected services, custom service list, generated buildings, roads, water, trees, and manual edits. The same state can also be saved as JSON and reopened later.' },
|
|
20
|
+
{ question: 'Which export should I use for a campaign handout?', answer: 'PNG is convenient for notes, virtual tabletops, and quick sharing. SVG stays sharp for printing and further vector editing. JSON is the full editable map state, so it is the best option when you want to preserve every generated and manually painted detail rather than only export a picture.' },
|
|
21
|
+
];
|
|
22
|
+
const howTo = [
|
|
23
|
+
{ name: 'Start with a memorable seed', text: 'Use the generated compound settlement name or type your own seed. The seed controls a repeatable layout variation, so it changes the arrangement without abandoning the selected settlement type.' },
|
|
24
|
+
{ name: 'Choose the landscape and character', text: 'Select forest, plains, coast, river, or mountain, then choose an architectural identity such as Medieval, Edo, Sahelian, Timber, Stone, Coastal, or Highland. The surrounding wild growth and the houses use the selected visual language.' },
|
|
25
|
+
{ name: 'Set the settlement footprint and homes', text: 'Choose hamlet, village, or town. Each footprint reacts with its own map scale, home range, layout grammar, and core services, then you can fine tune the number of homes to match the location in your campaign.' },
|
|
26
|
+
{ name: 'Add meaningful services', text: 'Select built-in services such as Tavern, Smithy, Temple, Market, Stable, and Hall, or add your own landmarks. Placement uses weighted centre and edge preferences with seeded variation, while custom services persist in the browser and in shared map data.' },
|
|
27
|
+
{ name: 'Correct the map in context', text: 'Right-click or long-press any cell. Add buildings, roads, water, or trees, inspect what is already there, or erase a cell. Roads repair their junctions and adjacent water cells recompute their river, pond, or lake shape as you paint.' },
|
|
28
|
+
{ name: 'Share and export the finished place', text: 'Copy a link for a complete editable version, save JSON as a source file, or export PNG for a handout and SVG for crisp printing. The map stays useful as both a worldbuilding draft and a practical exploration reference.' },
|
|
29
|
+
];
|
|
30
|
+
const faqSchema: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
|
|
31
|
+
const appSchema: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'RPG Settlement and Exploration Map Generator', operatingSystem: 'All', applicationCategory: 'GameApplication', description: 'A browser based RPG settlement map generator with deterministic layouts, five landscapes, seven architectural styles, weighted services, connected roads, reactive water, contextual editing, share links, local storage, and PNG, SVG, and JSON exports.' };
|
|
32
|
+
const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: 'How to make an RPG settlement exploration map', step: howTo.map((item) => ({ '@type': 'HowToStep', name: item.name, text: item.text })) };
|
|
33
|
+
|
|
34
|
+
export const content: SettlementMapLocaleContent = {
|
|
35
|
+
slug: 'rpg-settlement-exploration-map-generator', title: 'RPG Settlement and Exploration Map Generator', description: 'Generate a deterministic RPG settlement map with landscapes, architectural styles, smart services, connected roads, reactive water, contextual editing, share links, and PNG, SVG, and JSON export.', ui,
|
|
36
|
+
seo: [
|
|
37
|
+
{ type: 'title', text: 'Generate a Living RPG Settlement Map', level: 2 },
|
|
38
|
+
{ type: 'paragraph', html: 'Build a settlement that gives players somewhere to go, not just a picture of houses. This browser based RPG map generator creates an overhead exploration map where homes, roads, services, plazas, water, trees, and open terrain work together as a place with shape and purpose. Use it for a quick village stop, a faction filled town, a remote hamlet, or the first draft of a location you will keep developing during a campaign.' },
|
|
39
|
+
{ type: 'title', text: 'A Seed That Changes the Town Without Losing Its Character', level: 2 },
|
|
40
|
+
{ type: 'paragraph', html: 'Every generated settlement starts from a memorable compound name seed. The seed does more than rename the map: it selects a deterministic variation of the layout, including road rhythm, house spacing, service assignment, and surrounding wild growth. Change the seed to explore a new arrangement, then reuse the same seed and settings whenever you need to rebuild the same starting map for your notes, players, or future sessions.' },
|
|
41
|
+
{ type: 'list', items: ['Different seeds create different patterns inside the chosen settlement type.', 'The result stays reproducible instead of becoming an untraceable random roll.', 'The settlement remains readable as a hamlet, village, or town while its internal arrangement changes.', 'The same seed can be shared as a stable starting point for collaborative campaign preparation.'] },
|
|
42
|
+
{ type: 'title', text: 'Hamlet Village and Town Use Different Urban Grammars', level: 2 },
|
|
43
|
+
{ type: 'paragraph', html: 'The footprint selector is not a cosmetic size switch. Hamlets, villages, and towns use different construction patterns, spacing, home ranges, and service expectations. A hamlet can stay under ten houses without looking like a shrunken town, while a town has room for longer routes, more destinations, and a stronger central structure. The home count reacts to the selected footprint so the generated place keeps the right scale.' },
|
|
44
|
+
{ type: 'table', headers: ['Footprint', 'Home range', 'Character', 'Best campaign use'], rows: [['Hamlet', '3 to 18', 'Small, sparse, and easy to read at a glance', 'A roadside stop, isolated community, or village edge'], ['Village', '4 to 28', 'A local centre with several routes and landmarks', 'A recurring base, mystery location, or faction hub'], ['Town', '6 to 42', 'A broader network with more services and detours', 'A regional hub, investigation space, or starting settlement']] },
|
|
45
|
+
{ type: 'title', text: 'Choose an Architectural Identity', level: 2 },
|
|
46
|
+
{ type: 'paragraph', html: 'Give the settlement a visual identity before you start placing details. Timber, Stone, Coastal, Highland, Medieval, Edo, and Sahelian styles alter the houses with different roof profiles, wall colours, doors, windows, textures, and decorative details. The tree language changes with the setting too, from coastal palms and highland conifers to rounded Edo silhouettes, broad medieval canopies, and Sahelian acacia forms. The style makes the map feel like a region, era, or culture rather than a recoloured template.' },
|
|
47
|
+
{ type: 'list', items: ['Medieval and Timber support storybook villages, frontier settlements, and woodland communities.', 'Stone and Highland suit rugged, elevated, defensive, or weather exposed places.', 'Coastal introduces a brighter maritime identity with vegetation that belongs near the shore.', 'Edo provides a distinct historical and regional silhouette for streets, houses, and trees.', 'Sahelian gives dryland communities their own architecture, palette, and tree shapes.'] },
|
|
48
|
+
{ type: 'title', text: 'Place Services Where They Make Sense', level: 2 },
|
|
49
|
+
{ type: 'paragraph', html: 'Services are story anchors with spatial logic. Tavern, Smithy, Temple, Market, Stable, and Hall are not blindly assigned to the first five buildings. Seeded weights choose among suitable candidates, with civic buildings tending toward the centre, stables and smithies favouring outer roads, and other services receiving a useful middle ground with enough variation to avoid a repeated pattern. Add custom services such as a watch post, apothecary, shrine, guildhall, ferry office, or whatever your adventure needs. Full service names appear on large signs above the houses so they stay legible in a town and remain visually attached to the correct building.' },
|
|
50
|
+
{ type: 'title', text: 'Let the Landscape Be Part of the Story', level: 2 },
|
|
51
|
+
{ type: 'paragraph', html: 'Choose Forest, Plains, Coast, River, or Mountain and let the settlement sit inside that context. The map gives the surrounding landscape room to breathe, with wild growth and terrain framing the populated area instead of turning the village into the only protagonist. A river can define an approach, a forest can hide a path or landmark, and the open ground around a hamlet can communicate isolation before a single encounter is written.' },
|
|
52
|
+
{ type: 'title', text: 'Edit the Map Cell by Cell', level: 2 },
|
|
53
|
+
{ type: 'paragraph', html: 'The generated plan is a strong starting point, but the contextual editor is where it becomes your location. Right-click on desktop or long-press on a touch screen to open the cell actions exactly where you are working. Inspect a cell, add a building, draw a road, paint water, add a tree, or erase an unwanted mark. The menu repositions itself when the edge of the map would clip it, keeping the editing action available without covering the workspace.' },
|
|
54
|
+
{ type: 'list', items: ['Add a missing house, bridge approach, shrine, watch post, field, or other point of interest.', 'Move from generated structure to campaign-specific detail without opening a separate drawing toolbar.', 'Keep manual edits in the same map state as the generated content.', 'Use the same interaction on desktop and touch devices with right click or long press.'] },
|
|
55
|
+
{ type: 'title', text: 'Roads and Water Respond to Their Neighbours', level: 2 },
|
|
56
|
+
{ type: 'paragraph', html: 'Roads are generated as connected routes rather than decorative disconnected lines. Intersections are drawn cleanly when three or four paths meet, giving the settlement a usable circulation pattern. Water painting is equally reactive: a painted cell remains an exact edit, adjacent cells join into a river or pond, and larger connected groups resolve into a broader lake shape. This makes it practical to sketch a stream bend, extend a shoreline, add a crossing, or reshape a water feature directly on the map.' },
|
|
57
|
+
{ type: 'title', text: 'Keep Your Services and Share the Complete Place', level: 2 },
|
|
58
|
+
{ type: 'paragraph', html: 'Custom services are saved in local storage so a useful landmark list can grow across maps. Remove custom entries when they no longer belong; built-in presets remain available. When you copy a share link, the recipient gets the complete editable state: seed, footprint, home count, landscape, architectural style, service catalog, service marks, buildings, roads, water, trees, and manual edits. Nothing important is reduced to a screenshot.' },
|
|
59
|
+
{ type: 'title', text: 'Export for Notes, Printing, or Continued Editing', level: 2 },
|
|
60
|
+
{ type: 'table', headers: ['Format', 'Useful for', 'What it preserves'], rows: [['PNG', 'Virtual tabletops, notes, and quick handouts', 'A ready to view image of the current map'], ['SVG', 'Printing and vector workflows', 'A sharp scalable drawing for larger layouts'], ['JSON', 'Campaign archives and future edits', 'The complete editable settlement state']] },
|
|
61
|
+
{ type: 'tip', title: 'A Practical Workflow for Game Night', html: 'Start with a seed, footprint, landscape, and architectural style. Add only the services that can create scenes or clues, then use the contextual editor to place the one bridge, road, tree line, water cell, or outlying house that makes the adventure yours. Copy the share link for the editable master and export a PNG or SVG when you need a clean reference at the table.' },
|
|
62
|
+
], faq, bibliography, howTo, schemas: [faqSchema, appSchema, howToSchema] as unknown as Record<string, unknown>[],
|
|
63
|
+
};
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
2
|
+
import { bibliography } from '../bibliography';
|
|
3
|
+
import type { SettlementMapLocaleContent, SettlementMapUI } from '../entry';
|
|
4
|
+
|
|
5
|
+
const ui: SettlementMapUI = {
|
|
6
|
+
intro: 'Diseña un mapa de exploración de asentamiento para tus partidas. Elige el paisaje, el tipo de poblado y el estilo arquitectónico, y ajusta celdas con clic derecho o pulsación prolongada.',
|
|
7
|
+
seedLabel: 'Semilla y nombre de la aldea',
|
|
8
|
+
seedHint: 'La semilla genera un patrón determinista único para la distribución de caminos y edificios.',
|
|
9
|
+
randomSeed: 'Generar nuevo nombre',
|
|
10
|
+
environmentLabel: 'Paisaje circundante',
|
|
11
|
+
forest: 'Bosque',
|
|
12
|
+
plains: 'Llanura',
|
|
13
|
+
coast: 'Costa',
|
|
14
|
+
river: 'Río',
|
|
15
|
+
mountain: 'Montaña',
|
|
16
|
+
styleLabel: 'Estilo arquitectónico',
|
|
17
|
+
styleHint: 'Cambia la identidad estética: tejados, materiales, estructuras y vegetación regional.',
|
|
18
|
+
styleTimber: 'Entramado',
|
|
19
|
+
styleStone: 'Piedra',
|
|
20
|
+
styleCoastal: 'Costero',
|
|
21
|
+
styleHighland: 'Alta montaña',
|
|
22
|
+
styleMedieval: 'Medieval',
|
|
23
|
+
styleEdo: 'Edo',
|
|
24
|
+
styleSahelian: 'Saheliano',
|
|
25
|
+
sizeLabel: 'Tamaño del asentamiento',
|
|
26
|
+
hamlet: 'Aldea',
|
|
27
|
+
hamletHint: 'Poblado pequeño',
|
|
28
|
+
village: 'Pueblo',
|
|
29
|
+
villageHint: 'Base local',
|
|
30
|
+
town: 'Villa',
|
|
31
|
+
townHint: 'Núcleo urbano',
|
|
32
|
+
homesLabel: 'Viviendas',
|
|
33
|
+
homesHint: 'Ajusta la cantidad de casas respetando el tamaño y espacio disponible.',
|
|
34
|
+
servicesLabel: 'Servicios e hitos',
|
|
35
|
+
serviceListHint: 'Elige servicios predefinidos o añade puntos de interés personalizados.',
|
|
36
|
+
newServicePlaceholder: 'Añadir servicio o lugar',
|
|
37
|
+
addService: 'Añadir',
|
|
38
|
+
removeService: 'Eliminar',
|
|
39
|
+
serviceTavern: 'Taberna',
|
|
40
|
+
serviceSmithy: 'Herrería',
|
|
41
|
+
serviceTemple: 'Templo',
|
|
42
|
+
serviceMarket: 'Mercado',
|
|
43
|
+
serviceStable: 'Establo',
|
|
44
|
+
serviceHall: 'Ayuntamiento',
|
|
45
|
+
generate: 'Regenerar mapa',
|
|
46
|
+
mapRegionLabel: 'Mapa de asentamiento ROL editable',
|
|
47
|
+
mapSummary: 'Plano del poblado',
|
|
48
|
+
buildings: 'Edificios',
|
|
49
|
+
paths: 'Caminos',
|
|
50
|
+
services: 'Servicios',
|
|
51
|
+
terrain: 'Agua',
|
|
52
|
+
legendLabel: 'Leyenda del mapa',
|
|
53
|
+
legendHome: 'Casa',
|
|
54
|
+
legendService: 'Servicio',
|
|
55
|
+
legendPath: 'Camino',
|
|
56
|
+
legendWater: 'Agua',
|
|
57
|
+
legendWild: 'Bosque',
|
|
58
|
+
editLabel: 'Edición directa de mapa',
|
|
59
|
+
toolSelect: 'Inspeccionar',
|
|
60
|
+
toolBuilding: 'Edificio',
|
|
61
|
+
toolPath: 'Camino',
|
|
62
|
+
toolWater: 'Agua',
|
|
63
|
+
toolTree: 'Árbol',
|
|
64
|
+
toolErase: 'Borrar',
|
|
65
|
+
serviceSelectLabel: 'Nueva marca de servicio',
|
|
66
|
+
clickHint: 'Clic derecho o pulsación prolongada para editar una celda.',
|
|
67
|
+
selectedHint: 'Celda seleccionada en',
|
|
68
|
+
shareLink: 'Copiar enlace',
|
|
69
|
+
linkCopied: 'Enlace copiado al portapapeles',
|
|
70
|
+
exportPng: 'PNG',
|
|
71
|
+
exportSvg: 'SVG',
|
|
72
|
+
exportJson: 'Guardar JSON',
|
|
73
|
+
importJson: 'Abrir JSON',
|
|
74
|
+
importError: 'El archivo no es un mapa válido.',
|
|
75
|
+
mapData: 'Datos del mapa',
|
|
76
|
+
readyBadge: 'Listo para explorar',
|
|
77
|
+
serviceNone: 'Sin marca',
|
|
78
|
+
contextMenuLabel: 'Acciones de celda',
|
|
79
|
+
contextInspect: 'Inspeccionar celda',
|
|
80
|
+
contextBuilding: 'Añadir edificio',
|
|
81
|
+
contextPath: 'Añadir camino',
|
|
82
|
+
contextWater: 'Añadir agua',
|
|
83
|
+
contextTree: 'Añadir árbol',
|
|
84
|
+
contextErase: 'Borrar celda',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const faq = [
|
|
88
|
+
{
|
|
89
|
+
question: '¿Qué genera este generador de mapas de asentamientos para ROL?',
|
|
90
|
+
answer: 'Crea mapas cenitales interactivos y reproducibles para aldeas, pueblos y villas en juegos de rol. Genera viviendas, caminos conectados, fuentes de agua, vegetación y servicios con lógica urbanística.',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
question: '¿La semilla modifica realmente el diseño del mapa?',
|
|
94
|
+
answer: 'Sí. La semilla genera una distribución determinista de calles, casas y servicios. Utilizar la misma semilla y configuración reconstruirá exactamente el mismo mapa.',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
question: '¿Qué tamaños de asentamiento están disponibles?',
|
|
98
|
+
answer: 'Aldea, pueblo y villa. Cada uno amplía la escala del mapa, la densidad de caminos y la capacidad de viviendas.',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
question: '¿Se puede cambiar el estilo arquitectónico?',
|
|
102
|
+
answer: 'Sí. Incluye estilos Medieval, Edo, Saheliano, Entramado, Piedra, Costero y Alta montaña, adaptando tejados, paredes y árboles al entorno.',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
question: '¿Es posible elegir el entorno natural?',
|
|
106
|
+
answer: 'Sí. Puedes seleccionar bosque, llanura, costa, río o montaña para enmarcar el poblado en la geografía deseada.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
question: '¿Cómo se distribuyen los servicios en el poblado?',
|
|
110
|
+
answer: 'Los servicios predefinidos como taberna, herrería, templo, mercado, establo y ayuntamiento se ubican con pesos lógicos: el ayuntamiento hacia el centro y los establos o herrerías hacia los bordes.',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
question: '¿Puedo añadir mis propios puntos de interés?',
|
|
114
|
+
answer: 'Sí. Puedes añadir lugares de interés personalizados que se guardan en el navegador y se incluyen en los enlaces compartidos y archivos JSON.',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
question: '¿Se puede editar el mapa celda por celda?',
|
|
118
|
+
answer: 'Sí. Al hacer clic derecho o pulsación prolongada sobre cualquier celda puedes cambiar su contenido entre edificio, camino, agua, árbol o borrarla.',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
question: '¿Cómo reaccionan los caminos y el agua al editar?',
|
|
122
|
+
answer: 'Los caminos conectan automáticamente las cruces e intersecciones adyacentes, y las celdas de agua se unen formando ríos, estanques o lagos.',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
question: '¿Cómo comparto un asentamiento con mis jugadores?',
|
|
126
|
+
answer: 'Copia el enlace compartido o exporta el mapa en JSON. Ambos métodos conservan la configuración y todas las ediciones manuales.',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
question: '¿Qué formato de exportación es el más adecuado?',
|
|
130
|
+
answer: 'PNG para imágenes rápidas, SVG para impresión y edición vectorial, y JSON para guardar el estado editable completo.',
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const howTo = [
|
|
135
|
+
{
|
|
136
|
+
name: 'Elige una semilla',
|
|
137
|
+
text: 'Usa el nombre generado o escribe una semilla propia para controlar la distribución inicial del poblado.',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'Selecciona entorno y estilo',
|
|
141
|
+
text: 'Ajusta el paisaje entre bosque, llanura, costa, río o montaña, y elige una arquitectura como Medieval, Edo o Saheliano.',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: 'Define la escala',
|
|
145
|
+
text: 'Selecciona aldea, pueblo o villa y ajusta el número de viviendas deseadas.',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'Añade servicios e hitos',
|
|
149
|
+
text: 'Activa servicios clave como taberna o herrería, o crea tus propios nombres de lugares de interés.',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: 'Edita el plano celda a celda',
|
|
153
|
+
text: 'Haz clic derecho o mantén pulsado sobre el mapa para modificar caminos, agua, edificios o árboles.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'Exporta y comparte',
|
|
157
|
+
text: 'Obtén el enlace compartido, guarda en JSON o descarga el mapa en PNG o SVG para tus sesiones.',
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
|
|
161
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
162
|
+
'@context': 'https://schema.org',
|
|
163
|
+
'@type': 'FAQPage',
|
|
164
|
+
mainEntity: faq.map((item) => ({
|
|
165
|
+
'@type': 'Question',
|
|
166
|
+
name: item.question,
|
|
167
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
168
|
+
})),
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
172
|
+
'@context': 'https://schema.org',
|
|
173
|
+
'@type': 'SoftwareApplication',
|
|
174
|
+
name: 'Generador de Mapas de Asentamientos ROL',
|
|
175
|
+
operatingSystem: 'All',
|
|
176
|
+
applicationCategory: 'GameApplication',
|
|
177
|
+
description: 'Generador de mapas de exploración de poblados para juegos de rol con semillas deterministas, estilos arquitectónicos y edición directa.',
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const howToSchema: WithContext<HowTo> = {
|
|
181
|
+
'@context': 'https://schema.org',
|
|
182
|
+
'@type': 'HowTo',
|
|
183
|
+
name: 'Cómo crear un mapa de asentamiento para ROL',
|
|
184
|
+
step: howTo.map((item) => ({
|
|
185
|
+
'@type': 'HowToStep',
|
|
186
|
+
name: item.name,
|
|
187
|
+
text: item.text,
|
|
188
|
+
})),
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const schemas: WithContext<SoftwareApplication | FAQPage | HowTo>[] = [
|
|
192
|
+
faqSchema,
|
|
193
|
+
appSchema,
|
|
194
|
+
howToSchema,
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
export const content: SettlementMapLocaleContent = {
|
|
198
|
+
slug: 'generador-mapas-asentamientos-rol-exploracion',
|
|
199
|
+
title: 'Generador de Mapas de Asentamientos para ROL',
|
|
200
|
+
description: 'Genera mapas de exploración de aldeas, pueblos y villas para ROL con semillas deterministas, 7 estilos arquitectónicos, servicios e interacción celda a celda.',
|
|
201
|
+
ui,
|
|
202
|
+
seo: [
|
|
203
|
+
{ type: 'title', text: 'Crea Asentamientos Vivos para tus Partidas de ROL', level: 2 },
|
|
204
|
+
{ type: 'paragraph', html: 'Diseña poblados completos que ofrezcan a tus jugadores un lugar real que explorar, en lugar de una simple acumulación de casas sin contexto. Este generador de mapas de rol para navegador crea planos cenitales donde viviendas, caminos, plazas, fuentes de agua, vegetación y terreno abierto trabajan juntos como un espacio coherente con estructura y propósito. Utilízalo para un alto rápido en el camino, una villa llena de facciones, una aldea remota o el primer borrador de una ubicación clave en tu campaña.' },
|
|
205
|
+
{ type: 'title', text: 'Semillas Deterministas para Mapas Reproducibles', level: 2 },
|
|
206
|
+
{ type: 'paragraph', html: 'Cada poblado generado parte de una semilla basada en un nombre compuesto y memorable. La semilla no solo nombra el plano: selecciona una variante determinista de la distribución, incluyendo el ritmo de los caminos, el espacio entre viviendas, la asignación de servicios e hitos, y la densidad del bosque circundante. Cambiar la semilla genera una nueva ordenación, y reutilizar la misma combinación en el futuro reconstruye de forma exacta el mismo mapa de inicio.' },
|
|
207
|
+
{ type: 'list', items: ['Diferentes semillas crean patrones propios para cada tipo de asentamiento.', 'Los mapas son 100% reproducibles para tus notas de campaña o futuras partidas.', 'Mantiene la coherencia urbanística en aldeas, pueblos y villas.', 'Permite compartir semillas exactas con otros directores de juego para la preparación de campañas.'] },
|
|
208
|
+
{ type: 'title', text: 'Escala Adaptable de Aldea a Villa', level: 2 },
|
|
209
|
+
{ type: 'paragraph', html: 'La selección de tamaño no es un mero cambio cosmético. Aldeas, pueblos y villas emplean patrones de construcción, distancias, capacidades de viviendas y expectativas de servicios diferentes. Una aldea puede mantenerse por debajo de diez casas sin parecer una villa encogida, mientras que una villa dispone de espacio para rutas más largas, mayor número de destinos y una estructura central marcada. El contador de viviendas reacciona al tamaño elegido para asegurar la escala adecuada.' },
|
|
210
|
+
{ type: 'table', headers: ['Escala', 'Viviendas', 'Carácter', 'Uso en campaña'], rows: [['Aldea', '3 a 18', 'Pequeña, dispersa y fácil de abarcar a simple vista', 'Alto en el camino, comunidad aislada o borde del poblado'], ['Pueblo', '4 a 28', 'Centro local con varios caminos e hitos destacados', 'Base recurrente, lugar de misterio o núcleo de facción'], ['Villa', '6 a 42', 'Red amplia con múltiples servicios, rutas y desvíos', 'Centro comercial regional, lugar de investigación o poblado inicial']] },
|
|
211
|
+
{ type: 'title', text: 'Siete Estilos Arquitectónicos', level: 2 },
|
|
212
|
+
{ type: 'paragraph', html: 'Otorga una identidad visual propia al poblado antes de colocar los detalles. Los estilos Medieval, Edo, Saheliano, Entramado, Piedra, Costero y Alta montaña modifican las casas con diferentes pérfiles de tejados, tonos de pared, puertas, ventanas, texturas y detalles decorativos. La vegetación también se adapta al entorno, desde palmeras costeras hasta coníferas de montaña o copas redondeadas de inspiración oriental.' },
|
|
213
|
+
{ type: 'list', items: ['Medieval y Entramado para fantasía clásica, poblados fronterizos y comunidades del bosque.', 'Piedra y Alta montaña para entornos rocosos, fortificados o expuestos al clima.', 'Costero para una identidad marítima luminosa con vegetación propia de litoral.', 'Edo para una silueta histórica y regional reconocible en calles, tejados y vegetación.', 'Saheliano para comunidades de clima seco con una arquitectura y paleta propias.'] },
|
|
214
|
+
{ type: 'title', text: 'Ubicación Inteligente de Servicios', level: 2 },
|
|
215
|
+
{ type: 'paragraph', html: 'Los servicios son anclas narrativas con lógica espacial. Tabernas, herrerías, templos, mercados, establos y ayuntamientos no se asignan a ciegas a las primeras casas. Pesos algorítmicos situán los edificios cívicos hacia el centro del asentamiento, mientras que establos y herrerías tienden hacia los caminos exteriores. Puedes añadir nombres personalizados para puestos de guardia, boticarios, santuarios o gremios, apareciendo en carteles sobre los tejados para ser perfectamente legibles.' },
|
|
216
|
+
{ type: 'title', text: 'Integración en el Entorno Natural', level: 2 },
|
|
217
|
+
{ type: 'paragraph', html: 'Selecciona entornos de bosque, llanura, costa, río o montaña para integrar el poblado en su entorno geográfico. El mapa otorga al paisaje espacio para respirar, permitiendo que la vegetación silvestre y la topografía enmarquen la zona habitada en lugar de convertir el mapa en un único bloque de casas.' },
|
|
218
|
+
{ type: 'title', text: 'Edición Directa Celda a Celda', level: 2 },
|
|
219
|
+
{ type: 'paragraph', html: 'El plano generado es un excelente punto de partida, pero el editor contextual lo transforma en tu ubicación concreta. Haz clic derecho en ordenador o mantén pulsado en dispositivos táctiles para abrir el menú de acciones directamente en la celda donde estás trabajando. Inspecciona celdas, añade viviendas, dibuja caminos, pinta agua, planta árboles o borra elementos indeseados.' },
|
|
220
|
+
{ type: 'list', items: ['Añade casas faltantes, accesos a puentes, santuarios o puestos de guardia.', 'Modifica rutas sin necesidad de herramientas de dibujo externas.', 'Conserva todas las ediciones manuales en el mismo estado del mapa.', 'Misma interacción intuitiva en ordenadores y dispositivos táctiles.'] },
|
|
221
|
+
{ type: 'title', text: 'Caminos y Agua Dinámicos', level: 2 },
|
|
222
|
+
{ type: 'paragraph', html: 'Los caminos se generan como rutas conectadas y sus cruces se dibujan de forma limpia cuando se cruzan tres o cuatro vías. El pintado de agua reacciona al entorno: celdas adyacentes se unen formando ríos, estanques o lagos más amplios a medida que expandes el área de agua.' },
|
|
223
|
+
{ type: 'title', text: 'Guarda y Comparte tus Mapas', level: 2 },
|
|
224
|
+
{ type: 'paragraph', html: 'Genera enlaces para compartir la versión editable completa con tus jugadores o con otro director de juego. Se conserva la semilla, el tamaño, el estilo arquitectónico, la lista de servicios, los caminos, las celdas de agua y todas las modificaciones manuales realizadas. También puedes exportar el mapa completo como archivo JSON.' },
|
|
225
|
+
{ type: 'title', text: 'Formatos de Exportación Adaptados', level: 2 },
|
|
226
|
+
{ type: 'table', headers: ['Formato', 'Uso recomendado', 'Contenido conservado'], rows: [['PNG', 'Mesas virtuales y notas rápidas', 'Imagen lista del plano actual'], ['SVG', 'Impresión y diseño vectorial', 'Gráficos escalables de alta definición'], ['JSON', 'Archivo y edición futura', 'Estado editable completo del mapa']] },
|
|
227
|
+
{ type: 'tip', title: 'Flujo Recomendado para Sesiones', html: 'Empieza eligiendo semilla, tamaño y estilo. Añade los servicios narrativos clave y utiliza el editor contextual para dar el toque final a los caminos o edificios antes de la partida.' },
|
|
228
|
+
],
|
|
229
|
+
faq,
|
|
230
|
+
bibliography,
|
|
231
|
+
howTo,
|
|
232
|
+
schemas,
|
|
233
|
+
};
|