mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 12:01:23 +01:00
latest version
This commit is contained in:
parent
41432ac944
commit
c477c8dfcd
36 changed files with 3979 additions and 832 deletions
BIN
_maps/.DS_Store
vendored
Normal file
BIN
_maps/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
_maps/working/.DS_Store
vendored
Normal file
BIN
_maps/working/.DS_Store
vendored
Normal file
Binary file not shown.
211
_maps/working/Rouvraines (1).map
Normal file
211
_maps/working/Rouvraines (1).map
Normal file
File diff suppressed because one or more lines are too long
211
_maps/working/Rouvraines (2).map
Normal file
211
_maps/working/Rouvraines (2).map
Normal file
File diff suppressed because one or more lines are too long
211
_maps/working/Rouvraines 2022-08-01-10-21.map
Normal file
211
_maps/working/Rouvraines 2022-08-01-10-21.map
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-burgs (1).json
Normal file
1
_maps/working/Rouvraines-burgs (1).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-burgs (2).json
Normal file
1
_maps/working/Rouvraines-burgs (2).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-burgs.json
Normal file
1
_maps/working/Rouvraines-burgs.json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-cultures (1).json
Normal file
1
_maps/working/Rouvraines-cultures (1).json
Normal file
|
|
@ -0,0 +1 @@
|
|||
[{"name":"Wildlands","i":0,"base":1,"origin":null,"shield":"round"},{"name":"Dhommeam (Dwarf)","base":35,"shield":"erebor","center":2793,"i":1,"color":"#ffed6f","type":"Highland","expansionism":0.5,"origin":0,"code":"DD"},{"name":"Dunirr (Dwarf)","base":35,"shield":"ironHills","center":5754,"i":2,"color":"#dababf","type":"Generic","expansionism":0.1,"origin":0,"code":"DU"},{"name":"Mudtoe (Dwarf)","base":35,"shield":"erebor","center":183,"i":3,"color":"#ee4395","type":"Highland","expansionism":0.4,"origin":0,"code":"MD"},{"name":"Khazadur (Dwarf)","base":35,"shield":"erebor","center":3542,"i":4,"color":"#eb8de7","type":"Highland","expansionism":0.5,"origin":0,"code":"KD"},{"name":"Yotunn (Giant)","base":38,"shield":"pavise","center":702,"i":5,"color":"#80b1d3","type":"Hunting","expansionism":0.6,"origin":0,"code":"YG"},{"name":"Shazgob (Orc)","base":37,"shield":"moriaOrc","center":5639,"i":6,"color":"#fccde5","type":"Hunting","expansionism":0.7,"origin":0,"code":"SO"},{"name":"Gul (Orc)","base":37,"shield":"moriaOrc","center":6040,"i":7,"color":"#2f96e0","type":"Highland","expansionism":0.5,"origin":0,"code":"GO"},{"name":"Gongrem (Dwarf)","base":35,"shield":"erebor","center":2190,"i":8,"color":"#b3de69","type":"Highland","expansionism":0.3,"origin":0,"code":"GD"},{"name":"Gralcek (Human)","base":16,"shield":"round","center":3704,"i":9,"color":"#bc80bd","type":"Generic","expansionism":0.1,"origin":0,"code":"GH"},{"name":"Fruthos (Human)","base":32,"shield":"fantasy5","center":6517,"i":10,"color":"#ccebc5","type":"River","expansionism":0.4,"origin":0,"code":"FH"},{"name":"Rulor (Human)","base":32,"shield":"roman","center":2763,"i":11,"color":"#ff8c38","type":"Lake","expansionism":0.4,"origin":0,"code":"RH"},{"name":"Mazoga (Orc)","base":37,"shield":"moriaOrc","center":5278,"i":12,"color":"#6e40aa","type":"Highland","expansionism":0.5,"origin":0,"code":"MO"},{"name":"Heenzurm (Goblin)","base":36,"shield":"moriaOrc","center":3211,"i":13,"color":"#28ea8d","type":"Hunting","expansionism":0.9,"origin":0,"code":"HG"},{"name":"Zildud (Orc)","base":37,"shield":"moriaOrc","center":249,"i":14,"color":"#aff05b","type":"Highland","expansionism":0.5,"origin":0,"code":"ZO"},{"name":"Ginikirr (Dwarf)","base":35,"shield":"erebor","center":2794,"i":15,"color":"#8dd3c7","type":"Highland","expansionism":0.4,"origin":0,"code":"GI"},{"name":"Lothian (Elf)","base":33,"shield":"wedged","center":3477,"i":16,"color":"#c6b9c1","type":"River","expansionism":0.4,"origin":0,"code":"LE"},{"name":"Zakaos (Giant)","base":38,"shield":"pavise","center":439,"i":17,"color":"#fdb462","type":"Generic","expansionism":0.1,"origin":0,"code":"ZG"},{"name":"Lagakh (Orc)","base":37,"shield":"urukHai","center":2558,"i":18,"color":"#fb8072","type":"Highland","expansionism":0.5,"origin":0,"code":"LO"}]
|
||||
1
_maps/working/Rouvraines-cultures (2).json
Normal file
1
_maps/working/Rouvraines-cultures (2).json
Normal file
|
|
@ -0,0 +1 @@
|
|||
[{"name":"Wildlands","i":0,"base":1,"origin":null,"shield":"round"},{"name":"Dhommeam (Dwarf)","base":35,"shield":"erebor","center":2793,"i":1,"color":"#ffed6f","type":"Highland","expansionism":0.5,"origin":0,"code":"DD"},{"name":"Dunirr (Dwarf)","base":35,"shield":"ironHills","center":5759,"i":2,"color":"#dababf","type":"Generic","expansionism":0.1,"origin":0,"code":"DU"},{"name":"Mudtoe (Dwarf)","base":35,"shield":"erebor","center":603,"i":3,"color":"#ee4395","type":"Highland","expansionism":0.4,"origin":0,"code":"MD"},{"name":"Khazadur (Dwarf)","base":35,"shield":"erebor","center":2608,"i":4,"color":"#eb8de7","type":"Nomadic","expansionism":1.4,"origin":0,"code":"KD"},{"name":"Yotunn (Giant)","base":38,"shield":"pavise","center":701,"i":5,"color":"#80b1d3","type":"River","expansionism":0.3,"origin":0,"code":"YG"},{"name":"Shazgob (Orc)","base":37,"shield":"moriaOrc","center":5644,"i":6,"color":"#fccde5","type":"Hunting","expansionism":0.7,"origin":0,"code":"SO"},{"name":"Gul (Orc)","base":37,"shield":"moriaOrc","center":6045,"i":7,"color":"#2f96e0","type":"Highland","expansionism":0.5,"origin":0,"code":"GO"},{"name":"Gongrem (Dwarf)","base":35,"shield":"erebor","center":2190,"i":8,"color":"#b3de69","type":"Highland","expansionism":0.3,"origin":0,"code":"GD"},{"name":"Gralcek (Human)","base":16,"shield":"round","center":3922,"i":9,"color":"#bc80bd","type":"Hunting","expansionism":0.8,"origin":0,"code":"GH"},{"name":"Fruthos (Human)","base":32,"shield":"fantasy5","center":6399,"i":10,"color":"#ccebc5","type":"Naval","expansionism":0.6,"origin":0,"code":"FH"},{"name":"Rulor (Human)","base":32,"shield":"roman","center":2632,"i":11,"color":"#ff8c38","type":"Nomadic","expansionism":0.9,"origin":0,"code":"RH"},{"name":"Mazoga (Orc)","base":37,"shield":"moriaOrc","center":4222,"i":12,"color":"#6e40aa","type":"Hunting","expansionism":0.9,"origin":0,"code":"MO"},{"name":"Heenzurm (Goblin)","base":36,"shield":"moriaOrc","center":3211,"i":13,"color":"#28ea8d","type":"Hunting","expansionism":0.9,"origin":0,"code":"HG"},{"name":"Zildud (Orc)","base":37,"shield":"moriaOrc","center":5769,"i":14,"color":"#aff05b","type":"Highland","expansionism":0.5,"origin":0,"code":"ZO"},{"name":"Ginikirr (Dwarf)","base":35,"shield":"erebor","center":2794,"i":15,"color":"#8dd3c7","type":"Highland","expansionism":0.4,"origin":0,"code":"GI"},{"name":"Lothian (Elf)","base":33,"shield":"wedged","center":3480,"i":16,"color":"#c6b9c1","type":"River","expansionism":0.4,"origin":0,"code":"LE"},{"name":"Zakaos (Giant)","base":38,"shield":"pavise","center":417,"i":17,"color":"#fdb462","type":"Nomadic","expansionism":1.2,"origin":0,"code":"ZG"},{"name":"Lagakh (Orc)","base":37,"shield":"urukHai","center":2558,"i":18,"color":"#fb8072","type":"Highland","expansionism":0.5,"origin":0,"code":"LO"}]
|
||||
1
_maps/working/Rouvraines-cultures.json
Normal file
1
_maps/working/Rouvraines-cultures.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
[{"name":"Wildlands","i":0,"base":1,"origin":null,"shield":"round"},{"name":"Dhommeam (Dwarf)","base":35,"shield":"erebor","center":2793,"i":1,"color":"#ffed6f","type":"Highland","expansionism":0.5,"origin":0,"code":"DD"},{"name":"Dunirr (Dwarf)","base":35,"shield":"ironHills","center":5754,"i":2,"color":"#dababf","type":"Generic","expansionism":0.1,"origin":0,"code":"DU"},{"name":"Mudtoe (Dwarf)","base":35,"shield":"erebor","center":183,"i":3,"color":"#ee4395","type":"Highland","expansionism":0.4,"origin":0,"code":"MD"},{"name":"Khazadur (Dwarf)","base":35,"shield":"erebor","center":3542,"i":4,"color":"#eb8de7","type":"Highland","expansionism":0.5,"origin":0,"code":"KD"},{"name":"Yotunn (Giant)","base":38,"shield":"pavise","center":702,"i":5,"color":"#80b1d3","type":"Hunting","expansionism":0.6,"origin":0,"code":"YG"},{"name":"Shazgob (Orc)","base":37,"shield":"moriaOrc","center":5639,"i":6,"color":"#fccde5","type":"Hunting","expansionism":0.7,"origin":0,"code":"SO"},{"name":"Gul (Orc)","base":37,"shield":"moriaOrc","center":6040,"i":7,"color":"#2f96e0","type":"Highland","expansionism":0.5,"origin":0,"code":"GO"},{"name":"Gongrem (Dwarf)","base":35,"shield":"erebor","center":2190,"i":8,"color":"#b3de69","type":"Highland","expansionism":0.3,"origin":0,"code":"GD"},{"name":"Gralcek (Human)","base":16,"shield":"round","center":3704,"i":9,"color":"#bc80bd","type":"Generic","expansionism":0.1,"origin":0,"code":"GH"},{"name":"Fruthos (Human)","base":32,"shield":"fantasy5","center":6517,"i":10,"color":"#ccebc5","type":"River","expansionism":0.4,"origin":0,"code":"FH"},{"name":"Rulor (Human)","base":32,"shield":"roman","center":2763,"i":11,"color":"#ff8c38","type":"Lake","expansionism":0.4,"origin":0,"code":"RH"},{"name":"Mazoga (Orc)","base":37,"shield":"moriaOrc","center":5278,"i":12,"color":"#6e40aa","type":"Highland","expansionism":0.5,"origin":0,"code":"MO"},{"name":"Heenzurm (Goblin)","base":36,"shield":"moriaOrc","center":3211,"i":13,"color":"#28ea8d","type":"Hunting","expansionism":0.9,"origin":0,"code":"HG"},{"name":"Zildud (Orc)","base":37,"shield":"moriaOrc","center":249,"i":14,"color":"#aff05b","type":"Highland","expansionism":0.5,"origin":0,"code":"ZO"},{"name":"Ginikirr (Dwarf)","base":35,"shield":"erebor","center":2794,"i":15,"color":"#8dd3c7","type":"Highland","expansionism":0.4,"origin":0,"code":"GI"},{"name":"Lothian (Elf)","base":33,"shield":"wedged","center":3477,"i":16,"color":"#c6b9c1","type":"River","expansionism":0.4,"origin":0,"code":"LE"},{"name":"Zakaos (Giant)","base":38,"shield":"pavise","center":439,"i":17,"color":"#fdb462","type":"Generic","expansionism":0.1,"origin":0,"code":"ZG"},{"name":"Lagakh (Orc)","base":37,"shield":"urukHai","center":2558,"i":18,"color":"#fb8072","type":"Highland","expansionism":0.5,"origin":0,"code":"LO"}]
|
||||
1
_maps/working/Rouvraines-markers (1).json
Normal file
1
_maps/working/Rouvraines-markers (1).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-markers (2).json
Normal file
1
_maps/working/Rouvraines-markers (2).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-markers.json
Normal file
1
_maps/working/Rouvraines-markers.json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-notes (1).json
Normal file
1
_maps/working/Rouvraines-notes (1).json
Normal file
|
|
@ -0,0 +1 @@
|
|||
undefined
|
||||
1
_maps/working/Rouvraines-notes (2).json
Normal file
1
_maps/working/Rouvraines-notes (2).json
Normal file
|
|
@ -0,0 +1 @@
|
|||
undefined
|
||||
1
_maps/working/Rouvraines-notes.json
Normal file
1
_maps/working/Rouvraines-notes.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
undefined
|
||||
1
_maps/working/Rouvraines-poprate (1).txt
Normal file
1
_maps/working/Rouvraines-poprate (1).txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
530
|
||||
1
_maps/working/Rouvraines-poprate (2).txt
Normal file
1
_maps/working/Rouvraines-poprate (2).txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
530
|
||||
1
_maps/working/Rouvraines-poprate.txt
Normal file
1
_maps/working/Rouvraines-poprate.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
530
|
||||
1
_maps/working/Rouvraines-religions (1).json
Normal file
1
_maps/working/Rouvraines-religions (1).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-religions (2).json
Normal file
1
_maps/working/Rouvraines-religions (2).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-religions.json
Normal file
1
_maps/working/Rouvraines-religions.json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-states (1).json
Normal file
1
_maps/working/Rouvraines-states (1).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-states (2).json
Normal file
1
_maps/working/Rouvraines-states (2).json
Normal file
File diff suppressed because one or more lines are too long
1
_maps/working/Rouvraines-states.json
Normal file
1
_maps/working/Rouvraines-states.json
Normal file
File diff suppressed because one or more lines are too long
211
_maps/working/Rouvraines.map
Normal file
211
_maps/working/Rouvraines.map
Normal file
File diff suppressed because one or more lines are too long
11
index.css
11
index.css
|
|
@ -85,7 +85,7 @@ a {
|
|||
}
|
||||
|
||||
#prec text {
|
||||
font-size: 32px;
|
||||
font-size: 24px;
|
||||
stroke: none;
|
||||
text-shadow: 1px 1px 1px #9daac9;
|
||||
user-select: none;
|
||||
|
|
@ -297,12 +297,17 @@ i.icon-lock {
|
|||
}
|
||||
}
|
||||
|
||||
#provinceLabels,
|
||||
#burgLabels {
|
||||
dominant-baseline: alphabetic;
|
||||
text-anchor: middle;
|
||||
font-size: 0.1em;
|
||||
}
|
||||
#provinceLabels {
|
||||
dominant-baseline: alphabetic;
|
||||
text-anchor: leftOver;
|
||||
font-size: 0.2em;
|
||||
text-shadow: 1px 1px #e7ffa1;
|
||||
}
|
||||
|
||||
#routeLength,
|
||||
#coastlineArea {
|
||||
background-color: #eeeeee;
|
||||
|
|
|
|||
|
|
@ -1046,7 +1046,7 @@
|
|||
<option value="english" data-max="10">English</option>
|
||||
<option value="antique" data-max="10">Antique</option>
|
||||
<option value="highFantasy" data-max="17">High Fantasy</option>
|
||||
<option value="darkFantasy" data-max="18">Dark Fantasy</option>
|
||||
<option value="darkFantasy" data-max="32">Dark Fantasy</option>
|
||||
<option value="random" data-max="100">Random</option>
|
||||
</select>
|
||||
</td>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -11,34 +11,65 @@ window.Markers = (function () {
|
|||
return [
|
||||
{ type: "volcanoes", icon: "🌋", multiplier: 10, fn: addVolcanoes },
|
||||
{ type: "hot-springs", icon: "♨️", multiplier: 20, fn: addHotSprings },
|
||||
{type: "mines", icon: "⛏️", multiplier: 5, fn: addMines},
|
||||
{type: "bridges", icon: "🌉", multiplier: 10, fn: addBridges},
|
||||
{ type: "mines", icon: "⛏️", multiplier: 50, fn: addMines },
|
||||
{ type: "gem-mines", icon: "💎", multiplier: 3, fn: addGemMines },
|
||||
{ type: "bridges", icon: "🌉", multiplier: 40, fn: addBridges },
|
||||
{ type: "inns", icon: "🍻", multiplier: 20, fn: addInns },
|
||||
{ type: "lighthouses", icon: "🚨", multiplier: 1, fn: addLighthouses },
|
||||
{type: "waterfalls", icon: "⟱", multiplier: 3, fn: addWaterfalls},
|
||||
{type: "battlefields", icon: "⚔️", multiplier: 1, fn: addBattlefields},
|
||||
{type: "dungeons", icon: "🗝️", multiplier: 20, fn: addDungeons},
|
||||
{type: "lake-monsters", icon: "🐉", multiplier: 2, fn: addLakeMonsters},
|
||||
{type: "sea-monsters", icon: "🦑", multiplier: 5, fn: addSeaMonsters},
|
||||
{type: "hill-monsters", icon: "👹", multiplier: 20, fn: addHillMonsters},
|
||||
{type: "sacred-mountains", icon: "🗻", multiplier: 5, fn: addSacredMountains},
|
||||
{type: "sacred-forests", icon: "🌳", multiplier: 10, fn: addSacredForests},
|
||||
{type: "sacred-pineries", icon: "🌲", multiplier: 20, fn: addSacredPineries},
|
||||
{type: "sacred-palm-groves", icon: "🌴", multiplier: 1, fn: addSacredPalmGroves},
|
||||
{ type: "waterfalls", icon: "💦", multiplier: 1, fn: addWaterfalls },
|
||||
{ type: "battlefields", icon: "⚔️", multiplier: 3, fn: addBattlefields },
|
||||
{ type: "dungeons", icon: "🗝️", multiplier: 5, fn: addDungeons },
|
||||
{ type: "lake-monsters", icon: "🐉", multiplier: 8, fn: addLakeMonsters },
|
||||
{ type: "sea-monsters", icon: "🦑", multiplier: 150, fn: addSeaMonsters },
|
||||
{
|
||||
type: "hill-monsters",
|
||||
icon: "👹",
|
||||
multiplier: 20,
|
||||
fn: addHillMonsters,
|
||||
},
|
||||
{
|
||||
type: "sacred-mountains",
|
||||
icon: "🗻",
|
||||
multiplier: 5,
|
||||
fn: addSacredMountains,
|
||||
},
|
||||
{
|
||||
type: "sacred-forests",
|
||||
icon: "🌳",
|
||||
multiplier: 10,
|
||||
fn: addSacredForests,
|
||||
},
|
||||
{
|
||||
type: "sacred-pineries",
|
||||
icon: "🌲",
|
||||
multiplier: 10,
|
||||
fn: addSacredPineries,
|
||||
},
|
||||
{
|
||||
type: "sacred-palm-groves",
|
||||
icon: "🌴",
|
||||
multiplier: 5,
|
||||
fn: addSacredPalmGroves,
|
||||
},
|
||||
{ type: "brigands", icon: "💰", multiplier: 5, fn: addBrigands },
|
||||
{type: "pirates", icon: "🏴☠️", multiplier: 3, fn: addPirates},
|
||||
{ type: "pirates", icon: "🏴☠️", multiplier: 15, fn: addPirates },
|
||||
{ type: "statues", icon: "🗿", multiplier: 5, fn: addStatues },
|
||||
{ type: "ruines", icon: "🏺", multiplier: 10, fn: addRuines },
|
||||
{type: "spiders", icon: "🕷️", multiplier: 25, fn: addHillMonsters},
|
||||
{type: "giant goat heard", icon: "🐐", multiplier: 25, fn: addHillMonsters},
|
||||
{type: "citadel", icon: "🏯", multiplier: 25, fn: addSacredPineries},
|
||||
{type: "portals", icon: "🌀", multiplier: 4, fn: addPortals}
|
||||
{ type: "spiders", icon: "🕷️", multiplier: 45, fn: addSpiders },
|
||||
{
|
||||
type: "giant goat heard",
|
||||
icon: "🐐",
|
||||
multiplier: 25,
|
||||
fn: addGoatHeard,
|
||||
},
|
||||
{ type: "citadel", icon: "🏯", multiplier: 10, fn: addSacredCitidel },
|
||||
{ type: "portals", icon: "🌀", multiplier: 3, fn: addPortals },
|
||||
];
|
||||
}
|
||||
|
||||
const getConfig = () => config;
|
||||
|
||||
const setConfig = newConfig => {
|
||||
const setConfig = (newConfig) => {
|
||||
config = newConfig;
|
||||
};
|
||||
|
||||
|
|
@ -56,7 +87,7 @@ window.Markers = (function () {
|
|||
}
|
||||
const id = `marker${i}`;
|
||||
document.getElementById(id)?.remove();
|
||||
const index = notes.findIndex(note => note.id === id);
|
||||
const index = notes.findIndex((note) => note.id === id);
|
||||
if (index != -1) notes.splice(index, 1);
|
||||
return false;
|
||||
});
|
||||
|
|
@ -114,7 +145,11 @@ window.Markers = (function () {
|
|||
function addVolcanoes(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
let mountains = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] >= 70).sort((a, b) => cells.h[b] - cells.h[a]));
|
||||
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;
|
||||
|
||||
|
|
@ -122,8 +157,16 @@ window.Markers = (function () {
|
|||
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])}`});
|
||||
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--;
|
||||
}
|
||||
}
|
||||
|
|
@ -131,7 +174,11 @@ window.Markers = (function () {
|
|||
function addHotSprings(type, icon, multiplier) {
|
||||
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]));
|
||||
let springs = Array.from(
|
||||
cells.i
|
||||
.filter((i) => !occupied[i] && cells.h[i] > 50)
|
||||
.sort((a, b) => cells.h[b] - cells.h[a])
|
||||
);
|
||||
let quantity = getQuantity(springs, 30, 1200, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -140,7 +187,11 @@ window.Markers = (function () {
|
|||
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}`});
|
||||
notes.push({
|
||||
id,
|
||||
name: proper + " Hot Springs",
|
||||
legend: `A hot springs area. Average temperature: ${temp}`,
|
||||
});
|
||||
quantity--;
|
||||
}
|
||||
}
|
||||
|
|
@ -148,11 +199,22 @@ window.Markers = (function () {
|
|||
function addMines(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
let hillyBurgs = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] > 47 && cells.burg[i]));
|
||||
let hillyBurgs = Array.from(
|
||||
cells.i.filter((i) => !occupied[i] && cells.h[i] > 47 && cells.burg[i])
|
||||
);
|
||||
let quantity = getQuantity(hillyBurgs, 1, 15, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
const resources = {salt: 5, gold: 2, silver: 4, copper: 2, iron: 3, lead: 1, tin: 1};
|
||||
const resources = {
|
||||
salt: 5,
|
||||
coal: 7,
|
||||
gold: 2,
|
||||
silver: 4,
|
||||
copper: 2,
|
||||
iron: 3,
|
||||
lead: 1,
|
||||
tin: 1,
|
||||
};
|
||||
|
||||
while (quantity && hillyBurgs.length) {
|
||||
const [cell] = extractAnyElement(hillyBurgs);
|
||||
|
|
@ -167,12 +229,205 @@ window.Markers = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
function addGemMines(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
let hillyBurgs = Array.from(
|
||||
cells.i.filter((i) => !occupied[i] && cells.h[i] > 67)
|
||||
);
|
||||
let quantity = getQuantity(hillyBurgs, 1, 15, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
const resources = {
|
||||
Agni_mani: 1,
|
||||
Alamandine: 1,
|
||||
Alestone: 1,
|
||||
Alexandrite: 1,
|
||||
Algae: 1,
|
||||
Amaratha: 1,
|
||||
Amber: 1,
|
||||
Amethyst: 1,
|
||||
Andar: 1,
|
||||
Aquamarine: 1,
|
||||
Aradite: 1,
|
||||
Augelite: 1,
|
||||
Aventurine: 1,
|
||||
Azurite: 1,
|
||||
Banded_agate: 1,
|
||||
Beljuril: 1,
|
||||
Beryl: 1,
|
||||
Black_opal: 1,
|
||||
Black_pearl: 1,
|
||||
Black_sapphire: 1,
|
||||
Bloodstone: 1,
|
||||
Blue_quartz: 1,
|
||||
Blue_sapphire: 1,
|
||||
Blue_spinel: 1,
|
||||
Bluestone: 1,
|
||||
Boakhar: 1,
|
||||
Brandeen: 1,
|
||||
Carbuncle: 1,
|
||||
Carnelian: 1,
|
||||
Chalcedony: 1,
|
||||
Chrysoberyl: 1,
|
||||
Chrysocolla: 1,
|
||||
Chrysolite: 1,
|
||||
Chrysoprase: 1,
|
||||
Citrine: 1,
|
||||
Cleiophane: 1,
|
||||
Coral: 1,
|
||||
Corstal: 1,
|
||||
Corundum: 1,
|
||||
Crown_of_silver: 1,
|
||||
Cymophane: 1,
|
||||
Datcha: 1,
|
||||
Demontoid: 1,
|
||||
Diamond: 1,
|
||||
Diopside: 1,
|
||||
Dioptase: 1,
|
||||
Disthene: 1,
|
||||
Emerald: 1,
|
||||
Epidote: 1,
|
||||
Essonite: 1,
|
||||
Euclase: 1,
|
||||
Eye_agate: 1,
|
||||
Fire_agate: 1,
|
||||
Fire_opal: 1,
|
||||
Flamedance: 1,
|
||||
Fluorite: 1,
|
||||
Frost_agate: 1,
|
||||
Garnet: 1,
|
||||
Goldline: 1,
|
||||
Greenstone: 1,
|
||||
Hambergyle: 1,
|
||||
Hematite: 1,
|
||||
Hyacinth: 1,
|
||||
Hyaline: 1,
|
||||
Hyalite: 1,
|
||||
Hydrophane: 1,
|
||||
Hypersthene: 1,
|
||||
Idicolite: 1,
|
||||
Iolite: 1,
|
||||
Irtios: 1,
|
||||
Jacinth: 1,
|
||||
Jade: 1,
|
||||
Jargoon: 1,
|
||||
Jasmal: 1,
|
||||
Jasper: 1,
|
||||
Jet: 1,
|
||||
Kings_tears: 1,
|
||||
Kornerupine: 1,
|
||||
Kunzite: 1,
|
||||
Laerals_Tears: 1,
|
||||
Lapis_lazuli: 1,
|
||||
Luriyl: 1,
|
||||
Lynx_eye: 1,
|
||||
Malachite: 1,
|
||||
Malacon: 1,
|
||||
Mellochrysos: 1,
|
||||
Microcline: 1,
|
||||
Moonbar: 1,
|
||||
Moonstone: 1,
|
||||
Morganite: 1,
|
||||
Moss_agate: 1,
|
||||
Mykaro: 1,
|
||||
Mynteer: 1,
|
||||
Nelvine: 1,
|
||||
Nephrite: 1,
|
||||
Nune: 1,
|
||||
Obsidian: 1,
|
||||
Octel: 1,
|
||||
Olivine: 1,
|
||||
Ooline: 1,
|
||||
Onyx: 1,
|
||||
Ophealine: 1,
|
||||
Orbaline: 1,
|
||||
Orblen: 1,
|
||||
Orl: 1,
|
||||
Orprase: 1,
|
||||
Pearl: 1,
|
||||
Peridot: 1,
|
||||
Pyrope: 1,
|
||||
Quartz: 1,
|
||||
Raindrop: 1,
|
||||
Red_Tears: 1,
|
||||
Rhodochrosite: 1,
|
||||
Rhodolite: 1,
|
||||
Rhodonite: 1,
|
||||
Rosaline: 1,
|
||||
Rubellite: 1,
|
||||
Ruby: 1,
|
||||
Rusteen: 1,
|
||||
Saganite: 1,
|
||||
Samarskite: 1,
|
||||
Sanidine: 1,
|
||||
Sarbossa: 1,
|
||||
Sardonyx: 1,
|
||||
Satin_spar: 1,
|
||||
Scapra: 1,
|
||||
Serpentine: 1,
|
||||
Shandon: 1,
|
||||
Sharpstone: 1,
|
||||
Silkstone: 1,
|
||||
Sinhalite: 1,
|
||||
Skydrop: 1,
|
||||
Spessartite: 1,
|
||||
Sphene: 1,
|
||||
Spinel: 1,
|
||||
Star_rose_quarts: 1,
|
||||
Star_ruby: 1,
|
||||
Star_sapphire: 1,
|
||||
Sunstone: 1,
|
||||
Tabasheer: 1,
|
||||
Tanzanite: 1,
|
||||
Tchazar: 1,
|
||||
Thupartial: 1,
|
||||
Tiger_eye: 1,
|
||||
Topaz: 1,
|
||||
Tourmaline: 1,
|
||||
Tremair: 1,
|
||||
Turquoise: 1,
|
||||
Ulvaen: 1,
|
||||
Variscite: 1,
|
||||
Water_opal: 1,
|
||||
Waterstar: 1,
|
||||
White_opal: 1,
|
||||
Witherite: 1,
|
||||
Wonderstone: 1,
|
||||
Woodtine: 1,
|
||||
Yellow_sapphire: 1,
|
||||
Zarbrina: 1,
|
||||
Zendalure: 1,
|
||||
Ziose: 1,
|
||||
Zircon: 1,
|
||||
};
|
||||
|
||||
while (quantity && hillyBurgs.length) {
|
||||
const [cell] = extractAnyElement(hillyBurgs);
|
||||
const id = addMarker({ cell, icon, type, dx: 48, px: 13 });
|
||||
const resource = rw(resources);
|
||||
const burg = pack.burgs[cells.burg[cell]];
|
||||
const name = `${burg.name} — ${resource} mining town`;
|
||||
const population = rn(burg.population * populationRate * urbanization);
|
||||
const legend = `${resource} mine`;
|
||||
notes.push({ id, name, legend });
|
||||
quantity--;
|
||||
}
|
||||
}
|
||||
|
||||
function addBridges(type, icon, multiplier) {
|
||||
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(
|
||||
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;
|
||||
|
|
@ -181,7 +436,7 @@ window.Markers = (function () {
|
|||
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 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 = {
|
||||
|
|
@ -191,9 +446,15 @@ window.Markers = (function () {
|
|||
formidable: 2,
|
||||
rickety: 1,
|
||||
beaten: 1,
|
||||
weathered: 1
|
||||
weathered: 1,
|
||||
};
|
||||
notes.push({id, name: `${name} Bridge`, legend: `A ${rw(weightedAdjectives)} bridge spans over the ${riverName} near ${burg.name}`});
|
||||
notes.push({
|
||||
id,
|
||||
name: `${name} Bridge`,
|
||||
legend: `A ${rw(
|
||||
weightedAdjectives
|
||||
)} bridge spans over the ${riverName} near ${burg.name}`,
|
||||
});
|
||||
quantity--;
|
||||
}
|
||||
}
|
||||
|
|
@ -201,7 +462,15 @@ window.Markers = (function () {
|
|||
function addInns(type, icon, multiplier) {
|
||||
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));
|
||||
let taverns = Array.from(
|
||||
cells.i.filter(
|
||||
(i) =>
|
||||
!occupied[i] &&
|
||||
cells.h[i] >= 20 &&
|
||||
cells.road[i] > 4 &&
|
||||
cells.pop[i] > 10
|
||||
)
|
||||
);
|
||||
let quantity = getQuantity(taverns, 1, 100, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -221,7 +490,7 @@ window.Markers = (function () {
|
|||
"Amber",
|
||||
"Orange",
|
||||
"Brown",
|
||||
"Grey"
|
||||
"Grey",
|
||||
];
|
||||
const animals = [
|
||||
"Antelope",
|
||||
|
|
@ -277,7 +546,7 @@ window.Markers = (function () {
|
|||
"Camel",
|
||||
"Falcon",
|
||||
"Hound",
|
||||
"Ox"
|
||||
"Ox",
|
||||
];
|
||||
const adjectives = [
|
||||
"New",
|
||||
|
|
@ -313,7 +582,7 @@ window.Markers = (function () {
|
|||
"Favorable",
|
||||
"Brave",
|
||||
"Sunny",
|
||||
"Flying"
|
||||
"Flying",
|
||||
];
|
||||
const methods = [
|
||||
"Boiled",
|
||||
|
|
@ -340,7 +609,7 @@ window.Markers = (function () {
|
|||
"Steamed",
|
||||
"Cured",
|
||||
"Syrupped",
|
||||
"Flame-Broiled"
|
||||
"Flame-Broiled",
|
||||
];
|
||||
const courses = [
|
||||
"beef",
|
||||
|
|
@ -406,9 +675,23 @@ window.Markers = (function () {
|
|||
"cheese",
|
||||
"corn",
|
||||
"rat tails",
|
||||
"pig ears"
|
||||
"pig ears",
|
||||
];
|
||||
const types = [
|
||||
"hot",
|
||||
"cold",
|
||||
"fire",
|
||||
"ice",
|
||||
"smoky",
|
||||
"misty",
|
||||
"shiny",
|
||||
"sweet",
|
||||
"bitter",
|
||||
"salty",
|
||||
"sour",
|
||||
"sparkling",
|
||||
"smelly",
|
||||
];
|
||||
const types = ["hot", "cold", "fire", "ice", "smoky", "misty", "shiny", "sweet", "bitter", "salty", "sour", "sparkling", "smelly"];
|
||||
const drinks = [
|
||||
"wine",
|
||||
"brandy",
|
||||
|
|
@ -430,7 +713,7 @@ window.Markers = (function () {
|
|||
"tea",
|
||||
"water",
|
||||
"juice",
|
||||
"sap"
|
||||
"sap",
|
||||
];
|
||||
|
||||
while (quantity) {
|
||||
|
|
@ -439,10 +722,16 @@ window.Markers = (function () {
|
|||
const typeName = P(0.3) ? "inn" : "tavern";
|
||||
const isAnimalThemed = P(0.85);
|
||||
const animal = ra(animals);
|
||||
const name = isAnimalThemed ? (P(0.6) ? ra(colors) + " " + animal : ra(adjectives) + " " + animal) : ra(adjectives) + " " + capitalize(type);
|
||||
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 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--;
|
||||
|
|
@ -452,15 +741,28 @@ window.Markers = (function () {
|
|||
function addLighthouses(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
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])));
|
||||
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`});
|
||||
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--;
|
||||
}
|
||||
}
|
||||
|
|
@ -468,7 +770,15 @@ window.Markers = (function () {
|
|||
function addWaterfalls(type, icon, multiplier) {
|
||||
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 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 quantity = getQuantity(waterfalls, 1, 5, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -478,20 +788,35 @@ window.Markers = (function () {
|
|||
"An impressive waterfall has cut through the land",
|
||||
"The cascades of a stunning 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 id = addMarker({ cell, icon, type, dy: 54, px: 16 });
|
||||
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)}`});
|
||||
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) {
|
||||
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));
|
||||
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
|
||||
)
|
||||
);
|
||||
let quantity = getQuantity(battlefields, 50, 700, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -499,7 +824,8 @@ window.Markers = (function () {
|
|||
const [cell] = extractAnyElement(battlefields);
|
||||
const id = addMarker({ cell, icon, type, dy: 52 });
|
||||
const state = states[cells.state[cell]];
|
||||
if (!state.campaigns) state.campaigns = BurgsAndStates.generateCampaign(state);
|
||||
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";
|
||||
|
|
@ -512,7 +838,9 @@ window.Markers = (function () {
|
|||
function addDungeons(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
let dungeons = Array.from(cells.i.filter(i => !occupied[i] && cells.pop[i] && cells.pop[i] < 3));
|
||||
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;
|
||||
|
||||
|
|
@ -531,7 +859,12 @@ window.Markers = (function () {
|
|||
function addLakeMonsters(type, icon, multiplier) {
|
||||
const { features } = pack;
|
||||
|
||||
const lakes = features.filter(feature => feature.type === "lake" && feature.group === "freshwater" && !occupied[feature.firstCell]);
|
||||
const lakes = features.filter(
|
||||
(feature) =>
|
||||
feature.type === "lake" &&
|
||||
feature.group === "freshwater" &&
|
||||
!occupied[feature.firstCell]
|
||||
);
|
||||
let quantity = getQuantity(lakes, 2, 10, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -550,7 +883,14 @@ window.Markers = (function () {
|
|||
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"));
|
||||
const sea = Array.from(
|
||||
cells.i.filter(
|
||||
(i) =>
|
||||
!occupied[i] &&
|
||||
cells.h[i] < 20 &&
|
||||
features[cells.f[i]].type === "ocean"
|
||||
)
|
||||
);
|
||||
let quantity = getQuantity(sea, 50, 700, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -568,7 +908,9 @@ window.Markers = (function () {
|
|||
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]));
|
||||
const hills = Array.from(
|
||||
cells.i.filter((i) => !occupied[i] && cells.h[i] >= 50)
|
||||
);
|
||||
let quantity = getQuantity(hills, 30, 600, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -587,23 +929,33 @@ window.Markers = (function () {
|
|||
"superior",
|
||||
"terrifying",
|
||||
"horrifying",
|
||||
"feared"
|
||||
"feared",
|
||||
];
|
||||
const subjects = [
|
||||
"Locals",
|
||||
"Elders",
|
||||
"Inscriptions",
|
||||
"Tipplers",
|
||||
"Legends",
|
||||
"Whispers",
|
||||
"Rumors",
|
||||
"Journeying folk",
|
||||
"Tales",
|
||||
];
|
||||
const subjects = ["Locals", "Elders", "Inscriptions", "Tipplers", "Legends", "Whispers", "Rumors", "Journeying folk", "Tales"];
|
||||
const species = [
|
||||
"Ogre",
|
||||
"Ankheg",
|
||||
"Troll",
|
||||
"Cyclops",
|
||||
"Giant",
|
||||
"Monster",
|
||||
"Beast",
|
||||
"Dragon",
|
||||
"Griffon",
|
||||
"Hag",
|
||||
"Banshee",
|
||||
"Bearded Devil",
|
||||
"Roc",
|
||||
"Hydra",
|
||||
"Warg"
|
||||
"Warg",
|
||||
"Giant Owl",
|
||||
"Owlbear",
|
||||
"Dire bear",
|
||||
"Dire tiger",
|
||||
"Giant Lizard",
|
||||
"Hyenas",
|
||||
];
|
||||
const modusOperandi = [
|
||||
"steals cattle at night",
|
||||
|
|
@ -616,7 +968,7 @@ window.Markers = (function () {
|
|||
"harasses travelers in the area",
|
||||
"snatches people from homes",
|
||||
"attacks anyone who dares to approach its lair",
|
||||
"attacks unsuspecting victims"
|
||||
"attacks unsuspecting victims",
|
||||
];
|
||||
|
||||
while (quantity) {
|
||||
|
|
@ -625,7 +977,91 @@ window.Markers = (function () {
|
|||
const monster = ra(species);
|
||||
const toponym = Names.getCulture(cells.culture[cell]);
|
||||
const name = `${toponym} ${monster}`;
|
||||
const legend = `${ra(subjects)} speak of a ${ra(adjectives)} ${monster} who inhabits ${toponym} hills and ${ra(modusOperandi)}`;
|
||||
const legend = `${ra(subjects)} speak of a ${ra(
|
||||
adjectives
|
||||
)} ${monster} who inhabits ${toponym} hills and ${ra(modusOperandi)}`;
|
||||
notes.push({ id, name, legend });
|
||||
quantity--;
|
||||
}
|
||||
}
|
||||
|
||||
function addGoatHeard(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
const hills = Array.from(
|
||||
cells.i.filter((i) => !occupied[i] && cells.h[i] >= 20)
|
||||
);
|
||||
let quantity = getQuantity(hills, 30, 600, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
while (quantity) {
|
||||
const [cell] = extractAnyElement(hills);
|
||||
const id = addMarker({ cell, icon, type, dy: 54, px: 13 });
|
||||
const name = `Heard of Giant Goats`;
|
||||
const legend = `Giant heard of goats`;
|
||||
notes.push({ id, name, legend });
|
||||
quantity--;
|
||||
}
|
||||
}
|
||||
|
||||
function addSpiders(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
const hills = Array.from(
|
||||
cells.i.filter((i) => !occupied[i] && cells.h[i] >= 50)
|
||||
);
|
||||
let quantity = getQuantity(hills, 30, 600, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
const adjectives = [
|
||||
"prime",
|
||||
"proud",
|
||||
"fat",
|
||||
"hungry",
|
||||
"superior",
|
||||
"terrifying",
|
||||
"horrifying",
|
||||
"feared",
|
||||
];
|
||||
const subjects = [
|
||||
"Locals",
|
||||
"Elders",
|
||||
"Inscriptions",
|
||||
"Tipplers",
|
||||
"Legends",
|
||||
"Whispers",
|
||||
"Rumors",
|
||||
"Journeying folk",
|
||||
"Tales",
|
||||
];
|
||||
const species = [
|
||||
"Giant Spider",
|
||||
"Giant Wolf",
|
||||
"Mammoth Spider",
|
||||
"Phase Spider",
|
||||
"Sword Spider",
|
||||
"Steeder",
|
||||
];
|
||||
const modusOperandi = [
|
||||
"steals goats at night",
|
||||
"prefers eating children",
|
||||
"keeps the region at bay",
|
||||
"abducts young women",
|
||||
"terrorizes the region",
|
||||
"harasses travelers in the area",
|
||||
"attacks anyone who dares to approach its lair",
|
||||
"attacks unsuspecting victims",
|
||||
];
|
||||
|
||||
while (quantity) {
|
||||
const [cell] = extractAnyElement(hills);
|
||||
const id = addMarker({ cell, icon, type, dy: 54, px: 13 });
|
||||
const monster = ra(species);
|
||||
const toponym = Names.getCulture(cells.culture[cell]);
|
||||
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--;
|
||||
}
|
||||
|
|
@ -635,7 +1071,13 @@ window.Markers = (function () {
|
|||
const { cells, cultures } = pack;
|
||||
|
||||
let lonelyMountains = Array.from(
|
||||
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))
|
||||
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)
|
||||
)
|
||||
);
|
||||
let quantity = getQuantity(lonelyMountains, 1, 5, multiplier);
|
||||
if (!quantity) return;
|
||||
|
|
@ -643,7 +1085,7 @@ window.Markers = (function () {
|
|||
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 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}`;
|
||||
|
|
@ -655,7 +1097,12 @@ window.Markers = (function () {
|
|||
function addSacredForests(type, icon, multiplier) {
|
||||
const { cells, cultures } = pack;
|
||||
|
||||
let temperateForests = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && [6, 8].includes(cells.biome[i])));
|
||||
let temperateForests = Array.from(
|
||||
cells.i.filter(
|
||||
(i) =>
|
||||
!occupied[i] && cells.culture[i] && [6, 8].includes(cells.biome[i])
|
||||
)
|
||||
);
|
||||
let quantity = getQuantity(temperateForests, 30, 1000, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -673,7 +1120,11 @@ window.Markers = (function () {
|
|||
function addSacredPineries(type, icon, multiplier) {
|
||||
const { cells, cultures } = pack;
|
||||
|
||||
let borealForests = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.biome[i] === 9));
|
||||
let borealForests = Array.from(
|
||||
cells.i.filter(
|
||||
(i) => !occupied[i] && cells.culture[i] && cells.biome[i] === 9
|
||||
)
|
||||
);
|
||||
let quantity = getQuantity(borealForests, 30, 800, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -691,7 +1142,31 @@ window.Markers = (function () {
|
|||
function addSacredPalmGroves(type, icon, multiplier) {
|
||||
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]));
|
||||
let borealForests = Array.from(
|
||||
cells.i.filter(
|
||||
(i) => !occupied[i] && cells.culture[i] && cells.biome[i] === 5
|
||||
)
|
||||
);
|
||||
let quantity = getQuantity(borealForests, 30, 800, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
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 addSacredCitidel(type, icon, multiplier) {
|
||||
const { cells, cultures } = pack;
|
||||
|
||||
let oasises = Array.from(
|
||||
cells.i.filter((i) => !occupied[i] && cells.road[i] && cells.h[i] > 40)
|
||||
);
|
||||
let quantity = getQuantity(oasises, 1, 100, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -700,7 +1175,7 @@ window.Markers = (function () {
|
|||
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`;
|
||||
const legend = `A Sacred Citidel of ${cultures[culture].name} culture`;
|
||||
notes.push({ id, name, legend });
|
||||
quantity--;
|
||||
}
|
||||
|
|
@ -709,7 +1184,11 @@ window.Markers = (function () {
|
|||
function addBrigands(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
let roads = Array.from(cells.i.filter(i => !occupied[i] && cells.culture[i] && cells.road[i] > 4));
|
||||
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;
|
||||
|
||||
|
|
@ -743,7 +1222,7 @@ window.Markers = (function () {
|
|||
"Tigers",
|
||||
"Wolfs",
|
||||
"Wolverines",
|
||||
"Falcons"
|
||||
"Falcons",
|
||||
];
|
||||
const types = { brigands: 4, bandits: 3, robbers: 1, highwaymen: 1 };
|
||||
|
||||
|
|
@ -775,7 +1254,9 @@ window.Markers = (function () {
|
|||
function addPirates(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
|
||||
let searoutes = Array.from(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;
|
||||
|
||||
|
|
@ -791,17 +1272,33 @@ window.Markers = (function () {
|
|||
|
||||
function addStatues(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
let statues = Array.from(cells.i.filter(i => !occupied[i] && cells.h[i] >= 20 && cells.h[i] < 40));
|
||||
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 = {
|
||||
cypriot: "𐠁𐠂𐠃𐠄𐠅𐠈𐠊𐠋𐠌𐠍𐠎𐠏𐠐𐠑𐠒𐠓𐠔𐠕𐠖𐠗𐠘𐠙𐠚𐠛𐠜𐠝𐠞𐠟𐠠𐠡𐠢𐠣𐠤𐠥𐠦𐠧𐠨𐠩𐠪𐠫𐠬𐠭𐠮𐠯𐠰𐠱𐠲𐠳𐠴𐠵𐠷𐠸𐠼𐠿 ",
|
||||
geez: "ሀለሐመሠረሰቀበተኀነአከወዐዘየደገጠጰጸፀፈፐ ",
|
||||
coptic: "ⲲⲴⲶⲸⲺⲼⲾⳀⳁⳂⳃⳄⳆⳈⳊⳌⳎⳐⳒⳔⳖⳘⳚⳜⳞⳠⳢⳤ⳥⳧⳩⳪ⳫⳬⳭⳲ⳹⳾ ",
|
||||
tibetan: "ༀ༁༂༃༄༅༆༇༈༉༊་༌༐༑༒༓༔༕༖༗༘༙༚༛༜༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿",
|
||||
mongolian: "᠀᠐᠑᠒ᠠᠡᠦᠧᠨᠩᠪᠭᠮᠯᠰᠱᠲᠳᠵᠻᠼᠽᠾᠿᡀᡁᡆᡍᡎᡏᡐᡑᡒᡓᡔᡕᡖᡗᡙᡜᡝᡞᡟᡠᡡᡭᡮᡯᡰᡱᡲᡳᡴᢀᢁᢂᢋᢏᢐᢑᢒᢓᢛᢜᢞᢟᢠᢡᢢᢤᢥᢦ"
|
||||
mongolian:
|
||||
"᠀᠐᠑᠒ᠠᠡᠦᠧᠨᠩᠪᠭᠮᠯᠰᠱᠲᠳᠵᠻᠼᠽᠾᠿᡀᡁᡆᡍᡎᡏᡐᡑᡒᡓᡔᡕᡖᡗᡙᡜᡝᡞᡟᡠᡡᡭᡮᡯᡰᡱᡲᡳᡴᢀᢁᢂᢋᢏᢐᢑᢒᢓᢛᢜᢞᢟᢠᢡᢢᢤᢥᢦ",
|
||||
};
|
||||
|
||||
while (quantity) {
|
||||
|
|
@ -825,7 +1322,15 @@ window.Markers = (function () {
|
|||
|
||||
function addRuines(type, icon, multiplier) {
|
||||
const { cells } = pack;
|
||||
let ruins = Array.from(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;
|
||||
|
||||
|
|
@ -842,7 +1347,7 @@ window.Markers = (function () {
|
|||
"Outpost",
|
||||
"Fortification",
|
||||
"Fortress",
|
||||
"Castle"
|
||||
"Castle",
|
||||
];
|
||||
|
||||
while (quantity) {
|
||||
|
|
@ -857,13 +1362,12 @@ window.Markers = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function addPortals(type, icon, multiplier) {
|
||||
const { burgs } = pack;
|
||||
let portals = burgs
|
||||
.slice(1, Math.ceil(burgs.length / 10) + 1)
|
||||
.filter(({ cell }) => !occupied[cell])
|
||||
.map(burg => [burg.name, burg.cell]);
|
||||
.map((burg) => [burg.name, burg.cell]);
|
||||
let quantity = getQuantity(portals, 16, 8, multiplier);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
|
|||
168
modules/save.js
168
modules/save.js
|
|
@ -6,9 +6,19 @@ function getMapData() {
|
|||
TIME && console.time("createMapData");
|
||||
|
||||
const date = new Date();
|
||||
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
||||
const params = [version, license, dateString, seed, graphWidth, graphHeight, mapId].join("|");
|
||||
const dateString =
|
||||
date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||
const license =
|
||||
"File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
||||
const params = [
|
||||
version,
|
||||
license,
|
||||
dateString,
|
||||
seed,
|
||||
graphWidth,
|
||||
graphHeight,
|
||||
mapId,
|
||||
].join("|");
|
||||
const settings = [
|
||||
distanceUnitInput.value,
|
||||
distanceScaleInput.value,
|
||||
|
|
@ -34,10 +44,14 @@ function getMapData() {
|
|||
+hideLabels.checked,
|
||||
stylePreset.value,
|
||||
+rescaleLabels.checked,
|
||||
urbanDensity
|
||||
urbanDensity,
|
||||
].join("|");
|
||||
const coords = JSON.stringify(mapCoordinates);
|
||||
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
||||
const biomes = [
|
||||
biomesData.color,
|
||||
biomesData.habitability,
|
||||
biomesData.name,
|
||||
].join("|");
|
||||
const notesData = JSON.stringify(notes);
|
||||
const rulersString = rulers.toString();
|
||||
const fonts = JSON.stringify(getUsedFonts(svg.node()));
|
||||
|
|
@ -55,7 +69,14 @@ function getMapData() {
|
|||
const serializedSVG = new XMLSerializer().serializeToString(cloneEl);
|
||||
|
||||
const { spacing, cellsX, cellsY, boundary, points, features } = grid;
|
||||
const gridGeneral = JSON.stringify({spacing, cellsX, cellsY, boundary, points, features});
|
||||
const gridGeneral = JSON.stringify({
|
||||
spacing,
|
||||
cellsX,
|
||||
cellsY,
|
||||
boundary,
|
||||
points,
|
||||
features,
|
||||
});
|
||||
const packFeatures = JSON.stringify(pack.features);
|
||||
const cultures = JSON.stringify(pack.cultures);
|
||||
const states = JSON.stringify(pack.states);
|
||||
|
|
@ -75,7 +96,7 @@ function getMapData() {
|
|||
.join("/");
|
||||
|
||||
// round population to save space
|
||||
const pop = Array.from(pack.cells.pop).map(p => rn(p, 4));
|
||||
const pop = Array.from(pack.cells.pop).map((p) => rn(p, 4));
|
||||
|
||||
// data format as below
|
||||
const mapData = [
|
||||
|
|
@ -114,7 +135,7 @@ function getMapData() {
|
|||
rivers,
|
||||
rulersString,
|
||||
fonts,
|
||||
markers
|
||||
markers,
|
||||
].join("\r\n");
|
||||
TIME && console.timeEnd("createMapData");
|
||||
|
||||
|
|
@ -122,10 +143,7 @@ function getMapData() {
|
|||
}
|
||||
|
||||
// Download .map file
|
||||
function dowloadMap() {
|
||||
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
||||
closeDialogs("#alert");
|
||||
|
||||
function downloadMapOrig() {
|
||||
const mapData = getMapData();
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
|
|
@ -133,12 +151,104 @@ function dowloadMap() {
|
|||
link.download = getFileName() + ".map";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
tip(`${link.download} is saved. Open "Downloads" screen (CTRL + J) to check`, true, "success", 7000);
|
||||
}
|
||||
|
||||
function downloadMarkers() {
|
||||
const mapData = JSON.stringify(pack.markers);
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + "-markers.json";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
}
|
||||
|
||||
function downloadBurgs() {
|
||||
const mapData = JSON.stringify(pack.burgs);
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + "-burgs.json";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
}
|
||||
|
||||
function downloadReligions() {
|
||||
const mapData = JSON.stringify(pack.religions);
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + "-religions.json";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
}
|
||||
function downloadCultures() {
|
||||
const mapData = JSON.stringify(pack.cultures);
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + "-cultures.json";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
}
|
||||
|
||||
function downloadStates() {
|
||||
const mapData = JSON.stringify(pack.states);
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + "-states.json";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
}
|
||||
|
||||
function downloadNotes() {
|
||||
const mapData = JSON.stringify(pack.notes);
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + "-notes.json";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
}
|
||||
|
||||
function downloadPopRates() {
|
||||
const mapData = populationRate * urbanization;
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + "-poprate.txt";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
}
|
||||
|
||||
function dowloadMap() {
|
||||
if (customization)
|
||||
return tip(
|
||||
"Map cannot be saved when edit mode is active, please exit the mode and retry",
|
||||
false,
|
||||
"error"
|
||||
);
|
||||
closeDialogs("#alert");
|
||||
downloadMapOrig();
|
||||
downloadMarkers();
|
||||
downloadBurgs();
|
||||
downloadCultures();
|
||||
downloadNotes();
|
||||
downloadReligions();
|
||||
downloadPopRates();
|
||||
downloadStates();
|
||||
|
||||
window.URL.revokeObjectURL(URL);
|
||||
}
|
||||
|
||||
async function saveToDropbox() {
|
||||
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
||||
if (customization)
|
||||
return tip(
|
||||
"Map cannot be saved when edit mode is active, please exit the mode and retry",
|
||||
false,
|
||||
"error"
|
||||
);
|
||||
closeDialogs("#alert");
|
||||
const mapData = getMapData();
|
||||
const filename = getFileName() + ".map";
|
||||
|
|
@ -152,12 +262,22 @@ async function saveToDropbox() {
|
|||
}
|
||||
|
||||
function quickSave() {
|
||||
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
||||
if (customization)
|
||||
return tip(
|
||||
"Map cannot be saved when edit mode is active, please exit the mode and retry",
|
||||
false,
|
||||
"error"
|
||||
);
|
||||
|
||||
const mapData = getMapData();
|
||||
const blob = new Blob([mapData], { type: "text/plain" });
|
||||
if (blob) ldb.set("lastMap", blob); // auto-save map
|
||||
tip("Map is saved to browser memory. Please also save as .map file to secure progress", true, "success", 2000);
|
||||
tip(
|
||||
"Map is saved to browser memory. Please also save as .map file to secure progress",
|
||||
true,
|
||||
"success",
|
||||
2000
|
||||
);
|
||||
}
|
||||
|
||||
const saveReminder = function () {
|
||||
|
|
@ -170,7 +290,7 @@ const saveReminder = function () {
|
|||
"Don't forget to save your map on a regular basis!",
|
||||
"Just a gentle reminder for you to save the map",
|
||||
"Please don't forget to save your progress (saving as .map is the best option)",
|
||||
"Don't want to be reminded about need to save? Press CTRL+Q"
|
||||
"Don't want to be reminded about need to save? Press CTRL+Q",
|
||||
];
|
||||
const interval = 15 * 60 * 1000; // remind every 15 minutes
|
||||
|
||||
|
|
@ -184,12 +304,22 @@ saveReminder();
|
|||
|
||||
function toggleSaveReminder() {
|
||||
if (saveReminder.status) {
|
||||
tip("Save reminder is turned off. Press CTRL+Q again to re-initiate", true, "warn", 2000);
|
||||
tip(
|
||||
"Save reminder is turned off. Press CTRL+Q again to re-initiate",
|
||||
true,
|
||||
"warn",
|
||||
2000
|
||||
);
|
||||
clearInterval(saveReminder.reminder);
|
||||
localStorage.setItem("noReminder", true);
|
||||
saveReminder.status = 0;
|
||||
} else {
|
||||
tip("Save reminder is turned on. Press CTRL+Q to turn off", true, "warn", 2000);
|
||||
tip(
|
||||
"Save reminder is turned on. Press CTRL+Q to turn off",
|
||||
true,
|
||||
"warn",
|
||||
2000
|
||||
);
|
||||
localStorage.removeItem("noReminder");
|
||||
saveReminder();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,89 +7,170 @@ function editBurg(id) {
|
|||
|
||||
const burg = id || d3.event.target.dataset.id;
|
||||
elSelected = burgLabels.select("[data-id='" + burg + "']");
|
||||
burgLabels.selectAll("text").call(d3.drag().on("start", dragBurgLabel)).classed("draggable", true);
|
||||
burgLabels
|
||||
.selectAll("text")
|
||||
.call(d3.drag().on("start", dragBurgLabel))
|
||||
.classed("draggable", true);
|
||||
updateBurgValues();
|
||||
|
||||
$("#burgEditor").dialog({
|
||||
title: "Edit Burg",
|
||||
resizable: false,
|
||||
close: closeBurgEditor,
|
||||
position: {my: "left top", at: "left+10 top+10", of: "svg", collision: "fit"}
|
||||
position: {
|
||||
my: "left top",
|
||||
at: "left+10 top+10",
|
||||
of: "svg",
|
||||
collision: "fit",
|
||||
},
|
||||
});
|
||||
|
||||
if (modules.editBurg) return;
|
||||
modules.editBurg = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("burgGroupShow").addEventListener("click", showGroupSection);
|
||||
document.getElementById("burgGroupHide").addEventListener("click", hideGroupSection);
|
||||
document.getElementById("burgSelectGroup").addEventListener("change", changeGroup);
|
||||
document.getElementById("burgInputGroup").addEventListener("change", createNewGroup);
|
||||
document.getElementById("burgAddGroup").addEventListener("click", toggleNewGroupInput);
|
||||
document.getElementById("burgRemoveGroup").addEventListener("click", removeBurgsGroup);
|
||||
document
|
||||
.getElementById("burgGroupShow")
|
||||
.addEventListener("click", showGroupSection);
|
||||
document
|
||||
.getElementById("burgGroupHide")
|
||||
.addEventListener("click", hideGroupSection);
|
||||
document
|
||||
.getElementById("burgSelectGroup")
|
||||
.addEventListener("change", changeGroup);
|
||||
document
|
||||
.getElementById("burgInputGroup")
|
||||
.addEventListener("change", createNewGroup);
|
||||
document
|
||||
.getElementById("burgAddGroup")
|
||||
.addEventListener("click", toggleNewGroupInput);
|
||||
document
|
||||
.getElementById("burgRemoveGroup")
|
||||
.addEventListener("click", removeBurgsGroup);
|
||||
|
||||
document.getElementById("burgName").addEventListener("input", changeName);
|
||||
document.getElementById("burgNameReRandom").addEventListener("click", generateNameRandom);
|
||||
document
|
||||
.getElementById("burgNameReRandom")
|
||||
.addEventListener("click", generateNameRandom);
|
||||
document.getElementById("burgType").addEventListener("input", changeType);
|
||||
document.getElementById("burgCulture").addEventListener("input", changeCulture);
|
||||
document.getElementById("burgNameReCulture").addEventListener("click", generateNameCulture);
|
||||
document.getElementById("burgPopulation").addEventListener("change", changePopulation);
|
||||
burgBody.querySelectorAll(".burgFeature").forEach(el => el.addEventListener("click", toggleFeature));
|
||||
document.getElementById("mfcgBurgSeed").addEventListener("change", changeSeed);
|
||||
document.getElementById("regenerateMFCGBurgSeed").addEventListener("click", randomizeSeed);
|
||||
document
|
||||
.getElementById("burgCulture")
|
||||
.addEventListener("input", changeCulture);
|
||||
document
|
||||
.getElementById("burgNameReCulture")
|
||||
.addEventListener("click", generateNameCulture);
|
||||
document
|
||||
.getElementById("burgPopulation")
|
||||
.addEventListener("change", changePopulation);
|
||||
burgBody
|
||||
.querySelectorAll(".burgFeature")
|
||||
.forEach((el) => el.addEventListener("click", toggleFeature));
|
||||
document
|
||||
.getElementById("mfcgBurgSeed")
|
||||
.addEventListener("change", changeSeed);
|
||||
document
|
||||
.getElementById("regenerateMFCGBurgSeed")
|
||||
.addEventListener("click", randomizeSeed);
|
||||
|
||||
document.getElementById("burgStyleShow").addEventListener("click", showStyleSection);
|
||||
document.getElementById("burgStyleHide").addEventListener("click", hideStyleSection);
|
||||
document.getElementById("burgEditLabelStyle").addEventListener("click", editGroupLabelStyle);
|
||||
document.getElementById("burgEditIconStyle").addEventListener("click", editGroupIconStyle);
|
||||
document.getElementById("burgEditAnchorStyle").addEventListener("click", editGroupAnchorStyle);
|
||||
document
|
||||
.getElementById("burgStyleShow")
|
||||
.addEventListener("click", showStyleSection);
|
||||
document
|
||||
.getElementById("burgStyleHide")
|
||||
.addEventListener("click", hideStyleSection);
|
||||
document
|
||||
.getElementById("burgEditLabelStyle")
|
||||
.addEventListener("click", editGroupLabelStyle);
|
||||
document
|
||||
.getElementById("burgEditIconStyle")
|
||||
.addEventListener("click", editGroupIconStyle);
|
||||
document
|
||||
.getElementById("burgEditAnchorStyle")
|
||||
.addEventListener("click", editGroupAnchorStyle);
|
||||
|
||||
document.getElementById("burgEmblem").addEventListener("click", openEmblemEdit);
|
||||
document.getElementById("burgToggleMFCGMap").addEventListener("click", toggleMFCGMap);
|
||||
document.getElementById("burgEditEmblem").addEventListener("click", openEmblemEdit);
|
||||
document.getElementById("burgRelocate").addEventListener("click", toggleRelocateBurg);
|
||||
document.getElementById("burglLegend").addEventListener("click", editBurgLegend);
|
||||
document.getElementById("burgLock").addEventListener("click", toggleBurgLockButton);
|
||||
document.getElementById("burgRemove").addEventListener("click", removeSelectedBurg);
|
||||
document
|
||||
.getElementById("burgEmblem")
|
||||
.addEventListener("click", openEmblemEdit);
|
||||
document
|
||||
.getElementById("burgToggleMFCGMap")
|
||||
.addEventListener("click", toggleMFCGMap);
|
||||
document
|
||||
.getElementById("burgEditEmblem")
|
||||
.addEventListener("click", openEmblemEdit);
|
||||
document
|
||||
.getElementById("burgRelocate")
|
||||
.addEventListener("click", toggleRelocateBurg);
|
||||
document
|
||||
.getElementById("burglLegend")
|
||||
.addEventListener("click", editBurgLegend);
|
||||
document
|
||||
.getElementById("burgLock")
|
||||
.addEventListener("click", toggleBurgLockButton);
|
||||
document
|
||||
.getElementById("burgRemove")
|
||||
.addEventListener("click", removeSelectedBurg);
|
||||
|
||||
function updateBurgValues() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
const b = pack.burgs[id];
|
||||
const province = pack.cells.province[b.cell];
|
||||
const provinceName = province ? pack.provinces[province].fullName + ", " : "";
|
||||
const stateName = pack.states[b.state].fullName || pack.states[b.state].name;
|
||||
document.getElementById("burgProvinceAndState").innerHTML = provinceName + stateName;
|
||||
const provinceName = province
|
||||
? pack.provinces[province].fullName + ", "
|
||||
: "";
|
||||
const stateName =
|
||||
pack.states[b.state].fullName || pack.states[b.state].name;
|
||||
document.getElementById("burgProvinceAndState").innerHTML =
|
||||
provinceName + stateName;
|
||||
|
||||
document.getElementById("burgName").value = b.name;
|
||||
document.getElementById("burgType").value = b.type || "Generic";
|
||||
document.getElementById("burgPopulation").value = rn(b.population * populationRate * urbanization);
|
||||
document.getElementById("burgEditAnchorStyle").style.display = +b.port ? "inline-block" : "none";
|
||||
document.getElementById("burgPopulation").value = rn(
|
||||
b.population * populationRate * urbanization
|
||||
);
|
||||
document.getElementById("burgEditAnchorStyle").style.display = +b.port
|
||||
? "inline-block"
|
||||
: "none";
|
||||
|
||||
// update list and select culture
|
||||
const cultureSelect = document.getElementById("burgCulture");
|
||||
cultureSelect.options.length = 0;
|
||||
const cultures = pack.cultures.filter(c => !c.removed);
|
||||
cultures.forEach(c => cultureSelect.options.add(new Option(c.name, c.i, false, c.i === b.culture)));
|
||||
const cultures = pack.cultures.filter((c) => !c.removed);
|
||||
cultures.forEach((c) =>
|
||||
cultureSelect.options.add(
|
||||
new Option(c.name, c.i, false, c.i === b.culture)
|
||||
)
|
||||
);
|
||||
|
||||
const temperature = grid.cells.temp[pack.cells.g[b.cell]];
|
||||
document.getElementById("burgTemperature").innerHTML = convertTemperature(temperature);
|
||||
document.getElementById("burgTemperatureLikeIn").innerHTML = getTemperatureLikeness(temperature);
|
||||
document.getElementById("burgElevation").innerHTML = getHeight(pack.cells.h[b.cell]);
|
||||
document.getElementById("burgTemperature").innerHTML =
|
||||
convertTemperature(temperature);
|
||||
document.getElementById("burgTemperatureLikeIn").innerHTML =
|
||||
getTemperatureLikeness(temperature);
|
||||
document.getElementById("burgElevation").innerHTML = getHeight(
|
||||
pack.cells.h[b.cell]
|
||||
);
|
||||
|
||||
// toggle features
|
||||
if (b.capital) document.getElementById("burgCapital").classList.remove("inactive");
|
||||
if (b.capital)
|
||||
document.getElementById("burgCapital").classList.remove("inactive");
|
||||
else document.getElementById("burgCapital").classList.add("inactive");
|
||||
if (b.port) document.getElementById("burgPort").classList.remove("inactive");
|
||||
if (b.port)
|
||||
document.getElementById("burgPort").classList.remove("inactive");
|
||||
else document.getElementById("burgPort").classList.add("inactive");
|
||||
if (b.citadel) document.getElementById("burgCitadel").classList.remove("inactive");
|
||||
if (b.citadel)
|
||||
document.getElementById("burgCitadel").classList.remove("inactive");
|
||||
else document.getElementById("burgCitadel").classList.add("inactive");
|
||||
if (b.walls) document.getElementById("burgWalls").classList.remove("inactive");
|
||||
if (b.walls)
|
||||
document.getElementById("burgWalls").classList.remove("inactive");
|
||||
else document.getElementById("burgWalls").classList.add("inactive");
|
||||
if (b.plaza) document.getElementById("burgPlaza").classList.remove("inactive");
|
||||
if (b.plaza)
|
||||
document.getElementById("burgPlaza").classList.remove("inactive");
|
||||
else document.getElementById("burgPlaza").classList.add("inactive");
|
||||
if (b.temple) document.getElementById("burgTemple").classList.remove("inactive");
|
||||
if (b.temple)
|
||||
document.getElementById("burgTemple").classList.remove("inactive");
|
||||
else document.getElementById("burgTemple").classList.add("inactive");
|
||||
if (b.shanty) document.getElementById("burgShanty").classList.remove("inactive");
|
||||
if (b.shanty)
|
||||
document.getElementById("burgShanty").classList.remove("inactive");
|
||||
else document.getElementById("burgShanty").classList.add("inactive");
|
||||
|
||||
//toggle lock
|
||||
|
|
@ -101,7 +182,9 @@ function editBurg(id) {
|
|||
select.options.length = 0; // remove all options
|
||||
|
||||
burgLabels.selectAll("g").each(function () {
|
||||
select.options.add(new Option(this.id, this.id, false, this.id === group));
|
||||
select.options.add(
|
||||
new Option(this.id, this.id, false, this.id === group)
|
||||
);
|
||||
});
|
||||
|
||||
// set emlem image
|
||||
|
|
@ -157,7 +240,7 @@ function editBurg(id) {
|
|||
"Mogadishu",
|
||||
"Bangkok",
|
||||
"Aden",
|
||||
"Khartoum"
|
||||
"Khartoum",
|
||||
]; // 21 - 30
|
||||
if (temperature > 30) return "Mecca";
|
||||
return cities[temperature + 5] || null;
|
||||
|
|
@ -172,17 +255,25 @@ function editBurg(id) {
|
|||
const x = d3.event.x,
|
||||
y = d3.event.y;
|
||||
this.setAttribute("transform", `translate(${dx + x},${dy + y})`);
|
||||
tip('Use dragging for fine-tuning only, to actually move burg use "Relocate" button', false, "warning");
|
||||
tip(
|
||||
'Use dragging for fine-tuning only, to actually move burg use "Relocate" button',
|
||||
false,
|
||||
"warning"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function showGroupSection() {
|
||||
document.querySelectorAll("#burgBottom > button").forEach(el => (el.style.display = "none"));
|
||||
document
|
||||
.querySelectorAll("#burgBottom > button")
|
||||
.forEach((el) => (el.style.display = "none"));
|
||||
document.getElementById("burgGroupSection").style.display = "inline-block";
|
||||
}
|
||||
|
||||
function hideGroupSection() {
|
||||
document.querySelectorAll("#burgBottom > button").forEach(el => (el.style.display = "inline-block"));
|
||||
document
|
||||
.querySelectorAll("#burgBottom > button")
|
||||
.forEach((el) => (el.style.display = "inline-block"));
|
||||
document.getElementById("burgGroupSection").style.display = "none";
|
||||
document.getElementById("burgInputGroup").style.display = "none";
|
||||
document.getElementById("burgInputGroup").value = "";
|
||||
|
|
@ -216,7 +307,11 @@ function editBurg(id) {
|
|||
.replace(/[^\w\s]/gi, "");
|
||||
|
||||
if (document.getElementById(group)) {
|
||||
tip("Element with this id already exists. Please provide a unique name", false, "error");
|
||||
tip(
|
||||
"Element with this id already exists. Please provide a unique name",
|
||||
false,
|
||||
"error"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +339,9 @@ function editBurg(id) {
|
|||
const count = elSelected.node().parentNode.childElementCount;
|
||||
if (oldGroup !== "cities" && oldGroup !== "towns" && count === 1) {
|
||||
document.getElementById("burgSelectGroup").selectedOptions[0].remove();
|
||||
document.getElementById("burgSelectGroup").options.add(new Option(group, group, false, true));
|
||||
document
|
||||
.getElementById("burgSelectGroup")
|
||||
.options.add(new Option(group, group, false, true));
|
||||
toggleNewGroupInput();
|
||||
document.getElementById("burgInputGroup").value = "";
|
||||
labelG.id = group;
|
||||
|
|
@ -254,16 +351,24 @@ function editBurg(id) {
|
|||
}
|
||||
|
||||
// create new groups
|
||||
document.getElementById("burgSelectGroup").options.add(new Option(group, group, false, true));
|
||||
document
|
||||
.getElementById("burgSelectGroup")
|
||||
.options.add(new Option(group, group, false, true));
|
||||
toggleNewGroupInput();
|
||||
document.getElementById("burgInputGroup").value = "";
|
||||
|
||||
const newLabelG = document.querySelector("#burgLabels").appendChild(labelG.cloneNode(false));
|
||||
const newLabelG = document
|
||||
.querySelector("#burgLabels")
|
||||
.appendChild(labelG.cloneNode(false));
|
||||
newLabelG.id = group;
|
||||
const newIconG = document.querySelector("#burgIcons").appendChild(iconG.cloneNode(false));
|
||||
const newIconG = document
|
||||
.querySelector("#burgIcons")
|
||||
.appendChild(iconG.cloneNode(false));
|
||||
newIconG.id = group;
|
||||
if (anchor) {
|
||||
const newAnchorG = document.querySelector("#anchors").appendChild(anchorG.cloneNode(false));
|
||||
const newAnchorG = document
|
||||
.querySelector("#anchors")
|
||||
.appendChild(anchorG.cloneNode(false));
|
||||
newAnchorG.id = group;
|
||||
}
|
||||
moveBurgToGroup(id, group);
|
||||
|
|
@ -277,11 +382,17 @@ function editBurg(id) {
|
|||
for (let i = 0; i < group.children.length; i++) {
|
||||
burgsInGroup.push(+group.children[i].dataset.id);
|
||||
}
|
||||
const burgsToRemove = burgsInGroup.filter(b => !(pack.burgs[b].capital || pack.burgs[b].lock));
|
||||
const burgsToRemove = burgsInGroup.filter(
|
||||
(b) => !(pack.burgs[b].capital || pack.burgs[b].lock)
|
||||
);
|
||||
const capital = burgsToRemove.length < burgsInGroup.length;
|
||||
|
||||
alertMessage.innerHTML = `Are you sure you want to remove
|
||||
${basic || capital ? "all unlocked elements in the group" : "the entire burg group"}?
|
||||
${
|
||||
basic || capital
|
||||
? "all unlocked elements in the group"
|
||||
: "the entire burg group"
|
||||
}?
|
||||
<br>Please note that capital or locked burgs will not be deleted.
|
||||
<br><br>Burgs to be removed: ${burgsToRemove.length}`;
|
||||
$("#alert").dialog({
|
||||
|
|
@ -292,7 +403,7 @@ function editBurg(id) {
|
|||
$(this).dialog("close");
|
||||
$("#burgEditor").dialog("close");
|
||||
hideGroupSection();
|
||||
burgsToRemove.forEach(b => removeBurg(b));
|
||||
burgsToRemove.forEach((b) => removeBurg(b));
|
||||
|
||||
if (!basic && !capital) {
|
||||
// entirely remove group
|
||||
|
|
@ -306,8 +417,8 @@ function editBurg(id) {
|
|||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -342,7 +453,10 @@ function editBurg(id) {
|
|||
|
||||
function changePopulation() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
pack.burgs[id].population = rn(burgPopulation.value / populationRate / urbanization, 4);
|
||||
pack.burgs[id].population = rn(
|
||||
burgPopulation.value / populationRate / urbanization,
|
||||
4
|
||||
);
|
||||
}
|
||||
|
||||
function toggleFeature() {
|
||||
|
|
@ -356,7 +470,9 @@ function editBurg(id) {
|
|||
if (b[feature]) this.classList.remove("inactive");
|
||||
else if (!b[feature]) this.classList.add("inactive");
|
||||
|
||||
if (b.port) document.getElementById("burgEditAnchorStyle").style.display = "inline-block";
|
||||
if (b.port)
|
||||
document.getElementById("burgEditAnchorStyle").style.display =
|
||||
"inline-block";
|
||||
else document.getElementById("burgEditAnchorStyle").style.display = "none";
|
||||
}
|
||||
|
||||
|
|
@ -379,12 +495,16 @@ function editBurg(id) {
|
|||
}
|
||||
|
||||
function showStyleSection() {
|
||||
document.querySelectorAll("#burgBottom > button").forEach(el => (el.style.display = "none"));
|
||||
document
|
||||
.querySelectorAll("#burgBottom > button")
|
||||
.forEach((el) => (el.style.display = "none"));
|
||||
document.getElementById("burgStyleSection").style.display = "inline-block";
|
||||
}
|
||||
|
||||
function hideStyleSection() {
|
||||
document.querySelectorAll("#burgBottom > button").forEach(el => (el.style.display = "inline-block"));
|
||||
document
|
||||
.querySelectorAll("#burgBottom > button")
|
||||
.forEach((el) => (el.style.display = "inline-block"));
|
||||
document.getElementById("burgStyleSection").style.display = "none";
|
||||
}
|
||||
|
||||
|
|
@ -408,8 +528,10 @@ function editBurg(id) {
|
|||
const burgGeneratorURL = getBurgLink(burg);
|
||||
document.getElementById("mfcgPreview").setAttribute("src", mfcgURL);
|
||||
document.getElementById("mfcgLink").setAttribute("href", mfcgURL);
|
||||
document.getElementById("burgGenerator").setAttribute("href", burgGeneratorURL);
|
||||
debug
|
||||
document
|
||||
.getElementById("burgGenerator")
|
||||
.setAttribute("href", burgGeneratorURL);
|
||||
debug;
|
||||
}
|
||||
function getBurgSeed(burg) {
|
||||
return burg.MFCG || Number(`${seed}${String(burg.i).padStart(4, 0)}`);
|
||||
|
|
@ -417,12 +539,14 @@ function editBurg(id) {
|
|||
|
||||
function getBurgLink(burg) {
|
||||
const { cells } = pack;
|
||||
let burgCulture = pack.cultures[burg.culture].name.split('(')[1].split(')')[0];
|
||||
|
||||
let burgCulture = pack.cultures[burg.culture].name
|
||||
.split("(")[1]
|
||||
.split(")")[0];
|
||||
|
||||
const { name, population, cell } = burg;
|
||||
const burgSeed = getBurgSeed(burg);
|
||||
const sizeRaw = 0.43 * Math.pow((population * populationRate) / urbanDensity, 0.385);
|
||||
const sizeRaw =
|
||||
0.43 * Math.pow((population * populationRate) / urbanDensity, 0.385);
|
||||
const size = minmax(Math.ceil(sizeRaw), 2, 40);
|
||||
const people = rn(population * populationRate * urbanization);
|
||||
const hub = +cells.road[cell] > 50;
|
||||
|
|
@ -435,6 +559,7 @@ function editBurg(id) {
|
|||
const temple = +burg.temple;
|
||||
const shanty = +burg.shanty;
|
||||
|
||||
const worldName = mapName.value;
|
||||
const sea = coast && cells.haven[cell] ? getSeaDirections(cell) : "";
|
||||
function getSeaDirections(i) {
|
||||
const p1 = cells.p[i];
|
||||
|
|
@ -445,23 +570,22 @@ function editBurg(id) {
|
|||
return "&sea=" + norm;
|
||||
}
|
||||
let townSize = "tiny";
|
||||
if (people > 200) townSize = 'small';
|
||||
if (people > 900) townSize = 'medium';
|
||||
if (people > 2_000) townSize = 'average';
|
||||
if (people > 5_500) townSize = 'big';
|
||||
if (people > 200) townSize = "small";
|
||||
if (people > 900) townSize = "medium";
|
||||
if (people > 2_000) townSize = "average";
|
||||
if (people > 5_500) townSize = "big";
|
||||
const baseURL = "http://localhost:9090/town/";
|
||||
const url = `${baseURL}${name}-${burgCulture}/${townSize}`;
|
||||
const url = `${baseURL}${worldName}_${name}-${burgCulture}/${townSize}`;
|
||||
|
||||
return url;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function getMFCGlink(burg) {
|
||||
const { cells } = pack;
|
||||
const { name, population, cell } = burg;
|
||||
const burgSeed = getBurgSeed(burg);
|
||||
const sizeRaw = 0.43 * Math.pow((population * populationRate) / urbanDensity, 0.385);
|
||||
const sizeRaw =
|
||||
0.43 * Math.pow((population * populationRate) / urbanDensity, 0.385);
|
||||
const size = minmax(Math.ceil(sizeRaw), 2, 40) * 3;
|
||||
const people = rn(population * populationRate * urbanization);
|
||||
|
||||
|
|
@ -485,7 +609,8 @@ function editBurg(id) {
|
|||
return "&sea=" + norm;
|
||||
}
|
||||
|
||||
const baseURL = "https://watabou.github.io/city-generator/?random=0&continuous=0";
|
||||
const baseURL =
|
||||
"https://watabou.github.io/city-generator/?random=0&continuous=0";
|
||||
const url = `${baseURL}&name=${name}&population=${people}&size=${size}&seed=${burgSeed}&hub=${hub}&river=${river}&coast=${coast}&citadel=${citadel}&plaza=${plaza}&temple=${temple}&walls=${walls}&shantytown=${shanty}${sea}`;
|
||||
return url;
|
||||
}
|
||||
|
|
@ -515,8 +640,11 @@ function editBurg(id) {
|
|||
|
||||
function toggleMFCGMap() {
|
||||
options.showMFCGMap = !options.showMFCGMap;
|
||||
document.getElementById("mfcgPreviewSection").style.display = options.showMFCGMap ? "block" : "none";
|
||||
document.getElementById("burgToggleMFCGMap").className = options.showMFCGMap ? "icon-map" : "icon-map-o";
|
||||
document.getElementById("mfcgPreviewSection").style.display =
|
||||
options.showMFCGMap ? "block" : "none";
|
||||
document.getElementById("burgToggleMFCGMap").className = options.showMFCGMap
|
||||
? "icon-map"
|
||||
: "icon-map-o";
|
||||
}
|
||||
|
||||
function toggleRelocateBurg() {
|
||||
|
|
@ -524,7 +652,10 @@ function editBurg(id) {
|
|||
document.getElementById("burgRelocate").classList.toggle("pressed");
|
||||
if (document.getElementById("burgRelocate").classList.contains("pressed")) {
|
||||
viewbox.style("cursor", "crosshair").on("click", relocateBurgOnClick);
|
||||
tip("Click on map to relocate burg. Hold Shift for continuous move", true);
|
||||
tip(
|
||||
"Click on map to relocate burg. Hold Shift for continuous move",
|
||||
true
|
||||
);
|
||||
if (!layerIsOn("toggleCells")) {
|
||||
toggleCells();
|
||||
toggler.dataset.forced = true;
|
||||
|
|
@ -547,12 +678,20 @@ function editBurg(id) {
|
|||
const burg = pack.burgs[id];
|
||||
|
||||
if (cells.h[cell] < 20) {
|
||||
tip("Cannot place burg into the water! Select a land cell", false, "error");
|
||||
tip(
|
||||
"Cannot place burg into the water! Select a land cell",
|
||||
false,
|
||||
"error"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cells.burg[cell] && cells.burg[cell] !== id) {
|
||||
tip("There is already a burg in this cell. Please select a free cell", false, "error");
|
||||
tip(
|
||||
"There is already a burg in this cell. Please select a free cell",
|
||||
false,
|
||||
"error"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -614,8 +753,8 @@ function editBurg(id) {
|
|||
buttons: {
|
||||
Ok: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
alertMessage.innerHTML = "Are you sure you want to remove the burg?";
|
||||
|
|
@ -630,15 +769,18 @@ function editBurg(id) {
|
|||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function closeBurgEditor() {
|
||||
document.getElementById("burgRelocate").classList.remove("pressed");
|
||||
burgLabels.selectAll("text").call(d3.drag().on("drag", null)).classed("draggable", false);
|
||||
burgLabels
|
||||
.selectAll("text")
|
||||
.call(d3.drag().on("drag", null))
|
||||
.classed("draggable", false);
|
||||
unselect();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ restoreDefaultEvents(); // apply default viewbox events on load
|
|||
// restore default viewbox events
|
||||
function restoreDefaultEvents() {
|
||||
svg.call(zoom);
|
||||
viewbox.style("cursor", "default").on(".drag", null).on("click", clicked).on("touchmove mousemove", moved);
|
||||
viewbox
|
||||
.style("cursor", "default")
|
||||
.on(".drag", null)
|
||||
.on("click", clicked)
|
||||
.on("touchmove mousemove", moved);
|
||||
legend.call(d3.drag().on("start", dragLegendBox));
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +28,11 @@ function clicked() {
|
|||
if (grand.id === "emblems") editEmblem();
|
||||
else if (parent.id === "rivers") editRiver(el.id);
|
||||
else if (grand.id === "routes") editRoute();
|
||||
else if (el.tagName === "tspan" && grand.parentNode.parentNode.id === "labels") editLabel();
|
||||
else if (
|
||||
el.tagName === "tspan" &&
|
||||
grand.parentNode.parentNode.id === "labels"
|
||||
)
|
||||
editLabel();
|
||||
else if (grand.id === "burgLabels") editBurg();
|
||||
else if (grand.id === "burgIcons") editBurg();
|
||||
else if (parent.id === "ice") editIce();
|
||||
|
|
@ -71,7 +79,8 @@ function moveCircle(x, y, r = 20) {
|
|||
}
|
||||
|
||||
function removeCircle() {
|
||||
if (document.getElementById("brushCircle")) document.getElementById("brushCircle").remove();
|
||||
if (document.getElementById("brushCircle"))
|
||||
document.getElementById("brushCircle").remove();
|
||||
}
|
||||
|
||||
// get browser-defined fit-content
|
||||
|
|
@ -92,8 +101,8 @@ function sortLines(header) {
|
|||
if (!header.className.includes("icon-sort") && type === "name") order = "-up";
|
||||
|
||||
const headers = header.parentNode;
|
||||
headers.querySelectorAll("div.sortable").forEach(e => {
|
||||
e.classList.forEach(c => {
|
||||
headers.querySelectorAll("div.sortable").forEach((e) => {
|
||||
e.classList.forEach((c) => {
|
||||
if (c.includes("icon-sort")) e.classList.remove(c);
|
||||
});
|
||||
});
|
||||
|
|
@ -116,7 +125,7 @@ function applySorting(headers) {
|
|||
const bn = name ? b.dataset[sortby] : +b.dataset[sortby];
|
||||
return (an > bn ? 1 : an < bn ? -1 : 0) * desc;
|
||||
})
|
||||
.forEach(line => list.appendChild(line));
|
||||
.forEach((line) => list.appendChild(line));
|
||||
}
|
||||
|
||||
function addBurg(point) {
|
||||
|
|
@ -131,7 +140,10 @@ function addBurg(point) {
|
|||
const feature = cells.f[cell];
|
||||
|
||||
const temple = pack.states[state].form === "Theocracy";
|
||||
const population = Math.max((cells.s[cell] + cells.road[cell]) / 3 + i / 1000 + (cell % 100) / 1000, 0.1);
|
||||
const population = Math.max(
|
||||
(cells.s[cell] + cells.road[cell]) / 3 + i / 1000 + (cell % 100) / 1000,
|
||||
0.1
|
||||
);
|
||||
const type = BurgsAndStates.getType(cell, false);
|
||||
|
||||
// generate emblem
|
||||
|
|
@ -139,7 +151,22 @@ function addBurg(point) {
|
|||
coa.shield = COA.getShield(culture, state);
|
||||
COArenderer.add("burg", i, coa, x, y);
|
||||
|
||||
pack.burgs.push({name, cell, x, y, state, i, culture, feature, capital: 0, port: 0, temple, population, coa, type});
|
||||
pack.burgs.push({
|
||||
name,
|
||||
cell,
|
||||
x,
|
||||
y,
|
||||
state,
|
||||
i,
|
||||
culture,
|
||||
feature,
|
||||
capital: 0,
|
||||
port: 0,
|
||||
temple,
|
||||
population,
|
||||
coa,
|
||||
type,
|
||||
});
|
||||
cells.burg[cell] = i;
|
||||
|
||||
const townSize = burgIcons.select("#towns").attr("size") || 0.5;
|
||||
|
|
@ -219,7 +246,11 @@ function toggleCapital(burg) {
|
|||
return;
|
||||
}
|
||||
if (pack.burgs[burg].capital) {
|
||||
tip("To change capital please assign a capital status to another burg of this state", false, "error");
|
||||
tip(
|
||||
"To change capital please assign a capital status to another burg of this state",
|
||||
false,
|
||||
"error"
|
||||
);
|
||||
return;
|
||||
}
|
||||
const old = pack.states[state].capital;
|
||||
|
|
@ -244,7 +275,12 @@ function togglePort(burg) {
|
|||
|
||||
const haven = pack.cells.haven[b.cell];
|
||||
const port = haven ? pack.cells.f[haven] : -1;
|
||||
if (!haven) tip("Port haven is not found, system won't be able to make a searoute", false, "warn");
|
||||
if (!haven)
|
||||
tip(
|
||||
"Port haven is not found, system won't be able to make a searoute",
|
||||
false,
|
||||
"warn"
|
||||
);
|
||||
b.port = port;
|
||||
|
||||
const g = b.capital ? "cities" : "towns";
|
||||
|
|
@ -281,13 +317,22 @@ function drawLegend(name, data) {
|
|||
const vOffset = fontSize / 2;
|
||||
|
||||
// append items
|
||||
const boxes = legend.append("g").attr("stroke-width", 0.5).attr("stroke", "#111111").attr("stroke-dasharray", "none");
|
||||
const labels = legend.append("g").attr("fill", "#000000").attr("stroke", "none");
|
||||
const boxes = legend
|
||||
.append("g")
|
||||
.attr("stroke-width", 0.5)
|
||||
.attr("stroke", "#111111")
|
||||
.attr("stroke-dasharray", "none");
|
||||
const labels = legend
|
||||
.append("g")
|
||||
.attr("fill", "#000000")
|
||||
.attr("stroke", "none");
|
||||
|
||||
const columns = Math.ceil(data.length / itemsInCol);
|
||||
for (let column = 0, i = 0; column < columns; column++) {
|
||||
const linesInColumn = Math.ceil(data.length / columns);
|
||||
const offset = column ? colOffset * 2 + legend.node().getBBox().width : colOffset;
|
||||
const offset = column
|
||||
? colOffset * 2 + legend.node().getBBox().width
|
||||
: colOffset;
|
||||
|
||||
for (let l = 0; l < linesInColumn && data[i]; l++, i++) {
|
||||
boxes
|
||||
|
|
@ -354,7 +399,7 @@ function redrawLegend() {
|
|||
const data = legend
|
||||
.attr("data")
|
||||
.split("|")
|
||||
.map(l => l.split(","));
|
||||
.map((l) => l.split(","));
|
||||
drawLegend(name, data);
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +428,12 @@ function createPicker() {
|
|||
const cl = () => tip("Click to close the picker");
|
||||
const closePicker = () => contaiter.style("display", "none");
|
||||
|
||||
const contaiter = d3.select("body").append("svg").attr("id", "pickerContainer").attr("width", "100%").attr("height", "100%");
|
||||
const contaiter = d3
|
||||
.select("body")
|
||||
.append("svg")
|
||||
.attr("id", "pickerContainer")
|
||||
.attr("width", "100%")
|
||||
.attr("height", "100%");
|
||||
contaiter
|
||||
.append("rect")
|
||||
.attr("x", 0)
|
||||
|
|
@ -407,19 +457,39 @@ function createPicker() {
|
|||
const h = controls.append("g");
|
||||
h.append("text").attr("x", 4).attr("y", 14).text("H:");
|
||||
h.append("line").attr("x1", 18).attr("y1", 10).attr("x2", 107).attr("y2", 10);
|
||||
h.append("circle").attr("cx", 75).attr("cy", 10).attr("r", 5).attr("id", "pickerH");
|
||||
h.append("circle")
|
||||
.attr("cx", 75)
|
||||
.attr("cy", 10)
|
||||
.attr("r", 5)
|
||||
.attr("id", "pickerH");
|
||||
h.on("mousemove", () => tip("Set palette hue"));
|
||||
|
||||
const s = controls.append("g");
|
||||
s.append("text").attr("x", 113).attr("y", 14).text("S:");
|
||||
s.append("line").attr("x1", 124).attr("y1", 10).attr("x2", 206).attr("y2", 10);
|
||||
s.append("circle").attr("cx", 181.4).attr("cy", 10).attr("r", 5).attr("id", "pickerS");
|
||||
s.append("line")
|
||||
.attr("x1", 124)
|
||||
.attr("y1", 10)
|
||||
.attr("x2", 206)
|
||||
.attr("y2", 10);
|
||||
s.append("circle")
|
||||
.attr("cx", 181.4)
|
||||
.attr("cy", 10)
|
||||
.attr("r", 5)
|
||||
.attr("id", "pickerS");
|
||||
s.on("mousemove", () => tip("Set palette saturation"));
|
||||
|
||||
const l = controls.append("g");
|
||||
l.append("text").attr("x", 213).attr("y", 14).text("L:");
|
||||
l.append("line").attr("x1", 226).attr("y1", 10).attr("x2", 306).attr("y2", 10);
|
||||
l.append("circle").attr("cx", 282).attr("cy", 10).attr("r", 5).attr("id", "pickerL");
|
||||
l.append("line")
|
||||
.attr("x1", 226)
|
||||
.attr("y1", 10)
|
||||
.attr("x2", 306)
|
||||
.attr("y2", 10);
|
||||
l.append("circle")
|
||||
.attr("cx", 282)
|
||||
.attr("cy", 10)
|
||||
.attr("r", 5)
|
||||
.attr("id", "pickerL");
|
||||
l.on("mousemove", () => tip("Set palette lightness"));
|
||||
|
||||
controls.selectAll("line").on("click", clickPickerControl);
|
||||
|
|
@ -432,7 +502,9 @@ function createPicker() {
|
|||
.attr("y", 20)
|
||||
.attr("width", 303)
|
||||
.attr("height", 20)
|
||||
.on("mousemove", () => tip("Color value in different color spaces. Edit to change"));
|
||||
.on("mousemove", () =>
|
||||
tip("Color value in different color spaces. Edit to change")
|
||||
);
|
||||
const html = `
|
||||
<label style="margin-right: 6px">HSL:
|
||||
<input type="number" id="pickerHSL_H" data-space="hsl" min=0 max=360 value="231">,
|
||||
|
|
@ -448,12 +520,20 @@ function createPicker() {
|
|||
spaces.node().insertAdjacentHTML("beforeend", html);
|
||||
spaces.selectAll("input").on("change", changePickerSpace);
|
||||
|
||||
const colors = picker.append("g").attr("id", "pickerColors").attr("stroke", "#333333");
|
||||
const hatches = picker.append("g").attr("id", "pickerHatches").attr("stroke", "#333333");
|
||||
const colors = picker
|
||||
.append("g")
|
||||
.attr("id", "pickerColors")
|
||||
.attr("stroke", "#333333");
|
||||
const hatches = picker
|
||||
.append("g")
|
||||
.attr("id", "pickerHatches")
|
||||
.attr("stroke", "#333333");
|
||||
const hatching = d3.selectAll("g#hatching > pattern");
|
||||
const number = hatching.size();
|
||||
|
||||
const clr = d3.range(number).map(i => d3.hsl((i / number) * 360, 0.7, 0.7).hex());
|
||||
const clr = d3
|
||||
.range(number)
|
||||
.map((i) => d3.hsl((i / number) * 360, 0.7, 0.7).hex());
|
||||
clr.forEach(function (d, i) {
|
||||
colors
|
||||
.append("rect")
|
||||
|
|
@ -500,7 +580,12 @@ function createPicker() {
|
|||
.attr("fill", "#ffffff")
|
||||
.attr("stroke", "#5d4651")
|
||||
.on("mousemove", pos);
|
||||
picker.insert("text", ":first-child").attr("x", 291).attr("y", -10).attr("id", "pickerCloseText").text("✕");
|
||||
picker
|
||||
.insert("text", ":first-child")
|
||||
.attr("x", 291)
|
||||
.attr("y", -10)
|
||||
.attr("id", "pickerCloseText")
|
||||
.text("✕");
|
||||
picker
|
||||
.insert("rect", ":first-child")
|
||||
.attr("x", 288)
|
||||
|
|
@ -510,13 +595,32 @@ function createPicker() {
|
|||
.attr("height", 14)
|
||||
.on("mousemove", cl)
|
||||
.on("click", closePicker);
|
||||
picker.insert("text", ":first-child").attr("x", 12).attr("y", -10).attr("id", "pickerLabel").text("Color Picker").on("mousemove", pos);
|
||||
picker.insert("rect", ":first-child").attr("x", 0).attr("y", -30).attr("width", width).attr("height", 30).attr("id", "pickerHeader").on("mousemove", pos);
|
||||
picker.attr("transform", `translate(${(svgWidth - width) / 2},${(svgHeight - height) / 2})`);
|
||||
picker
|
||||
.insert("text", ":first-child")
|
||||
.attr("x", 12)
|
||||
.attr("y", -10)
|
||||
.attr("id", "pickerLabel")
|
||||
.text("Color Picker")
|
||||
.on("mousemove", pos);
|
||||
picker
|
||||
.insert("rect", ":first-child")
|
||||
.attr("x", 0)
|
||||
.attr("y", -30)
|
||||
.attr("width", width)
|
||||
.attr("height", 30)
|
||||
.attr("id", "pickerHeader")
|
||||
.on("mousemove", pos);
|
||||
picker.attr(
|
||||
"transform",
|
||||
`translate(${(svgWidth - width) / 2},${(svgHeight - height) / 2})`
|
||||
);
|
||||
}
|
||||
|
||||
function updateSelectedRect(fill) {
|
||||
document.getElementById("picker").querySelector("rect.selected").classList.remove("selected");
|
||||
document
|
||||
.getElementById("picker")
|
||||
.querySelector("rect.selected")
|
||||
.classList.remove("selected");
|
||||
document
|
||||
.getElementById("picker")
|
||||
.querySelector("rect[fill='" + fill.toLowerCase() + "']")
|
||||
|
|
@ -574,7 +678,9 @@ function openPicker(fill, callback) {
|
|||
updateSelectedRect(fill);
|
||||
|
||||
openPicker.updateFill = function () {
|
||||
const selected = document.getElementById("picker").querySelector("rect.selected");
|
||||
const selected = document
|
||||
.getElementById("picker")
|
||||
.querySelector("rect.selected");
|
||||
if (!selected) return;
|
||||
callback(selected.getAttribute("fill"));
|
||||
};
|
||||
|
|
@ -649,8 +755,15 @@ function changePickerSpace() {
|
|||
}
|
||||
|
||||
const space = this.dataset.space;
|
||||
const i = Array.from(this.parentNode.querySelectorAll("input")).map(input => input.value); // inputs
|
||||
const fill = space === "hex" ? d3.rgb(this.value) : space === "rgb" ? d3.rgb(i[0], i[1], i[2]) : d3.hsl(i[0], i[1] / 100, i[2] / 100);
|
||||
const i = Array.from(this.parentNode.querySelectorAll("input")).map(
|
||||
(input) => input.value
|
||||
); // inputs
|
||||
const fill =
|
||||
space === "hex"
|
||||
? d3.rgb(this.value)
|
||||
: space === "rgb"
|
||||
? d3.rgb(i[0], i[1], i[2])
|
||||
: d3.hsl(i[0], i[1] / 100, i[2] / 100);
|
||||
|
||||
const hsl = d3.hsl(fill);
|
||||
if (isNaN(hsl.l)) {
|
||||
|
|
@ -671,11 +784,27 @@ function fog(id, path) {
|
|||
if (defs.select("#fog #" + id).size()) return;
|
||||
const fadeIn = d3.transition().duration(2000).ease(d3.easeSinInOut);
|
||||
if (defs.select("#fog path").size()) {
|
||||
defs.select("#fog").append("path").attr("d", path).attr("id", id).attr("opacity", 0).transition(fadeIn).attr("opacity", 1);
|
||||
defs
|
||||
.select("#fog")
|
||||
.append("path")
|
||||
.attr("d", path)
|
||||
.attr("id", id)
|
||||
.attr("opacity", 0)
|
||||
.transition(fadeIn)
|
||||
.attr("opacity", 1);
|
||||
} else {
|
||||
defs.select("#fog").append("path").attr("d", path).attr("id", id).attr("opacity", 1);
|
||||
defs
|
||||
.select("#fog")
|
||||
.append("path")
|
||||
.attr("d", path)
|
||||
.attr("id", id)
|
||||
.attr("opacity", 1);
|
||||
const opacity = fogging.attr("opacity");
|
||||
fogging.style("display", "block").attr("opacity", 0).transition(fadeIn).attr("opacity", opacity);
|
||||
fogging
|
||||
.style("display", "block")
|
||||
.attr("opacity", 0)
|
||||
.transition(fadeIn)
|
||||
.attr("opacity", opacity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -689,7 +818,7 @@ function unfog(id) {
|
|||
}
|
||||
|
||||
function getFileName(dataType) {
|
||||
const formatTime = time => (time < 10 ? "0" + time : time);
|
||||
const formatTime = (time) => (time < 10 ? "0" + time : time);
|
||||
const name = mapName.value;
|
||||
const type = dataType ? dataType + " " : "";
|
||||
const date = new Date();
|
||||
|
|
@ -699,7 +828,9 @@ function getFileName(dataType) {
|
|||
const hour = formatTime(date.getHours());
|
||||
const minutes = formatTime(date.getMinutes());
|
||||
const dateString = [year, month, day, hour, minutes].join("-");
|
||||
return name + " " + type + dateString;
|
||||
//return name + " " + type + dateString;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
function downloadFile(data, name, type = "text/plain") {
|
||||
|
|
@ -716,7 +847,7 @@ function uploadFile(el, callback) {
|
|||
const fileReader = new FileReader();
|
||||
fileReader.readAsText(el.files[0], "UTF-8");
|
||||
el.value = "";
|
||||
fileReader.onload = loaded => callback(loaded.target.result);
|
||||
fileReader.onload = (loaded) => callback(loaded.target.result);
|
||||
}
|
||||
|
||||
function getBBox(element) {
|
||||
|
|
@ -734,9 +865,20 @@ function highlightElement(element, zoom) {
|
|||
const enter = d3.transition().duration(1000).ease(d3.easeBounceOut);
|
||||
const exit = d3.transition().duration(500).ease(d3.easeLinear);
|
||||
|
||||
const highlight = debug.append("rect").attr("x", box.x).attr("y", box.y).attr("width", box.width).attr("height", box.height);
|
||||
const highlight = debug
|
||||
.append("rect")
|
||||
.attr("x", box.x)
|
||||
.attr("y", box.y)
|
||||
.attr("width", box.width)
|
||||
.attr("height", box.height);
|
||||
highlight.classed("highlighted", 1).attr("transform", transform);
|
||||
highlight.transition(enter).style("outline-offset", "0px").transition(exit).style("outline-color", "transparent").delay(1000).remove();
|
||||
highlight
|
||||
.transition(enter)
|
||||
.style("outline-offset", "0px")
|
||||
.transition(exit)
|
||||
.style("outline-color", "transparent")
|
||||
.delay(1000)
|
||||
.remove();
|
||||
|
||||
if (zoom) {
|
||||
const tr = parseTransform(transform);
|
||||
|
|
@ -944,7 +1086,7 @@ function selectIcon(initial, callback) {
|
|||
"🍻",
|
||||
"🍺",
|
||||
"🍲",
|
||||
"🍷"
|
||||
"🍷",
|
||||
];
|
||||
|
||||
let row = "";
|
||||
|
|
@ -955,15 +1097,16 @@ function selectIcon(initial, callback) {
|
|||
}
|
||||
}
|
||||
|
||||
input.oninput = e => callback(input.value);
|
||||
table.onclick = e => {
|
||||
input.oninput = (e) => callback(input.value);
|
||||
table.onclick = (e) => {
|
||||
if (e.target.tagName === "TD") {
|
||||
input.value = e.target.innerHTML;
|
||||
callback(input.value);
|
||||
}
|
||||
};
|
||||
table.onmouseover = e => {
|
||||
if (e.target.tagName === "TD") tip(`Click to select ${e.target.innerHTML} icon`);
|
||||
table.onmouseover = (e) => {
|
||||
if (e.target.tagName === "TD")
|
||||
tip(`Click to select ${e.target.innerHTML} icon`);
|
||||
};
|
||||
|
||||
$("#iconSelector").dialog({
|
||||
|
|
@ -977,8 +1120,8 @@ function selectIcon(initial, callback) {
|
|||
Close: function () {
|
||||
callback(initial);
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -989,7 +1132,7 @@ function confirmationDialog(options) {
|
|||
cancel = "Cancel",
|
||||
confirm = "Continue",
|
||||
onCancel,
|
||||
onConfirm
|
||||
onConfirm,
|
||||
} = options;
|
||||
|
||||
const buttons = {
|
||||
|
|
@ -1000,7 +1143,7 @@ function confirmationDialog(options) {
|
|||
[cancel]: function () {
|
||||
if (onCancel) onCancel();
|
||||
$(this).dialog("close");
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
document.getElementById("alertMessage").innerHTML = message;
|
||||
|
|
@ -1016,12 +1159,19 @@ function listen(element, event, handler) {
|
|||
// Calls the refresh functionality on all editors currently open.
|
||||
function refreshAllEditors() {
|
||||
TIME && console.time("refreshAllEditors");
|
||||
if (document.getElementById("culturesEditorRefresh").offsetParent) culturesEditorRefresh.click();
|
||||
if (document.getElementById("biomesEditorRefresh").offsetParent) biomesEditorRefresh.click();
|
||||
if (document.getElementById("diplomacyEditorRefresh").offsetParent) diplomacyEditorRefresh.click();
|
||||
if (document.getElementById("provincesEditorRefresh").offsetParent) provincesEditorRefresh.click();
|
||||
if (document.getElementById("religionsEditorRefresh").offsetParent) religionsEditorRefresh.click();
|
||||
if (document.getElementById("statesEditorRefresh").offsetParent) statesEditorRefresh.click();
|
||||
if (document.getElementById("zonesEditorRefresh").offsetParent) zonesEditorRefresh.click();
|
||||
if (document.getElementById("culturesEditorRefresh").offsetParent)
|
||||
culturesEditorRefresh.click();
|
||||
if (document.getElementById("biomesEditorRefresh").offsetParent)
|
||||
biomesEditorRefresh.click();
|
||||
if (document.getElementById("diplomacyEditorRefresh").offsetParent)
|
||||
diplomacyEditorRefresh.click();
|
||||
if (document.getElementById("provincesEditorRefresh").offsetParent)
|
||||
provincesEditorRefresh.click();
|
||||
if (document.getElementById("religionsEditorRefresh").offsetParent)
|
||||
religionsEditorRefresh.click();
|
||||
if (document.getElementById("statesEditorRefresh").offsetParent)
|
||||
statesEditorRefresh.click();
|
||||
if (document.getElementById("zonesEditorRefresh").offsetParent)
|
||||
zonesEditorRefresh.click();
|
||||
TIME && console.timeEnd("refreshAllEditors");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,18 @@
|
|||
|
||||
// fit full-screen map if window is resized
|
||||
window.addEventListener("resize", function (e) {
|
||||
if (localStorage.getItem("mapWidth") && localStorage.getItem("mapHeight")) return;
|
||||
if (localStorage.getItem("mapWidth") && localStorage.getItem("mapHeight"))
|
||||
return;
|
||||
mapWidthInput.value = window.innerWidth;
|
||||
mapHeightInput.value = window.innerHeight;
|
||||
changeMapSize();
|
||||
});
|
||||
|
||||
if (location.hostname && location.hostname !== "localhost" && location.hostname !== "127.0.0.1") {
|
||||
if (
|
||||
location.hostname &&
|
||||
location.hostname !== "localhost" &&
|
||||
location.hostname !== "127.0.0.1"
|
||||
) {
|
||||
window.onbeforeunload = () => "Are you sure you want to navigate away?";
|
||||
}
|
||||
|
||||
|
|
@ -18,15 +23,26 @@ const tooltip = document.getElementById("tooltip");
|
|||
|
||||
// show tip for non-svg elemets with data-tip
|
||||
document.getElementById("dialogs").addEventListener("mousemove", showDataTip);
|
||||
document.getElementById("optionsContainer").addEventListener("mousemove", showDataTip);
|
||||
document.getElementById("exitCustomization").addEventListener("mousemove", showDataTip);
|
||||
document
|
||||
.getElementById("optionsContainer")
|
||||
.addEventListener("mousemove", showDataTip);
|
||||
document
|
||||
.getElementById("exitCustomization")
|
||||
.addEventListener("mousemove", showDataTip);
|
||||
|
||||
function tip(tip = "Tip is undefined", main, type, time) {
|
||||
tooltip.innerHTML = tip;
|
||||
tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #5e5c5c80, #ffffff00)";
|
||||
if (type === "error") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #e11d1dcc, #ffffff00)";
|
||||
else if (type === "warn") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #be5d08cc, #ffffff00)";
|
||||
else if (type === "success") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #127912cc, #ffffff00)";
|
||||
tooltip.style.background =
|
||||
"linear-gradient(0.1turn, #ffffff00, #5e5c5c80, #ffffff00)";
|
||||
if (type === "error")
|
||||
tooltip.style.background =
|
||||
"linear-gradient(0.1turn, #ffffff00, #e11d1dcc, #ffffff00)";
|
||||
else if (type === "warn")
|
||||
tooltip.style.background =
|
||||
"linear-gradient(0.1turn, #ffffff00, #be5d08cc, #ffffff00)";
|
||||
else if (type === "success")
|
||||
tooltip.style.background =
|
||||
"linear-gradient(0.1turn, #ffffff00, #127912cc, #ffffff00)";
|
||||
|
||||
if (main) {
|
||||
tooltip.dataset.main = tip;
|
||||
|
|
@ -50,7 +66,8 @@ function clearMainTip() {
|
|||
function showDataTip(e) {
|
||||
if (!e.target) return;
|
||||
let dataTip = e.target.dataset.tip;
|
||||
if (!dataTip && e.target.parentNode.dataset.tip) dataTip = e.target.parentNode.dataset.tip;
|
||||
if (!dataTip && e.target.parentNode.dataset.tip)
|
||||
dataTip = e.target.parentNode.dataset.tip;
|
||||
if (!dataTip) return;
|
||||
//const tooltip = lang === "en" ? dataTip : translate(e.target.dataset.t || e.target.parentNode.dataset.t, dataTip);
|
||||
tip(dataTip);
|
||||
|
|
@ -59,9 +76,13 @@ function showDataTip(e) {
|
|||
function showElementLockTip(event) {
|
||||
const locked = event?.target?.classList?.contains("icon-lock");
|
||||
if (locked) {
|
||||
tip("Click to unlock the element and allow it to be changed by regeneration tools");
|
||||
tip(
|
||||
"Click to unlock the element and allow it to be changed by regeneration tools"
|
||||
);
|
||||
} else {
|
||||
tip("Click to lock the element and prevent changes to it by regeneration tools");
|
||||
tip(
|
||||
"Click to lock the element and prevent changes to it by regeneration tools"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,11 +101,14 @@ function mouseMove() {
|
|||
// show note box on hover (if any)
|
||||
function showNotes(e, i) {
|
||||
if (notesEditor.offsetParent) return;
|
||||
let id = e.target.id || e.target.parentNode.id || e.target.parentNode.parentNode.id;
|
||||
if (e.target.parentNode.parentNode.id === "burgLabels") id = "burg" + e.target.dataset.id;
|
||||
else if (e.target.parentNode.parentNode.id === "burgIcons") id = "burg" + e.target.dataset.id;
|
||||
let id =
|
||||
e.target.id || e.target.parentNode.id || e.target.parentNode.parentNode.id;
|
||||
if (e.target.parentNode.parentNode.id === "burgLabels")
|
||||
id = "burg" + e.target.dataset.id;
|
||||
else if (e.target.parentNode.parentNode.id === "burgIcons")
|
||||
id = "burg" + e.target.dataset.id;
|
||||
|
||||
const note = notes.find(note => note.id === id);
|
||||
const note = notes.find((note) => note.id === id);
|
||||
if (note !== undefined && note.legend !== "") {
|
||||
document.getElementById("notes").style.display = "block";
|
||||
document.getElementById("notesHeader").innerHTML = note.name;
|
||||
|
|
@ -96,6 +120,34 @@ function showNotes(e, i) {
|
|||
}
|
||||
}
|
||||
|
||||
function createMetaTip(point, e, i, g) {
|
||||
const biome = pack.cells.biome[i];
|
||||
const religion = pack.cells.religion[i];
|
||||
const r = pack.religions[religion];
|
||||
const religionType =
|
||||
r.type === "Cult" || r.type == "Heresy" ? r.type : r.type + " religion";
|
||||
const state = pack.cells.state[i];
|
||||
const stateCulture = pack.cells.state[i].culture;
|
||||
const stateName = pack.states[state].fullName;
|
||||
const province = pack.cells.province[i];
|
||||
const prov = province ? pack.provinces[province].fullName + ", " : "";
|
||||
const culture = pack.cells.culture[i];
|
||||
tip("Culture: " + pack.cultures[culture].name);
|
||||
let tipText =
|
||||
pack.cultures[culture].name +
|
||||
" | " +
|
||||
religionType +
|
||||
": " +
|
||||
r.name +
|
||||
" | " +
|
||||
stateName +
|
||||
" - " +
|
||||
prov +
|
||||
" | Biome: " +
|
||||
biomesData.name[biome];
|
||||
tip(tipText);
|
||||
}
|
||||
|
||||
// show viewbox tooltip if main tooltip is blank
|
||||
function showMapTooltip(point, e, i, g) {
|
||||
tip(""); // clear tip
|
||||
|
|
@ -106,12 +158,17 @@ function showMapTooltip(point, e, i, g) {
|
|||
const land = pack.cells.h[i] >= 20;
|
||||
|
||||
// specific elements
|
||||
if (group === "armies") return tip(e.target.parentNode.dataset.name + ". Click to edit");
|
||||
if (group === "armies")
|
||||
return tip(e.target.parentNode.dataset.name + ". Click to edit");
|
||||
|
||||
if (group === "emblems" && e.target.tagName === "use") {
|
||||
const parent = e.target.parentNode;
|
||||
const [g, type] =
|
||||
parent.id === "burgEmblems" ? [pack.burgs, "burg"] : parent.id === "provinceEmblems" ? [pack.provinces, "province"] : [pack.states, "state"];
|
||||
parent.id === "burgEmblems"
|
||||
? [pack.burgs, "burg"]
|
||||
: parent.id === "provinceEmblems"
|
||||
? [pack.provinces, "province"]
|
||||
: [pack.states, "state"];
|
||||
const i = +e.target.dataset.i;
|
||||
if (event.shiftKey) highlightEmblemElement(type, g[i]);
|
||||
|
||||
|
|
@ -119,16 +176,19 @@ function showMapTooltip(point, e, i, g) {
|
|||
d3.select(parent).raise();
|
||||
|
||||
const name = g[i].fullName || g[i].name;
|
||||
tip(`${name} ${type} emblem. Click to edit. Hold Shift to show associated area or place`);
|
||||
tip(
|
||||
`${name} ${type} emblem. Click to edit. Hold Shift to show associated area or place`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (group === "rivers") {
|
||||
const river = +e.target.id.slice(5);
|
||||
const r = pack.rivers.find(r => r.i === river);
|
||||
const r = pack.rivers.find((r) => r.i === river);
|
||||
const name = r ? r.name + " " + r.type : "";
|
||||
tip(name + ". Click to edit");
|
||||
if (riversOverview.offsetParent) highlightEditorLine(riversOverview, river, 5000);
|
||||
if (riversOverview.offsetParent)
|
||||
highlightEditorLine(riversOverview, river, 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -141,22 +201,31 @@ function showMapTooltip(point, e, i, g) {
|
|||
const b = pack.burgs[burg];
|
||||
const population = si(b.population * populationRate * urbanization);
|
||||
tip(`${b.name}. Population: ${population}. Click to edit`);
|
||||
if (burgsOverview.offsetParent) highlightEditorLine(burgsOverview, burg, 5000);
|
||||
if (burgsOverview.offsetParent)
|
||||
highlightEditorLine(burgsOverview, burg, 5000);
|
||||
return;
|
||||
}
|
||||
if (group === "labels") return tip("Click to edit the Label");
|
||||
|
||||
if (group === "markers") return tip("Click to edit the Marker and pin the marker note");
|
||||
if (group === "markers")
|
||||
return tip("Click to edit the Marker and pin the marker note");
|
||||
|
||||
if (group === "ruler") {
|
||||
const tag = e.target.tagName;
|
||||
const className = e.target.getAttribute("class");
|
||||
if (tag === "circle" && className === "edge") return tip("Drag to adjust. Hold Ctrl and drag to add a point. Click to remove the point");
|
||||
if (tag === "circle" && className === "control") return tip("Drag to adjust. Hold Shift and drag to keep axial direction. Click to remove the point");
|
||||
if (tag === "circle" && className === "edge")
|
||||
return tip(
|
||||
"Drag to adjust. Hold Ctrl and drag to add a point. Click to remove the point"
|
||||
);
|
||||
if (tag === "circle" && className === "control")
|
||||
return tip(
|
||||
"Drag to adjust. Hold Shift and drag to keep axial direction. Click to remove the point"
|
||||
);
|
||||
if (tag === "circle") return tip("Drag to adjust the measurer");
|
||||
if (tag === "polyline") return tip("Click on drag to add a control point");
|
||||
if (tag === "path") return tip("Drag to move the measurer");
|
||||
if (tag === "text") return tip("Drag to move, click to remove the measurer");
|
||||
if (tag === "text")
|
||||
return tip("Drag to move, click to remove the measurer");
|
||||
}
|
||||
|
||||
if (subgroup === "burgIcons") return tip("Click to edit the Burg");
|
||||
|
|
@ -175,46 +244,55 @@ function showMapTooltip(point, e, i, g) {
|
|||
if (group === "zones") {
|
||||
const zone = path[path.length - 8];
|
||||
tip(zone.dataset.description);
|
||||
if (zonesEditor.offsetParent) highlightEditorLine(zonesEditor, zone.id, 5000);
|
||||
if (zonesEditor.offsetParent)
|
||||
highlightEditorLine(zonesEditor, zone.id, 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (group === "ice") return tip("Click to edit the Ice");
|
||||
|
||||
// covering elements
|
||||
if (layerIsOn("togglePrec") && land) tip("Annual Precipitation: " + getFriendlyPrecipitation(i));
|
||||
if (layerIsOn("togglePrec") && land)
|
||||
tip("Annual Precipitation: " + getFriendlyPrecipitation(i));
|
||||
else if (layerIsOn("togglePopulation")) tip(getPopulationTip(i));
|
||||
else if (layerIsOn("toggleTemp")) tip("Temperature: " + convertTemperature(grid.cells.temp[g]));
|
||||
else if (layerIsOn("toggleTemp"))
|
||||
tip("Temperature: " + convertTemperature(grid.cells.temp[g]));
|
||||
else if (layerIsOn("toggleBiomes") && pack.cells.biome[i]) {
|
||||
const biome = pack.cells.biome[i];
|
||||
tip("Biome: " + biomesData.name[biome]);
|
||||
createMetaTip(point, e, i, g);
|
||||
if (biomesEditor.offsetParent) highlightEditorLine(biomesEditor, biome);
|
||||
} else if (layerIsOn("toggleReligions") && pack.cells.religion[i]) {
|
||||
const religion = pack.cells.religion[i];
|
||||
const r = pack.religions[religion];
|
||||
const type = r.type === "Cult" || r.type == "Heresy" ? r.type : r.type + " religion";
|
||||
tip(type + ": " + r.name);
|
||||
if (religionsEditor.offsetParent) highlightEditorLine(religionsEditor, religion);
|
||||
} else if (pack.cells.state[i] && (layerIsOn("toggleProvinces") || layerIsOn("toggleStates"))) {
|
||||
const state = pack.cells.state[i];
|
||||
const stateName = pack.states[state].fullName;
|
||||
const province = pack.cells.province[i];
|
||||
const prov = province ? pack.provinces[province].fullName + ", " : "";
|
||||
tip(prov + stateName);
|
||||
createMetaTip(point, e, i, g);
|
||||
if (religionsEditor.offsetParent)
|
||||
highlightEditorLine(religionsEditor, religion);
|
||||
} else if (
|
||||
pack.cells.state[i] &&
|
||||
(layerIsOn("toggleProvinces") || layerIsOn("toggleStates"))
|
||||
) {
|
||||
createMetaTip(point, e, i, g);
|
||||
|
||||
if (statesEditor.offsetParent) highlightEditorLine(statesEditor, state);
|
||||
if (diplomacyEditor.offsetParent) highlightEditorLine(diplomacyEditor, state);
|
||||
if (militaryOverview.offsetParent) highlightEditorLine(militaryOverview, state);
|
||||
if (provincesEditor.offsetParent) highlightEditorLine(provincesEditor, province);
|
||||
if (diplomacyEditor.offsetParent)
|
||||
highlightEditorLine(diplomacyEditor, state);
|
||||
if (militaryOverview.offsetParent)
|
||||
highlightEditorLine(militaryOverview, state);
|
||||
if (provincesEditor.offsetParent)
|
||||
highlightEditorLine(provincesEditor, province);
|
||||
} else if (layerIsOn("toggleCultures") && pack.cells.culture[i]) {
|
||||
const culture = pack.cells.culture[i];
|
||||
tip("Culture: " + pack.cultures[culture].name);
|
||||
if (culturesEditor.offsetParent) highlightEditorLine(culturesEditor, culture);
|
||||
} else if (layerIsOn("toggleHeight")) tip("Height: " + getFriendlyHeight(point));
|
||||
createMetaTip(point, e, i, g);
|
||||
if (culturesEditor.offsetParent) {
|
||||
highlightEditorLine(culturesEditor, culture);
|
||||
}
|
||||
} else if (layerIsOn("toggleHeight"))
|
||||
tip("Height: " + getFriendlyHeight(point));
|
||||
}
|
||||
|
||||
function highlightEditorLine(editor, id, timeout = 15000) {
|
||||
Array.from(editor.getElementsByClassName("states hovered")).forEach(el => el.classList.remove("hovered")); // clear all hovered
|
||||
const hovered = Array.from(editor.querySelectorAll("div")).find(el => el.dataset.id == id);
|
||||
Array.from(editor.getElementsByClassName("states hovered")).forEach((el) =>
|
||||
el.classList.remove("hovered")
|
||||
); // clear all hovered
|
||||
const hovered = Array.from(editor.querySelectorAll("div")).find(
|
||||
(el) => el.dataset.id == id
|
||||
);
|
||||
if (hovered) hovered.classList.add("hovered"); // add hovered class
|
||||
if (timeout)
|
||||
setTimeout(() => {
|
||||
|
|
@ -228,23 +306,48 @@ function updateCellInfo(point, i, g) {
|
|||
const x = (infoX.innerHTML = rn(point[0]));
|
||||
const y = (infoY.innerHTML = rn(point[1]));
|
||||
const f = cells.f[i];
|
||||
infoLat.innerHTML = toDMS(mapCoordinates.latN - (y / graphHeight) * mapCoordinates.latT, "lat");
|
||||
infoLon.innerHTML = toDMS(mapCoordinates.lonW + (x / graphWidth) * mapCoordinates.lonT, "lon");
|
||||
infoLat.innerHTML = toDMS(
|
||||
mapCoordinates.latN - (y / graphHeight) * mapCoordinates.latT,
|
||||
"lat"
|
||||
);
|
||||
infoLon.innerHTML = toDMS(
|
||||
mapCoordinates.lonW + (x / graphWidth) * mapCoordinates.lonT,
|
||||
"lon"
|
||||
);
|
||||
|
||||
infoCell.innerHTML = i;
|
||||
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
|
||||
infoArea.innerHTML = cells.area[i] ? si(cells.area[i] * distanceScaleInput.value ** 2) + unit : "n/a";
|
||||
const unit =
|
||||
areaUnit.value === "square"
|
||||
? " " + distanceUnitInput.value + "²"
|
||||
: " " + areaUnit.value;
|
||||
infoArea.innerHTML = cells.area[i]
|
||||
? si(cells.area[i] * distanceScaleInput.value ** 2) + unit
|
||||
: "n/a";
|
||||
infoEvelation.innerHTML = getElevation(pack.features[f], pack.cells.h[i]);
|
||||
infoDepth.innerHTML = getDepth(pack.features[f], pack.cells.h[i], point);
|
||||
infoTemp.innerHTML = convertTemperature(grid.cells.temp[g]);
|
||||
infoPrec.innerHTML = cells.h[i] >= 20 ? getFriendlyPrecipitation(i) : "n/a";
|
||||
infoRiver.innerHTML = cells.h[i] >= 20 && cells.r[i] ? getRiverInfo(cells.r[i]) : "no";
|
||||
infoState.innerHTML = cells.h[i] >= 20 ? (cells.state[i] ? `${pack.states[cells.state[i]].fullName} (${cells.state[i]})` : "neutral lands (0)") : "no";
|
||||
infoProvince.innerHTML = cells.province[i] ? `${pack.provinces[cells.province[i]].fullName} (${cells.province[i]})` : "no";
|
||||
infoCulture.innerHTML = cells.culture[i] ? `${pack.cultures[cells.culture[i]].name} (${cells.culture[i]})` : "no";
|
||||
infoReligion.innerHTML = cells.religion[i] ? `${pack.religions[cells.religion[i]].name} (${cells.religion[i]})` : "no";
|
||||
infoRiver.innerHTML =
|
||||
cells.h[i] >= 20 && cells.r[i] ? getRiverInfo(cells.r[i]) : "no";
|
||||
infoState.innerHTML =
|
||||
cells.h[i] >= 20
|
||||
? cells.state[i]
|
||||
? `${pack.states[cells.state[i]].fullName} (${cells.state[i]})`
|
||||
: "neutral lands (0)"
|
||||
: "no";
|
||||
infoProvince.innerHTML = cells.province[i]
|
||||
? `${pack.provinces[cells.province[i]].fullName} (${cells.province[i]})`
|
||||
: "no";
|
||||
infoCulture.innerHTML = cells.culture[i]
|
||||
? `${pack.cultures[cells.culture[i]].name} (${cells.culture[i]})`
|
||||
: "no";
|
||||
infoReligion.innerHTML = cells.religion[i]
|
||||
? `${pack.religions[cells.religion[i]].name} (${cells.religion[i]})`
|
||||
: "no";
|
||||
infoPopulation.innerHTML = getFriendlyPopulation(i);
|
||||
infoBurg.innerHTML = cells.burg[i] ? pack.burgs[cells.burg[i]].name + " (" + cells.burg[i] + ")" : "no";
|
||||
infoBurg.innerHTML = cells.burg[i]
|
||||
? pack.burgs[cells.burg[i]].name + " (" + cells.burg[i] + ")"
|
||||
: "no";
|
||||
infoFeature.innerHTML = f ? pack.features[f].group + " (" + f + ")" : "n/a";
|
||||
infoBiome.innerHTML = biomesData.name[cells.biome[i]];
|
||||
}
|
||||
|
|
@ -255,7 +358,8 @@ function toDMS(coord, c) {
|
|||
const minutesNotTruncated = (Math.abs(coord) - degrees) * 60;
|
||||
const minutes = Math.floor(minutesNotTruncated);
|
||||
const seconds = Math.floor((minutesNotTruncated - minutes) * 60);
|
||||
const cardinal = c === "lat" ? (coord >= 0 ? "N" : "S") : coord >= 0 ? "E" : "W";
|
||||
const cardinal =
|
||||
c === "lat" ? (coord >= 0 ? "N" : "S") : coord >= 0 ? "E" : "W";
|
||||
return degrees + "° " + minutes + "′ " + seconds + "″ " + cardinal;
|
||||
}
|
||||
|
||||
|
|
@ -310,13 +414,15 @@ function getFriendlyPrecipitation(i) {
|
|||
}
|
||||
|
||||
function getRiverInfo(id) {
|
||||
const r = pack.rivers.find(r => r.i == id);
|
||||
const r = pack.rivers.find((r) => r.i == id);
|
||||
return r ? `${r.name} ${r.type} (${id})` : "n/a";
|
||||
}
|
||||
|
||||
function getCellPopulation(i) {
|
||||
const rural = pack.cells.pop[i] * populationRate;
|
||||
const urban = pack.cells.burg[i] ? pack.burgs[pack.cells.burg[i]].population * populationRate * urbanization : 0;
|
||||
const urban = pack.cells.burg[i]
|
||||
? pack.burgs[pack.cells.burg[i]].population * populationRate * urbanization
|
||||
: 0;
|
||||
return [rural, urban];
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +434,9 @@ function getFriendlyPopulation(i) {
|
|||
|
||||
function getPopulationTip(i) {
|
||||
const [rural, urban] = getCellPopulation(i);
|
||||
return `Cell population: ${si(rural + urban)}; Rural: ${si(rural)}; Urban: ${si(urban)}`;
|
||||
return `Cell population: ${si(rural + urban)}; Rural: ${si(
|
||||
rural
|
||||
)}; Urban: ${si(urban)}`;
|
||||
}
|
||||
|
||||
function highlightEmblemElement(type, el) {
|
||||
|
|
@ -357,11 +465,13 @@ function highlightEmblemElement(type, el) {
|
|||
|
||||
const [x, y] = el.pole || pack.cells.p[el.center];
|
||||
const obj = type === "state" ? cells.state : cells.province;
|
||||
const borderCells = cells.i.filter(id => obj[id] === i && cells.c[id].some(n => obj[n] !== i));
|
||||
const borderCells = cells.i.filter(
|
||||
(id) => obj[id] === i && cells.c[id].some((n) => obj[n] !== i)
|
||||
);
|
||||
const data = Array.from(borderCells)
|
||||
.filter((c, i) => !(i % 2))
|
||||
.map(i => cells.p[i])
|
||||
.map(i => [i[0], i[1], Math.hypot(i[0] - x, i[1] - y)]);
|
||||
.map((i) => cells.p[i])
|
||||
.map((i) => [i[0], i[1], Math.hypot(i[0] - x, i[1] - y)]);
|
||||
|
||||
debug
|
||||
.selectAll("line")
|
||||
|
|
@ -370,19 +480,19 @@ function highlightEmblemElement(type, el) {
|
|||
.append("line")
|
||||
.attr("x1", x)
|
||||
.attr("y1", y)
|
||||
.attr("x2", d => d[0])
|
||||
.attr("y2", d => d[1])
|
||||
.attr("x2", (d) => d[0])
|
||||
.attr("y2", (d) => d[1])
|
||||
.attr("stroke", "#d0240f")
|
||||
.attr("stroke-width", 0.5)
|
||||
.attr("opacity", 0.2)
|
||||
.attr("stroke-dashoffset", d => d[2])
|
||||
.attr("stroke-dasharray", d => d[2])
|
||||
.attr("stroke-dashoffset", (d) => d[2])
|
||||
.attr("stroke-dasharray", (d) => d[2])
|
||||
.transition(animation)
|
||||
.attr("stroke-dashoffset", 0)
|
||||
.attr("opacity", 1)
|
||||
.transition(animation)
|
||||
.delay(1000)
|
||||
.attr("stroke-dashoffset", d => d[2])
|
||||
.attr("stroke-dashoffset", (d) => d[2])
|
||||
.attr("opacity", 0)
|
||||
.remove();
|
||||
}
|
||||
|
|
@ -390,8 +500,14 @@ function highlightEmblemElement(type, el) {
|
|||
// assign lock behavior
|
||||
document.querySelectorAll("[data-locked]").forEach(function (e) {
|
||||
e.addEventListener("mouseover", function (event) {
|
||||
if (this.className === "icon-lock") tip("Click to unlock the option and allow it to be randomized on new map generation");
|
||||
else tip("Click to lock the option and always use the current value on new map generation");
|
||||
if (this.className === "icon-lock")
|
||||
tip(
|
||||
"Click to unlock the option and allow it to be randomized on new map generation"
|
||||
);
|
||||
else
|
||||
tip(
|
||||
"Click to lock the option and always use the current value on new map generation"
|
||||
);
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
|
|
@ -433,7 +549,7 @@ function stored(option) {
|
|||
}
|
||||
|
||||
// assign skeaker behaviour
|
||||
Array.from(document.getElementsByClassName("speaker")).forEach(el => {
|
||||
Array.from(document.getElementsByClassName("speaker")).forEach((el) => {
|
||||
const input = el.previousElementSibling;
|
||||
el.addEventListener("click", () => speak(input.value));
|
||||
});
|
||||
|
|
@ -450,7 +566,7 @@ function speak(text) {
|
|||
|
||||
// apply drop-down menu option. If the value is not in options, add it
|
||||
function applyOption(select, id, name = id) {
|
||||
const custom = !Array.from(select.options).some(o => o.value == id);
|
||||
const custom = !Array.from(select.options).some((o) => o.value == id);
|
||||
if (custom) select.options.add(new Option(name, id));
|
||||
select.value = id;
|
||||
}
|
||||
|
|
@ -460,11 +576,20 @@ function showInfo() {
|
|||
const Discord = link("https://discordapp.com/invite/X7E84HU", "Discord");
|
||||
const Reddit = link("https://www.reddit.com/r/FantasyMapGenerator", "Reddit");
|
||||
const Patreon = link("https://www.patreon.com/azgaar", "Patreon");
|
||||
const Trello = link("https://trello.com/b/7x832DG4/fantasy-map-generator", "Trello");
|
||||
const Trello = link(
|
||||
"https://trello.com/b/7x832DG4/fantasy-map-generator",
|
||||
"Trello"
|
||||
);
|
||||
const Armoria = link("https://azgaar.github.io/Armoria", "Armoria");
|
||||
|
||||
const QuickStart = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Quick-Start-Tutorial", "Quick start tutorial");
|
||||
const QAA = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Q&A", "Q&A page");
|
||||
const QuickStart = link(
|
||||
"https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Quick-Start-Tutorial",
|
||||
"Quick start tutorial"
|
||||
);
|
||||
const QAA = link(
|
||||
"https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Q&A",
|
||||
"Q&A page"
|
||||
);
|
||||
|
||||
alertMessage.innerHTML = `
|
||||
<b>Fantasy Map Generator</b> (FMG) is an open-source application, it means the code is published an anyone can use it.
|
||||
|
|
@ -482,10 +607,22 @@ function showInfo() {
|
|||
|
||||
<b>Links:</b>
|
||||
<ul style="columns:2">
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator", "GitHub repository")}</li>
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE", "License")}</li>
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog", "Changelog")}</li>
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys", "Hotkeys")}</li>
|
||||
<li>${link(
|
||||
"https://github.com/Azgaar/Fantasy-Map-Generator",
|
||||
"GitHub repository"
|
||||
)}</li>
|
||||
<li>${link(
|
||||
"https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE",
|
||||
"License"
|
||||
)}</li>
|
||||
<li>${link(
|
||||
"https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog",
|
||||
"Changelog"
|
||||
)}</li>
|
||||
<li>${link(
|
||||
"https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys",
|
||||
"Hotkeys"
|
||||
)}</li>
|
||||
</ul>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
|
|
@ -495,8 +632,8 @@ function showInfo() {
|
|||
buttons: {
|
||||
OK: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
},
|
||||
position: {my: "center", at: "center", of: "svg"}
|
||||
},
|
||||
position: { my: "center", at: "center", of: "svg" },
|
||||
});
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue