mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-07-18 17:11:22 -05:00
Extract stadium reminder moveset verifier step
Now flags as Stadium2 as source
This commit is contained in:
parent
49061f0047
commit
542d6541c3
|
|
@ -173,9 +173,6 @@ private static void Check(Span<MoveResult> result, ReadOnlySpan<ushort> current,
|
|||
if (!yw.TryGetPersonal(evo.Species, evo.Form, out var yp))
|
||||
return; // should never happen.
|
||||
|
||||
if (ParseSettings.AllowGen1Tradeback && ParseSettings.AllowGen2MoveReminder(pk))
|
||||
evo = evo with { LevelMin = 1 };
|
||||
|
||||
for (int i = result.Length - 1; i >= 0; i--)
|
||||
{
|
||||
ref var entry = ref result[i];
|
||||
|
|
@ -229,9 +226,6 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvolutionHistory history, IEn
|
|||
|
||||
private static void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types)
|
||||
{
|
||||
if (ParseSettings.AllowGen1Tradeback && ParseSettings.AllowGen2MoveReminder(pk))
|
||||
evo = evo with { LevelMin = 1 };
|
||||
|
||||
LearnSource1YW.Instance.GetAllMoves(result, pk, evo, types);
|
||||
LearnSource1RB.Instance.GetAllMoves(result, pk, evo, types);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,9 +107,7 @@ private static void Check(Span<MoveResult> result, ReadOnlySpan<ushort> current,
|
|||
if (!c.TryGetPersonal(evo.Species, evo.Form, out var cp))
|
||||
return; // should never happen.
|
||||
|
||||
if (ParseSettings.AllowGen2MoveReminder(pk))
|
||||
evo = evo with { LevelMin = 1 };
|
||||
|
||||
bool stad2 = ParseSettings.AllowGen2MoveReminder(pk);
|
||||
bool kor = pk.Korean; // Crystal is not available to Korean games.
|
||||
|
||||
for (int i = result.Length - 1; i >= 0; i--)
|
||||
|
|
@ -132,6 +130,13 @@ private static void Check(Span<MoveResult> result, ReadOnlySpan<ushort> current,
|
|||
chk = c.GetCanLearn(pk, cp, evo, move, types);
|
||||
if (chk != default && GetIsPreferable(entry, chk, stage))
|
||||
entry = new(chk, (byte)stage, Generation);
|
||||
|
||||
if (stad2)
|
||||
{
|
||||
chk = LearnSource2Stadium.Instance.GetCanRelearn(evo, move, types);
|
||||
if (chk != default && GetIsPreferable(entry, chk, stage))
|
||||
entry = new(chk, (byte)stage, Generation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,13 +174,12 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvolutionHistory history, IEn
|
|||
|
||||
private static void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types)
|
||||
{
|
||||
if (ParseSettings.AllowGen2MoveReminder(pk))
|
||||
evo = evo with { LevelMin = 1 };
|
||||
|
||||
LearnSource2GS.Instance.GetAllMoves(result, pk, evo, types);
|
||||
if (pk.Korean)
|
||||
return;
|
||||
LearnSource2C.Instance.GetAllMoves(result, pk, evo, types);
|
||||
if (ParseSettings.AllowGen2MoveReminder(pk))
|
||||
LearnSource2Stadium.Instance.GetAllMoves(result, pk, evo, types);
|
||||
}
|
||||
|
||||
private static void FlagEncounterMoves(PKM pk, IEncounterTemplate enc, Span<bool> result)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public enum LearnEnvironment : byte
|
|||
None,
|
||||
|
||||
/* Gen1 */ RB, YW,
|
||||
/* Gen2 */ GS, C,
|
||||
/* Gen2 */ GS, C, Stadium2,
|
||||
/* Gen3 */ RS, E, FR, LG,
|
||||
/* Gen4 */ DP, Pt, HGSS,
|
||||
/* Gen5 */ BW, B2W2,
|
||||
|
|
|
|||
|
|
@ -82,8 +82,7 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceTy
|
|||
if (types.HasFlag(MoveSourceType.LevelUp))
|
||||
{
|
||||
var learn = Learnsets[evo.Species];
|
||||
var min = ParseSettings.AllowGen1Tradeback && ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin;
|
||||
var span = learn.GetMoveRange(evo.LevelMax, min);
|
||||
var span = learn.GetMoveRange(evo.LevelMax, evo.LevelMin);
|
||||
foreach (var move in span)
|
||||
result[move] = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,9 +81,8 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceTy
|
|||
|
||||
if (types.HasFlag(MoveSourceType.LevelUp))
|
||||
{
|
||||
var learn = GetLearnset(evo.Species, evo.Form);
|
||||
var min = ParseSettings.AllowGen1Tradeback && ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin;
|
||||
var span = learn.GetMoveRange(evo.LevelMax, min);
|
||||
var learn = Learnsets[evo.Species];
|
||||
var span = learn.GetMoveRange(evo.LevelMax, evo.LevelMin);
|
||||
foreach (var move in span)
|
||||
result[move] = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,9 +97,8 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceTy
|
|||
bool removeVC = pk.Format == 1 || pk.VC1;
|
||||
if (types.HasFlag(MoveSourceType.LevelUp))
|
||||
{
|
||||
var learn = GetLearnset(evo.Species, evo.Form);
|
||||
var min = ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin;
|
||||
var span = learn.GetMoveRange(evo.LevelMax, min);
|
||||
var learn = Learnsets[evo.Species];
|
||||
var span = learn.GetMoveRange(evo.LevelMax, evo.LevelMin);
|
||||
foreach (var move in span)
|
||||
{
|
||||
if (!removeVC || move <= Legal.MaxMoveID_1)
|
||||
|
|
|
|||
|
|
@ -115,8 +115,7 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceTy
|
|||
if (types.HasFlag(MoveSourceType.LevelUp))
|
||||
{
|
||||
var learn = Learnsets[evo.Species];
|
||||
var min = ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin;
|
||||
var span = learn.GetMoveRange(evo.LevelMax, min);
|
||||
var span = learn.GetMoveRange(evo.LevelMax, evo.LevelMin);
|
||||
foreach (var move in span)
|
||||
{
|
||||
if (!removeVC || move <= Legal.MaxMoveID_1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class LearnSource2Stadium : ILearnSource<PersonalInfo2>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource2Stadium Instance = new();
|
||||
private static readonly LearnsetStadium[] Learnsets = LearnsetStadium.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("reminder_stad2.pkl"), "s2"u8));
|
||||
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_2;
|
||||
private const LearnEnvironment Game = Stadium2;
|
||||
public LearnEnvironment Environment => Game;
|
||||
|
||||
public Learnset GetLearnset(ushort species, byte form) => throw new InvalidOperationException("Not supported.");
|
||||
public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo2? pi) => throw new InvalidOperationException("Not supported.");
|
||||
public bool GetIsEggMove(ushort species, byte form, ushort move) => false;
|
||||
public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form) => [];
|
||||
private static bool IsSpeciesInGame(ushort species, byte form) => form is 0 && species is <= MaxSpecies and not 0;
|
||||
public LearnsetStadium GetLearnsetStadium(ushort species, byte form) => Learnsets[species < Learnsets.Length ? species : 0];
|
||||
|
||||
public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo2 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current)
|
||||
{
|
||||
return GetCanRelearn(evo, move, types);
|
||||
}
|
||||
|
||||
public MoveLearnInfo GetCanRelearn(EvoCriteria evo, ushort move, MoveSourceType types)
|
||||
{
|
||||
if (move > Legal.MaxMoveID_2) // byte
|
||||
return default;
|
||||
|
||||
if (types.HasFlag(MoveSourceType.LevelUp))
|
||||
{
|
||||
var learn = GetLearnsetStadium(evo.Species, evo.Form);
|
||||
if (learn.CanRelearn(move, evo.LevelMax, out var level))
|
||||
return new(LevelUp, Game, level);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All)
|
||||
{
|
||||
if (!IsSpeciesInGame(evo.Species, evo.Form))
|
||||
return;
|
||||
|
||||
if (!types.HasFlag(MoveSourceType.LevelUp))
|
||||
return;
|
||||
|
||||
bool removeVC = pk.Format == 1 || pk.VC1;
|
||||
var learn = GetLearnsetStadium(evo.Species, evo.Form);
|
||||
var span = learn.GetMoveRange(evo.LevelMax);
|
||||
foreach (var tuple in span)
|
||||
{
|
||||
if (!tuple.Source.IsAbleToBeRelearned())
|
||||
continue;
|
||||
var move = tuple.Move;
|
||||
if (!removeVC || move <= Legal.MaxMoveID_1)
|
||||
result[move] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static PKHeX.Core.LearnSourceStadium;
|
||||
using static PKHeX.Core.LearnMethodStadium2;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
|
@ -53,9 +53,11 @@ public bool TryGetMove(ushort move, out StadiumTuple result)
|
|||
/// </summary>
|
||||
/// <param name="move">Move ID to try and remember.</param>
|
||||
/// <param name="level">Current level of the Pokémon.</param>
|
||||
/// <param name="criteriaLevel">Level at which the move can be relearned, if applicable.</param>
|
||||
/// <returns>True if the move can be relearned.</returns>
|
||||
public bool CanRelearn(ushort move, byte level)
|
||||
public bool CanRelearn(ushort move, byte level, out byte criteriaLevel)
|
||||
{
|
||||
criteriaLevel = 0;
|
||||
foreach (var learn in Learn)
|
||||
{
|
||||
if (level < learn.Level)
|
||||
|
|
@ -64,6 +66,7 @@ public bool CanRelearn(ushort move, byte level)
|
|||
continue;
|
||||
if (!learn.Source.IsAbleToBeRelearned())
|
||||
continue;
|
||||
criteriaLevel = learn.Level; // remember the minimum level to relearn
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -107,6 +110,27 @@ public static LearnsetStadium[] GetArray(BinLinkerAccessor entries)
|
|||
result[i] = new LearnsetStadium(entries[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the range of moves that can be learned between the specified levels.
|
||||
/// </summary>
|
||||
/// <param name="levelMax">Maximum level to learn moves.</param>
|
||||
/// <param name="levelMin">>Minimum level to learn moves.</param>
|
||||
public ReadOnlySpan<StadiumTuple> GetMoveRange(byte levelMax, byte levelMin = 1)
|
||||
{
|
||||
// find start
|
||||
int start = 0;
|
||||
while (start < Learn.Length && Learn[start].Level < levelMin)
|
||||
start++;
|
||||
// find end
|
||||
int end = start;
|
||||
while (end < Learn.Length && Learn[end].Level <= levelMax)
|
||||
end++;
|
||||
// return the range
|
||||
if (start >= end)
|
||||
return []; // no moves in range
|
||||
return Learn.AsSpan(start, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -115,7 +139,7 @@ public static LearnsetStadium[] GetArray(BinLinkerAccessor entries)
|
|||
/// <param name="Level">Minimum level to learn the move.</param>
|
||||
/// <param name="Move">>Move ID.</param>
|
||||
/// <param name="Source">>Source of the move (e.g., level up, tutor, egg).</param>
|
||||
public readonly record struct StadiumTuple(byte Level, byte Move, LearnSourceStadium Source)
|
||||
public readonly record struct StadiumTuple(byte Level, byte Move, LearnMethodStadium2 Source)
|
||||
{
|
||||
public override string ToString() => $"Lv{Level} {(Move)Move} // {Source}";
|
||||
}
|
||||
|
|
@ -124,13 +148,15 @@ public static LearnsetStadium[] GetArray(BinLinkerAccessor entries)
|
|||
/// Flags for the source of moves learned in Stadium 2.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum LearnSourceStadium : byte
|
||||
public enum LearnMethodStadium2 : byte
|
||||
{
|
||||
None,
|
||||
None = 0,
|
||||
// Able to be remembered
|
||||
LevelUpRB = 1 << 0,
|
||||
LevelUpYW = 1 << 1,
|
||||
LevelUpGS = 1 << 2,
|
||||
LevelUpC = 1 << 3,
|
||||
// Permitted to know by legality checker, but not able to remember.
|
||||
TutorC = 1 << 4,
|
||||
EggC = 1 << 5,
|
||||
EggGS = 1 << 6,
|
||||
|
|
@ -142,5 +168,5 @@ public static class LearnSourceStadiumExtensions
|
|||
/// <summary>
|
||||
/// Checks if the source can be relearned.
|
||||
/// </summary>
|
||||
public static bool IsAbleToBeRelearned(this LearnSourceStadium source) => (source & (LevelUpRB | LevelUpYW | LevelUpGS | LevelUpC)) != 0;
|
||||
public static bool IsAbleToBeRelearned(this LearnMethodStadium2 source) => (source & (LevelUpRB | LevelUpYW | LevelUpGS | LevelUpC)) != 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public static class GameData
|
|||
Gen9 => LearnSource9SV.Instance,
|
||||
|
||||
Stadium => LearnSource1YW.Instance,
|
||||
Stadium2 => LearnSource2GS.Instance,
|
||||
Stadium2 => LearnSource2Stadium.Instance,
|
||||
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(game), $"{game} is not a valid entry in the expression."),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ public override void Verify(LegalityAnalysis data)
|
|||
|
||||
switch (pk)
|
||||
{
|
||||
case SK2 sk2:
|
||||
VerifyIsMovesetAllowed(data, sk2);
|
||||
break;
|
||||
case PK5 pk5:
|
||||
VerifyGen5Stats(data, pk5);
|
||||
break;
|
||||
|
|
@ -167,6 +170,28 @@ private void VerifyMiscScaleValues(LegalityAnalysis data, PKM pk, IEncounterTemp
|
|||
data.AddLine(GetInvalid(LStatIncorrectHeightValue));
|
||||
}
|
||||
|
||||
private void VerifyIsMovesetAllowed(LegalityAnalysis data, SK2 sk2)
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
sk2.GetMoves(moves);
|
||||
Span<bool> flags = stackalloc bool[4];
|
||||
|
||||
var learn = LearnSource2Stadium.Instance.GetLearnsetStadium(sk2.Species, sk2.Form);
|
||||
if (learn.Validate(moves, sk2.CurrentLevel, flags))
|
||||
return;
|
||||
|
||||
var parse = data.Info.Moves;
|
||||
for (int i = 0; i < flags.Length; i++)
|
||||
{
|
||||
if (!flags[i])
|
||||
continue;
|
||||
ref var m = ref parse[i];
|
||||
if (!m.Valid)
|
||||
continue;
|
||||
m = m with { Info = m.Info with { Method = LearnMethod.Unobtainable, Environment = LearnEnvironment.Stadium2 } };
|
||||
}
|
||||
}
|
||||
|
||||
private static void VerifyGen5Stats(LegalityAnalysis data, PK5 pk5)
|
||||
{
|
||||
var enc = data.EncounterMatch;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user