extends Node3D # Array of tree scenes to randomly choose from @export var tree_scenes: Array[PackedScene] = [] @export var spawn_area_size: Vector2 = Vector2(2.0, 2.0) # 2x2 area @export var max_trees: int = 3 # Maximum possible trees @export var min_distance: float = 0.5 # Minimum distance between trees var spawned_positions: Array[Vector3] = [] var parent_ground_tile: GroundTile var rng: RandomClass func _ready(): # Get reference to parent GroundTile parent_ground_tile = get_parent() as GroundTile if parent_ground_tile: # Connect to the signal parent_ground_tile.cell_info_updated.connect(_on_cell_info_updated) # If cell_info already exists, spawn trees immediately if parent_ground_tile.cell_info != null: _on_cell_info_updated(parent_ground_tile.cell_info) func _on_cell_info_updated(cell_info: CellDataResource): # Initialize RNG with the cell's seed for consistent results rng = RandomClass.new() rng.set_seed(cell_info.cell_seed) # Calculate number of trees based on vegetation_density var tree_count = calculate_tree_count(cell_info.vegetation_density) # Spawn the trees spawn_trees(tree_count) func calculate_tree_count(vegetation_density: float) -> int: if vegetation_density < 0.7: return 0 # vegetation_density should be between 0.0 and 1.0 # Scale it to our max_trees range var scaled_count = vegetation_density * max_trees # Round to nearest integer, but ensure at least 0 return max(0, int(round(scaled_count))) func spawn_trees(tree_count: int): if tree_scenes.is_empty(): print("No tree scenes assigned!") return if tree_count == 0: print("No trees to spawn (vegetation_density too low)") return # Clear any existing trees clear_trees() # Try to place trees var attempts = 0 var max_attempts = tree_count * 10 # Prevent infinite loops while spawned_positions.size() < tree_count and attempts < max_attempts: var pos = get_random_position() if is_position_valid(pos): spawn_tree_at_position(pos) spawned_positions.append(pos) attempts += 1 print("Spawned ", spawned_positions.size(), " trees") func get_random_position() -> Vector3: var x = rng.randf_range(-spawn_area_size.x / 2, spawn_area_size.x / 2) var z = rng.randf_range(-spawn_area_size.y / 2, spawn_area_size.y / 2) return Vector3(x, 0, z) func is_position_valid(pos: Vector3) -> bool: # Check if position is too close to existing trees for existing_pos in spawned_positions: if pos.distance_to(existing_pos) < min_distance: return false return true func spawn_tree_at_position(pos: Vector3): # Pick a random tree scene using the seeded RNG var random_index = rng.randi() % tree_scenes.size() var random_tree_scene = tree_scenes[random_index] var tree_instance = random_tree_scene.instantiate() add_child(tree_instance) tree_instance.position = pos # Optional: Add some random rotation using seeded RNG tree_instance.rotation.y = rng.randf() * TAU func clear_trees(): # Remove all existing tree children for child in get_children(): child.queue_free() spawned_positions.clear() # Call this if you want to respawn trees manually func respawn_trees(): if parent_ground_tile and parent_ground_tile.cell_info: _on_cell_info_updated(parent_ground_tile.cell_info)