Overview
Once you have a Pokémon entity, you can modify its properties extensively. This guide covers common and advanced property modifications.
Basic Properties
Change a Pokémon’s species or form:
var pk = new PK9();
// Change species
pk.Species = (ushort)Species.Charizard;
// Change form (e.g., Mega Evolution, Regional Forms)
pk.Form = 1; // Mega Charizard X
// For Pokémon with special forms
var rotom = new PK9
{
Species = (ushort)Species.Rotom,
Form = 1 // Heat Rotom
};
Level and Experience
Modify level and experience:
// Set level directly
pk.CurrentLevel = 100;
// Set experience for specific level
pk.EXP = Experience.GetEXP(100, pk.PersonalInfo.EXPGrowth);
// Get current level from experience
int level = Experience.GetLevel(pk.EXP, pk.PersonalInfo.EXPGrowth);
Nickname and Language
pk.IsNicknamed = true;
pk.Nickname = "Blaze";
pk.Language = (int)LanguageID.English;
// Clear nickname (use species name)
pk.IsNicknamed = false;
pk.Nickname = pk.Nickname; // Will display species name
Stats and Training
Individual Values (IVs)
// Set individual stats
pk.IV_HP = 31;
pk.IV_ATK = 31;
pk.IV_DEF = 31;
pk.IV_SPA = 0; // For physical attackers
pk.IV_SPD = 31;
pk.IV_SPE = 31;
// Randomize IVs
pk.SetRandomIVs();
// Set perfect IVs
pk.SetRandomIVs(flawless: 6);
// Get IV32 (all IVs as single value)
uint iv32 = pk.IV32;
IVs range from 0-31. Setting all IVs to 31 creates a “perfect” Pokémon.
Effort Values (EVs)
// Standard competitive EV spread
pk.EV_HP = 252;
pk.EV_ATK = 252;
pk.EV_DEF = 0;
pk.EV_SPA = 0;
pk.EV_SPD = 0;
pk.EV_SPE = 6;
// Clear all EVs
pk.EVs = new int[] { 0, 0, 0, 0, 0, 0 };
// Get EV total (should not exceed 510)
int evTotal = pk.EVTotal;
Nature
Natures affect stat growth:
// Set nature
pk.Nature = Nature.Adamant;
// Gen 8+ supports Stat Nature (mints)
pk.StatNature = Nature.Jolly; // Different from actual nature
// Get nature modifiers
var (plus, minus) = pk.Nature.GetNatureModification();
Moves and Abilities
Move Sets
// Set moves
pk.Move1 = (ushort)Move.FireBlast;
pk.Move2 = (ushort)Move.DragonPulse;
pk.Move3 = (ushort)Move.AirSlash;
pk.Move4 = (ushort)Move.Roost;
// Set move PP
pk.Move1_PP = pk.GetMovePP(pk.Move1, pk.Move1_PPUps);
// Set PP Ups (increases max PP)
pk.Move1_PPUps = 3; // Max PP Ups
// Relearn moves (Gen 6+)
if (pk is PK9 pk9)
{
pk9.RelearnMove1 = (ushort)Move.Ember;
pk9.RelearnMove2 = (ushort)Move.DragonBreath;
}
Abilities
// Set ability
pk.Ability = (int)Ability.Blaze;
// Set ability number (1, 2, or 4 for Hidden Ability)
pk.AbilityNumber = 4; // Hidden Ability
// Refresh ability based on ability number
pk.RefreshAbility(pk.AbilityNumber);
Original Trainer (OT)
pk.OriginalTrainerName = "Ash";
pk.OriginalTrainerGender = 0; // Male
pk.TID16 = 12345; // Trainer ID (visible)
pk.SID16 = 54321; // Secret ID (hidden)
// Or use combined ID32
pk.ID32 = 123456789;
// Get display IDs
uint displayTID = pk.DisplayTID;
uint displaySID = pk.DisplaySID;
Current Handler (Gen 6+)
For Pokémon that have been traded:
if (pk is PK9 pk9)
{
pk9.HandlingTrainerName = "Red";
pk9.HandlingTrainerGender = 0;
pk9.CurrentHandler = 1; // 0 = OT, 1 = HT
}
Friendship
// Set friendship (0-255)
pk.CurrentFriendship = 255; // Max friendship
// Friendship affects evolution and certain moves
pk.CurrentFriendship = 220; // Common evolution threshold
Met Location and Date
// Set where Pokémon was met
pk.MetLocation = 6; // Pallet Town (location varies by game)
pk.MetLevel = 5;
// Set met date
pk.MetDate = new DateTime(2024, 1, 1);
// Egg information
pk.IsEgg = false;
pk.EggLocation = 0;
pk.EggMetDate = DateTime.Now;
Version and Origin
pk.Version = (byte)GameVersion.SV; // Scarlet/Violet
pk.MetLocation = 6;
pk.Ball = (byte)Ball.Poke;
Pokérus
The beneficial virus that doubles EV gains:
// Give active Pokérus
pk.PokerusStrain = 1; // Strain (1-4)
pk.PokerusDays = 1; // Days remaining (1-4)
// Cured Pokérus (permanent EV bonus)
pk.PokerusStrain = 1;
pk.PokerusDays = 0;
// Check Pokérus status
if (pk.IsPokerusInfected)
Console.WriteLine("Has active Pokérus");
if (pk.IsPokerusCured)
Console.WriteLine("Cured Pokérus (permanent bonus)");
Shiny Pokémon
Making Pokémon Shiny
// Make shiny (random type)
pk.SetShiny();
// Check if shiny
if (pk.IsShiny)
Console.WriteLine("This Pokémon is shiny!");
// Force specific shiny type (Gen 8+)
pk.SetShinySID(Shiny.AlwaysStar); // Star shiny
pk.SetShinySID(Shiny.AlwaysSquare); // Square shiny (rare)
// Get shiny value
uint psv = pk.PSV; // Personal Shiny Value
uint tsv = pk.TSV; // Trainer Shiny Value
Ribbons and Marks
Pokémon can have various ribbons and marks:
if (pk is IRibbonSetCommon9 ribbons)
{
ribbons.RibbonChampionPaldea = true;
ribbons.RibbonMasterRank = true;
}
// Marks (Gen 8+)
if (pk is IRibbonSetMarks marks)
{
marks.RibbonMarkLunchtime = true;
marks.RibbonMarkCloudy = true;
}
// Set affixed ribbon (displays with name)
if (pk is IRibbonSetAffixed affixed)
{
affixed.AffixedRibbon = AffixedRibbon.ChampionPaldea;
}
Generation-Specific Properties
Gen 9: Tera Type
if (pk is ITeraType tera)
{
tera.TeraTypeOriginal = MoveType.Electric;
tera.TeraTypeOverride = MoveType.Flying; // Changed via Tera Shard
}
Gen 8: Dynamax Level
if (pk is PK8 pk8)
{
pk8.DynamaxLevel = 10; // Max level
pk8.CanGigantamax = true; // Can Gigantamax
}
Gen 7: Hyper Training
if (pk is IHyperTrain ht && pk.CurrentLevel == 100)
{
ht.HT_HP = true;
ht.HT_ATK = true;
ht.HT_DEF = true;
ht.HT_SPA = true;
ht.HT_SPD = true;
ht.HT_SPE = true;
}
Gen 6+: Contest Stats
if (pk is IContestStats contest)
{
contest.ContestCool = 255;
contest.ContestBeauty = 255;
contest.ContestCute = 255;
contest.ContestSmart = 255;
contest.ContestTough = 255;
contest.ContestSheen = 255;
}
Held Items
// Set held item
pk.HeldItem = (int)Item.ChoiceScarf;
// Remove held item
pk.HeldItem = 0;
Memory and Affection (Gen 6+)
if (pk is ITrainerMemories mem)
{
mem.OriginalTrainerMemory = 1;
mem.OriginalTrainerMemoryIntensity = 3;
mem.OriginalTrainerMemoryFeeling = 5;
mem.OriginalTrainerMemoryVariable = 1;
}
Validation and Finalization
Always Refresh After Editing
// After any modifications, refresh the checksum
pk.RefreshChecksum();
// Verify validity
if (!pk.Valid)
{
Console.WriteLine("Warning: Pokémon data may be invalid");
}
// Check checksum explicitly
if (!pk.ChecksumValid)
{
pk.RefreshChecksum();
}
Always call RefreshChecksum() after modifying properties. Without this, the Pokémon data will be invalid.
Batch Editing with Reflection
For advanced scenarios, you can use reflection to copy properties:
var source = new PK9 { Species = 25, CurrentLevel = 50 };
var destination = new PK9();
// Copy all properties from source to destination
source.TransferPropertiesWithReflection(destination);
Complete Editing Example
public void EditPokemon(PKM pk)
{
// Modify basic properties
pk.CurrentLevel = 100;
pk.Nature = Nature.Jolly;
pk.CurrentFriendship = 255;
// Perfect IVs
pk.IV_HP = 31;
pk.IV_ATK = 31;
pk.IV_DEF = 31;
pk.IV_SPA = 31;
pk.IV_SPD = 31;
pk.IV_SPE = 31;
// Optimal EVs
pk.EV_ATK = 252;
pk.EV_SPE = 252;
pk.EV_HP = 6;
// Change moves
pk.Move1 = (ushort)Move.CloseCombat;
pk.Move1_PP = pk.GetMovePP(pk.Move1, 3);
pk.Move1_PPUps = 3;
// Make shiny
pk.SetShiny();
// Add Pokérus
pk.PokerusStrain = 1;
pk.PokerusDays = 4;
// Gen 9 specific
if (pk is ITeraType tera)
{
tera.TeraTypeOverride = MoveType.Fighting;
}
// Always finalize
pk.RefreshChecksum();
}
Next Steps