class_name PokemonStorage extends Resource signal storage_changed enum ReceiveResult { TEAM, BOX, FULL } const NO_SLOT : Vector2i = Vector2i(-1, -1) #(boite, emplacement) var boxes : Array[PokemonBox] = [] func _init(p_box_count : int = 8, p_box_size : int = 30) -> void: for i in p_box_count: boxes.append(PokemonBox.new(p_box_size)) #---------- infos ---------- func box_count() -> int: return boxes.size() func get_box(box_index : int) -> PokemonBox: return boxes[box_index] if box_index >= 0 and box_index < boxes.size() else null func get_pokemon(box_index : int, slot : int) -> PokemonInstance: var box : PokemonBox = get_box(box_index) return box.get_pokemon(slot) if box else null func get_total_count() -> int: var n : int = 0 for box in boxes: n += box.count() return n func is_full() -> bool: return find_free_slot() == NO_SLOT func find_free_slot() -> Vector2i: for b in boxes.size(): var s : int = boxes[b].first_free_slot() if s != -1: return Vector2i(b, s) return NO_SLOT #---------- reception d'un nouveau pokemon ---------- func receive_pokemon(team : PokemonTeam, pokemon : PokemonInstance) -> ReceiveResult: #equipe d'abord ; si elle est pleine, premiere place libre du PC if pokemon == null: return ReceiveResult.FULL if team.add_pokemon(pokemon): return ReceiveResult.TEAM var dest : Vector2i = find_free_slot() if dest == NO_SLOT: return ReceiveResult.FULL boxes[dest.x].slots[dest.y] = pokemon storage_changed.emit() return ReceiveResult.BOX #---------- equipe <-> PC ---------- func deposit(team : PokemonTeam, team_index : int, box_index : int = -1, slot : int = -1) -> bool: #equipe -> PC (box_index = -1 : premiere place libre) if team.get_pokemon(team_index) == null: return false if !_team_stays_valid(team, team_index, null): return false var dest : Vector2i = find_free_slot() if box_index < 0 else Vector2i(box_index, slot) if dest == NO_SLOT or get_box(dest.x) == null: return false if dest.y < 0 or dest.y >= boxes[dest.x].size() or boxes[dest.x].slots[dest.y] != null: return false var pokemon : PokemonInstance = team.remove_at(team_index) boxes[dest.x].slots[dest.y] = pokemon storage_changed.emit() return true func withdraw(team : PokemonTeam, box_index : int, slot : int) -> bool: #PC -> equipe (a la fin) ; impossible si l'equipe est pleine var pokemon : PokemonInstance = get_pokemon(box_index, slot) if pokemon == null or team.is_full(): return false if !team.add_pokemon(pokemon): return false boxes[box_index].slots[slot] = null storage_changed.emit() return true func swap_with_team(team : PokemonTeam, team_index : int, box_index : int, slot : int) -> bool: #echange un pokemon de l'equipe avec celui d'un emplacement occupe du PC var from_team : PokemonInstance = team.get_pokemon(team_index) var from_box : PokemonInstance = get_pokemon(box_index, slot) if from_team == null or from_box == null: return false if !_team_stays_valid(team, team_index, from_box): return false if team.replace_at(team_index, from_box) == null: return false boxes[box_index].slots[slot] = from_team storage_changed.emit() return true #---------- deplacements dans le PC ---------- func move_slot(box_a : int, slot_a : int, box_b : int, slot_b : int) -> bool: #deplace (ou echange) le contenu d'un emplacement vers un autre, destination vide ou non var source : PokemonInstance = get_pokemon(box_a, slot_a) if source == null: return false var dest_box : PokemonBox = get_box(box_b) if dest_box == null or slot_b < 0 or slot_b >= dest_box.size(): return false if box_a == box_b and slot_a == slot_b: return false boxes[box_a].slots[slot_a] = dest_box.slots[slot_b] dest_box.slots[slot_b] = source storage_changed.emit() return true func release(box_index : int, slot : int) -> PokemonInstance: #retire definitivement un pokemon du PC (relacher) ; renvoie le pokemon retire var pokemon : PokemonInstance = get_pokemon(box_index, slot) if pokemon == null: return null boxes[box_index].slots[slot] = null storage_changed.emit() return pokemon #---------- regle d'equipe ---------- func _team_stays_valid(team : PokemonTeam, removed_index : int, replacement : PokemonInstance) -> bool: #l'equipe ne doit jamais etre vide, ni perdre son dernier pokemon apte #(sauf si elle n'en avait deja aucun : tous K.O.) var size_after : int = team.size() - (1 if replacement == null else 0) if size_after < 1: return false if !team.has_able_pokemon(): return true for i in team.size(): if i != removed_index and !team.members[i].is_fainted(): return true return replacement != null and !replacement.is_fainted() #---------- sauvegarde ---------- func to_dict() -> Dictionary: var boxes_data : Array = [] for box in boxes: var slots_data : Array = [] for p in box.slots: slots_data.append(p.to_dict() if p != null else null) boxes_data.append({"name": box.box_name, "slots": slots_data}) return {"boxes": boxes_data} static func from_dict(data : Dictionary) -> PokemonStorage: var storage := PokemonStorage.new(0) for box_data in data.get("boxes", []): var slots_data : Array = box_data.get("slots", []) var box := PokemonBox.new(slots_data.size()) box.box_name = box_data.get("name", "") for i in slots_data.size(): if slots_data[i] is Dictionary: box.slots[i] = PokemonInstance.from_dict(slots_data[i]) storage.boxes.append(box) if storage.boxes.is_empty(): return PokemonStorage.new() return storage