Refactoring iencounterable->pkm

SetPINGA{S}(pk, criteria) -> pid,iv, nature, gender, ability (stats
future?)
memes aside, this is where criteria data is forced

Split N encounterstatic (has fixed PID and special flag) from
EncounterStaticPID
This commit is contained in:
Kurt 2019-02-09 11:37:20 -08:00
parent cda06bc701
commit e79f46673c
18 changed files with 588 additions and 427 deletions

View File

@ -633,21 +633,21 @@ private static void MarkG5Slots(ref EncounterArea[] Areas)
new EncounterStatic { Species = 644, Level = 70, Location = 039, Shiny = Shiny.Never, Version = GameVersion.B2, }, // Zekrom @ Dragonspiral Tower
new EncounterStatic { Species = 646, Level = 70, Location = 061, Form = 0}, // Kyurem @ Giant Chasm
//N's Pokemon
new EncounterStaticPID { Species = 509, Level = 07, Location = 15, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Timid }, // Purloin @ Route 2
new EncounterStaticPID { Species = 519, Level = 13, Location = 33, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Sassy }, // Pidove @ Pinwheel Forest
new EncounterStaticPID { Species = 532, Level = 13, Location = 33, NSparkle = true, Ability = 1, PID = 0xFF00003F, Nature = Nature.Rash }, // Timburr @ Pinwheel Forest
new EncounterStaticPID { Species = 535, Level = 13, Location = 33, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Modest }, // Tympole @ Pinwheel Forest
new EncounterStaticPID { Species = 527, Level = 55, Location = 53, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Timid }, // Woobat @ Wellspring Cave
new EncounterStaticPID { Species = 551, Level = 22, Location = 34, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Docile }, // Sandile @ Desert Resort
new EncounterStaticPID { Species = 554, Level = 22, Location = 34, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Naive }, // Darumaka @ Desert Resort
new EncounterStaticPID { Species = 555, Level = 35, Location = 34, NSparkle = true, Ability = 4, PID = 0xFF00007F, Nature = Nature.Calm }, // Darmanitan @ Desert Resort
new EncounterStaticPID { Species = 559, Level = 22, Location = 34, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Lax }, // Scraggy @ Desert Resort
new EncounterStaticPID { Species = 561, Level = 22, Location = 34, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Gentle }, // Sigilyph @ Desert Resort
new EncounterStaticPID { Species = 525, Level = 28, Location = 37, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Naive }, // Boldore @ Chargestone Cave
new EncounterStaticPID { Species = 595, Level = 28, Location = 37, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Docile }, // Joltik @ Chargestone Cave
new EncounterStaticPID { Species = 597, Level = 28, Location = 37, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Bashful }, // Ferroseed @ Chargestone Cave
new EncounterStaticPID { Species = 599, Level = 28, Location = 37, NSparkle = true, Ability = 1, PID = 0xFF000000, Nature = Nature.Rash }, // Klink @ Chargestone Cave
new EncounterStaticPID { Species = 570, Level = 25, Location = 10, NSparkle = true, Ability = 1, PID = 0xFF00001F, Nature = Nature.Hasty, Gift = true} // N's Zorua @ Driftveil City
new EncounterStaticN { Species = 509, Level = 07, Location = 15, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Timid }, // Purloin @ Route 2
new EncounterStaticN { Species = 519, Level = 13, Location = 33, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Sassy }, // Pidove @ Pinwheel Forest
new EncounterStaticN { Species = 532, Level = 13, Location = 33, NSparkle = true, Ability = 1, PID = 0xFF00003F, Nature = Nature.Rash }, // Timburr @ Pinwheel Forest
new EncounterStaticN { Species = 535, Level = 13, Location = 33, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Modest }, // Tympole @ Pinwheel Forest
new EncounterStaticN { Species = 527, Level = 55, Location = 53, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Timid }, // Woobat @ Wellspring Cave
new EncounterStaticN { Species = 551, Level = 22, Location = 34, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Docile }, // Sandile @ Desert Resort
new EncounterStaticN { Species = 554, Level = 22, Location = 34, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Naive }, // Darumaka @ Desert Resort
new EncounterStaticN { Species = 555, Level = 35, Location = 34, NSparkle = true, Ability = 4, PID = 0xFF00007F, Nature = Nature.Calm }, // Darmanitan @ Desert Resort
new EncounterStaticN { Species = 559, Level = 22, Location = 34, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Lax }, // Scraggy @ Desert Resort
new EncounterStaticN { Species = 561, Level = 22, Location = 34, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Gentle }, // Sigilyph @ Desert Resort
new EncounterStaticN { Species = 525, Level = 28, Location = 37, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Naive }, // Boldore @ Chargestone Cave
new EncounterStaticN { Species = 595, Level = 28, Location = 37, NSparkle = true, Ability = 2, PID = 0xFF01007F, Nature = Nature.Docile }, // Joltik @ Chargestone Cave
new EncounterStaticN { Species = 597, Level = 28, Location = 37, NSparkle = true, Ability = 1, PID = 0xFF00007F, Nature = Nature.Bashful }, // Ferroseed @ Chargestone Cave
new EncounterStaticN { Species = 599, Level = 28, Location = 37, NSparkle = true, Ability = 1, PID = 0xFF000000, Nature = Nature.Rash }, // Klink @ Chargestone Cave
new EncounterStaticN { Species = 570, Level = 25, Location = 10, NSparkle = true, Ability = 1, PID = 0xFF00001F, Nature = Nature.Hasty, Gift = true} // N's Zorua @ Driftveil City
};
private static readonly EncounterStatic[] Encounter_B2W2 = Encounter_DreamRadar.SelectMany(e => e.DreamRadarClone()).Concat(Encounter_B2W2_Regular).ToArray();

View File

@ -22,28 +22,27 @@ public class EncounterEgg : IEncounterable, IVersion
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
int gen = Version.GetGeneration();
var version = Version;
if (gen < 2)
{
gen = 2;
Version = GameVersion.C;
version = GameVersion.C;
}
var pk = PKMConverter.GetBlank(gen, Version);
var pk = PKMConverter.GetBlank(gen, version);
SAV.ApplyToPKM(pk);
pk.Species = Species;
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, SAV.Language, gen);
pk.CurrentLevel = Level;
pk.Version = (int)Version;
pk.Version = (int)version;
pk.Ball = 4;
int[] moves = GetCurrentEggMoves(pk);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
pk.SetRandomIVs(flawless: 3);
int[] moves = SetEncounterMoves(pk, version);
SetPINGA(pk, criteria);
if (pk.Format <= 2 && Version != GameVersion.C)
if (pk.Format <= 2 && version != GameVersion.C)
return pk;
SetMetData(pk);
@ -51,14 +50,13 @@ public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
if (pk.Format < 3)
return pk;
SetNatureGenderAbility(pk, criteria);
if (pk.GenNumber >= 4)
pk.SetEggMetData(Version, (GameVersion)SAV.Game);
pk.SetEggMetData(version, (GameVersion)SAV.Game);
if (pk.Format < 6)
return pk;
if (pk.Gen6)
if (pk.Format == 6)
pk.SetHatchMemory6();
SetAltForm(pk, SAV);
@ -84,8 +82,12 @@ private void SetAltForm(PKM pk, ITrainerInfo SAV)
}
}
private static void SetNatureGenderAbility(PKM pk, EncounterCriteria criteria)
private static void SetPINGA(PKM pk, EncounterCriteria criteria)
{
pk.SetRandomIVs(flawless: 3);
if (pk.Format <= 2)
return;
int gender = criteria.GetGender(-1, pk.PersonalInfo);
int nature = (int)criteria.GetNature(Nature.Random);
@ -112,16 +114,24 @@ private static void SetMetData(PKM pk)
pk.Met_Location = Math.Max(0, EncounterSuggestion.GetSuggestedEggMetLocation(pk));
}
private int[] GetCurrentEggMoves(PKM pk)
private int[] SetEncounterMoves(PKM pk, GameVersion version)
{
var moves = MoveEgg.GetEggMoves(pk, Species, pk.AltForm, Version);
int[] moves = GetCurrentEggMoves(pk, version);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
return moves;
}
private int[] GetCurrentEggMoves(PKM pk, GameVersion version)
{
var moves = MoveEgg.GetEggMoves(pk, Species, pk.AltForm, version);
if (moves.Length == 0)
return MoveLevelUp.GetEncounterMoves(pk, Level, Version);
return MoveLevelUp.GetEncounterMoves(pk, Level, version);
if (moves.Length >= 4 || pk.Format < 6)
return moves;
// Sprinkle in some default level up moves
var lvl = Legal.GetBaseEggMoves(pk, Species, Version, Level);
var lvl = Legal.GetBaseEggMoves(pk, Species, version, Level);
return lvl.Concat(moves).ToArray();
}
}

View File

@ -69,14 +69,11 @@ public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
pk.AltForm = GetWildAltForm(pk, Form, SAV);
SetMetData(pk, level, Location);
SetNatureGenderAbility(pk, criteria);
SetPINGA(pk, criteria);
SetEncounterMoves(pk, version, level);
SetFormatSpecificData(pk);
var moves = this is EncounterSlotMoves m ? m.Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
if (pk.Format < 6)
return pk;
@ -86,6 +83,13 @@ public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
return pk;
}
private void SetEncounterMoves(PKM pk, GameVersion version, int level)
{
var moves = this is EncounterSlotMoves m ? m.Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
}
private void SetFormatSpecificData(PKM pk)
{
if (pk is PK1 pk1)
@ -122,7 +126,7 @@ private void SetFormatSpecificData(PKM pk)
}
}
private void SetNatureGenderAbility(PKM pk, EncounterCriteria criteria)
private void SetPINGA(PKM pk, EncounterCriteria criteria)
{
int gender = criteria.GetGender(-1, pk.PersonalInfo);
int nature = (int)criteria.GetNature(Nature.Random);

View File

@ -71,80 +71,34 @@ internal virtual EncounterStatic Clone()
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
SanityCheckVersion(ref version);
int lang = (int)Legal.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int level = LevelMin;
var pk = PKMConverter.GetBlank(Generation, Version);
int nature = Nature == Nature.Random ? Util.Rand.Next(25) : (int)Nature;
var today = DateTime.Today;
SAV.ApplyToPKM(pk);
pk.EncryptionConstant = Util.Rand32();
pk.Species = Species;
int gender = Gender < 0 ? pk.PersonalInfo.RandomGender : Gender;
pk.AltForm = Form;
int lang = (int)Legal.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int level = LevelMin;
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
SanityCheckVersion(ref version);
pk.Language = lang = GetEdgeCaseLanguage(pk, lang);
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, lang, Generation);
pk.CurrentLevel = level;
pk.Version = (int)version;
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, lang, Generation);
pk.Ball = Ball;
pk.AltForm = Form;
pk.HeldItem = HeldItem;
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
if (pk.Format > 2 || Version == GameVersion.C)
{
pk.Met_Location = Location;
pk.Met_Level = level;
if (Version == GameVersion.C && pk is PK2 pk2)
pk2.Met_TimeOfDay = EncounterTime.Any.RandomValidTime();
if (pk.Format >= 4)
pk.MetDate = DateTime.Today;
}
var today = DateTime.Today;
SetMetData(pk, level, today);
if (EggEncounter)
{
pk.Met_Location = Math.Max(0, EncounterSuggestion.GetSuggestedEggMetLocation(pk));
pk.Met_Level = EncounterSuggestion.GetSuggestedEncounterEggMetLevel(pk);
SetEggMetData(pk, SAV, today);
bool traded = (int)Version == SAV.Game;
if (pk.GenNumber >= 4)
{
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk, traded);
pk.EggMetDate = today;
}
pk.Egg_Location = EggLocation;
pk.EggMetDate = today;
}
if (this is EncounterStaticPID p)
{
pk.PID = p.PID;
pk.Gender = PKX.GetGenderFromPID(Species, p.PID);
if (pk is PK5 pk5)
{
pk5.IVs = new[] {30, 30, 30, 30, 30, 30};
pk5.NPokémon = p.NSparkle;
pk5.OT_Name = Legal.GetG5OT_NSparkle(lang);
pk5.TID = 00002;
pk5.SID = 00000;
}
else
{
SetIVs(pk);
}
if (Generation >= 5)
pk.Nature = nature;
pk.RefreshAbility(Ability >> 1);
}
else
{
var pidtype = GetPIDType();
PIDGenerator.SetRandomWildPID(pk, pk.Format, nature, Ability >> 1, gender, pidtype);
SetIVs(pk);
}
SetPINGA(pk, criteria);
SetEncounterMoves(pk, version, level);
switch (pk)
{
@ -159,28 +113,73 @@ public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
break;
}
if (RibbonWishing && pk is IRibbonSetEvent4 e4)
e4.RibbonWishing = true;
if (this is EncounterStaticN n)
n.SetNPokemonData((PK5)pk, lang);
if (pk is IContestStats s)
this.CopyContestStatsTo(s);
var moves = Moves ?? MoveLevelUp.GetEncounterMoves(pk, level, version);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
if (pk.Format >= 6 && Relearn.Length > 0)
pk.RelearnMoves = Relearn;
if (Fateful)
pk.FatefulEncounter = true;
if (pk.Format < 6)
return pk;
if (RibbonWishing && pk is IRibbonSetEvent4 e4)
e4.RibbonWishing = true;
if (Relearn.Length > 0)
pk.RelearnMoves = Relearn;
SAV.ApplyHandlingTrainerInfo(pk);
pk.SetRandomEC();
return pk;
}
protected virtual void SetPINGA(PKM pk, EncounterCriteria criteria)
{
int gender = criteria.GetGender(Gender, pk.PersonalInfo);
int nature = (int)criteria.GetNature(Nature);
int ability = Ability;
var pidtype = GetPIDType();
PIDGenerator.SetRandomWildPID(pk, pk.Format, nature, ability >> 1, gender, pidtype);
SetIVs(pk);
}
private void SetEggMetData(PKM pk, ITrainerInfo tr, DateTime today)
{
pk.Met_Location = Math.Max(0, EncounterSuggestion.GetSuggestedEggMetLocation(pk));
pk.Met_Level = EncounterSuggestion.GetSuggestedEncounterEggMetLevel(pk);
if (pk.GenNumber >= 4)
{
bool traded = (int)Version == tr.Game;
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk, traded);
pk.EggMetDate = today;
}
pk.Egg_Location = EggLocation;
pk.EggMetDate = today;
}
private void SetMetData(PKM pk, int level, DateTime today)
{
if (pk.Format > 2 || Version == GameVersion.C)
{
pk.Met_Location = Location;
pk.Met_Level = level;
if (Version == GameVersion.C && pk is PK2 pk2)
pk2.Met_TimeOfDay = EncounterTime.Any.RandomValidTime();
if (pk.Format >= 4)
pk.MetDate = today;
}
}
private void SetEncounterMoves(PKM pk, GameVersion version, int level)
{
var moves = Moves?.Length > 0 ? Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
}
private void SanityCheckVersion(ref GameVersion version)
{
if (Generation != 4 || version == GameVersion.Pt)
@ -194,7 +193,7 @@ private void SanityCheckVersion(ref GameVersion version)
}
}
private void SetIVs(PKM pk)
protected void SetIVs(PKM pk)
{
if (IVs != null)
pk.SetRandomIVs(IVs, FlawlessIVCount);

View File

@ -1,9 +1,37 @@
namespace PKHeX.Core
{
internal sealed class EncounterStaticPID : EncounterStatic
internal class EncounterStaticPID : EncounterStatic
{
public uint PID { get; set; }
public bool NSparkle { get; set; }
public override Shiny Shiny { get; set; } = Shiny.FixedValue;
protected override void SetPINGA(PKM pk, EncounterCriteria criteria)
{
int gender = criteria.GetGender(PKX.GetGenderFromPID(Species, PID), pk.PersonalInfo);
int nature = (int)(PID % 25);
int ability = Ability;
pk.PID = PID;
pk.Gender = gender;
SetIVs(pk);
if (Generation >= 5)
pk.Nature = nature;
pk.RefreshAbility(ability >> 1);
}
}
internal sealed class EncounterStaticN : EncounterStaticPID
{
public bool NSparkle { get; set; }
internal void SetNPokemonData(PK5 pk5, int lang)
{
pk5.IV_HP = pk5.IV_ATK = pk5.IV_DEF = pk5.IV_SPA = pk5.IV_SPD = pk5.IV_SPE = 30;
pk5.NPokémon = NSparkle;
pk5.OT_Name = Legal.GetG5OT_NSparkle(lang);
pk5.TID = 00002;
pk5.SID = 00000;
}
}
}

View File

@ -73,46 +73,44 @@ public int TID7
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
var pk = PKMConverter.GetBlank(Generation, Version);
SAV.ApplyToPKM(pk);
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
int lang = (int)Legal.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int level = CurrentLevel > 0 ? CurrentLevel : LevelMin;
if (level == 0)
level = 25; // avoid some cases
SAV.ApplyToPKM(pk);
int species = Species;
if (EvolveOnTrade)
species++;
pk.EncryptionConstant = Util.Rand32();
pk.Species = species;
pk.CurrentLevel = level;
pk.Version = (int)version;
pk.AltForm = Form;
pk.Ball = Ball;
pk.Language = lang;
pk.TID = TID;
pk.SID = SID;
pk.OT_Name = pk.Format == 1 ? StringConverter.G1TradeOTStr : GetOT(lang) ?? SAV.OT;
pk.OT_Gender = GetOT(lang) != null ? Math.Max(0, OTGender) : SAV.Gender;
pk.SetNickname(GetNickname(lang));
pk.CurrentLevel = level;
pk.Version = (int)version;
pk.TID = TID;
pk.SID = SID;
pk.Ball = Ball;
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
SetNatureGenderAbility(pk, criteria);
if (IVs != null)
pk.SetRandomIVs(IVs, 0);
else
pk.SetRandomIVs(flawless: 3);
SetPINGA(pk, criteria);
SetMoves(pk, version, level);
var time = DateTime.Now;
if (pk.Format != 2 || version == GameVersion.C)
{
var location = Location > 0 ? Location : DefaultMetLocation[Generation - 1];
SetMetData(pk, level, location);
SetMetData(pk, level, location, time);
}
if (EggLocation != 0)
SetEggMetData(pk);
SetEggMetData(pk, time);
if (pk is PK1 pk1 && this is EncounterTradeCatchRate c)
pk1.Catch_Rate = (int)c.Catch_Rate;
@ -120,8 +118,6 @@ public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
if (pk is IContestStats s)
this.CopyContestStatsTo(s);
SetMoves(pk, version, level);
if (Fateful)
pk.FatefulEncounter = true;
@ -141,26 +137,26 @@ public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
return pk;
}
private void SetNatureGenderAbility(PKM pk, EncounterCriteria criteria)
protected virtual void SetPINGA(PKM pk, EncounterCriteria criteria)
{
int gender = criteria.GetGender(Gender, pk.PersonalInfo);
int nature = (int)criteria.GetNature(Nature);
int ability = Ability >> 1;
if (this is EncounterTradePID p)
{
pk.PID = p.PID;
pk.Nature = nature;
pk.Gender = PKX.GetGenderFromPID(Species, p.PID);
pk.RefreshAbility(ability);
}
PIDGenerator.SetRandomWildPID(pk, Generation, nature, ability, gender);
pk.Nature = nature;
pk.Gender = gender;
pk.RefreshAbility(ability);
SetIVs(pk);
}
protected void SetIVs(PKM pk)
{
if (IVs != null)
pk.SetRandomIVs(IVs, 0);
else
{
PIDGenerator.SetRandomWildPID(pk, Generation, nature, ability, gender);
pk.Nature = nature;
pk.Gender = gender;
pk.RefreshAbility(ability);
}
pk.SetRandomIVs(flawless: 3);
}
private void SetMoves(PKM pk, GameVersion version, int level)
@ -172,17 +168,17 @@ private void SetMoves(PKM pk, GameVersion version, int level)
pk.SetMaximumPPCurrent(moves);
}
private void SetEggMetData(PKM pk)
private void SetEggMetData(PKM pk, DateTime time)
{
pk.Egg_Location = EggLocation;
pk.EggMetDate = DateTime.Today;
pk.EggMetDate = time;
}
private static void SetMetData(PKM pk, int level, int location)
private static void SetMetData(PKM pk, int level, int location, DateTime time)
{
pk.Met_Level = level;
pk.Met_Location = location;
pk.MetDate = DateTime.Today;
pk.MetDate = time;
}
private void UpdateEdgeCase(PKM pkm)

View File

@ -7,5 +7,19 @@ public sealed class EncounterTradePID : EncounterTrade
{
public uint PID;
public override Shiny Shiny { get; set; } = Shiny.FixedValue;
protected override void SetPINGA(PKM pk, EncounterCriteria criteria)
{
int gender = criteria.GetGender(PKX.GetGenderFromPID(Species, PID), pk.PersonalInfo);
int nature = (int)criteria.GetNature(Nature);
int ability = Ability >> 1;
pk.PID = PID;
pk.Nature = nature;
pk.Gender = gender;
pk.RefreshAbility(ability);
SetIVs(pk);
}
}
}

View File

@ -1,4 +1,6 @@
namespace PKHeX.Core
using System;
namespace PKHeX.Core
{
/// <summary>
/// Object that can be fed to a <see cref="IEncounterable"/> converter to ensure that the resulting <see cref="PKM"/> meets rough specifications.
@ -65,7 +67,7 @@ public static EncounterCriteria GetCriteria(ShowdownSet s)
public Nature GetNature(Nature encValue)
{
if (encValue != Nature.Random)
if ((uint)encValue < 25)
return encValue;
if (Nature != Nature.Random)
return Nature;
@ -74,7 +76,7 @@ public Nature GetNature(Nature encValue)
public int GetGender(int gender, PersonalInfo pkPersonalInfo)
{
if (gender >= 0)
if ((uint)gender < 3)
return gender;
if (!pkPersonalInfo.IsDualGender)
return pkPersonalInfo.FixedGender;
@ -82,5 +84,18 @@ public int GetGender(int gender, PersonalInfo pkPersonalInfo)
return Gender;
return pkPersonalInfo.RandomGender;
}
public int GetAbility(int abilityType, PersonalInfo pkPersonalInfo)
{
if (abilityType < 3)
return abilityType;
var abils = pkPersonalInfo.Abilities;
if (abilityType == 4 && abils.Length > 2 && abils[2] == Ability) // hidden allowed
return 2;
if (abils[1] == Ability)
return 1;
return 0;
}
}
}

View File

@ -58,7 +58,7 @@ public enum PIDType
BACD_U_A,
/// <summary>
/// Event Reversed Order PID restricted to 16bit Origin Seed, shiny
/// Event Reversed Order PID restricted to 8bit Origin Seed, shiny
/// </summary>
/// <remarks><see cref="RNG.LCRNG"/></remarks>
BACD_R_S,

View File

@ -14,7 +14,7 @@ public override void Verify(LegalityAnalysis data)
var pkm = data.pkm;
var EncounterMatch = data.EncounterMatch;
bool checksRequired = EncounterMatch is EncounterStaticPID s && s.NSparkle;
bool checksRequired = EncounterMatch is EncounterStaticN s && s.NSparkle;
if (pkm is PK5 pk5)
{
bool has = pk5.NPokémon;

View File

@ -50,7 +50,7 @@ private void VerifyShiny(LegalityAnalysis data)
break;
if (s.Gift || s.Roaming || s.Ability != 4)
break;
if (s is EncounterStaticPID p && p.NSparkle)
if (s is EncounterStaticN p && p.NSparkle)
break;
VerifyG5PID_IDCorrelation(data);
break;

View File

@ -22,7 +22,7 @@ public override void Verify(LegalityAnalysis data)
{
case EncounterTrade _:
case MysteryGift g when !g.IsEgg:
case EncounterStaticPID s when s.NSparkle:
case EncounterStaticN s when s.NSparkle:
return; // already verified
}

View File

@ -167,13 +167,14 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
if (!IsPokémon)
return null;
DateTime dt = DateTime.Now;
var dt = DateTime.Now;
if (Day == 0)
{
Day = (byte)dt.Day;
Month = (byte)dt.Month;
Year = (byte)dt.Year;
}
int currentLevel = Level > 0 ? Level : Util.Rand.Next(100) + 1;
var pi = PersonalTable.B2W2.GetFormeEntry(Species, Form);
PK5 pk = new PK5
@ -201,7 +202,7 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
CNT_Tough = CNT_Tough,
CNT_Sheen = CNT_Sheen,
EXP = Experience.GetEXP(Level, Species, 0),
EXP = Experience.GetEXP(currentLevel, Species, 0),
// Ribbons
RibbonCountry = RibbonCountry,
@ -230,12 +231,13 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
pk.Moves = MoveLevelUp.GetEncounterMoves(Species, Form, Level, (GameVersion)pk.Version);
pk.SetMaximumPPCurrent();
if (IsEgg) // User's
{
pk.TID = SAV.TID;
pk.SID = SAV.SID;
pk.OT_Name = SAV.OT;
pk.OT_Gender = 1; // Red PKHeX OT
pk.OT_Gender = SAV.Gender;
}
else // Hardcoded
{
@ -244,74 +246,92 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
pk.OT_Name = OT_Name;
pk.OT_Gender = (OTGender == 3 ? SAV.Gender : OTGender) & 1; // some events have variable gender based on receiving SaveFile
}
pk.IsNicknamed = IsNicknamed;
pk.Nickname = IsNicknamed ? Nickname : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
// More 'complex' logic to determine final values
SetPINGA(pk, criteria);
// Dumb way to generate random IVs.
int[] finalIVs = new int[6];
for (int i = 0; i < IVs.Length; i++)
finalIVs[i] = IVs[i] == 0xFF ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
pk.IVs = finalIVs;
if (IsEgg)
SetEggMetDetails(pk);
int av = 0;
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.RefreshChecksum();
return pk;
}
private void SetEggMetDetails(PK5 pk)
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}
private void SetPINGA(PKM pk, EncounterCriteria criteria)
{
var pi = PersonalTable.B2W2.GetFormeEntry(Species, Form);
pk.Nature = (int)criteria.GetNature((Nature)Nature);
pk.Gender = criteria.GetGender(Gender, pi);
var av = GetAbilityIndex(criteria, pi);
SetPID(pk, av);
pk.RefreshAbility(av);
SetIVs(pk);
}
private int GetAbilityIndex(EncounterCriteria criteria, PersonalInfo pi)
{
switch (AbilityType)
{
case 00: // 0 - 0
case 01: // 1 - 1
case 02: // 2 - H
av = AbilityType;
break;
return AbilityType;
case 03: // 0/1
case 04: // 0/1/H
av = Util.Rand.Next(AbilityType - 1);
break;
return criteria.GetAbility(AbilityType, pi); // 3 or 2
default:
throw new ArgumentException(nameof(AbilityType));
}
pk.HiddenAbility = av == 2;
pk.Ability = pi.Abilities[av];
}
private void SetPID(PKM pk, int av)
{
if (PID != 0)
{
pk.PID = PID;
return;
}
pk.PID = Util.Rand32();
// Force Gender
do { pk.PID = (pk.PID & 0xFFFFFF00) | (uint)Util.Rand.Next(0x100); }
while (!pk.IsGenderValid());
if (PIDType == 2) // Always
{
uint gb = pk.PID & 0xFF;
pk.PID = PIDGenerator.GetMG5ShinyPID(gb, (uint)av, pk.TID, pk.SID);
}
else if (PIDType != 1) // Force Not Shiny
{
if (pk.IsShiny)
pk.PID ^= 0x10000000;
}
if (av == 1)
pk.PID |= 0x10000;
else
{
pk.PID = Util.Rand32();
pk.PID &= 0xFFFEFFFF;
}
// Force Gender
do { pk.PID = (pk.PID & 0xFFFFFF00) | (uint)Util.Rand.Next(0x100); }
while (!pk.IsGenderValid());
// Force Ability
if (av == 1)
pk.PID |= 0x10000;
else
pk.PID &= 0xFFFEFFFF;
if (PIDType == 2) // Force Shiny
{
uint gb = pk.PID & 0xFF;
pk.PID = PIDGenerator.GetMG5ShinyPID(gb, (uint)av, pk.TID, pk.SID);
}
else if (PIDType != 1) // Force Not Shiny
{
if (pk.IsShiny)
pk.PID ^= 0x10000000;
}
}
if (IsEgg)
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.RefreshChecksum();
return pk;
private void SetIVs(PKM pk)
{
int[] finalIVs = new int[6];
for (int i = 0; i < IVs.Length; i++)
finalIVs[i] = IVs[i] == 0xFF ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
pk.IVs = finalIVs;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)

View File

@ -124,7 +124,8 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
if (!IsPokémon)
return null;
PK4 pk4 = new PK4((byte[])PK.Data.Clone()) {Sanity = 0};
// template is already filled out, only minor mutations required
PK4 pk4 = new PK4((byte[])PK.Data.Clone()) { Sanity = 0 };
if (!IsHatched && Detail == 0)
{
pk4.OT_Name = SAV.OT;
@ -134,31 +135,67 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
pk4.Language = SAV.Language;
}
uint seed = Util.Rand32();
if (IsManaphyEgg)
SetDefaultManaphyEggDetails(pk4);
SetPINGA(pk4, criteria);
SetMetData(pk4, SAV);
var pi = pk4.PersonalInfo;
pk4.CurrentFriendship = pk4.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk4.RefreshChecksum();
return pk4;
}
private void SetMetData(PK4 pk4, ITrainerInfo trainer)
{
if (!EggEncounter)
{
// Since none of this data is populated, fill in default info.
pk4.Species = 490;
pk4.Gender = 2;
// Level 1 Moves
pk4.Move1 = 294;
pk4.Move2 = 145;
pk4.Move3 = 346;
pk4.Ability = pk4.PersonalInfo.Abilities[0];
pk4.FatefulEncounter = true;
pk4.Ball = 4;
pk4.Version = 10; // Diamond
pk4.Language = (int)LanguageID.English; // English
pk4.Nickname = "MANAPHY";
pk4.Egg_Location = 1; // Ranger (will be +3000 later)
pk4.Move1_PP = pk4.GetMovePP(pk4.Move1, 0);
pk4.Move2_PP = pk4.GetMovePP(pk4.Move2, 0);
pk4.Move3_PP = pk4.GetMovePP(pk4.Move3, 0);
seed = GeneratePID(seed, pk4);
pk4.Met_Location = pk4.Egg_Location + 3000;
pk4.Egg_Location = 0;
pk4.MetDate = DateTime.Now;
pk4.IsEgg = false;
}
else
{
pk4.Egg_Location += 3000;
if (trainer.Generation == 4)
SetUnhatchedEggDetails(pk4);
else
SetHatchedEggDetails(pk4);
}
}
private static void SetDefaultManaphyEggDetails(PK4 pk4)
{
// Since none of this data is populated, fill in default info.
pk4.Species = 490;
pk4.Gender = 2;
// Level 1 Moves
pk4.Move1 = 294;
pk4.Move2 = 145;
pk4.Move3 = 346;
pk4.Ability = pk4.PersonalInfo.Abilities[0];
pk4.FatefulEncounter = true;
pk4.Ball = 4;
pk4.Version = 10; // Diamond
pk4.Language = (int)LanguageID.English; // English
pk4.Nickname = "MANAPHY";
pk4.Egg_Location = 1; // Ranger (will be +3000 later)
pk4.Move1_PP = pk4.GetMovePP(pk4.Move1, 0);
pk4.Move2_PP = pk4.GetMovePP(pk4.Move2, 0);
pk4.Move3_PP = pk4.GetMovePP(pk4.Move3, 0);
}
private void SetPINGA(PK4 pk4, EncounterCriteria criteria)
{
// Ability is forced already, can't force anything
// todo: loop force the Nature/Gender
// Generate IV
if (pk4.PID == 1) // Create Nonshiny
uint seed = Util.Rand32();
if (pk4.PID == 1 || IsManaphyEgg) // Create Nonshiny
seed = GeneratePID(seed, pk4);
if (!IsManaphyEgg)
@ -171,41 +208,21 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
uint iv2 = (PKX.LCRNG(ref seed) >> 16) & 0x7FFF;
pk4.IV32 = iv1 | iv2 << 15;
}
}
// Generate Met Info
if (!IsEgg && !IsManaphyEgg)
{
pk4.Met_Location = pk4.Egg_Location + 3000;
pk4.Egg_Location = 0;
pk4.MetDate = DateTime.Now;
pk4.IsEgg = false;
}
else
{
pk4.Egg_Location += 3000;
if (SAV.Generation == 4)
{
pk4.IsEgg = true;
pk4.IsNicknamed = false;
pk4.Nickname = PKX.GetSpeciesNameGeneration(0, pk4.Language, Format);
pk4.MetDate = DateTime.Now;
}
else
{
pk4.IsEgg = false;
// Met Location is modified when transferred to pk5; don't worry about it.
pk4.EggMetDate = DateTime.Now;
}
while (pk4.IsShiny)
pk4.PID = RNG.ARNG.Next(pk4.PID);
}
var pi = pk4.PersonalInfo;
pk4.CurrentFriendship = pk4.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
if (pk4.Species == 201) // Never will be true; Unown was never distributed.
pk4.AltForm = PKX.GetUnownForm(pk4.PID);
private static void SetHatchedEggDetails(PK4 pk4)
{
pk4.IsEgg = false;
// Met Location is modified when transferred to pk5; don't worry about it.
pk4.EggMetDate = DateTime.Now;
}
pk4.RefreshChecksum();
return pk4;
private void SetUnhatchedEggDetails(PK4 pk4)
{
pk4.IsEgg = true;
pk4.IsNicknamed = false;
pk4.Nickname = PKX.GetSpeciesNameGeneration(0, pk4.Language, Format);
pk4.MetDate = DateTime.Now;
}
private static uint GeneratePID(uint seed, PK4 pk4)

View File

@ -319,8 +319,9 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
int currentLevel = Level > 0 ? Level : Util.Rand.Next(100) + 1;
int metLevel = MetLevel > 0 ? MetLevel : currentLevel;
var pi = PersonalTable.USUM.GetFormeEntry(Species, Form);
var pi = PersonalTable.GG.GetFormeEntry(Species, Form);
var OT = GetOT(SAV.Language);
var pk = new PB7
{
Species = Species,
@ -328,8 +329,6 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
TID = TID,
SID = SID,
Met_Level = metLevel,
Nature = Nature != -1 ? Nature : Util.Rand.Next(25),
Gender = Gender != 3 ? Gender : pi.RandomGender,
AltForm = Form,
EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(),
Version = OriginGame != 0 ? OriginGame : SAV.Game,
@ -338,9 +337,14 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
Country = SAV.Country,
Region = SAV.SubRegion,
ConsoleRegion = SAV.ConsoleRegion,
Move1 = Move1, Move2 = Move2, Move3 = Move3, Move4 = Move4,
RelearnMove1 = RelearnMove1, RelearnMove2 = RelearnMove2,
RelearnMove3 = RelearnMove3, RelearnMove4 = RelearnMove4,
Move1 = Move1,
Move2 = Move2,
Move3 = Move3,
Move4 = Move4,
RelearnMove1 = RelearnMove1,
RelearnMove2 = RelearnMove2,
RelearnMove3 = RelearnMove3,
RelearnMove4 = RelearnMove4,
Met_Location = MetLocation,
Egg_Location = EggLocation,
AV_HP = AV_HP,
@ -361,6 +365,7 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
OT_Friendship = pi.BaseFriendship,
FatefulEncounter = true,
};
pk.SetMaximumPPCurrent();
if ((SAV.Generation > Format && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version))
{
@ -369,8 +374,6 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
while (!CanBeReceivedByVersion(pk.Version));
}
pk.SetMaximumPPCurrent();
if (OTGender == 3)
{
pk.TID = SAV.TID;
@ -378,43 +381,60 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
}
pk.MetDate = Date ?? DateTime.Now;
pk.IsNicknamed = GetIsNicknamed(pk.Language);
pk.Nickname = pk.IsNicknamed ? GetNickname(pk.Language) : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
int[] finalIVs = new int[6];
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
if (ivflag == 0) // Random IVs
{
for (int i = 0; i < 6; i++)
finalIVs[i] = IVs[i] > 31 ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
}
else // 1/2/3 perfect IVs
{
int IVCount = ivflag - 0xFB;
do { finalIVs[Util.Rand.Next(6)] = 31; }
while (finalIVs.Count(iv => iv == 31) < IVCount);
for (int i = 0; i < 6; i++)
finalIVs[i] = finalIVs[i] == 31 ? pk.MaxIV : Util.Rand.Next(pk.MaxIV + 1);
}
pk.IVs = finalIVs;
SetPINGA(pk, criteria);
int av = 0;
if (IsEgg)
SetEggMetData(pk);
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.HeightScalar = Util.Rand.Next(0x100);
pk.WeightScalar = Util.Rand.Next(0x100);
pk.ResetCalculatedValues(); // cp & dimensions
pk.RefreshChecksum();
return pk;
}
private void SetEggMetData(PKM pk)
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}
private void SetPINGA(PKM pk, EncounterCriteria criteria)
{
var pi = PersonalTable.GG.GetFormeEntry(Species, Form);
pk.Nature = (int)criteria.GetNature((Nature)Nature);
pk.Gender = criteria.GetGender(Gender, pi);
var av = GetAbilityIndex(criteria, pi);
pk.RefreshAbility(av);
SetPID(pk);
SetIVs(pk);
}
private int GetAbilityIndex(EncounterCriteria criteria, PersonalInfo pi)
{
switch (AbilityType)
{
case 00: // 0 - 0
case 01: // 1 - 1
case 02: // 2 - H
av = AbilityType;
break;
return AbilityType;
case 03: // 0/1
case 04: // 0/1/H
av = Util.Rand.Next(AbilityType - 1);
break;
return criteria.GetAbility(AbilityType, pi); // 3 or 2
default:
throw new ArgumentException(nameof(AbilityType));
}
pk.Ability = pi.Abilities[av];
pk.AbilityNumber = 1 << av;
}
private void SetPID(PKM pk)
{
switch (PIDType)
{
case Shiny.FixedValue: // Specified
@ -432,22 +452,26 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
if (pk.IsShiny) pk.PID ^= 0x10000000;
break;
}
}
if (IsEgg)
private void SetIVs(PKM pk)
{
int[] finalIVs = new int[6];
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
if (ivflag == 0) // Random IVs
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
for (int i = 0; i < 6; i++)
finalIVs[i] = IVs[i] > 31 ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
}
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.HeightScalar = Util.Rand.Next(0x100);
pk.WeightScalar = Util.Rand.Next(0x100);
pk.ResetCalculatedValues(); // cp & dimensions
pk.RefreshChecksum();
return pk;
else // 1/2/3 perfect IVs
{
int IVCount = ivflag - 0xFB;
do { finalIVs[Util.Rand.Next(6)] = 31; }
while (finalIVs.Count(iv => iv == 31) < IVCount);
for (int i = 0; i < 6; i++)
finalIVs[i] = finalIVs[i] == 31 ? pk.MaxIV : Util.Rand.Next(pk.MaxIV + 1);
}
pk.IVs = finalIVs;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)

View File

@ -90,77 +90,72 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
RibbonChampionNational = RibbonChampionNational,
FatefulEncounter = Fateful,
Version = GetVersion(SAV),
};
var pi = pk.PersonalInfo;
SetMoves(pk);
if (Version == 0)
{
bool gen3 = SAV.Game <= 15 && GameVersion.Gen3.Contains((GameVersion)SAV.Game);
pk.Version = gen3 ? SAV.Game : (int)GameVersion.R;
}
else
{
pk.Version = (int)GetRandomVersion(Version);
}
int lang = (int)GetSafeLanguage((LanguageID)SAV.Language, (LanguageID)Language);
bool hatchedEgg = IsEgg && SAV.Generation != 3;
if (hatchedEgg) // ugly workaround for character table interactions
if (hatchedEgg)
{
pk.Language = (int)LanguageID.English;
pk.OT_Name = "PKHeX";
pk.OT_Gender = SAV.Gender;
pk.TID = SAV.TID;
pk.SID = SAV.SID;
pk.OT_Friendship = pi.BaseFriendship;
pk.Met_Location = pk.FRLG ? 146 /* Four Island */ : 32; // Route 117
pk.FatefulEncounter &= pk.FRLG; // clear flag for RSE
pk.Met_Level = 0; // hatched
SetForceHatchDetails(pk, SAV);
}
else
{
if (IsEgg)
{
pk.IsEgg = true;
pk.IsNicknamed = true;
pk.Language = (int)LanguageID.Japanese; // JPN
if (SID >= 0)
pk.SID = SID;
if (TID >= 0)
pk.SID = TID;
}
else
{
pk.Language = lang;
}
pk.OT_Name = OT_Name ?? SAV.OT;
if (string.IsNullOrWhiteSpace(pk.OT_Name))
{
// Try again (only happens for eggs)
pk.IsEgg = false;
pk.Language = (int)LanguageID.English;
pk.OT_Name = SAV.OT;
pk.Language = (int)LanguageID.Japanese; // as egg is Japanese until hatched
pk.IsEgg = true;
}
pk.OT_Gender = OT_Gender != 3 ? OT_Gender & 1 : SAV.Gender;
pk.TID = TID;
pk.SID = SID;
pk.OT_Friendship = IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.Language = (int)GetSafeLanguage((LanguageID)SAV.Language, (LanguageID)Language);
pk.OT_Name = OT_Name ?? SAV.OT;
if (IsEgg)
pk.IsEgg = true; // lang should be set to japanese by IsEgg setter
}
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, pk.Language, 3); // will be set to Egg nickname if appropriate by PK3 setter
var pi = pk.PersonalInfo;
pk.OT_Friendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
// Generate PIDIV
SetPIDValues(pk);
SetPINGA(pk, criteria);
pk.HeldItem = 0; // clear, only random for Jirachis(?), no loss
if (Version == GameVersion.XD)
pk.FatefulEncounter = true; // pk3 is already converted from xk3
SetMoves(pk);
pk.RefreshChecksum();
return pk;
}
private static void SetForceHatchDetails(PK3 pk, ITrainerInfo SAV)
{
// ugly workaround for character table interactions
pk.Language = (int)LanguageID.English;
pk.OT_Name = "PKHeX";
pk.OT_Gender = SAV.Gender;
pk.TID = SAV.TID;
pk.SID = SAV.SID;
pk.Met_Location = pk.FRLG ? 146 /* Four Island */ : 32; // Route 117
pk.FatefulEncounter &= pk.FRLG; // clear flag for RSE
pk.Met_Level = 0; // hatched
}
private int GetVersion(ITrainerInfo SAV)
{
int version;
if (Version == 0)
{
bool gen3 = SAV.Game <= 15 && GameVersion.Gen3.Contains((GameVersion)SAV.Game);
version = gen3 ? SAV.Game : (int)GameVersion.R;
}
else
{
version = (int)GetRandomVersion(Version);
}
return version;
}
private void SetMoves(PK3 pk)
{
if (Moves.Length == 0) // not completely defined
@ -176,24 +171,24 @@ private void SetMoves(PK3 pk)
pk.SetMaximumPPCurrent(Moves);
}
private void SetPIDValues(PK3 pk)
private void SetPINGA(PK3 pk, EncounterCriteria criteria)
{
var seed = Util.Rand32();
SetPIDValues(pk, seed);
seed = GetSaneSeed(seed);
PIDGenerator.SetValuesFromSeed(pk, Method, seed);
}
private void SetPIDValues(PK3 pk, uint seed)
private uint GetSaneSeed(uint seed)
{
switch (Method)
{
case PIDType.BACD_R:
seed &= 0xFFFF;
break;
return seed & 0x0000FFFF;
case PIDType.BACD_R_S:
seed &= 0xFF;
break;
return seed & 0x000000FF;
default:
return seed; // unmodified
}
PIDGenerator.SetValuesFromSeed(pk, Method, seed);
}
private static LanguageID GetSafeLanguage(LanguageID hatchLang, LanguageID supplied)

View File

@ -298,8 +298,6 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
TID = TID,
SID = SID,
Met_Level = currentLevel,
Nature = Nature != -1 ? Nature : Util.Rand.Next(25),
Gender = Gender != 3 ? Gender : pi.RandomGender,
AltForm = Form,
EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(),
Version = OriginGame != 0 ? OriginGame : SAV.Game,
@ -389,39 +387,53 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
pk.IsNicknamed = IsNicknamed;
pk.Nickname = IsNicknamed ? Nickname : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
int[] finalIVs = new int[6];
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
if (ivflag == 0) // Random IVs
{
for (int i = 0; i < 6; i++)
finalIVs[i] = IVs[i] > pk.MaxIV ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
}
else // 1/2/3 perfect IVs
{
int IVCount = ivflag - 0xFB;
do { finalIVs[Util.Rand.Next(6)] = 31; }
while (finalIVs.Count(iv => iv == 31) < IVCount);
for (int i = 0; i < 6; i++)
finalIVs[i] = finalIVs[i] == 31 ? pk.MaxIV : Util.Rand.Next(pk.MaxIV + 1);
}
pk.IVs = finalIVs;
SetPINGA(pk, criteria);
int av = 0;
if (IsEgg)
SetEggMetData(pk);
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.RefreshChecksum();
return pk;
}
private void SetEggMetData(PKM pk)
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}
private void SetPINGA(PKM pk, EncounterCriteria criteria)
{
var pi = PersonalTable.AO.GetFormeEntry(Species, Form);
pk.Nature = (int)criteria.GetNature((Nature)Nature);
pk.Gender = criteria.GetGender(Gender, pi);
var av = GetAbilityIndex(criteria, pi);
pk.RefreshAbility(av);
SetPID(pk);
SetIVs(pk);
}
private int GetAbilityIndex(EncounterCriteria criteria, PersonalInfo pi)
{
switch (AbilityType)
{
case 00: // 0 - 0
case 01: // 1 - 1
case 02: // 2 - H
av = AbilityType;
break;
return AbilityType;
case 03: // 0/1
case 04: // 0/1/H
av = Util.Rand.Next(AbilityType - 1);
break;
return criteria.GetAbility(AbilityType, pi); // 3 or 2
default:
throw new ArgumentException(nameof(AbilityType));
}
pk.Ability = pi.Abilities[av];
pk.AbilityNumber = 1 << av;
}
private void SetPID(PKM pk)
{
switch (PIDType)
{
case Shiny.FixedValue: // Specified
@ -439,18 +451,26 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
if (pk.IsShiny) pk.PID ^= 0x10000000;
break;
}
}
if (IsEgg)
private void SetIVs(PKM pk)
{
int[] finalIVs = new int[6];
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
if (ivflag == 0) // Random IVs
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
for (int i = 0; i < 6; i++)
finalIVs[i] = IVs[i] > 31 ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
}
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.RefreshChecksum();
return pk;
else // 1/2/3 perfect IVs
{
int IVCount = ivflag - 0xFB;
do { finalIVs[Util.Rand.Next(6)] = 31; }
while (finalIVs.Count(iv => iv == 31) < IVCount);
for (int i = 0; i < 6; i++)
finalIVs[i] = finalIVs[i] == 31 ? pk.MaxIV : Util.Rand.Next(pk.MaxIV + 1);
}
pk.IVs = finalIVs;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)

View File

@ -341,8 +341,6 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
TID = TID,
SID = SID,
Met_Level = metLevel,
Nature = Nature != -1 ? Nature : Util.Rand.Next(25),
Gender = Gender != 3 ? Gender : pi.RandomGender,
AltForm = Form,
EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(),
Version = OriginGame != 0 ? OriginGame : SAV.Game,
@ -399,6 +397,7 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
EVs = EVs,
};
pk.SetMaximumPPCurrent();
if ((SAV.Generation > Format && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version))
{
@ -407,8 +406,6 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
while (!CanBeReceivedByVersion(pk.Version));
}
pk.SetMaximumPPCurrent();
if (OTGender == 3)
{
pk.TID = SAV.TID;
@ -420,39 +417,53 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
pk.IsNicknamed = IsNicknamed;
pk.Nickname = IsNicknamed ? Nickname : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
int[] finalIVs = new int[6];
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
if (ivflag == 0) // Random IVs
{
for (int i = 0; i < 6; i++)
finalIVs[i] = IVs[i] > 31 ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
}
else // 1/2/3 perfect IVs
{
int IVCount = ivflag - 0xFB;
do { finalIVs[Util.Rand.Next(6)] = 31; }
while (finalIVs.Count(iv => iv == 31) < IVCount);
for (int i = 0; i < 6; i++)
finalIVs[i] = finalIVs[i] == 31 ? pk.MaxIV : Util.Rand.Next(pk.MaxIV + 1);
}
pk.IVs = finalIVs;
SetPINGA(pk, criteria);
int av = 0;
if (IsEgg)
SetEggMetData(pk);
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.RefreshChecksum();
return pk;
}
private void SetEggMetData(PKM pk)
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}
private void SetPINGA(PKM pk, EncounterCriteria criteria)
{
var pi = PersonalTable.USUM.GetFormeEntry(Species, Form);
pk.Nature = (int)criteria.GetNature((Nature)Nature);
pk.Gender = criteria.GetGender(Gender, pi);
var av = GetAbilityIndex(criteria, pi);
pk.RefreshAbility(av);
SetPID(pk);
SetIVs(pk);
}
private int GetAbilityIndex(EncounterCriteria criteria, PersonalInfo pi)
{
switch (AbilityType)
{
case 00: // 0 - 0
case 01: // 1 - 1
case 02: // 2 - H
av = AbilityType;
break;
return AbilityType;
case 03: // 0/1
case 04: // 0/1/H
av = Util.Rand.Next(AbilityType - 1);
break;
return criteria.GetAbility(AbilityType, pi); // 3 or 2
default:
throw new ArgumentException(nameof(AbilityType));
}
pk.Ability = pi.Abilities[av];
pk.AbilityNumber = 1 << av;
}
private void SetPID(PKM pk)
{
switch (PIDType)
{
case Shiny.FixedValue: // Specified
@ -470,18 +481,26 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
if (pk.IsShiny) pk.PID ^= 0x10000000;
break;
}
}
if (IsEgg)
private void SetIVs(PKM pk)
{
int[] finalIVs = new int[6];
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
if (ivflag == 0) // Random IVs
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
for (int i = 0; i < 6; i++)
finalIVs[i] = IVs[i] > 31 ? Util.Rand.Next(pk.MaxIV + 1) : IVs[i];
}
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
pk.RefreshChecksum();
return pk;
else // 1/2/3 perfect IVs
{
int IVCount = ivflag - 0xFB;
do { finalIVs[Util.Rand.Next(6)] = 31; }
while (finalIVs.Count(iv => iv == 31) < IVCount);
for (int i = 0; i < 6; i++)
finalIVs[i] = finalIVs[i] == 31 ? pk.MaxIV : Util.Rand.Next(pk.MaxIV + 1);
}
pk.IVs = finalIVs;
}
public bool IsAshGreninjaWC7(PKM pkm)