extends Node class_name GameManager @export var dragon_template: PackedScene @export var dragon_ingame: PackedScene @export var name_setter: PackedScene @export var dragon_spots: Array[Node2D] @export var dragon_start_spots: Dictionary[Node2D, Node2D] var _filled_spots: Dictionary[Node2D, int] var _instantiator: DragonInstantiator var _save_load: SaveLoad var _library: DragonLibrary var _dragon_entities: Dictionary[int, Dragon] = {} var _instantiated_dragons: Dictionary[int, DragonEntity] = {} var rng: RandomNumberGenerator = RandomNumberGenerator.new() @export var min_dragon_instantiation_time: float @export var max_dragon_instantiation_time: float @onready var dragon_sharing: DragonSharing = $HTTPRequest func _ready(): _library = DragonLibrary.new() _instantiator = DragonInstantiator.new(dragon_template, get_viewport(), get_window()) _save_load = SaveLoad.new() await get_tree().process_frame move_window_to_bottom_right() _load_game() if _save_load.get_tower_name() == "": _show_name_setter_screen() _queue_dragon_instantiation() func _show_name_setter_screen(): var setter: NameSetter = name_setter.instantiate() setter.set_save_load(_save_load) add_child(setter) var display_index: int = DisplayServer.window_get_current_screen() var work_area_position: Vector2i = DisplayServer.screen_get_usable_rect(display_index).position var work_area_size: Vector2i = DisplayServer.screen_get_usable_rect(display_index).size var new_position: Vector2i = work_area_position + Vector2i(work_area_size.x / 2.0 - setter.size.x / 2.0, work_area_size.y / 2.0 - setter.size.y / 2.0) setter.position = new_position func _queue_dragon_instantiation(): await get_tree().create_timer(rng.randf_range(min_dragon_instantiation_time, max_dragon_instantiation_time)).timeout if _save_load.get_tower_name() != "": _instantiate_random_dragon() _queue_dragon_instantiation() func _instantiate_random_dragon(): var spot: Node2D = _get_free_spot() if spot == null: return #TODO: Add also a way to instantiate dragons in your library with a greater probability for i in range(5): dragon_sharing.receive(_save_load.get_tower_name()) var dragon: DragonProperties = await dragon_sharing.on_dragon_received if dragon == null: return for d in _library.dragons: # TODO: Search for dragon and if is in library or in instantiated dragons continue next iteration pass var dragon_entity: DragonEntity = _generate_entity(spot, dragon) _filled_spots[spot] = dragon_entity.properties.id return func _get_free_spot() -> Node2D: for spot in dragon_spots: if not _filled_spots.has(spot): return spot return null func _generate_entity(spot: Node2D, properties: DragonProperties) -> DragonEntity: properties.id = rng.randi() return _instantiate_dragon_ingame(spot, properties) func move_window_to_bottom_right(): var display_index: int = DisplayServer.window_get_current_screen() var work_area_position: Vector2i = DisplayServer.screen_get_usable_rect(display_index).position var work_area_size: Vector2i = DisplayServer.screen_get_usable_rect(display_index).size var window_size: Vector2i = DisplayServer.window_get_size() var new_position: Vector2i = work_area_position + Vector2i(work_area_size.x - window_size.x, work_area_size.y - window_size.y) DisplayServer.window_set_size(window_size) DisplayServer.window_set_position(new_position) func add_dragon(properties: DragonProperties): var id: int = _library.add_dragon(properties) dragon_sharing.send(properties) for spot in dragon_spots: if not _filled_spots.has(spot): _instantiate_dragon_ingame(spot, properties) _filled_spots[spot] = id break func _load_game(): _save_load.load() var dragons: Array[DragonProperties] = _save_load.get_dragons() _library.add_dragons(dragons) for d: DragonProperties in dragons: if d.position != Vector2i(0, 0): _pick_dragon(d, false) print(_save_load.contents_to_save) func _instantiate_dragon_ingame(spot: Node2D, properties: DragonProperties) -> DragonEntity: var dragon: DragonEntity = dragon_ingame.instantiate() spot.add_child(dragon) dragon.dress(properties) dragon.properties = properties dragon.on_pick.connect(_pick_dragon) dragon.on_quit.connect(_quit_dragon) _instantiated_dragons[properties.id] = dragon dragon.play_initial_animation(dragon_start_spots[spot]) return dragon func _pick_dragon(properties: DragonProperties, drag: bool = true): var dragon: Dragon = _instantiator.instantiate(properties, drag) _dragon_entities[properties.id] = dragon dragon.place_back.connect(_dragon_place_back) add_child(dragon) _instantiated_dragons.erase(properties.id) if not _library.has(properties): _library.add_dragon(properties) for spot in _filled_spots: if _filled_spots[spot] == properties.id: _filled_spots.erase(spot) func _quit_dragon(id: int): _instantiated_dragons.erase(id) for spot in _filled_spots: if _filled_spots[spot] == id: _filled_spots.erase(spot) func _dragon_place_back(dragon: Dragon): _dragon_entities.erase(dragon.properties.id) func _on_close_pressed() -> void: _save_load.clear_dragons() for d in _library.dragons: if _dragon_entities.has(d.id) and _dragon_entities[d.id] != null: _save_load.add_dragon(d) else: d.position = Vector2i(0, 0) _save_load.add_dragon(d) _save_load.save() await get_tree().process_frame await get_tree().process_frame await get_tree().process_frame await get_tree().process_frame await get_tree().process_frame get_tree().quit()