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
Replace dynamic import() with traditional script loading for TinyMCE editor
to resolve module loading issues. Adds loadScript helper function that
creates script elements and handles onload/onerror events properly.
Regiment CSV Export Enhancements:
- Add X_World (m) and Y_World (m) columns using meters per pixel conversion
- Include both current and base position world coordinates
- Rename existing coordinate columns to X_Pixel/Y_Pixel for clarity
- Add getMetersPerPixel() helper function supporting km, m, and miles units
GeoJSON Regiment Export:
- Create new saveGeoJsonRegiments() function in export.js
- Export regiments as Point features with Fantasy Map Cartesian coordinates
- Include all military unit data, state information, and position metadata
- Add regiments button to GeoJSON export UI section
This enables direct import of regiment data into QGIS using the custom
Fantasy Map Cartesian CRS with proper world coordinate positioning.
Population System Fixes:
- Fix province, culture, and religion population calculations to exclude rural population from cells without burgs
- Burgs now represent ALL population for their cells (both urban and rural components)
- Eliminate double-counting where cell populations were incorrectly added to burg populations
Export Enhancements:
- Add complete geoJSON export for burgs with all settlement properties
- Enhance routes geoJSON export to include type and feature metadata
- Add missing length and width properties to rivers geoJSON export
- Fix burg coordinate system to match CSV export format with xWorld/yWorld fields
UI Improvements:
- Add burgs export button to geoJSON export interface
- Fix vite module loading issue by adding type="module" to notes-editor.js script tag
Documentation:
- Create comprehensive QGIS Style Conversion guide with route types, burg features, and relief rendering methods
- Add WKT coordinate reference system definition for Fantasy Map Cartesian CRS
- Include rule-based styling examples and data processing workflows
This commit introduces a comprehensive tiered route generation system that replaces the basic route categories with specific route types based on medieval transportation networks:
Route System Changes:
- Major Sea Routes (majorSea): Long-distance maritime trade routes connecting capitals and major ports across water bodies, simulating Hanseatic League-style trade networks
- Regional Sea Routes (regional): Shorter routes within specific water bodies for high-traffic local maritime trade
- Royal Roads (royal): Capital-to-capital connections for diplomatic and military movement using minimum spanning tree algorithm
- Market Roads (market): Regional trade networks connecting market towns with 15-30km spacing based on medieval market day travel distances
- Local Roads (local): Village-to-market connections linking settlements to their nearest commercial centers
- Footpaths (footpath): Hamlet paths with 3-8km range for local community connections
Implementation Details:
- Removed fallback calls to legacy route generation functions to ensure clean tiered system operation
- Routes now include both 'group' (general category) and 'type' (specific tier) properties for detailed classification
- Enhanced route generation uses settlement hierarchy and geographic constraints for realistic medieval transportation patterns
- Route cost modifiers applied based on route type importance (royal and majorSea routes have priority routing)
CSV Export Enhancements:
- Added 'Type' column to routes CSV export to distinguish between route tiers
- Updated routes overview UI to display both group and type information
- Enhanced header layout to accommodate new type column
- Routes can now be analyzed by both general category and specific function
Technical Changes:
- Fixed route ID assignment conflicts between immediate and background processing phases
- Improved route data structure consistency across generation phases
- Updated routes overview display to show detailed route type information
- Enhanced CSV export function to include route type data from pack.routes
Rural population now correctly counted only from burgs with ≤100 people.
Eliminates double-counting and ensures consistent statistics across
charts and CSV exports.
- Fixed core issue where cells.pop and burg.population were both being counted
- Changed aggregation logic across all modules to use either burg OR cell population, never both
- If cell has burg: count only burg population (represents all people in that area)
- If cell has no burg: count only cells.pop (represents scattered population)
Files modified:
- modules/burgs-and-states.js: Fixed state population aggregation
- modules/ui/provinces-editor.js: Fixed province population aggregation
- modules/dynamic/editors/cultures-editor.js: Fixed culture population aggregation
- modules/dynamic/editors/religions-editor.js: Fixed religion population aggregation
- modules/ui/biomes-editor.js: Fixed biome population aggregation
- modules/ui/zones-editor.js: Fixed zone population calculations (2 locations)
- modules/military-generator.js: Redesigned military generation to use only burg populations
Military system changes:
- Removed rural military generation (all forces now come from settlements)
- Only burgs with 500+ people can maintain military forces
- Military strength based on actual burg population (2.5% mobilization rate)
Result: Population totals now consistent across all CSV exports (~2M total vs previous 40x discrepancy)
This commit introduces detailed documentation for modifying the Fantasy Map Generator's population system to create more realistic settlement sizes suitable for medieval fantasy settings.
Key features of the documentation:
- Complete analysis of current population calculation system in burgs-and-states.js
- Detailed code modifications to reduce city populations from ~250k to ~30k
- Hierarchical scaling that maintains realistic population gradients
- Military impact analysis showing proportional army size reductions
- Step-by-step implementation guide with exact line numbers
- Testing procedures and validation methods
- Troubleshooting section for common issues
- Rollback instructions for safe implementation
The proposed changes will create settlement populations of:
- Capitals: 25-35k (down from 200-300k)
- Large ports: 20-30k (down from 150-250k)
- Regional centers: 10-20k (down from 100-150k)
- Towns: 2-8k (down from 20-50k)
- Villages: 0.5-3k (down from 1-5k)
Military forces will scale proportionally, creating more historically accurate medieval army sizes where capitals field 60-120 troops instead of 500-1000.
The documentation preserves all existing functionality while providing a complete reference for population system modifications.
Major Changes:
- Enhanced burg placement system with three-tier hierarchy:
* Primary centers (capitals + large ports) connected by main roads
* Regional centers (plaza burgs) connected by secondary roads
* Local settlements connected by trails to existing network
Burg Placement Improvements (burgs-and-states.js):
- Added identifyLargePorts() function to mark coastal settlements as major population centers
- Implemented placeRegionalCenters() function for strategic plaza burg placement
- Enhanced placeTowns() with hierarchical scoring based on distance to major centers
- Updated population calculations to respect settlement hierarchy
- Modified defineBurgFeatures() to guarantee plazas for regional centers
Route Generation Overhaul (routes-generator.js):
- Created hierarchical route system eliminating overlapping routes:
* Main roads connect primary population centers (capitals + large ports)
* Secondary roads connect plaza burgs to main network and each other
* Trails connect isolated settlements to nearest existing routes
- Added filtered burg categorization to prevent duplicate connections
- Implemented intelligent pathfinding that integrates with existing routes
- Fixed getLength() function with fallback calculation for DOM timing issues
CSV Export Enhancement (routes-overview.js):
- Updated routes CSV export to include new "secondary" route type
- Added documentation for supported route types in export function
Technical Features:
- Distance-based population gradients radiating from major centers
- Urquhart graph algorithm for optimal route networks
- Integration with existing pathfinding cost system
- Proper route merging and connection tracking
- Robust error handling for route length calculations
Result:
- Realistic settlement hierarchy with proper population distribution
- Non-overlapping transportation network with clear purpose for each route type
- Radial patterns from major centers through regional hubs to local settlements
- Enhanced world-building with economically logical settlement placement
- Added X_World and Y_World columns in meters to CSV export
- Enhanced distance unit conversion with support for multiple units (km, m, mi, yd, ft, leagues)
- Renamed existing X,Y columns to X_Pixel, Y_Pixel for clarity
- World coordinates account for proper Y-axis orientation (negative for downward direction)
- Maintains backward compatibility with existing latitude/longitude columns
- Implement proper coordinate transformation from pixels to world meters
- Add comprehensive metadata to all GeoJSON exports including map settings, scale, and units
- Support multiple distance units (km, miles, yards, feet, leagues, meters)
- Calculate bounds in meters for proper geospatial reference
- Include CRS information as Fantasy Map Cartesian system
- Fix marker notes export to correctly reference note IDs
- Improve coordinate precision and consistency across all export types
The id field for geojson export was not consistent with csv exports.
Removes the prefix on routes, rivers and markers geojson, and on
markers csv, to make them all use only an integer as id.
This makes it easier to import and do joins in other software.