mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
fix: bypass issue if burg has no states assigned
This commit is contained in:
parent
182c6d558d
commit
4f4729c866
4 changed files with 102 additions and 55 deletions
|
|
@ -7821,7 +7821,7 @@
|
||||||
<script defer src="modules/relief-icons.js"></script>
|
<script defer src="modules/relief-icons.js"></script>
|
||||||
<script defer src="modules/ui/style.js"></script>
|
<script defer src="modules/ui/style.js"></script>
|
||||||
<script defer src="modules/ui/editors.js?v=080620222"></script>
|
<script defer src="modules/ui/editors.js?v=080620222"></script>
|
||||||
<script defer src="modules/ui/tools.js?v=01062022"></script>
|
<script defer src="modules/ui/tools.js?v=12062022"></script>
|
||||||
<script defer src="modules/ui/world-configurator.js?v=29052022"></script>
|
<script defer src="modules/ui/world-configurator.js?v=29052022"></script>
|
||||||
<script defer src="modules/ui/heightmap-editor.js?v=29052020"></script>
|
<script defer src="modules/ui/heightmap-editor.js?v=29052020"></script>
|
||||||
<script defer src="modules/ui/provinces-editor.js?v=29052022"></script>
|
<script defer src="modules/ui/provinces-editor.js?v=29052022"></script>
|
||||||
|
|
@ -7859,7 +7859,7 @@
|
||||||
<script defer src="libs/jquery.ui.touch-punch.min.js"></script>
|
<script defer src="libs/jquery.ui.touch-punch.min.js"></script>
|
||||||
|
|
||||||
<script defer src="modules/io/save.js?v=29052022"></script>
|
<script defer src="modules/io/save.js?v=29052022"></script>
|
||||||
<script defer src="modules/io/load.js?v=01062022"></script>
|
<script defer src="modules/io/load.js?v=12062022"></script>
|
||||||
<script defer src="modules/io/cloud.js?v=04062022"></script>
|
<script defer src="modules/io/cloud.js?v=04062022"></script>
|
||||||
<script defer src="modules/io/export.js?v=04062022"></script>
|
<script defer src="modules/io/export.js?v=04062022"></script>
|
||||||
<script defer src="modules/io/formats.js"></script>
|
<script defer src="modules/io/formats.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,7 @@ async function createSharableDropboxLink() {
|
||||||
try {
|
try {
|
||||||
url = await Cloud.providers.dropbox.getLink(mapFile);
|
url = await Cloud.providers.dropbox.getLink(mapFile);
|
||||||
} catch {
|
} catch {
|
||||||
tip("Dropbox API error. Can not create link.", true, "error", 2000);
|
return tip("Dropbox API error. Can not create link.", true, "error", 2000);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fmg = window.location.href.split("?")[0];
|
const fmg = window.location.href.split("?")[0];
|
||||||
|
|
@ -500,23 +499,28 @@ async function parseLoadedData(data) {
|
||||||
ERROR && console.error("Data Integrity Check. Invalid river", r, "is assigned to cells", invalidCells);
|
ERROR && console.error("Data Integrity Check. Invalid river", r, "is assigned to cells", invalidCells);
|
||||||
});
|
});
|
||||||
|
|
||||||
pack.burgs.forEach(b => {
|
pack.burgs.forEach(burg => {
|
||||||
if (!b.i || b.removed) return;
|
if (!burg.i || burg.removed) return;
|
||||||
if (b.port < 0) {
|
if (burg.port < 0) {
|
||||||
ERROR && console.error("Data Integrity Check. Burg", b.i, "has invalid port value", b.port);
|
ERROR && console.error("Data Integrity Check. Burg", burg.i, "has invalid port value", burg.port);
|
||||||
b.port = 0;
|
burg.port = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.cell >= cells.i.length) {
|
if (burg.cell >= cells.i.length) {
|
||||||
ERROR && console.error("Data Integrity Check. Burg", b.i, "is linked to invalid cell", b.cell);
|
ERROR && console.error("Data Integrity Check. Burg", burg.i, "is linked to invalid cell", burg.cell);
|
||||||
b.cell = findCell(b.x, b.y);
|
burg.cell = findCell(burg.x, burg.y);
|
||||||
cells.i.filter(i => cells.burg[i] === b.i).forEach(i => (cells.burg[i] = 0));
|
cells.i.filter(i => cells.burg[i] === burg.i).forEach(i => (cells.burg[i] = 0));
|
||||||
cells.burg[b.cell] = b.i;
|
cells.burg[burg.cell] = burg.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.state && !pack.states[b.state]) {
|
if (burg.state && !pack.states[burg.state]) {
|
||||||
ERROR && console.error("Data Integrity Check. Burg", b.i, "is linked to invalid state", b.state);
|
ERROR && console.error("Data Integrity Check. Burg", burg.i, "is linked to invalid state", burg.state);
|
||||||
b.state = 0;
|
burg.state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (burg.state === undefined) {
|
||||||
|
ERROR && console.error("Data Integrity Check. Burg", burg.i, "has no state data");
|
||||||
|
burg.state = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,8 @@ function regenerateStates() {
|
||||||
const statesCount = +regionsOutput.value;
|
const statesCount = +regionsOutput.value;
|
||||||
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
||||||
if (!burgs.length) return tip("There are no any burgs to generate states. Please create burgs first", false, "error");
|
if (!burgs.length) return tip("There are no any burgs to generate states. Please create burgs first", false, "error");
|
||||||
if (burgs.length < statesCount) tip(`Not enough burgs to generate ${statesCount} states. Will generate only ${burgs.length} states`, false, "warn");
|
if (burgs.length < statesCount)
|
||||||
|
tip(`Not enough burgs to generate ${statesCount} states. Will generate only ${burgs.length} states`, false, "warn");
|
||||||
|
|
||||||
// turn all old capitals into towns
|
// turn all old capitals into towns
|
||||||
burgs
|
burgs
|
||||||
|
|
@ -205,10 +206,15 @@ function regenerateStates() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const culture = capital.culture;
|
const culture = capital.culture;
|
||||||
const basename = capital.name.length < 9 && capital.cell % 5 === 0 ? capital.name : Names.getCulture(culture, 3, 6, "", 0);
|
const basename =
|
||||||
|
capital.name.length < 9 && capital.cell % 5 === 0 ? capital.name : Names.getCulture(culture, 3, 6, "", 0);
|
||||||
const name = Names.getState(basename, culture);
|
const name = Names.getState(basename, culture);
|
||||||
const nomadic = [1, 2, 3, 4].includes(pack.cells.biome[capital.cell]);
|
const nomadic = [1, 2, 3, 4].includes(pack.cells.biome[capital.cell]);
|
||||||
const type = nomadic ? "Nomadic" : pack.cultures[culture].type === "Nomadic" ? "Generic" : pack.cultures[culture].type;
|
const type = nomadic
|
||||||
|
? "Nomadic"
|
||||||
|
: pack.cultures[culture].type === "Nomadic"
|
||||||
|
? "Generic"
|
||||||
|
: pack.cultures[culture].type;
|
||||||
const expansionism = rn(Math.random() * powerInput.value + 1, 1);
|
const expansionism = rn(Math.random() * powerInput.value + 1, 1);
|
||||||
|
|
||||||
const cultureType = pack.cultures[culture].type;
|
const cultureType = pack.cultures[culture].type;
|
||||||
|
|
@ -253,57 +259,59 @@ function regenerateProvinces() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function regenerateBurgs() {
|
function regenerateBurgs() {
|
||||||
const cells = pack.cells,
|
const {cells, states} = pack;
|
||||||
states = pack.states,
|
const lockedburgs = pack.burgs.filter(b => b.lock);
|
||||||
Lockedburgs = pack.burgs.filter(b => b.lock);
|
|
||||||
rankCells();
|
rankCells();
|
||||||
|
|
||||||
cells.burg = new Uint16Array(cells.i.length);
|
cells.burg = new Uint16Array(cells.i.length);
|
||||||
const burgs = (pack.burgs = [0]); // clear burgs array
|
const burgs = (pack.burgs = [0]); // clear burgs array
|
||||||
states.filter(s => s.i).forEach(s => (s.capital = 0)); // clear state capitals
|
states.filter(s => s.i).forEach(s => (s.capital = 0)); // clear state capitals
|
||||||
pack.provinces.filter(p => p.i).forEach(p => (p.burg = 0)); // clear province capitals
|
pack.provinces.filter(p => p.i).forEach(p => (p.burg = 0)); // clear province capitals
|
||||||
const burgsTree = d3.quadtree();
|
const burgsTree = d3.quadtree();
|
||||||
|
|
||||||
|
// add locked burgs
|
||||||
|
for (let j = 0; j < lockedburgs.length; j++) {
|
||||||
|
const id = burgs.length;
|
||||||
|
const lockedBurg = lockedburgs[j];
|
||||||
|
lockedBurg.i = id;
|
||||||
|
burgs.push(lockedBurg);
|
||||||
|
|
||||||
|
burgsTree.add([lockedBurg.x, lockedBurg.y]);
|
||||||
|
cells.burg[lockedBurg.cell] = id;
|
||||||
|
|
||||||
|
if (lockedBurg.capital) {
|
||||||
|
const stateId = lockedBurg.state;
|
||||||
|
states[stateId].capital = id;
|
||||||
|
states[stateId].center = lockedBurg.cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const score = new Int16Array(cells.s.map(s => s * Math.random())); // cell score for capitals placement
|
const score = new Int16Array(cells.s.map(s => s * Math.random())); // cell score for capitals placement
|
||||||
const sorted = cells.i.filter(i => score[i] > 0 && cells.culture[i]).sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes
|
const sorted = cells.i.filter(i => score[i] > 0 && cells.culture[i]).sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes
|
||||||
const burgsCount =
|
const burgsCount =
|
||||||
manorsInput.value == 1000 ? rn(sorted.length / 5 / (grid.points.length / 10000) ** 0.8) + states.length : +manorsInput.value + states.length;
|
manorsInput.value === "1000"
|
||||||
|
? rn(sorted.length / 5 / (grid.points.length / 10000) ** 0.8) + states.length
|
||||||
|
: +manorsInput.value + states.length;
|
||||||
const spacing = (graphWidth + graphHeight) / 150 / (burgsCount ** 0.7 / 66); // base min distance between towns
|
const spacing = (graphWidth + graphHeight) / 150 / (burgsCount ** 0.7 / 66); // base min distance between towns
|
||||||
|
|
||||||
//clear locked list since ids will change
|
|
||||||
//burglock.selectAll("text").remove();
|
|
||||||
for (let j = 0; j < Lockedburgs.length; j++) {
|
|
||||||
const id = burgs.length;
|
|
||||||
const oldBurg = Lockedburgs[j];
|
|
||||||
oldBurg.i = id;
|
|
||||||
burgs.push(oldBurg);
|
|
||||||
burgsTree.add([oldBurg.x, oldBurg.y]);
|
|
||||||
cells.burg[oldBurg.cell] = id;
|
|
||||||
if (oldBurg.capital) {
|
|
||||||
states[oldBurg.state].capital = id;
|
|
||||||
states[oldBurg.state].center = oldBurg.cell;
|
|
||||||
}
|
|
||||||
//burglock.append("text").attr("data-id", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < sorted.length && burgs.length < burgsCount; i++) {
|
for (let i = 0; i < sorted.length && burgs.length < burgsCount; i++) {
|
||||||
const id = burgs.length;
|
const id = burgs.length;
|
||||||
const cell = sorted[i];
|
const cell = sorted[i];
|
||||||
const x = cells.p[cell][0],
|
const [x, y] = cells.p[cell];
|
||||||
y = cells.p[cell][1];
|
|
||||||
|
|
||||||
const s = spacing * gauss(1, 0.3, 0.2, 2, 2); // randomize to make the placement not uniform
|
const s = spacing * gauss(1, 0.3, 0.2, 2, 2); // randomize to make the placement not uniform
|
||||||
if (burgsTree.find(x, y, s) !== undefined) continue; // to close to existing burg
|
if (burgsTree.find(x, y, s) !== undefined) continue; // to close to existing burg
|
||||||
|
|
||||||
const state = cells.state[cell];
|
const stateId = cells.state[cell];
|
||||||
const capital = state && !states[state].capital; // if state doesn't have capital, make this burg a capital, no capital for neutral lands
|
const capital = stateId && !states[stateId].capital; // if state doesn't have capital, make this burg a capital, no capital for neutral lands
|
||||||
if (capital) {
|
if (capital) {
|
||||||
states[state].capital = id;
|
states[stateId].capital = id;
|
||||||
states[state].center = cell;
|
states[stateId].center = cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
const culture = cells.culture[cell];
|
const culture = cells.culture[cell];
|
||||||
const name = Names.getCulture(culture);
|
const name = Names.getCulture(culture);
|
||||||
burgs.push({cell, x, y, state, i: id, culture, name, capital, feature: cells.f[cell]});
|
burgs.push({cell, x, y, state: stateId, i: id, culture, name, capital, feature: cells.f[cell]});
|
||||||
burgsTree.add([x, y]);
|
burgsTree.add([x, y]);
|
||||||
cells.burg[cell] = id;
|
cells.burg[cell] = id;
|
||||||
}
|
}
|
||||||
|
|
@ -321,8 +329,9 @@ function regenerateBurgs() {
|
||||||
});
|
});
|
||||||
|
|
||||||
pack.features.forEach(f => {
|
pack.features.forEach(f => {
|
||||||
if (f.port) f.port = 0;
|
if (f.port) f.port = 0; // reset features ports counter
|
||||||
}); // reset features ports counter
|
});
|
||||||
|
|
||||||
BurgsAndStates.specifyBurgs();
|
BurgsAndStates.specifyBurgs();
|
||||||
BurgsAndStates.defineBurgFeatures();
|
BurgsAndStates.defineBurgFeatures();
|
||||||
BurgsAndStates.drawBurgs();
|
BurgsAndStates.drawBurgs();
|
||||||
|
|
@ -425,7 +434,10 @@ function regenerateMarkers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function regenerateZones(event) {
|
function regenerateZones(event) {
|
||||||
if (isCtrlClick(event)) prompt("Please provide zones number multiplier", {default: 1, step: 0.01, min: 0, max: 100}, v => addNumberOfZones(v));
|
if (isCtrlClick(event))
|
||||||
|
prompt("Please provide zones number multiplier", {default: 1, step: 0.01, min: 0, max: 100}, v =>
|
||||||
|
addNumberOfZones(v)
|
||||||
|
);
|
||||||
else addNumberOfZones(gauss(1, 0.5, 0.6, 5, 2));
|
else addNumberOfZones(gauss(1, 0.5, 0.6, 5, 2));
|
||||||
|
|
||||||
function addNumberOfZones(number) {
|
function addNumberOfZones(number) {
|
||||||
|
|
@ -542,7 +554,18 @@ function addRiverOnClick() {
|
||||||
if (cells.h[i] < 20) return tip("Cannot create river in water cell", false, "error");
|
if (cells.h[i] < 20) return tip("Cannot create river in water cell", false, "error");
|
||||||
if (cells.b[i]) return;
|
if (cells.b[i]) return;
|
||||||
|
|
||||||
const {alterHeights, resolveDepressions, addMeandering, getRiverPath, getBasin, getName, getType, getWidth, getOffset, getApproximateLength} = Rivers;
|
const {
|
||||||
|
alterHeights,
|
||||||
|
resolveDepressions,
|
||||||
|
addMeandering,
|
||||||
|
getRiverPath,
|
||||||
|
getBasin,
|
||||||
|
getName,
|
||||||
|
getType,
|
||||||
|
getWidth,
|
||||||
|
getOffset,
|
||||||
|
getApproximateLength
|
||||||
|
} = Rivers;
|
||||||
const riverCells = [];
|
const riverCells = [];
|
||||||
let riverId = rivers.length ? last(rivers).i + 1 : 1;
|
let riverId = rivers.length ? last(rivers).i + 1 : 1;
|
||||||
let parent = riverId;
|
let parent = riverId;
|
||||||
|
|
@ -623,7 +646,8 @@ function addRiverOnClick() {
|
||||||
const mouth = riverCells[riverCells.length - 2];
|
const mouth = riverCells[riverCells.length - 2];
|
||||||
|
|
||||||
const defaultWidthFactor = rn(1 / (pointsInput.dataset.cells / 10000) ** 0.25, 2);
|
const defaultWidthFactor = rn(1 / (pointsInput.dataset.cells / 10000) ** 0.25, 2);
|
||||||
const widthFactor = river?.widthFactor || (!parent || parent === riverId ? defaultWidthFactor * 1.2 : defaultWidthFactor);
|
const widthFactor =
|
||||||
|
river?.widthFactor || (!parent || parent === riverId ? defaultWidthFactor * 1.2 : defaultWidthFactor);
|
||||||
const meanderedPoints = addMeandering(riverCells);
|
const meanderedPoints = addMeandering(riverCells);
|
||||||
|
|
||||||
const discharge = cells.fl[mouth]; // m3 in second
|
const discharge = cells.fl[mouth]; // m3 in second
|
||||||
|
|
@ -641,7 +665,21 @@ function addRiverOnClick() {
|
||||||
const name = getName(mouth);
|
const name = getName(mouth);
|
||||||
const type = getType({i: riverId, length, parent});
|
const type = getType({i: riverId, length, parent});
|
||||||
|
|
||||||
rivers.push({i: riverId, source, mouth, discharge, length, width, widthFactor, sourceWidth: 0, parent, cells: riverCells, basin, name, type});
|
rivers.push({
|
||||||
|
i: riverId,
|
||||||
|
source,
|
||||||
|
mouth,
|
||||||
|
discharge,
|
||||||
|
length,
|
||||||
|
width,
|
||||||
|
widthFactor,
|
||||||
|
sourceWidth: 0,
|
||||||
|
parent,
|
||||||
|
cells: riverCells,
|
||||||
|
basin,
|
||||||
|
name,
|
||||||
|
type
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// render river
|
// render river
|
||||||
|
|
@ -678,7 +716,12 @@ function addRouteOnClick() {
|
||||||
unpressClickToAddButton();
|
unpressClickToAddButton();
|
||||||
const point = d3.mouse(this);
|
const point = d3.mouse(this);
|
||||||
const id = getNextId("route");
|
const id = getNextId("route");
|
||||||
elSelected = routes.select("g").append("path").attr("id", id).attr("data-new", 1).attr("d", `M${point[0]},${point[1]}`);
|
elSelected = routes
|
||||||
|
.select("g")
|
||||||
|
.append("path")
|
||||||
|
.attr("id", id)
|
||||||
|
.attr("data-new", 1)
|
||||||
|
.attr("d", `M${point[0]},${point[1]}`);
|
||||||
editRoute(true);
|
editRoute(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
// version and caching control
|
// version and caching control
|
||||||
|
|
||||||
const version = "1.86.04"; // generator version, update each time
|
const version = "1.86.05"; // generator version, update each time
|
||||||
|
|
||||||
{
|
{
|
||||||
document.title += " v" + version;
|
document.title += " v" + version;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue