Tales-of-PKMN/game/storage/pokemon_storage.gd
2026-10-04 17:42:26 +02:00

146 lines
5.3 KiB
GDScript

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