class_name BattleMon extends RefCounted #un pokemon en combat : enveloppe autour du PokemonInstance qui porte l'etat TEMPORAIRE du combat #(boosts, confusion, peur, compteurs...). Disparait au changement de pokemon ou a la fin du combat. #les PV, le K.O. et le statut principal s'appliquent directement au PokemonInstance (ils persistent). const MIN_STAGE : int = -6 const MAX_STAGE : int = 6 #noms PokeAPI -> cle dans "stages" (les stats classiques utilisent PokemonNature.Stat) const STAT_KEYS : Dictionary = { "attack": PokemonNature.Stat.ATTACK, "defense": PokemonNature.Stat.DEFENSE, "special-attack": PokemonNature.Stat.SP_ATTACK, "special-defense": PokemonNature.Stat.SP_DEFENSE, "speed": PokemonNature.Stat.SPEED, "accuracy": &"accuracy", "evasion": &"evasion", } const STAT_LABELS : Dictionary = { "attack": "L'Attaque", "defense": "La Défense", "special-attack": "L'Attaque Spéciale", "special-defense": "La Défense Spéciale", "speed": "La Vitesse", "accuracy": "La Précision", "evasion": "L'Esquive", } var pokemon : PokemonInstance var slot_id : int = -1 var stages : Dictionary = {} #cle (PokemonNature.Stat, &"accuracy" ou &"evasion") -> -6..6 var volatile : Array[BattleEffect] = [] #effets temporaires : confusion, peur... var status_turns : int = 0 #sommeil : nombre de tentatives d'action restantes var toxic_counter : int = 0 #poison grave : nombre de tours ecoules var acted_this_turn : bool = false func _init(p_pokemon : PokemonInstance) -> void: pokemon = p_pokemon if pokemon.status == PokemonInstance.Status.SLEEP: status_turns = 2 #deja endormi en entrant en combat func display_name() -> String: return pokemon.get_display_name() func is_fainted() -> bool: return pokemon.is_fainted() func get_types() -> Array[String]: var result : Array[String] = [] for t in pokemon.species.types: result.append(TypeChart.type_name(t)) return result #---------- effets ---------- func get_effects() -> Array[BattleEffect]: #statut principal + effets temporaires (nouveau tableau a chaque appel : on peut modifier pendant l'iteration) var result : Array[BattleEffect] = [] var status_effect : BattleEffect = StatusRegistry.effect_for(int(pokemon.status)) if status_effect != null: result.append(status_effect) result.append_array(volatile) return result func has_volatile(id : StringName) -> bool: for e in volatile: if e.id == id: return true return false func add_volatile(effect : BattleEffect) -> void: volatile.append(effect) func remove_volatile(id : StringName) -> void: for i in range(volatile.size() - 1, -1, -1): if volatile[i].id == id: volatile.remove_at(i) func cleanup_volatile() -> void: for i in range(volatile.size() - 1, -1, -1): if volatile[i].is_expired(): volatile.remove_at(i) func on_status_applied(status : int, rng : RandomNumberGenerator) -> void: toxic_counter = 0 status_turns = rng.randi_range(1, 3) if status == PokemonInstance.Status.SLEEP else 0 #---------- statistiques et boosts ---------- func get_stage(key : Variant) -> int: return int(stages.get(key, 0)) ## Applique un changement de boost ; renvoie le changement reellement applique (0 si deja au maximum/minimum). func change_stage(stat_name : String, delta : int) -> int: if !STAT_KEYS.has(stat_name): return 0 var key : Variant = STAT_KEYS[stat_name] var current : int = get_stage(key) var updated : int = clampi(current + delta, MIN_STAGE, MAX_STAGE) stages[key] = updated return updated - current static func _stage_multiplier(stage : int) -> float: return (2.0 + stage) / 2.0 if stage >= 0 else 2.0 / (2.0 - stage) ## Stat effective : stat du pokemon x boost, puis modifications des effets (brulure, paralysie...). func get_stat(stat : PokemonNature.Stat) -> float: var value : float = pokemon.get_stat(stat) * _stage_multiplier(get_stage(stat)) for effect in get_effects(): value = effect.modify_stat(self, stat, value) return value ## Multiplicateur de precision de cette attaque contre une cible (boost de precision - esquive). func accuracy_multiplier_against(target : BattleMon) -> float: var stage : int = clampi(get_stage(&"accuracy") - target.get_stage(&"evasion"), MIN_STAGE, MAX_STAGE) return (3.0 + stage) / 3.0 if stage >= 0 else 3.0 / (3.0 - stage)