Misc fixes

Simplify HM memory check (bit permission superset, just check directly)
Disallow BestFriends & Effort on PA8 exclusives
PA8 techrecord permits none.
This commit is contained in:
Kurt 2022-06-02 20:05:27 -07:00
parent 978be73b9a
commit df02532697
5 changed files with 33 additions and 25 deletions

View file

@ -33,9 +33,6 @@ namespace PKHeX.Core
/// <param name="moves">Moves to set flags for. If a move is not a Technical Record, it is skipped.</param>
public static void SetRecordFlags(this ITechRecord8 pk, IEnumerable<int> moves)
{
if (pk is PA8)
return;
var permit = pk.TechRecordPermitFlags;
var moveIDs = pk.TechRecordPermitIndexes;
if (permit.Length != moveIDs.Length)

View file

@ -24,18 +24,15 @@ namespace PKHeX.Core
62, // {0} saw itself in a mirror in a mirror cave that it went to with {1}. {4} that {3}.
};
internal static readonly int[][] MoveSpecificMemories =
internal static readonly byte[] MoveSpecificMemoryHM = // Ordered by HM index for bitflag checks.
{
new[] {
20, // {0} surfed across the water, carrying {1} on its back. {4} that {3}.
24, // {0} flew, carrying {1} on its back, to {2}. {4} that {3}.
35, // {0} proudly used Strength at {1}s instruction in... {2}. {4} that {3}.
36, // {0} proudly used Cut at {1}s instruction in... {2}. {4} that {3}.
37, // {0} shattered rocks to its hearts content at {1}s instruction in... {2}. {4} that {3}.
38, // {0} used Waterfall while carrying {1} on its back in... {2}. {4} that {3}.
69, // {1} asked {0} to dive. Down it went, deep into the ocean, to explore the bottom of the sea. {4} that {3}.
},
new[] { 57, 19, 70, 15, 249, 127, 291}, // Move IDs
36, // {0} proudly used Cut at {1}s instruction in... {2}. {4} that {3}.
24, // {0} flew, carrying {1} on its back, to {2}. {4} that {3}.
20, // {0} surfed across the water, carrying {1} on its back. {4} that {3}.
35, // {0} proudly used Strength at {1}s instruction in... {2}. {4} that {3}.
38, // {0} used Waterfall while carrying {1} on its back in... {2}. {4} that {3}.
37, // {0} shattered rocks to its hearts content at {1}s instruction in... {2}. {4} that {3}.
69, // {1} asked {0} to dive. Down it went, deep into the ocean, to explore the bottom of the sea. {4} that {3}.
};
/// <summary>

View file

@ -37,15 +37,19 @@ namespace PKHeX.Core
var memory = MemoryVariableSet.Read((ITrainerMemories)pkm, handler);
// Actionable HM moves
int matchingMoveMemory = Array.IndexOf(MemoryContext6.MoveSpecificMemories[0], memory.MemoryID);
if (matchingMoveMemory != -1)
int hmIndex = Array.IndexOf(MemoryContext6.MoveSpecificMemoryHM, memory.MemoryID);
if (hmIndex != -1)
{
if (gen != 6) // Gen8 has no HMs, so this memory can never exist.
return GetInvalid(string.Format(LMemoryArgBadMove, memory.Handler));
if (pkm.Species != (int)Species.Smeargle)
{
if (!GetCanLearnMachineMove(pkm, info.EvoChainsAllGens[gen], MemoryContext6.MoveSpecificMemories[1][matchingMoveMemory], 6))
// All AO hidden machine permissions are super-sets of Gen 3-5 games.
// Don't need to check the move history -- a learned HM in a prior game can still be learned in Gen6.
var evos = info.EvoChainsAllGens.Gen6;
var indexLearn = Array.FindIndex(evos, z => PersonalTable.AO.GetFormEntry(z.Species, 0).TMHM[100 + hmIndex]);
if (indexLearn == -1)
return GetInvalid(string.Format(LMemoryArgBadMove, memory.Handler));
}
}

View file

@ -161,12 +161,8 @@ namespace PKHeX.Core
yield return new RibbonResult(nameof(s6.RibbonCountMemoryBattle));
}
// Gen8+ replaced with Max Friendship. Gen6/7 uses affection.
if (pkm is IAffection a && s6.RibbonBestFriends) // can't lower affection
{
if (a.OT_Affection < 255 && pkm.IsUntraded)
yield return new RibbonResult(nameof(s6.RibbonBestFriends));
}
if (s6.RibbonBestFriends && !IsRibbonValidBestFriend(pkm, evos, gen))
yield return new RibbonResult(nameof(IRibbonSetCommon6.RibbonBestFriends));
}
if (pkm is IRibbonSetCommon7 s7)
{
@ -181,7 +177,7 @@ namespace PKHeX.Core
yield return new RibbonResult(nameof(s3.RibbonChampionG3)); // RSE HoF
if (s3.RibbonArtist && gen != 3)
yield return new RibbonResult(nameof(s3.RibbonArtist)); // RSE Master Rank Portrait
if (s3.RibbonEffort && gen == 5 && pkm.Format == 5) // unobtainable in Gen 5
if (s3.RibbonEffort && !IsRibbonValidEffort(pkm, evos, gen)) // unobtainable in Gen 5
yield return new RibbonResult(nameof(s3.RibbonEffort));
}
if (pkm is IRibbonSetCommon8 s8)
@ -193,6 +189,20 @@ namespace PKHeX.Core
}
}
private static bool IsRibbonValidEffort(PKM pkm, EvolutionHistory evos, int gen) => gen switch
{
5 when pkm.Format == 5 => false,
8 when !pkm.HasVisitedSWSH(evos.Gen8) && !pkm.HasVisitedBDSP(evos.Gen8b) => false,
_ => true,
};
private static bool IsRibbonValidBestFriend(PKM pkm, EvolutionHistory evos, int gen) => gen switch
{
< 7 when pkm is { IsUntraded: true } and IAffection { OT_Affection: < 255 } => false, // Gen6/7 uses affection. Can't lower it on OT!
8 when !pkm.HasVisitedSWSH(evos.Gen8) && !pkm.HasVisitedBDSP(evos.Gen8b) => false, // Gen8+ replaced with Max Friendship.
_ => true,
};
private static IEnumerable<RibbonResult> GetMissingContestRibbons(IReadOnlyList<bool> bits, IReadOnlyList<string> names)
{
for (int i = 0; i < bits.Count; i += 4)

View file

@ -57,7 +57,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset,
}
// Simple Generated Attributes
public ReadOnlySpan<bool> TechRecordPermitFlags => PersonalInfo.TMHM.AsSpan(PersonalInfoSWSH.CountTM);
public ReadOnlySpan<bool> TechRecordPermitFlags => Span<bool>.Empty;
public ReadOnlySpan<int> TechRecordPermitIndexes => Legal.TMHM_SWSH.AsSpan(PersonalInfoSWSH.CountTM);
public ReadOnlySpan<bool> MoveShopPermitFlags => PersonalInfo.SpecialTutors[0];
public ReadOnlySpan<ushort> MoveShopPermitIndexes => Legal.MoveShop8_LA;