mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
Generate a legend for manually added markers (#753)
Markers added by procedural generation have custom notes depending on the type of marker (e.g. dungeons have a procedurally generated map); however, the notes for markers manually added by the user are empty. This patch separates the cell selection logic from the legend and name generation logic in markers-generator.js, so that the latter can be shared with manually added markers. There is some additional simplifications such as storing the dx/dy/px/min/each values directly in the markers table to simplify the writing of the generic "list and add" loop in `generateTypes()`. Currently, the legend is only generated when adding a marker of the same type as an existing marker, and only when a legend generation function is available for that type. To generate a marker of a type that is not currently present on the map, one must first change the type field of an existing marker (which will not get a procedural note), then use "Add additional marker of that type". The UI for this can be improved later. Co-authored-by: Basile Clement <basile-github@clement.pm>
This commit is contained in:
parent
3ac075319f
commit
edfcad4e8c
2 changed files with 306 additions and 389 deletions
|
|
@ -9,27 +9,27 @@ window.Markers = (function () {
|
||||||
const isFantasy = culturesSet.includes("Fantasy");
|
const isFantasy = culturesSet.includes("Fantasy");
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{type: "volcanoes", icon: "🌋", multiplier: 1, fn: addVolcanoes},
|
{type: "volcanoes", icon: "🌋", dx: 52, px: 13, min: 10, each: 500, multiplier: 1, fn: [listVolcanoes, addVolcano]},
|
||||||
{type: "hot-springs", icon: "♨️", multiplier: 1, fn: addHotSprings},
|
{type: "hot-springs", icon: "♨️", dy: 52, min: 30, each: 1200, multiplier: 1, fn: [listHotSprings, addHotSpring]},
|
||||||
{type: "mines", icon: "⛏️", multiplier: 1, fn: addMines},
|
{type: "mines", icon: "⛏️", dx: 48, px: 13, min: 1, each: 15, multiplier: 1, fn: [listMines, addMine]},
|
||||||
{type: "bridges", icon: "🌉", multiplier: 1, fn: addBridges},
|
{type: "bridges", icon: "🌉", px: 14, min: 1, each: 5, multiplier: 1, fn: [listBridges, addBridge]},
|
||||||
{type: "inns", icon: "🍻", multiplier: 1, fn: addInns},
|
{type: "inns", icon: "🍻", px: 14, min: 1, each: 100, multiplier: 1, fn: [listInns, addInn]},
|
||||||
{type: "lighthouses", icon: "🚨", multiplier: 1, fn: addLighthouses},
|
{type: "lighthouses", icon: "🚨", px: 14, min: 1, each: 2, multiplier: 1, fn: [listLighthouses, addLighthouse]},
|
||||||
{type: "waterfalls", icon: "⟱", multiplier: 1, fn: addWaterfalls},
|
{type: "waterfalls", icon: "⟱", dy: 54, px: 16, min: 1, each: 5, multiplier: 1, fn: [listWaterfalls, addWaterfall]},
|
||||||
{type: "battlefields", icon: "⚔️", multiplier: 1, fn: addBattlefields},
|
{type: "battlefields", icon: "⚔️", dy: 52, min: 50, each: 700, multiplier: 1, fn: [listBattlefields, addBattlefield]},
|
||||||
{type: "dungeons", icon: "🗝️", multiplier: 1, fn: addDungeons},
|
{type: "dungeons", icon: "🗝️", dy: 51, px: 13, min: 30, each: 200, multiplier: 1, fn: [listDungeons, addDungeon]},
|
||||||
{type: "lake-monsters", icon: "🐉", multiplier: 1, fn: addLakeMonsters},
|
{type: "lake-monsters", icon: "🐉", dy: 48, min: 2, each: 10, multiplier: 1, fn: [listLakeMonsters, addLakeMonster]},
|
||||||
{type: "sea-monsters", icon: "🦑", multiplier: 1, fn: addSeaMonsters},
|
{type: "sea-monsters", icon: "🦑", min: 50, each: 700, multiplier: 1, fn: [listSeaMonsters, addSeaMonster]},
|
||||||
{type: "hill-monsters", icon: "👹", multiplier: 1, fn: addHillMonsters},
|
{type: "hill-monsters", icon: "👹", dy: 54, px: 13, min: 30, each: 600, multiplier: 1, fn: [listHillMonsters, addHillMonster]},
|
||||||
{type: "sacred-mountains", icon: "🗻", multiplier: 1, fn: addSacredMountains},
|
{type: "sacred-mountains", icon: "🗻", dy: 48, min: 1, each: 5, multiplier: 1, fn: [listSacredMountains, addSacredMountain]},
|
||||||
{type: "sacred-forests", icon: "🌳", multiplier: 1, fn: addSacredForests},
|
{type: "sacred-forests", icon: "🌳", min: 30, each: 1000, multiplier: 1, fn: [listSacredForests, addSacredForest]},
|
||||||
{type: "sacred-pineries", icon: "🌲", multiplier: 1, fn: addSacredPineries},
|
{type: "sacred-pineries", icon: "🌲", px: 13, min: 30, each: 800, multiplier: 1, fn: [listSacredPineries, addSacredPinery]},
|
||||||
{type: "sacred-palm-groves", icon: "🌴", multiplier: 1, fn: addSacredPalmGroves},
|
{type: "sacred-palm-groves", icon: "🌴", px: 13, min: 1, each: 100, multiplier: 1, fn: [listSacredPalmGroves, addSacredPalmGrove]},
|
||||||
{type: "brigands", icon: "💰", multiplier: 1, fn: addBrigands},
|
{type: "brigands", icon: "💰", px: 13, min: 50, each: 100, multiplier: 1, fn: [listBrigands, addBrigands]},
|
||||||
{type: "pirates", icon: "🏴☠️", multiplier: 1, fn: addPirates},
|
{type: "pirates", icon: "🏴☠️", dx: 51, min: 40, each: 300, multiplier: 1, fn: [listPirates, addPirates]},
|
||||||
{type: "statues", icon: "🗿", multiplier: 1, fn: addStatues},
|
{type: "statues", icon: "🗿", min: 80, each: 1200, multiplier: 1, fn: [listStatues, addStatue]},
|
||||||
{type: "ruines", icon: "🏺", multiplier: 1, fn: addRuines},
|
{type: "ruines", icon: "🏺", min: 80, each: 1200, multiplier: 1, fn: [listRuins, addRuins]},
|
||||||
{type: "portals", icon: "🌀", multiplier: +isFantasy, fn: addPortals}
|
{type: "portals", icon: "🌀", px: 14, min: 16, each: 8, multiplier: +isFantasy, fn: [listPortals, addPortal]}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,12 +61,36 @@ window.Markers = (function () {
|
||||||
generateTypes();
|
generateTypes();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const add = marker => {
|
||||||
|
const base = config.find(c => c.type === marker.type);
|
||||||
|
if (base) {
|
||||||
|
const {icon, type, dx, dy, px} = base;
|
||||||
|
marker = addMarker({icon, type, dx, dy, px}, marker);
|
||||||
|
base.fn[1]("marker" + marker.i, marker.cell);
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
const i = last(pack.markers)?.i + 1 || 0;
|
||||||
|
pack.markers.push({...marker, i});
|
||||||
|
occupied[marker.cell] = true;
|
||||||
|
return {...marker, i};
|
||||||
|
};
|
||||||
|
|
||||||
function generateTypes() {
|
function generateTypes() {
|
||||||
TIME && console.time("addMarkers");
|
TIME && console.time("addMarkers");
|
||||||
|
|
||||||
config.forEach(({type, icon, multiplier, fn}) => {
|
config.forEach(({type, icon, dx, dy, px, min, each, multiplier, fn}) => {
|
||||||
if (multiplier === 0) return;
|
if (multiplier === 0) return;
|
||||||
fn(type, icon, multiplier);
|
|
||||||
|
let candidates = Array.from(fn[0](pack));
|
||||||
|
let quantity = getQuantity(candidates, min, each, multiplier);
|
||||||
|
|
||||||
|
while (quantity && candidates.length) {
|
||||||
|
const [cell] = extractAnyElement(candidates);
|
||||||
|
const marker = addMarker({icon, type, dx, dy, px}, {cell});
|
||||||
|
fn[1]("marker" + marker.i, cell);
|
||||||
|
quantity--;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
occupied = [];
|
occupied = [];
|
||||||
|
|
@ -96,112 +120,84 @@ window.Markers = (function () {
|
||||||
return cells.p[cell];
|
return cells.p[cell];
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMarker({cell, type, icon, dx, dy, px}) {
|
function addMarker(base, marker) {
|
||||||
const i = last(pack.markers)?.i + 1 || 0;
|
const i = last(pack.markers)?.i + 1 || 0;
|
||||||
const [x, y] = getMarkerCoordinates(cell);
|
const [x, y] = getMarkerCoordinates(marker.cell);
|
||||||
const marker = {i, icon, type, x, y, cell};
|
marker = {...base, x, y, ...marker, i};
|
||||||
if (dx) marker.dx = dx;
|
|
||||||
if (dy) marker.dy = dy;
|
|
||||||
if (px) marker.px = px;
|
|
||||||
pack.markers.push(marker);
|
pack.markers.push(marker);
|
||||||
occupied[cell] = true;
|
occupied[marker.cell] = true;
|
||||||
return "marker" + i;
|
return marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addVolcanoes(type, icon, multiplier) {
|
function listVolcanoes({cells}) {
|
||||||
const {cells} = pack;
|
return cells.i.filter(i => !occupied[i] && cells.h[i] >= 70);
|
||||||
|
|
||||||
let mountains = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] >= 70).sort((a, b) => cells.h[b] - cells.h[a]));
|
|
||||||
let quantity = getQuantity(mountains, 10, 500, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(mountains);
|
|
||||||
const id = addMarker({cell, icon, type, dx: 52, px: 13});
|
|
||||||
const proper = Names.getCulture(cells.culture[cell]);
|
|
||||||
const name = P(0.3) ? "Mount " + proper : Math.random() > 0.3 ? proper + " Volcano" : proper;
|
|
||||||
notes.push({id, name, legend: `Active volcano. Height: ${getFriendlyHeight(cells.p[cell])}`});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addHotSprings(type, icon, multiplier) {
|
function addVolcano(id, cell) {
|
||||||
const {cells} = pack;
|
const {cells} = pack;
|
||||||
|
|
||||||
let springs = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] > 50).sort((a, b) => cells.h[b] - cells.h[a]));
|
const proper = Names.getCulture(cells.culture[cell]);
|
||||||
let quantity = getQuantity(springs, 30, 1200, multiplier);
|
const name = P(0.3) ? "Mount " + proper : Math.random() > 0.3 ? proper + " Volcano" : proper;
|
||||||
if (!quantity) return;
|
notes.push({id, name, legend: `Active volcano. Height: ${getFriendlyHeight(cells.p[cell])}`});
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(springs);
|
|
||||||
const id = addMarker({cell, icon, type, dy: 52});
|
|
||||||
const proper = Names.getCulture(cells.culture[cell]);
|
|
||||||
const temp = convertTemperature(gauss(35, 15, 20, 100));
|
|
||||||
notes.push({id, name: proper + " Hot Springs", legend: `A hot springs area. Average temperature: ${temp}`});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMines(type, icon, multiplier) {
|
function listHotSprings({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] > 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addHotSpring(id, cell) {
|
||||||
const {cells} = pack;
|
const {cells} = pack;
|
||||||
|
|
||||||
let hillyBurgs = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] > 47 && cells.burg[i]));
|
const proper = Names.getCulture(cells.culture[cell]);
|
||||||
let quantity = getQuantity(hillyBurgs, 1, 15, multiplier);
|
const temp = convertTemperature(gauss(35, 15, 20, 100));
|
||||||
if (!quantity) return;
|
notes.push({id, name: proper + " Hot Springs", legend: `A hot springs area. Average temperature: ${temp}`});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listMines({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] > 47 && cells.burg[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMine(id, cell) {
|
||||||
|
const {cells} = pack;
|
||||||
|
|
||||||
const resources = {salt: 5, gold: 2, silver: 4, copper: 2, iron: 3, lead: 1, tin: 1};
|
const resources = {salt: 5, gold: 2, silver: 4, copper: 2, iron: 3, lead: 1, tin: 1};
|
||||||
|
const resource = rw(resources);
|
||||||
while (quantity && hillyBurgs.length) {
|
const burg = pack.burgs[cells.burg[cell]];
|
||||||
const [cell] = extractAnyElement(hillyBurgs);
|
const name = `${burg.name} — ${resource} mining town`;
|
||||||
const id = addMarker({cell, icon, type, dx: 48, px: 13});
|
const population = rn(burg.population * populationRate * urbanization);
|
||||||
const resource = rw(resources);
|
const legend = `${burg.name} is a mining town of ${population} people just nearby the ${resource} mine`;
|
||||||
const burg = pack.burgs[cells.burg[cell]];
|
notes.push({id, name, legend});
|
||||||
const name = `${burg.name} — ${resource} mining town`;
|
|
||||||
const population = rn(burg.population * populationRate * urbanization);
|
|
||||||
const legend = `${burg.name} is a mining town of ${population} people just nearby the ${resource} mine`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addBridges(type, icon, multiplier) {
|
function listBridges({cells, burgs}) {
|
||||||
const {cells, burgs} = pack;
|
|
||||||
|
|
||||||
const meanFlux = d3.mean(cells.fl.filter(fl => fl));
|
const meanFlux = d3.mean(cells.fl.filter(fl => fl));
|
||||||
let bridges = Array.from(
|
return cells.i.filter(i => !occupied[i] && cells.burg[i] && cells.t[i] !== 1 && burgs[cells.burg[i]].population > 20 && cells.r[i] && cells.fl[i] > meanFlux);
|
||||||
cells.i.filter(i => !occupied[i] && cells.burg[i] && cells.t[i] !== 1 && burgs[cells.burg[i]].population > 20 && cells.r[i] && cells.fl[i] > meanFlux)
|
|
||||||
);
|
|
||||||
let quantity = getQuantity(bridges, 1, 5, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(bridges);
|
|
||||||
const id = addMarker({cell, icon, type, px: 14});
|
|
||||||
const burg = pack.burgs[cells.burg[cell]];
|
|
||||||
const river = pack.rivers.find(r => r.i === pack.cells.r[cell]);
|
|
||||||
const riverName = river ? `${river.name} ${river.type}` : "river";
|
|
||||||
const name = river && P(0.2) ? river.name : burg.name;
|
|
||||||
const weightedAdjectives = {
|
|
||||||
stone: 10,
|
|
||||||
wooden: 1,
|
|
||||||
lengthy: 2,
|
|
||||||
formidable: 2,
|
|
||||||
rickety: 1,
|
|
||||||
beaten: 1,
|
|
||||||
weathered: 1
|
|
||||||
};
|
|
||||||
notes.push({id, name: `${name} Bridge`, legend: `A ${rw(weightedAdjectives)} bridge spans over the ${riverName} near ${burg.name}`});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addInns(type, icon, multiplier) {
|
function addBridge(id, cell) {
|
||||||
const {cells} = pack;
|
const {cells} = pack;
|
||||||
|
|
||||||
let taverns = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] >= 20 && cells.road[i] > 4 && cells.pop[i] > 10));
|
const burg = pack.burgs[cells.burg[cell]];
|
||||||
let quantity = getQuantity(taverns, 1, 100, multiplier);
|
const river = pack.rivers.find(r => r.i === pack.cells.r[cell]);
|
||||||
if (!quantity) return;
|
const riverName = river ? `${river.name} ${river.type}` : "river";
|
||||||
|
const name = river && P(0.2) ? river.name : burg.name;
|
||||||
|
const weightedAdjectives = {
|
||||||
|
stone: 10,
|
||||||
|
wooden: 1,
|
||||||
|
lengthy: 2,
|
||||||
|
formidable: 2,
|
||||||
|
rickety: 1,
|
||||||
|
beaten: 1,
|
||||||
|
weathered: 1
|
||||||
|
};
|
||||||
|
notes.push({id, name: `${name} Bridge`, legend: `A ${rw(weightedAdjectives)} bridge spans over the ${riverName} near ${burg.name}`});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listInns({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] >= 20 && cells.road[i] > 4 && cells.pop[i] > 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addInn(id, cell) {
|
||||||
const colors = [
|
const colors = [
|
||||||
"Dark",
|
"Dark",
|
||||||
"Light",
|
"Light",
|
||||||
|
|
@ -430,44 +426,34 @@ window.Markers = (function () {
|
||||||
"sap"
|
"sap"
|
||||||
];
|
];
|
||||||
|
|
||||||
while (quantity) {
|
const typeName = P(0.3) ? "inn" : "tavern";
|
||||||
const [cell] = extractAnyElement(taverns);
|
const isAnimalThemed = P(0.7);
|
||||||
const id = addMarker({cell, icon, type, px: 14});
|
const animal = ra(animals);
|
||||||
const typeName = P(0.3) ? "inn" : "tavern";
|
const name = isAnimalThemed ? (P(0.6) ? ra(colors) + " " + animal : ra(adjectives) + " " + animal) : ra(adjectives) + " " + capitalize(typeName);
|
||||||
const isAnimalThemed = P(0.7);
|
const meal = isAnimalThemed && P(0.3) ? animal : ra(courses);
|
||||||
const animal = ra(animals);
|
const course = `${ra(methods)} ${meal}`.toLowerCase();
|
||||||
const name = isAnimalThemed ? (P(0.6) ? ra(colors) + " " + animal : ra(adjectives) + " " + animal) : ra(adjectives) + " " + capitalize(type);
|
const drink = `${P(0.5) ? ra(types) : ra(colors)} ${ra(drinks)}`.toLowerCase();
|
||||||
const meal = isAnimalThemed && P(0.3) ? animal : ra(courses);
|
const legend = `A big and famous roadside ${typeName}. Delicious ${course} with ${drink} is served here`;
|
||||||
const course = `${ra(methods)} ${meal}`.toLowerCase();
|
notes.push({id, name: "The " + name, legend});
|
||||||
const drink = `${P(0.5) ? ra(types) : ra(colors)} ${ra(drinks)}`.toLowerCase();
|
|
||||||
const legend = `A big and famous roadside ${typeName}. Delicious ${course} with ${drink} is served here`;
|
|
||||||
notes.push({id, name: "The " + name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLighthouses(type, icon, multiplier) {
|
function listLighthouses({cells}) {
|
||||||
const {cells} = pack;
|
return cells.i.filter(i => !occupied[i] && cells.harbor[i] > 6 && cells.c[i].some(c => cells.h[c] < 20 && cells.road[c]));
|
||||||
|
|
||||||
const lighthouses = Array.from(cells.i.filter(i => !occupied[i] && cells.harbor[i] > 6 && cells.c[i].some(c => cells.h[c] < 20 && cells.road[c])));
|
|
||||||
let quantity = getQuantity(lighthouses, 1, 2, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(lighthouses);
|
|
||||||
const id = addMarker({cell, icon, type, px: 14});
|
|
||||||
const proper = cells.burg[cell] ? pack.burgs[cells.burg[cell]].name : Names.getCulture(cells.culture[cell]);
|
|
||||||
notes.push({id, name: getAdjective(proper) + " Lighthouse" + name, legend: `A lighthouse to serve as a beacon for ships in the open sea`});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addWaterfalls(type, icon, multiplier) {
|
function addLighthouse(id, cell) {
|
||||||
const {cells} = pack;
|
const {cells} = pack;
|
||||||
|
|
||||||
const waterfalls = Array.from(cells.i.filter(i => cells.r[i] && !occupied[i] && cells.h[i] >= 50 && cells.c[i].some(c => cells.h[c] < 40 && cells.r[c])));
|
const proper = cells.burg[cell] ? pack.burgs[cells.burg[cell]].name : Names.getCulture(cells.culture[cell]);
|
||||||
const quantity = getQuantity(waterfalls, 1, 5, multiplier);
|
notes.push({id, name: getAdjective(proper) + " Lighthouse" + name, legend: `A lighthouse to serve as a beacon for ships in the open sea`});
|
||||||
if (!quantity) return;
|
}
|
||||||
|
|
||||||
|
function listWaterfalls({cells}) {
|
||||||
|
return cells.i.filter(i => cells.r[i] && !occupied[i] && cells.h[i] >= 50 && cells.c[i].some(c => cells.h[c] < 40 && cells.r[c]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addWaterfall(id, cell) {
|
||||||
|
const {cells} = pack;
|
||||||
|
|
||||||
const descriptions = [
|
const descriptions = [
|
||||||
"A gorgeous waterfall flows here",
|
"A gorgeous waterfall flows here",
|
||||||
|
|
@ -477,98 +463,73 @@ window.Markers = (function () {
|
||||||
"A river drops down from a great height forming a wonderous waterfall",
|
"A river drops down from a great height forming a wonderous waterfall",
|
||||||
"A breathtaking waterfall cuts through the landscape"
|
"A breathtaking waterfall cuts through the landscape"
|
||||||
];
|
];
|
||||||
for (let i = 0; i < waterfalls.length && i < quantity; i++) {
|
|
||||||
const cell = waterfalls[i];
|
const proper = cells.burg[cell] ? pack.burgs[cells.burg[cell]].name : Names.getCulture(cells.culture[cell]);
|
||||||
const id = addMarker({cell, icon, type, dy: 54, px: 16});
|
notes.push({id, name: getAdjective(proper) + " Waterfall" + name, legend: `${ra(descriptions)}`});
|
||||||
const proper = cells.burg[cell] ? pack.burgs[cells.burg[cell]].name : Names.getCulture(cells.culture[cell]);
|
|
||||||
notes.push({id, name: getAdjective(proper) + " Waterfall" + name, legend: `${ra(descriptions)}`});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addBattlefields(type, icon, multiplier) {
|
function listBattlefields({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.state[i] && cells.pop[i] > 2 && cells.h[i] < 50 && cells.h[i] > 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addBattlefield(id, cell) {
|
||||||
const {cells, states} = pack;
|
const {cells, states} = pack;
|
||||||
|
|
||||||
let battlefields = Array.from(cells.i.filter(i => !occupied[i] && cells.state[i] && cells.pop[i] > 2 && cells.h[i] < 50 && cells.h[i] > 25));
|
const state = states[cells.state[cell]];
|
||||||
let quantity = getQuantity(battlefields, 50, 700, multiplier);
|
if (!state.campaigns) state.campaigns = BurgsAndStates.generateCampaign(state);
|
||||||
if (!quantity) return;
|
const campaign = ra(state.campaigns);
|
||||||
|
const date = generateDate(campaign.start, campaign.end);
|
||||||
while (quantity && battlefields.length) {
|
const name = Names.getCulture(cells.culture[cell]) + " Battlefield";
|
||||||
const [cell] = extractAnyElement(battlefields);
|
const legend = `A historical battle of the ${campaign.name}. \r\nDate: ${date} ${options.era}`;
|
||||||
const id = addMarker({cell, icon, type, dy: 52});
|
notes.push({id, name, legend});
|
||||||
const state = states[cells.state[cell]];
|
|
||||||
if (!state.campaigns) state.campaigns = BurgsAndStates.generateCampaign(state);
|
|
||||||
const campaign = ra(state.campaigns);
|
|
||||||
const date = generateDate(campaign.start, campaign.end);
|
|
||||||
const name = Names.getCulture(cells.culture[cell]) + " Battlefield";
|
|
||||||
const legend = `A historical battle of the ${campaign.name}. \r\nDate: ${date} ${options.era}`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDungeons(type, icon, multiplier) {
|
function listDungeons({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.pop[i] && cells.pop[i] < 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDungeon(id, cell) {
|
||||||
|
const dungeonSeed = `${seed}${cell}`;
|
||||||
|
const name = "Dungeon";
|
||||||
|
const legend = `<div>Undiscovered dungeon. See <a href="https://watabou.github.io/one-page-dungeon/?seed=${dungeonSeed}" target="_blank">One page dungeon</a></div><iframe src="https://watabou.github.io/one-page-dungeon/?seed=${dungeonSeed}" sandbox="allow-scripts allow-same-origin"></iframe>`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listLakeMonsters({features}) {
|
||||||
|
return features.filter(feature => feature.type === "lake" && feature.group === "freshwater" && !occupied[feature.firstCell]).map(feature => feature.firstCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLakeMonster(id, cell) {
|
||||||
|
const lake = pack.features[pack.cells.f[cell]];
|
||||||
|
|
||||||
|
// Check that the feature is a lake in case the user clicked on a wrong
|
||||||
|
// square
|
||||||
|
if (lake.type !== "lake") return;
|
||||||
|
|
||||||
|
const name = `${lake.name} Monster`;
|
||||||
|
const length = gauss(10, 5, 5, 100);
|
||||||
|
const legend = `Rumors say a relic monster of ${length} ${heightUnit.value} long inhabits ${lake.name} Lake. Truth or lie, folks are afraid to fish in the lake`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listSeaMonsters({cells, features}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] < 20 && cells.road[i] && features[cells.f[i]].type === "ocean");
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSeaMonster(id, cell) {
|
||||||
|
const name = `${Names.getCultureShort(0)} Monster`;
|
||||||
|
const length = gauss(25, 10, 10, 100);
|
||||||
|
const legend = `Old sailors tell stories of a gigantic sea monster inhabiting these dangerous waters. Rumors say it can be ${length} ${heightUnit.value} long`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listHillMonsters({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] >= 50 && cells.pop[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addHillMonster(id, cell) {
|
||||||
const {cells} = pack;
|
const {cells} = pack;
|
||||||
|
|
||||||
let dungeons = Array.from(cells.i.filter(i => !occupied[i] && cells.pop[i] && cells.pop[i] < 3));
|
|
||||||
let quantity = getQuantity(dungeons, 30, 200, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(dungeons);
|
|
||||||
const id = addMarker({cell, icon, type, dy: 51, px: 13});
|
|
||||||
|
|
||||||
const dungeonSeed = `${seed}${cell}`;
|
|
||||||
const name = "Dungeon";
|
|
||||||
const legend = `<div>Undiscovered dungeon. See <a href="https://watabou.github.io/one-page-dungeon/?seed=${dungeonSeed}" target="_blank">One page dungeon</a></div><iframe src="https://watabou.github.io/one-page-dungeon/?seed=${dungeonSeed}" sandbox="allow-scripts allow-same-origin"></iframe>`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addLakeMonsters(type, icon, multiplier) {
|
|
||||||
const {features} = pack;
|
|
||||||
|
|
||||||
const lakes = features.filter(feature => feature.type === "lake" && feature.group === "freshwater" && !occupied[feature.firstCell]);
|
|
||||||
let quantity = getQuantity(lakes, 2, 10, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [lake] = extractAnyElement(lakes);
|
|
||||||
const cell = lake.firstCell;
|
|
||||||
const id = addMarker({cell, icon, type, dy: 48});
|
|
||||||
const name = `${lake.name} Monster`;
|
|
||||||
const length = gauss(10, 5, 5, 100);
|
|
||||||
const legend = `Rumors say a relic monster of ${length} ${heightUnit.value} long inhabits ${lake.name} Lake. Truth or lie, folks are afraid to fish in the lake`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addSeaMonsters(type, icon, multiplier) {
|
|
||||||
const {cells, features} = pack;
|
|
||||||
|
|
||||||
const sea = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] < 20 && cells.road[i] && features[cells.f[i]].type === "ocean"));
|
|
||||||
let quantity = getQuantity(sea, 50, 700, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(sea);
|
|
||||||
const id = addMarker({cell, icon, type});
|
|
||||||
const name = `${Names.getCultureShort(0)} Monster`;
|
|
||||||
const length = gauss(25, 10, 10, 100);
|
|
||||||
const legend = `Old sailors tell stories of a gigantic sea monster inhabiting these dangerous waters. Rumors say it can be ${length} ${heightUnit.value} long`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addHillMonsters(type, icon, multiplier) {
|
|
||||||
const {cells} = pack;
|
|
||||||
|
|
||||||
const hills = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] >= 50 && cells.pop[i]));
|
|
||||||
let quantity = getQuantity(hills, 30, 600, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
const adjectives = [
|
const adjectives = [
|
||||||
"great",
|
"great",
|
||||||
"big",
|
"big",
|
||||||
|
|
@ -619,100 +580,77 @@ window.Markers = (function () {
|
||||||
"attacks unsuspecting victims"
|
"attacks unsuspecting victims"
|
||||||
];
|
];
|
||||||
|
|
||||||
while (quantity) {
|
const monster = ra(species);
|
||||||
const [cell] = extractAnyElement(hills);
|
const toponym = Names.getCulture(cells.culture[cell]);
|
||||||
const id = addMarker({cell, icon, type, dy: 54, px: 13});
|
const name = `${toponym} ${monster}`;
|
||||||
const monster = ra(species);
|
const legend = `${ra(subjects)} speak of a ${ra(adjectives)} ${monster} who inhabits ${toponym} hills and ${ra(modusOperandi)}`;
|
||||||
const toponym = Names.getCulture(cells.culture[cell]);
|
notes.push({id, name, legend});
|
||||||
const name = `${toponym} ${monster}`;
|
|
||||||
const legend = `${ra(subjects)} speak of a ${ra(adjectives)} ${monster} who inhabits ${toponym} hills and ${ra(modusOperandi)}`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSacredMountains(type, icon, multiplier) {
|
// Sacred mountains spawn on lonely mountains
|
||||||
|
function listSacredMountains({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] >= 70 && cells.c[i].some(c => cells.culture[c]) && cells.c[i].every(c => cells.h[c] < 60));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSacredMountain(id, cell) {
|
||||||
const {cells, cultures} = pack;
|
const {cells, cultures} = pack;
|
||||||
|
|
||||||
let lonelyMountains = Array.from(
|
const culture = cells.c[cell].map(c => cells.culture[c]).find(c => c);
|
||||||
cells.i.filter(i => !occupied[i] && cells.h[i] >= 70 && cells.c[i].some(c => cells.culture[c]) && cells.c[i].every(c => cells.h[c] < 60))
|
const name = `${Names.getCulture(culture)} Mountain`;
|
||||||
);
|
const height = getFriendlyHeight(cells.p[cell]);
|
||||||
let quantity = getQuantity(lonelyMountains, 1, 5, multiplier);
|
const legend = `A sacred mountain of ${cultures[culture].name} culture. Height: ${height}`;
|
||||||
if (!quantity) return;
|
notes.push({id, name, legend});
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(lonelyMountains);
|
|
||||||
const id = addMarker({cell, icon, type, dy: 48});
|
|
||||||
const culture = cells.c[cell].map(c => cells.culture[c]).find(c => c);
|
|
||||||
const name = `${Names.getCulture(culture)} Mountain`;
|
|
||||||
const height = getFriendlyHeight(cells.p[cell]);
|
|
||||||
const legend = `A sacred mountain of ${cultures[culture].name} culture. Height: ${height}`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSacredForests(type, icon, multiplier) {
|
// Sacred forests spawn on temperate forests
|
||||||
|
function listSacredForests({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.culture[i] && [6, 8].includes(cells.biome[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSacredForest(id, cell) {
|
||||||
const {cells, cultures} = pack;
|
const {cells, cultures} = pack;
|
||||||
|
|
||||||
let temperateForests = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && [6, 8].includes(cells.biome[i])));
|
const culture = cells.culture[cell];
|
||||||
let quantity = getQuantity(temperateForests, 30, 1000, multiplier);
|
const name = `${Names.getCulture(culture)} Forest`;
|
||||||
if (!quantity) return;
|
const legend = `A sacred forest of ${cultures[culture].name} culture`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(temperateForests);
|
|
||||||
const id = addMarker({cell, icon, type});
|
|
||||||
const culture = cells.culture[cell];
|
|
||||||
const name = `${Names.getCulture(culture)} Forest`;
|
|
||||||
const legend = `A sacred forest of ${cultures[culture].name} culture`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSacredPineries(type, icon, multiplier) {
|
// Sacred pineries spawn on boreal forests
|
||||||
|
function listSacredPineries({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.biome[i] === 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSacredPinery(id, cell) {
|
||||||
const {cells, cultures} = pack;
|
const {cells, cultures} = pack;
|
||||||
|
|
||||||
let borealForests = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.biome[i] === 9));
|
const culture = cells.culture[cell];
|
||||||
let quantity = getQuantity(borealForests, 30, 800, multiplier);
|
const name = `${Names.getCulture(culture)} Pinery`;
|
||||||
if (!quantity) return;
|
const legend = `A sacred pinery of ${cultures[culture].name} culture`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(borealForests);
|
|
||||||
const id = addMarker({cell, icon, type, px: 13});
|
|
||||||
const culture = cells.culture[cell];
|
|
||||||
const name = `${Names.getCulture(culture)} Pinery`;
|
|
||||||
const legend = `A sacred pinery of ${cultures[culture].name} culture`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSacredPalmGroves(type, icon, multiplier) {
|
// Sacred palm groves spawn on oasises
|
||||||
|
function listSacredPalmGroves({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.biome[i] === 1 && cells.pop[i] > 1 && cells.road[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSacredPalmGrove(id, cell) {
|
||||||
const {cells, cultures} = pack;
|
const {cells, cultures} = pack;
|
||||||
|
|
||||||
let oasises = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.biome[i] === 1 && cells.pop[i] > 1 && cells.road[i]));
|
const culture = cells.culture[cell];
|
||||||
let quantity = getQuantity(oasises, 1, 100, multiplier);
|
const name = `${Names.getCulture(culture)} Palm Grove`;
|
||||||
if (!quantity) return;
|
const legend = `A sacred palm grove of ${cultures[culture].name} culture`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(oasises);
|
|
||||||
const id = addMarker({cell, icon, type, px: 13});
|
|
||||||
const culture = cells.culture[cell];
|
|
||||||
const name = `${Names.getCulture(culture)} Palm Grove`;
|
|
||||||
const legend = `A sacred palm grove of ${cultures[culture].name} culture`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addBrigands(type, icon, multiplier) {
|
function listBrigands({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.road[i] > 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addBrigands(id, cell) {
|
||||||
const {cells} = pack;
|
const {cells} = pack;
|
||||||
|
|
||||||
let roads = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.road[i] > 4));
|
|
||||||
let quantity = getQuantity(roads, 50, 100, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
const animals = [
|
const animals = [
|
||||||
"Apes",
|
"Apes",
|
||||||
"Badgers",
|
"Badgers",
|
||||||
|
|
@ -747,53 +685,43 @@ window.Markers = (function () {
|
||||||
];
|
];
|
||||||
const types = {brigands: 4, bandits: 3, robbers: 1, highwaymen: 1};
|
const types = {brigands: 4, bandits: 3, robbers: 1, highwaymen: 1};
|
||||||
|
|
||||||
while (quantity) {
|
const culture = cells.culture[cell];
|
||||||
const [cell] = extractAnyElement(roads);
|
const biome = cells.biome[cell];
|
||||||
const id = addMarker({cell, icon, type, px: 13});
|
const height = cells.p[cell];
|
||||||
const culture = cells.culture[cell];
|
const locality =
|
||||||
const biome = cells.biome[cell];
|
height >= 70
|
||||||
const height = cells.p[cell];
|
? "highlander"
|
||||||
const locality =
|
: [1, 2].includes(biome)
|
||||||
height >= 70
|
? "desert"
|
||||||
? "highlander"
|
: [3, 4].includes(biome)
|
||||||
: [1, 2].includes(biome)
|
? "mounted"
|
||||||
? "desert"
|
: [5, 6, 7, 8, 9].includes(biome)
|
||||||
: [3, 4].includes(biome)
|
? "forest"
|
||||||
? "mounted"
|
: biome === 12
|
||||||
: [5, 6, 7, 8, 9].includes(biome)
|
? "swamp"
|
||||||
? "forest"
|
: "angry";
|
||||||
: biome === 12
|
const name = `${Names.getCulture(culture)} ${ra(animals)}`;
|
||||||
? "swamp"
|
const legend = `A gang of ${locality} ${rw(types)}`;
|
||||||
: "angry";
|
notes.push({id, name, legend});
|
||||||
const name = `${Names.getCulture(culture)} ${ra(animals)}`;
|
|
||||||
const legend = `A gang of ${locality} ${rw(types)}`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPirates(type, icon, multiplier) {
|
// Pirates spawn on sea routes
|
||||||
const {cells} = pack;
|
function listPirates({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] < 20 && cells.road[i]);
|
||||||
let searoutes = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] < 20 && cells.road[i]));
|
|
||||||
let quantity = getQuantity(searoutes, 40, 300, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [cell] = extractAnyElement(searoutes);
|
|
||||||
const id = addMarker({cell, icon, type, dx: 51});
|
|
||||||
const name = `Pirates`;
|
|
||||||
const legend = `Pirate ships have been spotted in these waters`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStatues(type, icon, multiplier) {
|
function addPirates(id, cell) {
|
||||||
|
const name = `Pirates`;
|
||||||
|
const legend = `Pirate ships have been spotted in these waters`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listStatues({cells}) {
|
||||||
|
return cells.i.filter(i => !occupied[i] && cells.h[i] >= 20 && cells.h[i] < 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addStatue(id, cell) {
|
||||||
const {cells} = pack;
|
const {cells} = pack;
|
||||||
let statues = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] >= 20 && cells.h[i] < 40));
|
|
||||||
let quantity = getQuantity(statues, 80, 1200, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
const variants = ["Statue", "Obelisk", "Monument", "Column", "Monolith", "Pillar", "Megalith", "Stele", "Runestone", "Sculpture", "Effigy", "Idol"];
|
const variants = ["Statue", "Obelisk", "Monument", "Column", "Monolith", "Pillar", "Megalith", "Stele", "Runestone", "Sculpture", "Effigy", "Idol"];
|
||||||
const scripts = {
|
const scripts = {
|
||||||
|
|
@ -804,31 +732,25 @@ window.Markers = (function () {
|
||||||
mongolian: "᠀᠐᠑᠒ᠠᠡᠦᠧᠨᠩᠪᠭᠮᠯᠰᠱᠲᠳᠵᠻᠼᠽᠾᠿᡀᡁᡆᡍᡎᡏᡐᡑᡒᡓᡔᡕᡖᡗᡙᡜᡝᡞᡟᡠᡡᡭᡮᡯᡰᡱᡲᡳᡴᢀᢁᢂᢋᢏᢐᢑᢒᢓᢛᢜᢞᢟᢠᢡᢢᢤᢥᢦ"
|
mongolian: "᠀᠐᠑᠒ᠠᠡᠦᠧᠨᠩᠪᠭᠮᠯᠰᠱᠲᠳᠵᠻᠼᠽᠾᠿᡀᡁᡆᡍᡎᡏᡐᡑᡒᡓᡔᡕᡖᡗᡙᡜᡝᡞᡟᡠᡡᡭᡮᡯᡰᡱᡲᡳᡴᢀᢁᢂᢋᢏᢐᢑᢒᢓᢛᢜᢞᢟᢠᢡᢢᢤᢥᢦ"
|
||||||
};
|
};
|
||||||
|
|
||||||
while (quantity) {
|
const culture = cells.culture[cell];
|
||||||
const [cell] = extractAnyElement(statues);
|
|
||||||
const id = addMarker({cell, icon, type});
|
|
||||||
const culture = cells.culture[cell];
|
|
||||||
|
|
||||||
const variant = ra(variants);
|
const variant = ra(variants);
|
||||||
const name = `${Names.getCulture(culture)} ${variant}`;
|
const name = `${Names.getCulture(culture)} ${variant}`;
|
||||||
const script = scripts[ra(Object.keys(scripts))];
|
const script = scripts[ra(Object.keys(scripts))];
|
||||||
const inscription = Array(rand(40, 100))
|
const inscription = Array(rand(40, 100))
|
||||||
.fill(null)
|
.fill(null)
|
||||||
.map(() => ra(script))
|
.map(() => ra(script))
|
||||||
.join("");
|
.join("");
|
||||||
const legend = `An ancient ${variant.toLowerCase()}. It has an inscription, but no one can translate it:
|
const legend = `An ancient ${variant.toLowerCase()}. It has an inscription, but no one can translate it:
|
||||||
<div style="font-size: 1.8em; line-break: anywhere;">${inscription}</div>`;
|
<div style="font-size: 1.8em; line-break: anywhere;">${inscription}</div>`;
|
||||||
notes.push({id, name, legend});
|
notes.push({id, name, legend});
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRuines(type, icon, multiplier) {
|
function listRuins({cells}) {
|
||||||
const {cells} = pack;
|
return cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.h[i] >= 20 && cells.h[i] < 60);
|
||||||
let ruins = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.h[i] >= 20 && cells.h[i] < 60));
|
}
|
||||||
let quantity = getQuantity(ruins, 80, 1200, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
|
function addRuins(id, cell) {
|
||||||
const types = [
|
const types = [
|
||||||
"City",
|
"City",
|
||||||
"Town",
|
"Town",
|
||||||
|
|
@ -845,37 +767,30 @@ window.Markers = (function () {
|
||||||
"Castle"
|
"Castle"
|
||||||
];
|
];
|
||||||
|
|
||||||
while (quantity) {
|
const ruinType = ra(types);
|
||||||
const [cell] = extractAnyElement(ruins);
|
const name = `Ruined ${ruinType}`;
|
||||||
const id = addMarker({cell, icon, type});
|
const legend = `Ruins of an ancient ${ruinType.toLowerCase()}. Untold riches may lie within.`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
const ruinType = ra(types);
|
|
||||||
const name = `Ruined ${ruinType}`;
|
|
||||||
const legend = `Ruins of an ancient ${ruinType.toLowerCase()}. Untold riches may lie within.`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPortals(type, icon, multiplier) {
|
function listPortals({burgs}) {
|
||||||
const {burgs} = pack;
|
return burgs
|
||||||
let portals = burgs
|
|
||||||
.slice(1, Math.ceil(burgs.length / 10) + 1)
|
.slice(1, Math.ceil(burgs.length / 10) + 1)
|
||||||
.filter(({cell}) => !occupied[cell])
|
.filter(({cell}) => !occupied[cell])
|
||||||
.map(burg => [burg.name, burg.cell]);
|
.map(burg => burg.cell);
|
||||||
let quantity = getQuantity(portals, 16, 8, multiplier);
|
|
||||||
if (!quantity) return;
|
|
||||||
|
|
||||||
while (quantity) {
|
|
||||||
const [portal] = extractAnyElement(portals);
|
|
||||||
const [burgName, cell] = portal;
|
|
||||||
const id = addMarker({cell, icon, type, px: 14});
|
|
||||||
const name = `${burgName} Portal`;
|
|
||||||
const legend = `An element of the magic portal system connecting major cities. Portals installed centuries ago, but still work fine`;
|
|
||||||
notes.push({id, name, legend});
|
|
||||||
quantity--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {generate, regenerate, getConfig, setConfig};
|
function addPortal(id, cell) {
|
||||||
|
const {cells, burgs} = pack;
|
||||||
|
|
||||||
|
// Portals can only be added to burgs
|
||||||
|
if (cells.burg[cell]) return;
|
||||||
|
const burgName = burgs[cells.burg[cell]].name;
|
||||||
|
|
||||||
|
const name = `${burgName} Portal`;
|
||||||
|
const legend = `An element of the magic portal system connecting major cities. Portals installed centuries ago, but still work fine`;
|
||||||
|
notes.push({id, name, legend});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {add, generate, regenerate, getConfig, setConfig};
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -706,14 +706,16 @@ function addMarkerOnClick() {
|
||||||
const point = d3.mouse(this);
|
const point = d3.mouse(this);
|
||||||
const x = rn(point[0], 2);
|
const x = rn(point[0], 2);
|
||||||
const y = rn(point[1], 2);
|
const y = rn(point[1], 2);
|
||||||
const i = markers.length ? last(markers).i + 1 : 0;
|
|
||||||
|
|
||||||
|
// Find the current cell
|
||||||
|
const cell = findCell(point[0], point[1]);
|
||||||
|
|
||||||
|
// Find the currently selected marker to use as a base
|
||||||
const isMarkerSelected = markers.length && elSelected?.node()?.parentElement?.id === "markers";
|
const isMarkerSelected = markers.length && elSelected?.node()?.parentElement?.id === "markers";
|
||||||
const selectedMarker = isMarkerSelected ? markers.find(marker => marker.i === +elSelected.attr("id").slice(6)) : null;
|
const selectedMarker = isMarkerSelected ? markers.find(marker => marker.i === +elSelected.attr("id").slice(6)) : null;
|
||||||
const baseMarker = selectedMarker || {icon: "❓"};
|
const baseMarker = selectedMarker || {icon: "❓"};
|
||||||
const marker = {...baseMarker, i, x, y};
|
const marker = Markers.add({...baseMarker, x, y, cell});
|
||||||
|
|
||||||
markers.push(marker);
|
|
||||||
const markersElement = document.getElementById("markers");
|
const markersElement = document.getElementById("markers");
|
||||||
const rescale = +markersElement.getAttribute("rescale");
|
const rescale = +markersElement.getAttribute("rescale");
|
||||||
markersElement.insertAdjacentHTML("beforeend", drawMarker(marker, rescale));
|
markersElement.insertAdjacentHTML("beforeend", drawMarker(marker, rescale));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue