Add Ground Zero ruin landmark placeholder

This commit is contained in:
2026-05-16 09:44:20 -07:00
parent 8b0b5fff92
commit 56f8ef9bae
5 changed files with 163 additions and 4 deletions
+1 -1
View File
@@ -460,7 +460,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
- [x] Add first-pass environment asset variation so trees, bushes, grass, resource nodes, and water do not read as repeated placeholders. Added repeatable labeled variation actors for tree canopies/trunks, rounded bushes, grass mats, rock slabs, and a freshwater surface using multiple prototype mesh silhouettes, unique scales, rotations, and Ground Zero material families; extended the natural-environment verifier to require variation coverage.
- [x] Replace `LevelPrototyping` cube/cylinder mesh dependencies in Agrarian setup scripts and prototype Blueprints with Agrarian-native placeholder environment meshes. Added repeatable Agrarian-native placeholder mesh assets under `/Game/Agrarian/Environment/PlaceholderMeshes`, updated playable Blueprint and Ground Zero setup scripts to use those native paths, regenerated affected Blueprints/map content, and added verification that Blueprint, foliage, and variation meshes no longer point at template mesh paths.
- [x] Add weather exposure zones if needed. Added native `AAgrarianWeatherExposureZone` volumes with exposure multipliers and temperature offsets, wired survival to apply the strongest overlapping zone after shelter protection, exposed current zone effects on the dev HUD, placed three Ground Zero zones for ridge, coastal-wind, and drainage cooling cases, and added verification for zone placement plus docs.
- [ ] Add landmark or ruin placeholder.
- [x] Add landmark or ruin placeholder. Added a repeatable five-piece Ground Zero ruin cluster using Agrarian-native placeholder stone meshes for a visible MVP point of interest, regenerated the map, documented the pass, and added verification for actor count, native mesh paths, stone material assignment, distinct placement, and roadmap/doc coverage.
- [ ] Add spawn area with validation that the player spawns above sea level, above terrain by a safe offset, away from water, away from steep slopes, away from dense resource clusters, and with a known safe fallback coordinate.
- [ ] Add performance profiling markers.
- [ ] Add navigation support for wildlife.
Binary file not shown.
@@ -14,6 +14,9 @@ space.
- First-pass asset variation actors add additional tree canopies/trunks, rounded
bushes, grass mats, rock slabs, and a visible freshwater surface with varied
meshes, scales, rotations, and material families.
- A first-pass ruin landmark placeholder gives the Ground Zero demo a visible
point of interest using five native placeholder stone pieces: foundation,
wall fragments, a cairn marker, and a threshold.
- The foliage and asset variation layers now use Agrarian-native placeholder
mesh assets from `/Game/Agrarian/Environment/PlaceholderMeshes` instead of
direct `LevelPrototyping` mesh references.
@@ -49,7 +52,9 @@ profiles, and coverage across tree, bush, grass, rock, and water visual
families. `Scripts/verify_native_placeholder_meshes.py` checks that playable
resource/structure/water Blueprints, foliage components, and environment
variation actors use Agrarian-native placeholder meshes rather than template
mesh paths.
mesh paths. `Scripts/verify_ground_zero_landmark_placeholder.py` checks the
ruin landmark placeholder actor count, native mesh paths, stone material
assignment, distinct placement, and roadmap/doc coverage.
## Follow-Up
+51
View File
@@ -390,6 +390,54 @@ ENVIRONMENT_VARIATION_ACTORS = [
},
]
RUIN_PLACEHOLDER_ACTORS = [
{
"label": "AGR_GZ_Landmark_Ruin_Foundation_01",
"mesh_key": "chamfer_cube",
"material_key": "stone_resource",
"location_xy": unreal.Vector(6400.0, 24700.0, 0.0),
"z_offset": 38.0,
"scale": unreal.Vector(4.8, 3.2, 0.22),
"rotation": unreal.Rotator(0.0, -22.0, 0.0),
},
{
"label": "AGR_GZ_Landmark_Ruin_Wall_01",
"mesh_key": "chamfer_cube",
"material_key": "stone_resource",
"location_xy": unreal.Vector(5750.0, 25350.0, 0.0),
"z_offset": 165.0,
"scale": unreal.Vector(0.42, 2.35, 1.65),
"rotation": unreal.Rotator(0.0, -22.0, 0.0),
},
{
"label": "AGR_GZ_Landmark_Ruin_Wall_02",
"mesh_key": "chamfer_cube",
"material_key": "stone_resource",
"location_xy": unreal.Vector(7250.0, 24250.0, 0.0),
"z_offset": 118.0,
"scale": unreal.Vector(0.36, 1.7, 1.05),
"rotation": unreal.Rotator(0.0, 68.0, 0.0),
},
{
"label": "AGR_GZ_Landmark_Ruin_Cairn_01",
"mesh_key": "cylinder",
"material_key": "stone_resource",
"location_xy": unreal.Vector(7900.0, 25300.0, 0.0),
"z_offset": 92.0,
"scale": unreal.Vector(0.9, 0.9, 1.15),
"rotation": unreal.Rotator(0.0, 11.0, 0.0),
},
{
"label": "AGR_GZ_Landmark_Ruin_Threshold_01",
"mesh_key": "quarter_cylinder",
"material_key": "stone_resource",
"location_xy": unreal.Vector(6550.0, 23550.0, 0.0),
"z_offset": 70.0,
"scale": unreal.Vector(1.8, 0.55, 0.5),
"rotation": unreal.Rotator(0.0, -22.0, 0.0),
},
]
FOLIAGE_ZONES = {
"trees": {
@@ -756,6 +804,7 @@ def main():
labels.update(spec["label"] for spec in WATER_SOURCE_ACTORS)
labels.update(spec["label"] for spec in WEATHER_EXPOSURE_ZONES)
labels.update(spec["label"] for spec in ENVIRONMENT_VARIATION_ACTORS)
labels.update(spec["label"] for spec in RUIN_PLACEHOLDER_ACTORS)
labels.add(FOLIAGE_LABEL)
remove_existing_demo_actors(labels)
@@ -771,6 +820,8 @@ def main():
spawn_weather_exposure_zone(spec, height_values)
for spec in ENVIRONMENT_VARIATION_ACTORS:
spawn_environment_variation_actor(spec, height_values, materials)
for spec in RUIN_PLACEHOLDER_ACTORS:
spawn_environment_variation_actor(spec, height_values, materials)
for spec in DEMO_ACTORS:
spawn_demo_actor(spec, height_values, materials)
@@ -0,0 +1,103 @@
import unreal
MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test"
LANDMARK_PREFIX = "AGR_GZ_Landmark_Ruin_"
EXPECTED_LABELS = {
"AGR_GZ_Landmark_Ruin_Foundation_01",
"AGR_GZ_Landmark_Ruin_Wall_01",
"AGR_GZ_Landmark_Ruin_Wall_02",
"AGR_GZ_Landmark_Ruin_Cairn_01",
"AGR_GZ_Landmark_Ruin_Threshold_01",
}
PLACEHOLDER_MESH_PATH_PREFIX = "/Game/Agrarian/Environment/PlaceholderMeshes/"
STONE_MATERIAL_PATH = "/Game/Agrarian/Materials/M_AGR_GZ_Stone_Sandstone"
def get_actor_label(actor):
try:
return actor.get_actor_label()
except Exception:
return actor.get_name()
def normalized_asset_path(asset):
if not asset:
return ""
return asset.get_path_name().split(".", 1)[0]
def main():
if not unreal.EditorLevelLibrary.load_level(MAP_PATH):
raise RuntimeError(f"Could not load map: {MAP_PATH}")
failures = []
actors = unreal.EditorLevelLibrary.get_all_level_actors()
landmark_actors = {
get_actor_label(actor): actor
for actor in actors
if get_actor_label(actor).startswith(LANDMARK_PREFIX)
}
missing = EXPECTED_LABELS.difference(landmark_actors)
unexpected = set(landmark_actors).difference(EXPECTED_LABELS)
if missing:
failures.append(f"missing landmark placeholder actors: {sorted(missing)}")
if unexpected:
failures.append(f"unexpected landmark placeholder actors: {sorted(unexpected)}")
mesh_paths = set()
location_keys = set()
for label, actor in landmark_actors.items():
if not isinstance(actor, unreal.StaticMeshActor):
failures.append(f"{label} is not a StaticMeshActor")
continue
mesh_component = actor.static_mesh_component
mesh_path = normalized_asset_path(mesh_component.static_mesh)
mesh_paths.add(mesh_path)
if not mesh_path.startswith(PLACEHOLDER_MESH_PATH_PREFIX):
failures.append(f"{label} uses non-native mesh path {mesh_path}")
material_path = normalized_asset_path(mesh_component.get_material(0))
if material_path != STONE_MATERIAL_PATH:
failures.append(f"{label} expected stone material, got {material_path}")
scale = actor.get_actor_scale3d()
if min(scale.x, scale.y, scale.z) <= 0.0:
failures.append(f"{label} has invalid scale {scale}")
location = actor.get_actor_location()
if location.z <= 0.0:
failures.append(f"{label} appears below terrain/sea-level check threshold at {location}")
location_keys.add((round(location.x, 0), round(location.y, 0)))
if len(mesh_paths) < 3:
failures.append(f"expected at least 3 landmark mesh silhouettes, got {len(mesh_paths)}")
if len(location_keys) != len(EXPECTED_LABELS):
failures.append("landmark placeholder actors should occupy distinct positions")
roadmap = unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_dir()) + "AGRARIAN_DEVELOPMENT_ROADMAP.md"
natural_environment_doc = (
unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_dir())
+ "Docs/Terrain/GroundZeroNaturalEnvironmentPass.md"
)
for path, snippet in [
(roadmap, "[x] Add landmark or ruin placeholder"),
(natural_environment_doc, "ruin landmark placeholder"),
]:
with open(path, "r", encoding="utf-8") as handle:
text = handle.read()
if snippet not in text:
failures.append(f"{path} missing `{snippet}`")
if failures:
raise RuntimeError("Ground Zero landmark placeholder verification failed: " + "; ".join(failures))
unreal.log(
"Ground Zero landmark placeholder verification complete: "
f"{len(landmark_actors)} ruin actors, {len(mesh_paths)} mesh silhouettes."
)
main()