PKHeX/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterSlot3.cs

151 lines
5.6 KiB
C#

using static PKHeX.Core.PIDType;
using static PKHeX.Core.SlotType3;
using static PKHeX.Core.RandomCorrelationRating;
namespace PKHeX.Core;
/// <summary>
/// Encounter Slot found in <see cref="EntityContext.Gen3"/>.
/// </summary>
public record EncounterSlot3(EncounterArea3 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, byte SlotNumber, byte MagnetPullIndex, byte MagnetPullCount, byte StaticIndex, byte StaticCount)
: IEncounterable, IEncounterMatch, IEncounterConvertible<PK3>, IEncounterSlot3, IRandomCorrelation
{
public byte Generation => 3;
ushort ILocation.Location => Location;
public EntityContext Context => EntityContext.Gen3;
public bool IsEgg => false;
public Ball FixedBall => GetRequiredBall();
public byte AreaRate => Parent.Rate;
public AbilityPermission Ability => AbilityPermission.Any12;
public Shiny Shiny => Shiny.Random;
public bool IsShiny => false;
public ushort EggLocation => 0;
public string Name => $"Wild Encounter ({Version})";
public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}";
public GameVersion Version => Parent.Version;
public byte Location => Parent.Location;
public SlotType3 Type => Parent.Type;
public bool IsSafari => Locations.IsSafariZoneLocation3(Location);
public bool IsSafariHoenn => Locations.IsSafariZoneLocation3RSE(Location);
private Ball GetRequiredBall(Ball fallback = Ball.None) => IsSafari ? Ball.Safari : fallback;
#region Generating
PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria);
PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr);
public PK3 ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted);
public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
{
int language = (int)Language.GetSafeLanguage3((LanguageID)tr.Language);
var version = Version switch
{
GameVersion.RSE => tr.Version switch
{
GameVersion.R => GameVersion.R,
GameVersion.S => GameVersion.S,
GameVersion.RS => GameVersion.R,
_ => GameVersion.E,
},
_ => Version
};
var pi = PersonalTable.E[Species];
var pk = new PK3
{
Species = Species,
CurrentLevel = LevelMin,
OriginalTrainerFriendship = pi.BaseFriendship,
MetLocation = Location,
MetLevel = LevelMin,
Version = version,
Ball = (byte)GetRequiredBall(Ball.Poke),
Language = language,
OriginalTrainerGender = tr.Gender,
ID32 = tr.ID32,
Nickname = SpeciesName.GetSpeciesNameGeneration(Species, language, Generation),
};
// Copy from SaveFile's OT name. Trash bytes here should be pure, but our OT name might not always source from a PK3/SAV3.
// Condition the buffer as if it came from a correct SAV3 named after the OT.
var ot = pk.OriginalTrainerTrash;
ot[..(language == 1 ? 6 : 7)].Fill(0xFF);
pk.OriginalTrainerName = EncounterUtil.GetTrainerName(tr, language);
SetPINGA(pk, criteria, pi);
SetEncounterMoves(pk);
pk.ResetPartyStats();
return pk;
}
private void SetPINGA(PK3 pk, in EncounterCriteria criteria, PersonalInfo3 pi)
{
if (Species != (int)Core.Species.Unown)
{
if (criteria.IsSpecifiedIVsAll() && this.SetFromIVs(pk, pi, criteria, pk.E))
return;
this.SetRandom(pk, pi, criteria, Util.Rand32());
}
else
{
if (criteria.IsSpecifiedIVsAll() && this.SetFromIVsUnown(pk, criteria))
return;
this.SetRandomUnown(pk, criteria, Util.Rand32());
}
}
protected virtual void SetEncounterMoves(PK3 pk) => EncounterUtil.SetEncounterMoves(pk, Version, LevelMin);
#endregion
#region Matching
public bool IsMatchExact(PKM pk, EvoCriteria evo)
{
if (Form != evo.Form && Species is not (int)Core.Species.Burmy)
return false;
if (pk.Format == 3)
{
// Must match level exactly.
if (!this.IsLevelWithinRange(pk.MetLevel))
return false;
}
else
{
if (evo.LevelMax < LevelMin)
return false;
}
return true;
}
public EncounterMatchRating GetMatchRating(PKM pk)
{
if (IsDeferredSafari3(pk.Ball == (int)Ball.Safari))
return EncounterMatchRating.PartialMatch;
if (IsDeferredWurmple(pk))
return EncounterMatchRating.PartialMatch;
return EncounterMatchRating.Match;
}
private bool IsDeferredWurmple(PKM pk) => Species == (int)Core.Species.Wurmple && pk.Species != (int)Core.Species.Wurmple && !WurmpleUtil.IsWurmpleEvoValid(pk);
private bool IsDeferredSafari3(bool IsSafariBall) => IsSafariBall != Locations.IsSafariZoneLocation3(Location);
#endregion
public RandomCorrelationRating IsCompatible(PIDType type, PKM pk)
{
var match = Species != (int)Core.Species.Unown
? type is Method_1 or Method_2 or Method_3 or Method_4
: type is Method_1_Unown or Method_2_Unown or Method_3_Unown or Method_4_Unown;
return match ? Match : Mismatch;
}
public PIDType GetSuggestedCorrelation() => Species == (int)Core.Species.Unown ? Method_1_Unown : Method_1;
public byte PressureLevel => Type != Grass ? LevelMax : Parent.GetPressureMax(Species, LevelMax);
}