Add Ground Zero biome resources
This commit is contained in:
@@ -426,7 +426,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
|||||||
- [x] Verify neighboring tile edge coordinates against the registry before multi-tile stitching.
|
- [x] Verify neighboring tile edge coordinates against the registry before multi-tile stitching.
|
||||||
- [x] Add foliage pass.
|
- [x] Add foliage pass.
|
||||||
- [~] Add resource nodes.
|
- [~] Add resource nodes.
|
||||||
- [ ] Add biome-appropriate natural resources based on Ground Zero.
|
- [x] Add biome-appropriate natural resources based on Ground Zero.
|
||||||
- [ ] Add water source.
|
- [ ] Add water source.
|
||||||
- [ ] Add weather exposure zones if needed.
|
- [ ] Add weather exposure zones if needed.
|
||||||
- [ ] Add landmark or ruin placeholder.
|
- [ ] Add landmark or ruin placeholder.
|
||||||
@@ -1402,4 +1402,4 @@ Next version .01 priorities:
|
|||||||
|
|
||||||
Immediate next item:
|
Immediate next item:
|
||||||
|
|
||||||
- [ ] Add biome-appropriate natural resources based on Ground Zero.
|
- [ ] Add water source.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,39 @@
|
|||||||
|
# Ground Zero Biome Resource Pass
|
||||||
|
|
||||||
|
The Ground Zero map now has a first pass of biome-appropriate natural resources
|
||||||
|
based on the selected tile's coastal California scrub/woodland biome, terrain
|
||||||
|
height, slope, and drainage-candidate analysis.
|
||||||
|
|
||||||
|
## Resource Types
|
||||||
|
|
||||||
|
- Wood: scrub/woodland and hillside patches.
|
||||||
|
- Fiber: grassland, scrub, and drainage-candidate areas.
|
||||||
|
- Stone: slope, exposed terrain, and valley-edge areas.
|
||||||
|
|
||||||
|
Freshwater remains separate because the water-source roadmap item follows this
|
||||||
|
pass and should be implemented as its own gameplay actor/system.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
- Added `BP_StoneResourceNode` through `Scripts/setup_playable_blueprints.py`.
|
||||||
|
- Updated `Scripts/setup_ground_zero_demo_map.py` to place deterministic Ground
|
||||||
|
Zero resource nodes.
|
||||||
|
- Added `Scripts/verify_ground_zero_resources.py` to validate node presence,
|
||||||
|
yield item IDs, and remaining harvests.
|
||||||
|
|
||||||
|
## Counts
|
||||||
|
|
||||||
|
The map now contains:
|
||||||
|
|
||||||
|
- Wood nodes: `4`
|
||||||
|
- Fiber nodes: `5`
|
||||||
|
- Stone nodes: `4`
|
||||||
|
|
||||||
|
These counts include the original demo wood and fiber nodes so the first player
|
||||||
|
path remains intact while expanding the broader tile resource layer.
|
||||||
|
|
||||||
|
## Follow-Up
|
||||||
|
|
||||||
|
Future passes should replace the prototype meshes with real coastal scrub,
|
||||||
|
grass, rock, and woodland assets, then drive density from land-cover and
|
||||||
|
hydrography data instead of fixed authored points.
|
||||||
@@ -98,6 +98,87 @@ DEMO_ACTORS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
BIOME_RESOURCE_ACTORS = [
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Wood_CoastalScrub_01",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_WoodResourceNode",
|
||||||
|
"location_xy": unreal.Vector(-28600.0, 7400.0, 0.0),
|
||||||
|
"z_offset": 70.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 18.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Wood_CoastalScrub_02",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_WoodResourceNode",
|
||||||
|
"location_xy": unreal.Vector(-5400.0, 21400.0, 0.0),
|
||||||
|
"z_offset": 70.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, -42.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Wood_Hillside_03",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_WoodResourceNode",
|
||||||
|
"location_xy": unreal.Vector(18400.0, 32200.0, 0.0),
|
||||||
|
"z_offset": 70.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 86.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Fiber_Grassland_01",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_FiberResourceNode",
|
||||||
|
"location_xy": unreal.Vector(-33400.0, -16200.0, 0.0),
|
||||||
|
"z_offset": 65.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 6.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Fiber_Grassland_02",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_FiberResourceNode",
|
||||||
|
"location_xy": unreal.Vector(8200.0, -18200.0, 0.0),
|
||||||
|
"z_offset": 65.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, -28.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Fiber_Scrub_03",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_FiberResourceNode",
|
||||||
|
"location_xy": unreal.Vector(29200.0, -4200.0, 0.0),
|
||||||
|
"z_offset": 65.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 54.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Fiber_DrainageCandidate_04",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_FiberResourceNode",
|
||||||
|
"location_xy": unreal.Vector(-6200.0, 9200.0, 0.0),
|
||||||
|
"z_offset": 65.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 114.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Stone_Slope_01",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_StoneResourceNode",
|
||||||
|
"location_xy": unreal.Vector(22600.0, 17600.0, 0.0),
|
||||||
|
"z_offset": 45.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 12.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Stone_Slope_02",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_StoneResourceNode",
|
||||||
|
"location_xy": unreal.Vector(37600.0, 28600.0, 0.0),
|
||||||
|
"z_offset": 45.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, -36.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Stone_ExposedTerrain_03",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_StoneResourceNode",
|
||||||
|
"location_xy": unreal.Vector(11800.0, 38200.0, 0.0),
|
||||||
|
"z_offset": 45.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 71.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_Stone_ValleyEdge_04",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_StoneResourceNode",
|
||||||
|
"location_xy": unreal.Vector(-24800.0, 28600.0, 0.0),
|
||||||
|
"z_offset": 45.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 133.0, 0.0),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
FOLIAGE_ZONES = {
|
FOLIAGE_ZONES = {
|
||||||
"trees": {
|
"trees": {
|
||||||
"count": 42,
|
"count": 42,
|
||||||
@@ -313,11 +394,14 @@ def main():
|
|||||||
raise RuntimeError(f"Could not load map: {MAP_PATH}")
|
raise RuntimeError(f"Could not load map: {MAP_PATH}")
|
||||||
|
|
||||||
labels = {spec["label"] for spec in DEMO_ACTORS}
|
labels = {spec["label"] for spec in DEMO_ACTORS}
|
||||||
|
labels.update(spec["label"] for spec in BIOME_RESOURCE_ACTORS)
|
||||||
labels.add(FOLIAGE_LABEL)
|
labels.add(FOLIAGE_LABEL)
|
||||||
remove_existing_demo_actors(labels)
|
remove_existing_demo_actors(labels)
|
||||||
|
|
||||||
height_values = load_heightmap()
|
height_values = load_heightmap()
|
||||||
spawn_foliage_actor(height_values)
|
spawn_foliage_actor(height_values)
|
||||||
|
for spec in BIOME_RESOURCE_ACTORS:
|
||||||
|
spawn_demo_actor(spec, height_values)
|
||||||
for spec in DEMO_ACTORS:
|
for spec in DEMO_ACTORS:
|
||||||
spawn_demo_actor(spec, height_values)
|
spawn_demo_actor(spec, height_values)
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ WILDLIFE_FOLDER = f"{BLUEPRINT_ROOT}/Wildlife"
|
|||||||
|
|
||||||
WOOD_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Wood"
|
WOOD_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Wood"
|
||||||
FIBER_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Fiber"
|
FIBER_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Fiber"
|
||||||
|
STONE_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Stone"
|
||||||
|
|
||||||
MESH_CUBE_PATH = "/Game/LevelPrototyping/Meshes/SM_Cube"
|
MESH_CUBE_PATH = "/Game/LevelPrototyping/Meshes/SM_Cube"
|
||||||
MESH_CYLINDER_PATH = "/Game/LevelPrototyping/Meshes/SM_Cylinder"
|
MESH_CYLINDER_PATH = "/Game/LevelPrototyping/Meshes/SM_Cylinder"
|
||||||
@@ -37,6 +38,18 @@ BLUEPRINTS = [
|
|||||||
"mesh": MESH_CYLINDER_PATH,
|
"mesh": MESH_CYLINDER_PATH,
|
||||||
"scale": unreal.Vector(0.8, 0.8, 1.0),
|
"scale": unreal.Vector(0.8, 0.8, 1.0),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"asset": "BP_StoneResourceNode",
|
||||||
|
"folder": RESOURCE_FOLDER,
|
||||||
|
"parent": unreal.AgrarianResourceNode,
|
||||||
|
"defaults": {
|
||||||
|
"yield_item_definition": STONE_ITEM_PATH,
|
||||||
|
"remaining_harvests": 12,
|
||||||
|
"quantity_per_harvest": 2,
|
||||||
|
},
|
||||||
|
"mesh": MESH_CUBE_PATH,
|
||||||
|
"scale": unreal.Vector(0.9, 0.75, 0.45),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"asset": "BP_Campfire",
|
"asset": "BP_Campfire",
|
||||||
"folder": STRUCTURE_FOLDER,
|
"folder": STRUCTURE_FOLDER,
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import unreal
|
||||||
|
|
||||||
|
|
||||||
|
MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test"
|
||||||
|
|
||||||
|
EXPECTED_RESOURCE_LABELS = {
|
||||||
|
"wood": [
|
||||||
|
"AGR_DemoWoodResource_01",
|
||||||
|
"AGR_GZ_Wood_CoastalScrub_01",
|
||||||
|
"AGR_GZ_Wood_CoastalScrub_02",
|
||||||
|
"AGR_GZ_Wood_Hillside_03",
|
||||||
|
],
|
||||||
|
"fiber": [
|
||||||
|
"AGR_DemoFiberResource_01",
|
||||||
|
"AGR_GZ_Fiber_Grassland_01",
|
||||||
|
"AGR_GZ_Fiber_Grassland_02",
|
||||||
|
"AGR_GZ_Fiber_Scrub_03",
|
||||||
|
"AGR_GZ_Fiber_DrainageCandidate_04",
|
||||||
|
],
|
||||||
|
"stone": [
|
||||||
|
"AGR_GZ_Stone_Slope_01",
|
||||||
|
"AGR_GZ_Stone_Slope_02",
|
||||||
|
"AGR_GZ_Stone_ExposedTerrain_03",
|
||||||
|
"AGR_GZ_Stone_ValleyEdge_04",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_actor_label(actor):
|
||||||
|
try:
|
||||||
|
return actor.get_actor_label()
|
||||||
|
except Exception:
|
||||||
|
return actor.get_name()
|
||||||
|
|
||||||
|
|
||||||
|
def resource_item_id(actor):
|
||||||
|
item_asset = actor.get_editor_property("yield_item_definition")
|
||||||
|
definition = item_asset.get_editor_property("definition") if item_asset else None
|
||||||
|
return str(definition.get_editor_property("item_id")) if definition else ""
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not unreal.EditorLevelLibrary.load_level(MAP_PATH):
|
||||||
|
raise RuntimeError(f"Could not load map: {MAP_PATH}")
|
||||||
|
|
||||||
|
actors_by_label = {get_actor_label(actor): actor for actor in unreal.EditorLevelLibrary.get_all_level_actors()}
|
||||||
|
failures = []
|
||||||
|
|
||||||
|
for expected_item_id, labels in EXPECTED_RESOURCE_LABELS.items():
|
||||||
|
for label in labels:
|
||||||
|
actor = actors_by_label.get(label)
|
||||||
|
if not actor:
|
||||||
|
failures.append(f"{label} missing")
|
||||||
|
continue
|
||||||
|
|
||||||
|
actual_item_id = resource_item_id(actor)
|
||||||
|
if actual_item_id != expected_item_id:
|
||||||
|
failures.append(f"{label} expected {expected_item_id}, got {actual_item_id}")
|
||||||
|
|
||||||
|
if actor.get_editor_property("remaining_harvests") <= 0:
|
||||||
|
failures.append(f"{label} has no remaining harvests")
|
||||||
|
|
||||||
|
if failures:
|
||||||
|
raise RuntimeError("Ground Zero resource verification failed: " + "; ".join(failures))
|
||||||
|
|
||||||
|
unreal.log(
|
||||||
|
"Ground Zero resource verification complete: "
|
||||||
|
f"{len(EXPECTED_RESOURCE_LABELS['wood'])} wood, "
|
||||||
|
f"{len(EXPECTED_RESOURCE_LABELS['fiber'])} fiber, "
|
||||||
|
f"{len(EXPECTED_RESOURCE_LABELS['stone'])} stone nodes."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -16,6 +16,13 @@ EXPECTED = {
|
|||||||
},
|
},
|
||||||
"yield_item_id": "fiber",
|
"yield_item_id": "fiber",
|
||||||
},
|
},
|
||||||
|
"/Game/Agrarian/Blueprints/Resources/BP_StoneResourceNode": {
|
||||||
|
"properties": {
|
||||||
|
"remaining_harvests": 12,
|
||||||
|
"quantity_per_harvest": 2,
|
||||||
|
},
|
||||||
|
"yield_item_id": "stone",
|
||||||
|
},
|
||||||
"/Game/Agrarian/Blueprints/Structures/BP_Campfire": {
|
"/Game/Agrarian/Blueprints/Structures/BP_Campfire": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"fuel_seconds": 180.0,
|
"fuel_seconds": 180.0,
|
||||||
|
|||||||
Reference in New Issue
Block a user