Nuevos Métodos de Encuentro
Pokémon Essentials incluye un conjunto de métodos de encuentro predefinidos: Land (Hierba), Cave (Cueva), Water (Surf), OldRod, GoodRod, SuperRod, RockSmash, HeadbuttLow y HeadbuttHigh, entre otros. Sin embargo, es posible que tu proyecto necesite métodos de encuentro personalizados que no existen en el sistema base.
Este artículo explica la arquitectura del sistema de tipos de encuentro, cómo crear nuevos tipos personalizados, cómo registrarlos en el motor y cómo definir encuentros para ellos en los archivos PBS.
Entendiendo el Sistema de Encuentros
El sistema de encuentros salvajes en Pokémon Essentials se compone de varios elementos interconectados:
- Tipos de encuentro (
GameData::EncounterType): Define los métodos posibles de encuentro (hierba, cueva, agua, pesca, etc.). - Tablas de encuentro (
PBS/encounters.txt): Define qué Pokémon aparecen con cada método en cada mapa. - Disparadores de encuentro: El código que decide cuándo y cómo se activa un encuentro según el contexto del juego (caminar por hierba, surfear, usar caña, etc.).
- Densidad de encuentro: La probabilidad base de que ocurra un encuentro en cada paso.
Estructura de GameData::EncounterType
Cada tipo de encuentro se registra en GameData::EncounterType y contiene las siguientes
propiedades:
| Propiedad | Tipo | Descripción |
|---|---|---|
id |
Symbol | Identificador interno único del tipo de encuentro. |
real_name |
String | Nombre visible para las herramientas y depuración. |
type |
Symbol | Categoría general (:land, :water, :fishing, :contest, etc.). |
trigger_chance |
Integer | Probabilidad base de activar un encuentro por paso (ej: 21 para hierba). |
old_slots |
Array | Distribución de probabilidades para cada slot de la tabla de encuentros. |
Tipos de Encuentro Predefinidos
Los tipos de encuentro estándar en Pokémon Essentials son:
| ID | Nombre | Categoría | Descripción |
|---|---|---|---|
Land |
Hierba | :land | Encuentros caminando por hierba alta. |
LandDay |
Hierba (Día) | :land | Encuentros en hierba durante el día. |
LandNight |
Hierba (Noche) | :land | Encuentros en hierba durante la noche. |
LandMorning |
Hierba (Mañana) | :land | Encuentros en hierba por la mañana. |
Cave |
Cueva | :cave | Encuentros caminando dentro de cuevas. |
Water |
Surf | :water | Encuentros surfeando en agua. |
OldRod |
Caña Vieja | :fishing | Pesca con Caña Vieja. |
GoodRod |
Caña Buena | :fishing | Pesca con Caña Buena. |
SuperRod |
Supercaña | :fishing | Pesca con Supercaña. |
RockSmash |
Golpe Roca | :none | Encuentros al romper rocas. |
HeadbuttLow |
Cabezazo (Bajo) | :none | Encuentros al golpear árboles (frecuentes). |
HeadbuttHigh |
Cabezazo (Alto) | :none | Encuentros al golpear árboles (raros). |
BugContest |
Concurso de Insectos | :contest | Encuentros durante el concurso de insectos. |
Crear un Nuevo Tipo de Encuentro
Veamos paso a paso cómo crear un nuevo tipo de encuentro personalizado. Como ejemplo, crearemos un tipo "Excavación" (_Digging_) que permite encontrar Pokémon bajo tierra al usar una pala.
Paso 1: Registrar el tipo en GameData::EncounterType
En tu archivo de scripts personalizado (en la sección de Plugins o antes de Main), registra
el nuevo tipo de encuentro:
# Registrar nuevo tipo de encuentro: Excavación (Digging)
GameData::EncounterType.register({
:id => :Digging,
:real_name => "Excavación",
:type => :none, # Categoría personalizada
:trigger_chance => 0, # 0 porque se activa manualmente, no al caminar
:old_slots => [30, 25, 20, 15, 10] # 5 slots con distribución personalizada
})
Desglose de los parámetros:
:id— El identificador interno del tipo. Debe ser único y se usa enencounters.txt.:real_name— Nombre legible para depuración y herramientas.:type— Categoría general. Usa:nonepara tipos que no encajan en land/water/fishing. Si tu tipo se comporta como un encuentro terrestre, usa:land.:trigger_chance— Probabilidad base de encuentro por paso. Usa 0 si el encuentro se activa solo por evento/acción.:old_slots— Array de probabilidades para cada slot. La suma debería ser 100.
Paso 2: Definir encuentros en PBS
Una vez registrado el tipo, puedes usarlo en PBS/encounters.txt para definir qué Pokémon
aparecen al usar este método en cada mapa:
# PBS/encounters.txt — Mapa 035 (Cueva Minera)
[035]
Cave,10
ZUBAT,15,20
GEODUDE,15,20
ONIX,18,22
Digging,0
DIGLETT,10,18
DUGTRIO,20,25
ONIX,15,22
SANDSHREW,12,18
TRAPINCH,15,20
El tipo Digging aparece como una sección más de encuentros para el mapa 035. Como
trigger_chance es 0, estos encuentros no ocurren al caminar; debes activarlos manualmente.
Paso 3: Crear el disparador del encuentro
Ahora necesitas crear el código que activa el encuentro cuando el jugador realiza la acción correspondiente. En nuestro ejemplo, esto sería usar una pala:
# Definir el objeto "Pala" con uso en el campo
# En PBS/items.txt:
# [SHOVEL]
# Name = Pala
# NamePlural = Palas
# Pocket = 8
# Price = 0
# FieldUse = Direct
# Flags = KeyItem
# Description = Una pala resistente. Permite excavar en suelos blandos.
# Handler para usar la Pala en el campo
ItemHandlers::UseFromBag.add(:SHOVEL, proc { |item|
# Verificar que el tile actual permite excavación
terrain = $game_map.terrain_tag($game_player.x, $game_player.y)
if terrain == :Diggable # Terrain tag personalizado para suelo excavable
next 2 # 2 = usar objeto y cerrar mochila
else
pbMessage("No puedes excavar aquí.")
next 0 # 0 = no usar
end
})
ItemHandlers::UseInField.add(:SHOVEL, proc { |item|
terrain = $game_map.terrain_tag($game_player.x, $game_player.y)
if terrain != :Diggable
pbMessage("El suelo aquí es demasiado duro para excavar.")
next false
end
pbMessage("Has empezado a excavar...")
pbWait(40)
# Intentar generar un encuentro del tipo Digging
encounter = $PokemonEncounters.choose_wild_pokemon(:Digging)
if encounter
species, level = encounter
pbMessage("¡Has encontrado un Pokémon bajo tierra!")
pbWildBattle(species, level)
else
# Si no hay encuentro, encontrar un objeto aleatorio
pbMessage("No has encontrado ningún Pokémon, pero...")
items = [:NUGGET, :STARDUST, :REVIVE, :RARECANDY, :HARDSTONE]
found_item = items.sample
pbReceiveItem(found_item)
end
next true
})
Paso 4: Crear el terrain tag personalizado (opcional)
Si tu método de encuentro depende de un terrain tag específico (como "suelo excavable"), debes registrarlo:
# En PBS/terrain_tags.txt, añade:
# [Diggable]
# ID = 13
# CanEncounter = false
# O regístralo por código:
GameData::TerrainTag.register({
:id => :Diggable,
:id_number => 13
})
Ejemplo Completo: Encuentros Nocturnos Especiales
Veamos otro ejemplo: un tipo de encuentro que solo se activa durante la noche en zonas boscosas, simulando Pokémon nocturnos que salen de sus escondites.
Registro del tipo
GameData::EncounterType.register({
:id => :NightForest,
:real_name => "Bosque Nocturno",
:type => :land,
:trigger_chance => 15, # Probabilidad base de encuentro al caminar
:old_slots => [20, 20, 15, 15, 10, 10, 5, 5] # 8 slots
})
Disparador automático
Como este tipo tiene :type => :land y un trigger_chance mayor que 0, necesitamos
modificar el sistema de encuentros para que lo use en las condiciones correctas:
# Sobrescribir el método que elige el tipo de encuentro al caminar
module EncounterModifier
class << self
alias_method :original_encounter_type, :encounter_type
end
def self.encounter_type
# Si es de noche y estamos en un mapa con NightForest definido
if PBDayNight.isNight? && $PokemonEncounters.has_encounter_type?(:NightForest)
return :NightForest
end
# Si no, usar el tipo de encuentro original
return original_encounter_type
end
end
PBS
# PBS/encounters.txt — Mapa 022 (Bosque Misterioso)
[022]
Land,21
CATERPIE,6,8
WEEDLE,6,8
PIKACHU,8,10
ODDISH,8,10
NightForest,15
HOOTHOOT,8,12
SPINARAK,8,10
MURKROW,10,14
MISDREAVUS,10,14
SHUPPET,12,15
DUSKULL,12,15
HOUNDOUR,10,14
ABSOL,15,18
Ejemplo: Encuentros por Enjambre
Los enjambres (swarms) son otro tipo de encuentro personalizable. Aquí tienes una implementación simplificada:
GameData::EncounterType.register({
:id => :Swarm,
:real_name => "Enjambre",
:type => :land,
:trigger_chance => 40, # Alta probabilidad de encuentro durante enjambres
:old_slots => [50, 30, 20] # 3 slots, el enjambre domina
})
# Activar un enjambre en un mapa
def pbStartSwarm(map_id, species, duration_hours = 24)
$PokemonGlobal.swarm = {
map_id: map_id,
species: species,
end_time: pbGetTimeNow + (duration_hours * 3600)
}
pbMessage("¡Se ha reportado un enjambre de #{GameData::Species.get(species).name}!")
end
# Detener el enjambre actual
def pbStopSwarm
$PokemonGlobal.swarm = nil
end
# Verificar si hay enjambre activo en el mapa actual
def pbSwarmActive?
swarm = $PokemonGlobal.swarm
return false if !swarm
return false if swarm[:map_id] != $game_map.map_id
return false if pbGetTimeNow > swarm[:end_time]
return true
end
Registrar Tipos con Variaciones Horarias
Si quieres que tu tipo de encuentro tenga variaciones según la hora del día (como Land tiene LandDay, LandNight, LandMorning), puedes registrar múltiples tipos relacionados:
# Tipo base y variaciones horarias
GameData::EncounterType.register({
:id => :Desert, :real_name => "Desierto",
:type => :land, :trigger_chance => 18,
:old_slots => [25, 20, 20, 15, 10, 10]
})
GameData::EncounterType.register({
:id => :DesertDay, :real_name => "Desierto (Día)",
:type => :land, :trigger_chance => 18,
:old_slots => [25, 20, 20, 15, 10, 10]
})
GameData::EncounterType.register({
:id => :DesertNight, :real_name => "Desierto (Noche)",
:type => :land, :trigger_chance => 12, # Menos encuentros de noche
:old_slots => [25, 20, 20, 15, 10, 10]
})
# En PBS/encounters.txt:
# [050] # Mapa: Gran Desierto
# Desert,18
# SANDSHREW,20,25
# TRAPINCH,20,25
# CACNEA,22,28
# BALTOY,22,26
# SANDILE,20,25
# HIPPOPOTAS,24,28
# DesertNight,12
# SANDSHREW,20,25
# TRAPINCH,20,25
# SKORUPI,22,28
# SANDILE,22,26
# KROKOROK,26,30
# KROOKODILE,30,35
Probar Tus Nuevos Tipos de Encuentro
Después de crear un nuevo tipo de encuentro, es importante probarlo exhaustivamente:
-
Compilar los PBS: Ejecuta el juego en modo debug y deja que compile los archivos PBS. Si
hay errores en el formato de
encounters.txt, aparecerán aquí. -
Verificar el registro: En la consola de debug, comprueba que el tipo existe:
# En la consola de debug (F9) p GameData::EncounterType.exists?(:Digging) # Debería imprimir true - Probar en el mapa: Ve al mapa donde definiste los encuentros y activa el método correspondiente.
- Verificar distribución: Usa el modo debug para verificar que la distribución de especies es la esperada.
Compatibilidad y Buenas Prácticas
- Usa IDs descriptivos y únicos para tus tipos de encuentro para evitar conflictos con plugins.
- Documenta tus tipos personalizados para que otros desarrolladores de tu equipo puedan entenderlos.
- Mantén la coherencia en la distribución de slots: la suma de
old_slotsdebe ser 100. - Prueba extensamente con diferentes tamaños de equipo y habilidades del primer Pokémon.
- Asegúrate de que los Pokémon definidos en tus tablas de encuentro existen en
pokemon.txt. - Si tu tipo se activa al caminar, gestiona correctamente el Repelente (Repel) para que funcione con tu nuevo tipo.
- Considera la interacción con habilidades como Intimidación (reduce encuentros) y Efecto Faro (atrae Pokémon de nivel alto).
Resolución de Problemas
Error al compilar PBS: tipo de encuentro desconocido
- Asegúrate de registrar el tipo antes de que se compile
encounters.txt. Coloca el registro en un script que se cargue temprano. - Verifica que el nombre del tipo en PBS coincide exactamente con el
:idregistrado (sensible a mayúsculas/minúsculas).
Los encuentros no se activan
- Si
trigger_chancees 0, el tipo no se activa automáticamente al caminar. Debes dispararlo manualmente. - Si
trigger_chancees mayor que 0, verifica que el sistema de encuentros está usando tu tipo en las condiciones correctas. - Comprueba que el mapa tiene definidos encuentros para tu tipo personalizado.
Distribución de Pokémon incorrecta
- Revisa que el array
old_slotstiene el mismo número de elementos que los slots definidos en PBS. - Verifica que la suma de probabilidades de
old_slotses 100. - Recuerda que el primer slot es el que tiene mayor probabilidad por convención.