J. Rogers, SE Ohio
1. Executive Summary
2. Goals & Requirements
Structured Generation: Ensure complex locations are assembled logically. A "Farmstead" Blueprint should generate a farmhouse, a barn, and a field, not a random cluster of rooms.Verticality & Connectivity: Natively support multi-floor buildings and multi-level dungeons with a formal system for "Portals" (stairs, ladders) that link different map nodes.Persistence: The generated grid layouts for each level must be saved to the database (geometry_data) so they are not re-generated on every visit.Modularity & Extensibility: New building or dungeon types can be added by creating new JSON Blueprint files in a designated directory, requiring no changes to the Python generation code. These files can be easily shared.Hierarchical Integrity: The system must integrate seamlessly with our existing three-layer map hierarchy (World -> Local -> Tactical).
3. Core Concept: The Blueprint File System
data/└── blueprints/
├── buildings/
│ ├── tavern_two_story.json
│ ├── farmhouse_small.json
│ └── temple_main.json
└── dungeons/
├── crypt_standard.json
└── goblin_warren.json
4. Blueprint Schema Design
{ "id": "farmhouse_small",
"name": "Small Farmhouse",
"tags": ["residential", "rural"],
"layout": {
"grid_size": {"w": 12, "h": 10},
"floors": 2,
"room_rules": [
{ "tag": "kitchen", "floor": 1, "placement_hint": "rear", "min_size": 12 },
{ "tag": "living_area", "floor": 1, "placement_hint": "front", "min_size": 20 },
{ "tag": "bedroom", "floor": 2, "count": 2, "min_size": 9 }
],
"portals": [
{ "type": "stairs", "link": [1, 2], "placement_hint": "central" }
]
}
}
"id": "farmstead_small",
"name": "Small Farmstead",
"description": "A modest farm with a main house and outbuildings.",
"plot_size": {"w": 60, "h": 60},
"main_building": {
"blueprint_id": "farmhouse_small",
"name_template": "{owner_name}'s Farmhouse"
},
"outbuildings": [
{
"blueprint_id": "barn_simple",
"count": 1,
"placement_rules": { "min_dist_from_main": 8, "max_dist_from_main": 20 }
}
]
}
5. Generation Workflow (Code Logic)
Trigger: User Shift+Clicks a "Building" marker on the Local Map (e.g., "Miller's Farm"). The marker's metadata contains {"blueprint_id": "farmstead_small"}.Check Persistence: The generator first queries the DB for any child nodes linked to the source marker's node_id and coordinates. If they exist, it loads them. If not, it proceeds.Parse Blueprint: The generator loads farmstead_small.json. It identifies it as aCompound Blueprint because it contains a plot_size key instead of a layout key.Generate Compound Plot (Recursive Step): A primary "plot" node is created to represent the farmstead's exterior area (this could be a simple grid or even a mini-GeoController map). The generator recursively calls itself to generate the main_building by loading the farmhouse_small.json blueprint.
Generate Simple Structure (Base Step): The generator processes farmhouse_small.json. It sees "floors": 2. It creates a new node record for Floor 1 . Its parent_node_id is the Local Map's node ID.It runs a partitioning algorithm (e.g., Binary Space Partitioning) on the grid_size to create rooms satisfying the room_rules for floor: 1. It creates a second node record for Floor 2 , with the same parent_node_id.It runs the partitioning algorithm again for floor: 2.
Create Portals: The generator reads the portals array. It sees "link": [1, 2]. On the Floor 1 node (e.g., ID 101), it creates a marker of type stairs at a suitable grid location. This marker's metadata will be {"target_node_id": 102} (the ID of the Floor 2 node). On the Floor 2 node (ID 102), it creates a reciprocal stairs marker with metadata {"target_node_id": 101}. This establishes the two-way link.
Save Geometry & Return: The final grid data for each floor [[1,1,0], [0,1,0]] is saved into the geometry_data field of its corresponding node. The generator returns the ID of the primary entry point (Floor 1 of the main house).
6. Database & UI Integration
Nodes: Each floor of a building and each level of a dungeon is a separate node record. The existing parent_node_id hierarchy works perfectly for this. The type will be building_interior or dungeon_level.Markers: On the Local Map (Layer 2), a single marker represents the entire compound (the Farmstead). Inside a Tactical Map (Layer 3), markers are used for Portals (linking to other nodes) and interactive objects.
User Interaction: When creating a marker on the Local Map, if the type is "Building" or "Lair", a new dropdown will appear, populated by scanning the data/blueprints/ directory. The user selects a blueprint (e.g., "Small Farmstead"), which saves the blueprint_id to the marker's metadata. Shift+Clicking this marker now triggers the generation workflow. Shift+Clicking a "Stairs" marker inside a tactical map will trigger a transition to the target_node_id.
No comments:
Post a Comment