Skip to main content

PK9 and PA9 Classes

Generation 9 introduces the latest Pokémon data formats: PK9 for Scarlet/Violet and PA9 for Z-A (Legends Z-A).

PK9 Class

Namespace: PKHeX.Core File: PKHeX.Core/PKM/PK9.cs

Format Specifications

PropertyValue
SIZE_STORED328 bytes (0x148)
SIZE_PARTY344 bytes (0x158)
Generation9
ContextEntityContext.Gen9
GamesScarlet, Violet

Key Features

Terastallization

Gen 9’s main battle mechanic:
public byte TeraTypeOriginal { get; set; }
public byte TeraTypeOverride { get; set; }
  • TeraTypeOriginal: Natural Tera Type (based on species)
  • TeraTypeOverride: Changed Tera Type (0x19 = no override)

Obedience Level

public byte ObedienceLevel { get; set; }
Tracks the level at which the Pokémon will obey, based on badges.

Scale System

public byte Scale { get; set; }
public byte HeightScalar { get; set; }
public byte WeightScalar { get; set; }
Expanded size variation system from PLA.

Data Structure

Same block structure as PK8:
  • 4 blocks of 80 bytes each
  • 8-byte header
  • Total: 328 bytes stored, 344 party

Important Properties

Tech Records Continued

public bool GetMoveRecordFlag(int index) { get; set; }
Gen 9 continues using the Tech Record system.

Battle Version

public byte BattleVersion { get; set; }
Tracks which game version the Pokémon last battled in.

HOME Tracker

public ulong Tracker { get; set; }
Unique identifier for Pokémon HOME.

Tera Type System

public MoveType TeraType
{
    get
    {
        var val = TeraTypeOverride;
        if (val != 19) // 19 = no override
            return (MoveType)val;
        return (MoveType)TeraTypeOriginal;
    }
}
The effective Tera Type is the override if set, otherwise the original.

Relearn Move Management

public void FixRelearn()
{
    // Compresses relearn moves to remove gaps
    // If move 4 exists but move 3 is empty, shifts down
}
Ensures relearn moves are properly ordered without gaps.

PA9 Class

Namespace: PKHeX.Core File: PKHeX.Core/PKM/PA9.cs

Format Specifications

PropertyValue
SIZE_STORED328 bytes (0x148)
SIZE_PARTY344 bytes (0x158)
Generation9
ContextEntityContext.Gen9a
GamesLegends: Z-A

Key Features

Alpha Pokémon (Returning)

public bool IsAlpha { get; set; }
Alpha Pokémon return from Legends: Arceus.

Plus Records

New learning system:
public interface IPlusRecord
{
    bool GetPlusRecordFlag(int index) { get; set; }
}
Extended version of Tech Records for Z-A.

Data Structure

Same size as PK9 but with different internal structure:
  • Modified block layout for Alpha support
  • Plus Record flags replace some PK9 features
  • Different PersonalInfo table (PersonalTable.ZA)

Differences from PK9

Added Features

  • Alpha Pokémon
  • Plus Records system
  • Possibly modified battle mechanics

Removed Features

  • Terastallization (may not be in Z-A)
  • Some SV-specific marks/ribbons

Modified Features

  • Uses PersonalInfo9ZA instead of PersonalInfo9SV
  • Different move pools and availability

Comparison Table

FeaturePK9PA9
Size (Stored)328 bytes328 bytes
Size (Party)344 bytes344 bytes
Block Size80 bytes80 bytes
TerastallizationYesNo
AlphaNoYes
Plus RecordsNoYes
Tech RecordsYesYes
Scale SystemYesYes
Obedience LevelYesYes
Contest StatsNoYes

Code Examples

Creating a PK9 with Tera Type

var pk9 = new PK9
{
    Species = 908, // Meowscarada
    Form = 0,
    CurrentLevel = 50,
    TeraTypeOriginal = (byte)MoveType.Grass,
    TeraTypeOverride = (byte)MoveType.Dark, // Changed Tera Type
    ObedienceLevel = 50,
    Ball = 1, // Poke Ball
};
pk9.SetRandomIVs(6);
pk9.RefreshChecksum();

Checking Tera Type

var pk9 = new PK9(data);

if (pk9.TeraTypeOverride != 19)
{
    Console.WriteLine($"Tera Type changed to: {(MoveType)pk9.TeraTypeOverride}");
}
else
{
    Console.WriteLine($"Original Tera Type: {(MoveType)pk9.TeraTypeOriginal}");
}

Creating an Alpha PA9

var pa9 = new PA9
{
    Species = 901, // Ursaluna (Blood Moon?)
    CurrentLevel = 70,
    IsAlpha = true,
    HeightScalar = 255,
    WeightScalar = 255,
};
pa9.SetRandomIVs(6);
pa9.RefreshChecksum();

Setting Scale Values

var pk9 = new PK9
{
    Species = 25, // Pikachu
    Scale = 128,      // Average scale
    HeightScalar = 150,
    WeightScalar = 100,
};

Fixing Relearn Moves

var pk9 = new PK9(data);

// Before: [Move1, 0, 0, Move4]
pk9.FixRelearn();
// After:  [Move1, Move4, 0, 0]

Handler Update System

public void UpdateHandler(ITrainerInfo tr)
{
    if (IsEgg)
    {
        // Eggs get link trade data if traded
        const ushort location = Locations.LinkTrade6;
        if (MetLocation != location && !BelongsTo(tr))
        {
            var date = EncounterDate.GetDateSwitch();
            SetLinkTradeEgg(date.Day, date.Month, date.Year, location);
        }
        return;
    }

    // Update handler if OT doesn't match
    if (!TradeOT(tr))
        TradeHT(tr);
}

New Gen 9 Features

Unhatched Eggs

public bool IsUnhatchedEgg => Version == 0 && IsEgg;
Eggs that haven’t been given a version yet.

Enhanced Shiny Calculation

public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4;
public override uint TSV => (uint)(TID16 ^ SID16) >> 4;
Gen 9 uses 4-bit shift (1/4096 shiny rate) instead of 3-bit.

Characteristic

public override int Characteristic => 
    EntityCharacteristic.GetCharacteristicInit0(EncryptionConstant, IV32);
Based on Encryption Constant and IVs.

Migration from Gen 8

When migrating from Gen 8 to Gen 9:
  1. Encryption Constant preserved
  2. PID preserved
  3. IVs preserved
  4. Tera Type assigned based on species
  5. Obedience Level set based on current level
  6. Scale values generated
  7. Tech Records preserved
  8. Ribbons preserved where applicable

See Also

Build docs developers (and LLMs) love