Update iencounterable api with new criteria arg

rearrange some logic for clearer function (extract some methods)
This commit is contained in:
Kurt 2018-12-29 22:24:34 -08:00
parent c2422d6927
commit 78ff441e8b
25 changed files with 316 additions and 239 deletions

View file

@ -17,7 +17,9 @@ namespace PKHeX.Core
public GameVersion Version { get; set; }
public PKM ConvertToPKM(ITrainerInfo SAV)
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
int gen = Version.GetGeneration();
if (gen < 2)
@ -26,12 +28,14 @@ namespace PKHeX.Core
Version = GameVersion.C;
}
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.Ball = 4;
int[] moves = GetCurrentEggMoves(pk);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
@ -42,16 +46,48 @@ namespace PKHeX.Core
if (pk.Format <= 2 && Version != GameVersion.C)
return pk;
pk.Met_Level = EncounterSuggestion.GetSuggestedEncounterEggMetLevel(pk);
pk.Met_Location = Math.Max(0, EncounterSuggestion.GetSuggestedEggMetLocation(pk));
SetMetData(pk);
if (pk.Format < 3)
return pk;
pk.Ball = 4;
SetNatureGenderAbility(pk, criteria);
int gender = pk.PersonalInfo.RandomGender;
int nature = Util.Rand.Next(25);
if (pk.GenNumber >= 4)
pk.SetEggMetData(Version, (GameVersion)SAV.Game);
if (pk.Format < 6)
return pk;
if (pk.Gen6)
pk.SetHatchMemory6();
SetAltForm(pk, SAV);
pk.SetRandomEC();
pk.RelearnMoves = moves;
return pk;
}
private void SetAltForm(PKM pk, ITrainerInfo SAV)
{
switch (Species)
{
case 774: // Minior
pk.AltForm = Util.Rand.Next(7, 14);
break;
case 664: // Scatterbug
case 665:
case 666:
pk.AltForm = Legal.GetVivillonPattern(SAV.Country, SAV.SubRegion);
break;
}
}
private static void SetNatureGenderAbility(PKM pk, EncounterCriteria criteria)
{
int gender = criteria.GetGender(-1, pk.PersonalInfo);
int nature = (int)criteria.GetNature(Nature.Random);
if (pk.Format <= 5)
{
@ -68,34 +104,12 @@ namespace PKHeX.Core
pk.Gender = gender;
pk.RefreshAbility(Util.Rand.Next(2));
}
}
bool traded = (int)Version == SAV.Game;
var today = pk.MetDate = DateTime.Today;
if (pk.GenNumber >= 4)
{
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk, traded);
pk.EggMetDate = today;
}
if (pk.Format < 6)
return pk;
if (pk.Gen6)
pk.SetHatchMemory6();
switch (Species)
{
case 774: // Minior
pk.AltForm = Util.Rand.Next(7, 14);
break;
case 664: // Scatterbug
pk.AltForm = Legal.GetVivillonPattern(SAV.Country, SAV.SubRegion);
break;
}
pk.SetRandomEC();
pk.RelearnMoves = moves;
return pk;
private static void SetMetData(PKM pk)
{
pk.Met_Level = EncounterSuggestion.GetSuggestedEncounterEggMetLevel(pk);
pk.Met_Location = Math.Max(0, EncounterSuggestion.GetSuggestedEggMetLocation(pk));
}
private int[] GetCurrentEggMoves(PKM pk)
@ -112,7 +126,7 @@ namespace PKHeX.Core
}
}
public class EncounterEggSplit : EncounterEgg
public sealed class EncounterEggSplit : EncounterEgg
{
public int OtherSpecies;
}

View file

@ -5,7 +5,7 @@ namespace PKHeX.Core
/// <summary>
/// Invalid Encounter Data
/// </summary>
public class EncounterInvalid : IEncounterable
public sealed class EncounterInvalid : IEncounterable
{
public int Species { get; }
public int LevelMin { get; }
@ -22,6 +22,7 @@ namespace PKHeX.Core
EggEncounter = pkm.WasEgg;
}
public PKM ConvertToPKM(ITrainerInfo SAV) => throw new ArgumentException($"Cannot convert an {nameof(EncounterInvalid)} to PKM.");
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria) => throw new ArgumentException($"Cannot convert an {nameof(EncounterInvalid)} to PKM.");
}
}

View file

@ -5,7 +5,7 @@ namespace PKHeX.Core
/// <summary>
/// Pokémon Link Encounter Data
/// </summary>
public class EncounterLink : IEncounterable, IRibbonSetEvent4, IMoveset, ILocation, IVersion
public sealed class EncounterLink : IEncounterable, IRibbonSetEvent4, IMoveset, ILocation, IVersion
{
public int Species { get; set; }
public int Level { get; set; }
@ -37,7 +37,9 @@ namespace PKHeX.Core
public bool RibbonChampionWorld { get; set; }
public bool RibbonSouvenir { get; set; }
public PKM ConvertToPKM(ITrainerInfo SAV)
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
const int gen = 6;
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
@ -52,21 +54,21 @@ namespace PKHeX.Core
PID = Util.Rand32(),
Nickname = PKX.GetSpeciesNameGeneration(Species, lang, gen),
Ball = Ball,
Met_Level = Level,
Met_Location = Location,
MetDate = DateTime.Today
};
SAV.ApplyToPKM(pk);
SetMetData(pk);
SetNatureGender(pk, criteria);
pk.RefreshAbility(Ability >> 1);
pk.SetRandomIVs(flawless: 3);
pk.Version = (int)version;
pk.Gender = pk.PersonalInfo.RandomGender;
pk.Language = lang;
pk.Moves = Moves;
pk.SetMaximumPPCurrent(Moves);
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
pk.SetRandomIVs(flawless: 3);
pk.RefreshAbility(Ability >> 1);
if (RelearnMoves.Length > 0)
pk.RelearnMoves = RelearnMoves;
if (RibbonClassic)
@ -78,5 +80,18 @@ namespace PKHeX.Core
return pk;
}
private static void SetNatureGender(PKM pk, EncounterCriteria criteria)
{
pk.Nature = (int)criteria.GetNature(Nature.Random);
pk.Gender = criteria.GetGender(-1, pk.PersonalInfo);
}
private void SetMetData(PKM pk)
{
pk.MetDate = DateTime.Today;
pk.Met_Level = Level;
pk.Met_Location = Location;
}
}
}

View file

@ -5,7 +5,7 @@ namespace PKHeX.Core
/// <summary>
/// Rejected Encounter Data containing a reason why the encounter was rejected (not compatible).
/// </summary>
public class EncounterRejected : IEncounterable
public sealed class EncounterRejected : IEncounterable
{
public readonly IEncounterable Encounter;
public readonly CheckResult Check;
@ -23,6 +23,7 @@ namespace PKHeX.Core
Check = check;
}
public PKM ConvertToPKM(ITrainerInfo SAV) => throw new ArgumentException($"Cannot convert an {nameof(EncounterRejected)} to PKM.");
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria) => throw new ArgumentException($"Cannot convert an {nameof(EncounterRejected)} to PKM.");
}
}

View file

@ -2,23 +2,6 @@
namespace PKHeX.Core
{
public class EncounterSlotPermissions
{
public int StaticIndex { get; set; } = -1;
public int MagnetPullIndex { get; set; } = -1;
public int StaticCount { get; set; }
public int MagnetPullCount { get; set; }
public bool AllowDexNav { get; set; }
public bool Pressure { get; set; }
public bool DexNav { get; set; }
public bool WhiteFlute { get; set; }
public bool BlackFlute { get; set; }
public bool IsNormalLead => !(WhiteFlute || BlackFlute || DexNav);
public bool IsDexNav => AllowDexNav && DexNav;
public EncounterSlotPermissions Clone() => (EncounterSlotPermissions)MemberwiseClone();
}
/// <summary>
/// Wild Encounter Slot data
/// </summary>
@ -65,80 +48,35 @@ namespace PKHeX.Core
}
}
public PKM ConvertToPKM(ITrainerInfo SAV)
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
int lang = (int)Legal.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int level = LevelMin;
var pk = PKMConverter.GetBlank(Generation, Version);
int nature = Util.Rand.Next(25);
SAV.ApplyToPKM(pk);
pk.Species = Species;
int gender = pk.PersonalInfo.RandomGender;
pk.Language = lang;
pk.CurrentLevel = level;
pk.Version = (int)version;
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, lang, Generation);
pk.Ball = GetBall();
pk.AltForm = GetWildAltForm(Form, pk, SAV);
if (pk.Format > 2 || Version == GameVersion.C)
{
pk.Met_Location = Location;
pk.Met_Level = level;
if (Version == GameVersion.C && pk is PK2 pk2 && this is EncounterSlot1 slot)
pk2.Met_TimeOfDay = slot.Time.RandomValidTime();
if (pk.Format >= 4)
pk.MetDate = DateTime.Today;
}
pk.Ball = (int)Type.GetBall();
pk.Language = lang;
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
pk.AltForm = GetWildAltForm(pk, Form, SAV);
var ability = Util.Rand.Next(2);
var pidtype = GetPIDType();
if (pidtype == PIDType.PokeSpot)
PIDGenerator.SetRandomPokeSpotPID(pk, nature, gender, ability, SlotNumber);
else
PIDGenerator.SetRandomWildPID(pk, pk.Format, nature, ability, gender, pidtype);
SetMetData(pk, level, Location);
SetNatureGenderAbility(pk, criteria);
if (Permissions.IsDexNav)
{
pk.RefreshAbility(2);
var eggMoves = MoveEgg.GetEggMoves(pk, Species, pk.AltForm, Version);
if (eggMoves.Length > 0)
pk.RelearnMove1 = eggMoves[Util.Rand.Next(eggMoves.Length)];
}
switch (pk.Format)
{
case 1 when Species == 64 && Version == GameVersion.YW: // Kadabra
((PK1)pk).Catch_Rate = 96;
break;
case 1 when Species == 148 && Version == GameVersion.YW: // Dragonair
((PK1)pk).Catch_Rate = 27;
break;
case 3:
case 4:
if (pk.Format == 4)
pk.EncounterType = TypeEncounter.GetIndex();
pk.Gender = gender;
break;
case 5:
if (Type == SlotType.HiddenGrotto)
pk.RefreshAbility(2);
break;
case 6:
pk.SetRandomMemory6();
break;
}
SetFormatSpecificData(pk);
var moves = this is EncounterSlotMoves m ? m.Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
if (Version == GameVersion.XD)
pk.FatefulEncounter = true;
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
if (pk.Format < 6)
return pk;
@ -148,7 +86,72 @@ namespace PKHeX.Core
return pk;
}
private static int GetWildAltForm(int form, PKM pk, ITrainerInfo SAV)
private void SetFormatSpecificData(PKM pk)
{
if (pk is PK1 pk1)
{
if (Species == 64 && Version == GameVersion.YW) // Kadabra
pk1.Catch_Rate = 96;
else if (Species == 148 && Version == GameVersion.YW) // Dragonair
pk1.Catch_Rate = 27;
else
pk1.Catch_Rate = PersonalTable.RB[Species].CatchRate; // RB
}
else if (pk is PK2 pk2)
{
if (Version == GameVersion.C && this is EncounterSlot1 slot)
pk2.Met_TimeOfDay = slot.Time.RandomValidTime();
}
else if (pk is XK3 xk3)
{
xk3.FatefulEncounter = true; // PokeSpot
}
else if (pk is PK4 pk4)
{
pk4.EncounterType = TypeEncounter.GetIndex();
}
else if (pk is PK6 pk6)
{
if (Permissions.IsDexNav)
{
var eggMoves = MoveEgg.GetEggMoves(pk, Species, pk.AltForm, Version);
if (eggMoves.Length > 0)
pk6.RelearnMove1 = eggMoves[Util.Rand.Next(eggMoves.Length)];
}
pk.SetRandomMemory6();
}
}
private void SetNatureGenderAbility(PKM pk, EncounterCriteria criteria)
{
int gender = criteria.GetGender(-1, pk.PersonalInfo);
int nature = (int)criteria.GetNature(Nature.Random);
var ability = Util.Rand.Next(2);
if (Type == SlotType.HiddenGrotto) // don't force hidden for DexNav
ability = 2;
var pidtype = GetPIDType();
if (pidtype == PIDType.PokeSpot)
PIDGenerator.SetRandomPokeSpotPID(pk, nature, gender, ability, SlotNumber);
else
PIDGenerator.SetRandomWildPID(pk, pk.Format, nature, ability, gender, pidtype);
pk.Gender = gender;
}
private void SetMetData(PKM pk, int level, int location)
{
if (pk.Format <= 2 && Version != GameVersion.C)
return;
pk.Met_Location = location;
pk.Met_Level = level;
if (pk.Format >= 4)
pk.MetDate = DateTime.Today;
}
private static int GetWildAltForm(PKM pk, int form, ITrainerInfo SAV)
{
if (form < 30)
{
@ -171,14 +174,5 @@ namespace PKHeX.Core
return PIDType.PokeSpot;
return PIDType.None; // depends on format, let the program auto-detect.
}
private int GetBall()
{
if (Type == SlotType.BugContest)
return 24; // Sport
if (Type.IsSafariType())
return 5; // Safari
return 4; // Poké Ball
}
}
}

View file

@ -7,7 +7,7 @@
/// Contains Time data which is present in <see cref="GameVersion.C"/> origin data.
/// Contains <see cref="GameVersion"/> identification, as this Version value is not stored in <see cref="PK1"/> or <see cref="PK2"/> formats.
/// </remarks>
internal class EncounterSlot1 : EncounterSlot
internal sealed class EncounterSlot1 : EncounterSlot
{
public int Rate;
internal EncounterTime Time;

View file

@ -1,6 +1,6 @@
namespace PKHeX.Core
{
internal class EncounterSlotMoves : EncounterSlot, IMoveset
internal sealed class EncounterSlotMoves : EncounterSlot, IMoveset
{
public int[] Moves { get; set; }
}

View file

@ -0,0 +1,19 @@
namespace PKHeX.Core
{
public sealed class EncounterSlotPermissions
{
public int StaticIndex { get; set; } = -1;
public int MagnetPullIndex { get; set; } = -1;
public int StaticCount { get; set; }
public int MagnetPullCount { get; set; }
public bool AllowDexNav { get; set; }
public bool Pressure { get; set; }
public bool DexNav { get; set; }
public bool WhiteFlute { get; set; }
public bool BlackFlute { get; set; }
public bool IsNormalLead => !(WhiteFlute || BlackFlute || DexNav);
public bool IsDexNav => AllowDexNav && DexNav;
public EncounterSlotPermissions Clone() => (EncounterSlotPermissions)MemberwiseClone();
}
}

View file

@ -68,7 +68,9 @@ namespace PKHeX.Core
private const string _name = "Static Encounter";
public string Name => Version == GameVersion.Any ? _name : $"{_name} ({Version})";
public PKM ConvertToPKM(ITrainerInfo SAV)
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
SanityCheckVersion(ref version);
@ -88,6 +90,9 @@ namespace PKHeX.Core
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)
{
@ -99,11 +104,13 @@ namespace PKHeX.Core
if (pk.Format >= 4)
pk.MetDate = DateTime.Today;
}
if (EggEncounter)
{
bool traded = (int)Version == SAV.Game;
pk.Met_Location = Math.Max(0, EncounterSuggestion.GetSuggestedEggMetLocation(pk));
pk.Met_Level = EncounterSuggestion.GetSuggestedEncounterEggMetLevel(pk);
bool traded = (int)Version == SAV.Game;
if (pk.GenNumber >= 4)
{
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk, traded);
@ -113,8 +120,6 @@ namespace PKHeX.Core
pk.EggMetDate = today;
}
pk.AltForm = Form;
if (this is EncounterStaticPID p)
{
pk.PID = p.PID;
@ -142,18 +147,16 @@ namespace PKHeX.Core
SetIVs(pk);
}
switch (pk.Format)
switch (pk)
{
case 3:
if (this is EncounterStaticShadow)
((PK3)pk).RibbonNational = true;
case PK3 pk3 when this is EncounterStaticShadow:
pk3.RibbonNational = true;
break;
case 4:
if (this is EncounterStaticTyped t)
pk.EncounterType = t.TypeEncounter.GetIndex();
case PK4 pk4 when this is EncounterStaticTyped t:
pk4.EncounterType = t.TypeEncounter.GetIndex();
break;
case 6:
pk.SetRandomMemory6();
case PK6 pk6:
pk6.SetRandomMemory6();
break;
}
@ -161,12 +164,10 @@ namespace PKHeX.Core
this.CopyContestStatsTo(s);
var moves = Moves ?? MoveLevelUp.GetEncounterMoves(pk, level, version);
pk.HeldItem = HeldItem;
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
if (pk.Format >= 6 && Relearn.Length > 0)
pk.RelearnMoves = Relearn;
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
if (Fateful)
pk.FatefulEncounter = true;
@ -347,7 +348,7 @@ namespace PKHeX.Core
{
for (int i = 0; i < 6; i++)
{
if (IVs[i] != -1 && IVs[i] != pkm.IVs[i])
if (IVs[i] != -1 && IVs[i] != pkm.GetIV(i))
return false;
}
}

View file

@ -1,6 +1,6 @@
namespace PKHeX.Core
{
internal class EncounterStaticPID : EncounterStatic
internal sealed class EncounterStaticPID : EncounterStatic
{
public uint PID { get; set; }
public bool NSparkle { get; set; }

View file

@ -2,7 +2,7 @@
namespace PKHeX.Core
{
public class EncounterStaticShadow : EncounterStatic
public sealed class EncounterStaticShadow : EncounterStatic
{
public TeamLock[] Locks { get; internal set; } = Array.Empty<TeamLock>();
public int Gauge { get; internal set; }

View file

@ -1,6 +1,6 @@
namespace PKHeX.Core
{
public class EncounterStaticTyped : EncounterStatic
public sealed class EncounterStaticTyped : EncounterStatic
{
public EncounterType TypeEncounter { get; internal set; } = EncounterType.None;
}

View file

@ -25,13 +25,6 @@ namespace PKHeX.Core
public int SID { get; set; }
public GameVersion Version { get; set; } = GameVersion.Any;
public int[] IVs { get; set; }
public int[] Contest { set => this.SetContestStats(value); }
public int CNT_Cool { get; set; }
public int CNT_Beauty { get; set; }
public int CNT_Cute { get; set; }
public int CNT_Smart { get; set; }
public int CNT_Tough { get; set; }
public int CNT_Sheen { get; set; }
public int Form { get; set; }
public virtual Shiny Shiny { get; set; } = Shiny.Never;
public int Gender { get; set; } = -1;
@ -42,6 +35,14 @@ namespace PKHeX.Core
public int Ball { get; set; } = 4;
public int CurrentLevel { get; set; } = -1;
public int[] Contest { set => this.SetContestStats(value); }
public int CNT_Cool { get; set; }
public int CNT_Beauty { get; set; }
public int CNT_Cute { get; set; }
public int CNT_Smart { get; set; }
public int CNT_Tough { get; set; }
public int CNT_Sheen { get; set; }
public int TID7
{
set
@ -67,67 +68,51 @@ namespace PKHeX.Core
0, 126, 254, 2001, 30002, 30001, 30001,
};
public PKM ConvertToPKM(ITrainerInfo SAV)
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
var pk = PKMConverter.GetBlank(Generation, Version);
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
var pk = PKMConverter.GetBlank(Generation, Version);
pk.EncryptionConstant = Util.Rand32();
pk.Species = Species;
pk.CurrentLevel = level;
int gender = Gender < 0 ? pk.PersonalInfo.RandomGender : Gender;
int nature = Nature == Nature.Random ? Util.Rand.Next(25) : (int)Nature;
SAV.ApplyToPKM(pk);
pk.Nature = nature;
int species = Species;
if (EvolveOnTrade)
species++;
pk.EncryptionConstant = Util.Rand32();
pk.Species = species;
pk.CurrentLevel = level;
pk.Version = (int)version;
pk.AltForm = Form;
if (this is EncounterTradePID p)
{
pk.PID = p.PID;
pk.Gender = PKX.GetGenderFromPID(Species, p.PID);
pk.RefreshAbility(Ability >> 1);
}
else
{
int ability = Ability >> 1;
PIDGenerator.SetRandomWildPID(pk, Generation, nature, ability, gender);
pk.Gender = gender;
pk.RefreshAbility(ability);
}
pk.Ball = Ball;
if (pk.Format != 2 || version == GameVersion.C)
{
pk.Met_Level = level;
pk.Met_Location = Location > 0 ? Location : DefaultMetLocation[Generation - 1];
}
var today = DateTime.Today;
pk.MetDate = today;
if (EggLocation != 0)
{
pk.Egg_Location = EggLocation;
pk.EggMetDate = today;
}
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.OT_Friendship = pk.PersonalInfo.BaseFriendship;
SetNatureGenderAbility(pk, criteria);
if (IVs != null)
pk.SetRandomIVs(IVs, 0);
else
pk.SetRandomIVs(flawless: 3);
if (pk.Format == 6)
pk.SetRandomMemory6();
if (pk.Format != 2 || version == GameVersion.C)
{
var location = Location > 0 ? Location : DefaultMetLocation[Generation - 1];
SetMetData(pk, level, location);
}
if (EggLocation != 0)
SetEggMetData(pk);
if (pk is PK1 pk1 && this is EncounterTradeCatchRate c)
pk1.Catch_Rate = (int)c.Catch_Rate;
@ -135,32 +120,71 @@ namespace PKHeX.Core
if (pk is IContestStats s)
this.CopyContestStatsTo(s);
var moves = Moves ?? MoveLevelUp.GetEncounterMoves(pk, level, version);
if (pk.Format == 1 && moves.All(z => z == 0))
moves = ((PersonalInfoG1)PersonalTable.RB[Species]).Moves;
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
SetMoves(pk, version, level);
if (Fateful)
pk.FatefulEncounter = true;
UpdateEdgeCase(pk);
if (EvolveOnTrade)
++pk.Species;
if (pk.Format < 6)
return pk;
SAV.ApplyHandlingTrainerInfo(pk, force: true);
pk.SetRandomEC();
if (pk.Format == 7)
if (pk.Format == 6)
pk.SetRandomMemory6();
else if (pk.Format == 7)
SetSMOTMemory(pk);
return pk;
}
private void SetNatureGenderAbility(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);
}
else
{
PIDGenerator.SetRandomWildPID(pk, Generation, nature, ability, gender);
pk.Nature = nature;
pk.Gender = gender;
pk.RefreshAbility(ability);
}
}
private void SetMoves(PKM pk, GameVersion version, int level)
{
var moves = Moves ?? MoveLevelUp.GetEncounterMoves(pk, level, version);
if (pk.Format == 1 && moves.All(z => z == 0))
moves = ((PersonalInfoG1)PersonalTable.RB[Species]).Moves;
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
}
private void SetEggMetData(PKM pk)
{
pk.Egg_Location = EggLocation;
pk.EggMetDate = DateTime.Today;
}
private static void SetMetData(PKM pk, int level, int location)
{
pk.Met_Level = level;
pk.Met_Location = location;
pk.MetDate = DateTime.Today;
}
private void UpdateEdgeCase(PKM pkm)
{
switch (Generation)

View file

@ -6,7 +6,7 @@
/// <remarks>
/// Generation 1 specific value used in detecting unmodified/untraded Generation 1 Trade Encounter data.
/// </remarks>
public class EncounterTradeCatchRate : EncounterTrade
public sealed class EncounterTradeCatchRate : EncounterTrade
{
public uint Catch_Rate;
}

View file

@ -3,7 +3,7 @@
/// <summary>
/// Trade Encounter data with a fixed PID.
/// </summary>
public class EncounterTradePID : EncounterTrade
public sealed class EncounterTradePID : EncounterTrade
{
public uint PID;
public override Shiny Shiny { get; set; } = Shiny.FixedValue;

View file

@ -5,7 +5,7 @@ namespace PKHeX.Core
/// <summary>
/// Calculated Information storage with properties useful for parsing the legality of the input <see cref="PKM"/>.
/// </summary>
public class LegalInfo
public sealed class LegalInfo
{
/// <summary>The <see cref="PKM"/> object used for comparisons.</summary>
private readonly PKM pkm;

View file

@ -12,6 +12,7 @@
int LevelMax { get; }
PKM ConvertToPKM(ITrainerInfo SAV);
PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria);
}
public static partial class Extensions

View file

@ -82,7 +82,8 @@ namespace PKHeX.Core
public byte[] Data { get; set; }
public abstract int Format { get; }
public abstract PKM ConvertToPKM(ITrainerInfo SAV);
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
public abstract PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria);
protected abstract bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs);
protected abstract bool IsMatchDeferred(PKM pkm);

View file

@ -126,9 +126,9 @@ namespace PKHeX.Core
return true;
}
public override PKM ConvertToPKM(ITrainerInfo SAV)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
return Gift.ConvertToPKM(SAV);
return Gift.ConvertToPKM(SAV, criteria);
}
public bool CanBeReceivedBy(int pkmVersion) => (CardCompatibility >> pkmVersion & 1) == 1;

View file

@ -162,7 +162,7 @@ namespace PKHeX.Core
public override bool IsItem { get => CardType == 2; set { if (value) CardType = 2; } }
public bool IsPower { get => CardType == 3; set { if (value) CardType = 3; } }
public override PKM ConvertToPKM(ITrainerInfo SAV)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
return null;

View file

@ -119,7 +119,7 @@ namespace PKHeX.Core
public override int Location { get => PK.Met_Location; set => PK.Met_Location = value; }
public override int EggLocation { get => PK.Egg_Location; set => PK.Egg_Location = value; }
public override PKM ConvertToPKM(ITrainerInfo SAV)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
return null;

View file

@ -116,14 +116,6 @@ namespace PKHeX.Core
public bool MultiObtain { get => Data[CardStart + 0x53] == 1; set => Data[CardStart + 0x53] = (byte)(value ? 1 : 0); }
// BP Properties
public override bool IsBP { get => CardType == 3; set { if (value) CardType = 3; } }
public override int BP { get => ItemID; set => ItemID = value; }
// Bean (Mame) Properties
public override bool IsBean { get => CardType == 2; set { if (value) CardType = 2; } }
public override int Bean { get => ItemID; set => ItemID = value; }
// Item Properties
public override bool IsItem { get => CardType == 1; set { if (value) CardType = 1; } }
public override int ItemID { get => BitConverter.ToUInt16(Data, CardStart + 0x68); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x68); }
@ -320,7 +312,7 @@ namespace PKHeX.Core
return 0xEE + (index * 0x1A);
}
public override PKM ConvertToPKM(ITrainerInfo SAV)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
return null;

View file

@ -70,7 +70,7 @@ namespace PKHeX.Core
set => _metLevel = value;
}
public override PKM ConvertToPKM(ITrainerInfo SAV)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
PK3 pk = new PK3
{
@ -151,22 +151,19 @@ namespace PKHeX.Core
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, pk.Language, 3); // will be set to Egg nickname if appropriate by PK3 setter
// Generate PIDIV
var seed = Util.Rand32();
switch (Method)
{
case PIDType.BACD_R:
seed &= 0xFFFF;
break;
case PIDType.BACD_R_S:
seed &= 0xFF;
break;
}
PIDGenerator.SetValuesFromSeed(pk, Method, seed);
SetPIDValues(pk);
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;
}
if (Moves == null || Moves.Length == 0) // not completely defined
private void SetMoves(PK3 pk)
{
if (Moves.Length == 0) // not completely defined
Moves = Legal.GetBaseEggMoves(pk, Species, (GameVersion)pk.Version, Level);
if (Moves.Length != 4)
{
@ -177,9 +174,26 @@ namespace PKHeX.Core
pk.Moves = Moves;
pk.SetMaximumPPCurrent(Moves);
pk.HeldItem = 0; // clear, only random for Jirachis(?), no loss
pk.RefreshChecksum();
return pk;
}
private void SetPIDValues(PK3 pk)
{
var seed = Util.Rand32();
SetPIDValues(pk, seed);
}
private void SetPIDValues(PK3 pk, uint seed)
{
switch (Method)
{
case PIDType.BACD_R:
seed &= 0xFFFF;
break;
case PIDType.BACD_R_S:
seed &= 0xFF;
break;
}
PIDGenerator.SetValuesFromSeed(pk, Method, seed);
}
private static LanguageID GetSafeLanguage(LanguageID hatchLang, LanguageID supplied)

View file

@ -284,7 +284,7 @@ namespace PKHeX.Core
}
}
public override PKM ConvertToPKM(ITrainerInfo SAV)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
return null;

View file

@ -326,7 +326,7 @@ namespace PKHeX.Core
}
}
public override PKM ConvertToPKM(ITrainerInfo SAV)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
return null;