From 86372a652ebaf3a57b43833e3ced454df494eaf8 Mon Sep 17 00:00:00 2001 From: Voyager Date: Thu, 20 Aug 2026 17:53:38 -0400 Subject: [PATCH] Add layered inland cliff generation --- tests/generated_world_runtime_validation.gd | 166 +++++++++++- .../terrain_chunk_compatibility_report.gd | 1 + .../terrain_chunk_generator_test.tscn | 5 +- tests/terrain_chunk_generator_validation.gd | 135 +++++++++- tools/blender/export_terrain_chunks.py | 10 +- .../biomes/definitions/biome_forest.tres | 7 +- .../biomes/definitions/biome_pine_forest.tres | 7 +- .../assets/chunk_0005_cliff_wall.png.import | 2 +- .../assets/chunk_0005_grass_lite.png.import | 2 +- .../assets/chunk_0006_cliff_wall.png.import | 2 +- .../assets/chunk_0006_grass_lite.png.import | 2 +- .../chunks/assets/chunk_0006_sand.png.import | 2 +- .../assets/chunk_0007_cliff_wall.png.import | 2 +- .../assets/chunk_0007_grass_lite.png.import | 2 +- world/generation/chunks/assets/chunk_0008.glb | Bin 0 -> 17996 bytes .../chunks/assets/chunk_0008.glb.import | 45 ++++ .../chunks/assets/chunk_0008_sand.png | Bin 0 -> 6289 bytes .../chunks/assets/chunk_0008_sand.png.import | 45 ++++ world/generation/chunks/assets/chunk_0009.glb | Bin 0 -> 7700 bytes .../chunks/assets/chunk_0009.glb.import | 45 ++++ .../chunks/assets/chunk_0009_grass_lite.png | Bin 0 -> 6317 bytes .../assets/chunk_0009_grass_lite.png.import | 43 +++ world/generation/chunks/assets/chunk_0010.glb | Bin 0 -> 19908 bytes .../chunks/assets/chunk_0010.glb.import | 45 ++++ .../chunks/assets/chunk_0010_cliff_wall.png | Bin 0 -> 9025 bytes .../assets/chunk_0010_cliff_wall.png.import | 43 +++ .../chunks/assets/chunk_0010_grass_lite.png | Bin 0 -> 6317 bytes .../assets/chunk_0010_grass_lite.png.import | 43 +++ world/generation/chunks/assets/chunk_0011.glb | Bin 0 -> 19420 bytes .../chunks/assets/chunk_0011.glb.import | 45 ++++ .../chunks/assets/chunk_0011_cliff_wall.png | Bin 0 -> 9025 bytes .../assets/chunk_0011_cliff_wall.png.import | 43 +++ .../chunks/assets/chunk_0011_grass_lite.png | Bin 0 -> 6317 bytes .../assets/chunk_0011_grass_lite.png.import | 43 +++ world/generation/chunks/assets/chunk_0012.glb | Bin 0 -> 30804 bytes .../chunks/assets/chunk_0012.glb.import | 45 ++++ .../chunks/assets/chunk_0012_cliff_wall.png | Bin 0 -> 9025 bytes .../assets/chunk_0012_cliff_wall.png.import | 43 +++ .../chunks/assets/chunk_0012_dirt.png | Bin 0 -> 5589 bytes .../chunks/assets/chunk_0012_dirt.png.import | 43 +++ .../chunks/assets/chunk_0012_grass_lite.png | Bin 0 -> 6317 bytes .../assets/chunk_0012_grass_lite.png.import | 43 +++ .../chunks/definitions/chunk_0002.tres | 2 +- .../chunks/definitions/chunk_0008.tres | 22 ++ .../chunks/definitions/chunk_0009.tres | 23 ++ .../chunks/definitions/chunk_0010.tres | 27 ++ .../chunks/definitions/chunk_0011.tres | 27 ++ .../chunks/definitions/chunk_0012.tres | 27 ++ .../chunks/terrain_chunk_catalog.tres | 9 +- world/generation/generated_world_region.gd | 133 +++++++--- world/generation/generated_world_region.tscn | 7 +- .../props/definitions/prop_mushroom.tres | 4 + .../props/definitions/prop_pine.tres | 2 + .../props/definitions/prop_tree_1.tres | 9 +- .../props/definitions/prop_tree_2.tres | 9 +- .../props/definitions/prop_tree_3.tres | 9 +- .../generation/props/materials/leaf_dark.tres | 9 + .../props/materials/leaf_light.tres | 9 + .../generation/props/materials/leaf_mid.tres | 9 + world/generation/terrain_biome_prop_rule.gd | 3 + world/generation/terrain_chunk_analyzer.gd | 23 ++ world/generation/terrain_chunk_catalog.gd | 18 ++ world/generation/terrain_chunk_definition.gd | 14 + world/generation/terrain_chunk_generator.gd | 249 +++++++++++++++++- world/generation/terrain_prop_catalog.gd | 19 ++ world/generation/terrain_prop_definition.gd | 9 + 66 files changed, 1552 insertions(+), 79 deletions(-) create mode 100644 world/generation/chunks/assets/chunk_0008.glb create mode 100644 world/generation/chunks/assets/chunk_0008.glb.import create mode 100644 world/generation/chunks/assets/chunk_0008_sand.png create mode 100644 world/generation/chunks/assets/chunk_0008_sand.png.import create mode 100644 world/generation/chunks/assets/chunk_0009.glb create mode 100644 world/generation/chunks/assets/chunk_0009.glb.import create mode 100644 world/generation/chunks/assets/chunk_0009_grass_lite.png create mode 100644 world/generation/chunks/assets/chunk_0009_grass_lite.png.import create mode 100644 world/generation/chunks/assets/chunk_0010.glb create mode 100644 world/generation/chunks/assets/chunk_0010.glb.import create mode 100644 world/generation/chunks/assets/chunk_0010_cliff_wall.png create mode 100644 world/generation/chunks/assets/chunk_0010_cliff_wall.png.import create mode 100644 world/generation/chunks/assets/chunk_0010_grass_lite.png create mode 100644 world/generation/chunks/assets/chunk_0010_grass_lite.png.import create mode 100644 world/generation/chunks/assets/chunk_0011.glb create mode 100644 world/generation/chunks/assets/chunk_0011.glb.import create mode 100644 world/generation/chunks/assets/chunk_0011_cliff_wall.png create mode 100644 world/generation/chunks/assets/chunk_0011_cliff_wall.png.import create mode 100644 world/generation/chunks/assets/chunk_0011_grass_lite.png create mode 100644 world/generation/chunks/assets/chunk_0011_grass_lite.png.import create mode 100644 world/generation/chunks/assets/chunk_0012.glb create mode 100644 world/generation/chunks/assets/chunk_0012.glb.import create mode 100644 world/generation/chunks/assets/chunk_0012_cliff_wall.png create mode 100644 world/generation/chunks/assets/chunk_0012_cliff_wall.png.import create mode 100644 world/generation/chunks/assets/chunk_0012_dirt.png create mode 100644 world/generation/chunks/assets/chunk_0012_dirt.png.import create mode 100644 world/generation/chunks/assets/chunk_0012_grass_lite.png create mode 100644 world/generation/chunks/assets/chunk_0012_grass_lite.png.import create mode 100644 world/generation/chunks/definitions/chunk_0008.tres create mode 100644 world/generation/chunks/definitions/chunk_0009.tres create mode 100644 world/generation/chunks/definitions/chunk_0010.tres create mode 100644 world/generation/chunks/definitions/chunk_0011.tres create mode 100644 world/generation/chunks/definitions/chunk_0012.tres create mode 100644 world/generation/props/materials/leaf_dark.tres create mode 100644 world/generation/props/materials/leaf_light.tres create mode 100644 world/generation/props/materials/leaf_mid.tres diff --git a/tests/generated_world_runtime_validation.gd b/tests/generated_world_runtime_validation.gd index c6ac945..3a7a297 100644 --- a/tests/generated_world_runtime_validation.gd +++ b/tests/generated_world_runtime_validation.gd @@ -82,8 +82,14 @@ func _validate_generated_region( generator: TerrainChunkGenerator, ) -> void: var placements := generator.placement_keys() - assert(placements.size() == 49) - assert(placements[24].begins_with("chunk_spawn@")) + var expected_chunk_count := generator.grid_size.x * generator.grid_size.y + var center := Vector2i( + generator.grid_size.x / 2, + generator.grid_size.y / 2, + ) + var center_index := center.y * generator.grid_size.x + center.x + assert(placements.size() == expected_chunk_count) + assert(placements[center_index].begins_with("chunk_spawn@")) assert(_placement_count(placements, "chunk_spawn") == 1) assert(_placement_count(placements, "chunk_0001") >= 1) assert(_placement_count(placements, "chunk_0002") >= 1) @@ -92,8 +98,24 @@ func _validate_generated_region( assert(_placement_count(placements, "chunk_0005") >= 1) assert(_placement_count(placements, "chunk_0006") >= 1) assert(_placement_count(placements, "chunk_0007") >= 1) - assert(generator.get_generated_chunks_root().get_child_count() == 49) - assert(generator.get_primary_terrain_meshes().size() == 49) + assert(_placement_count(placements, "chunk_0008") >= 1) + assert(_placement_count(placements, "chunk_0009") == 1) + assert(_placement_count(placements, "chunk_0010") == 4) + assert( + _placement_count(placements, "chunk_0011") + + _placement_count(placements, "chunk_0012") + == 4 + ) + assert(_placement_count(placements, "chunk_0012") <= 1) + assert( + generator.get_generated_chunks_root().get_child_count() + == expected_chunk_count + ) + assert( + generator.get_primary_terrain_meshes().size() + == expected_chunk_count + ) + _validate_elevated_cliff_feature(generator) var shop := region.get_node("Interactables/FishingShopWorld") as Node3D var storage := region.get_node("Interactables/PlayerStorageBox") as Node3D @@ -111,6 +133,7 @@ func _validate_generated_region( var fresh_root := region.get_node("WaterBodies/FreshWaterBodies") as Node3D assert(ocean != null and fresh_root != null) assert(ocean.water_type == WaterType.Type.SALT_WATER) + assert(is_equal_approx(ocean.position.y, GeneratedWorldRegion.WATER_HEIGHT)) var fresh_placement_count := 0 for record: Dictionary in generator.placement_records(): var tags: PackedStringArray = record.get("tags", PackedStringArray()) @@ -123,6 +146,7 @@ func _validate_generated_region( var fresh := child as WaterBodyAuthoring assert(fresh != null) assert(fresh.water_type == WaterType.Type.FRESH_WATER) + assert(is_equal_approx(fresh.position.y, GeneratedWorldRegion.WATER_HEIGHT)) assert(fresh.visible) assert(fresh.surface_size.x < 10.0 or fresh.surface_size.y < 10.0) assert(not fresh.visual_surface_enabled) @@ -155,13 +179,13 @@ func _validate_generated_region( &"terrain_chunk_coordinate", Vector2i.ZERO, ) - var center := Vector2i( + var spawn_coordinate := Vector2i( generator.grid_size.x / 2, generator.grid_size.y / 2, ) var spawn_distance := ( - absi(coordinate.x - center.x) - + absi(coordinate.y - center.y) + absi(coordinate.x - spawn_coordinate.x) + + absi(coordinate.y - spawn_coordinate.y) ) assert(spawn_distance >= definition.minimum_spawn_chunk_distance) _validate_decoration_transform( @@ -169,6 +193,13 @@ func _validate_generated_region( child as Node3D, definition, ) + if prop_id in [&"prop_tree_1", &"prop_tree_2", &"prop_tree_3"]: + assert( + _has_material_variant_override( + child.get_node_or_null("Visual"), + definition.material_variants, + ) + ) assert(_decoration_group_count(region, &"grass_tree") > 0) assert(_decoration_group_count(region, &"sand_tree") > 0) assert( @@ -187,6 +218,69 @@ func _validate_generated_region( ) +func _validate_elevated_cliff_feature( + generator: TerrainChunkGenerator, +) -> void: + var elevated_coordinates: Dictionary[Vector2i, StringName] = {} + var top_coordinate := Vector2i(-1, -1) + for record: Dictionary in generator.placement_records(): + var stable_id: StringName = record.get("stable_id", &"") + if stable_id not in [ + &"chunk_0009", + &"chunk_0010", + &"chunk_0011", + &"chunk_0012", + ]: + continue + var coordinate: Vector2i = record.get("coordinate", Vector2i.ZERO) + assert(coordinate.x > 0 and coordinate.x < generator.grid_size.x - 1) + assert(coordinate.y > 0 and coordinate.y < generator.grid_size.y - 1) + elevated_coordinates[coordinate] = stable_id + if stable_id == &"chunk_0009": + top_coordinate = coordinate + assert(elevated_coordinates.size() == 9) + assert(top_coordinate != Vector2i(-1, -1)) + for row_offset: int in range(-1, 2): + for column_offset: int in range(-1, 2): + assert( + elevated_coordinates.has( + top_coordinate + Vector2i(column_offset, row_offset) + ) + ) + + var generated := generator.get_generated_chunks_root() + assert(generated != null) + var layered_count := 0 + for chunk_root: Node in generated.get_children(): + var stable_id := StringName( + chunk_root.get_meta(&"terrain_chunk_id", &"") + ) + if stable_id not in [ + &"chunk_0009", + &"chunk_0010", + &"chunk_0011", + &"chunk_0012", + ]: + continue + layered_count += 1 + var base_layer := chunk_root.get_node_or_null("TerrainBaseLayer") + var overlay := chunk_root.get_node_or_null("TerrainOverlay") + assert(base_layer != null and overlay != null) + var base_mesh := TerrainChunkAnalyzer.find_primary_mesh( + base_layer, + &"chunk_0000", + ) + var overlay_mesh := TerrainChunkAnalyzer.find_primary_mesh( + overlay, + stable_id, + ) + assert(base_mesh != null and base_mesh.mesh != null) + assert(overlay_mesh != null and overlay_mesh.mesh != null) + assert(base_mesh.has_node("TerrainBaseLayerCollision")) + assert(overlay_mesh.has_node("TerrainCollision")) + assert(layered_count == 9) + + func _validate_ocean_facing_record( record: Dictionary, grid_size: Vector2i, @@ -224,6 +318,23 @@ func _validate_prop_catalog(region: GeneratedWorldRegion) -> void: assert(instance.position.is_zero_approx()) assert(_find_mesh_instance(instance) != null) instance.free() + var mushroom := catalog.definition_for_id(&"prop_mushroom") + assert(mushroom != null and mushroom.has_collision()) + assert(mushroom.visual_offset.y < 0.0) + for tree_id: StringName in [ + &"prop_tree_1", + &"prop_tree_2", + &"prop_tree_3", + ]: + var tree := catalog.definition_for_id(tree_id) + assert(tree != null) + assert(tree.minimum_visual_scale < tree.maximum_visual_scale) + assert(tree.material_variants.size() >= 3) + assert(not tree.variant_material_slot_names.is_empty()) + var pine := catalog.definition_for_id(&"prop_pine") + assert(pine != null) + assert(pine.minimum_visual_scale < pine.maximum_visual_scale) + assert(pine.material_variants.is_empty()) func _validate_biome_catalog( @@ -276,7 +387,16 @@ func _validate_decoration_transform( var collision := prop.get_node_or_null( "TrunkCollision/CollisionShape" ) as CollisionShape3D - assert(visual_root != null and visual_root.position.is_zero_approx()) + assert(visual_root != null) + assert(visual_root.position.is_equal_approx(definition.visual_offset)) + var visual_scale := float( + prop.get_meta(&"terrain_prop_visual_scale", 1.0) + ) + assert(visual_scale >= definition.minimum_visual_scale - 0.001) + assert(visual_scale <= definition.maximum_visual_scale + 0.001) + assert( + visual_root.scale.is_equal_approx(Vector3.ONE * visual_scale) + ) assert(visual != null and visual.mesh != null) if definition.has_collision(): assert(collision != null) @@ -319,6 +439,26 @@ func _find_mesh_instance(root_node: Node) -> MeshInstance3D: return null +func _has_material_variant_override( + root_node: Node, + variants: Array[Material], +) -> bool: + if root_node == null: + return false + var mesh_instance := root_node as MeshInstance3D + if mesh_instance != null and mesh_instance.mesh != null: + for surface_index: int in mesh_instance.mesh.get_surface_count(): + var override := mesh_instance.get_surface_override_material( + surface_index + ) + if override != null and override in variants: + return true + for child: Node in root_node.get_children(): + if _has_material_variant_override(child, variants): + return true + return false + + func _validate_authored_chunk_surfaces( region: GeneratedWorldRegion, generator: TerrainChunkGenerator, @@ -329,6 +469,7 @@ func _validate_authored_chunk_surfaces( var found_grass_ocean_edge := false var found_grass_beach_transition := false var found_grass_ocean_corner := false + var found_beach_ocean_corner := false for chunk_root: Node in generated.get_children(): if chunk_root.name.begins_with("chunk_0002r"): var beach := chunk_root.find_child( @@ -383,11 +524,20 @@ func _validate_authored_chunk_surfaces( assert("grass_lite" in corner_materials) assert("cliff_wall" in corner_materials) found_grass_ocean_corner = true + elif chunk_root.name.begins_with("chunk_0008r"): + var beach_ocean_corner := chunk_root.find_child( + "chunk_0008", true, false + ) as MeshInstance3D + assert(beach_ocean_corner != null and beach_ocean_corner.mesh != null) + var beach_corner_materials := _material_names(beach_ocean_corner) + assert("sand" in beach_corner_materials) + found_beach_ocean_corner = true assert(found_beach) assert(found_pond) assert(found_grass_ocean_edge) assert(found_grass_beach_transition) assert(found_grass_ocean_corner) + assert(found_beach_ocean_corner) func _material_names(mesh_instance: MeshInstance3D) -> PackedStringArray: diff --git a/tests/manual/terrain_chunk_generator/terrain_chunk_compatibility_report.gd b/tests/manual/terrain_chunk_generator/terrain_chunk_compatibility_report.gd index 64d5f1f..04976a9 100644 --- a/tests/manual/terrain_chunk_generator/terrain_chunk_compatibility_report.gd +++ b/tests/manual/terrain_chunk_generator/terrain_chunk_compatibility_report.gd @@ -119,6 +119,7 @@ func _make_generator() -> TerrainChunkGenerator: "chunk_0005", "chunk_0006", "chunk_0007", + "chunk_0008", ] ) return generator diff --git a/tests/manual/terrain_chunk_generator/terrain_chunk_generator_test.tscn b/tests/manual/terrain_chunk_generator/terrain_chunk_generator_test.tscn index 964da9a..7e12544 100644 --- a/tests/manual/terrain_chunk_generator/terrain_chunk_generator_test.tscn +++ b/tests/manual/terrain_chunk_generator/terrain_chunk_generator_test.tscn @@ -21,12 +21,13 @@ shadow_enabled = true [node name="TerrainChunkGenerator" type="Node3D" parent="."] script = ExtResource("2_generator") catalog = ExtResource("3_catalog") -grid_size = Vector2i(7, 7) +grid_size = Vector2i(11, 9) generation_seed = 13001 build_collision = true show_chunk_labels = false force_center_chunk_id = &"chunk_spawn" -required_chunk_ids = PackedStringArray("chunk_spawn", "chunk_0001", "chunk_0002", "chunk_0003", "chunk_0004", "chunk_0005", "chunk_0006", "chunk_0007") +required_chunk_ids = PackedStringArray("chunk_spawn", "chunk_0001", "chunk_0002", "chunk_0003", "chunk_0004", "chunk_0005", "chunk_0006", "chunk_0007", "chunk_0008") +elevated_cliff_feature_enabled = true [node name="Player" parent="." instance=ExtResource("4_player")] position = Vector3(0, 0.3, 0) diff --git a/tests/terrain_chunk_generator_validation.gd b/tests/terrain_chunk_generator_validation.gd index 0d70816..467c154 100644 --- a/tests/terrain_chunk_generator_validation.gd +++ b/tests/terrain_chunk_generator_validation.gd @@ -12,6 +12,11 @@ const EXPECTED_IDS: Array[String] = [ "chunk_0005", "chunk_0006", "chunk_0007", + "chunk_0008", + "chunk_0009", + "chunk_0010", + "chunk_0011", + "chunk_0012", "chunk_spawn", ] const REQUIRED_IDS: Array[String] = [ @@ -23,10 +28,11 @@ const REQUIRED_IDS: Array[String] = [ "chunk_0005", "chunk_0006", "chunk_0007", + "chunk_0008", ] const TEST_SEED := 13001 const CONNECTOR_STRESS_SEED := 287 -const EXPECTED_SOLVER_VARIANT_COUNT := 27 +const EXPECTED_SOLVER_VARIANT_COUNT := 31 const EXPECTED_VARIANT_COUNTS: Dictionary[StringName, int] = { &"chunk_0000": 4, &"chunk_0001": 4, @@ -36,6 +42,11 @@ const EXPECTED_VARIANT_COUNTS: Dictionary[StringName, int] = { &"chunk_0005": 4, &"chunk_0006": 4, &"chunk_0007": 4, + &"chunk_0008": 4, + &"chunk_0009": 4, + &"chunk_0010": 4, + &"chunk_0011": 4, + &"chunk_0012": 4, &"chunk_spawn": 1, } @@ -75,6 +86,11 @@ func _validate_catalog() -> void: var grass_ocean_edge := CATALOG.definition_for_id(&"chunk_0005") var grass_beach_transition := CATALOG.definition_for_id(&"chunk_0006") var grass_ocean_corner := CATALOG.definition_for_id(&"chunk_0007") + var beach_ocean_corner := CATALOG.definition_for_id(&"chunk_0008") + var cliff_top := CATALOG.definition_for_id(&"chunk_0009") + var cliff_corner := CATALOG.definition_for_id(&"chunk_0010") + var cliff_edge := CATALOG.definition_for_id(&"chunk_0011") + var cliff_ramp := CATALOG.definition_for_id(&"chunk_0012") var spawn := CATALOG.definition_for_id(&"chunk_spawn") _check( ( @@ -84,6 +100,11 @@ func _validate_catalog() -> void: and grass_ocean_edge != null and grass_beach_transition != null and grass_ocean_corner != null + and beach_ocean_corner != null + and cliff_top != null + and cliff_corner != null + and cliff_edge != null + and cliff_ramp != null and spawn != null ), "The authored biome-rule definitions must be available.", @@ -95,6 +116,11 @@ func _validate_catalog() -> void: and grass_ocean_edge != null and grass_beach_transition != null and grass_ocean_corner != null + and beach_ocean_corner != null + and cliff_top != null + and cliff_corner != null + and cliff_edge != null + and cliff_ramp != null and spawn != null ): _check( @@ -193,6 +219,45 @@ func _validate_catalog() -> void: ), "Both corner land seams must accept straight grass ocean edges.", ) + _check( + beach_ocean_corner.ocean_facing_edges + == ( + (1 << int(TerrainChunkTopology.Edge.EAST)) + | (1 << int(TerrainChunkTopology.Edge.SOUTH)) + ), + "The authored beach corner must expose east and south to ocean.", + ) + _check( + beach_ocean_corner.minimum_required_neighbors == 2 + and ( + "beach_ocean_edge" + in beach_ocean_corner.required_neighbor_tags + ), + "The beach corner must join two straight beach ocean edges.", + ) + for cliff_definition: TerrainChunkDefinition in [ + cliff_top, + cliff_corner, + cliff_edge, + cliff_ramp, + ]: + _check( + cliff_definition.overlay_only + and cliff_definition.must_be_interior + and cliff_definition.base_layer_scene != null + and cliff_definition.base_layer_mesh_name == &"chunk_0000", + "Every second-tier piece must overlay level-one grass inland.", + ) + _check( + cliff_top.minimum_required_neighbors == 4 + and "elevation_2" in cliff_top.required_neighbor_tags, + "The second-tier top must be enclosed on all four sides.", + ) + _check( + "ramp" in cliff_ramp.tags + and cliff_ramp.maximum_placements > 0, + "The second-tier ramp must remain available without being required.", + ) func _validate_profiles() -> void: @@ -443,11 +508,13 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: var grass_ocean_edge := CATALOG.definition_for_id(&"chunk_0005") var grass_beach_transition := CATALOG.definition_for_id(&"chunk_0006") var grass_ocean_corner := CATALOG.definition_for_id(&"chunk_0007") + var beach_ocean_corner := CATALOG.definition_for_id(&"chunk_0008") _check( ( grass_ocean_edge != null and grass_beach_transition != null and grass_ocean_corner != null + and beach_ocean_corner != null ), "The authored coastline additions must be available.", ) @@ -455,6 +522,7 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: grass_ocean_edge == null or grass_beach_transition == null or grass_ocean_corner == null + or beach_ocean_corner == null ): return var beach_zero := _find_variant(generator, &"chunk_0002", 0) @@ -462,12 +530,14 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: var grass_edge_south := _find_variant(generator, &"chunk_0005", 3) var transition_zero := _find_variant(generator, &"chunk_0006", 0) var corner_zero := _find_variant(generator, &"chunk_0007", 0) + var beach_corner_zero := _find_variant(generator, &"chunk_0008", 0) _check( beach_zero != null and grass_edge_zero != null and grass_edge_south != null and transition_zero != null - and corner_zero != null, + and corner_zero != null + and beach_corner_zero != null, "The unrotated coastline variants must be available.", ) if ( @@ -476,6 +546,7 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: and grass_edge_south != null and transition_zero != null and corner_zero != null + and beach_corner_zero != null ): _check( grass_edge_zero.profile( @@ -522,6 +593,24 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: ), "The corner's west side must join a straight grass ocean edge.", ) + _check( + beach_corner_zero.profile(TerrainChunkTopology.Edge.NORTH).matches( + beach_zero.profile(TerrainChunkTopology.Edge.SOUTH), + generator.edge_match_tolerance, + ), + "The beach corner's north side must join a straight beach.", + ) + var beach_south := _find_variant(generator, &"chunk_0002", 3) + _check( + beach_south != null + and beach_corner_zero.profile( + TerrainChunkTopology.Edge.WEST + ).matches( + beach_south.profile(TerrainChunkTopology.Edge.EAST), + generator.edge_match_tolerance, + ), + "The beach corner's west side must join a rotated straight beach.", + ) var flat_grass := _find_variant(generator, &"chunk_0000", 0) var flat_sand := _find_variant(generator, &"chunk_0001", 0) _check( @@ -560,7 +649,12 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: ), "No transition rotation may accept sand behind it.", ) - for stable_id: StringName in [&"chunk_0005", &"chunk_0006", &"chunk_0007"]: + for stable_id: StringName in [ + &"chunk_0005", + &"chunk_0006", + &"chunk_0007", + &"chunk_0008", + ]: for quarter_turns: int in 4: var coast_variant := _find_variant( generator, @@ -580,11 +674,15 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: ), "%s must never place its ocean edge inside the map." % stable_id, ) - if stable_id != &"chunk_0007": + if stable_id != &"chunk_0007" and stable_id != &"chunk_0008": continue var boundary_coordinate := Vector2i(3, 3) var ocean_edges := coast_variant.rotated_edge_mask( - grass_ocean_corner.ocean_facing_edges + ( + grass_ocean_corner.ocean_facing_edges + if stable_id == &"chunk_0007" + else beach_ocean_corner.ocean_facing_edges + ) ) for edge_value: int in TerrainChunkTopology.Edge.values(): if (ocean_edges & (1 << edge_value)) == 0: @@ -603,15 +701,15 @@ func _validate_authored_rotations(generator: TerrainChunkGenerator) -> void: coast_variant, boundary_coordinate, ), - "Each grass corner rotation must fit its matching map corner.", + "Each coast corner rotation must fit its matching map corner.", ) func _validate_generation_summary(generator: TerrainChunkGenerator) -> void: var summary := generator._build_summary() _check( - int(summary.get("variant_count", 0)) == 33, - "The current catalog must expose all 33 authored rotations.", + int(summary.get("variant_count", 0)) == 53, + "The current catalog must expose all 53 authored rotations.", ) _check( int(summary.get("solver_variant_count", 0)) @@ -811,6 +909,27 @@ func _validate_layout_rules(generator: TerrainChunkGenerator) -> void: straight_edge_neighbors == 2, "Every grass corner must join two straight grass ocean edges.", ) + if placement.definition.stable_id == &"chunk_0008": + var straight_beach_neighbors := 0 + for edge_value: int in TerrainChunkTopology.Edge.values(): + var neighbor_coordinate := ( + coordinate + + TerrainChunkTopology.grid_offset( + edge_value as TerrainChunkTopology.Edge + ) + ) + if not generator._coordinate_is_inside_grid(neighbor_coordinate): + continue + var neighbor := generator._placements[ + neighbor_coordinate.y * generator.grid_size.x + + neighbor_coordinate.x + ] + if neighbor.definition.stable_id == &"chunk_0002": + straight_beach_neighbors += 1 + _check( + straight_beach_neighbors == 2, + "Every beach corner must join two straight beach ocean edges.", + ) if placement.definition.stable_id != &"chunk_0001": continue var touches_coast := false diff --git a/tools/blender/export_terrain_chunks.py b/tools/blender/export_terrain_chunks.py index 27b775d..654227e 100644 --- a/tools/blender/export_terrain_chunks.py +++ b/tools/blender/export_terrain_chunks.py @@ -282,10 +282,16 @@ def _discover_chunks(tolerance: float) -> list[ChunkSource]: # Coastline meshes may intentionally stop before the positive-X edge, # leaving the surrounding ocean visible. Positive X is the canonical # authored ocean direction; Godot supplies the quarter-turn variants. - allow_open_east_edge = "ocean_edge" in label + # Elevated inland cliff overlays intentionally stop at their downhill + # edge. The runtime places them over the existing flat grass chunk, so + # these omissions are not coastline openings or holes in the final cell. + layered_inland_cliff = "cliff_2" in label + allow_open_east_edge = "ocean_edge" in label or layered_inland_cliff # Corner pieces additionally leave canonical negative Y open. Their # two marked ocean edges rotate together at runtime. - allow_open_south_edge = "ocean_edge_corner" in label + allow_open_south_edge = ( + "ocean_edge_corner" in label or layered_inland_cliff + ) bound_problems = _validate_bounds( bounds, tolerance, diff --git a/world/generation/biomes/definitions/biome_forest.tres b/world/generation/biomes/definitions/biome_forest.tres index 0d11be2..a660042 100644 --- a/world/generation/biomes/definitions/biome_forest.tres +++ b/world/generation/biomes/definitions/biome_forest.tres @@ -6,10 +6,11 @@ [sub_resource type="Resource" id="Rule_grass_tree"] script = ExtResource("2_rule") procedural_group = &"grass_tree" -placement_chance = 9000 -adjacency_bonus = 1000 -maximum_density = 10000 +placement_chance = 8200 +adjacency_bonus = 1200 +maximum_density = 8500 minimum_placements = 2 +placement_attempts_per_chunk = 3 allowed_prop_ids = PackedStringArray("prop_tree_1", "prop_tree_2", "prop_tree_3") [sub_resource type="Resource" id="Rule_grass_detail"] diff --git a/world/generation/biomes/definitions/biome_pine_forest.tres b/world/generation/biomes/definitions/biome_pine_forest.tres index 293acbc..6601a46 100644 --- a/world/generation/biomes/definitions/biome_pine_forest.tres +++ b/world/generation/biomes/definitions/biome_pine_forest.tres @@ -6,10 +6,11 @@ [sub_resource type="Resource" id="Rule_grass_tree"] script = ExtResource("2_rule") procedural_group = &"grass_tree" -placement_chance = 9000 -adjacency_bonus = 1000 -maximum_density = 10000 +placement_chance = 8200 +adjacency_bonus = 1200 +maximum_density = 8500 minimum_placements = 2 +placement_attempts_per_chunk = 3 allowed_prop_ids = PackedStringArray("prop_pine") [sub_resource type="Resource" id="Rule_grass_detail"] diff --git a/world/generation/chunks/assets/chunk_0005_cliff_wall.png.import b/world/generation/chunks/assets/chunk_0005_cliff_wall.png.import index 0796279..51d8e11 100644 --- a/world/generation/chunks/assets/chunk_0005_cliff_wall.png.import +++ b/world/generation/chunks/assets/chunk_0005_cliff_wall.png.import @@ -28,7 +28,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=true +mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/world/generation/chunks/assets/chunk_0005_grass_lite.png.import b/world/generation/chunks/assets/chunk_0005_grass_lite.png.import index c1b1dd6..01e84d4 100644 --- a/world/generation/chunks/assets/chunk_0005_grass_lite.png.import +++ b/world/generation/chunks/assets/chunk_0005_grass_lite.png.import @@ -28,7 +28,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=true +mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/world/generation/chunks/assets/chunk_0006_cliff_wall.png.import b/world/generation/chunks/assets/chunk_0006_cliff_wall.png.import index 238e929..411a5b1 100644 --- a/world/generation/chunks/assets/chunk_0006_cliff_wall.png.import +++ b/world/generation/chunks/assets/chunk_0006_cliff_wall.png.import @@ -28,7 +28,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=true +mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/world/generation/chunks/assets/chunk_0006_grass_lite.png.import b/world/generation/chunks/assets/chunk_0006_grass_lite.png.import index fb37b89..2d01a58 100644 --- a/world/generation/chunks/assets/chunk_0006_grass_lite.png.import +++ b/world/generation/chunks/assets/chunk_0006_grass_lite.png.import @@ -28,7 +28,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=true +mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/world/generation/chunks/assets/chunk_0006_sand.png.import b/world/generation/chunks/assets/chunk_0006_sand.png.import index bc9f61a..d829b05 100644 --- a/world/generation/chunks/assets/chunk_0006_sand.png.import +++ b/world/generation/chunks/assets/chunk_0006_sand.png.import @@ -28,7 +28,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=true +mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/world/generation/chunks/assets/chunk_0007_cliff_wall.png.import b/world/generation/chunks/assets/chunk_0007_cliff_wall.png.import index 007f60d..d78acc6 100644 --- a/world/generation/chunks/assets/chunk_0007_cliff_wall.png.import +++ b/world/generation/chunks/assets/chunk_0007_cliff_wall.png.import @@ -28,7 +28,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=true +mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/world/generation/chunks/assets/chunk_0007_grass_lite.png.import b/world/generation/chunks/assets/chunk_0007_grass_lite.png.import index abe6b52..03e4dc5 100644 --- a/world/generation/chunks/assets/chunk_0007_grass_lite.png.import +++ b/world/generation/chunks/assets/chunk_0007_grass_lite.png.import @@ -28,7 +28,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=true +mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/world/generation/chunks/assets/chunk_0008.glb b/world/generation/chunks/assets/chunk_0008.glb new file mode 100644 index 0000000000000000000000000000000000000000..d785e6577767243494c8e8a172b1da547d501df8 GIT binary patch literal 17996 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 S34iAgbhHdK%QbeyLim4SWU+Vv literal 0 HcmV?d00001 diff --git a/world/generation/chunks/assets/chunk_0008.glb.import b/world/generation/chunks/assets/chunk_0008.glb.import new file mode 100644 index 0000000..a090711 --- /dev/null +++ b/world/generation/chunks/assets/chunk_0008.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bm1teitx5ijxl" +path="res://.godot/imported/chunk_0008.glb-0b0a6712e5384c3f72c65e6ef1fc12c4.scn" + +[deps] + +source_file="res://world/generation/chunks/assets/chunk_0008.glb" +dest_files=["res://.godot/imported/chunk_0008.glb-0b0a6712e5384c3f72c65e6ef1fc12c4.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/world/generation/chunks/assets/chunk_0008_sand.png b/world/generation/chunks/assets/chunk_0008_sand.png new file mode 100644 index 0000000000000000000000000000000000000000..06f807ac1af29baf7fd7adad1fd94b6a54cae740 GIT binary patch literal 6289 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 Hu0mjfqaXRk literal 0 HcmV?d00001 diff --git a/world/generation/chunks/assets/chunk_0008_sand.png.import b/world/generation/chunks/assets/chunk_0008_sand.png.import new file mode 100644 index 0000000..9c135d8 --- /dev/null +++ b/world/generation/chunks/assets/chunk_0008_sand.png.import @@ -0,0 +1,45 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dj24j2d1u8712" +path.s3tc="res://.godot/imported/chunk_0008_sand.png-55d7cf4f540d9cfb7d4ba59e9f9f38da.s3tc.ctex" +path.etc2="res://.godot/imported/chunk_0008_sand.png-55d7cf4f540d9cfb7d4ba59e9f9f38da.etc2.ctex" +metadata={ +"imported_formats": ["s3tc_bptc", "etc2_astc"], +"vram_texture": true +} +generator_parameters={ +"md5": "adfa66b8fe9da7f3450d3ddfd432b86a" +} + +[deps] + +source_file="res://world/generation/chunks/assets/chunk_0008_sand.png" +dest_files=["res://.godot/imported/chunk_0008_sand.png-55d7cf4f540d9cfb7d4ba59e9f9f38da.s3tc.ctex", "res://.godot/imported/chunk_0008_sand.png-55d7cf4f540d9cfb7d4ba59e9f9f38da.etc2.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/world/generation/chunks/assets/chunk_0009.glb b/world/generation/chunks/assets/chunk_0009.glb new file mode 100644 index 0000000000000000000000000000000000000000..8c09d3a2ec87ac868e44d34924eb0dc6450f033d GIT binary patch literal 7700 zcmb7J2UJtdwmv{W5D)|eM3E4w(tDE*(tDFmhyfxcl!O*aK$;4oB1NUD5CQ2;I)Wla znsgA5CcXFmg8uj3|Gm4`yYHQ|=FIFpv-ke?H+xRjI&pL{zC#EA0No7$r~v_hrjed5 z1_Jf+f}Fa>4ekj=Aw40|5G^N9q#M!;?1(o3E4jek?!i658UlJ?Z!vyhei11M zFT@+}>4iYL;TH?@3qk^UAzm=N1BkTXUn4Jwv?T`O26e^jAV$CEcp+}cd+_rKLF+*4 ze@PgKE8NTJx9MN&VNPf_XInu*K`F@jLRTmX?umf9{PB4YiMDrv8zJt&??I$do@hAU z)1NSop7?BRT@WZZ9-zCurw$wib#Xz!43TI@CpWkk-W~(7hkC)4kuFG2W4JF0?TLqn zfgtb+`r-lL({TOE<_;A0n+w6f-w5ykejzE75NF zB03KQ#q($>#w*M#hWF%(z!!)m-?_+lE~EZHFjZ9+!IunvFaCxSPsxAq{l8fY|39pS z|1CD2@_�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 literal 0 HcmV?d00001 diff --git a/world/generation/chunks/assets/chunk_0009.glb.import b/world/generation/chunks/assets/chunk_0009.glb.import new file mode 100644 index 0000000..72c9778 --- /dev/null +++ b/world/generation/chunks/assets/chunk_0009.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://hasempwso5gi" +path="res://.godot/imported/chunk_0009.glb-397f642bee3da14146c56fddf8e21369.scn" + +[deps] + +source_file="res://world/generation/chunks/assets/chunk_0009.glb" +dest_files=["res://.godot/imported/chunk_0009.glb-397f642bee3da14146c56fddf8e21369.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/world/generation/chunks/assets/chunk_0009_grass_lite.png b/world/generation/chunks/assets/chunk_0009_grass_lite.png new file mode 100644 index 0000000000000000000000000000000000000000..52c7ccb8088ddfae88f9b861a807f1de2d38f855 GIT binary patch literal 6317 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%0D^qM=gHOe=vbcCt&%aQCo&K-OfVO z(!pSAYGHs&OIf++5HKUVX2)O;K{x9R0U@+sn_r3@iy7lLI!((4fu1(@y@E~Po|vd~ z^kUJ`)1pn3@7421kY<;WW~WU1T%>yjyk$)PY}|X}u;S#uS<>ORdgyppU~syG+iDi% z^@9YaRqp_Qb?HSvaG-TEb>!qHhM)Jzm;a|qiHtd;ez=P4=yf7};4wsh$UnT8 z-c9CJQh^!)6~4aQy%Xy-@;fm~!ScVja1r*7zY*$)?6iXdM3Kb$ClXiIjDJw9A_Ux= zRs#Ut(L_3l;AnHl9RaYKx$yuCJc@q~D2eU8SrF?hU#t6gP{GhDcDDs{VZF^|AK6ml z=}FZgbVc~Apqfi|P;B;gw7eqlXpoFTi{rjO^`Z2X%jot{IX@2C3K}@Hde|1r$;>|{ z;_tXW&U}bi8u7i{8L{%dJ!W#()4R-kxLA2V5rCfHcrRMfKpxg90N;ln%Yh(*t|p5Q zk6^{2MRogqFc)VBDjGGA?Cw%$&$sR4(Gv+Lm@Fh=u^YHaD0ELTC^KkMoVo2j+oZdW zofdh5)s@=?F=wwvvS18ohQt{DZLrMSM&au4+1|r+^ljq%~1|WP%xRI68xcaW;7tK+UR~XIqG42S*%B? zWzq3Oizvi*B3B^N4b4d@ewfEt7`RwqC&w6p2I8+1j$GYAz|OO%SN7pvhnBYn=Uxep zx7bGQm&kq}9=L8TYx%f*@km!gGjl^ZpzTPqV6u`A5#SM^7B%W*sMZvBTqXl!tK$Qc z_Z}Q?a7{(}yzY$HL=P(Wmk3Pd1%?9P05j|~s=U~q49TZ{H77pOet>u2P52zzj2&HCeSudXMTYUpB;oZFr51I=acgc4zU$6J$%}^5b_veEgqHPy$KxfQ^ zKXF3NdVyXp41o5cBht{0D7WJRl2d_a=nn)?E4@8!%HwFwiQBn`Gx8jfnQf|U&k{11 z7B0VEKEFIYL=JnK+!p9{<9~a-Q+-7HB19RzBWM)HnIfbJ-7;3LeKg}|+kiBeu4#ua ze}Q4{MXve5T$Ch!xfL}buoyO4!Nb4kkFIMYEOLj*GTsw#KzeQUi73$Q2XEmU?*Lb_ zdAXlqEzTqBJxgRzK)}g&CtQ3J$WEg>`fJI`6!4@S656F`Ko=2ro#;A`bZ7qD6F=BU z9}RFm=~urA*r2k`Mwn**zLC3pF95o*3Uki3+)vCD>#Ms*b*2R)!d{_2+^-0Xv?<(` z=o&|~Fu-q5WgZtkU`H;6eqD)NVgVrA(>F^1?Zx*Zs#&-^r7Z??GN1KQ?Bcv3WD*&T`3XbJcw!#N+3FO&$!n~D=nZ`GGh z87Jk&)Rac)%&bq_$_TXW`mEDomO*K7b#ku51Vu|@h$Htgi%ODo!vxU@W4vNGqT{FJ z;fb2&_%Qx4oG4q5pP)m!6Q;GvjVwr#Qk#SLw!xR_ggm3G>zjV(3Fd<^6WeOKjn!Kp z@|Ss{@Pf}*?vBDD_odNI#&ma~5GnGKl-8k{;R`+UG(er=Z`geqB&-Zqwm-SivRHun zK!wEl9P)xH7}g&M0|lM>>tiWgLHmxUwfGW*3YZe$mxk}dY)~bhH^t=;(Pe_WKiP$T z4*DP+gJ>L*TxBa@m9LQ`>%A;LCa1KLYZg|dVXk1F#W@TrFXt?vtRX(M$CN6}vI19@ zHbxZ<-f;tIz?wRjF+wm@@K+?&5n><1hFz+~NG4-|AP#&xQp65^yJg8+s6$;73w7)n z3eHW0VxGJNDJ%-l^l*->`jA#AetsRDnMsTfs{*GnYr$YaL*HVH#hD;7)ali%WF%7B z4-7j8=}{y|*0A!(cH&1iV6x0oLYlvodN!chDJ5HbT?z3 zw4g0av5}8*9UZn;0hpV$wxAMfW7MzF~&A?+Ri&eO9fIW!BxfPn_!Rw9PB%39TZEaADZ{ zFqmM5?>;QX0IPnk>~^XQpOx|kgDR5=z@<}DfjO5rUZ?;UIhs}K+{o(Vu5hO1v6Hg7BnG|8^D9Ll*YOos>JJG*o^}<; z`Hh7`5UQKgv_oO0$Q#k53B^pthhw4li2hMOUpbOR0bMaJ4?|Wu?K~1pZqj{!q_61~ z#bS6Nhiu&HAtQhzYZ~LyxdW@7Zw}&s%9WNKIAZ65lGhPMkN}ClY_d@G^uXae!BLdc zlJ^|IW89aG_vVuoxa)Bt)(^YyTo_j%*4_fRB*{!fe zKZc!0;1f_N5L-C5R|h6Dw_!6s(>4~hjF%g9>Fp4Ni6DHVi0&&g{G`U9UW=Jp@g1r7 zYic#gseTfaVs#s`925qc8R}c>#moC`dRLpz(+k<>j$unIu{Tb%Uzl}zODU__daouo zKn7e-LR2Hztqp{NWb>^!T?QYPx=YmjP8)$uXEVDe&+A)^V?)0o^Um*muPxRr6nkCB zAvv2F#Zm#yS^X7zcgMZ>+h%jfrY`q5(&CADDVgP&sq0vWN?u7H-V=HH#@8lZ$R=KP zmEN6(F1ub6pHl1ZU;_YJ;X`g;9wUKf;V_!D`Yc=tr3`62((WWDCXO;w-mne&#p0Nu$9_M%Y?xDb} z->xtjy3!NR7dq+eM?$OE7~P}Ykz9BKpQ;+JSdwR00z5y@|S-tRCPnlCgt7=8X;axd;t6xa- zNMp+nSdSSSt*7HQl<9+)bCq+Z)_&Ua{`?t9QZJYZ+iSGQu>2FM0C}aiJ}4OG@NTP$ zj-p;iX!eC4RMNMxci>q>I}Y%}Pxs(U4=vsAJX4^)3%+Fdc}lM7lQxB4ckJEln#})HF-WCThdj5Gia6=(d>s9WrhF_W z{*OF|MCs|MnNKP3U0-Y5AAVvl#Tk|YTajkw%)eT+jYU!BUt2;na0Zt{*; zjiIihFysH!_u#Uq2%vj2lQR)=hA8GyFkzy5_BM~9>W$n;SYye|=QB7vrcZ@27u&ulvG6gp#yJO5Jl2i+({FG=CcB{N)@w1R>-i9ibOmK^ zgpiuaQ+*4S(p{0F{09lRu~day4HCZeMI2OR@()4vh4{+aFdpIwF6q77Iq1*u6@;NL z7V;K*ysK8g42TXWmxV9+?m93?L-xNE<)v=07<^{XE;2?g^JY-9@xIxH)h^(QvjiKT znmXGHi{Hp?r9)#RPWsG;stf>%aNIe=&#ID9IDx9b_-y3hqg|pM0aNGE+(F^0NGKEl zX8Ai!)d4lJSW7Ni4ct=n=aq&TAc`atj!8K3YtBanEO2#EVEgV@U6#1%N_A^};ULoN z6y!HN&Ws`BNU?n7i$f|}*|vGeMoOVzD@7s?#V!vW-9CPyfB=elF8^dnPfT@oew~2q z5I3CS;5=ldoO->z@OQJu6r4M?dHoB`Z|K)>K91;0NPW6Ppxo)k$#U%8rjo%6ht(F( zYL%5a6J%*CYFWo@~0Yjbv_C#+^Y8_ zCH5@=*OP?N&H|G_ikh0q_$)4}4+s(p8!LJ>4QOerRfc*WG%)9_Ycf8uT%}aq>Nai8 z6h$^za=tf5(hyi9UFR?R%x&;e$RfgyYGjI4UDms@dU+CYH1Z9{v4nEA5~E)>F-_?x zV^f%m%Cy4uw{q=Thk}68%>K(Q&O-ZH+?)#y%u$PLMssteE}ySq&x;APBm?Ho${Q+` zYMxc;+ed%S3g;p$?CTRE4RH>_{eW{-U{Rr!CttOVz-A#>z@~M~V`o*V)4Q9#YtTqJ znTaXJQbCVolKQch@)`Y#naX_k{M6H7$2X;u^C45_%p*3%uP^P%i*+bxaY-`Lp5BCA z9p0`J2E7YR^8ZLnnl=%KR-g?B7ney)_+GMr#cst=8BqwfsL=J@#E=EDTPV5K6eBmR zXKGu>z9Rm2E6)I&^^zcGRYv_H>}ukqQXiS3(04rJc2iu8YU^BbT9g5Tc0D zXLw`ifozyG4ydAJ9{cG5*iPxyE*nJMo)opT-l@!=2051&T{)9H^F6Q``+8Y|(M^1d zU?_!bEJ=6LqfCOPb+u4g>Kx%TARnYA`znb55mpXbzxP1@%04uPIsl8M2hX5l&?HtK zpMs(({iEda=+r#r)qM<0?g(BYy#p;ggTnevZ>3@-){vzu@k)u5I=eF(LdezAeEyO{ zP7HnaN|LQszoMs{0R z=dx+9iZ{i(L-BC*ZtXSE5w6~kg=w`>?G9BgR$${NxMRBAx~QXeEQ)BK5Nef}@z87G zW8wP;>}pSe0uT1j71-I;$b88er#`8bah~wgG|5W6Hpb3^bi$a^f*92ed71o^3KWWj zeOsvYa<3cZJxtUUp3kWzIz}WFY=vV=(>B)D0_(S7c;fJk&G+sLo zv#JSNGw?vkIs^)+w+0;5#~;k@q<=4tApxvNVm)*ibX)_MKXHMd^iMP74h32o+`-$- z@+WiSp}!d_&Irwr5yxbL3WlYz?8{s;dU}c1EMvl^r>^w1tZ&RM zlU$tdJ?8cm-iEW%+7Gkln=9G)(kS$)qcPU{Ghk_#r&4ZSiAyT-^m^zr3=}yN?0DE7 zU0F874GX#lZyuHv7uHXUUy`cSePbsJ5KBPJLxdSC%5%_(6K$iddoiOrYl|>w$aV6D z5k?#|P->#bH!1u)tv3DydnO)=JIKN(-0!p!VZhtbkHKcy<6U6Pfzi9B?!c@JV02?D zv%Ae+%iy)a^Z5{@2e}vLE4=Dl<4e!4&!mU14Lfh)usTB7Q8-8wtn{%%cV`>kYKxn8 zYSle&C!_X{{g^vE@-tgmqR5fXz%)C&?vswnkS$I`yP}PyoB)DO7wTu_3nht!sX0+4 zLDI1WTOVjk*C3em4?H?@+$3i?@cz^$DP>q+FZG`yTMoNQ)L>5-K8dqtU08T&K}?G=KF0cXU^9D432-?^pD|}JsD2mN*a0FqqnHFhsH%iuqlH0p4yDYoM6{u1i ztqd8f!%iGBu)niHeaqjhLWzuL)kBFZF)%{;y(4YQ*a|l-ud3LT+vP!Rz2w1AD`0~$ zL#bklYt5H+3nA%vC}e@Y#cyA` zU|Z6zZGyq8o!McOqQvyE;}{a=7yilomVFJL8|f#>Y-mEs&kSd#@l^DV(}N~B__xCy zw&VtP^AmV&yr~1=S(J<&T<_6}K<-s4jV%X6tF;4-e%Y){WI>+gW_%kso$N z9vQ*ND{xPO*dvYKtP-GQd|X>R(Pf%5L-OC_+qUPI#=fw!JX&sTNVuP4=&pfPb#7O( zMN)%HOVyWVPK!%Lil8;E9Hl4IOKvM4_~X3F|IH2+Ab*Y~bVhWFrbr zW~oEaHS;=2iZD-X(s(ksuDlXEo~LVg=C0f2{jhjYFX{>R$%%*2yo<&T5iwd$ zxPsl#s*O7Oj*eU!FNlbUW|x*=w}r!R1}~zGi}G-cwu-;PlSm;|EB7OZN(<$Kg<3O` zcD#w#P78HW1Fp7G`GtigTb3f+8jtdRB44Cbeu}{x<-kX=Ja1n)Fykg%J3Pb)_@Eln zLrgp%foeemqy6Je-EJ045h(V3w`oEUW7erzRu+zYw{eAWWsmfN(}4bVS`I3C{JL(h z@=PLKRP^m?C_3$^6VnOcf%b8ry0Q`83^l?m{GL5TOVEU0jv@?SajRh4QJzgn#IQO;f8UusEKC~pYnn6O&SvI^`;Fl-BEWq8Tmw|W(mI=i$0)qojHzJqSs zDiE_uTNj?19GV?R4YJ~jq%JJ8XV=1)D&zMyMJ?pyCz1^l?cX2ay@giVHUu0ePtwKv0524zI+n6UC|; z?81QTv7TLW3CIIPrDAn8xwWS5udk~^RDU`)SPhjL=Ef5#HWenBIys@Y8MxgP>BX-b$eB!VhfP%e`oG?CGU{XM`fTLT< zcbZhO>hAhe%w{yJcu5!{#`L1%_lv}c_)NZ%5|fS>XN)a$Ry@WUyq8d6w4>lF=w@zR zGkx}tcEZHL$iaD<*dH?$;L=-CJkUlB+q;z5Br6p1ZJ6S}%JLUj7F41+vpY)%JClVW zLX4ea)*YT5w0G}??kSAD@lSP@W|MR!p&0a_^C57YdUx3QGS)W<>Rp00w_#aMmfOqz zC*9}f#-Xoi)SnV(#jnLeKzf_$6?FiUq{K}ah4fsP%o~V zrX);$c3rRbvL6(H|5;|dUL=;gGyP;b7$20V7!sqe1Zh{f9H1%ciW5ObW;&xOV zQp46r+i!T!5#3xg06Hs@x7J~TmqXU5mE8F5XGd%!-DMo_@Sss!T#efOqS#UDfGAB> zse_#1NyatNbr%gp{N$v(*bpqeLuOW=QCsp7njctVWjwxP`0z#F)8*}0){pQ*bSKlt zzPqDfAn8hJmy%=z*%8G3$i3TOUPLl@IwBzKe~oQrWi=Q&`4hucT3l*l-cywHS#qw2 zR!`XxrDZKHV+#9=k$plPyTB~@^Y$mCughN3ZMuWXQetUzw%DOFi3~Lo;7{Lj^JhY( za_*}$st%5Dmme}9S0x3s$AbisGno$S`;58qDdQ<)BcBe?XZU@dBrPr?L^6zC$cTN* z*B3&x0Vv7w`tWq<5_J}Mq`|(L@0NawpxlWbVov3TvPLf6i(QXjNwI-H0+mA^C#V-| z(_T6aHO~+E5AAij-i9!iAPWL{47n~wOlt}6!%%jC@_ez3#tFXp8^Q}Da;+$5x9vBP z3NVhoeCXr0PSkm<@sLaQ@Y~tZSHqyUaS`Ony$MBMDw5wIjaYjl2c`z$t~ca0q(eEq zhxHRzZHm^b<`0wIeUWL~AW0ol?zYJ_c8)D65>O+(#t1omZOvW>xw{;@JrD$ug&+PByioCOIR>?|<0 zH8p&+ODldZIS4^mH>xX3zP)bHG&a9w?rHf{2;`@XXjXUXDDp_gR5qz-cl5rzqv*~T zT~yAja!D~=Ck5O5FU~7c;x1sJm`t?o5^u6(;hsSMT>PLTbIXm{RM!$?=!CTraD%F} zlBHn>6{9w&Z@H4>ndj~jP?gk-u_y@NJ4E@eMnKWt3?t%$hjY-fr4z--^1@=@hEqqM z^O(`t3(YP`hec=@l_BSw5YFLx3X-Z!*qrkPVDt*`Fig>${uL_Jwwq@>y>TVxe6@(FNoZ}C1|i%h1g{KEBi z8-8|qssFx&e=bJIg4cd0Va$yD`oT!^=MMC4-o^{Zys7;l zH>hpm91;KMf|Ai8zM&5aaW?Ay$`_=q32}~IZ&^&UvU66?hN)(w>NR|5lhlO0A1IpJ z2w5y*H&#dd{cfh5-l)r|1TH5wfOXk6uArJT7vesvl`nPs9*FfG1l(Bo0HZX%2R@>X z#EarqW@fb0Um=0v3%t0H4JdB;h&bw$(nJ@wI?~o+-JmCLfGL4+j=sOT+=D*0=U`zQ zj}f8=4?jE4dNAP?Mq%C175;oTdO7froJ#Z+@$;s-rUdu|QStJ&*Bn!|+dh|F1-iYX zp^cSGL=%xx{%`{b<4gKBAEcWWKHcBne{DOkKXpF1OBkEmVFk^1Yax3btSIBJTs$YL zkzx4MwYFE3`NI2vqS5mliR=wVh>+L8mpnt@(4P#QtSy1;_VC$7dvM4x?8c0 zzGl@)uRmaX@PDAt&E5)Y^L-%Y<>e(j5GSxKLo!ut*!=#fPETk-Uh&h~(nU%}^j@}u zJ1;L7-l~MDMB=2;JYcEa*Q?uqm_v$Gxn79G?{ctz$3clElq2E>oh(UiD30dME6(q0 zOE-t|^;sCu3qnHW|7W)QKRozp$KjY8Zld3#etdo5wfMCisU|XdcdLUQx0&sd{_%gQ SitM(%+eDXx7Kz@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007 zbV*G`2kHkM4<|PQe33x_03ZNKL_t(|+ULS<)=7W_L$=0{1&=h-)2(iIEm>PuCX-9V zTYU&dFi1u)BACpjTJ->;Dw)h+#QSaEZ++yazkJ~EZvCTO^xYP`V}N(-9Rs{u?-=0S zddC3oR`b>IZ+t%(pv8MQ?0kTq9DISF9DLE}A_U}WAA<0e|8~6JE4Pyx;a zq>=dP{XfKCeDhzH6MgshaXfgA`#Zmfz-s{jJ_PX9sq`~n{P0hqjRI!^0Ptu3=RcmCq4FCzzy9)@ z|AyVpd-&+iXL$VbD|B01_?!Rt-?7tv507sCKCHDMgupom#u$t-2t5x{Nf-wRXE9bI z{OZY{73cwq4Syf~_*w0Hy}9ubLT>|{3Oqmi2Gju$c0U1Q0v;9F=f-N3{lDnDOBvwb z{M$cpceWpa5CSQai#X>%NTRkpuZ7se@R<+i9RBj#{|W&3{LarIm4KJTsW-5Fv_Im&(p0Am!GBcP1KnnXi!Ot?{TVoO~WDFl4{0x8h^v?_b-WUxK0;eVJ?Y)mq(1kK8`~1W0Pq7p3;_qMn zZ}jEMr3|p$-dm0*=Crjo8vXuhH4bqOG^gr!dv~$Xx&cBc{`Sc+KE3yI0KkjWeH@RT z;-g!i0{{+szlUCH8=t@TuK)ml^$-6U0pG;Ky-(2&x|8RhUe`-8hnu}oFGr7?-P`!; z_*eM!@C$^ZmA!v=`+fZS=&$i6dV)_6zktsJa3O-F4`z%?zR#NMy~sv0T4KL@IHO*l z_n&0%*@;9Lt7jw{0NjMntTi~?eGgh`JU#sqEz!e%?;iSR#T$QP>o%m4cz$vp+Dhz% zyKv6p!`&YN0Dkl8Zx$F~(?7ruZhclsNTW5F@EU8DR05?O!Sh;h&cd7Q?LqJ3na_T3 z^T$*Be&Zu(oe0)2>f@i@{y7BqXM}K_X6}=lKgP5E4R9tv2?hBN|Nh@O&b>_ir&?f! zyD10f)tmC9{}hMagVNuJ-7NqBV-&{N83K1VdWpI`tCqHnjV?x`AP8`kBtsnuYV zpNp`miCNd;)@n#Oz3F-4ClaawR5QRb;sbz+Mi4;@#wzSGSFx8z-AU!o_QY%z(H? ziwR(Ym9A6ZCcuGbW&^ zgwNZEV*Af0ud4@5M(f0XrW~8wH?X&Vn1R4|tHL9QM;X02p)6>h|AC59u!htK!N?uD3!1JMHJPU^X7RGV%9u?fLP4s!xTt)oLwS)E@wTr}Ki5Vn> zf;#}Z28dY&=rCvyH~{+69+-R&eEQT~O}rBUgY#nz;&99Jbm>9z1>4lSQN>5 zs`;-ZJ24o%S$PB2t|mn;8fXpTI6j}&qYRvL#A*c01!y>@fR!`kNQI;*Je_C+326nK zjzD+-YfZJAH;LSyzIp;e2)a851p;E5F+eNu5Dy1)>M0G&EJ_;n0w{C&L@siBnh@_i zlJ9#{X7bxxh{m%a^jI47b`Jm$ME#?Tz{a9qIC>m#mr4|D)#tp)S=t-^1uh1f-SKm@Io89=Gk)qkG&6?Y8)2)ao)T#Zj)RCHki zQREc`L5Q)8>N5bP6iOxFB%g<`^1+2G-q7=^*_0_;t@im%0H1D)pD z$QLyyT_tFi5+5i`fQ|aEOAHaf>0H^;xMFlb#nfJvceGI7cO-NL6*eDt;eawO)q(70QF+|v# zi7l)GGOyAU>F9K(=H$A9n)83F(zb@u(Cbb|oceCa$N z4^9zwdRdt;@jKuY5W>&Ghcg$*#jew)$g5h;T9CJ_5;({N6~#~Il}M?EsO}-P|<9&M4Em^t|^u= zFEIhGptD3PnUxNw8&5vOYlvaxuiOdPX%y6idix z&|qKUnHIIGTtMERPoCA`>})pd?1vq+I-3Q=U)(9)>;a<--^8?lfdlaU<*p|ov{^gY zdVB$t=Fq4>*a>SfK>zG?f%tV+TIw~`c4WbgU*?{YTx&cb6g&+_x*81}ga<2CrDRsX znnu2J8Z9hZ!_fep_Qtic@1y}3p^rE)$4!zox13Y9`1=#F!eAbROaZz;IYD z8Lhy>@N_zeDeUwhRe6}z7_;(tx^k5`Lrs8Cz*!)lsUsYe(%OwE^HocX5*X{CZIedU ziPy!J2f@;?bpPxW-Hl$U0Of~cWGu_b#kW-jL3v<;t&sFci#rzHpX4^qXV4Ac3@jMz zTy-;LtbQkw*PhdY^$9<9qtjtp^`f9Du98a5gtn*G%=HFlH%17Ub1;NlShGMBm1_{= zY^?^>RlSB;4hd&ACK-BBOi&5~n$rMz?IFS*n5alh!9vEP`b1w!*lwd|?*ty?cu@;< zHg_OL$@?@Nkzzrzf3L$bQY~#PWsI#20Gi3@wfqQ~^rcC;)RhrG57L?tzZw8O#p$c3 z6F+p>E5)RX_vd>Ij0cM*V4m;QHE6b6){+(kVd(_cy!t|Eq!>?F19d@CuCSfewIWuoNmJBBS;s81z16xyh%v)IxW4V zx3OwuTizc(Po00+HH{pV#8pNhJOKCFNz32F#isH2>{3AB+KE6syj#tdjG`Gc5s%Nn zqhWs`u&~sQoHHZ12trKb-&?S?4w&GsUR$_S65436n#C>omahC-x8&EQhqY!hv1AHV zIpH4SII7GvU5GnnhHE3v)h<&>c&)GA)Ctdrk}>i^Pn}LGe4QL6sn066gmF;TO#0@l zSh8)SeyN+s_~kOBY}gi__f!(kW%?>)WKO|((u7y08CFDo+4ZZntxm88nHy9EoKFbAupO)haXvc9*?^?oAl#XLf!S z;-`RcQ7T-e6t5hVsd-4HgQzvpYt=Ix-i{K7yrcLG}kF%=&?dcUv=LvF3d10Hfa2AG;W(6XtdsGngDN3Q{qmPDg zQ0N3-=y82c&QU&m?h{|?+SQx#v96%cs-6X-Q>dEE2VeroodcLL0i~5S zY}UvHz((M~X$e}xmQt9+)tl^Hp7>?Kp42t8gkzOyx0U7XM$a;_y`JIeI>^8J8ab3s z<|MQbuUvj%lnov!Fr)I30no`arNs5`!RsHS*ktK^6s* z7$xUogf-NE(o*k%)JQNf_V)JJX9}Z2ODZLyw7anH&L1t?n0m4-c|cihfJ#dU?N#*V z8*A{7VHsmDw2Vxf`dA>Zt)v{4YXIw9t%D>o3{j+};&FxfU>Ok17hhg4>gh|@7^|9u zRdNh`6}MDyK;`zuUI+JWu6t%(mAmUqd|lRxr73K*Ng2=N7-fM0Oq~-%bRO}W8Moq6 zgGnTwJeUBX1X4+mlo<&HN&;NO?_Bw8gNr176D`9RU98Drj7u0HA-9>iMBdNU+9LV> zi!Gnd7n3M$CI=}@;`_v{O|28kW^x?gr$tjRa1IE9`9q;Nr|<-Yjn9^L_`Yq6(eK}} zbUcp;*WH^(aET2R+=G;}j3^j|9Q9YaUfx8USNhxS7KX#ox$faYH9+AnbPTG?Yu^kJ zFr&NU)FAr!nK6>cVTd*|)#QpRKy&e|Ch$tYQCRS+Q*o)^NOBzT$# zGA;LA6->$WFG)NYa2W8ciIR}3RFCK1Oy?|g%^C#5I}n|{guvcn#87x4sPI9B55idC zKF%}5xulq~iN0;Fac4ka5f;!|!deZ_Yb{L<#R#%aEEf;52aE^D$ZN9n0Hbv<%&Zih zuM0Pon)G>>t&MgE)+Lor#A#q~Iww35);bWcwV<0g)J!2w8ph=fv`Ue-OLbvWOjp@b zlWvBTqveGXMkcnhvH;@zgcm^vD!Lf^SSO}IiOV@Si_c??0Vz?#8Uo0f&Z~Aun+=JI z%LhKX1|?ikG=@CK0Zqf$zyrYi5N0wJoOrF7&0NN;!dW=jY%WqdXel)TNo{{QQ@noh zw2trC=$Y!KiyZ)G9gKBZDOqxV-o-OO5y#dkpUQt`UHu1X*f^Cm7Y~xkrkaDANI?=S z0f7Z2X2zT=;j&)9n~cYEK*j*`3|m{1`Yq5rV)Sw-vM!QjW|VPo{&m^zOrnJ@CTz1pa}!erJ!wDjXu35vwGK2*lGyLUNiHODg!|T$f;plH`F{=n6i%Z z6xWUcG=OD!g?#j_2*`MDd?{((b*O)f?_a35!hf8a0MFyqo5HDaZRSV3aIRWA0&N@xu46**;DQ2qBQM1myx)u~;J|ew|tS z^Cye=K>)bqjDdLA$M<2KXU0I9_u!YMYSJTGtX3dwwR3#JbDYveKmY=ef+AGL*z)7w z2*ukzxn!vqu!{8O-wVU#F@trT&m)AFjXoQW25T!SO^I*F_X7l01%~p!udM-!j%!Op zsF$4yjQU4l0JIjhJ7Vjs&V<2@F&K`9D{zubx~tjsonAr+&5C%Pv-KHZ*@>N6DO}dP z!Tf4@0%mf61DUurSxPh=^_~ZPBw?1S6VmuxLknjd)+J{GFPm$W=0nI8Gr+Qh7Nsl` zSVHJ}27_PK37W(Hi==OFLS{!uLiiNP6FQmu&obh#79e79B8`eph|jL)kkzVG@WQEK zO)j1uL~wQLYud+ZtV=3u#sla`F5r?V8iO&u^vK)v{NMQ#Hk@@3LO`jv=b*?{>pE#_ z3rx*ZF{O;5wQd9yFJh%tG`2*tgCJ~l-f`Y^jiXT^@!!f|Qw7uTDKMyK4Wc-@P$CN# zXTu^ELdeb{>c5!fU}qMXpsuE3G;#k@;-~*!R(|6unog|MGvRwK|^V=vgWipwM!Zr8@HorlOH?6lNyjm-N>AeDr%27(JHtuB|qg<8&A>!8a*qUXAqmWACf-tav19QpYTt!o2$W`2y`NT*5`1%A;o&S{bFbJ~~IL>X(oXZ&U!nBN_P}((4uB9V? z`84{KBxvje0h0+?7m6e%U&NdPph4!O%9Sv|h2Vu13RL})xrHe%P;=OZJDGVIsoGAx zloV@BsZpGrTcsc-9lSHIEz)aIEDu%Nsw!>9K@j98g*t#FLl#j$(uKcARD#5(&7%3u zNNNh#r}~;y0MBTVI4Z3nNMZov1w!P{4Xk7^j{yY|-;@d3?Ox%Cos@kC$HNTZQQ}Zm zPg*tah?lANN`Df(^rY)`Ps1+b;JRwq7z@tpYo&FXfeYUT5r8m zLWpdrR%iPF@%RiPXaj`8stACa8O&XIb`j%=21wn%I&z!(ltmh#Kh$8lv+0}zr38$z!eWnr zDxCCVoSYR)!eFdmt;0s!Z^&Hdn4S$Fj^bLxPuG(tiHiK-gAXRpZ!7Zvbq=}6udTKR zV-1F5h5j&tRytugN+EI#gN+JZ0-~<#u#>Yw!s9Ov7;ybQ7Q4$HHtMDqi6+7(y_)Ok{Yo}dhZ;PakZRL z_=3UrcD_P4*q&0G6ug>6tu!Eyu{4o5IrPlSR(cmlnUWrMAarC_u? zchK*j;nm4mAut|ejI%yLyVFLy-2x#=wDZmJNo6Y97=x!zpW^P_yOm6-P-}R5`iG-4`RGIi{K`+g_o6sosA>}XETQ+q^fK%Rv1O9 zICx?Wq%t@gNrXPf?#?#+0#4^%0Bs$twfOG4@6I(A?&#Tb?Cm$_y(ktRZmn zW+L4i0YaYx1q5);;qx|H}zN+_v72!U1#uV25$-rgP< z3=9}x6+i`^J$r_;v$Ikh7X$%18*Pw3`jbDdwQGa`ozTPSAVM@6!A_=AQcB^s!qSni zf>G>lwP(tyUZ0K|O}C_!VsCE`yKNKK?*C7`7ZMuP$RZ%!~c?PGA-FMWBB_&cPX#9Q_&(VbvH;#|wRf(P+Ft{8S^Hym?bfd}noXeWMnJT{-8# zvm3B#hUg9ep&W$!03k5OAR3N}In+5sqcOrxd)6LJuKoJOi{y$fL8pWX5Z2sH>i3g| zj+-~9r(wT(^(wn3XEk6{HuwRACeJ|m0=hI>V_Yz~Ydjo*3xS|j6uFyB2AR8-bq>#7 zzQIl}M667qX)BJ>NjRfsqpc2bFmOhJa36#TM58hE60`92@4mwAgY8Vvl6{wOMlVEi z9U;keCwUoe)u`~mh>Uxb0jQ5?G+wHnoO6iB5yJLlV1tn*Q$rk_j^T^~6=7r8-|zPk z1OYZTHxbA2#LhW56)&DR;tZTMa7fCvQ>L@lA{v!P`m|Dr#{_;D%t+C+J&Yt_S|(<~ zwXaX>M-QDESB{@^I);oTw5pEKJUu!=Ya=m5%V-Mck~a1Ub8%DvCubd^XoNcW%4iL( zG#GUC@h{H8sxhb+0u8%zU%q^aFbuN*iB(ZW@1D!lD&aojaa0Kym6V{2f)iWtEG~J^ zY9Oa2>k~h!HG9w)2c_znOKUCS@fdqji`CklMmVLkLg6 z4}xSPa}41iLBtfa7_A}W7|sEnAdNa(jA_29)&bf$a8{w>C&aacEr4YiOAt!IDiUZy zc<_TTIjf;Rnzqw7+WQ*!3LsXAaC7I9hfD)*dp8f!YHuW3W-LwL~O~t8?TyLg3R< zs1SrL+`j+*G|7WxWX$Qw37#JvLDke;)>enqrJ8DX@{3>m!UbNkiTek4u(h*S2r%9p zALGg6$Iz-CBLv=J;pU9H7285-6r4a5Xe0-Ual9CxAOr|JT8Y7&OTM$oVvM1?*+Z+< zg6|0c4rl#S3`+`NBWafo{V01j&ku0-!6R@kN|cMi^P}fDdiJcAjrRosD`8k`llz=W z1`z`6+_+gt{4^4`v%8C4Zxi2s`wdRtoK$N8i&Dv4X5W-{pmcG5u9UhE+&Txu$|9(+ zIZbS15QeyQaDd)sZz0a!+uX+EZ@9s2iV@-$Ns?`9NxYQ;fY*6g;U%-xKq2wpAdrE zckaL%i`Pry@6Ni+zYoGTw)bwJ)$V|E0p}c^J$;I!r_aha%D7C8X;Xbq_a3~Djc#|M zEn=LVp5XP%BiMO-jlUJS})`I0lJ&p zjm%Q3-NJkCKg92T`(=3m&n0{Bc|L9&+(Bn!V}5ANXJ!w=ByZDneX5Q19=2iV#!@6&gLA!xP1g;(i{-hc2QBR-HE zSGTjbj|Y!FL94xyG1ao?dHBJjTEx$TwyoV8(}zWU2FM7}-CSw7Mz`C={{H^bz3*)F zaPR$((AnrN1lqz@3wQ6|PZ;0#R~xWMDaFCz?WLP~c<&*$cJ>M%k`RJBckj)hUI6fY z9}geBk01Q-N4Wp+L%jFsW3*c3jJA7YuauFv5V(E+AzGc~guQ$J9yT^M8t*|FW~vHe zO||6e#j{&G+e=Nw;obL^nu_h6ZFDv^KnG{1E2l#9wq$z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007 zbV*G`2kHkM5+@%cHwl;k02lE|L_t(|+TC4ymZQ9ny^;+{RnIDB8?%ks|0;f6m4GeH zAGQfec-UZ)^l;91zV5C^0A1^OCDH%R^C0GxjrZKv=iJhw6+1SkaoC{+T1RWx1RFH=?sPk(j- zhie74TLyvME|r_gF+yM;PInD~-wU6>hQjG58a_7x12k=BzJ3|MU+W+s1xVIkI{Wa9 zQy(~hU<3$__ofIyN$*VO?m?+YI|>7`@NB|BZvheo_46{>41m)w;}mcHh>Iu)-x$7A z`;RCjA`mI`;XX+6K)_N#Luq;sw0v4NyaUw*^`D`oyH-KUu>JHs@cxHBLihwW3}YE= z=7b+!5L46)Q(qV0>xW?%PL?^=x7#fEr12&njWDbJr!+y=D*TKe!=L)_gJ3nDf*G(8 zV-^4jsOKMsbu_EmKl1sb*_%RuH@fJ9O=$wx=v}n1-v>D8QUz2MA^=2zd$T{7gCuk! z0yvzft0NDupP+7zIE0I~E^!g}7etoz3Bk z1SWu)httnY!8>0PrUq}GCB)7Ez?lx)C1?ZV=`cSgSKS9kHmdz7{Pe_g4j_$uFp8lC zjs8oHEy)c8G?O^_d;rXvig4mp0E$x7Okvud@GS;YezXz}1;tqC!F*wG_Qt+UGKG)N z#DXEea_5XI4MHxt|9=($cR<)6u&J27I|cK=5_1|pq^zk@q(I5J9SJ>wVNUbS0l3z+ z2mo&smoGunGn($b>hdKjd7NZn9UR60gpgzB9jR=JQOgkF(7f4GYy}L%0$jRmp35|d_8GMb320V%QAO}4!w#(C?&drO?c7( zln|rqMVU;qW1CRCc}(?Zn*gPdQ0N;UfNU8`UX z>Npn+stWIu@O5xp$G*T_CKUVS&rGn50TJN6?Dql2KxjKc(;W*0iGub5LXv+V%h-giYJ3d&yK@Pr+wsqGnjTp9BVt+Mbbogc#x#>VT9_NdGnXGi-$OrQAtMg$>^Xfy>V1^xnh{3uTv)mz-yB6m$X_7qle%bs&h3@-`zkfR@AC zakcbO;5pHfU6oG3LtoCo_g~5qx@&?;_Zv?6yzutN@GO8gb?!$A=o&@WcvwehyIcG| z3j$FnLb#Z7_-!nh~tl3|1B3LDe(1U z4#^v&vgfA&>HdAy3zJK(F$k)d03$*0?R8z{hYS=?df8t;^^-@YqR?uRL{1$o_8hzx z1hl~f#M<)d%J}{dXT4}hI4OJ&vO+Gw^hkHS=Cj&S~!8RL{N~OXlBD5#7n8y8h0I->U2+ho> z?FE7Lv`hF?6znY_+v!>;{NyWTrhSjN>|ViJ%k#Ya5^h>g_yTXr7H$#N8U?#FBe>RK zJm)Ba?Y??2tI;inK; zrA&Il!1XLcT}6y;ItaG>Uyk3VYAcm%*&J$nuW-^%#O2oaa;|6U5Vaq|F3 zb&#cZM-;q!X2w!iyJ{Zy&ozqcSs*hl;U(849x(g!9ca*P$5{-Pv3-}MHvR2^ZFBDo zGV>%CEyu2Z{{&62^l)v@I0qqPlQ`PbJ+dt98W?Q=|Qn0O~ zp+CSn+T?AkDx6cmNpLPPgA;_rWXT)t$} z4QZwJmSNb#Na#7Mj-nCe9x=LF8lody^S=XB*mcnO=s zz`lvS0I4bD4c$S>`RYz#K*F3>Vx~zFsyQ6v^00bp$ye&ruDk8uWltLR#(Mx4F9 z%kaF#d4OaZ+U|YbK_TNtv%(LjNtd<41`763AW&5p=1IV}S3=Vnbf+-fVspD$ub2ly>HX_Y01Qz>Y#eO7oe* zQVRClA7=!FN7GPx0I3E5?n0K>9dx=-Rd&vvd-66UJDQ%BK~O>R!E+aU{nFusr;=%C zuLiCOZR}h4nbiO=&My7@(cmav-s2x6!MoUMMhY0uo9p|z*YzwAR{VY`zWKw&FK2y|@PVdXrltrVUPJZ6BaJ<>lvl zJ3pzrs@-qOMae=NNue5ukh$?^DtnfaM3+3+_DV1=6o%HOj8J7iKnX=FX|5;5_d$M< ziDUJ*RNYxO_yA2GxbL~AFR@_~Qma0^4|9pq^o=;wrs48Hz6@qbHZn6!JF5r zIXn!K0st6^Y2HF4-;o}u{wW{{{fov^a15o zgj^Pao$7uuet%VOE*oVG-%+8C(+FW=r|ARXvt)kYJBT60SikFINPm#K>7arCNV8o> zB!D%Z2Ajr0I9+L%tqLKDnWZ`#%kW;SaRpa3!s0fs8O>$Qz$5(EF6RRGG0hJ&OmGX4 zm$iri5 z{`2(gxRb{i{%8;=-O|ygiT3(Ljb8*n#a9RKH2T{*P^?sSm}hH74VlIoc<=JFc+smq zy4EoETh^SYcV6R;AyVM9akjjzsdna0w5r0puZD9L06?uoYS&m@R1nyUXAaMzDtBzY0^a23p z-AZA_^%OLN^&yO`S?NljF}FcPDAd{6YiJhTyClL)k63>f2)tEX&SlNGvayqN767@E zH=R+qF9n}N*Gdf_C;?)zZ1W;3h-JSiuy(W}L{kfQ2x)I?X+yHZ7={WC%MYaGm0RA~ zmNjGZ8lYfG)}Vs4?&)9q?BowLx_!GR8yZ4b9Rz>(YG0=EO9n#B$$)DCAen)j1xf=$ z$kjRhe&zI!zt>rSL^o$M*BUclae1S-e9La`qOuk{1B+HB#|)&N{aQYNa@is&q31~9 zo!6KjkmcpKil0AHg}Azf_h^>^u&mcv!VsrwkpN*>5}5UcRJ=TbPqCs0)Avm2N%ZTzm0D^f`rMny3KEjt=?lsa00@dBbXw)+STVl z==QeJG@ZaTr&K8<+V<`zeEz-V%$L=zVa7lE0i_eMh4U#LwtZ^xGoEQaX5vpoZ_2sZs6koi{K(?Mq`?(z7mU zfUU!}-Ua~E6VPg)U~k;|MITPDT6NUoY+kMKyzP}BXZ;uruzDM5zt5H}VgGL~Ez348 z@ehp)gD>0eh-Ou-4*&qw)4c!M)pUe5lZQYV8ZXWI`SX{nj?+0r1AOFRWW03x2r1B9 z8Ev;7^^~Ng*@rcJwKj^*&Qmt?tz-6I6Mh=}lomTt3<;0+Ge{A$jl4Lxadv+3iiWkl z$sY{8@{S%qKWuifkufa)FaY@014y74G3d|(Kod2A$05u$KtN!0&9pbaXMJ6$sv7id zbULXH07MjQV=tj0xL$^L@^1lP6pKr2ZubhX3EIHOtwoIDyvVd1q86`@6tG>eLtT3h zf*kvw^ZVN?qv^0Z9dtefx&Hz2w>Dtru;9zNFf-Yn&NfuR($C89Bf3W ze>zD6@znNVvKSo{4X6UndDzC>o|kF18Y3@C$@614(PWT6wy;@-k!CA#sdF+r)vC4= zm`Jaww~_s^p`iD-6TkKzUNuAM34f;x!`bHfuqIG%IxruzKSY1#BaBgl&nDy}pONjpuzpz@=sGyXl;B7VCRM=o>9g6g>*ATGdhGAYWQH7c_G85^wNRu5qLz zqHn9nu5toT7lw7ZX$09)5@?S)&pq{_N|smYW2TS@d|@I=M8h1yH%?5=+86LCjUluW z4kmi|rc+Nq+l2bWs{|rGjG%evINE=T6`V%JPFCv1r{1GDyh}=|X$&0XB|;IAu+?M3 zl~&}QFZ;&!Rp&7Yhb`J-jyXj%Vg6adiBB25E#ckROxcFBriSgtvu+|3dFV@q0K*mvUxvY zbrX<;o^I?+TxA^nfLIMGew@)$)T!U6$>zh$u|X4v7kJSk2l4uqDBNYkG;+1eZ?tjon@SVm9;o_1v)G;smjJ8erw?1pItU z*2-F2Q!TA=3TvB#+Sk;69q%QUtJhy<+Gaipj8nbEky(u((Fgnbi<9m}i&b}7} zM1Y;zmFJ59Q1_<7A}C#DAQRI|>06KSd<}EepR~%Fozif3yt?qbT1EnCyG;=uZD9TC9)X3$}`(b?o7u8OOfbw~qNnz%xr9sKEYCm6`P{u>Uydm%gi zbKdXQd%eqR&N1egqvyCMu*R*Wow^h>002vJ0HB8e0J3UIir$pQuCC^8lmgzAmgWxT zF2-(-E|db4a#k*m4vwzmmJktgF*|byGjkVm8CE6o*W4@|ES&t5Oq8$9U0kgl9U#mc zENqm%Oq8ys5CxP1Y=6UCDFt-BDIJXMAv8+0KlYd?9URTfpElU^ef9so@}{&mceVOM z^l$v8R_+eAhHPx??37Q8_Qr1JF4o3&f9f=IbT_dxSF<)VH=`7Ab8$C^X!_HPr3)k) zLpy6XbBKdZCN2u*ZpL#=B^NVZ%PwmS95VkJ4Y9Fb5A#S7l?b_l-7^{ zJs}Q2!m$6FjFhqIAGu)j^=0y={P#9Z?W`><3_T!r{{Puz|JOF3qJ|{pk8J%{8kOyg z9n4wS*m<8!xmepIi%R03dYgh#q_Cmo>KjfG8o+qNa1LX1Ifb82FLrP4SgN2umo1LADn}dg!i;st!mxGCei5sHZ z-Wu{S=`wRemdsCUw?6~YloaQLJYN6kH{>Y)Cu{#noa6sQoa3LYLyF~}t^Yy%BUVU6 ze>txvE-Ejo`cDcVh4aq}{+=vOh=M3PPJ`OexZgwsnCbs`Md4CxC_eb?){XZoSQrZ8L^M4or=j8GIEAhW4j|;N@H}Suc z2dRa>SK9BD_s6qi;^k&8Z|-2}2Dv~vxFBWrL{PG@_~TZGEZvMp$>w^8Gh! zyzFcc%J1g>Q=&x6+h%D`A6$~ z92{IvH{0KC-9O6pMX zlXtA*U_Nf(kKub5@be#@PZ&SI%GzN>>&fF5J_anfPr8r5GpEUz(QtZ00S~(0GJRe>K`*E zL~Dey;!9K{LL`U_s4~(Lst_3PG!Wn*bGNYZ5ClNEs=gG1njc{Dhb%yrq6(q_@F@=Y z&KMT5CO4Hdu*J70#hzaBQ`o>9VkX_7(Owj{1a1}YHBdlwWj!>8v z3Wm$xqRo$>-S7uFIjr=Ip}_4?v>F*-fDs5G=CTL@EORKo^GmcuS`Z1Q=E$xK>j}kD+x{2-h@HUDbVHLkk?KX~{ni7NIY+YFT1l*x2DsKG-z0OC6rv+vj_BF)Y2lM&@|}W)m_=}o*)%<)Kt~$dnq0`(I=?)M zd+f)FL_Gu>F>^ZT+zs5eApuMU}GNSVwnd}L0k!Z*FL~-dZg2a1`w$_C2zcteZ&l> z=2wS_2K!ZOx6{Yi>7utyo+C7FtS5+~-DM}55mk)k%cDOo-~pZ^uP#Y#6NEkOz;q=P zE+{WiEdUREAwhf*XsmcT0`+;O9szK~PGJ?D z>IGW~icOLrgCc@1q-qD7y?=!wi;Lww!v|U20B!Xf-$oq21O_B^M5|y2R1j=sINA3X zq2&mwY^?qSJ%>%2t0ygHw0!l+MKQIJ!hJ6q_tnA$Kpvv7Sn55XZlKg@Y4yQEt2qY* z7qgK4-X{cq17|-VQAzso#m*}v;N2-l5(cMT$Z6q{jBF_CDkyMhbn9%T2MyUg<$X$~ zr6aZ*G$CFc^{qSk+qe@RD&BzP?nUSNGnF;|iFo}a#ZGa<(T+>QLChxGAlXYI#p{-% zi@qbK0ABZBFA;YMC1*XgURpKl-U%Z^tI&&mPIbMqXG+~Rf2CpwQ!wP&H9K~4?5;V{ z_y)f_jIqEy2II|CyNG4CYYywscU7DKdY`EW+dQLH?{{=swJ4zFF8F>}@ZvMY6rA<; zfLE{b>xSTQ!=*ocg!&bt@eZV{a<(BFYh<^kEN@9pm+cX!mQ-qI+od$m_#>9NWs3fQ zRGakSMt^7bfP=r(sWrE`i7rXx6^CIG@fg0_&%(*x;MD`VWvi8i*kpQYe`*B2-?b@} zvK&kuNnUG9j{B?!>4v*1a=8U`M(p?*Z8IPtA---L(P*QGK-B1lN8)Q^8^A!v@rD86 zP5Uxv3z^JHr;Wm1azyu)64uWb^_!EQW^?8!@0>>;l3q4~k*U4R}VgF>NSlrX0zuRIoFY=B1{L`RQ zcj&a`4%0zL=?dC$5ZB?^3?XbY7uDw(W1$`TVmY2~{w=86yQhZ@{We&@+u*g?DO`3~ zhsREGdiMnv`nd@9Otp_XLx&>ERqMqV+J*9Ox;oC8#Pubk9Rv^>?zVuKZSRdP=s~%x zQ&o)WE&dW+`Z*~CheEE*A+U)!n~-7kz%(EW_P}(j5Wc_VIkg^omyhI@g?@h%5hr3Z z?g{G9dEt!)S{=L^KzNq&^U(mQ!TA)Bc7Ips@e;em+oD(XRkIE0SS+Ek0vh6k+EJaIo{Qm&v(2FF&p66|i%yVqB~Jx` zX^<`w$uLysX&IGrOLqmy7MHB??K$@tM`)ZD#>;YlXfY<>C|m)u9rYS|x{wQGS+n)j zfMUa_0_p&TOKtl2a#3XBtA%d!bJgmK{5+8kfrTymvges<9WqYBbp1qenZAX&MXpNs zn#*iIK(x=*J_Mvdi*na!d=!f@2sk7=<@(uKIbLR?Ty0MVIF%;O;;Fp#)M~Z-iD_!( zpaJdoaJ78bFB$rbdvX8eSdqr0Omq7^7%*g{cQ)m;tyb3UXW)&6(zV!>dQx&6TKJjoxfo^)6I7f-Abs zwkj1~Z14VuB7mYIZb$5kcVLbBUG_AsOBLy2k<1bl@^Vu74Nw9H{1Qu^BXMg|)_6Ud z?R~;SEtsC2EUGMe(&>ulbN_8UxH#V0stT?W(f+6IRoXPbHp+5;H?c-)7n2nvds$XBeBdl`g2?=l|_Y%N| z3%FeH$cypK?J2dRO#qj9YWjUnEOl}XD;aaIFUD>0`*w)m=#QRkk?R(-{($j(L&CMe z$F!vp5DX`oEnskfwe)>?Eb~p-uHxju*52XEz+A^-!E{zj--M&UBK_jj<7b5A#S%Ii z+nnQ#K`ShcN#VvL=Z6fEq6q=pz~HM(P=PhMmoQiouwzdAS<`I4f`Ry=AAa{$shd8d zWa3S0%7BseiyJ_1b1KK*t9~(D;RORi_>|i((0eNAfT`Q|Qi{>4_kJJtlBk2EJ)k=v zMbHj6B8x93VMSOe$?*~? zLUR|gY%JJeGeyzL<|1H3Nk;2Ry04d_e(xhp&l}a3wRx`q1+veFUy4~j8DpxJ3AdoT zMtnPq;U}MZ4RzaKS02Ml!LH%jWogx!FRVT!wt&X_ha|-*KlMZGDlfe$%~ytFg7XP zgITXN^IH>qOYv2!{fDWv|GVbB+`vcaTK$*Q0o>Ve8NFhB`qn8GNE8uig#tuFM+Rli zu&=ngHh8KCM$AV#sP1N2cAziWN6@+Cosi$B)W_yxFQi`zFi2qUz>Jq#_vt<0vxm?{n)zVf9HLaJ>^YEnBbD~VRX@>1WcP8_rhrwnnh3ZJl05IbGnajF48De_FWQ_^u8X=Wyg0R zo8zYF?EcQ>|Bezc{S+0?-j>gbjktk-FBD-fL8IQRK@1yCZy z?`uGM3u+k%^XtP-^by>pXP#vPE zB9%)^I_w@*pNcjQ0A|}sLB5%Y)tcUOgWh$g+8_GRmGu_KUktk}zI9e#ROh>QrW>bX zvp2fs!SM=j(2h0w2Kx0XklY#3r7Tt#=L{P7zAS6}^&Fck_?#lTTzgM8hrLl$f_`d# z-qs3txtY34K2FOY51~avZ`6F`bIqp&H(cOL0&kYeXI9u8@mX0^a(XC}Pj;u2jBm}` z8LD5`QA(&Gdmval+FFa(bmNC1p$(xIY$xfi%qMf3o)YF7$(gT_r`H_~_Jk82GqP zOP+bQNcmM&z%wE@>@cZB<=`-jmreLU&Q#}HEsJ$PMR&sr959JBZj)=|xO5{)rdXxp zKDA+IP;u09kVI~IkB?gYhRC{oEScH((UFCDh==7EJq9_Lb@A6*3ylhN0GOU^d0d!w z3*ku!2NMvoj@(?Irj*4_@=L(@Y#E!ixZNNyjO!8DH`aerz|{i#xE7Vwf8YHgX%O<88O})&E#ZcxLY=P=W?XVB49p=23h$2=h2`gfha8 zlCyKTM5;zy=;*JIjNWMJuOt3|TNQ_0tzRv!?~NWre4BH6yU3WoS1mx|CJg%W2zA`Z zWAwdxZRiUd=X~}kk9y~~ndpJYxo|zK7oM_>+wcb5Qx`9!%uPso^VGTFUj%YB6!#6I zBbNGV&bW=si;xev%X`%F*hN)??LyubGF;1z! zjL7qO0gEw1Ud#lQCxX~ykzsxGp&Dyh$Ah+mpMX~Dagst13L4hA--LG3NT?L1ldnq~ zVOhoq-Hb5-`XF>dK00FLOAj*Jgoa(uP>z^OEpuT^ba*o2OMhzq^qgCZLI7 z*5HjXA`Vrp9NnfkN>*T)wl9YErMpx#GOCr}zGk~I)65lK{Y4{biV_U2z5N+C1;`On zyl8ai!Z67(Sbt0~(OSLTkr+Q$*DSV>T<@J&Br+GbG8zf-*!>CGI*!VDAc^Obci(YU-EwpGlHLhkz#^8s z+`Le|D&a+9t&BW7f2T3^5R8DK*Qbzy;u)3qbowWEVW`nxyw)fQztw#%EDvw(4Jkbo z*I0j}uL#Pj49Ph>N4Mj-*ex4Hk20fmvfc2+N+Y(D_~zAYX=7Qe%>Tcd4>M(${ z{hqnS@bwHVLflZiD@B8!ccZ?>Hk4P{=X52w2U#uZUzZhq zfg`rLu6BRj-52yLYSEiCMEs+uKl$%vt}0V}>jCCCkhFNd%w+gTQSZb{v$HMH1>>HT zAFR!|KfJ|viI^3!Um#WLOsi~?8|v`lak-pfIv%N2Iu}rVa4hSubb(gF3v+L>2FPthc=v8awQW;mivr zvHX%;#t+(E5lRHD%WrS)stnm^tcE@@blI`$QUeBEPK0pig zxnJgl+EmGE@xb@)p--Y%Z}B`QDB+K9lIWMrySZHIf0~xI+2VAmwzSqi2U@0!jbBm} z>Y;-Q0warZjeVlkWp_&Gk2~du55!?oVy! zJfe=Ek;l)w`O5|O%$~*-gU$&Bmbikq|IGm!L%cw8!)rv5s)TmU73#L0`J?iy>&;r< z>J%VX03jBM6K{XIlp^yYl2dVK@*=?$UL_7BjVkKD|lj;)_+p~ZrQFk-Y?>(}?%G2|2Qw>R68zbv>>*EsXe2GWhnq13rEFNEWgX`;Up zw0F7Jfd|NCN5(|x59?iWwI_%dB`^=YZ!l-AKo(# z!!2B%l0Cb}@3zwM<^_K&pep>{?+W>{t!fND&_#LEJAr?+4G$y{khPGs69p(=7Ijh5 z>zk8fP0H=*#vS{hx=!cR4W?&(bMk0ux*R}MAK``K{`t6sY|&m5ysHr2M^w?U-JJ&B z_mpIOv#;n^?s3EkoRIyZpFzj?zRzl2z4G-#h5o#^hK`;I!|ieXaiYFw$_=Ybb%C#+ zw@A142(H)%<7pl*Z(IY^(*(|6jOv{FRs&HwE3`HzrkK0aXlq$cI99}YS$mS?kzc%_ zds3`n3d#GqT=@>@2W5t*`nSinVH;|~dL#hG@iQ+q-4;AgvTIadJVKnbAtg0?0N>ws zS%>l(V{+WC^g|h9S=|Xuk}Vm@XJRpx)qUeK1F=noFNXQf3-hLk0v@$Zk#KZJ&p`ZG z4Yngcm9A|w=4&M7*@lfi6kn8n36Wc68WS13UTQTqjAeMfjZFVTpQKlt1Wt2@HtGR= zLl^G+S?WMHq#pptNGeKHiWvn#(9z33`e+a=w}Zrm3XH|D4e4#=f`7-s6e?f{!_z0= zU*Y^`IN-nNPq-rfAALFqJ9)?N_-}o*KWyRtY3m>GxC~M7pL8JLe}n(k*L(8qU*Z3~ z_Xntmf(zibMKr%*g8w)8@4dp`@vL~z-~1%+_}}2a<@q1_iSy6BMChKu3)3rsg>$9p zMR@9kMLK79UrbMXi7cQa3oj0{2=~j{i(q8~!b~XjZOQq*BDL*E!lloG1%BuGo&G!j z@A~_3=|tp3MMV650K&iHzw_kjQHku_3y7eLdbO1$GKehpiii+=Q4#oE=kK=u9slpK z{I2KU(f?g6zw7_q=YL24-Ou0S`d$C;J|MoK2g@d!igcaqw1Y`HU;G8b$G!%ZXTWS7X(`Y-sT2iWBic!E~+9WVZZPx4Re{{)}pp7x)h!2n_V@9?_=(I0;O zJNRV(iT`)_WbbMHub^`D&L43+!6!K)NUswSAc71600+{?dWQ+E{YkNzqeq^n8{U_&~fWRRH*(o2N}a3MWdSjZs#zq=ob zPR9%F^B&TDB?tcOhaUJ2#8GMctz0%}NzrYQF_H$|~DRmzKrers47;Hi4 zrX4{bgti;AE0GfsBm4%(8JPf(cth_y*f_4q$qEM#W^G+f+61{CU0(z#Hfbp~%GBXP zopa#B^R!{3o?H7>N8hdDcAvE)hx>f}vt`^C(*TbjBrq+yhxlvDZ~A~k&C}^)M;{UV z+^^nzKYapnhb?dQzmLINXryq4{<(XMHo{vF5vn;nG97%i(p> z^1XD<2K;hPx!bewsB`Ma>+tp-N76@b1N6tdqsy7SBpyX&s8LYC`>VZsksd>zQ^RB| z-^)v9A$5niCH%HYEzSh8zU-R%$L;Os(0qWY8FUuhqB zw|+T(Cguo}i6kU)3pWLY{#pde6q*!gey7(a@xFbxS&m?B^=?tb$)kZR5CfVaA&PGY zEd8NDs48@>=O_(*hxp-S@ev8Qx*Hv%NQDRFXe=Q)55E=Zq9@&O%z5+@3qXJ57Hj7| z)t3yp-w5{?NTR3!f9{wa^NXo6d>BiLc$`=f=~irBayZo_3i6)J;SYC3b5x8S;x-Zj zE*IIzF-D<**qgXx7dH^F`!eF4U8u*A#hw0zN1VeQwqe^9vd`y7&O3`5UQTa3(zW1> zoM3inTarwe%%md(cm${=^;&7Fb%kB$DgWrISpTGhM~7QnlNY@n_lB&(hZVn;2~6bp z2mRmxQ|wf#-01Ff32~q5Q!gnWz|;S>Z|;yZnFG2Qdf5pJI6CeehE#udv~*2 zbxivvNC~|?U<}5IBB&7EB3ia>Ed6I|zZ9pANxL^+zCq4qj@jXSgam$>B{du466q;vSQEqTBC~^v3clk-zB=o`QH!KNqqE*`FcJPNN&$%Vbc1-|4<1F1|73 zq|qIGHD#ppxl@k_ZIjiZ3yC{Vb(}`KGJYP29&Vqc zDz4_3h7_us$(vP}iGnmuRH``!w#Jw2o@Muyrd{NQ|3^@hpQp8DAvvA9F;D^^^GUsf% zX;CLZb+C}S7520<$*@jEC&JKMPB}l0pkST7M(3o>EeRQ0d~0$$Mpsn^uORiK$G?a; zW0AMI(LXh?!=tQ=>g`K{R{lID%R`;|&o9=A;gyq1)`w1Xk*~;NIkdV08AoLegq=FbUp72kMr-HpbjPHP ziR3*IwKVMjVgQ{$rs}XlbFR8Da4Pw*DvO5yh}~_cGhG&+|y%(e9u9x%i_vf*aKdr*HzSl?D#F(UNAG2w2~}@ zR;U|%!Z|bfD4DK3HlSfxE571@B+f1A&;oj)EGrPAHEd=q*b}f-sL$YySjujD11*No zBnS@+ZIZzbW<0_`hj-m)KpkR|B|L|wcfFQiaq&*aI24LM^j5PtS=4>oTT5}KMF=@H z07K$FKf1$f%@SF9!;S0IvG!ietel?EGOQ36hOHNa5oYLqSV~}rW45f{!R7~8Ww@ft zu_AO%(i04-NFo52Oi%k~U*UM50tihqe0niTM(S?H&?;Lvu%d52MelP0h1jw*Yt%X6 zRVSUHj4R`(rSpjlx)m4K3P6s-JI<6JVuajn%8=(b8V*6Qc3#64g^40}RD&iMGYKD# znch9}N8LijXeI@8`Ggz{S;>skXdt<9*Tb=%hHC_~!KEy+QH#4YKaPw^lyk=}tXiHK zh#e|NN~ZsqjT1^vTNptMB>J||T;;Vp4(}wY|LI(-_eWK1%8`GA<4Dmj#A z9eaB7-((!q}|z1p{RAEIFJ99+$g{ zRejDHfGsCe+h?!pnvJ4^za#T39PHN=X%vXOFJPCL%ZOkuhvumIhP}7zR`h+VDQHWF zYXWKMRJ4T5;@re#yj?lBxEJr49DT!kV-I9w58DdQ4g=>skIAnob@#A-0Ikpwmp8W| zf0IxM&3auXu9#xF6rRa6|D|NS6Z7!2`axta_heM=2Nld-P4>1!IS|D{Yu2{>H@>-b zrp)Xx&#YLv49X&hp*7huiyZ=JfYSZqKF=)}nDf~aB12bv_WF%>8r!kp8a77PSXVeF zUjNt1$)f%;ol%{4jpdkpUzK0ss1aPQ%CpDBcA9hbcO_@f%2EsAkqxdMeL-+IE3_vM z46fxtd|#RM!@~IGgs&BU*AWtPG{S=Ngk7yfx}Q`fLoz!nJ5*(EtpsCQ5?V2lk_1~m z6ybrc42!oPOnqh#e5N>4N^oV3uqeC>dr#FHDQ+ojxqhp0Bg2g}-1<^I@JfzS_VoHs zJD#6E!%6A{GGKcQml#%lLggc`_S6Lg!W`XiSJF|`X$#K1@qtSGKK>CrhiJdbg4F1LS`nN?g=34qPM>0 zumB2wGZ8#X{U8*;g7wy|y{P2GhPGd-CzUYXjdTO1!%2&UprWJu$W7oa!_PBv4X@N` z{Mr-GCYK~WafJZo4sG(B5-Q@vZwoQ>ry6q6nD{?(?GvPCB4)oP!*_nGc6nawJINMf)2;$;TB9{g8x7HthnC=t zio7xsO!_3?bwJTYn)*>%zEi9>|3<=4cFrN+@(@J2<*9<~#^XW$a^RMWQ2ljCMjm`0HL-F_wtiJmc4bsLLI1lxX-U zTBGd4X>O|qy_tAikntX9rsYP&@n#{&JWXE76CtR2>P*jExn%D}Vcw${+<1!oojM6` z+7b?`68YzVx&nM9Ef{yvIOnvUoow`%`0_%~my5Ye-JX@JUtvzpdV72l&V=TZ%XC_W|LZY{_+iB1k2~%DR!OH!B0vuQN z(96ms6b_)$KQ;?F@OY1Cm*2!`EN4KdG8_s8fLYn6sXU}67HQ5wtA<;S9A2%T1tLf? z;24F%zh!@s#{yRs`nTBN=A<7c6uH(ffUVKwlt`$nProUY^WFv zwp1W;SLk%t*6HOF^z)-w;Pg$Bc#WyX#;5I<737Lj6qt*wm|drP5c+Y>h=OCcCbw^~ zDV}~E=gX*$nB>=c1j^kmoJ@zV9V%(OP*^R|%oZ8xa{=bog2qoaX1Xh6B1&2Q^V~7S zNj(};&Q3ur>L%;ip}Jt`ivkZ zzqzVgU5}Q!R%xL7Ssio1syh8E^L29NolfJ{Y+-o41;-~dBz69E(ha`SVJ`i*g63hi zRHM@@YBHV`RV!17W8v}aCt^xjiqCzrh-pg3o;QX#E6>Q^d@s|gvCsD_$>_V<<|we6 z!_B@_#~d@id2VK=*y;5xi6~7I+KDyf=4EX4u==+71G<7ltEnf=`E+&JR z@RLM7v+b&Z5~3h%VS&rX$w6~u*I;tZ>E~RquTxrsektJZTfX+g*(eThQhBadh+RdT zSmGsJ82piY!giYTx#|X|tR|(O0C^^zo{=c+&Ps)MVRu60wv2!>Bbh zyCQ|}RB^SX4+ncV@;itwvR=j+HBPu;?<`;`OT5)F&KP9#zURkCAQ~uvn z4+E#9+1M{GF6Jze^2Owy)8y4PS09d&F)yaRsbTU0Yug9N${`$RoP8&|B(05pNTAFu&a|H7~8@(4}_A>!jf)UY zingJq2H3a@!4rjl-h_XvMOP#mF~rXoHD($E#h}tn2;HAHTK4*725Lm)5WH{`9F3j| zSC~*AltTAh2TaEuh6M*sre{Ukh+c1bmp0#=9gC`f6$3YvjJ-dqT8J`C0??jQZ54h=sxcKK(f17n-h8C|V*n)>hcUo8Y7J<7hhSmjaUoLGK! zb1pS>W6*I2ht(d;hQdx7XQ_uByf;_>K}*!6L$mf(8yU54^p~8W(VtmLVucQL`X*VS zwO_TB2W@b|+7zrUWcd-aJ5h&~E)~V%rsstf5fLcfeFAMmYkkt9qVdbpzCERjx)KFG zZ$$@s&h=dyXIb`w(=XRj3T?ho>6B}d+ts`Jbh&1JlLQ0M?}8}Rd*@CzR}sE03V$&x z!K;ou+gU~K-ewPW&l;l&Nr@3AiiNXfe6A4T*nbHF(u55=X|Jk)ij1|D6aSc!g&2MF z(g>)-trs-;Q9c^d8N-er8^-7qFW*!)f1YI^hAZQ^(FejLt@nh@MVCM+$n-8XQ- zhSP}Y-49U(j*em$FQvtbO%L@K@=tK4}vU8;W6Rbs5bl1(b% z=bJEuNk*n7!?+fAQ>Y^%{#O(;Y($T++Cc+pqCMz}f~`engGE zFgmZ^0ffzJQmDbzAW;)cZs)e*yy6y6^r7 z(Ods|Gwn2q6-_YdrNQhBp0e&qTEHYb-%hCgw(P)OUL23LC$%3uv!ao`%L7^=$gMJ- z$2_PGuM;2s2lZP7@}!VYa6!oQ6)Y(op*o|wKXQk}KI}B5C5JAvuBM~~C@inhzs5sn zi^j57F1*;<0@L>*oM=ts!?+Ht>q+WjyndEt*n2dT2sJpkr8=oL0Gz_}Zr7R*9DWaC zhRtMtPfd10(XX+TeBJZ%;pzsYob{M^!iG?b#W!j{nmL4j(p49otGvLiSXoHrf6aB1 zL~ZpG1eJiOjTcExYuJ+slPmhYU@(cTGjuH!2TA=t{!1tWi?Zunm|&V0LCJz*Ya+I- ze2GeCmTnJl>HI;O@ z58tMgT*~@mwwx9Ga98SP*<5R~nZrjO{b5_^o*sz23im94E!-%6jQ}nE%lgu(4&%Hj zlJ5cUjvb#A_NAr8@k&d5+`~LWS2e7PQ=6gcWfj=5+?_+S z_g&7PUXI0c`jWnQQ%CrVoOlS$vvB+f5u^E(Gtd>S%CNon_}IDOl8A_CZh0AYM=11m z;4;#vFc-&gyXYG{i6l~$QXg`#lwclMuq8cl*OPettUw3V?|M6hPe@3jc{$9r;W+mv z@?~DVbW1Hd_UrAWW}}kFZs_zV%_h)AMBc3hqtlK#GM)nNXkYrPDjMKT zQNv6_AJ~F41&sM*DMG*)SIDc@6<;^|;wa3W%Oz}M`r^noN3#TvS|mkXvBpL&?`+_l zMvaNTzFSzg`-RQgi~riAp%awxDWC3Mh2eOTJCYke-wIal+oxX2c*0MzZw`s$o$E7I zu7Wx*Jr7pAD!3IDHHXCSE*jgvj_BT6h1x62cDjHF&|b3XD1`)xc|y0oGY_taDKx4R z@)$qNS)U%zreGsAjjk0IZJv~BUWTTSsXHAxmN9?6fFE3}l(X?`xj9L`tUi!^(sC`+ z(!V>-pf!+%;VoD1+I3XQ-0~t+J!T;JF1kqzf7BXnZD>kTa8?X8$dWUhx}emKO%q?T zl+V)ywSa?(9eOV@q3P)j+ zDnA|SEeA^sa$<=T8VeFl939bH4V*D|uCDN_3|e&vtk`=sh1+5|BZFJ{t0nPc4bUmf zYd^o7w(IsJ79G)7^CW#3i1YiLJF)M#nrWrOSC&BCwG_h#pP3!QPKv_0QG8(|q>>Oy zY|FF}5j3%e-`Di)c=FKm;f_BxHWrshTA{#*Cbtk(Dj4duf-XeU7u@jW5B@ie|-AF^-ogjEapPMs>V#Y;`r$I{)!Hy<}lpMR&L zmZ;h$Y!?m4BM!L*DA;<*31cJqr}!oE*}D|IXGj$)?{B_FZAG$(7Kb2W%q%JFUnYdb zX7Cml8@InXf8I=I$!(<0a|IPbI|janZsO80)nof&D?}WK9GI(t{Ut*lF0DD)9c|2@ zty7UzqFg@Dnlbj93}3!Qeg&Eno0C+a6Ilo%#Ml{T?a}#RTh~GGf&6&9Z;F!?tAq;) z#eh4V7lFg{$D@w7(cXzrALFdJ3`(;zUElUS>$)&A3Vu(cCQh6gyB-aVV{AINdU*K^ z1jWP4`>gM{XOy20hc%mT10|E&NqVqet*CZ}k}&DzO`Yo7K9C>&u=GUTi)dLdRU_+?|A~aMa53`4+p05jUIIAP#Cne@a2Vv%e-Uci`e({rv^^tz zU;3VI%MDbT98IIW%?6!8WS|}gfA)ckF9Rxt!_I=N^Mb{&2N#U}nJR5p2xfNr#PTgeR60w3gm$!^f~)Q2z!m=nlh$aX%* zv=Z|?3TERk%M(d&nB-l!CA>r;*Nkv--H8vEhjH-cMW3*7q|RlDgm#bt7^z#u7b3IwCc~y)f;y_qb&F4I zZBq3kMhNp#+v5Y*K(LwF@ZJDoHW`WN^pxI=X82TLy3Om8D8suhSc95~TX>J^`r20r zY%9cMn**DD8xIV2-0>lCzmdT*XFbf?QsDkm1%#Hh~G{2jhG7v;$@m#|Qb##*)s zx0y0<&!B%Ueb$z~*nlNnb?G}Bmmzt zNcpjvU%}24BkZ%gQ^1OaBgN>-;!^LXV|%aDxZ(I4jZO*sC1@DsL8sf5VATy6z#OF! z4SgJO-DL#;puL{n1(@Gm`?2aOu;ynb$!h`~_@Za5(y>M*sZe z111y^RU}gx*dv!HqbZhG-V4-y`L*$~c}<;t!HeNny9sfh>RUBZ%_tH#)_&cGa=zC< zJ>6KMr20j+#PY(>%g^4e+4F2YJc+Jig!97={M^cN-$N$}@k$%=dW4>EsM?ayXSL?O z9E_kvk6#^xQL}Ozhoeoy?dV-R4VMnN)4u{-p>~L~U-(Am7mp3{4t|!8u~zd{x+HCh zi*fMyz-*G4mA!U8L^T&tr|w0Ys4C?7NYT_v$ZQ_Hxi;$Sb35%AuO_SPzmiZ7)?wYe zhHA=Kj2TufTki5c6zMtiyEXR$#%R0`y@VZzmqaa1O=)MoK@!93e|ah6SJeCkam+Ef zkuGFyw6)o)URO>ZQw-q({ny$`H~RR2y}3;+MvyK%{M-V|;iN|hg;jlL=&QZR75^i0 zD&cp;uNrF`>vrpITcwKeo>-3BTH&iSWO@>SQ!u2CeEbCc+mTFx5`tb1Z zt@Y6E%<1qxZhU^11+>tmiR^K>s)WCK`HHAon&E5b`axmF8_z?EhSwKJWbqh5f*yw> zxdyz@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007 zbV*G`2kHkM4<|PQe33x_03ZNKL_t(|+ULS<)=7W_L$=0{1&=h-)2(iIEm>PuCX-9V zTYU&dFi1u)BACpjTJ->;Dw)h+#QSaEZ++yazkJ~EZvCTO^xYP`V}N(-9Rs{u?-=0S zddC3oR`b>IZ+t%(pv8MQ?0kTq9DISF9DLE}A_U}WAA<0e|8~6JE4Pyx;a zq>=dP{XfKCeDhzH6MgshaXfgA`#Zmfz-s{jJ_PX9sq`~n{P0hqjRI!^0Ptu3=RcmCq4FCzzy9)@ z|AyVpd-&+iXL$VbD|B01_?!Rt-?7tv507sCKCHDMgupom#u$t-2t5x{Nf-wRXE9bI z{OZY{73cwq4Syf~_*w0Hy}9ubLT>|{3Oqmi2Gju$c0U1Q0v;9F=f-N3{lDnDOBvwb z{M$cpceWpa5CSQai#X>%NTRkpuZ7se@R<+i9RBj#{|W&3{LarIm4KJTsW-5Fv_Im&(p0Am!GBcP1KnnXi!Ot?{TVoO~WDFl4{0x8h^v?_b-WUxK0;eVJ?Y)mq(1kK8`~1W0Pq7p3;_qMn zZ}jEMr3|p$-dm0*=Crjo8vXuhH4bqOG^gr!dv~$Xx&cBc{`Sc+KE3yI0KkjWeH@RT z;-g!i0{{+szlUCH8=t@TuK)ml^$-6U0pG;Ky-(2&x|8RhUe`-8hnu}oFGr7?-P`!; z_*eM!@C$^ZmA!v=`+fZS=&$i6dV)_6zktsJa3O-F4`z%?zR#NMy~sv0T4KL@IHO*l z_n&0%*@;9Lt7jw{0NjMntTi~?eGgh`JU#sqEz!e%?;iSR#T$QP>o%m4cz$vp+Dhz% zyKv6p!`&YN0Dkl8Zx$F~(?7ruZhclsNTW5F@EU8DR05?O!Sh;h&cd7Q?LqJ3na_T3 z^T$*Be&Zu(oe0)2>f@i@{y7BqXM}K_X6}=lKgP5E4R9tv2?hBN|Nh@O&b>_ir&?f! zyD10f)tmC9{}hMagVNuJ-7NqBV-&{N83K1VdWpI`tCqHnjV?x`AP8`kBtsnuYV zpNp`miCNd;)@n#Oz3F-4ClaawR5QRb;sbz+Mi4;@#wzSGSFx8z-AU!o_QY%z(H? ziwR(Ym9A6ZCcuGbW&^ zgwNZEV*Af0ud4@5M(f0XrW~8wH?X&Vn1R4|tHL9QM;X02p)6>h|AC59u!htK!N?uD3!1JMHJPU^X7RGV%9u?fLP4s!xTt)oLwS)E@wTr}Ki5Vn> zf;#}Z28dY&=rCvyH~{+69+-R&eEQT~O}rBUgY#nz;&99Jbm>9z1>4lSQN>5 zs`;-ZJ24o%S$PB2t|mn;8fXpTI6j}&qYRvL#A*c01!y>@fR!`kNQI;*Je_C+326nK zjzD+-YfZJAH;LSyzIp;e2)a851p;E5F+eNu5Dy1)>M0G&EJ_;n0w{C&L@siBnh@_i zlJ9#{X7bxxh{m%a^jI47b`Jm$ME#?Tz{a9qIC>m#mr4|D)#tp)S=t-^1uh1f-SKm@Io89=Gk)qkG&6?Y8)2)ao)T#Zj)RCHki zQREc`L5Q)8>N5bP6iOxFB%g<`^1+2G-q7=^*_0_;t@im%0H1D)pD z$QLyyT_tFi5+5i`fQ|aEOAHaf>0H^;xMFlb#nfJvceGI7cO-NL6*eDt;eawO)q(70QF+|v# zi7l)GGOyAU>F9K(=H$A9n)83F(zb@u(Cbb|oceCa$N z4^9zwdRdt;@jKuY5W>&Ghcg$*#jew)$g5h;T9CJ_5;({N6~#~Il}M?EsO}-P|<9&M4Em^t|^u= zFEIhGptD3PnUxNw8&5vOYlvaxuiOdPX%y6idix z&|qKUnHIIGTtMERPoCA`>})pd?1vq+I-3Q=U)(9)>;a<--^8?lfdlaU<*p|ov{^gY zdVB$t=Fq4>*a>SfK>zG?f%tV+TIw~`c4WbgU*?{YTx&cb6g&+_x*81}ga<2CrDRsX znnu2J8Z9hZ!_fep_Qtic@1y}3p^rE)$4!zox13Y9`1=#F!eAbROaZz;IYD z8Lhy>@N_zeDeUwhRe6}z7_;(tx^k5`Lrs8Cz*!)lsUsYe(%OwE^HocX5*X{CZIedU ziPy!J2f@;?bpPxW-Hl$U0Of~cWGu_b#kW-jL3v<;t&sFci#rzHpX4^qXV4Ac3@jMz zTy-;LtbQkw*PhdY^$9<9qtjtp^`f9Du98a5gtn*G%=HFlH%17Ub1;NlShGMBm1_{= zY^?^>RlSB;4hd&ACK-BBOi&5~n$rMz?IFS*n5alh!9vEP`b1w!*lwd|?*ty?cu@;< zHg_OL$@?@Nkzzrzf3L$bQY~#PWsI#20Gi3@wfqQ~^rcC;)RhrG57L?tzZw8O#p$c3 z6F+p>E5)RX_vd>Ij0cM*V4m;QHE6b6){+(kVd(_cy!t|Eq!>?F19d@CuCSfewIWuoNmJBBS;s81z16xyh%v)IxW4V zx3OwuTizc(Po00+HH{pV#8pNhJOKCFNz32F#isH2>{3AB+KE6syj#tdjG`Gc5s%Nn zqhWs`u&~sQoHHZ12trKb-&?S?4w&GsUR$_S65436n#C>omahC-x8&EQhqY!hv1AHV zIpH4SII7GvU5GnnhHE3v)h<&>c&)GA)Ctdrk}>i^Pn}LGe4QL6sn066gmF;TO#0@l zSh8)SeyN+s_~kOBY}gi__f!(kW%?>)WKO|((u7y08CFDo+4ZZntxm88nHy9EoKFbAupO)haXvc9*?^?oAl#XLf!S z;-`RcQ7T-e6t5hVsd-4HgQzvpYt=Ix-i{K7yrcLG}kF%=&?dcUv=LvF3d10Hfa2AG;W(6XtdsGngDN3Q{qmPDg zQ0N3-=y82c&QU&m?h{|?+SQx#v96%cs-6X-Q>dEE2VeroodcLL0i~5S zY}UvHz((M~X$e}xmQt9+)tl^Hp7>?Kp42t8gkzOyx0U7XM$a;_y`JIeI>^8J8ab3s z<|MQbuUvj%lnov!Fr)I30no`arNs5`!RsHS*ktK^6s* z7$xUogf-NE(o*k%)JQNf_V)JJX9}Z2ODZLyw7anH&L1t?n0m4-c|cihfJ#dU?N#*V z8*A{7VHsmDw2Vxf`dA>Zt)v{4YXIw9t%D>o3{j+};&FxfU>Ok17hhg4>gh|@7^|9u zRdNh`6}MDyK;`zuUI+JWu6t%(mAmUqd|lRxr73K*Ng2=N7-fM0Oq~-%bRO}W8Moq6 zgGnTwJeUBX1X4+mlo<&HN&;NO?_Bw8gNr176D`9RU98Drj7u0HA-9>iMBdNU+9LV> zi!Gnd7n3M$CI=}@;`_v{O|28kW^x?gr$tjRa1IE9`9q;Nr|<-Yjn9^L_`Yq6(eK}} zbUcp;*WH^(aET2R+=G;}j3^j|9Q9YaUfx8USNhxS7KX#ox$faYH9+AnbPTG?Yu^kJ zFr&NU)FAr!nK6>cVTd*|)#QpRKy&e|Ch$tYQCRS+Q*o)^NOBzT$# zGA;LA6->$WFG)NYa2W8ciIR}3RFCK1Oy?|g%^C#5I}n|{guvcn#87x4sPI9B55idC zKF%}5xulq~iN0;Fac4ka5f;!|!deZ_Yb{L<#R#%aEEf;52aE^D$ZN9n0Hbv<%&Zih zuM0Pon)G>>t&MgE)+Lor#A#q~Iww35);bWcwV<0g)J!2w8ph=fv`Ue-OLbvWOjp@b zlWvBTqveGXMkcnhvH;@zgcm^vD!Lf^SSO}IiOV@Si_c??0Vz?#8Uo0f&Z~Aun+=JI z%LhKX1|?ikG=@CK0Zqf$zyrYi5N0wJoOrF7&0NN;!dW=jY%WqdXel)TNo{{QQ@noh zw2trC=$Y!KiyZ)G9gKBZDOqxV-o-OO5y#dkpUQt`UHu1X*f^Cm7Y~xkrkaDANI?=S z0f7Z2X2zT=;j&)9n~cYEK*j*`3|m{1`Yq5rV)Sw-vM!QjW|VPo{&m^zOrnJ@CTz1pa}!erJ!wDjXu35vwGK2*lGyLUNiHODg!|T$f;plH`F{=n6i%Z z6xWUcG=OD!g?#j_2*`MDd?{((b*O)f?_a35!hf8a0MFyqo5HDaZRSV3aIRWA0&N@xu46**;DQ2qBQM1myx)u~;J|ew|tS z^Cye=K>)bqjDdLA$M<2KXU0I9_u!YMYSJTGtX3dwwR3#JbDYveKmY=ef+AGL*z)7w z2*ukzxn!vqu!{8O-wVU#F@trT&m)AFjXoQW25T!SO^I*F_X7l01%~p!udM-!j%!Op zsF$4yjQU4l0JIjhJ7Vjs&V<2@F&K`9D{zubx~tjsonAr+&5C%Pv-KHZ*@>N6DO}dP z!Tf4@0%mf61DUurSxPh=^_~ZPBw?1S6VmuxLknjd)+J{GFPm$W=0nI8Gr+Qh7Nsl` zSVHJ}27_PK37W(Hi==OFLS{!uLiiNP6FQmu&obh#79e79B8`eph|jL)kkzVG@WQEK zO)j1uL~wQLYud+ZtV=3u#sla`F5r?V8iO&u^vK)v{NMQ#Hk@@3LO`jv=b*?{>pE#_ z3rx*ZF{O;5wQd9yFJh%tG`2*tgCJ~l-f`Y^jiXT^@!!f|Qw7uTDKMyK4Wc-@P$CN# zXTu^ELdeb{>c5!fU}qMXpsuE3G;#k@;-~*!R(|6unog|MGvRwK|^V=vgWipwM!Zr8@HorlOH?6lNyjm-N>AeDr%27(JHtuB|qg<8&A>!8a*qUXAqmWACf-tav19QpYTt!o2$W`2y`NT*5`1%A;o&S{bFbJ~~IL>X(oXZ&U!nBN_P}((4uB9V? z`84{KBxvje0h0+?7m6e%U&NdPph4!O%9Sv|h2Vu13RL})xrHe%P;=OZJDGVIsoGAx zloV@BsZpGrTcsc-9lSHIEz)aIEDu%Nsw!>9K@j98g*t#FLl#j$(uKcARD#5(&7%3u zNNNh#r}~;y0MBTVI4Z3nNMZov1w!P{4Xk7^j{yY|-;@d3?Ox%Cos@kC$HNTZQQ}Zm zPg*tah?lANN`Df(^rY)`Ps1+b;JRwq7z@tpYo&FXfeYUT5r8m zLWpdrR%iPF@%RiPXaj`8stACa8O&XIb`j%=21wn%I&z!(ltmh#Kh$8lv+0}zr38$z!eWnr zDxCCVoSYR)!eFdmt;0s!Z^&Hdn4S$Fj^bLxPuG(tiHiK-gAXRpZ!7Zvbq=}6udTKR zV-1F5h5j&tRytugN+EI#gN+JZ0-~<#u#>Yw!s9Ov7;ybQ7Q4$HHtMDqi6+7(y_)Ok{Yo}dhZ;PakZRL z_=3UrcD_P4*q&0G6ug>6tu!Eyu{4o5IrPlSR(cmlnUWrMAarC_u? zchK*j;nm4mAut|ejI%yLyVFLy-2x#=wDZmJNo6Y97=x!zpW^P_yOm6-P-}R5`iG-4`RGIi{K`+g_o6sosA>}XETQ+q^fK%Rv1O9 zICx?Wq%t@gNrXPf?#?#+0#4^%0Bs$twfOG4@6I(A?&#Tb?Cm$_y(ktRZmn zW+L4i0YaYx1q5);;qx|H}zN+_v72!U1#uV25$-rgP< z3=9}x6+i`^J$r_;v$Ikh7X$%18*Pw3`jbDdwQGa`ozTPSAVM@6!A_=AQcB^s!qSni zf>G>lwP(tyUZ0K|O}C_!VsCE`yKNKK?*C7`7ZMuP$RZ%!~c?PGA-FMWBB_&cPX#9Q_&(VbvH;#|wRf(P+Ft{8S^Hym?bfd}noXeWMnJT{-8# zvm3B#hUg9ep&W$!03k5OAR3N}In+5sqcOrxd)6LJuKoJOi{y$fL8pWX5Z2sH>i3g| zj+-~9r(wT(^(wn3XEk6{HuwRACeJ|m0=hI>V_Yz~Ydjo*3xS|j6uFyB2AR8-bq>#7 zzQIl}M667qX)BJ>NjRfsqpc2bFmOhJa36#TM58hE60`92@4mwAgY8Vvl6{wOMlVEi z9U;keCwUoe)u`~mh>Uxb0jQ5?G+wHnoO6iB5yJLlV1tn*Q$rk_j^T^~6=7r8-|zPk z1OYZTHxbA2#LhW56)&DR;tZTMa7fCvQ>L@lA{v!P`m|Dr#{_;D%t+C+J&Yt_S|(<~ zwXaX>M-QDESB{@^I);oTw5pEKJUu!=Ya=m5%V-Mck~a1Ub8%DvCubd^XoNcW%4iL( zG#GUC@h{H8sxhb+0u8%zU%q^aFbuN*iB(ZW@1D!lD&aojaa0Kym6V{2f)iWtEG~J^ zY9Oa2>k~h!HG9w)2c_znOKUCS@fdqji`CklMmVLkLg6 z4}xSPa}41iLBtfa7_A}W7|sEnAdNa(jA_29)&bf$a8{w>C&aacEr4YiOAt!IDiUZy zc<_TTIjf;Rnzqw7+WQ*!3LsXAaC7I9hfD)*dp8f!YHuW3W-LwL~O~t8?TyLg3R< zs1SrL+`j+*G|7WxWX$Qw37#JvLDke;)>enqrJ8DX@{3>m!UbNkiTek4u(h*S2r%9p zALGg6$Iz-CBLv=J;pU9H7285-6r4a5Xe0-Ual9CxAOr|JT8Y7&OTM$oVvM1?*+Z+< zg6|0c4rl#S3`+`NBWafo{V01j&ku0-!6R@kN|cMi^P}fDdiJcAjrRosD`8k`llz=W z1`z`6+_+gt{4^4`v%8C4Zxi2s`wdRtoK$N8i&Dv4X5W-{pmcG5u9UhE+&Txu$|9(+ zIZbS15QeyQaDd)sZz0a!+uX+EZ@9s2iV@-$Ns?`9NxYQ;fY*6g;U%-xKq2wpAdrE zckaL%i`Pry@6Ni+zYoGTw)bwJ)$V|E0p}c^J$;I!r_aha%D7C8X;Xbq_a3~Djc#|M zEn=LVp5XP%BiMO-jlUJS})`I0lJ&p zjm%Q3-NJkCKg92T`(=3m&n0{Bc|L9&+(Bn!V}5ANXJ!w=ByZDneX5Q19=2iV#!@6&gLA!xP1g;(i{-hc2QBR-HE zSGTjbj|Y!FL94xyG1ao?dHBJjTEx$TwyoV8(}zWU2FM7}-CSw7Mz`C={{H^bz3*)F zaPR$((AnrN1lqz@3wQ6|PZ;0#R~xWMDaFCz?WLP~c<&*$cJ>M%k`RJBckj)hUI6fY z9}geBk01Q-N4Wp+L%jFsW3*c3jJA7YuauFv5V(E+AzGc~guQ$J9yT^M8t*|FW~vHe zO||6e#j{&G+e=Nw;obL^nu_h6ZFDv^KnG{1E2l#9wq$z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007 zbV*G`2kHkM5+@%cHwl;k02lE|L_t(|+TC4ymZQ9ny^;+{RnIDB8?%ks|0;f6m4GeH zAGQfec-UZ)^l;91zV5C^0A1^OCDH%R^C0GxjrZKv=iJhw6+1SkaoC{+T1RWx1RFH=?sPk(j- zhie74TLyvME|r_gF+yM;PInD~-wU6>hQjG58a_7x12k=BzJ3|MU+W+s1xVIkI{Wa9 zQy(~hU<3$__ofIyN$*VO?m?+YI|>7`@NB|BZvheo_46{>41m)w;}mcHh>Iu)-x$7A z`;RCjA`mI`;XX+6K)_N#Luq;sw0v4NyaUw*^`D`oyH-KUu>JHs@cxHBLihwW3}YE= z=7b+!5L46)Q(qV0>xW?%PL?^=x7#fEr12&njWDbJr!+y=D*TKe!=L)_gJ3nDf*G(8 zV-^4jsOKMsbu_EmKl1sb*_%RuH@fJ9O=$wx=v}n1-v>D8QUz2MA^=2zd$T{7gCuk! z0yvzft0NDupP+7zIE0I~E^!g}7etoz3Bk z1SWu)httnY!8>0PrUq}GCB)7Ez?lx)C1?ZV=`cSgSKS9kHmdz7{Pe_g4j_$uFp8lC zjs8oHEy)c8G?O^_d;rXvig4mp0E$x7Okvud@GS;YezXz}1;tqC!F*wG_Qt+UGKG)N z#DXEea_5XI4MHxt|9=($cR<)6u&J27I|cK=5_1|pq^zk@q(I5J9SJ>wVNUbS0l3z+ z2mo&smoGunGn($b>hdKjd7NZn9UR60gpgzB9jR=JQOgkF(7f4GYy}L%0$jRmp35|d_8GMb320V%QAO}4!w#(C?&drO?c7( zln|rqMVU;qW1CRCc}(?Zn*gPdQ0N;UfNU8`UX z>Npn+stWIu@O5xp$G*T_CKUVS&rGn50TJN6?Dql2KxjKc(;W*0iGub5LXv+V%h-giYJ3d&yK@Pr+wsqGnjTp9BVt+Mbbogc#x#>VT9_NdGnXGi-$OrQAtMg$>^Xfy>V1^xnh{3uTv)mz-yB6m$X_7qle%bs&h3@-`zkfR@AC zakcbO;5pHfU6oG3LtoCo_g~5qx@&?;_Zv?6yzutN@GO8gb?!$A=o&@WcvwehyIcG| z3j$FnLb#Z7_-!nh~tl3|1B3LDe(1U z4#^v&vgfA&>HdAy3zJK(F$k)d03$*0?R8z{hYS=?df8t;^^-@YqR?uRL{1$o_8hzx z1hl~f#M<)d%J}{dXT4}hI4OJ&vO+Gw^hkHS=Cj&S~!8RL{N~OXlBD5#7n8y8h0I->U2+ho> z?FE7Lv`hF?6znY_+v!>;{NyWTrhSjN>|ViJ%k#Ya5^h>g_yTXr7H$#N8U?#FBe>RK zJm)Ba?Y??2tI;inK; zrA&Il!1XLcT}6y;ItaG>Uyk3VYAcm%*&J$nuW-^%#O2oaa;|6U5Vaq|F3 zb&#cZM-;q!X2w!iyJ{Zy&ozqcSs*hl;U(849x(g!9ca*P$5{-Pv3-}MHvR2^ZFBDo zGV>%CEyu2Z{{&62^l)v@I0qqPlQ`PbJ+dt98W?Q=|Qn0O~ zp+CSn+T?AkDx6cmNpLPPgA;_rWXT)t$} z4QZwJmSNb#Na#7Mj-nCe9x=LF8lody^S=XB*mcnO=s zz`lvS0I4bD4c$S>`RYz#K*F3>Vx~zFsyQ6v^00bp$ye&ruDk8uWltLR#(Mx4F9 z%kaF#d4OaZ+U|YbK_TNtv%(LjNtd<41`763AW&5p=1IV}S3=Vnbf+-fVspD$ub2ly>HX_Y01Qz>Y#eO7oe* zQVRClA7=!FN7GPx0I3E5?n0K>9dx=-Rd&vvd-66UJDQ%BK~O>R!E+aU{nFusr;=%C zuLiCOZR}h4nbiO=&My7@(cmav-s2x6!MoUMMhY0uo9p|z*YzwAR{VY`zWKw&FK2y|@PVdXrltrVUPJZ6BaJ<>lvl zJ3pzrs@-qOMae=NNue5ukh$?^DtnfaM3+3+_DV1=6o%HOj8J7iKnX=FX|5;5_d$M< ziDUJ*RNYxO_yA2GxbL~AFR@_~Qma0^4|9pq^o=;wrs48Hz6@qbHZn6!JF5r zIXn!K0st6^Y2HF4-;o}u{wW{{{fov^a15o zgj^Pao$7uuet%VOE*oVG-%+8C(+FW=r|ARXvt)kYJBT60SikFINPm#K>7arCNV8o> zB!D%Z2Ajr0I9+L%tqLKDnWZ`#%kW;SaRpa3!s0fs8O>$Qz$5(EF6RRGG0hJ&OmGX4 zm$iri5 z{`2(gxRb{i{%8;=-O|ygiT3(Ljb8*n#a9RKH2T{*P^?sSm}hH74VlIoc<=JFc+smq zy4EoETh^SYcV6R;AyVM9akjjzsdna0w5r0puZD9L06?uoYS&m@R1nyUXAaMzDtBzY0^a23p z-AZA_^%OLN^&yO`S?NljF}FcPDAd{6YiJhTyClL)k63>f2)tEX&SlNGvayqN767@E zH=R+qF9n}N*Gdf_C;?)zZ1W;3h-JSiuy(W}L{kfQ2x)I?X+yHZ7={WC%MYaGm0RA~ zmNjGZ8lYfG)}Vs4?&)9q?BowLx_!GR8yZ4b9Rz>(YG0=EO9n#B$$)DCAen)j1xf=$ z$kjRhe&zI!zt>rSL^o$M*BUclae1S-e9La`qOuk{1B+HB#|)&N{aQYNa@is&q31~9 zo!6KjkmcpKil0AHg}Azf_h^>^u&mcv!VsrwkpN*>5}5UcRJ=TbPqCs0)Avm2N%ZTzm0D^f`rMny3KEjt=?lsa00@dBbXw)+STVl z==QeJG@ZaTr&K8<+V<`zeEz-V%$L=zVa7lE0i_eMh4U#LwtZ^xGoEQaX5vpoZ_2sZs6koi{K(?Mq`?(z7mU zfUU!}-Ua~E6VPg)U~k;|MITPDT6NUoY+kMKyzP}BXZ;uruzDM5zt5H}VgGL~Ez348 z@ehp)gD>0eh-Ou-4*&qw)4c!M)pUe5lZQYV8ZXWI`SX{nj?+0r1AOFRWW03x2r1B9 z8Ev;7^^~Ng*@rcJwKj^*&Qmt?tz-6I6Mh=}lomTt3<;0+Ge{A$jl4Lxadv+3iiWkl z$sY{8@{S%qKWuifkufa)FaY@014y74G3d|(Kod2A$05u$KtN!0&9pbaXMJ6$sv7id zbULXH07MjQV=tj0xL$^L@^1lP6pKr2ZubhX3EIHOtwoIDyvVd1q86`@6tG>eLtT3h zf*kvw^ZVN?qv^0Z9dtefx&Hz2w>Dtru;9zNFf-Yn&NfuR($C89Bf3W ze>zD6@znNVvKSo{4X6UndDzC>o|kF18Y3@C$@614(PWT6wy;@-k!CA#sdF+r)vC4= zm`Jaww~_s^p`iD-6TkKzUNuAM34f;x!`bHfuqIG%IxruzKSY1#BaBgl&nDy}pONjpuzpz@=sGyXl;B7VCRM=o>9g6g>*ATGdhGAYWQH7c_G85^wNRu5qLz zqHn9nu5toT7lw7ZX$09)5@?S)&pq{_N|smYW2TS@d|@I=M8h1yH%?5=+86LCjUluW z4kmi|rc+Nq+l2bWs{|rGjG%evINE=T6`V%JPFCv1r{1GDyh}=|X$&0XB|;IAu+?M3 zl~&}QFZ;&!Rp&7Yhb`J-jyXj%Vg6adiBB25E#ckROxcFBriSgtvu+|3dFV@q0K*mvUxvY zbrX<;o^I?+TxA^nfLIMGew@)$)T!U6$>zh$u|X4v7kJSk2l4uqDBNYkG;+1eZ?tjon@SVm9;o_1v)G;smjJ8erw?1pItU z*2-F2Q!TA=3TvB#+Sk;69q%QUtJhy<+Gaipj8nbEky(u((Fgnbi<9m}i&b}7} zM1Y;zmFJ59Q1_<7A}C#DAQRI|>06KSd<}EepR~%Fozif3yt?qbT1EnCyG;=uZD9TC9)X3$}`(b?o7u8OOfbw~qNnz%xr9sKEYCm6`P{u>Uydm%q+6s6kS-}{q*SCqBot7(TR>4jy5AX} z>wS3ced7MUf4%ZKd#%0p>b3ShGjoo1&N}kQ008Lt0RR{W0F<=V)dCnSyu56@8AJmZ z>}*_ZJT1K4JQ+k8lDSHK_&`4{HJAZirA;A-Ilr!i>%T;pJHb+fiXEI>?xOn#pQFu2%w z+5Z&%7r&LgkE@dz1j571fM9g7@V4=EuyFoOr?s1prL&E;gSCw{gQ&Nsj}2VYZ)WT~ z;nA2mJ9yi`9dx(!RJHN8aCUaE(sJ{$vv;-eg3AXmSXy}5$hbMXdFt5sdHZ<6-3wrF zfCuOYcK{xS%fDpgEv$a#0umI&5y0@*Hm#f;Y;Dba;dcISHhKOJHmw~zz5j34c>mlQ zBFFF&{H)Eti>Bdh;cCML;Xzc}-P6Iv!Q0{Pzc?(sy*(W)eY_FV00s?pZABeLb+w-r zR8!Ydl~Q34<>6q^k<*t^SJ#p?gD{9948ybRV1*Fj`@N(;lMe5~zfj1}!SG9=z#kO~ zURNk|T_HT9f2~mXcZDKkh!PV&&%I?&fOa z>it^;0zABe2%?WG{Jat2MdTO0=Ztu{goFinc=!c)1%>#91qFn7Ie0k);JRHL;HQfb zrvL{8e&Pu73Gs;t3-O2u2@45wa3a>df6I%WoD3iQ{P|<}@ap}O^}iE`JNLhf!_TPy zunzC<{}%sA{24nBKRm(zGOsNor6Q&EUmD=e{@)sY&mIpP{VjWZT=29B3h?vu2#fFw z@bT~p{2_br!M}BzrtuB78yuf?`@-E<7(#(zmfCsK;Zr(DC)MhKR;f;E8=b8X@~fv z0dGb@_}$>we*GVWe^d9r$_w$qUB7OdmlpzWssB}+R~XLx2XT>~+x43Fe1GG;ARiCB z{jbaO@$&s`xQLVRI=_g30G#r_y36xl;zIxF?%!JH{f}rxL=frwU#;{1hcpiaB8ceR z|1nu25cqNRhv0c2JUoBvF9cD`>*?Y_?7Tmk{C`ux3*kY8aoy*?Qvg31{^$TN50AkA zL&|s&)x917FOM*y2-ofZU4sb-2*dB~e^3DLZwTUM{IAa!zimzUM+$idXZYu4_`Oz$ z_vgm}*MAe>cT$AFZ`=7_Tlw1l%G{Fgrn{{IEng!01f@AgX~_^;!iN+3V!h@4!B7>bDT7ye5>f_@!G=#kSu_{o1A|HT7`ZP)Q%IuZ2i_%B%m z{W@O6?biOQ76=?+3qBA1Py9C?aQpB4e~u&a`HSbTaJUaYd2Uvm{)`L3|G(l0|9|oS z9q#u|zWq0!^I+HT_TO>vKjH}gfARkr&X0Wj(|-id-{A;9fARb$4xj(@6R!VS-3g(H z7=P3G*Z414c&}dT0r1cKAY>8rUwZx%hvx?VFBDO004^-)1Ga{)>n%uL+~Aeu#rK2e z4e?1L)_(C^r`v8hN$A`UfpUHBp7}vh_?TK}90Dc%J$<1hCrK?b@fDIUtlXhhOK~mN z^=ukOi?4ZxKxc5nTdvDq=fAH1y3Xr4xt@pX`mf7g*MFVoI{iBTbz9f{xgL9MJBvg} zO9(U*Ua#x1T<5=@&$SK~3C*?;C?`C(*L}WTi|h5ePQUK+U-ij#o?Up2?zDzLtE|~1 zuKRGE=XxwRIby_v>O!FFha!Kd(O>b#c&%uH{1tvZC)f2~=f9r+>#_V5{ks2urT@Cm*JHe%|Lc1GisyQ~*Z1{x{eQ(noubj! z{T;8pQ+5M-9UARlNh0RIAc9X`xJB|8MDTkjxwickM93l5{|X}XAl84u)EFoXVGl9a z?|%pV1rhoY^S^=!{fPCyf&yadFvR*V$mhciL)iTV5q8GKC1D8t*C9e5V*U#v{QI@; zK<@j~9|T0mUx$WpImG-IM67GM;Ugo!0Neo#0U7ux18@S0@O3fxCIKTpM08)Sud=vr*0DM3I;DwL8@MDM^E+-2gWr3Rj9e@dN0iu91 zpb8&V0SWk*3k^U4J}Ll$a2a`cbOP{;7mx(h03Co8fC9SkQ5Vnx&;WkG2tFDC`hX@N z4Hy8i8fv$3u_&?NMsO7sWVPTh6memo!N)F1ivc)5^3u93jWpHA5dxop?4(qs0N_Ou z_PGTrd=9o!&{73}drWYlNB}s6lR`HDzy|^VU(5kOGz|dA+_RcA#o-HRmddwffh)vc zUQ5XnI0e&P!N3auxNagYB)=l)T{sclTTxXG{R=t`Av4`gAxwmZT}4?b9lz;0lYplM z%}FhfaTRrk*lell5~i-$f=yCFIX}=fVk-Jgnm^umAM|bgUUeHV`Rae`n$2u2&1E5MB7i>uDXNXj z)bfYhs9*R2Xe0*e)`VfsL_l;u+9;>FNpD!_q<1-mY^`E>V}K%xw>A=<4E33kVw>ddlDckguq1>v!6%WoKDRbH*5hrw>`RZlbKRd z2nmJX#kMt=qRs3p7>uegZYFxR6R%At9BK~2NH{9SfGKXPtbdm(RS?5Msoinzgt;LR zq8{w=PT_=(aIX-%UEYsl!B`+~)jmsNVPqg+-CvSa_yKFzl9F+_hhHCPDA`x@aH%@@eRglY*&C=}@7jjR;i-~$YF>E)NF_1D+J(6JlOMRQ> zvL9O%OBXpR^jM6P&M)ef>2~&qr8p2%XnM@ZkV=P`8DTM+Th6WSL7+VyZ&5jNXh}o` z$0uSuQ!hw+X@Pvp>fK|0SrHEY(r=Q4KvMXdxD(war2826-!*zpQv^0ovxnWXM_Ji~ zK$-5$q2CrPyI?ur@Akq2Cj>$s3GqTh%eTDTwfw5sq%B@K0l)3>z` zO3A{CQmsN*-)kC7i7*Sby$?vQ#v3pIH{w)osS&=6?=4?`++y?3vbLb1?g1hnTCLNR zIzP}HAXpl1p3-(kIm~!+vcWRbkV%SG#Vj>}tg3D=R&|%5%pr^ga%-z!c2FW!h#ogk z!a>1HEd1L5ukU@lmIu--x0=FL{XPN71O;E^(pBoLGBuk0RSxVjfue^R8&q_m?rSgY zBa@L;r4_@~CnmVv^d5-}Jt1T_DL2RcB20!;hPC}<$H(3HU2D4u6Y<&FkV;Jg(v8KI zts|r!n7x?v2n{wUHvCY&uK!KI_b6-`>HHhyAp29GwPE?w2e;Q@p(*Y0n#7@%6swu; zF1^Kgxni2j3tJ#I)Rf5v+7foVJ1;!d(q7X0Y{rw`nLY%-k*YIg0ew2A>K%6W&usPI zxl+~Z9l;B$`LE1FeQio#t0g$)d@?$3AQVcVoW zO3ku!Blbq7B&%mU^8w#a`XP8zDD-L9j7P)1=Ay{Q$0jLi9WrKv?MG()giTK2N=H;` zC(S#D?{+vsg?zr>#@wKkoAA@WZU4sTToM~ulSTSfn%A)lN7|ar9ZfTo!U4a|iJ>36 zK6)Qt-XrgdW-s(fAh?jKYiONZ%uMAA&SA_m`y-&7BuDRP4aaIlf8SDP_)1o$6EUUlTc- zM_Inn8qi*znyhbp;}t1$Z^?Vp#GC@X!)um8Jw$H5g1Hc)s`)-h@)&iLfY#wT;dtvH z*`Vl!PbdMQq!ocPTD#8OE$>@_SDa)_tUCu*czslbwd*Co=4H?r_7mkQ9*nXy;HK2h zHy@L=7#w2tdsAl6gD1C(pA9=cmQ|zSJfvHCZh>*bP8o< z=Do*?aj$I-w2Dn%al7~>bSbhhN_a{(J=v1 zHOwf&w>t!>o+uS{GBeaO*QNDb_yINP!5AOjKmUdrc2KW;tWCVdNk6k`$a22QZc`kT z^lHnr!)Rcy`JB+zQ2iL$t)JBO#yBPF8~&TG#x2CxSxS@zKZP{ou5IjXH}*Ob0rw*o zCq_wmP+hM&z$`w~o-C8GJXzY$4F|TNbJa^F1O`Pa_d44TIAl!Z;$1~C8qZgOgtdU> zPUL>&>^&`lnpKffBbG^d4A&z5tO1y%3`E?lrf&>Tg8349S4v)-3GO)zJS@QS&c?qu zjZK0&4*P-H4J88bKnwlHeHb@Vx2{aF8a?&^1)qmSzPE{+18jS=?!0lNJsN`F!3@BB zoJ+SRZqY){_Gs*fUEUesJbe+AS}1t&EzHGh8;5s~k&N?QRmc@cwPxSl3;DTJhag_N zgZwd6MDaxw+7PmtqR2y6$EP2I7#Ak3)w%4DvO^n_#M^K^+}WhbWgz1?U&h^3KE*$g z^8%-VV7IUilj#VwrkL2(^U5~F=w@ae$X)n0*+1NJpB^sH`>N0WghcfiP-<_`H8z4D zAai;xd#3cu=9Ng_aQL;yc8_MDAK%&>OPlFFb&C)IcIMa=@%nWbl0 ztVp=3hjpmQNJ@uf?m`~CM#rDzffiK0VOT1k)zUJs)BM&y)S7bod(fN|{fc~DCw_@y zYC|U)Tm-D4Oa580{pB6$5en}T$gJgEE*L9tSRC#)CzU%Ud{4-jp^HCRqXz$tUG>8# zjadHpR;TJTbm`5DuWA5}ri?Rn5ZN~e+|NpT>780whck3`pvc=J8ux%wG~m1R(@7fd zCJo)YgE;{|1R2FLa-K?QNd4&WA`86uv=mYD*ulOUtqRj+%jh_L41f%BU7UYhWHFsz zp=0cLGwCRgMLv}I_3ZV;0SAHJc`$41RYs~rz!$aoFCbb%hr0>O>q*t$Uw_6}5Xcu7 z<$u~kfgU63c_^qNEj+oY-iG%PILg;HdFRemuiQAFIeGVR*opkzI`uu1!5^z&qZ00~ zD1P^7_?Lw_R&_%o(ByJNO}`P%ex4i3x>vrTHu7zCbNhB!o?D4n2De?%lbx_)lajRE z8}E{=?V1 zc5DGpAIqkSPaY~kxQL_2i{mwHpfF51c84nFw?|UJk7BJ3Uh2#l2pt2ebg#BwmvFzZ zAk-?CY{vJB{j{GT0v^4Kbk^uxksw6RqwCdaXWx-IQ6?ge^B5T*k9C-rW?Xng`}~p> zjCm2)qwS7UDfs~pr=%?hzcwm!qTv8A=ct|z5CjQxkjB=k01n`IS4_K}k}DPf2Y;mt zg~E3P!wPIKC$V#p+VwuT)r``ogoKvuQ-d&Sk9%XCogT*P=3=A_$&jmAZpJ4!CBDE zPaMIpuq@d`S*o)RUKG1e|5m^4tCd2?!#A6GVOI)uCbt=ws81 zM5zXLOv^n`?+A1*3szHnu=&t_^L&D99r=jo13tfsJNBd0hQvJL>5L;$R$1b8l;JXm zUK5Rz#5l`^#Wsx4LYh;__yj9cz7ZN-iyyPmGOGtTlrlS)d;43jp1dQ!v?pMh`}DCS z_V83T!3+d@dk1}+|8z!Fqe90g&CW?4H@%0_Z~I4`-^X&vrg6xj(RkK#U(=ODdacEJ zkH+T8(z~D4>dQLc)NE~fyn116jdqJkYf{_bYMJREq#D&;ajp`MzhJ7{(jP>q<<23WCE0D4OUJim#uP3uX%CVMi>6`( z0viM$3=V1w?p0bHnh^z4o+p!vY2sie9r7vMs7q)Te&umDc=thcLrWhWPRox(S}4@{ z?u$n}99IzFcpOC`kDO;?7zIWo5cZD#y#Nem?){-&sLd|O}LlVClNuS50Q_+3v)sM28TNwB z8c`Z=Nzm&nq}`W-=AUa82VO(?rg8=abvizc$M-#$j4>vX@KbuZhHfe_dMF`pV@cDK zuOomi5yszG^6ou8W?7Klxc9IM6x`>d;#()^99IK#j=b-tFZc1_vaNGyg}n%)AH zJuIl#tY%}8eN^XmY<{2wD#19ogaaubirHkF>9F&xhG@>vm#JNZf=T~sgkB5@8P%iL zl4-N#Z&jB92^rgXbTubLn2+@e>ADI^W z*rZppou4Ybr?{2CsVkIVP93FHHMmB<^Hh~}%%uc5i1|p(+`LX!-~@7Nt(Pac@covY z6;1@K?rbY*6i}w5mw4&JPhgpAx^(r#Qh(uWU3U0DN3XobR>V9vMV0xT`lx==VUn(g-7qX!B z!p+~bMK0ipKQKe2qC6$uphbC@T&JkQBhq2PIDjH*=KmtHuVh^F5wppU^Jv`o*ZzwP zl%MKf6;;Hv^hB0z%jhoMGf@L&S4HM-AK*I+9&VHm;>TGtxjQZU5v5Z*%RUbgRYchx zJ+!DLry<6Djy&i;*)yAy>d;7elUu28&r0~C^+RZ5jY0GyTXv69FJ7^+vPPmbh3e9m zk1k&1=N-KyYCEJg6_DA)3@O3xnmX~}?o;MM2R_`KW0&>heROa-q#wRhiM_I8y0&yQ zSYRU-K(6B*5UGO#IJj)u*uFm*N5x1Qcr3SH#g+ZFS0hS$h>$H>nSSBXVA@xSjB%Ce z&C9n@!Z}_$#i!?=9H#cAZuZ9EvsLk9D~hSM=lv)s<-3%aYGXaCdT^{}x^+GnWZ}qg zoO8fjO8PCkS?BGXS`e@Une1!}G1`z|nb(eAxkV*1h`S|np?F-C8q@%ACV>=W3KU0T zJ{0$SyluU|Dm87@D#J0&6|kA15E;McKB3!=c9lor&1Y`q zy;Yvb>SWPAO%9+bEkgSw(IJV0e5I#%Hm!;uVgy<+D9LtFcM7Sge3&NNVNIZi|JcEF z@3>f79X1nr+FcG}kc`jsUl*PZc|ejS|5i=!OHavsfpD|3Qkeq|_3AC@8;@$nth!S4 zR&%(|dJc8hc`#!*r!5mj6WZ~q99vX&q&Bl!f2f5I z(Zk3b*DV!e8|sTteO$KStdH8Gr3)o}pSuQLNDd=mAassR3J|jBN2;_?8{ggeZri{g{9!$>A`Hx(lY49JxcSnub}fl z8cg48v%&DL zLJ_7Du<&@`NJ5mCT=KMMVmo!w=(Qi&?#B`+fo}hoA3@~?=rG~HZCaupbX#12`lrd^i?UT8N@M69h{F(PsR+uA3E@q93GhErx#w4$Ny8S(M zT0@R)oa}9LEpDpQ-#(ZaMHUrZ>mjO0A{k29-o^xac50^h?%1P&Wg8l)drnq}g_`b92@R`{6#Tm{sIsULB z+!(`K%yuWSr_RsblmkC_9e~`O>VQ%N?&bFq{>IX;_2I<>_58xGzf%NgO2HuHl9GC# z;O{tH!>_+zL;!-p+S#G-cP_x~*YRt9!mhtZbadAj`gO@uvMBd$i(?Hv^rTk+8mODw z>d55_wR7;5+?#wWaUH+T-_At~t-K)sg?y@(ypCVz`Gd~C(0^U_I{pVe*ZsMsXV}dd z8jNQTm6l;_6%H7c_yuo)-$KuC+?EXgq}AGe36uQP(gp=MB*j88UO~zC-%0#}_z_J| zU_Z7=H?jkoR`OQj7u*VMZUOcv#0kGrwL+xEB!0n=s^^kwZylkBCyowF6kuok9p8;rLeV;UJ9GQ|n{s z52!hLquaP*C`hKU=OJnm|Hw$Ct1qX4ksi|%W}|KL#kqU$fNj0Kv0b-7D0$x70O75`&|K=k zF!=Rxg8{VaNEg17a&>nE+FlZ4#((+dY$kVUCG)EGv#;6gWrgSVNy^-XLhds9TyBN; zjhMIt#;cQT@8Q=*`wBM))E#51wB zn06;5KoSf3Zsf_rlKEHqMU3FH{b~SU-W^G&5glr3yPyCTGgq!q0fhMb;F9?6vl(bl z`BL5M?F!ar=*1e!k^MTKbIhBXyLWH4iJeg1E~w^H?1N6850zJh?Do;o>+xK^OT8-H z=QBIsQO{36wnGMX?5@_KIhpxCsD#@te`H=o&kY6~Zw%V`o&R9>HZnTSygFKVF%pcQ zqQ5E)23 zP1^PJ1_2wlV;?$4`R>@Bn;iNkxtzM3b; zB|t8@_5E8*lG<<-FWcF9*EjVSMBkUU%`V;c*9MAkYUbvR5}7~OHwaQ*TsjEgdEoJv zeDMwNeetmgNt)&Iu#ZQw<;V+Yj~fZ1PRdy>Fv>*%@b0z6m^xAAwjIHHD&zqFiUMh& zyQ@Y0BVN;!^<2{lWuBPK7ESKkNttsq$6t=`9PjU7M?Onw3GqD(IzQd0-etNMu8!Xp zI)vg*A6|rS8?V$ll(E&)E6-N#H4BZDiGq=7;ZLg#c1-tLP(>@DcxoMw`F%J2%k~@DX0y?sbbkDZ^ z{v;FHQ+J8$&IH3mJ;A@aTo4&-QMo8FG>?A6ioQOU`J?cPIA$*5(?ZM~Cjc)`&m;x1 zuh6~NCh_v8jR^@{@&)woWg}pCOIZ<(Sb>&gW;i)ZGnZE%fQ7wFtJwvA&^kZHjiL$L z&KR;rTOcq6&3zX9TMAYqFeLTG<=)3EFEx9zM z3ZXRYzUhld2VChpFB5X8m@{FWZ=E9EhrW`J!!!?1sd5yt%hyR(^qW^6R#IEYwTdj# zu~xCp;vE2$m-7}d)KKp@6Ur54*}*DH8)J+5F8F~oU`d=TyeAho|~!{*J| z7_%uH%> zR1GwpNgGz1TP$xJiFlJF`rCb*)XXGG-vI;ep+@vcvNc=+itXev4TPMzE8hByDM;}9 zx_41`8;2tIXnZmXi`}Tl)dw7+{k!;lOnIe|Lo@d+&xV+*%h6TkzjlWdQ)kWy)w~Qz z3v2f+@4R{cHbsj_K8M}5VZ$qlC2Dkyr=?2+Ka8-C=@NPMJHyxql}wfK+xPNq#Id6< zNP9ef(2~qntM2=c8q1vzG(;TIG{kjV#ZoXvhKm7BX!i|JHz4)|!ocY#+O$CYz|&C^ z)n+23h&?Ncf>r7JnSPu*aSXxpEtaV|e)BW)GW?VshS;x{eLV;3CeMwA6fCGz{4kU~ zsb;6*~=XG3Qiqp55YV42216|u@AG~7Pavf80GoWLYnEs|l%&>V+@M!Dx}i}^Dc#FlAT4x_5IXo;sjbcNB$#lu))7>~XpZ~o0azaM zxzLHkq+>vtmGJtaQoBz^f_TsYsAWz@L!Y?MzwD%%QH+PY*}xxVyoyPVi_#uF4Oqas^o z^1#@42=LLpzOdpBa41n8AhUR#$Z~lGWDsnNKi&?|w*4_?AlLOFU+PzBN`Y1l`2LMY!w{>R(sjb&pwAoBy%j;2LXO7C;`88Z z{dDDE7CmysM`aYc(sB2}FtA1E<*u==S1hOLkrK9fvyXxZiK1nkNBaho4ZlAiM2UNQk@lUw#r3F%l=LK9A_m2qygZyHa1 zYJz=~tEvy)X{uyNG>?z=!n2*NK0nvj4vi#u2p;6fDp~r+3b3~gojtS97IUujAS&6-s6}4~+y~K_9*Zm?Fa9Bj0 zAm*d0?60;Kw?78ii*)W_amHgzYkYLBlg$X0uVQ`5!_9+Kl~*Uro}PkNLZvPXDL|t9 zW~9g!5RB50)s3Dd!;u;lpe%Rb>Ii0kj%osMGtDZBqwB;50X0Z#PlmQb(e*>lRt-wP(n;dQoz67gJr%6F$xKK7Y_^dn}=6E+*gPbBc0D(6&$o1#$CkWAm1|f;j^g-W_~=8GZKD)3H2!$ zu`oP%md9H4SZOe_v1H=?0h+ClJVu%qB+^*F4n~~fM6lvqi8iL&5^aEoX(z};aZgi4 z0}CZ%1n~bx-$|SHTtTHnx~Je&)=X*AwZLv0M7!#ziR~@u3%=cV#!vIeQmQtjx{Ftf z(}lw(z7iM6=-X&G$4K8VQhYs{as!J0DTAPm5|DhmSzbZ}^`2sXTNrn=9)J^%9>-*! zvpptY-)KDkm=t8O2^w!cg}R+ihufs9sQY1r*NpBP+h~+-N)+W^Nuv#?s+{Z42&K=G z;HraPh1M66tLvlqNF{lscdzH*-zHZPM?RX#o9*(eT7a=)y5Jla-WR%PBcKic{-G!@ zb%oR9J*$3^Id+*JtCoY`**dCz0bhbG%zWR{-C11fOld70nc&H&|8#^#FQAIXpEGc~ zDg}oZs0vBU#tz%vq}mX%bRWv?6R(Ov!U0g`zucU zW?3S6J!mK`_x1vVVWX2I%e8a;rUF?Ms=icKv!cR*C}&II%NLH;M)Pz~_3V%-fduN5 zZe4jW{7b{M;=n@p+v45hEiKsMbSzA~+33U5_-7P+HC--WS$bIwDK7%fe;v`AzPN*+e_t z9311)R`jc^o*%^=ih0cQLs~ssjV&;n`c~->+sjA~jd7LJ&*l2HE(O7*neUF*cnh5; zNpp^L2#0J=*{rSAI{ZIH-YKTglMS9aC~v4#tGQie?EK(;Rums)VNZ`3ZMb_V=_`_x z0-FlGJmso&3~n3I0&cw@0#0_72Hl(Kn7aK54lG0?P$(%)=?3^!ChCUBT4tmW*n>LbwSD=rEmXJwJ z`9ijU(`ms}9a9XosL=EINWTrXR|HsZjEx`lZfZ;TcUAH)c6WnGmPbLxpf%o-~RuO<2t-tVW420vsyvV>U*L6!i)Dt#!*tfzgmp zTH9fx3J{*d!^25CtO99ewp;o2Z)&y&={RT7?$vVm!wg(Pm6S2Q>F$4~a@t9mMT((Sa+@$Dm24teZ`$2VikHh;5sHjC;%PuW zNK5fyG6g2860&jkw(*H`L>yx<5oZ^fNkyMUyfQgG{mb;%vhzb@(+nqWKURJ zn9x~Ome0B?RV#`5Z9S(1%SH`3^?kFUQkNejT1xV>@82AmdfZa@ly!O^DX zM;yCt%H-m+W6kN)|NR1|)v{*vS%U-#?6 zwA$EKmnsiCnE4ITVZ%;C+#x4URlK(twQ3w>__gTq=zD)vn2Ql=gE1TV9eZzsmFv#yu6C2EvohTw0>`tO7`iE+Hb?&B43%iQAJK z>0gTDXaGB!cpn2+1J988w|uZ0@5Whk`$KF^F3=q&g;V&+@E`XVXGCNuND;Clg`wWE z?a5+asx@uTjDP0^>jCy~jEtU~at@1I?t8M-ay_=TP4;lV^qKmu@+^vr$$5Y)-&)Nf z;Fd~{HXd7T5G#>>c`C!|iIl9WK(~(}Yj2S|#fFdL?ul(f!hooE*y>JMabf+q)G@6_ z-De10Ff<7>4-;j$D9^HWVpPZ>fcm(5U#GwA#cy;)z5g z{!knLsKEV7j9x$2Kvsu&pXVWQ+h)&Sc7|kS07ENdnVl`pdM1xd?o5YcT`Ao=ToBae z`#5*!^gw>#)U^E^ji@aGg2O|bWM@nqu{qiBOkc{fU9av=D;;A{{OjC-!L4j{=^|HV z6U*$Vy0-=z{f;Ejt*Q>TN+K8r9k}n+kJO}-#-=3IFfr&Kz5uNu>%Y*yc`G>E;B1dM z?pO+VwHhDhH~H?!BHOM9mT|P0TIBfYreTF1*tx+gu+uB+lN<~{ei+W6(=+*FWdY;u zjO1(UQnH!{`|AtXU28lMKG{PzBU2M3sS?qg*x6KL-FlBuKzgXrKiaA*ksc&EDa$-h z&BlyBy=@NElQxK1eytdc>`34tPmE@Ff2`6}K6Q|7Dvj~sfnRpr0fqTgY_=h*@pyB` zxuZX_t!F4o`YQngC4QQN9P}VYi>GBopN@@Xuo1A{h_M$hht?rJDsH# zs$4m=vhF@#oTlG7Rw%PM^`LAha4kM&p^V^Z-S3^*KVLW@63p@;kcO4MT+i#({VM9< zh^_KLo2Mu~zrhtm%xzhu%ikzl8v%Cqp7)sdPAJf%-(Bc8*G3)LVTC-m!+j>)q``nq zX4l0)D&0HC@TDzn&D@SOEw8HBlHcP>Yq{jgR4;giEkmthjBhD`YYij$M}K%P1=IZ= zjBs~($8l6-fg5>);ZmH|6hnhg)lr#h2)H^x5qwWn@i8MvBMGL0$Q&xpgSe?oU#oGt z=k(@}-<9~bq&=#ii&Xe{y==pPjU;c_Gr34~53~5$BM)L*rlnOFY_UB%l0lN1CH^CU zwDnO?im+`@!`+qiy%cUdv6S1U6XRqWMnBR+M|gzSqg>XM`Zn{E1ReYsgV8zF%w0S$ z@rpp+RgVR2!t2R8$kD$t-p2r^M7}@^$7ZSIN^Ora95nixHz56Ny(#@^)ExIhYI>;Z z+#<_eGJHrpk&8yr;p!@kr3d4O{unumSKpGcoDsp@8`)+(I|Io`{r#(2Bieny9=gz4 zolW2N=WtHcEY3%abU)~Ob!VTRbl<)_J_TuHUnT#5VAK%_54sFy4UqrntdGyrm=;j0 zD!LhR!hf2=XukzQdV*;{_JEPetUC)OPwI1Fe+r}{YB7ogOXuS8>nK((4X?>)v2=fm z(rLApWMU_kQq8PvqarX9O*3CL=O-sk4t(92GB%eUDS}nzDA7M5uI^o?V zAD*3jP;kVWC^^m00fy`!3A0twD_8<6sM4!LxE0orBqUVAg=Ea>Z>CH4vy+3+-*w?E zYA$Q&sT&Gx-%l+)QVJn#-Y@*>qu#}}ve@J}Nsc}E)v3rQBMf^1?M5gh#{BUj1zyJM zrP)10_9-i@pl?F!&cgD~It!j=~T4-sh#_}9#38`4oOqP{H z^hJ>kq|*1DpX=G30lUXI4E89Ion;uInH29${O{gaiA7VGYZLX%JWZCP%!7`akA~Hi zR}v=*bPP;fbb7qFJ@l9_h*siWJ>_>W^#Gn<(eMr?!J9q4FfY7nv$meyU5~~iDk`eU zxjEEz@u;)DqX*_ic_e0Q#h=h=ac z%td=O?&fV_A3d#n8%H+8Lylv6*t)Q7#ZS4kvqKR4N;ABRnz~mS*X9?N2D8O>n&qUt zh=x8Kojanr4_Z*aeK@`3{GFJ)hy1Q@V+SbnMFI1LChP8qzyksD0((^DPcM2H9#g(h zy0=aJ*rOp!^EkZY$nV>{f2Dw$n%;oS`Qgj9w;zno?4w*XlsY^?6nM8GhU$^w(tgM- z4{ahU6N=31#eIjjbC<^Y4Co=WR`GR`Qg24&-^?M?E7tFQ*j2P)ng3!EQUhTacmv~XrQtsysugQ% zDJ{M1{Pd_gTyx8{!LGm5G&hk-^<`nQrJEami>U|U`tdP&wP}kXg*{J?o@8qx--C!2 zks3MjL{ofvo4QxG$DF(TsHHxbX#3G#_9X?s%KP{wcp=N)P`LaFW9MvwFnU%_0uL&Mmwo;&- zk7rN;X|##RdV3vJjbro%9*|ERc?Qr!dcc&44@5>qWD9sY)dI$8RjV#e-^Q&z;F2nd z#3UG>RsC}GBswuusHDWA?cM>~8)iEJa~;8Bq)4VA*a>nIzoC^eMqYM>q$f3=fmtz;X3wwr~Q6>Kr+(vBzu0-vYafh`|oaa9$K46Ji4VVL!Fhl z6pu_|VKuq1eRKnaBq$_wk+mht6hYlur zN^)L&IFZo~2bcelBe>+&S0ZScK)^6LdeN73Whc(%UGi|l(e&Xj-Z%tUhI0C)G#Q~z z6bWB*FIG5au}owJMZ|+niS6v{`XWZR2t4Jb~!D%=yU~5*gxSWO`XL0^g6)78g-snLe1wh<_&36Hc`Ps3{5h3$z(h zwHNrLp+21Ml$XI!Z^sX}zUhUt1eWS1t|zagUm+hv$^j>c8pS)bmX0G$3&a1{<1%x1 zLnLRY4TUm+QU@EMy|mv>1Vp4fADYoPA~bzQd4vVli*@%}e;lKN;u;`?|IyKnF^?+| ze#q{8KG^+a8u~0D8l2LdRP>=D@Ku%l(EcjI;7%VumlJW;kzGo+;rzsN{;K;D_9r4 zcUbW>;RqFp-9q2#$yt^n+70Bb*;fV%=lp~(>)ynfx)Ch|pW&)4Wa&5|#cA~!+b$&E z&GYsMu1anqm=#6u?q_&jBckeTMG*bU$31l3){TB}erC33#jUN!eb{XHo^FS%%PcaA zM!);ne1z6A3Sfit5)XeEbIEfa0FeC=?*dG1EPh=GYWV+}InSV|x@O-GIZKu-Fepht zau8;QENO_6k(`qV5{EEIP6CQZ6cq$Xf*?6aPLh!%89`7aC}GInJ=Uda-sc`}J*Uo> z^I@-luim}a>eZ{LqM+*+nA+Om`d(N2KAmISfihi#gu8we1g|?Riu`>|NN(yTA1O?i z*hUp^$1~3Ivw$Ju%k}Qu$|q{C>RY?RW}*()pC-PqYSK@$WlvdN+&YU8N!BOZU7iJV zY_ZM?KrH-&-5xgh?JY$;<0>5xdA&w3H9yyV-pax}-%PR;V+M`To0X~6Yv|6Qcr@d? z)xsDzslL2DSl|DVyiL3s<^FPf3+aWm#{2>j6q{Qx)F;tbtC8TO7o>%{)|i;!?)#eG zIxG9d;{GR&shAIU{W()~W&HlI*Eccp+r@uf91IFP8NdHTPfa^y{%Mu0$*r$PSoN7R z3H`dob8U!iSjTqoiJd=a=muijAL`CLE9YQi!#Obu6hS?0x}RFZ6}~vw z)ZkcUs(z13p74NtYjM7ve0bB%&iOILBU1u`sV@TCW4__+j#aG@hTmi7Lw49Wph?Vz zHI+4q1c^|&;-+Mw@rpJ7!`57rj-jyX(mAHFD5W6$9>S41GpAbRnwie?^YhWBZPz`I z?X$$;>2(3zFKq@SzS|30^b06Mrg9aY&eo;PH<}}sZV$XP2kiv0 zlCw4?vYzhTsr|E~(1=>M`CzgdUyZOSOG&P!s15qVZj!wk-h}vbO1yfh~3O~dnhh0OW;s&vp{~g+BSHu8R6R&^hrqRn$`ztmcYZ_ z?sYfK8(~6`C*-UtYJCYeo+JtXSeiT8QU8!dfjuKFT@3lSvv>q0lyfr_y%o>ZUG`wY zqBPo0lv!X7q5Cybyq@Xs&ztKk)lJp31wcm)X3y0{KNa9b{u>+3FS0du1NyQ+$bVy_ zxkj<&KmNx58~Y-MfA)8wd$%kdT+sX*HzXX(BK zI9E?#nDzx5>Yp5{3pNzmk7-}T13hy8!Ii@FU&NzhFzshKEPr!A`~QuNW)}Td94a(J z$q{$w@BRK;`@h3wLZ5{V%MV~WQT=6eUD)WlapT0HSz&)`cwwW@h|UM?zs$biFQH>F zZFK&cID3D;{Wmtv8TfAwK#$kQ%j}E%(J`0V7kQ#%F0(K4M8{y-7kQ%n|Hj^AoP{b9 zIlzeOzBGQ|nuYq4JHW1JmdTWMF~Cqo8t8ijDR48xMyAzZSxemwm@FgV)i9{qU0;|z ziN6dcrwEfZr1!`L^5J?2>;cLR@;lN65=;!1}f)}is0T+6(a~-zbF9V~K*Mef^ zhFL?*x?#p&mIJ0Av!18M+z^Oj2+SK`TVeWNbjLwu{&>U0g`^>vxnb7xmjO3q(iq@t z9lHGo*9$Y}%htinnJU}`f^QlEyK%w;;Rf!JUpoY*l_1rGdB2y%VBS0CSr)cbA)Hzv zuot7|O_+J^?x;eR%tK)EXX=p4YJ%y4XTkjTvKY)YF>8qVvw&I8 z%lwz!5oSFxV=!xiS?9~@hPe)Ayml*rESQ}dc9~}K;la@FFH`SSnUCoAmnnK(*RgpR z@&I4f*7oK{;m)1E>-~2$*k}fZjz=p+=N}lf>i^ZWTiY=7`WIT{fBtuVnWEQ=e)#0? zx@bk84^z?SLC-G~{T{?9-}FyKzeoEobRIJMH|{b$Z+Q2&UKg4b7WsGn|5J1x==T?j z-VZ&$$cGWn>~H>PMV|{((Rrcg|5Wt;X#a(x*F(=QQ~YO3u<$>T(0?kr9%%nR6}=zY z|4&8lhxT76dO!61GF1iL0oY5bz;gp&DBT8nyd{AL7vMDU0SqQZfPh2&QDOr)PK*GPi5K7`T>-``0N;rX@KXaL zH9%;h1UOJ2fa!z+LHycvdGk11QP%&gl%^D>jp> zJ|-Yb;o~a&LHAO-Wx&!jt5<;v=&1ff=xPooZ6ggCB*E%QS-48hHoA|n)j-`V_nmx! zO_a2L?gEZ$e&2DMKQmr#nwxR#MEdsHDS($R#9_P!I< z+<3Og=`~g(Tp1C1Mh>$@AJWl==c__wDTE2%C2mlecNxVpAhq{h!DpmTIr?87K9pg{ zwikWlRv0_m&JGqNk*onxVp-Kv;(~0*ET6f+_d_X(hP5r51-?JSaw-!FC2)LeXVt86 zO1DA&V9?IZ$~4RP_E?nI&Pi`ef70W{H7ll$Nf%Nu&d;-Q8Z9eqD~chcO0u$Q12SU= zJQ{4@_{UfcC7a6}8EpwRWCx!f`-8?^bw6|a&UDVuhcbi*J^vg>C_`7EYo5avoQY+k zAzSMlcJ(=m%EE>TA`(p)xDlsh5K_40^Vsv79korFhr(LOZFpHD%bLs``hBd zD%wL`>s#M_23nVPvUX(?WA*B8mrSYt+343Y+@of1YoBKpHW=(s9%%1hY$VwBx9c0q zB*R)e8>IP6IKg_fo|~8v`RXR~RcpV~b-DWt!zMW5pOW6{ORyIzik~Wo{Cvefxc$NQ zF!QFf8|8Ov>@BM_VivbgM@Nm^Rj=_(s*)j`(JZ|?nKE=R8;O{6#HiP8% zIJk9EobBZCercH46iZ2gqlfHgq{C_~Y}Ibh2~~i9m&NP1^gfwTAKt6^>I*=`n!;{CI(bA9 zFx;;T;hFso8eON}d2&C=N@jD0Yq`iKwT2%q7LRf9_TI>Q$`O-k3m40Ia^#+<+;q%n ziA-%h1taRzC=TW_bv-k=uXRuy-4(i$LAcT^@3f&*?n72hZ{nQl5f;F5UN&+77Kt#xH2jQcgC8mI#(cgS-eEbdM^GH7KztYTlQ5 z7H0&Y;%qeFwsE7d6&A{Dc&JB-RG@P17wxinuf`Eh7x!AJ5n(Ikfh`?r;kyEMS2PPz zq!TowladB*{WgcZ?2gZs6LbjO?JD4`>WVuGxc#JYyP+V~QT0KD$6)(VyN@cZz1Mj% z?Ub)j+p>Agd%FiaelnIOt(DOPQ;$p#5hT0X(zvoOIeUB{PT)s51o(twnd?K~mUFuR z-By*GXNvjh-FKY*mk`VM(<78DACR2NT%*n&=|eOz-fU~kyz;iyaU$;;J{Wu|<4WBo zddmi>vnlM#pu=^foDd8DCRgO-95eLCXm_2;i{{P}v)uMW#peO!=9|&@ulia~dDa%E zB*Y@w@G0(4YiA^soe&NaPmg-tkK>Le4EI~EwBnvnyt1AkulCX`gMUo$GdGneIeXDE znAy9{p23SDF2Fu@DvHrlm{wjoY~7g4wrb-zDwum;Qn2u(<+bmVE?sCY}ry!Qx+%K`??UfQ* zb1>t#Ktx;IBVBsZCH%|Wt>2tq|!P-|np|f=(Ezpv-1_ZE4lFc&=+DhjS)Z<4yZO%OKCdv`=88t2ktu{UV`_ z4AusP1D_<#$}fz(duT?3hVBqX)11w)pGWcx?GpR!$d zQ%kab z7+0|sDiu+2-?C)jI2UTC_u7v*4c#SO4onjYM_BeWJ=M;8F%NwkGA+BVYa~T%T8SmX zwID=x{btLdXL>-K)Ek@|I4uG$IUz7QkId`v7PT+VK7>R#jc#-*-rv|d*7O!C62pyf zQxzmUT6BC!6K1m#;6yaI^>%_C+#|naWoI*(^-XF%t`bwW(wiVQONI2SOn7l@T(=aH zDb5@j*!Q=#-_IfD6GRxOAJu2*Y0uuuh7N-~q6trf1#0%U%TU^Uij+z3W1SbLPH4z` z=$$DRKD=@ws+zHZ+EPE6jFe{Z^5HDDay$=qGgvinM$yYX8S2DqxvqnxaOI3L2Sb0b zFYW78*uYDAS3W1HHjNF$tY4LlXU8^Rd+Us?q{O7-#k{O!j2oCSB++V`b6d@zOYl&I zklbYhr?i2AB`UNeqp{6jx#gD`fpX`ByPt$@4{1w1)5mF4wn+`VRYSj@4*M?oLuL}4 zKjy^@-g`BslU3eagx!XLSCtdg*t34`JZ zJ~FAPNbLcOvH&e!4lVP*G_eRTJ=7(3ZdD%TzGsePL)Ky{UbpS1rj5q@IA(mdKd)T9b46b>L_NyQx{?b%xJq);{Hrvjv;C`g&j6@_}Sa@CUeh^j*H zPDp%FJa}7PO!W+YAds0_UFdVm(@v%_{D%qNaGG#rDFqjENmi_!DQ6*Vn1K3O;Z4H0 zY`K$C>sm_r?=KEYwSCEU_=>~vC*?*$r#C+{d#5bs(nzi~G(L#op5&MFUR^9*!G4(Q zXDW?DOpq-)xoPDPzO)*1>qlh-*`ulXfRE{4s!*gXN+pjSuaB7$=KcJxciV(@ib?zP z2WeK9(|mV3jzwAQ=@xb#Ry(4vJoCl^RytEmSW|K*Xdwwt`CQfJheng zZ4TmgIY}&V#^v`TtFAKdBf6Qi&PZNuO)wswtwgT}t=1XnjK zok-*zlIG91yeep~Jbyj}3Xv&^SgZIM{b!K2(P}z^=MEPAordv^)3B$IYEp^^oBbg< zzV{Ns*Y&f1-ZEj4h&@n0GuW6pP8fCDJ$n&nDo62x!BN+x9cpjEYT* z+{>Jf1#ccxior!qP3I=KIa7Mn62gDkLtun)ARJD4miU-b?Za>j1L4dew@gR2S~}r5%NCpPJKz$4w;LdWEV5BRpU*u zw|jQY1#Uj7mfcQdYfNO7uJD$*`eA0jlo+#v*k{icR<#WqFHvqWwGDoko2MCByezKg zfo|vJ`>JN+3;Y%{cM7IX`s16^gV%oI(=ga0ZzUAJ4+QPkGDeY)96`!gYpW1Hlqs?x zR2E$tNVC0s3moQ}uQsCj)_i?}5^wa<@fvqq-)orGD_KgpOKqg>{TehR8l1OBj%1qG zgjjKYxC`RErO4nm=rn$|JGfeA0gKH+fwbSMsw@P46%x^Aby;{uK%f0SZsWFyYe!AB zW^{~B*LRPN-@!Vw%Vw>L4-e)@5#82Bf;!K{7};L?D7(Mr@WBJI>3tIK^LOnd70ZZK zmLkf;``T=zeATMOy-^c^T%#Oxw}iL{@L=El@&cXw5TR$t@_r@U0rGnR;Dn%h2_?pb+vo4pi;5G3 zJqruFc~@7?o$|w^&&mbM{8&P`rX-3=R~O8@NAVSEhq=RC?j&~2YuSLdPj4%1Yr4&z z5XUji)Z(^HD87$0{zUVXVy`ku>3T`-$Hwc{=Y;08N{~w84-ecn8y~6%Cz`*01$QXb zbv--VT+2c=jPK>B;I6(~kfGhCc2%#bvksR&+1x``PD^pTETDZ_5Mi_hh@zP>+PG_T9|1nbwk@5|+c(<@j;yGJ2S z6&4j+?$aX!DCD9+AA_$o9JpE;l<|Hia(5B7LOM^%G z2xL^6@W>*!N>Y%n%7q_a8vZUkH0yOWtYE;KB0W8oNdXPl-HP31&iV9&UvO?VfuaKL zNx<$oR$8OE=fczIcA51wdDKbY6bU^ik6vjBAk zv*36z^W^>(2~dFVuQwnfV|?yXoy`JWDH$I30JYyo@A@61ojaeXoT51W#kz<^QEOT;|EK+dF)gz+>D&Vk=;C2;R!F)<@Jb? z#U?4M@GD}dACQgEkn4Gh50kc6jY>*^V;PD;jkc7}vNNF1$<1p!M`P2_x76%F*_$Hq zZo(eFI_a9~SJx7Q5uRSHJ-um>DaEWyds{Pk*2#F-0*9#<6IDxdh z_Q_0_?=C(e9xt(B`eYV#vY|HN`C+VpTf0CIK+aQ12u9i@3NatjPtwZw}*kEI@sDVZDCe|Dcz|L{Oc!DdMG34vpkB+IYk z*!DgwNz~G30&pN1)K*Y; zn-;z2PEVQijksp|aRKkB-*bpzSp*!X=(D28EqI>M>$_*AMYueX=K8{q6{dTf$b^Ku zK#W^smU!=_@s*WmbeY)X#!`))vV^{sYd6fLj@QIGOjIX-37S5po9Q6i93gAD@tDn% zC~qQf`npGO%qSnb^%W_^H#*B|yj|Ub=Sr5&-3EP64pPFzX1iY(&(2le_pJywOb;rH zRRYPJc>i>%HzeCpP((Hjkrub5|GX-fFLD_Ygs;XO@ei^H#q{%FGAvoUS*sHwt-USRPtVHlGhj-u6+l zCq8*fW@Iy;+BxhvTjcc1{mz1+uSa+2n-Ol)s^siD+)2b>_XFR^Z^tJ08FUxESRf$w?<}Ov%qKV}QQLg=UAT!+ zczf(W(l&LQ+|)xA5v5kxFO*LW6K5g3A2KtTCi92(Ol+(X#vGzulakN`|C&-sSb{~) z$msQ-3hZwyq>VVYuE>%$$F7yX;y40t6XY=CtJwUuIG&i6DKQp$I&C{6v=q7NGG*pN zqD$v8>jbOJ;SZJc9TQh>7hnBEfd!#>G4#eXEVX-RJ@n;K=a;E_w(^RCoebTg56KXx zEIy52EAs1^OS^iFawi-WlU)n*zh7s$rqi5{e7_!^k>Xa|lQ-{bvRYnk%sm{gX}&gu zbM2s$?sMO-p`tDx^T8AE$-!YE%Frr#PQE}Dp5f&(&ap}x{B_ph*$>lXoZPK7 z>Pq>>1AOByhgRFKl`Ld&+MVHwtVh} zJey)wI10`VqA6inI8jgGl#icUnCKQksb$~>I&dgUi<5Z|uG->l(K%;_G$K+mZPEr- z5-8q$gs_iib|A4Nv=`D1axrkv%QV21h2BfZ+^|h}?dw2+t6%8pS{6O#%%FHkfM9K$ QTyAH;LI2YfgJbi50D{b{MgRZ+ literal 0 HcmV?d00001 diff --git a/world/generation/chunks/assets/chunk_0012.glb.import b/world/generation/chunks/assets/chunk_0012.glb.import new file mode 100644 index 0000000..65fad11 --- /dev/null +++ b/world/generation/chunks/assets/chunk_0012.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c4i32u0bdtix5" +path="res://.godot/imported/chunk_0012.glb-1c818ae539bef19d5ca4fbe3ace96887.scn" + +[deps] + +source_file="res://world/generation/chunks/assets/chunk_0012.glb" +dest_files=["res://.godot/imported/chunk_0012.glb-1c818ae539bef19d5ca4fbe3ace96887.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/world/generation/chunks/assets/chunk_0012_cliff_wall.png b/world/generation/chunks/assets/chunk_0012_cliff_wall.png new file mode 100644 index 0000000000000000000000000000000000000000..3fe157f58237f17fdca91532dd58dd47fb9d8335 GIT binary patch literal 9025 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 literal 0 HcmV?d00001 diff --git a/world/generation/chunks/assets/chunk_0012_dirt.png.import b/world/generation/chunks/assets/chunk_0012_dirt.png.import new file mode 100644 index 0000000..bdc481f --- /dev/null +++ b/world/generation/chunks/assets/chunk_0012_dirt.png.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c3f1w276lmg7i" +path="res://.godot/imported/chunk_0012_dirt.png-5c3a2a10642f9d078ad1d1c6333d8264.ctex" +metadata={ +"vram_texture": false +} +generator_parameters={ +"md5": "07d90b3c46a4c3d0c172bed143dc9436" +} + +[deps] + +source_file="res://world/generation/chunks/assets/chunk_0012_dirt.png" +dest_files=["res://.godot/imported/chunk_0012_dirt.png-5c3a2a10642f9d078ad1d1c6333d8264.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/world/generation/chunks/assets/chunk_0012_grass_lite.png b/world/generation/chunks/assets/chunk_0012_grass_lite.png new file mode 100644 index 0000000000000000000000000000000000000000..52c7ccb8088ddfae88f9b861a807f1de2d38f855 GIT binary patch literal 6317 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 void: func generate_world(seed: int) -> bool: if seed <= 0 or seed > PlayerSaveManager.MAX_WORLD_SEED: return false + if ( + seed == _current_seed + and _generator.get_generated_chunks_root() != null + ): + return true _current_seed = seed _generator.generation_seed = seed return _generator.generate() @@ -237,29 +242,34 @@ func _on_generation_completed(summary: Dictionary) -> void: _prop_definitions_for(rule, tags), coordinate, ) - if ( - definitions.is_empty() - or not _prop_group_roll_succeeds( - rule, - group_key, + for _placement_attempt: int in ( + rule.placement_attempts_per_chunk + ): + if group_counts.get(group_key, 0) >= maximum: + break + if ( + definitions.is_empty() + or not _prop_group_roll_succeeds( + rule, + group_key, + coordinate, + random, + ) + ): + continue + if _maybe_add_prop( + definitions, + record.get("position", Vector3.ZERO), coordinate, + biome.stable_id, random, - ) - ): - continue - if _maybe_add_prop( - definitions, - record.get("position", Vector3.ZERO), - coordinate, - biome.stable_id, - random, - terrain_triangles, - ): - group_counts[group_key] += 1 - _record_prop_group_coordinate( - group_key, - coordinate, - ) + terrain_triangles, + ): + group_counts[group_key] += 1 + _record_prop_group_coordinate( + group_key, + coordinate, + ) _ensure_minimum_props( eligible_records, group_counts, @@ -322,7 +332,7 @@ func _configure_static_water() -> void: _ocean.fish_pool = OCEAN_POOL _ocean.location_tags = [&"coast", &"ocean", &"generated_ocean"] _ocean.surface_size = Vector2(10000.0, 10000.0) - _ocean.position.y = WATER_HEIGHT - 0.025 + _ocean.position.y = WATER_HEIGHT _apply_water_materials() @@ -451,6 +461,11 @@ func _add_prop( ) -> bool: if definition == null or definition.packed_scene == null: return false + var visual_scale := random.randf_range( + definition.minimum_visual_scale, + definition.maximum_visual_scale, + ) + var scaled_clearance := definition.clearance_radius * visual_scale var placement := Vector3.ZERO var found_surface := false for attempt: int in PROP_PLACEMENT_ATTEMPTS: @@ -470,7 +485,7 @@ func _add_prop( > WATER_HEIGHT + PROP_MINIMUM_GROUND_CLEARANCE and _has_prop_clearance( placement, - definition.clearance_radius, + scaled_clearance, ) ): placement.y = surface_height @@ -492,22 +507,26 @@ func _add_prop( prop.set_meta(&"terrain_prop_group", definition.procedural_group) prop.set_meta(&"terrain_chunk_coordinate", chunk_coordinate) prop.set_meta(&"terrain_biome_id", biome_id) + prop.set_meta(&"terrain_prop_visual_scale", visual_scale) prop.position = placement prop.rotation.y = random.randf_range(-PI, PI) _decorations.add_child(prop) visual_root.name = "Visual" prop.add_child(visual_root) + visual_root.position = definition.visual_offset + visual_root.scale = Vector3.ONE * visual_scale _configure_prop_visuals(visual_root) - _add_prop_collision(prop, definition) + _apply_prop_material_variant(visual_root, definition, random) + _add_prop_collision(prop, definition, visual_scale) _placed_prop_positions.append(placement) - _placed_prop_clearance_radii.append(definition.clearance_radius) + _placed_prop_clearance_radii.append(scaled_clearance) _placed_prop_groups.append(definition.procedural_group) if definition.gatherable_anchor_height > 0.0: var anchor := Marker3D.new() anchor.name = "TreeAnchor_%d" % _tree_anchors.get_child_count() anchor.position = prop.position + Vector3( 0.0, - definition.gatherable_anchor_height, + definition.gatherable_anchor_height * visual_scale, 0.0, ) _tree_anchors.add_child(anchor) @@ -624,7 +643,11 @@ func _prop_group_maximum( if eligible_count <= 0: return 0 var maximum := ceili( - float(eligible_count * rule.maximum_density) + float( + eligible_count + * rule.placement_attempts_per_chunk + * rule.maximum_density + ) / float(PROP_CHANCE_SCALE) ) return maxi(maximum, rule.minimum_placements) @@ -777,6 +800,51 @@ func _configure_prop_visuals(root_node: Node) -> void: _configure_prop_visuals(child) +func _apply_prop_material_variant( + root_node: Node, + definition: TerrainPropDefinition, + random: RandomNumberGenerator, +) -> void: + if ( + definition.material_variants.is_empty() + or definition.variant_material_slot_names.is_empty() + ): + return + var variant := definition.material_variants[ + random.randi_range(0, definition.material_variants.size() - 1) + ] + _apply_material_variant_to_meshes( + root_node, + definition.variant_material_slot_names, + variant, + ) + + +func _apply_material_variant_to_meshes( + root_node: Node, + target_material_names: PackedStringArray, + variant: Material, +) -> void: + var mesh_instance := root_node as MeshInstance3D + if mesh_instance != null and mesh_instance.mesh != null: + for surface_index: int in mesh_instance.mesh.get_surface_count(): + var active_material := mesh_instance.get_active_material(surface_index) + if ( + active_material != null + and active_material.resource_name in target_material_names + ): + mesh_instance.set_surface_override_material( + surface_index, + variant, + ) + for child: Node in root_node.get_children(): + _apply_material_variant_to_meshes( + child, + target_material_names, + variant, + ) + + func _terrain_surface_triangles() -> Array[PackedVector3Array]: var triangles: Array[PackedVector3Array] = [] for mesh_instance: MeshInstance3D in _generator.get_primary_terrain_meshes(): @@ -818,6 +886,7 @@ func _surface_height_at( func _add_prop_collision( prop: Node3D, definition: TerrainPropDefinition, + visual_scale: float, ) -> void: if not definition.has_collision(): return @@ -830,16 +899,16 @@ func _add_prop_collision( collision.name = "CollisionShape" if definition.has_box_collision(): var box := BoxShape3D.new() - box.size = definition.collision_box_size + box.size = definition.collision_box_size * visual_scale collision.shape = box - collision.position = definition.collision_offset + collision.position = definition.collision_offset * visual_scale else: var cylinder := CylinderShape3D.new() - cylinder.radius = definition.collision_radius - cylinder.height = definition.collision_height + cylinder.radius = definition.collision_radius * visual_scale + cylinder.height = definition.collision_height * visual_scale collision.shape = cylinder collision.position = ( - definition.collision_offset + definition.collision_offset * visual_scale + Vector3.UP * cylinder.height * 0.5 ) body.add_child(collision) diff --git a/world/generation/generated_world_region.tscn b/world/generation/generated_world_region.tscn index e46796f..b9d3a0e 100644 --- a/world/generation/generated_world_region.tscn +++ b/world/generation/generated_world_region.tscn @@ -31,12 +31,13 @@ gatherable_anchor_root = NodePath("GatherableAnchors") unique_name_in_owner = true script = ExtResource("2_generator") catalog = ExtResource("3_catalog") -grid_size = Vector2i(7, 7) +grid_size = Vector2i(15, 13) generation_seed = 13001 generate_on_ready = false build_collision = true force_center_chunk_id = &"chunk_spawn" -required_chunk_ids = PackedStringArray("chunk_spawn", "chunk_0001", "chunk_0002", "chunk_0003", "chunk_0004", "chunk_0005", "chunk_0006", "chunk_0007") +required_chunk_ids = PackedStringArray("chunk_spawn", "chunk_0001", "chunk_0002", "chunk_0003", "chunk_0004", "chunk_0005", "chunk_0006", "chunk_0007", "chunk_0008") +elevated_cliff_feature_enabled = true required_chunk_weight_multiplier = 64.0 maximum_backtracks = 100000 @@ -60,7 +61,7 @@ script = ExtResource("8_diggable") area_id = &"starter_beach" terrain_source = NodePath("../../Terrain/TerrainChunkGenerator") surface_materials = Array[StringName]([&"sand"]) -generation_bounds = Rect2(-35, -35, 70, 70) +generation_bounds = Rect2(-55, -45, 110, 90) minimum_global_y = -0.24 maximum_global_y = 0.5 minimum_up_dot = 0.72 diff --git a/world/generation/props/definitions/prop_mushroom.tres b/world/generation/props/definitions/prop_mushroom.tres index cf63eff..e4bff54 100644 --- a/world/generation/props/definitions/prop_mushroom.tres +++ b/world/generation/props/definitions/prop_mushroom.tres @@ -16,3 +16,7 @@ preferred_nearby_prop_groups = PackedStringArray("grass_tree") preferred_nearby_radius = 12.0 nearby_preference_weight_multiplier = 3.0 clearance_radius = 0.8 +visual_offset = Vector3(0, -0.08, 0) +collision_radius = 0.65 +collision_height = 1.0 +collision_offset = Vector3(0, -0.08, 0) diff --git a/world/generation/props/definitions/prop_pine.tres b/world/generation/props/definitions/prop_pine.tres index 19361c8..0a569cf 100644 --- a/world/generation/props/definitions/prop_pine.tres +++ b/world/generation/props/definitions/prop_pine.tres @@ -13,6 +13,8 @@ required_chunk_tags = PackedStringArray("grass") selection_weight = 0.7 minimum_spawn_chunk_distance = 2 clearance_radius = 1.55 +minimum_visual_scale = 0.75 +maximum_visual_scale = 1.22 collision_radius = 0.5 collision_height = 4.0 gatherable_anchor_height = 2.15 diff --git a/world/generation/props/definitions/prop_tree_1.tres b/world/generation/props/definitions/prop_tree_1.tres index 4b942db..41ab406 100644 --- a/world/generation/props/definitions/prop_tree_1.tres +++ b/world/generation/props/definitions/prop_tree_1.tres @@ -1,7 +1,10 @@ -[gd_resource type="Resource" script_class="TerrainPropDefinition" load_steps=3 format=3] +[gd_resource type="Resource" script_class="TerrainPropDefinition" load_steps=6 format=3] [ext_resource type="Script" path="res://world/generation/terrain_prop_definition.gd" id="1_definition"] [ext_resource type="PackedScene" path="res://world/generation/props/assets/prop_tree_1.glb" id="2_scene"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_light.tres" id="3_leaf_light"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_mid.tres" id="4_leaf_mid"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_dark.tres" id="5_leaf_dark"] [resource] script = ExtResource("1_definition") @@ -12,6 +15,10 @@ procedural_group = &"grass_tree" required_chunk_tags = PackedStringArray("grass") minimum_spawn_chunk_distance = 2 clearance_radius = 1.3 +minimum_visual_scale = 0.75 +maximum_visual_scale = 1.15 +variant_material_slot_names = PackedStringArray("leaf_light", "leaf", "leaf_dark") +material_variants = Array[Material]([ExtResource("3_leaf_light"), ExtResource("4_leaf_mid"), ExtResource("5_leaf_dark")]) collision_radius = 0.4 collision_height = 3.2 gatherable_anchor_height = 2.15 diff --git a/world/generation/props/definitions/prop_tree_2.tres b/world/generation/props/definitions/prop_tree_2.tres index 3d1ab62..c4d09fa 100644 --- a/world/generation/props/definitions/prop_tree_2.tres +++ b/world/generation/props/definitions/prop_tree_2.tres @@ -1,7 +1,10 @@ -[gd_resource type="Resource" script_class="TerrainPropDefinition" load_steps=3 format=3] +[gd_resource type="Resource" script_class="TerrainPropDefinition" load_steps=6 format=3] [ext_resource type="Script" path="res://world/generation/terrain_prop_definition.gd" id="1_definition"] [ext_resource type="PackedScene" path="res://world/generation/props/assets/prop_tree_2.glb" id="2_scene"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_light.tres" id="3_leaf_light"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_mid.tres" id="4_leaf_mid"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_dark.tres" id="5_leaf_dark"] [resource] script = ExtResource("1_definition") @@ -12,6 +15,10 @@ procedural_group = &"grass_tree" required_chunk_tags = PackedStringArray("grass") minimum_spawn_chunk_distance = 2 clearance_radius = 1.5 +minimum_visual_scale = 0.8 +maximum_visual_scale = 1.18 +variant_material_slot_names = PackedStringArray("leaf_light", "leaf", "leaf_dark") +material_variants = Array[Material]([ExtResource("3_leaf_light"), ExtResource("4_leaf_mid"), ExtResource("5_leaf_dark")]) collision_radius = 0.5 collision_height = 3.8 gatherable_anchor_height = 2.15 diff --git a/world/generation/props/definitions/prop_tree_3.tres b/world/generation/props/definitions/prop_tree_3.tres index 637a281..642a8de 100644 --- a/world/generation/props/definitions/prop_tree_3.tres +++ b/world/generation/props/definitions/prop_tree_3.tres @@ -1,7 +1,10 @@ -[gd_resource type="Resource" script_class="TerrainPropDefinition" load_steps=3 format=3] +[gd_resource type="Resource" script_class="TerrainPropDefinition" load_steps=6 format=3] [ext_resource type="Script" path="res://world/generation/terrain_prop_definition.gd" id="1_definition"] [ext_resource type="PackedScene" path="res://world/generation/props/assets/prop_tree_3.glb" id="2_scene"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_light.tres" id="3_leaf_light"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_mid.tres" id="4_leaf_mid"] +[ext_resource type="Material" path="res://world/generation/props/materials/leaf_dark.tres" id="5_leaf_dark"] [resource] script = ExtResource("1_definition") @@ -12,6 +15,10 @@ procedural_group = &"grass_tree" required_chunk_tags = PackedStringArray("grass") minimum_spawn_chunk_distance = 2 clearance_radius = 1.8 +minimum_visual_scale = 0.85 +maximum_visual_scale = 1.15 +variant_material_slot_names = PackedStringArray("leaf_light", "leaf", "leaf_dark") +material_variants = Array[Material]([ExtResource("3_leaf_light"), ExtResource("4_leaf_mid"), ExtResource("5_leaf_dark")]) collision_radius = 0.55 collision_height = 4.2 gatherable_anchor_height = 2.15 diff --git a/world/generation/props/materials/leaf_dark.tres b/world/generation/props/materials/leaf_dark.tres new file mode 100644 index 0000000..d75f991 --- /dev/null +++ b/world/generation/props/materials/leaf_dark.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3] + +[resource] +resource_name = "leaf_variant_dark" +albedo_color = Color(0.1712, 0.252, 0, 1) +metallic = 0.0 +roughness = 1.0 +shading_mode = 1 +texture_filter = 0 diff --git a/world/generation/props/materials/leaf_light.tres b/world/generation/props/materials/leaf_light.tres new file mode 100644 index 0000000..d49f786 --- /dev/null +++ b/world/generation/props/materials/leaf_light.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3] + +[resource] +resource_name = "leaf_variant_light" +albedo_color = Color(0.3388, 0.7187, 0, 1) +metallic = 0.0 +roughness = 1.0 +shading_mode = 1 +texture_filter = 0 diff --git a/world/generation/props/materials/leaf_mid.tres b/world/generation/props/materials/leaf_mid.tres new file mode 100644 index 0000000..d0ee646 --- /dev/null +++ b/world/generation/props/materials/leaf_mid.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3] + +[resource] +resource_name = "leaf_variant_mid" +albedo_color = Color(0.3147, 0.4631, 0, 1) +metallic = 0.0 +roughness = 1.0 +shading_mode = 1 +texture_filter = 0 diff --git a/world/generation/terrain_biome_prop_rule.gd b/world/generation/terrain_biome_prop_rule.gd index 96da0db..7b02e98 100644 --- a/world/generation/terrain_biome_prop_rule.gd +++ b/world/generation/terrain_biome_prop_rule.gd @@ -6,6 +6,9 @@ extends Resource @export_range(0, 10000, 1) var adjacency_bonus := 0 @export_range(0, 10000, 1) var maximum_density := 10000 @export_range(0, 64, 1) var minimum_placements := 0 +## More than one attempt permits intentionally dense biomes without changing +## the density of every biome that uses the same procedural prop group. +@export_range(1, 8, 1) var placement_attempts_per_chunk := 1 ## Empty permits every compatible prop in the procedural group. @export var allowed_prop_ids := PackedStringArray() diff --git a/world/generation/terrain_chunk_analyzer.gd b/world/generation/terrain_chunk_analyzer.gd index 9f1557c..84895b1 100644 --- a/world/generation/terrain_chunk_analyzer.gd +++ b/world/generation/terrain_chunk_analyzer.gd @@ -34,6 +34,29 @@ static func create_variants( chunk_size, edge_epsilon, ) + if definition.base_layer_scene != null: + var base_layer_root := definition.base_layer_scene.instantiate() + var base_layer_mesh := find_primary_mesh( + base_layer_root, + definition.base_layer_mesh_name, + ) + if base_layer_mesh == null or base_layer_mesh.mesh == null: + push_error( + "Terrain chunk %s has no base-layer MeshInstance3D named %s." + % [definition.stable_id, definition.base_layer_mesh_name] + ) + base_layer_root.free() + chunk_root.free() + return variants + boundary_points.append_array( + _collect_boundary_points( + base_layer_mesh.mesh, + _transform_relative_to(base_layer_mesh, base_layer_root), + chunk_size, + edge_epsilon, + ) + ) + base_layer_root.free() for quarter_turns: int in 4: if not definition.allows_quarter_turn(quarter_turns): continue diff --git a/world/generation/terrain_chunk_catalog.gd b/world/generation/terrain_chunk_catalog.gd index 3c73822..e6741f1 100644 --- a/world/generation/terrain_chunk_catalog.gd +++ b/world/generation/terrain_chunk_catalog.gd @@ -30,6 +30,19 @@ func validation_errors() -> PackedStringArray: errors.append("%s has no PackedScene." % definition.stable_id) if definition.primary_mesh_name == &"": errors.append("%s has no primary mesh name." % definition.stable_id) + if ( + (definition.base_layer_scene == null) + != (definition.base_layer_mesh_name == &"") + ): + errors.append( + "%s must define both base-layer scene and mesh name." + % definition.stable_id + ) + if definition.overlay_only and definition.base_layer_scene == null: + errors.append( + "%s is overlay-only but has no base-layer scene." + % definition.stable_id + ) if definition.allowed_rotation_mask == 0: errors.append("%s allows no rotations." % definition.stable_id) var has_coast := "coast" in definition.tags @@ -44,6 +57,11 @@ func validation_errors() -> PackedStringArray: "%s has an ocean-facing edge without the coast tag." % definition.stable_id ) + if definition.must_be_interior and definition.prefers_map_boundary: + errors.append( + "%s cannot require the interior and prefer the boundary." + % definition.stable_id + ) var has_fresh_water := "fresh_water" in definition.tags var has_water_footprint := ( definition.water_surface_size.x > 0.0 diff --git a/world/generation/terrain_chunk_definition.gd b/world/generation/terrain_chunk_definition.gd index 54f27cb..2d4c548 100644 --- a/world/generation/terrain_chunk_definition.gd +++ b/world/generation/terrain_chunk_definition.gd @@ -5,6 +5,17 @@ extends Resource @export var label := "" @export var packed_scene: PackedScene @export var primary_mesh_name: StringName +## Optional existing level-one chunk placed beneath an authored elevated +## overlay. This lets cliff edges leave their downhill side open while the +## ordinary base terrain remains present in the same generated cell. +@export_group("Layered Terrain") +@export var base_layer_scene: PackedScene +@export var base_layer_mesh_name: StringName +## Overlay-only chunks replace a reserved base-terrain placement after the +## ordinary terrain solve. They remain in placement manifests and runtime +## output, but do not inflate every cell's global solver domain. +@export var overlay_only := false +@export_group("") @export_flags("0 degrees", "90 degrees", "180 degrees", "270 degrees") var allowed_rotation_mask := 15 @export_range(0.01, 100.0, 0.01) var selection_weight := 1.0 @@ -36,6 +47,9 @@ var allowed_rotation_mask := 15 ## weight. This shapes regions without turning a visual preference into a hard ## generation constraint. @export var preferred_neighbor_tags := PackedStringArray() +## Interior-only pieces may not occupy any outer grid cell. Coastal elevated +## pieces use separate authored definitions rather than weakening this rule. +@export var must_be_interior := false ## Coastal transition pieces should normally migrate toward the generated ## region's perimeter while remaining legal in the interior. @export var prefers_map_boundary := false diff --git a/world/generation/terrain_chunk_generator.gd b/world/generation/terrain_chunk_generator.gd index df3afc6..091179e 100644 --- a/world/generation/terrain_chunk_generator.gd +++ b/world/generation/terrain_chunk_generator.gd @@ -5,6 +5,8 @@ signal generation_completed(summary: Dictionary) const CONSTRAINT_PROFILE_QUANTIZATION := 0.001 const CANDIDATE_WEIGHT_SCALE := 10000.0 +const LARGE_GRID_LIGHTWEIGHT_THRESHOLD := 128 +const LARGE_GRID_PROPAGATION_INTERVAL := 8 @export var catalog: TerrainChunkCatalog @export var grid_size := Vector2i(7, 7) @@ -14,6 +16,15 @@ const CANDIDATE_WEIGHT_SCALE := 10000.0 @export var show_chunk_labels := false @export var force_center_chunk_id: StringName = &"chunk_0000" @export var required_chunk_ids := PackedStringArray() +@export_group("Elevated Inland Feature") +@export var elevated_cliff_feature_enabled := false +@export var elevated_cliff_base_chunk_id: StringName = &"chunk_0000" +@export var elevated_cliff_top_chunk_id: StringName = &"chunk_0009" +@export var elevated_cliff_corner_chunk_id: StringName = &"chunk_0010" +@export var elevated_cliff_edge_chunk_id: StringName = &"chunk_0011" +@export var elevated_cliff_ramp_chunk_id: StringName = &"chunk_0012" +@export_range(0.0, 1.0, 0.05) var elevated_cliff_ramp_chance := 0.75 +@export_group("") @export_range(1.0, 100.0, 1.0) var required_chunk_weight_multiplier := 64.0 @export_range(1.0, 4.0, 0.05) var preferred_neighbor_weight_multiplier := 1.6 @export_range(0.01, 1.0, 0.01) var long_repeat_weight_multiplier := 0.3 @@ -33,6 +44,8 @@ var _placements: Array[TerrainChunkVariant] = [] var _random := RandomNumberGenerator.new() var _generated_chunks: Node3D var _backtrack_count := 0 +var _elevated_feature_center := Vector2i(-1, -1) +var _elevated_feature_reserved_grass_indices: Dictionary[int, bool] = {} func _ready() -> void: @@ -49,6 +62,9 @@ func generate() -> bool: _backtrack_count = 0 _placements.clear() _placements.resize(grid_size.x * grid_size.y) + if not _prepare_elevated_feature_region(): + _placements.assign(previous_placements) + return false if not _solve_cell(0): _placements.assign(previous_placements) push_error( @@ -57,6 +73,9 @@ func generate() -> bool: ) return false _resolve_equivalent_rotations() + if not _apply_elevated_feature(): + _placements.assign(previous_placements) + return false var solution_root := _build_solution_root() if solution_root == null: _placements.assign(previous_placements) @@ -195,6 +214,8 @@ func _prepare_catalog() -> bool: return false for variant: TerrainChunkVariant in analyzed: _variants.append(variant) + if definition.overlay_only: + continue var constraint_key := _constraint_key(variant) var rotations: PackedInt32Array = _equivalent_rotations.get( constraint_key, @@ -207,6 +228,9 @@ func _prepare_catalog() -> bool: if _variants.is_empty(): push_error("Terrain chunk catalog produced no usable variants.") return false + if _solver_variants.is_empty(): + push_error("Terrain chunk catalog produced no base-terrain solver variants.") + return false for index: int in _solver_variants.size(): _solver_variant_indices[_solver_variants[index]] = index _build_edge_compatibility_cache() @@ -303,7 +327,7 @@ func _solve_cell(placed_count: int) -> bool: return false if not _requirements_can_still_be_satisfied(): return false - var next_cell := _select_next_cell() + var next_cell := _select_next_cell(placed_count) var index := int(next_cell.get("index", -1)) if index < 0: return false @@ -325,7 +349,12 @@ func _solve_cell(placed_count: int) -> bool: return false -func _select_next_cell() -> Dictionary: +func _select_next_cell(placed_count: int) -> Dictionary: + if ( + _placements.size() >= LARGE_GRID_LIGHTWEIGHT_THRESHOLD + and placed_count % LARGE_GRID_PROPAGATION_INTERVAL != 0 + ): + return _select_next_large_grid_cell() # Rebuild and propagate the small domain table on every branch. This catches # unsupported connector chains before they turn into a deep recursive dead # end, while keeping placement state simple and deterministic. @@ -356,6 +385,54 @@ func _select_next_cell() -> Dictionary: return {"index": best_index, "candidates": best_candidates} +func _select_next_large_grid_cell() -> Dictionary: + # Full all-cell arc propagation scales cubically as the map grows. Large + # worlds instead use the same compatibility checks with a frontier-aware MRV + # pass. Exact placement validation and backtracking remain unchanged. + var best_index := -1 + var best_candidates: Array[TerrainChunkVariant] = [] + var best_placed_neighbors := -1 + for index: int in _placements.size(): + if _placements[index] != null: + continue + var candidates := _compatible_candidates(index) + if candidates.is_empty(): + return {"index": index, "candidates": candidates} + var placed_neighbors := _placed_neighbor_count(index) + if ( + best_index < 0 + or candidates.size() < best_candidates.size() + or ( + candidates.size() == best_candidates.size() + and placed_neighbors > best_placed_neighbors + ) + ): + best_index = index + best_candidates = candidates + best_placed_neighbors = placed_neighbors + return {"index": best_index, "candidates": best_candidates} + + +func _placed_neighbor_count(index: int) -> int: + var coordinate := Vector2i(index % grid_size.x, index / grid_size.x) + var count := 0 + for edge_value: int in TerrainChunkTopology.Edge.values(): + var neighbor_coordinate := ( + coordinate + + TerrainChunkTopology.grid_offset( + edge_value as TerrainChunkTopology.Edge + ) + ) + if not _coordinate_is_inside_grid(neighbor_coordinate): + continue + var neighbor_index := ( + neighbor_coordinate.y * grid_size.x + neighbor_coordinate.x + ) + if _placements[neighbor_index] != null: + count += 1 + return count + + func _propagate_domains(domains: Dictionary) -> bool: var changed := true while changed: @@ -568,6 +645,11 @@ func _candidate_can_occupy_cell( if not _definition_has_capacity(candidate.definition): return false var coordinate := Vector2i(index % grid_size.x, index / grid_size.x) + if ( + _elevated_feature_reserved_grass_indices.has(index) + and candidate.definition.stable_id != elevated_cliff_base_chunk_id + ): + return false var center := Vector2i(grid_size.x / 2, grid_size.y / 2) var center_index := center.y * grid_size.x + center.x if ( @@ -599,10 +681,123 @@ func _candidate_can_occupy_cell( ) +func _prepare_elevated_feature_region() -> bool: + _elevated_feature_center = Vector2i(-1, -1) + _elevated_feature_reserved_grass_indices.clear() + if not elevated_cliff_feature_enabled: + return true + for stable_id: StringName in [ + elevated_cliff_base_chunk_id, + elevated_cliff_top_chunk_id, + elevated_cliff_corner_chunk_id, + elevated_cliff_edge_chunk_id, + elevated_cliff_ramp_chunk_id, + ]: + if catalog.definition_for_id(stable_id) == null: + push_error("Elevated cliff feature references missing chunk %s." % stable_id) + return false + if grid_size.x < 11 or grid_size.y < 9: + push_error( + "Elevated cliff feature requires at least an 11x9 terrain grid." + ) + return false + var forced_center := Vector2i(grid_size.x / 2, grid_size.y / 2) + var candidates: Array[Vector2i] = [] + for row: int in range(2, grid_size.y - 2): + for column: int in range(2, grid_size.x - 2): + var candidate := Vector2i(column, row) + if ( + absi(candidate.x - forced_center.x) <= 2 + and absi(candidate.y - forced_center.y) <= 2 + ): + continue + candidates.append(candidate) + if candidates.is_empty(): + push_error("Terrain grid has no inland 3x3 cliff feature location.") + return false + var feature_random := RandomNumberGenerator.new() + feature_random.seed = generation_seed ^ 0x2E1E7A7ED + _elevated_feature_center = candidates[ + feature_random.randi_range(0, candidates.size() - 1) + ] + # Solve the authored 3x3 cliff assembly into a one-cell ring of ordinary + # level-one flat grass. Every raised piece still occupies one of the inner + # nine grass cells; the outer ring prevents a stream, pond, or coast profile + # from being exposed directly against its downhill edge. + for row_offset: int in range(-2, 3): + for column_offset: int in range(-2, 3): + var coordinate := ( + _elevated_feature_center + + Vector2i(column_offset, row_offset) + ) + _elevated_feature_reserved_grass_indices[ + coordinate.y * grid_size.x + coordinate.x + ] = true + return true + + +func _apply_elevated_feature() -> bool: + if not elevated_cliff_feature_enabled: + return true + if _elevated_feature_center.x < 0 or _elevated_feature_center.y < 0: + push_error("Elevated cliff feature has no reserved base region.") + return false + var edge_specs: Array[Dictionary] = [ + {"offset": Vector2i(0, -1), "turns": 1}, + {"offset": Vector2i(1, 0), "turns": 0}, + {"offset": Vector2i(0, 1), "turns": 3}, + {"offset": Vector2i(-1, 0), "turns": 2}, + ] + var feature_random := RandomNumberGenerator.new() + feature_random.seed = generation_seed ^ 0x51A7C11FF + var ramp_edge := -1 + if feature_random.randf() < elevated_cliff_ramp_chance: + ramp_edge = feature_random.randi_range(0, edge_specs.size() - 1) + var placements: Array[Dictionary] = [ + {"offset": Vector2i(-1, -1), "id": elevated_cliff_corner_chunk_id, "turns": 2}, + {"offset": Vector2i(1, -1), "id": elevated_cliff_corner_chunk_id, "turns": 1}, + {"offset": Vector2i(0, 0), "id": elevated_cliff_top_chunk_id, "turns": 0}, + {"offset": Vector2i(-1, 1), "id": elevated_cliff_corner_chunk_id, "turns": 3}, + {"offset": Vector2i(1, 1), "id": elevated_cliff_corner_chunk_id, "turns": 0}, + ] + for edge_index: int in edge_specs.size(): + var edge_spec := edge_specs[edge_index] + placements.append({ + "offset": edge_spec["offset"], + "id": ( + elevated_cliff_ramp_chunk_id + if edge_index == ramp_edge + else elevated_cliff_edge_chunk_id + ), + "turns": edge_spec["turns"], + }) + for spec: Dictionary in placements: + var definition := catalog.definition_for_id(spec["id"] as StringName) + var variant := _authored_variant(definition, int(spec["turns"])) + if variant == null: + push_error( + "Elevated cliff feature cannot resolve %s rotation %d." + % [spec["id"], spec["turns"]] + ) + return false + var coordinate := _elevated_feature_center + (spec["offset"] as Vector2i) + _placements[coordinate.y * grid_size.x + coordinate.x] = variant + var validation_error := _resolved_layout_validation_error(_placements) + if not validation_error.is_empty(): + push_error("Elevated cliff feature is invalid: " + validation_error) + return false + return true + + func _variant_respects_ocean_boundary( variant: TerrainChunkVariant, coordinate: Vector2i, ) -> bool: + if ( + variant.definition.must_be_interior + and _coordinate_is_on_boundary(coordinate) + ): + return false var ocean_edges := variant.rotated_edge_mask( variant.definition.ocean_facing_edges ) @@ -1231,7 +1426,7 @@ func _build_solution_root() -> Node3D: if variant == null: continue var coordinate := Vector2i(index % grid_size.x, index / grid_size.x) - var chunk_root := variant.definition.packed_scene.instantiate() as Node3D + var chunk_root := _instantiate_chunk_root(variant.definition) if chunk_root == null: push_error("%s does not instantiate as Node3D." % variant.stable_key()) solution_root.free() @@ -1260,6 +1455,27 @@ func _build_solution_root() -> Node3D: return solution_root +func _instantiate_chunk_root( + definition: TerrainChunkDefinition, +) -> Node3D: + var terrain_visual := definition.packed_scene.instantiate() as Node3D + if terrain_visual == null: + return null + if definition.base_layer_scene == null: + return terrain_visual + var base_layer_visual := definition.base_layer_scene.instantiate() as Node3D + if base_layer_visual == null: + terrain_visual.free() + return null + var layered_root := Node3D.new() + layered_root.name = "LayeredTerrainChunk" + base_layer_visual.name = "TerrainBaseLayer" + terrain_visual.name = "TerrainOverlay" + layered_root.add_child(base_layer_visual) + layered_root.add_child(terrain_visual) + return layered_root + + func _replace_generated_chunks(solution_root: Node3D) -> void: _clear_generated_chunks() _generated_chunks = solution_root @@ -1274,11 +1490,34 @@ func _add_collision( chunk_root, definition.primary_mesh_name, ) + _add_collision_to_mesh( + primary_mesh, + definition.stable_id, + "TerrainCollision", + ) + if definition.base_layer_scene == null: + return + var base_layer_mesh := TerrainChunkAnalyzer.find_primary_mesh( + chunk_root, + definition.base_layer_mesh_name, + ) + _add_collision_to_mesh( + base_layer_mesh, + definition.stable_id, + "TerrainBaseLayerCollision", + ) + + +func _add_collision_to_mesh( + primary_mesh: MeshInstance3D, + stable_id: StringName, + collision_name: String, +) -> void: if primary_mesh == null or primary_mesh.mesh == null: return var terrain_shape := primary_mesh.mesh.create_trimesh_shape() if terrain_shape == null or terrain_shape.get_faces().is_empty(): - push_warning("%s produced no terrain collision." % definition.stable_id) + push_warning("%s produced no terrain collision." % stable_id) return var concave_shape := terrain_shape as ConcavePolygonShape3D if concave_shape != null: @@ -1287,7 +1526,7 @@ func _add_collision( # can never become an invisible collision gap. concave_shape.backface_collision = true var collision_body := StaticBody3D.new() - collision_body.name = "TerrainCollision" + collision_body.name = collision_name collision_body.collision_layer = 1 collision_body.collision_mask = 0 primary_mesh.add_child(collision_body) diff --git a/world/generation/terrain_prop_catalog.gd b/world/generation/terrain_prop_catalog.gd index f3375b1..e73fbe0 100644 --- a/world/generation/terrain_prop_catalog.gd +++ b/world/generation/terrain_prop_catalog.gd @@ -82,4 +82,23 @@ func validation_errors() -> PackedStringArray: "%s has a negative box collision dimension." % definition.stable_id ) + if definition.minimum_visual_scale > definition.maximum_visual_scale: + errors.append( + "%s has an inverted visual scale range." + % definition.stable_id + ) + if ( + not definition.material_variants.is_empty() + and definition.variant_material_slot_names.is_empty() + ): + errors.append( + "%s has material variants but no target material slots." + % definition.stable_id + ) + for material: Material in definition.material_variants: + if material == null: + errors.append( + "%s contains an empty material variant." + % definition.stable_id + ) return errors diff --git a/world/generation/terrain_prop_definition.gd b/world/generation/terrain_prop_definition.gd index ca04b21..f6e73ae 100644 --- a/world/generation/terrain_prop_definition.gd +++ b/world/generation/terrain_prop_definition.gd @@ -18,6 +18,15 @@ extends Resource @export_range(0.0, 100.0, 0.5) var preferred_nearby_radius := 0.0 @export_range(1.0, 10.0, 0.1) var nearby_preference_weight_multiplier := 1.0 @export_range(0.0, 10.0, 0.05) var clearance_radius := 0.5 +## Procedural instances use a deterministic uniform scale in this range. +@export_range(0.1, 4.0, 0.05) var minimum_visual_scale := 1.0 +@export_range(0.1, 4.0, 0.05) var maximum_visual_scale := 1.0 +## Presentation-only offset. The prop root remains exactly terrain-aligned. +@export var visual_offset := Vector3.ZERO +## A single material is chosen per prop and applied only to matching imported +## material slots. This keeps trunks untouched while varying foliage. +@export var variant_material_slot_names := PackedStringArray() +@export var material_variants: Array[Material] = [] @export_range(0.0, 5.0, 0.05) var collision_radius := 0.0 @export_range(0.0, 20.0, 0.05) var collision_height := 0.0 @export var collision_box_size := Vector3.ZERO