122 lines
4.6 KiB
GDScript
122 lines
4.6 KiB
GDScript
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
|
|
var field : BattleField = null #terrain du combat (meteo...), renseigne par Battle
|
|
var flags : Dictionary = {} #petits etats libres pour les talents (ex. "flash_fire")
|
|
var _ability_effect : BattleEffect = null
|
|
|
|
func _init(p_pokemon : PokemonInstance) -> void:
|
|
pokemon = p_pokemon
|
|
if pokemon.status == PokemonInstance.Status.SLEEP:
|
|
status_turns = 2 #deja endormi en entrant en combat
|
|
if pokemon.ability != null:
|
|
_ability_effect = AbilityRegistry.create(pokemon.ability.api_name)
|
|
|
|
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)
|
|
if _ability_effect != null: result.append(_ability_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)
|
|
if field != null: value = field.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)
|