mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-03-21 17:48:28 -05:00
Extract bonus move interface from slot6ao/8b-under
This commit is contained in:
parent
4d0bfa46df
commit
d5bf6e67d5
|
|
@ -88,7 +88,7 @@ public static void GetSuggestedRelearnMoves(this LegalityAnalysis legal, Span<us
|
|||
if (enc is MysteryGift or IEncounterEgg)
|
||||
return;
|
||||
|
||||
if (enc is EncounterSlot6AO {CanDexNav: true} dn)
|
||||
if (enc is ISingleMoveBonus {IsMoveBonusPossible: true} bonus)
|
||||
{
|
||||
var chk = legal.Info.Moves;
|
||||
for (int i = 0; i < chk.Length; i++)
|
||||
|
|
@ -97,34 +97,17 @@ public static void GetSuggestedRelearnMoves(this LegalityAnalysis legal, Span<us
|
|||
continue;
|
||||
|
||||
var move = legal.Entity.GetMove(i);
|
||||
if (!dn.CanBeDexNavMove(move))
|
||||
continue;
|
||||
moves.Clear();
|
||||
moves[0] = move;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc is EncounterSlot8b { IsUnderground: true } ug)
|
||||
{
|
||||
var chk = legal.Info.Moves;
|
||||
for (int i = 0; i < chk.Length; i++)
|
||||
{
|
||||
if (!chk[i].ShouldBeInRelearnMoves())
|
||||
continue;
|
||||
|
||||
var move = legal.Entity.GetMove(i);
|
||||
if (!ug.CanBeUndergroundMove(move))
|
||||
if (!bonus.IsMoveBonus(move))
|
||||
continue;
|
||||
moves.Clear();
|
||||
moves[0] = move;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ug.GetBaseEggMove(out var any))
|
||||
if (bonus.IsMoveBonusRequired && bonus.TryGetRandomMoveBonus(out var bonusMove))
|
||||
{
|
||||
moves.Clear();
|
||||
moves[0] = any;
|
||||
moves[0] = bonusMove;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -432,10 +432,8 @@ private static bool HasAllNeededMovesSlot(ReadOnlySpan<ushort> needs, IEncounter
|
|||
{
|
||||
if (slot is IMoveset m)
|
||||
return m.Moves.ContainsAll(needs);
|
||||
if (needs.Length == 1 && slot is EncounterSlot6AO dn)
|
||||
return dn.CanDexNav && dn.CanBeDexNavMove(needs[0]);
|
||||
if (needs.Length == 1 && slot is EncounterSlot8b ug)
|
||||
return ug.IsUnderground && ug.CanBeUndergroundMove(needs[0]);
|
||||
if (needs.Length == 1 && slot is ISingleMoveBonus bonus)
|
||||
return bonus is { IsMoveBonusPossible: true, IsMoveBonusRequired: true } && bonus.IsMoveBonus(needs[0]);
|
||||
if (slot.Generation <= 2)
|
||||
return HasAllNeededMovesEncounter2(needs, slot);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace PKHeX.Core;
|
|||
/// Encounter Slot found in <see cref="GameVersion.ORAS"/>.
|
||||
/// </summary>
|
||||
public sealed record EncounterSlot6AO(EncounterArea6AO Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax)
|
||||
: IEncounterable, IEncounterMatch, IEncounterConvertible<PK6>, IEncounterFormRandom, IEncounterDownlevel
|
||||
: IEncounterable, IEncounterMatch, IEncounterConvertible<PK6>, IEncounterFormRandom, IEncounterDownlevel, ISingleMoveBonus
|
||||
{
|
||||
public byte Generation => 6;
|
||||
public EntityContext Context => EntityContext.Gen6;
|
||||
|
|
@ -24,18 +24,25 @@ public sealed record EncounterSlot6AO(EncounterArea6AO Parent, ushort Species, b
|
|||
public ushort Location => Parent.Location;
|
||||
public SlotType6 Type => Parent.Type;
|
||||
public bool CanDexNav => Type != Rock_Smash;
|
||||
|
||||
/// <summary>
|
||||
/// DexNav encounters can provide a move bonus.
|
||||
/// </summary>
|
||||
public bool IsMoveBonusPossible => CanDexNav;
|
||||
public bool IsMoveBonusRequired => false;
|
||||
|
||||
public bool IsHorde => Type == Horde;
|
||||
|
||||
private HiddenAbilityPermission IsHiddenAbilitySlot() => CanDexNav || IsHorde ? HiddenAbilityPermission.Possible : HiddenAbilityPermission.Never;
|
||||
private HiddenAbilityPermission IsHiddenAbilitySlot() => IsMoveBonusPossible || IsHorde ? HiddenAbilityPermission.Possible : HiddenAbilityPermission.Never;
|
||||
|
||||
private ReadOnlySpan<ushort> GetDexNavMoves()
|
||||
public ReadOnlySpan<ushort> GetMoveBonusPossible()
|
||||
{
|
||||
var et = EvolutionTree.Evolves6;
|
||||
var baby = et.GetBaseSpeciesForm(Species, Form);
|
||||
return LearnSource6AO.Instance.GetEggMoves(baby.Species, baby.Form);
|
||||
}
|
||||
|
||||
public bool CanBeDexNavMove(ushort move) => GetDexNavMoves().Contains(move);
|
||||
public bool IsMoveBonus(ushort move) => GetMoveBonusPossible().Contains(move);
|
||||
|
||||
public AbilityPermission Ability => IsHiddenAbilitySlot() switch
|
||||
{
|
||||
|
|
@ -85,9 +92,9 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
|
||||
SetPINGA(pk, criteria, pi);
|
||||
EncounterUtil.SetEncounterMoves(pk, Version, LevelMin);
|
||||
if (CanDexNav)
|
||||
if (IsMoveBonusPossible)
|
||||
{
|
||||
var eggMoves = GetDexNavMoves();
|
||||
var eggMoves = GetMoveBonusPossible();
|
||||
if (eggMoves.Length != 0)
|
||||
pk.RelearnMove1 = eggMoves[Util.Rand.Next(eggMoves.Length)];
|
||||
}
|
||||
|
|
@ -114,6 +121,18 @@ private void SetPINGA(PK6 pk, in EncounterCriteria criteria, PersonalInfo6AO pi)
|
|||
pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability));
|
||||
criteria.SetRandomIVs(pk);
|
||||
}
|
||||
|
||||
public bool TryGetRandomMoveBonus(out ushort move)
|
||||
{
|
||||
var moves = GetMoveBonusPossible();
|
||||
if (moves.Length == 0)
|
||||
{
|
||||
move = 0;
|
||||
return false;
|
||||
}
|
||||
move = moves[Util.Rand.Next(moves.Length)];
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Matching
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace PKHeX.Core;
|
|||
/// Encounter Slot found in <see cref="EntityContext.Gen8b"/>.
|
||||
/// </summary>
|
||||
public sealed record EncounterSlot8b(EncounterArea8b Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax)
|
||||
: IEncounterable, IEncounterMatch, IEncounterConvertible<PB8>
|
||||
: IEncounterable, IEncounterMatch, IEncounterConvertible<PB8>, ISingleMoveBonus
|
||||
{
|
||||
public byte Generation => 8;
|
||||
public EntityContext Context => EntityContext.Gen8b;
|
||||
|
|
@ -16,6 +16,13 @@ public sealed record EncounterSlot8b(EncounterArea8b Parent, ushort Species, byt
|
|||
public bool IsShiny => false;
|
||||
public ushort EggLocation => 0;
|
||||
public bool IsUnderground => Locations8b.IsUnderground(Parent.Location);
|
||||
|
||||
/// <summary>
|
||||
/// Each Pokémon also has one of their Egg Moves when you catch them in the Underground, provided they have any Egg Moves to begin with.
|
||||
/// </summary>
|
||||
public bool IsMoveBonusPossible => IsUnderground;
|
||||
public bool IsMoveBonusRequired => true;
|
||||
|
||||
public bool IsMarsh => Locations8b.IsMarsh(Parent.Location);
|
||||
public Ball FixedBall => GetRequiredBall();
|
||||
private Ball GetRequiredBall(Ball fallback = Ball.None) => IsMarsh ? Ball.Safari : fallback;
|
||||
|
|
@ -26,7 +33,7 @@ public sealed record EncounterSlot8b(EncounterArea8b Parent, ushort Species, byt
|
|||
public ushort Location => Parent.Location;
|
||||
public SlotType8b Type => Parent.Type;
|
||||
|
||||
public bool CanUseRadar => Type is Grass && !IsUnderground && !IsMarsh && CanUseRadarOverworld(Location);
|
||||
public bool CanUseRadar => Type is Grass && !IsMoveBonusPossible && !IsMarsh && CanUseRadarOverworld(Location);
|
||||
|
||||
private static bool CanUseRadarOverworld(ushort location) => location switch
|
||||
{
|
||||
|
|
@ -87,7 +94,7 @@ public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
};
|
||||
SetPINGA(pk, criteria, pi);
|
||||
EncounterUtil.SetEncounterMoves(pk, Version, LevelMin);
|
||||
if (IsUnderground && GetBaseEggMove(out var move1, pi))
|
||||
if (IsMoveBonusPossible && TryGetRandomMoveBonus(out var move1))
|
||||
pk.RelearnMove1 = move1;
|
||||
pk.ResetPartyStats();
|
||||
return pk;
|
||||
|
|
@ -107,12 +114,17 @@ private void SetPINGA(PB8 pk, in EncounterCriteria criteria, PersonalInfo8BDSP p
|
|||
pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd);
|
||||
}
|
||||
|
||||
public bool GetBaseEggMove(out ushort move) => GetBaseEggMove(out move, PersonalTable.BDSP[Species, Form]);
|
||||
|
||||
private static bool GetBaseEggMove(out ushort move, PersonalInfo8BDSP pi)
|
||||
public ReadOnlySpan<ushort> GetMoveBonusPossible()
|
||||
{
|
||||
var species = pi.HatchSpecies;
|
||||
var baseEgg = LearnSource8BDSP.Instance.GetEggMoves(species, 0);
|
||||
var et = PersonalTable.BDSP;
|
||||
var sf = et.GetFormEntry(Species, Form);
|
||||
var species = sf.HatchSpecies;
|
||||
return LearnSource8BDSP.Instance.GetEggMoves(species, 0);
|
||||
}
|
||||
|
||||
public bool TryGetRandomMoveBonus(out ushort move)
|
||||
{
|
||||
var baseEgg = GetMoveBonusPossible();
|
||||
if (baseEgg.Length == 0)
|
||||
{
|
||||
move = 0;
|
||||
|
|
@ -176,15 +188,10 @@ public EncounterMatchRating GetMatchRating(PKM pk)
|
|||
_ => false,
|
||||
};
|
||||
|
||||
public bool CanBeUndergroundMove(ushort move)
|
||||
public bool IsMoveBonus(ushort move)
|
||||
{
|
||||
var et = PersonalTable.BDSP;
|
||||
var sf = et.GetFormEntry(Species, Form);
|
||||
var species = sf.HatchSpecies;
|
||||
var baseEgg = LearnSource8BDSP.Instance.GetEggMoves(species, 0);
|
||||
if (baseEgg.Length == 0)
|
||||
return move == 0;
|
||||
return baseEgg.Contains(move);
|
||||
var moves = GetMoveBonusPossible();
|
||||
return (moves.Length == 0 && move == 0) || moves.Contains(move);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for encounter objects that conditionally provide a special extra move.
|
||||
/// </summary>
|
||||
public interface ISingleMoveBonus
|
||||
{
|
||||
bool IsMoveBonusPossible { get; }
|
||||
ReadOnlySpan<ushort> GetMoveBonusPossible();
|
||||
bool IsMoveBonus(ushort move);
|
||||
|
||||
bool IsMoveBonusRequired { get; }
|
||||
bool TryGetRandomMoveBonus(out ushort move);
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ public sealed class LearnGroup6 : ILearnGroup
|
|||
{
|
||||
if (enc is EncounterEgg6 egg)
|
||||
CheckEncounterMoves(result, current, egg);
|
||||
else if (enc is EncounterSlot6AO { CanDexNav: true } dexnav && pk.IsOriginalMovesetDeleted())
|
||||
else if (enc is EncounterSlot6AO { IsMoveBonusPossible: true } dexnav && pk.IsOriginalMovesetDeleted())
|
||||
CheckDexNavMoves(result, current, dexnav);
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ private static void CheckDexNavMoves(Span<MoveResult> result, ReadOnlySpan<ushor
|
|||
if (result[i].Valid)
|
||||
continue;
|
||||
var move = current[i];
|
||||
if (!dexnav.CanBeDexNavMove(move))
|
||||
if (!dexnav.IsMoveBonus(move))
|
||||
continue;
|
||||
result[i] = new(new(LearnMethod.Encounter, LearnEnvironment.ORAS), Generation: Generation);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -16,10 +16,8 @@ public static void Verify(Span<MoveResult> result, IEncounterTemplate enc, PKM p
|
|||
VerifyRelearnSpecifiedMoveset(pk, x, result);
|
||||
else if (enc is IEncounterEgg e)
|
||||
VerifyEggMoveset(e, result, pk);
|
||||
else if (enc is EncounterSlot6AO { CanDexNav: true } z && pk.RelearnMove1 != 0)
|
||||
VerifyRelearnDexNav(pk, result, z);
|
||||
else if (enc is EncounterSlot8b { IsUnderground: true } u)
|
||||
VerifyRelearnUnderground(pk, result, u);
|
||||
else if (enc is ISingleMoveBonus { IsMoveBonusPossible: true } z && (z.IsMoveBonusRequired || pk.RelearnMove1 != 0))
|
||||
VerifyRelearnBonusMove(pk, result, z);
|
||||
else
|
||||
VerifyRelearnNone(pk, result);
|
||||
}
|
||||
|
|
@ -44,26 +42,15 @@ private static MoveResult ParseExpect(ushort move, ushort expect = 0)
|
|||
return MoveResult.Relearn;
|
||||
}
|
||||
|
||||
private static void VerifyRelearnDexNav(PKM pk, Span<MoveResult> result, EncounterSlot6AO slot)
|
||||
private static void VerifyRelearnBonusMove(PKM pk, Span<MoveResult> result, ISingleMoveBonus slot)
|
||||
{
|
||||
// Only has one relearn move from the encounter. Every other relearn move must be empty.
|
||||
result[3] = ParseExpect(pk.RelearnMove4);
|
||||
result[2] = ParseExpect(pk.RelearnMove3);
|
||||
result[1] = ParseExpect(pk.RelearnMove2);
|
||||
|
||||
// DexNav Pokémon can have 1 random egg move as a relearn move.
|
||||
result[0] = slot.CanBeDexNavMove(pk.RelearnMove1) ? MoveResult.Relearn : MoveResult.Unobtainable(); // DexNav
|
||||
}
|
||||
|
||||
private static void VerifyRelearnUnderground(PKM pk, Span<MoveResult> result, EncounterSlot8b slot)
|
||||
{
|
||||
// Only has one relearn move from the encounter. Every other relearn move must be empty.
|
||||
result[3] = ParseExpect(pk.RelearnMove4);
|
||||
result[2] = ParseExpect(pk.RelearnMove3);
|
||||
result[1] = ParseExpect(pk.RelearnMove2);
|
||||
|
||||
// Underground Pokémon can have 1 random egg move as a relearn move.
|
||||
result[0] = slot.CanBeUndergroundMove(pk.RelearnMove1) ? MoveResult.Relearn : MoveResult.Unobtainable(); // Underground
|
||||
// 1 random egg move as a relearn move.
|
||||
result[0] = slot.IsMoveBonus(pk.RelearnMove1) ? MoveResult.Relearn : MoveResult.Unobtainable();
|
||||
}
|
||||
|
||||
private static void VerifyRelearnNone(PKM pk, Span<MoveResult> result)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user