Definir un Tipo

Los tipos son una parte fundamental del sistema de combate Pokémon. Cada Pokémon tiene uno o dos tipos, y cada movimiento tiene exactamente un tipo. Las interacciones entre tipos (ventajas, resistencias e inmunidades) determinan la efectividad de los ataques. En Pokémon Essentials, los tipos se definen en el archivo PBS types.txt.

Ubicación del archivo

PBS/types.txt

Formato de una entrada de tipo

Cada tipo se define como un bloque con un identificador interno entre corchetes y sus propiedades:

[FIRE]
Name       = Fuego
IconPosition = 10
IsSpecialType = true
Weaknesses = WATER,GROUND,ROCK
Resistances = FIRE,GRASS,ICE,BUG,STEEL,FAIRY
Immunities =

Propiedades disponibles

PropiedadDescripciónObligatoria
NameNombre visible del tipo en el juego.
IconPositionPosición del icono del tipo en el archivo de iconos (Graphics/UI/types.png). Cada icono ocupa un espacio en la imagen, numerado desde 0.
IsSpecialTypeSi es true, los movimientos de este tipo son especiales de forma predeterminada (sistema Gen 1-3). En Gen 4+, esto no tiene efecto porque cada movimiento define su categoría individualmente.No
IsPseudoTypeSi es true, el tipo no puede asignarse a un Pokémon como tipo primario o secundario. Se usa para tipos virtuales como ??? (el tipo de "Lucha" en algunos contextos).No
WeaknessesLista separada por comas de los tipos que hacen daño x2 contra este tipo.No
ResistancesLista separada por comas de los tipos que hacen daño x0.5 contra este tipo.No
ImmunitiesLista separada por comas de los tipos a los que este tipo es completamente inmune (daño x0).No
FlagsFlags especiales para el tipo. Puede incluir valores como PseudoType.No

Tipos estándar

Essentials incluye los 18 tipos oficiales de Pokémon. Aquí están todos con sus relaciones:

Lista completa de tipos

ID internoNombreIconPosition
NORMALNormal0
FIGHTINGLucha1
FLYINGVolador2
POISONVeneno3
GROUNDTierra4
ROCKRoca5
BUGBicho6
GHOSTFantasma7
STEELAcero8
FIREFuego10
WATERAgua11
GRASSPlanta12
ELECTRICEléctrico13
PSYCHICPsíquico14
ICEHielo15
DRAGONDragón16
DARKSiniestro17
FAIRYHada18

La posición 9 generalmente se reserva para el tipo ??? (QMARKS) que es un pseudo-tipo.

Tabla de efectividad de tipos

La efectividad se calcula a partir de las propiedades Weaknesses, Resistances e Immunities. La relación funciona así:

Para Pokémon con dos tipos, los multiplicadores se combinan. Por ejemplo, un Pokémon Planta/Volador recibe x4 de Hielo (x2 contra Planta × x2 contra Volador).

Ejemplo: Definición completa de un tipo

Aquí se muestra la definición completa del tipo Agua:

[WATER]
Name         = Agua
IconPosition = 11
Weaknesses   = GRASS,ELECTRIC
Resistances  = FIRE,WATER,ICE,STEEL
Immunities   =

Esto significa:

Crear un tipo personalizado

Puedes añadir tipos nuevos a tu juego. A continuación se muestra un ejemplo completo de cómo crear un tipo "Sonido" (Sound) personalizado:

Paso 1: Definir en types.txt

[SOUND]
Name         = Sonido
IconPosition = 19
Weaknesses   = STEEL,GROUND
Resistances  = SOUND,FLYING,NORMAL
Immunities   =

Paso 2: Actualizar otros tipos

Los otros tipos deben reflejar sus relaciones con el nuevo tipo. Por ejemplo, si Sonido es supereficaz contra Hielo, debes agregar SOUND a las debilidades de Hielo:

[ICE]
Name         = Hielo
IconPosition = 15
Weaknesses   = FIRE,FIGHTING,ROCK,STEEL,SOUND
Resistances  = ICE
Immunities   =

Paso 3: Crear el icono del tipo

Edita el archivo Graphics/UI/types.png y añade el icono del nuevo tipo en la posición 19 (o la que hayas configurado en IconPosition). Cada posición tiene un tamaño fijo de 64×28 píxeles (puede variar según tu configuración).

Paso 4: Asignar a Pokémon y movimientos

En pokemon.txt, puedes asignar el nuevo tipo a un Pokémon:

[EXPLOUD]
...
Types = NORMAL,SOUND
...

En moves.txt, crea movimientos del nuevo tipo:

[SONICBOOM_CUSTOM]
Name          = Onda Sónica
Type          = SOUND
Category      = Special
Power         = 80
Accuracy      = 100
TotalPP       = 15
Target        = NearOther
FunctionCode  = None
Description   = Una potente onda de sonido que golpea al objetivo.

Paso 5: Compilar

Después de realizar todos los cambios en los archivos PBS, compila el juego desde el menú de depuración para que los nuevos datos se carguen correctamente.

Otro ejemplo: Tipo Hada (Fairy)

Si tu proyecto no incluye el tipo Hada y deseas añadirlo, aquí está la definición oficial:

[FAIRY]
Name         = Hada
IconPosition = 18
Weaknesses   = POISON,STEEL
Resistances  = FIGHTING,BUG,DARK
Immunities   = DRAGON

Además, debes actualizar los siguientes tipos que interactúan con Hada:

# Agregar FAIRY a las debilidades de FIGHTING
[FIGHTING]
Weaknesses = FLYING,PSYCHIC,FAIRY
...

# Agregar FAIRY a las debilidades de DRAGON
[DRAGON]
Weaknesses = ICE,DRAGON,FAIRY
...

# Agregar FAIRY a las debilidades de DARK
[DARK]
Weaknesses = FIGHTING,BUG,FAIRY
...

# Agregar FAIRY a las resistencias de FIRE
[FIRE]
Resistances = FIRE,GRASS,ICE,BUG,STEEL,FAIRY
...

# Agregar FAIRY a las resistencias de POISON
[POISON]
Resistances = FIGHTING,POISON,BUG,GRASS,FAIRY
...

# Agregar FAIRY a las resistencias de STEEL
[STEEL]
Resistances = NORMAL,FLYING,ROCK,BUG,STEEL,GRASS,PSYCHIC,ICE,DRAGON,FAIRY
...

Cómo funcionan los tipos en el combate

El cálculo de efectividad de tipo se realiza en el módulo Effectiveness del código de batalla. El flujo es:

  1. Se obtiene el tipo del movimiento atacante.
  2. Se obtienen los tipos del Pokémon defensor (tipo 1 y tipo 2).
  3. Se calcula el multiplicador contra cada tipo del defensor.
  4. Los multiplicadores se multiplican entre sí.
  5. El resultado final puede ser: x0, x0.25, x0.5, x1, x2 o x4.
# Verificar efectividad por script
type_atk = :FIRE
type_def = :GRASS
eff = Effectiveness.calculate(type_atk, type_def)
# Devuelve: 4 (supereficaz, x2)

# Valores de retorno:
# 0 = inmune (x0)
# 1 = doblemente resistido (x0.25)
# 2 = resistido (x0.5)
# 4 = normal (x1)
# 8 = supereficaz (x2)
# 16 = doblemente supereficaz (x4)

Consultar tipos por script

# Obtener datos de un tipo
type_data = GameData::Type.get(:FIRE)
pbMessage("Nombre: #{type_data.name}")             # "Fuego"
pbMessage("Posición icono: #{type_data.icon_position}")  # 10

# Comprobar si un tipo existe
if GameData::Type.exists?(:SOUND)
  pbMessage("El tipo Sonido existe.")
end

# Iterar sobre todos los tipos
GameData::Type.each do |type|
  next if type.pseudo_type
  pbMessage("Tipo: #{type.name}")
end

# Verificar debilidades
type_data = GameData::Type.get(:WATER)
if type_data.weaknesses.include?(:ELECTRIC)
  pbMessage("Agua es débil contra Eléctrico.")
end

Iconos de tipo

Los iconos de tipo se almacenan en una imagen única (sprite sheet) ubicada en:

Graphics/UI/types.png

Cada tipo ocupa un rectángulo de tamaño fijo en la imagen. La propiedad IconPosition indica qué rectángulo usar, contando desde 0 de arriba a abajo. Cuando añades un tipo nuevo, debes ampliar esta imagen y dibujar el icono correspondiente en la posición correcta.

El icono debe tener:

Tipo ??? (QMARKS)

El tipo especial ??? es un pseudo-tipo que no se asigna a Pokémon normales. Se usa internamente en ciertos contextos (como el movimiento Maldición en generaciones antiguas). Se define con la flag IsPseudoType:

[QMARKS]
Name         = ???
IconPosition = 9
IsPseudoType = true
Weaknesses   =
Resistances  =
Immunities   =

Consejos y buenas prácticas