From 05c900789885efe446f62a196fdcb568fa550a25 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 13 Sep 2021 00:06:03 +0300 Subject: [PATCH 01/44] new markers - monsters --- modules/markers-generator.js | 53 +++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 615f2051..79f7b815 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -14,6 +14,7 @@ window.Markers = (function () { addWaterfalls(number); addBattlefields(number); addDungeons(number); + addMonsters(number); TIME && console.timeEnd("addMarkers"); }; @@ -174,7 +175,7 @@ window.Markers = (function () { let dungeons = Array.from(cells.i.filter(i => cells.pop[i] > 0)); let count = dungeons.length < 100 ? 0 : Math.ceil((dungeons.length / 1000) * number); - if (count) addMarker("dungeon", "🗝️", 50, 52, 12); + if (count) addMarker("dungeon", "🗝️", 50, 51, 13); while (count && dungeons.length) { const cell = dungeons.splice(Math.floor(Math.random() * dungeons.length), 1); @@ -188,6 +189,56 @@ window.Markers = (function () { } } + function addMonsters(number) { + const {cells, features} = pack; + + const lakeMonster = number > 1 || P(0.7); + const hillMonster = number > 2 || P(0.7); + const seaMonster = number > 3 || P(0.4); + + if (lakeMonster) { + const lakes = features.filter(feature => feature.type === "lake" && feature.group === "freshwater"); + if (lakes.length) { + addMarker("lake_monster", "🐉", 50, 48, 12.5); + const lake = ra(lakes); + const cell = lake.firstCell; + const id = appendMarker(cell, "lake_monster"); + const name = `${lake.name} Monster`; + const length = gauss(10, 5, 5, 100); + const legend = `Rumors said a relic monster of ${length} ${heightUnit.value} long inhabits ${lake.name} Lake. Truth or lie, but folks are affraid to fish in the lake`; + notes.push({id, name, legend}); + } + } + + if (hillMonster) { + const hills = cells.i.filter(i => cells.h[i] >= 50 && cells.pop[i]); + if (hills.length) { + addMarker("hill_monster", "👹", 50, 50, 12); + const cell = ra(hills); + const id = appendMarker(cell, "hill_monster"); + const species = ra(["Ogre", "Troll", "Cyclopes", "Giant", "Monster", "Troll", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]); + const modus = ra(["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay"]); + const toponym = Names.getCulture(cells.culture[cell]); + const name = `${toponym} ${species}`; + const legend = `Locals tell tales of an old ${species} who inhabits ${toponym} hills and ${modus}`; + notes.push({id, name, legend}); + } + } + + if (seaMonster) { + const sea = cells.i.filter(i => cells.h[i] < 20 && cells.road[i] && features[cells.f[i]].type === "ocean"); + if (sea.length) { + addMarker("sea_monster", "🐙", 50, 50, 12); + const cell = ra(sea); + const id = appendMarker(cell, "sea_monster"); + const name = `${Names.getCultureShort(0)} Monster`; + const length = gauss(20, 10, 5, 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 addMarker(id, icon, x, y, size) { const markers = svg.select("#defs-markers"); if (markers.select("#marker_" + id).size()) return; From 8de49858baf2f455d01fe357934679658403fc1b Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 13 Sep 2021 00:17:04 +0300 Subject: [PATCH 02/44] markers - fix bridges placement --- modules/markers-generator.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 79f7b815..03f16335 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -78,17 +78,16 @@ window.Markers = (function () { } function addBridges(number) { - const {cells} = pack; + const {cells, burgs} = pack; - const meanRoad = d3.mean(cells.road.filter(r => r)); const meanFlux = d3.mean(cells.fl.filter(fl => fl)); - let bridges = Array.from(cells.i.filter(i => cells.burg[i] && cells.h[i] >= 20 && cells.r[i] && cells.fl[i] > meanFlux && cells.road[i] > meanRoad).sort((a, b) => cells.road[b] + cells.fl[b] / 10 - (cells.road[a] + cells.fl[a] / 10))); + let bridges = Array.from(cells.i.filter(i => cells.burg[i] && cells.t[i] !== 1 && burgs[cells.burg[i]].population > 20 && cells.r[i] && cells.fl[i] > meanFlux)); let count = !bridges.length ? 0 : Math.ceil((bridges.length / 12) * number); if (count) addMarker("bridge", "🌉", 50, 50, 14); while (count && bridges.length) { - const cell = bridges.splice(0, 1); + const cell = bridges.splice(Math.floor(Math.random() * bridges.length), 1); const id = appendMarker(cell, "bridge"); const burg = pack.burgs[cells.burg[cell]]; const river = pack.rivers.find(r => r.i === pack.cells.r[cell]); From fb8a79e7b61028b82fef303db3997854a21af2a6 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 13 Sep 2021 00:27:51 +0300 Subject: [PATCH 03/44] markers - fix number --- modules/markers-generator.js | 5 +++-- modules/ui/tools.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 03f16335..852e9e26 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -215,11 +215,12 @@ window.Markers = (function () { addMarker("hill_monster", "👹", 50, 50, 12); const cell = ra(hills); const id = appendMarker(cell, "hill_monster"); + const subject = ra(["Locals", "Old folks", "Old books", "Tipplers"]); const species = ra(["Ogre", "Troll", "Cyclopes", "Giant", "Monster", "Troll", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]); - const modus = ra(["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay"]); + const modusOperandi = ra(["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay", "eats their kids", "abducts young women"]); const toponym = Names.getCulture(cells.culture[cell]); const name = `${toponym} ${species}`; - const legend = `Locals tell tales of an old ${species} who inhabits ${toponym} hills and ${modus}`; + const legend = `${subject} tell tales of an old ${species} who inhabits ${toponym} hills and ${modusOperandi}`; notes.push({id, name, legend}); } } diff --git a/modules/ui/tools.js b/modules/ui/tools.js index 3880f2bb..420e8544 100644 --- a/modules/ui/tools.js +++ b/modules/ui/tools.js @@ -427,7 +427,7 @@ function regenerateMarkers(event) { }) .remove(); - Markers.generate(); + Markers.generate(number); if (!layerIsOn("toggleMarkers")) toggleMarkers(); } } From fdeae9160a5491bc21926d2404e49b8df8a184d2 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 13 Sep 2021 23:20:59 +0300 Subject: [PATCH 04/44] markers - sacred places --- modules/markers-generator.js | 107 +++++++++++++++++++++++++++++------ 1 file changed, 91 insertions(+), 16 deletions(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 852e9e26..978491e4 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -15,6 +15,7 @@ window.Markers = (function () { addBattlefields(number); addDungeons(number); addMonsters(number); + addSacredPlaces(number); TIME && console.timeEnd("addMarkers"); }; @@ -27,7 +28,7 @@ window.Markers = (function () { if (count) addMarker("volcano", "🌋", 52, 50, 13); while (count && mounts.length) { - const cell = mounts.splice(biased(0, mounts.length - 1, 5), 1); + const [cell] = mounts.splice(biased(0, mounts.length - 1, 5), 1); const [x, y] = cells.p[cell]; const id = appendMarker(cell, "volcano"); const proper = Names.getCulture(cells.culture[cell]); @@ -45,7 +46,7 @@ window.Markers = (function () { if (count) addMarker("hot_springs", "♨️", 50, 52, 12.5); while (count && springs.length) { - const cell = springs.splice(biased(1, springs.length - 1, 3), 1); + const [cell] = springs.splice(biased(1, springs.length - 1, 3), 1); const id = appendMarker(cell, "hot_springs"); const proper = Names.getCulture(cells.culture[cell]); const temp = convertTemperature(gauss(30, 15, 20, 100)); @@ -65,7 +66,7 @@ window.Markers = (function () { const resources = {salt: 5, gold: 2, silver: 4, copper: 2, iron: 3, lead: 1, tin: 1}; while (count && hills.length) { - const cell = hills.splice(Math.floor(Math.random() * hills.length), 1); + const [cell] = hills.splice(Math.floor(Math.random() * hills.length), 1); const id = appendMarker(cell, "mine"); const resource = rw(resources); const burg = pack.burgs[cells.burg[cell]]; @@ -87,7 +88,7 @@ window.Markers = (function () { if (count) addMarker("bridge", "🌉", 50, 50, 14); while (count && bridges.length) { - const cell = bridges.splice(Math.floor(Math.random() * bridges.length), 1); + const [cell] = bridges.splice(Math.floor(Math.random() * bridges.length), 1); const id = appendMarker(cell, "bridge"); const burg = pack.burgs[cells.burg[cell]]; const river = pack.rivers.find(r => r.i === pack.cells.r[cell]); @@ -101,8 +102,7 @@ window.Markers = (function () { function addInns(number) { const {cells} = pack; - const maxRoad = d3.max(cells.road) * 0.9; - let taverns = Array.from(cells.i.filter(i => cells.crossroad[i] && cells.h[i] >= 20 && cells.road[i] > maxRoad)); + let taverns = Array.from(cells.i.filter(i => cells.crossroad[i] && cells.h[i] >= 20 && cells.road[i])); if (!taverns.length) return; const count = Math.ceil(4 * number); addMarker("inn", "🍻", 50, 50, 14.5); @@ -112,7 +112,7 @@ window.Markers = (function () { const adj = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"]; for (let i = 0; i < taverns.length && i < count; i++) { - const cell = taverns.splice(Math.floor(Math.random() * taverns.length), 1); + const [cell] = taverns.splice(Math.floor(Math.random() * taverns.length), 1); const id = appendMarker(cell, "inn"); const type = P(0.3) ? "inn" : "tavern"; const name = P(0.5) ? ra(color) + " " + ra(animal) : P(0.6) ? ra(adj) + " " + ra(animal) : ra(adj) + " " + capitalize(type); @@ -128,7 +128,7 @@ window.Markers = (function () { const count = Math.ceil(4 * number); for (let i = 0; i < lighthouses.length && i < count; i++) { - const cell = lighthouses.splice(Math.floor(Math.random() * lighthouses.length), 1); + const [cell] = lighthouses.splice(Math.floor(Math.random() * lighthouses.length), 1); const id = appendMarker(cell, "lighthouse"); 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 keep the navigation safe`}); @@ -158,7 +158,7 @@ window.Markers = (function () { if (count) addMarker("battlefield", "⚔️", 50, 52, 12); while (count && battlefields.length) { - const cell = battlefields.splice(Math.floor(Math.random() * battlefields.length), 1); + const [cell] = battlefields.splice(Math.floor(Math.random() * battlefields.length), 1); const id = appendMarker(cell, "battlefield"); const campaign = ra(states[cells.state[cell]].campaigns); const date = generateDate(campaign.start, campaign.end); @@ -172,12 +172,14 @@ window.Markers = (function () { function addDungeons(number) { const {cells} = pack; - let dungeons = Array.from(cells.i.filter(i => cells.pop[i] > 0)); - let count = dungeons.length < 100 ? 0 : Math.ceil((dungeons.length / 1000) * number); - if (count) addMarker("dungeon", "🗝️", 50, 51, 13); + let dungeons = Array.from(cells.i.filter(i => cells.pop[i] > 0 && cells.pop[i] < 3)); + if (!dungeons.length) return; - while (count && dungeons.length) { - const cell = dungeons.splice(Math.floor(Math.random() * dungeons.length), 1); + let count = dungeons.length < 100 ? 0 : Math.ceil((dungeons.length / 500) * number); + addMarker("dungeon", "🗝️", 50, 51, 13); + + while (count) { + const [cell] = dungeons.splice(Math.floor(Math.random() * dungeons.length), 1); const id = appendMarker(cell, "dungeon"); const dungeonSeed = `${seed}${cell}`; @@ -216,7 +218,7 @@ window.Markers = (function () { const cell = ra(hills); const id = appendMarker(cell, "hill_monster"); const subject = ra(["Locals", "Old folks", "Old books", "Tipplers"]); - const species = ra(["Ogre", "Troll", "Cyclopes", "Giant", "Monster", "Troll", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]); + const species = ra(["Ogre", "Troll", "Cyclopes", "Giant", "Monster", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]); const modusOperandi = ra(["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay", "eats their kids", "abducts young women"]); const toponym = Names.getCulture(cells.culture[cell]); const name = `${toponym} ${species}`; @@ -228,7 +230,7 @@ window.Markers = (function () { if (seaMonster) { const sea = cells.i.filter(i => cells.h[i] < 20 && cells.road[i] && features[cells.f[i]].type === "ocean"); if (sea.length) { - addMarker("sea_monster", "🐙", 50, 50, 12); + addMarker("sea_monster", "🦑", 50, 50, 12); const cell = ra(sea); const id = appendMarker(cell, "sea_monster"); const name = `${Names.getCultureShort(0)} Monster`; @@ -239,6 +241,79 @@ window.Markers = (function () { } } + function addSacredPlaces(number) { + const {cells, cultures} = pack; + + { + let mountains = Array.from(cells.i.filter(i => cells.h[i] >= 70 && cells.c[i].some(c => cells.culture[c]) && cells.c[i].every(c => cells.h[c] < 60))); + let count = mountains.length ? Math.ceil((mountains.length / 5) * number) : 0; + if (count) addMarker("sacred_mountain", "🗻", 50, 48, 12); + + while (count && mountains.length) { + const [cell] = mountains.splice(Math.floor(Math.random() * mountains.length), 1); + const id = appendMarker(cell, "sacred_mountain"); + + 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}); + count--; + } + } + + { + let forests = Array.from(cells.i.filter(i => cells.culture[i] && [6, 8].includes(cells.biome[i]))); + let count = forests.length ? Math.ceil((forests.length / 1000) * number) : 0; + if (count) addMarker("sacred_forest", "🌳", 50, 50, 12); + + while (count) { + const [cell] = forests.splice(Math.floor(Math.random() * forests.length), 1); + const id = appendMarker(cell, "sacred_forest"); + + 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}); + count--; + } + } + + { + let borealForests = Array.from(cells.i.filter(i => cells.culture[i] && cells.biome[i] === 9)); + let count = borealForests.length ? Math.ceil((borealForests.length / 800) * number) : 0; + if (count) addMarker("pinery", "🌲", 50, 50, 13); + + while (count) { + const [cell] = borealForests.splice(Math.floor(Math.random() * borealForests.length), 1); + const id = appendMarker(cell, "pinery"); + + 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}); + count--; + } + } + + { + let oasises = Array.from(cells.i.filter(i => cells.culture[i] && cells.biome[i] === 1 && cells.pop[i] > 1 && cells.road[i])); + let count = oasises.length ? Math.ceil((oasises.length / 3) * number) : 0; + if (count) addMarker("palm_grove", "🌴", 50, 50, 13); + + while (count) { + const [cell] = oasises.splice(Math.floor(Math.random() * oasises.length), 1); + const id = appendMarker(cell, "palm_grove"); + + const culture = cells.culture[cell]; + const name = `${Names.getCulture(culture)} Pinery`; + const legend = `A sacred palm grove of ${cultures[culture].name} culture`; + notes.push({id, name, legend}); + count--; + } + } + } + function addMarker(id, icon, x, y, size) { const markers = svg.select("#defs-markers"); if (markers.select("#marker_" + id).size()) return; From b0ca9b9705b3f93113468569e0198f41ef6bb257 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Tue, 14 Sep 2021 21:25:08 +0300 Subject: [PATCH 05/44] markers - refactor functions --- modules/markers-generator.js | 405 +++++++++++++++++++---------------- 1 file changed, 225 insertions(+), 180 deletions(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 978491e4..687e14be 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -1,72 +1,95 @@ "use strict"; window.Markers = (function () { - const generate = (number = 1) => { - if (number === 0) return; + let multiplier = 1; + + const generate = requestedQtyMultiplier => { + if (requestedQtyMultiplier === 0) return; + if (requestedQtyMultiplier) multiplier = requestedQtyMultiplier; TIME && console.time("addMarkers"); - addVolcanoes(number); - addHotSprings(number); - addMines(number); - addBridges(number); - addInns(number); - addLighthouses(number); - addWaterfalls(number); - addBattlefields(number); - addDungeons(number); - addMonsters(number); - addSacredPlaces(number); + addVolcanoes(); + addHotSprings(); + addMines(); + addBridges(); + addInns(); + addLighthouses(); + addWaterfalls(); + addBattlefields(); + addDungeons(); + addLakeMonsters(); + addSeaMonsters(); + addHillMonsters(); + addSacredMountains(); + addSacredForests(); + addSacredPineries(); + addSacredPalmGroves(); TIME && console.timeEnd("addMarkers"); }; - function addVolcanoes(number) { + const getQuantity = (array, min, each) => { + if (array.length < min) return 0; + return Math.ceil((array.length / each) * multiplier); + }; + + const extractAnyElement = array => { + const index = Math.floor(Math.random() * array.length); + return array.splice(index, 1); + }; + + function addVolcanoes() { const {cells} = pack; - let mounts = Array.from(cells.i.filter(i => cells.h[i] > 70).sort((a, b) => cells.h[b] - cells.h[a])); - let count = mounts.length < 10 ? 0 : Math.ceil((mounts.length / 300) * number); - if (count) addMarker("volcano", "🌋", 52, 50, 13); + let mountains = Array.from(cells.i.filter(i => cells.h[i] >= 70).sort((a, b) => cells.h[b] - cells.h[a])); + let quantity = getQuantity(mountains, 10, 300); + if (!quantity) return; - while (count && mounts.length) { - const [cell] = mounts.splice(biased(0, mounts.length - 1, 5), 1); - const [x, y] = cells.p[cell]; + addMarker("volcano", "🌋", 52, 50, 13); + const highestMountains = mountains.slice(0, 20); + + while (quantity) { + const [cell] = extractAnyElement(highestMountains); const id = appendMarker(cell, "volcano"); 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([x, y])}`}); - count--; + notes.push({id, name, legend: `Active volcano. Height: ${getFriendlyHeight(cells.p[cell])}`}); + quantity--; } } - function addHotSprings(number) { + function addHotSprings() { const {cells} = pack; let springs = Array.from(cells.i.filter(i => cells.h[i] > 50).sort((a, b) => cells.h[b] - cells.h[a])); - let count = springs.length < 30 ? 0 : Math.ceil((springs.length / 1000) * number); - if (count) addMarker("hot_springs", "♨️", 50, 52, 12.5); + let quantity = getQuantity(springs, 30, 800); + if (!quantity) return; - while (count && springs.length) { - const [cell] = springs.splice(biased(1, springs.length - 1, 3), 1); + addMarker("hot_springs", "♨️", 50, 52, 12.5); + const highestSprings = springs.slice(0, 40); + + while (quantity) { + const [cell] = extractAnyElement(highestSprings); const id = appendMarker(cell, "hot_springs"); const proper = Names.getCulture(cells.culture[cell]); - const temp = convertTemperature(gauss(30, 15, 20, 100)); - notes.push({id, name: proper + " Hot Springs", legend: `A hot springs area. Temperature: ${temp}`}); - count--; + 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(number) { + function addMines() { const {cells} = pack; - let hills = Array.from(cells.i.filter(i => cells.h[i] > 47 && cells.burg[i])); - let count = !hills.length ? 0 : Math.ceil((hills.length / 7) * number); - if (!count) return; + let hillyBurgs = Array.from(cells.i.filter(i => cells.h[i] > 47 && cells.burg[i])); + let quantity = getQuantity(hillyBurgs, 1, 15); + if (!quantity) return; - addMarker("mine", "⛏️", 48, 50, 13.5); + addMarker("mine", "⛏️", 48, 50, 13); const resources = {salt: 5, gold: 2, silver: 4, copper: 2, iron: 3, lead: 1, tin: 1}; - while (count && hills.length) { - const [cell] = hills.splice(Math.floor(Math.random() * hills.length), 1); + while (quantity && hillyBurgs.length) { + const [cell] = extractAnyElement(hillyBurgs); const id = appendMarker(cell, "mine"); const resource = rw(resources); const burg = pack.burgs[cells.burg[cell]]; @@ -74,75 +97,80 @@ window.Markers = (function () { 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}); - count--; + quantity--; } } - function addBridges(number) { + function addBridges() { const {cells, burgs} = pack; const meanFlux = d3.mean(cells.fl.filter(fl => fl)); - let bridges = Array.from(cells.i.filter(i => cells.burg[i] && cells.t[i] !== 1 && burgs[cells.burg[i]].population > 20 && cells.r[i] && cells.fl[i] > meanFlux)); - let count = !bridges.length ? 0 : Math.ceil((bridges.length / 12) * number); - if (count) addMarker("bridge", "🌉", 50, 50, 14); + let quantity = getQuantity(bridges, 1, 5); + if (!quantity) return; - while (count && bridges.length) { - const [cell] = bridges.splice(Math.floor(Math.random() * bridges.length), 1); + addMarker("bridge", "🌉", 50, 50, 14); + + while (quantity) { + const [cell] = extractAnyElement(bridges); const id = appendMarker(cell, "bridge"); 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; notes.push({id, name: `${name} Bridge`, legend: `A stone bridge over the ${riverName} near ${burg.name}`}); - count--; + quantity--; } } - function addInns(number) { + function addInns() { const {cells} = pack; - let taverns = Array.from(cells.i.filter(i => cells.crossroad[i] && cells.h[i] >= 20 && cells.road[i])); - if (!taverns.length) return; - const count = Math.ceil(4 * number); - addMarker("inn", "🍻", 50, 50, 14.5); + let taverns = Array.from(cells.i.filter(i => cells.h[i] >= 20 && cells.road[i] > 4 && cells.pop[i] > 10)); + let quantity = getQuantity(taverns, 1, 100); + if (!quantity) return; + addMarker("inn", "🍻", 50, 50, 14); - const color = ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"]; - const animal = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"]; - const adj = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"]; + const colors = ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"]; + const animals = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"]; + const adjectives = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"]; - for (let i = 0; i < taverns.length && i < count; i++) { - const [cell] = taverns.splice(Math.floor(Math.random() * taverns.length), 1); + while (quantity) { + const [cell] = extractAnyElement(taverns); const id = appendMarker(cell, "inn"); const type = P(0.3) ? "inn" : "tavern"; - const name = P(0.5) ? ra(color) + " " + ra(animal) : P(0.6) ? ra(adj) + " " + ra(animal) : ra(adj) + " " + capitalize(type); + const name = P(0.5) ? ra(colors) + " " + ra(animals) : P(0.6) ? ra(adjectives) + " " + ra(animals) : ra(adjectives) + " " + capitalize(type); notes.push({id, name: "The " + name, legend: `A big and famous roadside ${type}`}); + quantity--; } } - function addLighthouses(number) { + function addLighthouses() { const {cells} = pack; const lighthouses = Array.from(cells.i.filter(i => cells.harbor[i] > 6 && cells.c[i].some(c => cells.h[c] < 20 && cells.road[c]))); - if (lighthouses.length) addMarker("lighthouse", "🚨", 50, 50, 16); - const count = Math.ceil(4 * number); + let quantity = getQuantity(lighthouses, 1, 2); + if (!quantity) return; + addMarker("lighthouse", "🚨", 50, 50, 15); - for (let i = 0; i < lighthouses.length && i < count; i++) { - const [cell] = lighthouses.splice(Math.floor(Math.random() * lighthouses.length), 1); + while (quantity) { + const [cell] = extractAnyElement(lighthouses); const id = appendMarker(cell, "lighthouse"); 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 keep the navigation safe`}); + quantity--; } } - function addWaterfalls(number) { + function addWaterfalls() { const {cells} = pack; - const waterfalls = Array.from(cells.i.filter(i => cells.r[i] && cells.h[i] > 70)); - if (waterfalls.length) addMarker("waterfall", "⟱", 50, 54, 16.5); - const count = Math.ceil(3 * number); + const waterfalls = Array.from(cells.i.filter(i => cells.r[i] && cells.h[i] >= 50 && cells.c[i].some(c => cells.h[c] < 40 && cells.r[c]))); + const quantity = getQuantity(waterfalls, 1, 3); + if (!quantity) return; + addMarker("waterfall", "⟱", 50, 54, 16); - for (let i = 0; i < waterfalls.length && i < count; i++) { + for (let i = 0; i < waterfalls.length && i < quantity; i++) { const cell = waterfalls[i]; const id = appendMarker(cell, "waterfall"); const proper = cells.burg[cell] ? pack.burgs[cells.burg[cell]].name : Names.getCulture(cells.culture[cell]); @@ -150,167 +178,183 @@ window.Markers = (function () { } } - function addBattlefields(number) { + function addBattlefields() { const {cells, states} = pack; let battlefields = Array.from(cells.i.filter(i => cells.state[i] && cells.pop[i] > 2 && cells.h[i] < 50 && cells.h[i] > 25)); - let count = battlefields.length < 100 ? 0 : Math.ceil((battlefields.length / 500) * number); - if (count) addMarker("battlefield", "⚔️", 50, 52, 12); + let quantity = getQuantity(battlefields, 50, 700); + if (!quantity) return; + addMarker("battlefield", "⚔️", 50, 52, 12); - while (count && battlefields.length) { - const [cell] = battlefields.splice(Math.floor(Math.random() * battlefields.length), 1); + while (quantity && battlefields.length) { + const [cell] = extractAnyElement(battlefields); const id = appendMarker(cell, "battlefield"); const campaign = ra(states[cells.state[cell]].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}); - count--; + quantity--; } } - function addDungeons(number) { + function addDungeons() { const {cells} = pack; - let dungeons = Array.from(cells.i.filter(i => cells.pop[i] > 0 && cells.pop[i] < 3)); - if (!dungeons.length) return; - - let count = dungeons.length < 100 ? 0 : Math.ceil((dungeons.length / 500) * number); + let dungeons = Array.from(cells.i.filter(i => cells.pop[i] && cells.pop[i] < 3)); + let quantity = getQuantity(dungeons, 30, 200); + if (!quantity) return; addMarker("dungeon", "🗝️", 50, 51, 13); - while (count) { - const [cell] = dungeons.splice(Math.floor(Math.random() * dungeons.length), 1); + while (quantity) { + const [cell] = extractAnyElement(dungeons); const id = appendMarker(cell, "dungeon"); const dungeonSeed = `${seed}${cell}`; const name = "Dungeon"; const legend = `
Undiscovered dungeon. See One page dungeon.
`; notes.push({id, name, legend}); - count--; + quantity--; } } - function addMonsters(number) { + function addLakeMonsters() { + const {features} = pack; + + const lakes = features.filter(feature => feature.type === "lake" && feature.group === "freshwater"); + let quantity = getQuantity(lakes, 2, 10); + if (!quantity) return; + addMarker("lake_monster", "🐉", 50, 48, 12.5); + + while (quantity) { + const [lake] = extractAnyElement(lakes); + const cell = lake.firstCell; + const id = appendMarker(cell, "lake_monster"); + const name = `${lake.name} Monster`; + const length = gauss(10, 5, 5, 100); + const legend = `Rumors said a relic monster of ${length} ${heightUnit.value} long inhabits ${lake.name} Lake. Truth or lie, but folks are affraid to fish in the lake`; + notes.push({id, name, legend}); + quantity--; + } + } + + function addSeaMonsters() { const {cells, features} = pack; - const lakeMonster = number > 1 || P(0.7); - const hillMonster = number > 2 || P(0.7); - const seaMonster = number > 3 || P(0.4); + const sea = Array.from(cells.i.filter(i => cells.h[i] < 20 && cells.road[i] && features[cells.f[i]].type === "ocean")); + let quantity = getQuantity(sea, 50, 700); + if (!quantity) return; + addMarker("sea_monster", "🦑", 50, 50, 12); - if (lakeMonster) { - const lakes = features.filter(feature => feature.type === "lake" && feature.group === "freshwater"); - if (lakes.length) { - addMarker("lake_monster", "🐉", 50, 48, 12.5); - const lake = ra(lakes); - const cell = lake.firstCell; - const id = appendMarker(cell, "lake_monster"); - const name = `${lake.name} Monster`; - const length = gauss(10, 5, 5, 100); - const legend = `Rumors said a relic monster of ${length} ${heightUnit.value} long inhabits ${lake.name} Lake. Truth or lie, but folks are affraid to fish in the lake`; - notes.push({id, name, legend}); - } - } - - if (hillMonster) { - const hills = cells.i.filter(i => cells.h[i] >= 50 && cells.pop[i]); - if (hills.length) { - addMarker("hill_monster", "👹", 50, 50, 12); - const cell = ra(hills); - const id = appendMarker(cell, "hill_monster"); - const subject = ra(["Locals", "Old folks", "Old books", "Tipplers"]); - const species = ra(["Ogre", "Troll", "Cyclopes", "Giant", "Monster", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]); - const modusOperandi = ra(["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay", "eats their kids", "abducts young women"]); - const toponym = Names.getCulture(cells.culture[cell]); - const name = `${toponym} ${species}`; - const legend = `${subject} tell tales of an old ${species} who inhabits ${toponym} hills and ${modusOperandi}`; - notes.push({id, name, legend}); - } - } - - if (seaMonster) { - const sea = cells.i.filter(i => cells.h[i] < 20 && cells.road[i] && features[cells.f[i]].type === "ocean"); - if (sea.length) { - addMarker("sea_monster", "🦑", 50, 50, 12); - const cell = ra(sea); - const id = appendMarker(cell, "sea_monster"); - const name = `${Names.getCultureShort(0)} Monster`; - const length = gauss(20, 10, 5, 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}); - } + while (quantity) { + const [cell] = extractAnyElement(sea); + const id = appendMarker(cell, "sea_monster"); + 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 addSacredPlaces(number) { + function addHillMonsters() { + const {cells} = pack; + + const hills = Array.from(cells.i.filter(i => cells.h[i] >= 50 && cells.pop[i])); + let quantity = getQuantity(hills, 30, 600); + if (!quantity) return; + addMarker("hill_monster", "👹", 50, 54, 13); + + const subjects = ["Locals", "Old folks", "Old books", "Tipplers"]; + const species = ["Ogre", "Troll", "Cyclopes", "Giant", "Monster", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]; + const modusOperandi = ["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay", "eats their kids", "abducts young women"]; + + while (quantity) { + const [cell] = extractAnyElement(hills); + const id = appendMarker(cell, "hill_monster"); + const monster = ra(species); + const toponym = Names.getCulture(cells.culture[cell]); + const name = `${toponym} ${monster}`; + const legend = `${ra(subjects)} tell tales of an old ${monster} who inhabits ${toponym} hills and ${ra(modusOperandi)}`; + notes.push({id, name, legend}); + quantity--; + } + } + + function addSacredMountains() { const {cells, cultures} = pack; - { - let mountains = Array.from(cells.i.filter(i => cells.h[i] >= 70 && cells.c[i].some(c => cells.culture[c]) && cells.c[i].every(c => cells.h[c] < 60))); - let count = mountains.length ? Math.ceil((mountains.length / 5) * number) : 0; - if (count) addMarker("sacred_mountain", "🗻", 50, 48, 12); + let lonelyMountains = Array.from(cells.i.filter(i => cells.h[i] >= 70 && cells.c[i].some(c => cells.culture[c]) && cells.c[i].every(c => cells.h[c] < 60))); + let quantity = getQuantity(lonelyMountains, 1, 5); + if (!quantity) return; + addMarker("sacred_mountain", "🗻", 50, 48, 12); - while (count && mountains.length) { - const [cell] = mountains.splice(Math.floor(Math.random() * mountains.length), 1); - const id = appendMarker(cell, "sacred_mountain"); - - 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}); - count--; - } + while (quantity) { + const [cell] = extractAnyElement(lonelyMountains); + const id = appendMarker(cell, "sacred_mountain"); + 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--; } + } - { - let forests = Array.from(cells.i.filter(i => cells.culture[i] && [6, 8].includes(cells.biome[i]))); - let count = forests.length ? Math.ceil((forests.length / 1000) * number) : 0; - if (count) addMarker("sacred_forest", "🌳", 50, 50, 12); + function addSacredForests() { + const {cells, cultures} = pack; - while (count) { - const [cell] = forests.splice(Math.floor(Math.random() * forests.length), 1); - const id = appendMarker(cell, "sacred_forest"); + let temperateForests = Array.from(cells.i.filter(i => cells.culture[i] && [6, 8].includes(cells.biome[i]))); + let quantity = getQuantity(temperateForests, 30, 1000); + if (!quantity) return; + addMarker("sacred_forest", "🌳", 50, 50, 12); - 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}); - count--; - } + while (quantity) { + const [cell] = extractAnyElement(temperateForests); + const id = appendMarker(cell, "sacred_forest"); + 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--; } + } - { - let borealForests = Array.from(cells.i.filter(i => cells.culture[i] && cells.biome[i] === 9)); - let count = borealForests.length ? Math.ceil((borealForests.length / 800) * number) : 0; - if (count) addMarker("pinery", "🌲", 50, 50, 13); + function addSacredPineries() { + const {cells, cultures} = pack; - while (count) { - const [cell] = borealForests.splice(Math.floor(Math.random() * borealForests.length), 1); - const id = appendMarker(cell, "pinery"); + let borealForests = Array.from(cells.i.filter(i => cells.culture[i] && cells.biome[i] === 9)); + let quantity = getQuantity(borealForests, 30, 800); + if (!quantity) return; + addMarker("pinery", "🌲", 50, 50, 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}); - count--; - } + while (quantity) { + const [cell] = extractAnyElement(borealForests); + const id = appendMarker(cell, "pinery"); + 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--; } + } - { - let oasises = Array.from(cells.i.filter(i => cells.culture[i] && cells.biome[i] === 1 && cells.pop[i] > 1 && cells.road[i])); - let count = oasises.length ? Math.ceil((oasises.length / 3) * number) : 0; - if (count) addMarker("palm_grove", "🌴", 50, 50, 13); + function addSacredPalmGroves() { + const {cells, cultures} = pack; - while (count) { - const [cell] = oasises.splice(Math.floor(Math.random() * oasises.length), 1); - const id = appendMarker(cell, "palm_grove"); + let oasises = Array.from(cells.i.filter(i => cells.culture[i] && cells.biome[i] === 1 && cells.pop[i] > 1 && cells.road[i])); + let quantity = getQuantity(oasises, 1, 100); + if (!quantity) return; + addMarker("palm_grove", "🌴", 50, 50, 13); - const culture = cells.culture[cell]; - const name = `${Names.getCulture(culture)} Pinery`; - const legend = `A sacred palm grove of ${cultures[culture].name} culture`; - notes.push({id, name, legend}); - count--; - } + while (quantity) { + const [cell] = extractAnyElement(oasises); + const id = appendMarker(cell, "palm_grove"); + const culture = cells.culture[cell]; + const name = `${Names.getCulture(culture)} Pinery`; + const legend = `A sacred palm grove of ${cultures[culture].name} culture`; + notes.push({id, name, legend}); + quantity--; } } @@ -322,6 +366,7 @@ window.Markers = (function () { .append("symbol") .attr("id", "marker_" + id) .attr("viewBox", "0 0 30 30"); + symbol.append("path").attr("d", "M6,19 l9,10 L24,19").attr("fill", "#000000").attr("stroke", "none"); symbol.append("circle").attr("cx", 15).attr("cy", 15).attr("r", 10).attr("fill", "#ffffff").attr("stroke", "#000000").attr("stroke-width", 1); symbol From 5e7d34e5bd2613b451abcc20b7f090df5a670cf7 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Tue, 14 Sep 2021 22:49:48 +0300 Subject: [PATCH 06/44] markers - course generator for inns --- modules/markers-generator.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 687e14be..ec882de8 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -134,13 +134,20 @@ window.Markers = (function () { const colors = ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"]; const animals = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"]; const adjectives = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"]; + const methods = ["Boiled", "Grilled", "Roasted", "Spit-roasted", "Stewed", "Stuffed", "Jugged", "Mashed", "Baked", "Braised", "Poached", "Marinated", "Pickled", "Smoked", "Dried", "Dry-aged", "Corned", "Fried", "Pan-fried", "Deep-fried", "Dressed", "Steamed", "Cured", "Syrupped"]; + const courses = ["beef", "pork", "bacon", "chicken", "lamb", "chevon", "hare", "rabbit", "hart", "deer", "antlers", "bear", "buffalo", "badger", "beaver", "turkey", "pheasant", "duck", "goose", "teal", "quail", "pigeon", "seal", "carp", "bass", "pike", "catfish", "sturgeon", "escallop", "pie", "cake", "pottage", "pudding"]; + const types = ["hot", "cold", "fire", "ice", "smoky", "misty", "shiny", "sweet", "bitter", "salty", "sour", "sparkling", "smelly"]; + const drinks = ["wine", "brandy", "jinn", "whisky", "rom", "beer", "cider", "mead", "liquor", "spirit", "vodka", "tequila", "absinthe", "nectar", "milk", "kvass", "kumis", "tea", "water", "juice", "sap"]; while (quantity) { const [cell] = extractAnyElement(taverns); const id = appendMarker(cell, "inn"); const type = P(0.3) ? "inn" : "tavern"; const name = P(0.5) ? ra(colors) + " " + ra(animals) : P(0.6) ? ra(adjectives) + " " + ra(animals) : ra(adjectives) + " " + capitalize(type); - notes.push({id, name: "The " + name, legend: `A big and famous roadside ${type}`}); + const course = `${ra(methods)} ${ra(courses)}`; + const drink = `${P(0.5) ? ra(types) : ra(colors)} ${ra(drinks)}`; + const legend = `A big and famous roadside ${type}. ${course} with ${drink.toLowerCase()} is served here`; + notes.push({id, name: "The " + name, legend}); quantity--; } } From 2f2697e60faf323112c8eff093c24e0c8645e2e1 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Tue, 14 Sep 2021 23:42:44 +0300 Subject: [PATCH 07/44] markers - course generator enhancement --- modules/markers-generator.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index ec882de8..5121d6de 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -135,7 +135,7 @@ window.Markers = (function () { const animals = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"]; const adjectives = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"]; const methods = ["Boiled", "Grilled", "Roasted", "Spit-roasted", "Stewed", "Stuffed", "Jugged", "Mashed", "Baked", "Braised", "Poached", "Marinated", "Pickled", "Smoked", "Dried", "Dry-aged", "Corned", "Fried", "Pan-fried", "Deep-fried", "Dressed", "Steamed", "Cured", "Syrupped"]; - const courses = ["beef", "pork", "bacon", "chicken", "lamb", "chevon", "hare", "rabbit", "hart", "deer", "antlers", "bear", "buffalo", "badger", "beaver", "turkey", "pheasant", "duck", "goose", "teal", "quail", "pigeon", "seal", "carp", "bass", "pike", "catfish", "sturgeon", "escallop", "pie", "cake", "pottage", "pudding"]; + const courses = ["beef", "pork", "bacon", "chicken", "lamb", "chevon", "hare", "rabbit", "hart", "deer", "antlers", "bear", "buffalo", "badger", "beaver", "turkey", "pheasant", "duck", "goose", "teal", "quail", "pigeon", "seal", "carp", "bass", "pike", "catfish", "sturgeon", "escallop", "pie", "cake", "pottage", "pudding", "onions", "carrot", "potato", "beet", "garlic", "cabbage", "eggplant", "eggs", "broccoli", "zucchini", "pepper", "olives", "pumpkin", "spinach", "peas", "chickpea", "beans", "rice", "pasta", "bread", "apples", "peaches", "pears", "melon", "oranges", "mango", "tomatoes", "cheese", "corn", "rat tails", "pig ears"]; const types = ["hot", "cold", "fire", "ice", "smoky", "misty", "shiny", "sweet", "bitter", "salty", "sour", "sparkling", "smelly"]; const drinks = ["wine", "brandy", "jinn", "whisky", "rom", "beer", "cider", "mead", "liquor", "spirit", "vodka", "tequila", "absinthe", "nectar", "milk", "kvass", "kumis", "tea", "water", "juice", "sap"]; @@ -143,10 +143,13 @@ window.Markers = (function () { const [cell] = extractAnyElement(taverns); const id = appendMarker(cell, "inn"); const type = P(0.3) ? "inn" : "tavern"; - const name = P(0.5) ? ra(colors) + " " + ra(animals) : P(0.6) ? ra(adjectives) + " " + ra(animals) : ra(adjectives) + " " + capitalize(type); - const course = `${ra(methods)} ${ra(courses)}`; - const drink = `${P(0.5) ? ra(types) : ra(colors)} ${ra(drinks)}`; - const legend = `A big and famous roadside ${type}. ${course} with ${drink.toLowerCase()} is served here`; + const isAnimalThemed = P(0.7); + const animal = ra(animals); + const name = isAnimalThemed ? (P(0.6) ? ra(colors) + " " + animal : ra(adjectives) + " " + animal) : ra(adjectives) + " " + capitalize(type); + const meal = isAnimalThemed && P(0.3) ? animal : ra(courses); + const course = `${ra(methods)} ${meal}`.toLowerCase(); + const drink = `${P(0.5) ? ra(types) : ra(colors)} ${ra(drinks)}`.toLowerCase(); + const legend = `A big and famous roadside ${type}. Delicious ${course} with ${drink} is served here`; notes.push({id, name: "The " + name, legend}); quantity--; } @@ -219,7 +222,7 @@ window.Markers = (function () { const dungeonSeed = `${seed}${cell}`; const name = "Dungeon"; - const legend = `
Undiscovered dungeon. See One page dungeon.
`; + const legend = `
Undiscovered dungeon. See One page dungeon
`; notes.push({id, name, legend}); quantity--; } From d176e3188c8519c896dc2962175105e25c12ac0a Mon Sep 17 00:00:00 2001 From: Azgaar Date: Wed, 15 Sep 2021 21:51:37 +0300 Subject: [PATCH 08/44] markers - bandits and pirates --- modules/markers-generator.js | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 5121d6de..c940154b 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -24,6 +24,8 @@ window.Markers = (function () { addSacredForests(); addSacredPineries(); addSacredPalmGroves(); + addBrigands(); + addPirates(); TIME && console.timeEnd("addMarkers"); }; @@ -134,7 +136,7 @@ window.Markers = (function () { const colors = ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"]; const animals = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"]; const adjectives = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"]; - const methods = ["Boiled", "Grilled", "Roasted", "Spit-roasted", "Stewed", "Stuffed", "Jugged", "Mashed", "Baked", "Braised", "Poached", "Marinated", "Pickled", "Smoked", "Dried", "Dry-aged", "Corned", "Fried", "Pan-fried", "Deep-fried", "Dressed", "Steamed", "Cured", "Syrupped"]; + const methods = ["Boiled", "Grilled", "Roasted", "Spit-roasted", "Stewed", "Stuffed", "Jugged", "Mashed", "Baked", "Braised", "Poached", "Marinated", "Pickled", "Smoked", "Dried", "Dry-aged", "Corned", "Fried", "Pan-fried", "Deep-fried", "Dressed", "Steamed", "Cured", "Syrupped", "Flame-Broiled"]; const courses = ["beef", "pork", "bacon", "chicken", "lamb", "chevon", "hare", "rabbit", "hart", "deer", "antlers", "bear", "buffalo", "badger", "beaver", "turkey", "pheasant", "duck", "goose", "teal", "quail", "pigeon", "seal", "carp", "bass", "pike", "catfish", "sturgeon", "escallop", "pie", "cake", "pottage", "pudding", "onions", "carrot", "potato", "beet", "garlic", "cabbage", "eggplant", "eggs", "broccoli", "zucchini", "pepper", "olives", "pumpkin", "spinach", "peas", "chickpea", "beans", "rice", "pasta", "bread", "apples", "peaches", "pears", "melon", "oranges", "mango", "tomatoes", "cheese", "corn", "rat tails", "pig ears"]; const types = ["hot", "cold", "fire", "ice", "smoky", "misty", "shiny", "sweet", "bitter", "salty", "sour", "sparkling", "smelly"]; const drinks = ["wine", "brandy", "jinn", "whisky", "rom", "beer", "cider", "mead", "liquor", "spirit", "vodka", "tequila", "absinthe", "nectar", "milk", "kvass", "kumis", "tea", "water", "juice", "sap"]; @@ -176,7 +178,7 @@ window.Markers = (function () { const {cells} = pack; const waterfalls = Array.from(cells.i.filter(i => cells.r[i] && cells.h[i] >= 50 && cells.c[i].some(c => cells.h[c] < 40 && cells.r[c]))); - const quantity = getQuantity(waterfalls, 1, 3); + const quantity = getQuantity(waterfalls, 1, 5); if (!quantity) return; addMarker("waterfall", "⟱", 50, 54, 16); @@ -276,7 +278,7 @@ window.Markers = (function () { addMarker("hill_monster", "👹", 50, 54, 13); const subjects = ["Locals", "Old folks", "Old books", "Tipplers"]; - const species = ["Ogre", "Troll", "Cyclopes", "Giant", "Monster", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]; + const species = ["Ogre", "Troll", "Cyclops", "Giant", "Monster", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"]; const modusOperandi = ["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay", "eats their kids", "abducts young women"]; while (quantity) { @@ -368,6 +370,49 @@ window.Markers = (function () { } } + function addBrigands() { + const {cells} = pack; + + let roads = Array.from(cells.i.filter(i => cells.culture[i] && cells.road[i] > 4)); + let quantity = getQuantity(roads, 50, 100); + if (!quantity) return; + addMarker("brigands", "💰", 50, 50, 13); + + const animals = ["Apes", "Badgers", "Bears", "Beavers", "Bisons", "Boars", "Cats", "Crows", "Dogs", "Foxes", "Hares", "Hawks", "Hyenas", "Jackals", "Jaguars", "Leopards", "Lions", "Owls", "Panthers", "Rats", "Ravens", "Rooks", "Scorpions", "Sharks", "Snakes", "Spiders", "Tigers", "Wolfs", "Wolverines", "Falcons"]; + const types = {brigands: 4, bandits: 3, robbers: 1, highwaymen: 1}; + + while (quantity) { + const [cell] = extractAnyElement(roads); + const id = appendMarker(cell, "brigands"); + const culture = cells.culture[cell]; + const biome = cells.biome[cell]; + const height = cells.p[cell]; + const locality = height >= 70 ? "highlander" : [1, 2].includes(biome) ? "desert" : [3, 4].includes(biome) ? "mounted" : [5, 6, 7, 8, 9].includes(biome) ? "forest" : biome === 12 ? "swamp" : "angry"; + const name = `${Names.getCulture(culture)} ${ra(animals)}`; + const legend = `A gang of ${locality} ${rw(types)}`; + notes.push({id, name, legend}); + quantity--; + } + } + + function addPirates() { + const {cells} = pack; + + let searoutes = Array.from(cells.i.filter(i => cells.h[i] < 20 && cells.road[i])); + let quantity = getQuantity(searoutes, 40, 300); + if (!quantity) return; + addMarker("pirates", "🏴‍☠️", 51, 50, 12); + + while (quantity) { + const [cell] = extractAnyElement(searoutes); + const id = appendMarker(cell, "pirates"); + const name = `Pirates`; + const legend = `Pirate ships have been spotted in these waters`; + notes.push({id, name, legend}); + quantity--; + } + } + function addMarker(id, icon, x, y, size) { const markers = svg.select("#defs-markers"); if (markers.select("#marker_" + id).size()) return; From a9755dacc8a13b43c20c819bfe05871a39bed955 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Thu, 16 Sep 2021 10:20:54 +0300 Subject: [PATCH 09/44] burg editor - MFCG preview --- index.css | 6 ++ index.html | 16 ++++- main.js | 1 - modules/markers-generator.js | 2 +- modules/ui/burg-editor.js | 111 ++++++++++++++++++----------------- 5 files changed, 78 insertions(+), 58 deletions(-) diff --git a/index.css b/index.css index a5768367..1b0512fe 100644 --- a/index.css +++ b/index.css @@ -36,6 +36,12 @@ textarea { width: 100%; } +iframe { + border: 0; + pointer-events: none; + width: 100%; +} + #map { background-color: #000000; mask-mode: alpha; diff --git a/index.html b/index.html index a143b30c..c84bcd61 100644 --- a/index.html +++ b/index.html @@ -1947,8 +1947,9 @@ diff --git a/modules/load.js b/modules/load.js index b6699857..672edec0 100644 --- a/modules/load.js +++ b/modules/load.js @@ -815,6 +815,7 @@ function parseLoadedData(data) { const riverPoints = []; const length = node.getTotalLength() / 2; + if (!length) continue; const segments = Math.ceil(length / 6); const increment = length / segments; diff --git a/modules/markers-generator.js b/modules/markers-generator.js index 74448046..2ee99eef 100644 --- a/modules/markers-generator.js +++ b/modules/markers-generator.js @@ -493,50 +493,5 @@ window.Markers = (function () { return "marker" + i; } - function addMarkerGroup(id, icon, x, y, size) { - // TODO: remove and replace with individual markers rendering - const markers = svg.select("#defs-markers"); - if (markers.select("#marker_" + id).size()) return; - - const symbol = markers - .append("symbol") - .attr("id", "marker_" + id) - .attr("viewBox", "0 0 30 30"); - - symbol.append("path").attr("d", "M6,19 l9,10 L24,19").attr("fill", "#000000").attr("stroke", "none"); - symbol.append("circle").attr("cx", 15).attr("cy", 15).attr("r", 10).attr("fill", "#ffffff").attr("stroke", "#000000").attr("stroke-width", 1); - symbol - .append("text") - .attr("x", x + "%") - .attr("y", y + "%") - .attr("fill", "#000000") - .attr("stroke", "#3200ff") - .attr("stroke-width", 0) - .attr("font-size", size + "px") - .attr("dominant-baseline", "central") - .text(icon); - } - - function drawMarker(cell, type) { - const [x, y] = getMarkerCoordinates(cell); - const id = getNextId("marker"); - const name = "#marker_" + type; - - markers - .append("use") - .attr("id", id) - .attr("xlink:href", name) - .attr("data-id", name) - .attr("data-x", x) - .attr("data-y", y) - .attr("x", x - 15) - .attr("y", y - 30) - .attr("data-size", 1) - .attr("width", 30) - .attr("height", 30); - - return id; - } - return {generate}; })(); diff --git a/modules/ui/editors.js b/modules/ui/editors.js index cfc798a9..55a88e92 100644 --- a/modules/ui/editors.js +++ b/modules/ui/editors.js @@ -29,7 +29,7 @@ function clicked() { else if (grand.id === "burgIcons") editBurg(); else if (parent.id === "ice") editIce(); else if (parent.id === "terrain") editReliefIcon(); - else if (parent.id === "markers") editMarker(); + else if (grand.id === "markers") editMarker(); else if (grand.id === "coastline") editCoastline(); else if (great.id === "armies") editRegiment(); else if (pack.cells.t[i] === 1) { @@ -948,6 +948,12 @@ function selectIcon(initial, callback) { }); } +// add and register event listeners to clean up on editor closure +function listen(element, event, handler) { + element.addEventListener(event, handler); + return () => element.removeEventListener(event, handler); +} + // Calls the refresh functionality on all editors currently open. function refreshAllEditors() { TIME && console.time("refreshAllEditors"); diff --git a/modules/ui/layers.js b/modules/ui/layers.js index 7efea9f8..76cf9d79 100644 --- a/modules/ui/layers.js +++ b/modules/ui/layers.js @@ -965,7 +965,9 @@ function drawStates() { const bodyString = bodyData.map(d => ``).join(""); const gapString = gapData.map(d => ``).join(""); const clipString = bodyData.map(d => ``).join(""); - const haloString = haloData.map(d => ``).join(""); + const haloString = haloData + .map(d => ``) + .join(""); statesBody.html(bodyString + gapString); defs.select("#statePaths").html(clipString); @@ -1522,7 +1524,7 @@ function drawMarkers() { markers.html(html.join("")); } -const getPin = (shape = "no", fill = "#fff", stroke = "#000") => { +const getPin = (shape = "bubble", fill = "#fff", stroke = "#000") => { if (shape === "bubble") return ``; if (shape === "pin") return ``; if (shape === "square") return ``; diff --git a/modules/ui/markers-editor.js b/modules/ui/markers-editor.js index c1ea19f6..07bdef31 100644 --- a/modules/ui/markers-editor.js +++ b/modules/ui/markers-editor.js @@ -1,168 +1,113 @@ "use strict"; function editMarker() { if (customization) return; - closeDialogs("#markerEditor, .stable"); - $("#markerEditor").dialog(); + closeDialogs(".stable"); + + const element = d3.event.target.parentElement; + elSelected = d3.select(element).call(d3.drag().on("start", dragMarker)).classed("draggable", true); + const marker = pack.markers.find(({i}) => Number(elSelected.attr("id").slice(6)) === i); + if (!marker) return; + + // dom elements + const markerSelectGroup = document.getElementById("markerSelectGroup"); + const markerIconSize = document.getElementById("markerIconSize"); + const markerIconShiftX = document.getElementById("markerIconShiftX"); + const markerIconShiftY = document.getElementById("markerIconShiftY"); + + const markerSize = document.getElementById("markerSize"); + const markerBaseStroke = document.getElementById("markerBaseStroke"); + const markerBaseFill = document.getElementById("markerBaseFill"); + + const markerToggleBubble = document.getElementById("markerToggleBubble"); + const markerIconSelect = document.getElementById("markerIconSelect"); - elSelected = d3.select(d3.event.target).call(d3.drag().on("start", dragMarker)).classed("draggable", true); updateInputs(); - if (modules.editMarker) return; - modules.editMarker = true; - $("#markerEditor").dialog({ - title: "Edit Marker", resizable: false, - position: {my: "center top+30", at: "bottom", of: d3.event, collision: "fit"}, + title: "Edit Marker", + resizable: false, + position: {my: "center top+30", at: "bottom", of: element, collision: "fit"}, close: closeMarkerEditor }); - // add listeners - document.getElementById("markerGroup").addEventListener("click", toggleGroupSection); - document.getElementById("markerAddGroup").addEventListener("click", toggleGroupInput); - document.getElementById("markerSelectGroup").addEventListener("change", changeGroup); - document.getElementById("markerInputGroup").addEventListener("change", createGroup); - document.getElementById("markerRemoveGroup").addEventListener("click", removeGroup); - - document.getElementById("markerIcon").addEventListener("click", toggleIconSection); - document.getElementById("markerIconSize").addEventListener("input", changeIconSize); - document.getElementById("markerIconShiftX").addEventListener("input", changeIconShiftX); - document.getElementById("markerIconShiftY").addEventListener("input", changeIconShiftY); - document.getElementById("markerIconSelect").addEventListener("click", selectMarkerIcon); - - document.getElementById("markerStyle").addEventListener("click", toggleStyleSection); - document.getElementById("markerSize").addEventListener("input", changeMarkerSize); - document.getElementById("markerBaseStroke").addEventListener("input", changePinStroke); - document.getElementById("markerBaseFill").addEventListener("input", changePinFill); - document.getElementById("markerIconStrokeWidth").addEventListener("input", changeIconStrokeWidth); - document.getElementById("markerIconStroke").addEventListener("input", changeIconStroke); - document.getElementById("markerIconFill").addEventListener("input", changeIconFill); - - document.getElementById("markerToggleBubble").addEventListener("click", togglePinVisibility); - document.getElementById("markerLegendButton").addEventListener("click", editMarkerLegend); - document.getElementById("markerAdd").addEventListener("click", toggleAddMarker); - document.getElementById("markerRemove").addEventListener("click", removeMarker); - - updateGroupOptions(); + const listeners = [ + listen(markerSelectGroup, "change", changeGroup), + listen(document.getElementById("markerIcon"), "click", toggleIconSection), + listen(markerIconSize, "input", changeIconSize), + listen(markerIconShiftX, "input", changeIconShiftX), + listen(markerIconShiftY, "input", changeIconShiftY), + listen(document.getElementById("markerIconSelect"), "click", selectMarkerIcon), + listen(document.getElementById("markerStyle"), "click", toggleStyleSection), + listen(markerSize, "input", changeMarkerSize), + listen(markerBaseStroke, "input", changePinStroke), + listen(markerBaseFill, "input", changePinFill), + listen(markerToggleBubble, "click", togglePinVisibility), + listen(document.getElementById("markerLegendButton"), "click", editMarkerLegend), + listen(document.getElementById("markerAdd"), "click", toggleAddMarker), + listen(document.getElementById("markerRemove"), "click", removeMarker) + ]; function dragMarker() { - const tr = parseTransform(this.getAttribute("transform")); - const x = +tr[0] - d3.event.x, y = +tr[1] - d3.event.y; - - d3.event.on("drag", function() { - const transform = `translate(${(x + d3.event.x)},${(y + d3.event.y)})`; - this.setAttribute("transform", transform); + const dx = +this.getAttribute("x") - d3.event.x; + const dy = +this.getAttribute("y") - d3.event.y; + + d3.event.on("drag", function () { + const {x, y} = d3.event; + this.setAttribute("x", dx + x); + this.setAttribute("y", dy + y); + }); + + d3.event.on("end", function () { + const {x, y} = d3.event; + this.setAttribute("x", rn(dx + x, 2)); + this.setAttribute("y", rn(dy + y, 2)); + + const size = marker.size || 30; + const zoomSize = Math.max(rn(size / 5 + 24 / scale, 2), 1); + marker.x = rn(x + dx + zoomSize / 2, 1); + marker.y = rn(y + dy + zoomSize, 1); }); } function updateInputs() { - const id = elSelected.attr("data-id"); - const symbol = d3.select("#defs-markers").select(id); - const icon = symbol.select("text"); + const {icon, type = "", size = 30, dx = 50, dy = 50, px = 12, stroke = "#000", fill = "#fff", pin = "bubble"} = marker; - markerSelectGroup.value = id.slice(1); - markerIconSize.value = parseFloat(icon.attr("font-size")); - markerIconShiftX.value = parseFloat(icon.attr("x")); - markerIconShiftY.value = parseFloat(icon.attr("y")); + markerSelectGroup.value = type; + markerIconSize.value = px; + markerIconShiftX.value = dx; + markerIconShiftY.value = dy; - markerSize.value = elSelected.attr("data-size"); - markerBaseStroke.value = symbol.select("path").attr("fill"); - markerBaseFill.value = symbol.select("circle").attr("fill"); + markerSize.value = size; + markerBaseStroke.value = stroke; + markerBaseFill.value = fill; - markerIconStrokeWidth.value = icon.attr("stroke-width"); - markerIconStroke.value = icon.attr("stroke"); - markerIconFill.value = icon.attr("fill"); - - markerToggleBubble.className = symbol.select("circle").attr("opacity") === "0" ? "icon-info" : "icon-info-circled"; - markerIconSelect.innerHTML = icon.text(); + markerToggleBubble.className = pin; + markerIconSelect.innerHTML = icon; } function toggleGroupSection() { if (markerGroupSection.style.display === "inline-block") { - markerEditor.querySelectorAll("button:not(#markerGroup)").forEach(b => b.style.display = "inline-block"); + markerEditor.querySelectorAll("button:not(#markerGroup)").forEach(b => (b.style.display = "inline-block")); markerGroupSection.style.display = "none"; } else { - markerEditor.querySelectorAll("button:not(#markerGroup)").forEach(b => b.style.display = "none"); + markerEditor.querySelectorAll("button:not(#markerGroup)").forEach(b => (b.style.display = "none")); markerGroupSection.style.display = "inline-block"; } } - function updateGroupOptions() { - markerSelectGroup.innerHTML = ""; - d3.select("#defs-markers").selectAll("symbol").each(function() { - markerSelectGroup.options.add(new Option(this.id, this.id)); - }); - markerSelectGroup.value = elSelected.attr("data-id").slice(1); - } - - function toggleGroupInput() { - if (markerInputGroup.style.display === "inline-block") { - markerSelectGroup.style.display = "inline-block"; - markerInputGroup.style.display = "none"; - } else { - markerSelectGroup.style.display = "none"; - markerInputGroup.style.display = "inline-block"; - markerInputGroup.focus(); - } - } - function changeGroup() { - elSelected.attr("xlink:href", "#"+this.value); - elSelected.attr("data-id", "#"+this.value); - } - - function createGroup() { - let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, ""); - if (Number.isFinite(+newGroup.charAt(0))) newGroup = "m" + newGroup; - if (document.getElementById(newGroup)) { - tip("Element with this id already exists. Please provide a unique name", false, "error"); - return; - } - - markerInputGroup.value = ""; - // clone old group assigning new id - const id = elSelected.attr("data-id"); - const clone = d3.select("#defs-markers").select(id).node().cloneNode(true); - clone.id = newGroup; - document.getElementById("defs-markers").insertBefore(clone, null); - elSelected.attr("xlink:href", "#"+newGroup).attr("data-id", "#"+newGroup); - - // select new group - markerSelectGroup.options.add(new Option(newGroup, newGroup, false, true)); - toggleGroupInput(); - } - - function removeGroup() { - const id = elSelected.attr("data-id"); - const used = document.querySelectorAll("use[data-id='"+id+"']"); - const count = used.length === 1 ? "1 element" : used.length + " elements"; - alertMessage.innerHTML = "Are you sure you want to remove all markers of that type (" + count + ")?"; - - $("#alert").dialog({resizable: false, title: "Remove marker type", - buttons: { - Remove: function() { - $(this).dialog("close"); - if (id !== "#marker0") d3.select("#defs-markers").select(id).remove(); - used.forEach(e => { - const index = notes.findIndex(n => n.id === e.id); - if (index != -1) notes.splice(index, 1); - e.remove(); - }); - updateGroupOptions(); - updateGroupOptions(); - $("#markerEditor").dialog("close"); - }, - Cancel: function() {$(this).dialog("close");} - } - }); + elSelected.attr("xlink:href", "#" + this.value); + elSelected.attr("data-id", "#" + this.value); } function toggleIconSection() { + console.log(marker); if (markerIconSection.style.display === "inline-block") { - markerEditor.querySelectorAll("button:not(#markerIcon)").forEach(b => b.style.display = "inline-block"); + markerEditor.querySelectorAll("button:not(#markerIcon)").forEach(b => (b.style.display = "inline-block")); markerIconSection.style.display = "none"; markerIconSelect.style.display = "none"; } else { - markerEditor.querySelectorAll("button:not(#markerIcon)").forEach(b => b.style.display = "none"); + markerEditor.querySelectorAll("button:not(#markerIcon)").forEach(b => (b.style.display = "none")); markerIconSection.style.display = "inline-block"; markerIconSelect.style.display = "inline-block"; } @@ -178,34 +123,44 @@ function editMarker() { function changeIconSize() { const id = elSelected.attr("data-id"); - d3.select("#defs-markers").select(id).select("text").attr("font-size", this.value + "px"); + d3.select("#defs-markers") + .select(id) + .select("text") + .attr("font-size", this.value + "px"); } function changeIconShiftX() { const id = elSelected.attr("data-id"); - d3.select("#defs-markers").select(id).select("text").attr("x", this.value + "%"); + d3.select("#defs-markers") + .select(id) + .select("text") + .attr("x", this.value + "%"); } function changeIconShiftY() { const id = elSelected.attr("data-id"); - d3.select("#defs-markers").select(id).select("text").attr("y", this.value + "%"); + d3.select("#defs-markers") + .select(id) + .select("text") + .attr("y", this.value + "%"); } function toggleStyleSection() { if (markerStyleSection.style.display === "inline-block") { - markerEditor.querySelectorAll("button:not(#markerStyle)").forEach(b => b.style.display = "inline-block"); + markerEditor.querySelectorAll("button:not(#markerStyle)").forEach(b => (b.style.display = "inline-block")); markerStyleSection.style.display = "none"; } else { - markerEditor.querySelectorAll("button:not(#markerStyle)").forEach(b => b.style.display = "none"); + markerEditor.querySelectorAll("button:not(#markerStyle)").forEach(b => (b.style.display = "none")); markerStyleSection.style.display = "inline-block"; } } function changeMarkerSize() { const id = elSelected.attr("data-id"); - document.querySelectorAll("use[data-id='"+id+"']").forEach(e => { - const x = +e.dataset.x, y = +e.dataset.y; - const desired = e.dataset.size = +markerSize.value; + document.querySelectorAll("use[data-id='" + id + "']").forEach(e => { + const x = +e.dataset.x, + y = +e.dataset.y; + const desired = (e.dataset.size = +markerSize.value); const size = Math.max(desired * 5 + 25 / scale, 1); e.setAttribute("x", x - size / 2); @@ -245,8 +200,10 @@ function editMarker() { function togglePinVisibility() { const id = elSelected.attr("data-id"); let show = 1; - if (this.className === "icon-info-circled") {this.className = "icon-info"; show = 0; } - else this.className = "icon-info-circled"; + if (this.className === "icon-info-circled") { + this.className = "icon-info"; + show = 0; + } else this.className = "icon-info-circled"; d3.select(id).select("circle").attr("opacity", show); d3.select(id).select("path").attr("opacity", show); } @@ -262,21 +219,27 @@ function editMarker() { function removeMarker() { alertMessage.innerHTML = "Are you sure you want to remove the marker?"; - $("#alert").dialog({resizable: false, title: "Remove marker", + $("#alert").dialog({ + resizable: false, + title: "Remove marker", buttons: { - Remove: function() { + Remove: function () { $(this).dialog("close"); const index = notes.findIndex(n => n.id === elSelected.attr("id")); if (index != -1) notes.splice(index, 1); elSelected.remove(); $("#markerEditor").dialog("close"); }, - Cancel: function() {$(this).dialog("close");} + Cancel: function () { + $(this).dialog("close"); + } } }); } function closeMarkerEditor() { + listeners.forEach(removeListener => removeListener()); + unselect(); if (addMarker.classList.contains("pressed")) addMarker.classList.remove("pressed"); if (markerAdd.classList.contains("pressed")) markerAdd.classList.remove("pressed"); @@ -284,4 +247,3 @@ function editMarker() { clearMainTip(); } } - From 95f9d990d95f7cbd18a5ee083f895a793f07ec00 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 20 Sep 2021 02:29:50 +0300 Subject: [PATCH 22/44] markers rework - editor functions --- index.css | 10 +- index.html | 85 ++++++---- main.js | 49 +++++- modules/markers-generator.js | 292 +++++++++++++++++++++++++++++++++-- modules/ui/editors.js | 77 ++++++++- modules/ui/layers.js | 59 ++++--- modules/ui/markers-editor.js | 254 ++++++++++++++---------------- modules/ui/tools.js | 21 ++- 8 files changed, 633 insertions(+), 214 deletions(-) diff --git a/index.css b/index.css index 8e4b69ef..7f99eb16 100644 --- a/index.css +++ b/index.css @@ -238,8 +238,7 @@ i.icon-lock { } #routeEditor > *, -#labelEditor div, -#markerEditor div { +#labelEditor div { display: inline-block; } @@ -1525,7 +1524,8 @@ div.states > .coaIcon > use { #stateNameEditor div.label, #provinceNameEditor div.label, -#regimentBody div.label { +#regimentBody div.label, +#markerEditor div.label { display: inline-block; width: 5.5em; } @@ -1974,10 +1974,6 @@ div.textual span, dominant-baseline: central; } -#markerEditor > button { - vertical-align: top; -} - .highlighted { outline-width: 2px; outline-style: dashed; diff --git a/index.html b/index.html index 657c14a0..598fee6f 100644 --- a/index.html +++ b/index.html @@ -2036,39 +2036,66 @@