mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-16 17:31:24 +01:00
fix: sky port behavior, default sky altitude, Sky Realm robustness, and unfly state restore
Summary Ground burgs with sky ports keep land capabilities and land routes. Only truly flying burgs join the Sky Realm; turning off “flying” restores the ground state. Replace magic altitude 1000 with a DOM-configurable default. Guard state hover/pin logic for geometry-less Sky Realm to prevent console errors. Watabou link uses sky settings only for flying burgs. Details Land routing with sky ports: Change: include sky ports in land road/trail networks; exclude only flying burgs. Why: sky ports should not impose flying/land restrictions on a ground burg. File: modules/routes-generator.js Sky port toggle does not move state: Change: toggling skyPort no longer assigns the burg’s state to the Sky Realm or reassigns cell ownership. Why: sky port ≠ flying city; it’s just air connectivity. File: modules/ui/burg-editor.js Flying toggle and state restore: Change: enabling “flying” assigns the burg to the Sky Realm but does not overwrite the cell’s ground state; disabling “flying” restores the burg’s state to the underlying ground state (pack.cells.state[burg.cell]). Change: when relocating, assign Sky Realm only if the burg is placed over water; ground placements keep ground state. Why: fixes bug where reverting to ground left burg in Sky Realm and preserves ground sovereignty. File: modules/ui/burg-editor.js Default sky altitude via DOM (no more magic 1000): Change: add hidden input #burgDefaultSkyAltitude (default 1000 m) and read it everywhere altitude is defaulted (editor and “add burg on water” flow). Why: centralizes default, documents units, and makes it configurable without touching code. Files: index.html, modules/ui/burg-editor.js, modules/ui/burgs-overview.js Sky State creation robustness: Change: initialize a neutral diplomacy row for the new Sky State and extend existing states’ diplomacy arrays. Change: do not forcibly set the anchor cell ownership to Sky state when creating the Sky Realm. Why: prevents UI/editor crashes that assume diplomacy is rectangular; avoids accidental land transfer to Sky Realm. File: modules/ui/editors.js State hover/pin guards for Sky Realm: Change: skip fog/hover/highlight when the target state has no geometry (e.g., Sky Realm) or the path is missing. Why: fixes console errors in State hover and Pin feature. Files: modules/dynamic/editors/states-editor.js, modules/ui/diplomacy-editor.js, modules/ui/military-overview.js Watabou integration: Change: only treat burgs as “sky” for city links when flying is true (not when only skyPort is set). Why: ground burgs with sky ports should still have gates/roads/hubs/shanty, etc. File: modules/ui/editors.js User-visible Effects Ground cities can have sea port + sky port + roads/trails simultaneously. Toggling flying on shows altitude row; default altitude is read from the DOM. Toggling flying off restores the burg to its ground state affiliation. No more console errors when interacting with state hover/pin around the Sky Realm. Potential Impacts Land route generation may produce additional roads because sky-ported (but ground) burgs are now included. Diplomacy arrays gain a neutral column for the Sky Realm when first created (non-breaking, UI-aligned). Test Plan Set sky port on a ground burg: verify roads/trails remain; sea port and other features unaffected. Toggle flying on: burg state switches to Sky Realm; cell remains with ground state; altitude defaults from #burgDefaultSkyAltitude; air routes generate. Toggle flying off: burg state returns to the ground state; altitude row hides; routes regenerate. Hover/fog/pin states with the editors open: no errors with Sky Realm selected or hovered. Open Watabou (city generator) links: Ground + sky port: uses ground settings (gates/roads/hubs/shanty allowed). Flying: uses sky settings (no farms/gates/hub etc. as appropriate). Files Changed modules/routes-generator.js modules/ui/burg-editor.js modules/ui/burgs-overview.js modules/ui/editors.js modules/dynamic/editors/states-editor.js modules/ui/diplomacy-editor.js modules/ui/military-overview.js index.html
This commit is contained in:
parent
7292c73d10
commit
c4663e7b9b
9 changed files with 58 additions and 32 deletions
|
|
@ -3413,6 +3413,8 @@
|
|||
<div class="label">Altitude:</div>
|
||||
<input id="burgAltitude" type="number" min="0" step="50" style="width: 9em" /> m
|
||||
</div>
|
||||
<!-- Hidden default for sky altitude (meters) -->
|
||||
<input id="burgDefaultSkyAltitude" type="number" value="1000" style="display: none" />
|
||||
|
||||
<div data-tip="Burg average yearly temperature" style="display: flex; justify-content: space-between">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
|||
<li>Styling: separate <code>#burgIcons > #skyburgs</code> group for sky burg icons</li>
|
||||
</ul>
|
||||
|
||||
<p>Join our <a href="${discord}" target="_blank">Discord server</a> and <a href="${reddit}" target="_blank">Reddit community</a> to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.</p>
|
||||
<p>Join our <a href="${discord}" target="_blank">Discord server</a> and <a href="${reddit}" target="_blank">Reddit community</a> to ask questions, share maps, discuss the Generator and Worldbuilding, report bugs and propose new features.</p>
|
||||
<span><i>Thanks for all supporters on <a href="${patreon}" target="_blank">Patreon</a>!</i></span>`;
|
||||
|
||||
$("#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 };
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue