diff --git a/modules/dynamic/editors/states-editor.js b/modules/dynamic/editors/states-editor.js
index 69d2618b..1636f0da 100644
--- a/modules/dynamic/editors/states-editor.js
+++ b/modules/dynamic/editors/states-editor.js
@@ -572,8 +572,11 @@ function stateChangeExpansionism(state, line, value) {
function toggleFog(state, cl) {
if (customization) return;
+ // Skip virtual/sky states that have no geometry
+ if (pack.states[state]?.skyRealm) return;
const path = statesBody.select("#state" + state).attr("d"),
id = "focusState" + state;
+ if (!path) return; // nothing to fog/unfog
cl.contains("inactive") ? fog(id, path) : unfog(id);
cl.toggle("inactive");
}
diff --git a/modules/routes-generator.js b/modules/routes-generator.js
index a47d044f..5ca969ac 100644
--- a/modules/routes-generator.js
+++ b/modules/routes-generator.js
@@ -74,8 +74,8 @@ window.Routes = (function () {
};
for (const burg of burgs) {
- if (burg.i && !burg.removed && !burg.flying && !burg.skyPort) {
- // Exclude flying / sky port burgs from land road/trail graphs
+ if (burg.i && !burg.removed && !burg.flying) {
+ // Exclude only flying burgs from land road/trail graphs
const {feature, capital, port} = burg;
addBurg(burgsByFeature, feature, burg);
diff --git a/modules/ui/burg-editor.js b/modules/ui/burg-editor.js
index 52a01535..ecaf3ad1 100644
--- a/modules/ui/burg-editor.js
+++ b/modules/ui/burg-editor.js
@@ -81,8 +81,10 @@ function editBurg(id) {
const altitudeRow = byId("burgAltitudeRow");
if (b.flying) {
altitudeRow.style.display = "flex";
- byId("burgAltitude").value = b.altitude ?? 1000;
- byId("burgElevation").innerHTML = `${b.altitude ?? 1000} m (sky altitude)`;
+ const defAlt = getDefaultSkyAltitude();
+ const altitude = b.altitude ?? defAlt;
+ byId("burgAltitude").value = altitude;
+ byId("burgElevation").innerHTML = `${altitude} m (sky altitude)`;
} else {
altitudeRow.style.display = "none";
byId("burgElevation").innerHTML = getHeight(pack.cells.h[b.cell]);
@@ -318,20 +320,8 @@ function editBurg(id) {
const turnOn = this.classList.contains("inactive");
if (feature === "port") togglePort(id);
else if (feature === "skyPort") {
+ // Sky port should not change land restrictions or state
burg.skyPort = +turnOn;
- // Assign to Sky State when turning on (if not a state capital)
- if (turnOn) {
- try {
- if (!burg.capital) {
- const skyId = ensureSkyState(id);
- if (burg.state !== skyId) {
- // Reassign cell ownership
- pack.cells.state[burg.cell] = skyId;
- burg.state = skyId;
- }
- }
- } catch (e) { ERROR && console.error(e); }
- }
// Regenerate routes to reflect air network
regenerateRoutes();
if (layerIsOn("toggleBurgIcons")) drawBurgIcons();
@@ -342,11 +332,15 @@ function editBurg(id) {
try {
const skyId = ensureSkyState(id);
if (burg.state !== skyId) {
- pack.cells.state[burg.cell] = skyId;
burg.state = skyId;
}
- if (burg.altitude == null) burg.altitude = 1000;
+ if (burg.altitude == null) burg.altitude = getDefaultSkyAltitude();
} catch (e) { ERROR && console.error(e); }
+ } else {
+ // Turning flying off: restore ground state ownership for the burg
+ // Do not change cells.state here; use the underlying cell state
+ const groundState = pack.cells.state[burg.cell] || 0;
+ burg.state = groundState;
}
regenerateRoutes();
if (layerIsOn("toggleBurgIcons")) drawBurgIcons();
@@ -532,9 +526,10 @@ function editBurg(id) {
cells.burg[burg.cell] = 0;
cells.burg[cell] = id;
burg.cell = cell;
-
+ if (isWater) {
+
// Set target state based on terrain and sky features
- if (isWater || burg.flying) {
+ if (isWater) {
const skyId = ensureSkyState(id);
cells.state[cell] = skyId;
burg.state = skyId;
@@ -555,6 +550,12 @@ function editBurg(id) {
if (burg.flying) byId("burgElevation").innerHTML = `${burg.altitude} m (sky altitude)`;
}
+ function getDefaultSkyAltitude() {
+ const el = byId("burgDefaultSkyAltitude");
+ const v = el ? +el.value : NaN;
+ return Number.isFinite(v) && v >= 0 ? v : 1000;
+ }
+
function editBurgLegend() {
const id = elSelected.attr("data-id");
const name = elSelected.text();
diff --git a/modules/ui/burgs-overview.js b/modules/ui/burgs-overview.js
index c33ef695..095d8271 100644
--- a/modules/ui/burgs-overview.js
+++ b/modules/ui/burgs-overview.js
@@ -293,7 +293,13 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) {
const burg = pack.burgs[id];
burg.flying = 1;
burg.skyPort = 1;
- if (burg.altitude == null) burg.altitude = 1000;
+ try {
+ const defAltEl = byId("burgDefaultSkyAltitude");
+ const defAlt = defAltEl ? +defAltEl.value : NaN;
+ burg.altitude = burg.altitude ?? (Number.isFinite(defAlt) && defAlt >= 0 ? defAlt : 1000);
+ } catch (e) {
+ burg.altitude = burg.altitude ?? 1000;
+ }
const skyStateId = ensureSkyState(id);
if (burg.state !== skyStateId) burg.state = skyStateId;
// Keep as non-sea port
diff --git a/modules/ui/diplomacy-editor.js b/modules/ui/diplomacy-editor.js
index 0f363b7b..b77860a8 100644
--- a/modules/ui/diplomacy-editor.js
+++ b/modules/ui/diplomacy-editor.js
@@ -151,6 +151,7 @@ function editDiplomacy() {
const state = +event.target.dataset.id;
if (customization || !state) return;
const d = regions.select("#state" + state).attr("d");
+ if (!d) return; // no geometry to highlight (e.g., Sky Realm)
const path = debug
.append("path")
diff --git a/modules/ui/editors.js b/modules/ui/editors.js
index b0188edc..87b64521 100644
--- a/modules/ui/editors.js
+++ b/modules/ui/editors.js
@@ -259,10 +259,22 @@ function ensureSkyState(anchorBurgId) {
lock: 1,
skyRealm: 1
};
+ // initialize minimal diplomacy for the new Sky State
+ try {
+ const diplomacy = states.map(s => (s && s.i && !s.removed ? "Neutral" : "x"));
+ diplomacy[i] = "x";
+ newState.diplomacy = diplomacy;
+ // extend existing states' diplomacy; skip state 0 (chronicle holder)
+ for (const s of states) {
+ if (s && s.i && !s.removed && Array.isArray(s.diplomacy)) s.diplomacy.push("Neutral");
+ }
+ } catch (err) {
+ // fail-safe: do nothing if diplomacy cannot be set up
+ }
+
states.push(newState);
- // Assign the burg and its cell to the Sky State
- if (cells && typeof b.cell === "number") cells.state[b.cell] = i;
+ // Do not assign the cell itself to Sky state; keep underlying ground state mapping
if (b) {
b.state = i;
b.capital = 1;
@@ -361,8 +373,8 @@ function togglePort(burg) {
function getBurgLink(burg) {
if (burg.link) return burg.link;
- // Sky burgs: force MFCG with sky-friendly parameters
- if (burg.flying || burg.skyPort) return createMfcgLink(burg, true);
+ // Sky-only: use sky generator options only for truly flying burgs
+ if (burg.flying) return createMfcgLink(burg, true);
const population = burg.population * populationRate * urbanization;
if (population >= options.villageMaxPopulation || burg.citadel || burg.walls || burg.temple || burg.shanty)
diff --git a/modules/ui/military-overview.js b/modules/ui/military-overview.js
index 46a86138..1b229fe1 100644
--- a/modules/ui/military-overview.js
+++ b/modules/ui/military-overview.js
@@ -176,6 +176,7 @@ function overviewMilitary() {
if (!layerIsOn("toggleStates")) return;
const d = regions.select("#state" + state).attr("d");
+ if (!d) return; // no geometry to highlight (e.g., Sky Realm)
const path = debug
.append("path")
diff --git a/versioning.js b/versioning.js
index 05152dd6..b618c103 100644
--- a/versioning.js
+++ b/versioning.js
@@ -22,7 +22,7 @@ if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format o
if (loadingScreenVersion) loadingScreenVersion.innerText = `v${VERSION}`;
const storedVersion = localStorage.getItem("version");
- if (compareVersions(storedVersion, VERSION, {major: true, minor: true, patch: false}).isOlder) {
+ if (compareVersions(storedVersion, VERSION, { major: true, minor: true, patch: false }).isOlder) {
setTimeout(showUpdateWindow, 6000);
}
@@ -45,14 +45,14 @@ if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format o
Styling: separate #burgIcons > #skyburgs group for sky burg icons
-
Join our Discord server and Reddit community to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.
+
Join our Discord server and Reddit community to ask questions, share maps, discuss the Generator and Worldbuilding, report bugs and propose new features.
Thanks for all supporters on Patreon!`;
$("#alert").dialog({
resizable: false,
title: "Fantasy Map Generator update",
width: "28em",
- position: {my: "center center-4em", at: "center", of: "svg"},
+ position: { my: "center center-4em", at: "center", of: "svg" },
buttons: {
"Clear cache": () => cleanupData(),
"Don't show again": function () {
@@ -100,8 +100,8 @@ function isValidVersion(versionString) {
return !isNaN(major) && !isNaN(minor) && !isNaN(patch);
}
-function compareVersions(version1, version2, options = {major: true, minor: true, patch: true}) {
- if (!isValidVersion(version1) || !isValidVersion(version2)) return {isEqual: false, isNewer: false, isOlder: false};
+function compareVersions(version1, version2, options = { major: true, minor: true, patch: true }) {
+ if (!isValidVersion(version1) || !isValidVersion(version2)) return { isEqual: false, isNewer: false, isOlder: false };
let [major1, minor1, patch1] = version1.split(".").map(Number);
let [major2, minor2, patch2] = version2.split(".").map(Number);
@@ -114,5 +114,5 @@ function compareVersions(version1, version2, options = {major: true, minor: true
const isNewer = major1 > major2 || (major1 === major2 && (minor1 > minor2 || (minor1 === minor2 && patch1 > patch2)));
const isOlder = major1 < major2 || (major1 === major2 && (minor1 < minor2 || (minor1 === minor2 && patch1 < patch2)));
- return {isEqual, isNewer, isOlder};
+ return { isEqual, isNewer, isOlder };
}