Extract IMetLevel for level!=met encounters

No longer marks Ranch gifts as Fishy for leveled @ threshold.
Encounter range check now ignores the MetLevel if it can't exist that low.
This commit is contained in:
Kurt
2024-07-06 01:40:12 -05:00
parent 99ebc47866
commit 52e22086e9
14 changed files with 73 additions and 50 deletions

View File

@@ -112,28 +112,28 @@ internal static class Encounters4DPPt
internal static readonly EncounterTrade4RanchGift[] RanchGifts =
[
new(323975838, 025, 18) { Moves = new(447,085,148,104), TID16 = 1000, SID16 = 19840, OTGender = 1, Location = 0068, Gender = 0, Ability = OnlyFirst, CurrentLevel = 20 }, // Pikachu
new(323977664, 037, 16) { Moves = new(412,109,053,219), TID16 = 1000, SID16 = 21150, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlyFirst, CurrentLevel = 30 }, // Vulpix
new(323975579, 077, 13) { Moves = new(036,033,039,052), TID16 = 1000, SID16 = 01123, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 16 }, // Ponyta
new(323975564, 108, 34) { Moves = new(076,111,014,205), TID16 = 1000, SID16 = 03050, OTGender = 1, Location = 0077, Gender = 0, Ability = OnlyFirst, CurrentLevel = 40 }, // Lickitung
new(323977579, 114, 01) { Moves = new(437,438,079,246), TID16 = 1000, SID16 = 49497, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlySecond }, // Tangela
new(323977675, 133, 16) { Moves = new(363,270,098,247), TID16 = 1000, SID16 = 47710, OTGender = 1, Location = 0068, Gender = 0, Ability = OnlySecond, CurrentLevel = 30 }, // Eevee
new(323977588, 142, 20) { Moves = new(363,089,444,332), TID16 = 1000, SID16 = 43066, OTGender = 1, Location = 0094, Gender = 0, Ability = OnlyFirst, CurrentLevel = 50 }, // Aerodactyl
new(232975554, 193, 22) { Moves = new(318,095,246,138), TID16 = 1000, SID16 = 42301, OTGender = 1, Location = 0052, Gender = 0, Ability = OnlyFirst, CurrentLevel = 45, FixedBall = Ball.Safari }, // Yanma
new(323975570, 241, 16) { Moves = new(208,215,360,359), TID16 = 1000, SID16 = 02707, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 48 }, // Miltank
new(323975563, 285, 22) { Moves = new(402,147,206,078), TID16 = 1000, SID16 = 02788, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 45, FixedBall = Ball.Safari }, // Shroomish
new(323975559, 320, 30) { Moves = new(156,323,133,058), TID16 = 1000, SID16 = 27046, OTGender = 1, Location = 0038, Gender = 0, Ability = OnlySecond, CurrentLevel = 45 }, // Wailmer
new(323977657, 360, 01) { Moves = new(204,150,227,000), TID16 = 1000, SID16 = 01788, OTGender = 1, Location = 0004, Gender = 0, Ability = OnlySecond, EggLocation = 2000 }, // Wynaut
new(323975563, 397, 02) { Moves = new(355,017,283,018), TID16 = 1000, SID16 = 59298, OTGender = 1, Location = 0016, Gender = 0, Ability = OnlySecond, CurrentLevel = 23 }, // Staravia
new(323970584, 415, 05) { Moves = new(230,016,000,000), TID16 = 1000, SID16 = 54140, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 20 }, // Combee
new(323977539, 417, 09) { Moves = new(447,045,351,098), TID16 = 1000, SID16 = 18830, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlySecond, CurrentLevel = 10 }, // Pachirisu
new(323974107, 422, 20) { Moves = new(363,352,426,104), TID16 = 1000, SID16 = 39272, OTGender = 1, Location = 0028, Gender = 0, Ability = OnlySecond, CurrentLevel = 25, Form = 1 }, // Shellos
new(323977566, 427, 10) { Moves = new(204,193,409,098), TID16 = 1000, SID16 = 31045, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 16 }, // Buneary
new(323975579, 453, 22) { Moves = new(310,207,426,389), TID16 = 1000, SID16 = 41342, OTGender = 1, Location = 0052, Gender = 0, Ability = OnlySecond, CurrentLevel = 31, FixedBall = Ball.Safari }, // Croagunk
new(323977566, 456, 15) { Moves = new(213,352,219,392), TID16 = 1000, SID16 = 48348, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 35 }, // Finneon
new(323975582, 459, 32) { Moves = new(452,420,275,059), TID16 = 1000, SID16 = 23360, OTGender = 1, Location = 0031, Gender = 0, Ability = OnlyFirst, CurrentLevel = 41 }, // Snover
new(151, 50) { Moves = new(235,216,095,100), TID16 = 1000, SID16 = 59228, OTGender = 1, FixedBall = Ball.Cherish, Gender = 2, Ability = Any12 }, // Mew
new(489, 01) { Moves = new(447,240,156,057), TID16 = 1000, SID16 = 09248, OTGender = 1, FixedBall = Ball.Cherish, Gender = 2, Ability = Any12, CurrentLevel = 50, EggLocation = 3000 }, // Phione
new(323975838, 025, 18, 20) { Moves = new(447,085,148,104), SID16 = 19840, OTGender = 1, Location = 0068, Gender = 0, Ability = OnlyFirst }, // Pikachu
new(323977664, 037, 16, 30) { Moves = new(412,109,053,219), SID16 = 21150, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlyFirst }, // Vulpix
new(323975579, 077, 13, 16) { Moves = new(036,033,039,052), SID16 = 01123, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlySecond }, // Ponyta
new(323975564, 108, 34, 40) { Moves = new(076,111,014,205), SID16 = 03050, OTGender = 1, Location = 0077, Gender = 0, Ability = OnlyFirst }, // Lickitung
new(323977579, 114, 01, 01) { Moves = new(437,438,079,246), SID16 = 49497, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlySecond }, // Tangela
new(323977675, 133, 16, 30) { Moves = new(363,270,098,247), SID16 = 47710, OTGender = 1, Location = 0068, Gender = 0, Ability = OnlySecond }, // Eevee
new(323977588, 142, 20, 50) { Moves = new(363,089,444,332), SID16 = 43066, OTGender = 1, Location = 0094, Gender = 0, Ability = OnlyFirst }, // Aerodactyl
new(232975554, 193, 22, 45) { Moves = new(318,095,246,138), SID16 = 42301, OTGender = 1, Location = 0052, Gender = 0, Ability = OnlyFirst, FixedBall = Ball.Safari }, // Yanma
new(323975570, 241, 16, 48) { Moves = new(208,215,360,359), SID16 = 02707, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlyFirst }, // Miltank
new(323975563, 285, 22, 45) { Moves = new(402,147,206,078), SID16 = 02788, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlySecond, FixedBall = Ball.Safari }, // Shroomish
new(323975559, 320, 30, 45) { Moves = new(156,323,133,058), SID16 = 27046, OTGender = 1, Location = 0038, Gender = 0, Ability = OnlySecond }, // Wailmer
new(323977657, 360, 01, 01) { Moves = new(204,150,227,000), SID16 = 01788, OTGender = 1, Location = 0004, Gender = 0, Ability = OnlySecond, EggLocation = 2000 }, // Wynaut
new(323975563, 397, 02, 23) { Moves = new(355,017,283,018), SID16 = 59298, OTGender = 1, Location = 0016, Gender = 0, Ability = OnlySecond }, // Staravia
new(323970584, 415, 05, 20) { Moves = new(230,016,000,000), SID16 = 54140, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlyFirst }, // Combee
new(323977539, 417, 09, 10) { Moves = new(447,045,351,098), SID16 = 18830, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlySecond }, // Pachirisu
new(323974107, 422, 20, 25) { Moves = new(363,352,426,104), SID16 = 39272, OTGender = 1, Location = 0028, Gender = 0, Ability = OnlySecond, Form = 1 }, // Shellos
new(323977566, 427, 10, 16) { Moves = new(204,193,409,098), SID16 = 31045, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlyFirst }, // Buneary
new(323975579, 453, 22, 31) { Moves = new(310,207,426,389), SID16 = 41342, OTGender = 1, Location = 0052, Gender = 0, Ability = OnlySecond, FixedBall = Ball.Safari }, // Croagunk
new(323977566, 456, 15, 35) { Moves = new(213,352,219,392), SID16 = 48348, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlyFirst }, // Finneon
new(323975582, 459, 32, 41) { Moves = new(452,420,275,059), SID16 = 23360, OTGender = 1, Location = 0031, Gender = 0, Ability = OnlyFirst }, // Snover
new(151, 50, 50) { Moves = new(235,216,095,100), SID16 = 59228, OTGender = 1, FixedBall = Ball.Cherish, Gender = 2, Ability = Any12 }, // Mew
new(489, 01, 50) { Moves = new(447,240,156,057), SID16 = 09248, OTGender = 1, FixedBall = Ball.Cherish, Gender = 2, Ability = Any12, EggLocation = 3000 }, // Phione
];
internal static readonly EncounterTrade4PID[] TradeGift_DPPtIngame =

View File

@@ -6,7 +6,8 @@ namespace PKHeX.Core;
/// Generation 4 Trade Encounter with a fixed PID value, met location, and version.
/// </summary>
public sealed record EncounterTrade4RanchGift
: IEncounterable, IEncounterMatch, IEncounterConvertible<PK4>, IFatefulEncounterReadOnly, IFixedTrainer, IMoveset, IFixedGender, IFixedNature
: IEncounterable, IEncounterMatch, IEncounterConvertible<PK4>, IFatefulEncounterReadOnly, IFixedTrainer,
IMoveset, IFixedGender, IFixedNature, IMetLevel
{
public byte Generation => 4;
public EntityContext Context => EntityContext.Gen4;
@@ -16,7 +17,7 @@ public sealed record EncounterTrade4RanchGift
/// </summary>
public readonly uint PID;
public Nature Nature => (Nature)(PID % 25);
public Nature Nature => FatefulEncounter ? Nature.Random : (Nature)(PID % 25);
public ushort Location { get; init; }
public Shiny Shiny => FatefulEncounter ? Shiny.Never : Shiny.FixedValue;
@@ -30,37 +31,48 @@ public sealed record EncounterTrade4RanchGift
public byte LevelMin => Level;
public byte LevelMax => Level;
public ushort Species { get; }
public byte MetLevel { get; }
public byte Level { get; }
public bool FatefulEncounter { get; }
public required Moveset Moves { get; init; }
public required ushort TID16 { get; init; }
public const ushort TID16 = 1000;
public required ushort SID16 { get; init; }
private uint ID32 => (uint)(TID16 | (SID16 << 16));
public required byte OTGender { get; init; }
public required byte Gender { get; init; }
public required AbilityPermission Ability { get; init; }
public byte CurrentLevel { get; init; }
public byte Form { get; init; }
private static readonly string[] TrainerNames = [string.Empty, "ユカリ", "Hayley", "EULALIE", "GIULIA", "EUKALIA", string.Empty, "Eulalia"];
private static string GetTrainerName(int language) => language switch
{
1 => "ユカリ",
2 => "Hayley",
3 => "EULALIE",
4 => "GIULIA",
5 => "EUKALIA",
7 => "Eulalia",
_ => "",
};
private const string _name = "In-game Trade";
private const string _name = "My Pokémon Ranch - Trade";
public string Name => _name;
public string LongName => _name;
public EncounterTrade4RanchGift(uint pid, ushort species, byte level)
public EncounterTrade4RanchGift(uint pid, ushort species, byte met, byte level)
{
Version = GameVersion.D;
PID = pid;
Species = species;
MetLevel = met;
Level = level;
}
public EncounterTrade4RanchGift(ushort species, byte level)
public EncounterTrade4RanchGift(ushort species, byte met, byte level)
{
Version = GameVersion.D;
Species = species;
MetLevel = met;
Level = level;
FatefulEncounter = true;
Location = 3000;
@@ -77,15 +89,14 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
{
var version = this.GetCompatibleVersion(tr.Version);
int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version);
var actualLevel = CurrentLevel != default ? CurrentLevel : Level;
var pi = PersonalTable.DP[Species];
var pk = new PK4
{
Species = Species,
Form = Form,
CurrentLevel = actualLevel,
CurrentLevel = Level,
MetLocation = Location,
MetLevel = Level,
MetLevel = MetLevel,
MetDate = EncounterDate.GetDateNDS(),
Ball = (byte)FixedBall,
FatefulEncounter = FatefulEncounter,
@@ -94,7 +105,7 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
Version = version,
Language = lang,
OriginalTrainerGender = OTGender,
OriginalTrainerName = TrainerNames[lang],
OriginalTrainerName = GetTrainerName(lang),
OriginalTrainerFriendship = pi.BaseFriendship,
@@ -113,7 +124,7 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
if (Moves.HasMoves)
pk.SetMoves(Moves);
else
EncounterUtil.SetEncounterMoves(pk, version, actualLevel);
EncounterUtil.SetEncounterMoves(pk, version, Level);
SetPINGA(pk, criteria);
pk.ResetPartyStats();
@@ -134,7 +145,7 @@ private void SetPINGA(PK4 pk, EncounterCriteria criteria)
#region Matching
public bool IsTrainerMatch(PKM pk, ReadOnlySpan<char> trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]);
public bool IsTrainerMatch(PKM pk, ReadOnlySpan<char> trainer, int language) => trainer.SequenceEqual(GetTrainerName(language));
public bool IsMatchExact(PKM pk, EvoCriteria evo)
{
@@ -173,7 +184,7 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo)
return evo.LevelMax >= Level;
if (Location != default)
return pk.MetLevel == Level;
return pk.MetLevel == MetLevel;
return pk.MetLevel >= LevelMin;
}

View File

@@ -25,9 +25,8 @@ public static bool IsWithinEncounterRange(this IEncounterTemplate encounter, PKM
return encounter.IsLevelWithinRange(level);
if (encounter.IsEgg)
return level == encounter.LevelMin;
if (encounter is MysteryGift g)
return level == g.Level;
if (encounter is IMetLevel)
return encounter.IsLevelWithinRange(level);
var met = pk.MetLevel;
if (met != 0)
return level == met;

View File

@@ -0,0 +1,13 @@
namespace PKHeX.Core;
/// <summary>
/// Contains information about the level the object was met at.
/// </summary>
public interface IMetLevel
{
/// <summary>
/// Level met.
/// </summary>
/// <remarks>Can be below the original current level if the encounter says so.</remarks>
byte MetLevel { get; }
}

View File

@@ -127,7 +127,7 @@ private static int LoadBareMinimumMoveset(ISpeciesForm enc, EvolutionHistory h,
return AddMasteredMissing(pa, moves, count, moveset, currentLearn, level);
}
private static void LoadPurchasedMoves(IMoveShop8 pa, Span<ushort> result)
private static void LoadPurchasedMoves(PA8 pa, Span<ushort> result)
{
int ctr = 0;
var purchased = pa.Permit.RecordPermitIndexes;

View File

@@ -68,7 +68,6 @@ private static bool IsMetLevelMatchEncounter(MysteryGift gift, PKM pk)
return gift switch
{
WC3 wc3 when wc3.MetLevel == pk.MetLevel || wc3.IsEgg => true,
WC7 wc7 when wc7.MetLevel == pk.MetLevel => true,
PGT { IsManaphyEgg: true } when pk.MetLevel == 0 => true,
_ => false,

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Generation 5 Mystery Gift Template File
/// </summary>
public sealed class PGF(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, ILangNick,
IContestStats, INature, IRestrictVersion
IContestStats, INature, IMetLevel, IRestrictVersion
{
public PGF() : this(new byte[Size]) { }
public int RestrictLanguage { get; set; } // None

View File

@@ -9,7 +9,7 @@ namespace PKHeX.Core;
/// </summary>
public sealed class WA8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel,
IRibbonIndex, IMemoryOT, IRelearn, IEncounterServerDate,
ILangNicknamedTemplate, IGanbaru, IAlpha,
ILangNicknamedTemplate, IGanbaru, IAlpha, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7,
IRibbonSetCommon8, IRibbonSetMark8
{

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Generation 7 Mystery Gift Template File (LGP/E)
/// </summary>
public sealed class WB7(byte[] Data)
: DataMysteryGift(Data), ILangNick, IAwakened, IRelearn, INature, ILangNicknamedTemplate, IRestrictVersion
: DataMysteryGift(Data), ILangNick, IAwakened, IRelearn, INature, ILangNicknamedTemplate, IMetLevel, IRestrictVersion
{
public WB7() : this(new byte[Size]) { }

View File

@@ -9,7 +9,7 @@ namespace PKHeX.Core;
/// </summary>
public sealed class WB8(byte[] Data) : DataMysteryGift(Data),
ILangNick, INature, IRibbonIndex, IContestStatsReadOnly, IRelearn,
ILangNicknamedTemplate, IEncounterServerDate,
ILangNicknamedTemplate, IEncounterServerDate, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7,
IRibbonSetCommon8, IRibbonSetMark8
{

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Generation 7 Mystery Gift Template File
/// </summary>
public sealed class WC7(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, ILangNick,
IContestStats, INature, IMemoryOT, IRelearn, IRestrictVersion
IContestStats, INature, IMemoryOT, IRelearn, IMetLevel, IRestrictVersion
{
public WC7() : this(new byte[Size]) { }

View File

@@ -7,7 +7,8 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 8 Mystery Gift Template File
/// </summary>
public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel, IRibbonIndex, IMemoryOT, ILangNicknamedTemplate, IRelearn, IEncounterServerDate, IRestrictVersion,
public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel, IRibbonIndex, IMemoryOT,
ILangNicknamedTemplate, IRelearn, IEncounterServerDate, IRestrictVersion, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, ITrashUnderlaySpecies
{
public WC8() : this(new byte[Size]) { }

View File

@@ -8,7 +8,7 @@ namespace PKHeX.Core;
/// Generation 9 Mystery Gift Template File
/// </summary>
public sealed class WC9(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, ITeraType, IRibbonIndex, IMemoryOT,
ILangNicknamedTemplate, IEncounterServerDate, IRelearn,
ILangNicknamedTemplate, IEncounterServerDate, IRelearn, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7,
IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetCommon9, IRibbonSetMark9, IEncounterMarkExtra
{

View File

@@ -262,7 +262,7 @@ public static void LoadSettings<T>(string defaultLanguage, bool add = true)
LoadSettings<T>(add, t, context);
}
private static void LoadSettings<T>(bool add, IReflect type, Dictionary<string, string> context)
private static void LoadSettings<T>(bool add, Type type, Dictionary<string, string> context)
{
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)