import unreal MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test" EXPECTED_ZONES = { "AGR_GZ_WeatherExposure_Ridge_01": { "zone_id": "ground_zero_ridge_exposed", "exposure_multiplier_min": 1.4, "temperature_offset_max": -1.0, }, "AGR_GZ_WeatherExposure_CoastalWind_01": { "zone_id": "ground_zero_coastal_wind", "exposure_multiplier_min": 1.2, "temperature_offset_max": -0.5, }, "AGR_GZ_WeatherExposure_DrainageCool_01": { "zone_id": "ground_zero_drainage_cool", "exposure_multiplier_min": 1.05, "temperature_offset_max": -0.5, }, } def get_actor_label(actor): try: return actor.get_actor_label() except Exception: return actor.get_name() 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() zones_by_label = { get_actor_label(actor): actor for actor in actors if isinstance(actor, unreal.AgrarianWeatherExposureZone) } if len(zones_by_label) != len(EXPECTED_ZONES): failures.append(f"expected {len(EXPECTED_ZONES)} weather exposure zones, found {len(zones_by_label)}") for label, expected in EXPECTED_ZONES.items(): zone = zones_by_label.get(label) if not zone: failures.append(f"missing weather exposure zone: {label}") continue zone_id = str(zone.get_editor_property("exposure_zone_id")) if zone_id != expected["zone_id"]: failures.append(f"{label} zone id expected {expected['zone_id']}, got {zone_id}") exposure_multiplier = zone.get_editor_property("exposure_multiplier") if exposure_multiplier < expected["exposure_multiplier_min"]: failures.append( f"{label} exposure multiplier expected >= {expected['exposure_multiplier_min']}, got {exposure_multiplier}" ) temperature_offset_c = zone.get_editor_property("temperature_offset_c") if temperature_offset_c > expected["temperature_offset_max"]: failures.append( f"{label} temperature offset expected <= {expected['temperature_offset_max']}, got {temperature_offset_c}" ) if not zone.exposure_volume: failures.append(f"{label} has no exposure volume") continue extent = zone.exposure_volume.get_unscaled_box_extent() if min(extent.x, extent.y, extent.z) <= 0.0: failures.append(f"{label} has invalid exposure volume extent {extent}") roadmap = unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_dir()) + "AGRARIAN_DEVELOPMENT_ROADMAP.md" technical_design = unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_dir()) + "Docs/TechnicalDesignDocument.md" for path, snippet in [ (roadmap, "[x] Add weather exposure zones if needed"), (technical_design, "Weather exposure zones"), ]: 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("Weather exposure zone verification failed: " + "; ".join(failures)) unreal.log( "Weather exposure zone verification complete: " f"{len(zones_by_label)} zones with exposure multipliers and temperature offsets." ) main()