extends StaticBody3D enum TileType { Empty, Plain, Forest, Lake } var tile_materials = [ # must be in the same order as an enum above! preload("res://materials/empty_tile.tres"), # Empty preload("res://materials/plain_tile.tres"), # Plain preload("res://materials/plain_tile.tres"), # Forest preload("res://materials/lake_tile.tres") # Lake ] @export var decorations = { "Forest": { "min": 5, "max": 10, "object": preload("res://scenes/models/tree.tscn") } } @export var tile_type: TileType = TileType.Empty @onready var visible_mesh = $VisibleMesh @onready var God = get_tree().root.get_node("world/God") var maximum_decoration_objects = 0 func generate_predictable_random_int(min, max, salt): seed((str(World.world_info.seed) + str(position) + str(salt)).hash()) return randi() % (max + 1) + min func generate_predictable_random_float(min, max, salt): seed((str(World.world_info.seed) + str(position) + str(salt)).hash()) return clamp(randf(), min, max) func generate_decoration_objects(): match tile_type: TileType.Forest: var key = TileType.keys()[tile_type] maximum_decoration_objects = generate_predictable_random_int(decorations[key]["min"], decorations[key]["max"], ""); for i in range(0, maximum_decoration_objects): var decoration = decorations[TileType.keys()[tile_type]]["object"].instantiate() var pos = Vector3(generate_predictable_random_int(0, 10, str(i) + "x") - 5, 0, generate_predictable_random_int(0, 10, str(i) + "z") - 5) var scale = generate_predictable_random_float(0.05, 0.15, str(i) + "scale") var y_rot = generate_predictable_random_int(0, 360, str(i) + "rot_y") decoration.rotation.y = y_rot decoration.position = pos decoration.scale = Vector3(scale, scale, scale) decoration.add_to_group("Decoration") add_child(decoration) func update_tile(): for decoration in get_children(): if(decoration.is_in_group("Decoration")): decoration.queue_free() visible_mesh.set_surface_override_material(0, tile_materials[tile_type]) generate_decoration_objects() func _ready(): update_tile() func get_empty_dirs_around(): var empty_tiles_around = [] var space_state = get_world_3d().direct_space_state var query_north = PhysicsRayQueryParameters3D.create(self.position + Vector3(0, -2.5, 0), self.position + Vector3(10, -2.5, 0)) var query_south = PhysicsRayQueryParameters3D.create(self.position + Vector3(0, -2.5, 0), self.position + Vector3(-12, -2.5, 0)) var query_west = PhysicsRayQueryParameters3D.create(self.position + Vector3(0, -2.5, 0), self.position + Vector3(0, -2.5, -10)) var query_east = PhysicsRayQueryParameters3D.create(self.position + Vector3(0, -2.5, 0), self.position + Vector3(0, -2.5, 10)) var result_north = space_state.intersect_ray(query_north) var result_south = space_state.intersect_ray(query_south) var result_west = space_state.intersect_ray(query_west) var result_east = space_state.intersect_ray(query_east) if !result_north: empty_tiles_around.push_back("north") if !result_south: empty_tiles_around.push_back("south") if !result_west: empty_tiles_around.push_back("west") if !result_east: empty_tiles_around.push_back("east") return empty_tiles_around func save(): if tile_type == TileType.Empty: return {} return { "node": "tile", "pos_x": position.x, "pos_y": position.y, "pos_z": position.z, "tile_type": tile_type } func _process(delta): if (tile_type == TileType.Empty): visible = (position.distance_to(God.position) < 100)