Efectos de Objetos

Los efectos de los objetos en Pokémon Essentials se definen mediante handlers (manejadores) en el módulo ItemHandlers. Cada handler es un bloque de código Ruby que se ejecuta cuando el jugador usa un objeto en una situación determinada. Los handlers se encuentran en los scripts del juego, principalmente en la sección de scripts de objetos.

Módulo ItemHandlers

El módulo ItemHandlers contiene todos los manejadores de efectos de objetos. Cada tipo de handler corresponde a una situación de uso diferente:

Handler Cuándo se ejecuta FieldUse / BattleUse requerido
UseFromBag Cuando el jugador selecciona "Usar" en la mochila (antes de elegir Pokémon). FieldUse = Direct
ConfirmUseInField Confirmación antes de usar un objeto en el campo. Si devuelve false, se cancela el uso. FieldUse = Direct
UseInField Efecto principal al usar un objeto directamente en el campo (fuera de la mochila). FieldUse = Direct
UseOnPokemon Efecto al usar un objeto sobre un Pokémon del equipo, tanto en campo como en combate. FieldUse = OnPokemon o BattleUse = OnPokemon
BattleUseOnBattler Efecto al usar un objeto sobre el Pokémon activo en combate. BattleUse = OnBattler
BattleUseOnPokemon Efecto al usar un objeto sobre un Pokémon del equipo durante el combate. BattleUse = OnPokemon

UseFromBag

Este handler se ejecuta cuando el jugador usa un objeto directamente desde la mochila. Debe devolver un valor que indica el resultado:

Ejemplo: Objeto de uso directo

ItemHandlers::UseFromBag.add(:REPEL, proc { |item|
  if $PokemonGlobal.repel > 0
    pbMessage(_INTL("Ya hay un repelente activo."))
    next 0  # No se usa
  end
  $PokemonGlobal.repel = 100
  pbMessage(_INTL("Se activó el Repelente."))
  next 3  # Usado, cerrar mochila, no consumir
})

UseInField

Este handler se ejecuta cuando el objeto se usa en el campo de juego (fuera de la mochila). Se ejecuta después de cerrar la pantalla de la mochila. Es útil para objetos que interactúan con el mapa o el entorno del jugador.

Ejemplo: Cuerda Huida

ItemHandlers::UseInField.add(:ESCAPEROPE, proc { |item|
  if $game_player.pbHasDependentEvents?
    pbMessage(_INTL("No puedes usar eso ahora."))
    next false
  end
  if GameData::MapMetadata.exists?($game_map.map_id) &&
     GameData::MapMetadata.get($game_map.map_id).can_escape
    pbUseItemMessage(item)
    pbEscapeRope
    next true
  end
  pbMessage(_INTL("No puedes usar eso aquí."))
  next false
})

UseOnPokemon

Este handler se ejecuta cuando el jugador usa un objeto sobre un Pokémon del equipo. Recibe como parámetros el objeto, el Pokémon objetivo y la escena actual.

Ejemplo: Poción (restaurar PS)

ItemHandlers::UseOnPokemon.add(:POTION, proc { |item, qty, pkmn, scene|
  next false if !pkmn.able? || pkmn.hp == pkmn.totalhp
  pkmn.hp += 20
  scene.pbRefresh
  pbMessage(_INTL("{1} recuperó PS.", pkmn.name))
  next true
})

Ejemplo: Piedra evolutiva

ItemHandlers::UseOnPokemon.add(:FIRESTONE, proc { |item, qty, pkmn, scene|
  if pkmn.check_evolution_on_use_item(item)
    pbFadeOutInWithMusic {
      evo = PokemonEvolutionScene.new
      evo.pbStartScreen(pkmn, pkmn.check_evolution_on_use_item(item))
      evo.pbEvolution
      evo.pbEndScreen
      scene.pbRefresh
    }
    next true
  end
  pbMessage(_INTL("No tiene efecto."))
  next false
})

Ejemplo: Caramelo Raro

ItemHandlers::UseOnPokemon.add(:RARECANDY, proc { |item, qty, pkmn, scene|
  if pkmn.level >= GameData::GrowthRate.max_level
    pbMessage(_INTL("{1} ya está al nivel máximo.", pkmn.name))
    next false
  end
  pbSEPlay("Pkmn level up")
  pkmn.level += 1
  pkmn.calc_stats
  scene.pbRefresh
  pbMessage(_INTL("{1} subió al nivel {2}.", pkmn.name, pkmn.level))
  # Comprobar si aprende movimientos al subir de nivel
  pkmn.getMoveList.each do |m|
    next if m[0] != pkmn.level
    pbLearnMove(pkmn, m[1])
  end
  # Comprobar evolución
  new_species = pkmn.check_evolution_on_level_up
  if new_species
    pbFadeOutInWithMusic {
      evo = PokemonEvolutionScene.new
      evo.pbStartScreen(pkmn, new_species)
      evo.pbEvolution
      evo.pbEndScreen
      scene.pbRefresh
    }
  end
  next true
})

BattleUseOnBattler

Este handler se ejecuta cuando el jugador usa un objeto sobre el Pokémon activo durante un combate. Recibe el objeto, el battler objetivo y la batalla.

Ejemplo: Ataque X

ItemHandlers::BattleUseOnBattler.add(:XATTACK, proc { |item, battler, scene|
  battler.pbRaiseStatStage(:ATTACK, 1, battler)
  next true
})

Ejemplo: Guardia Especial

ItemHandlers::BattleUseOnBattler.add(:GUARDSPEC, proc { |item, battler, scene|
  battler.effects[PBEffects::Mist] = 5
  pbMessage(_INTL("¡El equipo de {1} quedó protegido de la reducción de estadísticas!",
            battler.pbThis(true)))
  next true
})

BattleUseOnPokemon

Similar a UseOnPokemon, pero específico para el contexto de combate. Se usa para objetos curativos durante la batalla.

Ejemplo: Restaura PP en combate

ItemHandlers::BattleUseOnPokemon.add(:ELIXIR, proc { |item, pkmn, battler, choices, scene|
  pkmn.moves.each do |move|
    next if move.id == nil
    move.pp = [move.pp + 10, move.total_pp].min
  end
  pbMessage(_INTL("Se restauraron los PP de {1}.", pkmn.name))
  battler&.pbCheckFormOnMovesetChange if battler
  next true
})

Efectos de objetos equipados (Hold Items)

Los objetos equipados a un Pokémon pueden tener efectos durante el combate a través de handlers especializados. Estos se encuentran en el módulo Battle::ItemEffects.

Tipos de handlers de objetos equipados

Handler Descripción
DamageCalcFromUser Modifica el daño cuando el portador del objeto ataca.
DamageCalcFromTarget Modifica el daño cuando el portador del objeto recibe un ataque.
OnBeingHit Se activa cuando el portador recibe un golpe.
OnEndOfUsingMove Se activa al final de un turno en que el portador usó un movimiento.
EndOfRoundHealing Se activa al final de cada ronda para curar al portador (ej: Restos).
StatusCure Comprueba si el objeto cura automáticamente un estado alterado.
OnSwitchIn Se activa cuando el portador entra al campo de batalla.
SpeedCalc Modifica la velocidad del portador del objeto.
WeightCalc Modifica el peso del portador (relevante para movimientos como Hierba Lazo).
CriticalCalc Modifica la probabilidad de golpe crítico.
AccuracyCalcFromUser Modifica la precisión del portador al atacar.
AccuracyCalcFromTarget Modifica la evasión del portador al ser atacado.

Ejemplo: Restos (curación al final de ronda)

Battle::ItemEffects::EndOfRoundHealing.add(:LEFTOVERS,
  proc { |item, battler, battle|
    next if !battler.canHeal?
    battle.pbCommonAnimation("UseItem", battler)
    battler.pbRecoverHP(battler.totalhp / 16)
    battle.pbDisplay(_INTL("¡{1} recuperó un poco de PS con sus {2}!",
                    battler.pbThis, battler.itemName))
  }
)

Ejemplo: Cinta Focus (sobrevivir con 1 PS)

Battle::ItemEffects::OnBeingHit.add(:FOCUSBAND,
  proc { |item, user, target, move, battle|
    next if target.hp > 0
    next if rand(10) != 0  # 10% de probabilidad
    target.hp = 1
    battle.pbCommonAnimation("UseItem", target)
    battle.pbDisplay(_INTL("¡{1} aguantó el golpe con su {2}!",
                    target.pbThis, target.itemName))
  }
)

Ejemplo: Objeto que potencia un tipo

Battle::ItemEffects::DamageCalcFromUser.add(:CHARCOAL,
  proc { |item, user, target, move, mults, baseDmg, type|
    mults[:attack_multiplier] *= 1.2 if type == :FIRE
  }
)

Crear un objeto personalizado completo

Para crear un objeto totalmente nuevo, necesitas:

  1. Definir el objeto en el PBS (items.txt):
    [SUPERELIXIR]
    Name = Súper Elixir
    NamePlural = Súper Elixires
    Pocket = 2
    Price = 5000
    FieldUse = OnPokemon
    BattleUse = OnPokemon
    Flags = Fling_30
    Description = Restaura todos los PS y PP de un Pokémon.
  2. Crear el handler de uso en campo:
    ItemHandlers::UseOnPokemon.add(:SUPERELIXIR, proc { |item, qty, pkmn, scene|
      # Comprobar si hace falta usar el objeto
      if pkmn.hp == pkmn.totalhp && !pkmn.moves.any? { |m| m.pp < m.total_pp }
        pbMessage(_INTL("{1} ya tiene los PS y PP al máximo.", pkmn.name))
        next false
      end
      # Aplicar efecto
      pkmn.heal_HP
      pkmn.heal_PP
      scene.pbRefresh
      pbMessage(_INTL("Se restauraron todos los PS y PP de {1}.", pkmn.name))
      next true
    })
  3. Añadir el gráfico en Graphics/Items/SUPERELIXIR.png.
  4. Compilar el juego para que reconozca el nuevo objeto.

Consejos para handlers