Definir un Desafío de Batalla

El sistema de Battle Challenge (Desafío de Batalla) en Pokémon Essentials permite crear instalaciones de combate estilo Battle Frontier. Estas instalaciones ofrecen combates consecutivos contra entrenadores generados dinámicamente, con reglas especiales, progresión por rondas y recompensas al alcanzar ciertas rachas de victorias. En esta página se explica cómo configurar y personalizar un desafío de batalla completo.

Tipos de instalaciones de batalla

Essentials incluye soporte para varios tipos de instalaciones, inspiradas en las de los juegos oficiales:

La Base de Sky incluye la implementación de la Battle Tower y la Battle Factory como instalaciones principales. Las demás pueden implementarse como extensiones personalizadas.

Clase BattleChallenge

La clase central del sistema es BattleChallenge. Esta clase gestiona el estado del desafío, las rondas, las rachas de victorias y la generación de entrenadores. Se accede a ella a través de la variable global $PokemonGlobal.challenge.

# Estructura interna principal de BattleChallenge
class BattleChallenge
  attr_accessor :currentChallenge   # Tipo de desafío actual
  attr_accessor :battleRules        # Reglas de batalla activas
  attr_accessor :wins               # Victorias en la racha actual
  attr_accessor :swaps              # Intercambios realizados (Battle Factory)
  attr_accessor :pokemon            # Equipo del jugador en el desafío
  attr_accessor :trainers           # Lista de entrenadores disponibles
end

Iniciar un desafío

Para iniciar un desafío de batalla desde un evento, usa la siguiente secuencia de comandos:

# Ejemplo: Iniciar una Battle Tower en formato individual
pbBattleChallenge.set("pokemon_challenge",   # ID interno del desafío
                       7,                     # Número de combates por ronda
                       Pokemon::MAX_LEVEL,    # Nivel máximo permitido
                       Pokemon::MAX_PARTY_SIZE # Tamaño máximo del equipo
                      )
pbBattleTowerChallenge

El primer argumento es el identificador interno del desafío, que debe coincidir con los datos guardados de rachas de victorias. Los argumentos configuran las reglas básicas del desafío.

Evento NPC de recepción

El NPC de recepción en la instalación de batalla debe seguir este flujo:

# Evento del NPC de recepción
pbMessage(_I("¡Bienvenido a la Torre Batalla!"))
pbMessage(_I("Aquí podrás poner a prueba tu fuerza en combates consecutivos."))

# Preguntar el tipo de desafío
choices = [_I("Combate Individual"), _I("Combate Doble"), _I("Cancelar")]
choice = pbMessage(_I("¿Qué tipo de desafío deseas?"), choices, 3)

case choice
when 0  # Individual
  pbMessage(_I("Elige 3 Pokémon de tu equipo para participar."))
  if pbBattleChallenge.set("pokemon_challenge_single", 7, 50, 3)
    pbBattleTowerChallenge
  end
when 1  # Doble
  pbMessage(_I("Elige 4 Pokémon de tu equipo para participar."))
  if pbBattleChallenge.set("pokemon_challenge_double", 7, 50, 4)
    pbBattleTowerChallenge
  end
when 2  # Cancelar
  pbMessage(_I("¡Vuelve cuando estés listo!"))
end

Reglas de batalla

Las reglas de batalla determinan las restricciones y formato de los combates dentro del desafío. Se configuran mediante el objeto BattleRules:

# Configurar reglas de batalla
rules = PokemonChallengeRules.new

# Nivel máximo
rules.setLevelAdjustment(OpenLevelAdjustment.new(50))

# Número de Pokémon por equipo
rules.addPokemonRule(MaximumNumberRestriction.new(3))

# Prohibir Pokémon legendarios
rules.addPokemonRule(BannedSpeciesRestriction.new(
  :MEWTWO, :MEW, :LUGIA, :HOOH, :CELEBI,
  :KYOGRE, :GROUDON, :RAYQUAZA, :JIRACHI, :DEOXYS,
  :DIALGA, :PALKIA, :GIRATINA, :ARCEUS
))

# Prohibir objetos duplicados
rules.addTeamRule(UniqueItemRestriction.new)

# Prohibir Pokémon duplicados
rules.addTeamRule(SpeciesClause.new)

Tipos de restricciones disponibles

RestricciónDescripción
MaximumNumberRestrictionLimita el número máximo de Pokémon en el equipo.
BannedSpeciesRestrictionProhíbe especies específicas de Pokémon.
UniqueItemRestrictionNo permite objetos duplicados en el equipo.
SpeciesClauseNo permite especies duplicadas en el equipo.
LevelRestrictionLimita el nivel máximo de los Pokémon.
BannedItemRestrictionProhíbe objetos específicos.
BannedMoveRestrictionProhíbe movimientos específicos.

Pool de entrenadores

Los entrenadores del desafío se generan a partir de un pool definido en el archivo PBS battle_tower_trainers.txt (o el archivo correspondiente a la instalación). Cada entrada define un entrenador con su equipo:

# Formato de battle_tower_trainers.txt
# Cada entrenador tiene un tipo, nombre y equipo de Pokémon

[POKEMONTRAINER_Aria,Aria,0]
Pokemon = GARDEVOIR,50
  Item = CHOICE_SPECS
  Moves = PSYCHIC,MOONBLAST,THUNDERBOLT,SHADOW_BALL
  Nature = MODEST
  EVs = 0,0,0,252,4,252
Pokemon = LUCARIO,50
  Item = LIFE_ORB
  Moves = AURA_SPHERE,FLASH_CANNON,DARK_PULSE,NASTY_PLOT
  Nature = TIMID
  EVs = 0,0,0,252,4,252
Pokemon = TOGEKISS,50
  Item = LEFTOVERS
  Moves = AIR_SLASH,DAZZLING_GLEAM,ROOST,THUNDER_WAVE
  Nature = CALM
  EVs = 252,0,0,0,200,56

Se recomienda crear al menos 50–100 entrenadores en el pool para garantizar variedad. El sistema selecciona entrenadores aleatoriamente con dificultad escalada según la racha actual del jugador.

Progresión por rondas

Un desafío estándar de Battle Tower sigue esta progresión:

Puedes personalizar la aparición del Brain configurando el evento correspondiente:

# En el script del desafío, definir cuándo aparece el Brain
if pbBattleChallenge.wins == 6  # Victoria 7 (índice 6)
  # Mostrar diálogo especial del Brain
  pbMessage(_I("¡Has llegado al combate final de la ronda!"))
  pbMessage(_I("El As de la Torre te está esperando."))
  # Combate contra el Brain
  pbTrainerBattle(:POKEMON_TRAINER_Brain, "Arturo", 0)
end

Rachas de victorias (Win Streaks)

El sistema registra automáticamente la racha de victorias más alta del jugador. Esta se almacena y se puede consultar:

# Obtener la racha actual
current_wins = pbBattleChallenge.wins

# Obtener la racha récord
record = pbBattleChallenge.pokemon_challenge_record
pbMessage(_I("Tu racha récord es de #{record} victorias."))

Las rachas se usan para desbloquear recompensas especiales y para mostrar en la Tarjeta de Entrenador.

Recompensas

Después de completar cada ronda (7 victorias consecutivas), el jugador recibe recompensas. Puedes configurar Battle Points (BP) u objetos:

# Dar Battle Points como recompensa
# Los BP se almacenan como una variable del jugador
$player.battle_points += 3
pbMessage(_I("¡Has ganado 3 Puntos de Batalla!"))

# Recompensas escalonadas según la racha
case pbBattleChallenge.wins
when 7
  $player.battle_points += 3
  pbMessage(_I("¡Racha de 7! Has ganado 3 PB."))
when 14
  $player.battle_points += 5
  pbMessage(_I("¡Racha de 14! Has ganado 5 PB."))
when 21
  $player.battle_points += 7
  pbReceiveItem(:ABILITYCAPSULE)
  pbMessage(_I("¡Racha de 21! Has ganado 7 PB y una Cápsula de Habilidad."))
when 49
  $player.battle_points += 10
  pbReceiveItem(:STARRIBBON)
  pbMessage(_I("¡Racha de 49! Has ganado 10 PB y la Cinta Estrella."))
end

Tienda de intercambio de BP

Puedes crear una tienda donde los jugadores canjeen sus Puntos de Batalla por objetos:

# Tienda de BP (evento NPC)
pbMessage(_I("¡Bienvenido a la Tienda de Batalla!"))
pbMessage(_I("Tus PB actuales: #{$player.battle_points}"))

items = [
  [:RARECANDY,    1],   # 1 BP
  [:PPUP,         3],   # 3 BP
  [:CHOICEBAND,   10],  # 10 BP
  [:CHOICESPECS,  10],
  [:CHOICESCARF,  10],
  [:LIFEORB,      15],
  [:FOCUSSASH,    10],
  [:ABILITYCAPSULE, 25]
]

# Mostrar opciones
choices = items.map { |item, cost|
  name = GameData::Item.get(item).name
  _I("#{name} - #{cost} PB")
}
choices.push(_I("Cancelar"))

loop do
  choice = pbMessage(_I("¿Qué deseas comprar?"), choices, choices.length)
  break if choice == choices.length - 1
  item, cost = items[choice]
  if $player.battle_points >= cost
    $player.battle_points -= cost
    pbReceiveItem(item)
  else
    pbMessage(_I("No tienes suficientes Puntos de Batalla."))
  end
end

Battle Factory: Pokémon de alquiler

La Battle Factory tiene una mecánica especial donde el jugador no usa sus propios Pokémon. En su lugar, elige de un grupo de Pokémon generados aleatoriamente:

# Iniciar Battle Factory
pbBattleChallenge.set("pokemon_factory", 7, 50, 3)
pbBattleFactoryChallenge

El sistema genera automáticamente un grupo de 6 Pokémon aleatorios del pool. El jugador elige 3. Después de cada combate victorioso, el jugador puede intercambiar uno de sus Pokémon por uno del equipo rival derrotado.

Configurar la instalación completa

Para montar una instalación de batalla completa necesitas:

  1. Mapa de la instalación: lobby con NPCs de recepción, reglas y tienda de BP.
  2. Mapa de combate: un mapa simple donde ocurren los combates consecutivos.
  3. NPC de recepción: explica las reglas y permite iniciar el desafío.
  4. NPC de reglas: muestra las restricciones del desafío actual.
  5. NPC de récords: muestra las rachas de victorias del jugador.
  6. Tienda BP: NPC donde canjear puntos por objetos.
  7. Pool de entrenadores: el archivo PBS con todos los entrenadores del desafío.
  8. Brain/Tycoon: el entrenador jefe de la instalación con diálogos especiales.

Guardar progreso del desafío

Los desafíos de batalla guardan automáticamente el progreso entre rondas. Si el jugador pierde o se retira, la racha actual se reinicia pero el récord se mantiene. El jugador puede guardar la partida entre combates en algunas instalaciones, dependiendo de la configuración.

# Forzar guardado entre rondas (opcional)
if pbBattleChallenge.wins % 7 == 0 && pbBattleChallenge.wins > 0
  pbMessage(_I("¿Deseas guardar la partida antes de continuar?"))
  if pbConfirmMessage(_I("¿Guardar?"))
    pbSave
    pbMessage(_I("Partida guardada."))
  end
end

Errores comunes