2022-08-16 04:04:30 +00:00
|
|
|
using static PKHeX.Core.RibbonIndex;
|
|
|
|
|
|
|
|
namespace PKHeX.Core;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Parsing logic for <see cref="IRibbonSetCommon6"/>.
|
|
|
|
/// </summary>
|
|
|
|
public static class RibbonVerifierCommon6
|
|
|
|
{
|
|
|
|
public static void Parse(this IRibbonSetCommon6 r, RibbonVerifierArguments args, ref RibbonResultList list)
|
|
|
|
{
|
2022-08-24 04:25:22 +00:00
|
|
|
if (r is IRibbonSetMemory6 m)
|
|
|
|
GetInvalidRibbons6Memory(m, args, ref list);
|
2022-08-16 04:04:30 +00:00
|
|
|
var pk = args.Entity;
|
|
|
|
var evos = args.History;
|
|
|
|
|
|
|
|
bool gen6 = evos.HasVisitedGen6;
|
|
|
|
bool bdsp = evos.HasVisitedBDSP;
|
|
|
|
bool kalos6 = gen6 && !(pk.IsUntraded && pk.AO) && args.Encounter is not EncounterStatic6 { Species: (int)Species.Pikachu, Form: not 0 };
|
|
|
|
bool oras6 = gen6 && !(pk.IsUntraded && pk.XY);
|
|
|
|
bool contest = oras6 || bdsp;
|
|
|
|
|
|
|
|
bool k = r.RibbonChampionKalos;
|
|
|
|
bool h = r.RibbonChampionG6Hoenn;
|
|
|
|
if (k && !kalos6)
|
|
|
|
list.Add(ChampionKalos);
|
|
|
|
if (h && !oras6)
|
|
|
|
list.Add(ChampionG6Hoenn);
|
|
|
|
if (!k && !h) // no champ ribbon, check memory.
|
|
|
|
CheckChampionMemory(args, ref list);
|
|
|
|
|
|
|
|
if (!contest)
|
|
|
|
{
|
|
|
|
FlagContest(r, ref list);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Winning a contest in Gen6 adds 20 to OT affection. Each ribbon, add 20 to our expected minimum.
|
|
|
|
if (pk is IAffection a) // False in Gen8+
|
|
|
|
FlagContestAffection(r, ref list, a.OT_Affection);
|
|
|
|
|
|
|
|
// Winning all contests grants the Contest Star ribbon.
|
|
|
|
// If we have all ribbons and the star is not present, flag it as missing.
|
|
|
|
// If we have the star and not all are present, flag it as invalid.
|
|
|
|
bool allContest = r.HasAllContestRibbons();
|
|
|
|
if (allContest != r.RibbonContestStar)
|
2022-08-18 06:47:15 +00:00
|
|
|
list.Add(ContestStar, allContest);
|
2022-08-16 04:04:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (r.RibbonBestFriends && !RibbonRules.IsRibbonValidBestFriends(args.Entity, evos, args.Encounter.Generation))
|
|
|
|
list.Add(BestFriends);
|
|
|
|
|
|
|
|
if (!gen6)
|
|
|
|
{
|
|
|
|
if (r.RibbonTraining)
|
|
|
|
list.Add(Training);
|
|
|
|
|
|
|
|
// Maison
|
|
|
|
if (r.RibbonBattlerSkillful)
|
|
|
|
list.Add(BattlerSkillful);
|
|
|
|
if (r.RibbonBattlerExpert)
|
|
|
|
list.Add(BattlerExpert);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (r.RibbonTraining && pk is ISuperTrain s && !RibbonRules.IsRibbonValidSuperTraining(s))
|
|
|
|
list.Add(Training);
|
|
|
|
|
|
|
|
// Maison
|
|
|
|
CheckMaisonRibbons(r, args, ref list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void ParseEgg(this IRibbonSetCommon6 r, ref RibbonResultList list)
|
|
|
|
{
|
|
|
|
if (r.RibbonChampionKalos)
|
|
|
|
list.Add(ChampionKalos);
|
|
|
|
if (r.RibbonChampionG6Hoenn)
|
|
|
|
list.Add(ChampionG6Hoenn);
|
|
|
|
if (r.RibbonBestFriends)
|
|
|
|
list.Add(BestFriends);
|
|
|
|
if (r.RibbonTraining)
|
|
|
|
list.Add(Training);
|
|
|
|
if (r.RibbonBattlerSkillful)
|
|
|
|
list.Add(BattlerSkillful);
|
|
|
|
if (r.RibbonBattlerExpert)
|
|
|
|
list.Add(BattlerExpert);
|
|
|
|
|
|
|
|
FlagContest(r, ref list);
|
|
|
|
}
|
|
|
|
|
2022-08-24 04:25:22 +00:00
|
|
|
private static void GetInvalidRibbons6Memory(IRibbonSetMemory6 r, RibbonVerifierArguments args, ref RibbonResultList list)
|
2022-08-16 04:04:30 +00:00
|
|
|
{
|
2022-08-31 05:49:54 +00:00
|
|
|
var format = args.Entity.Format;
|
|
|
|
(byte contest, byte battle) = RibbonRules.GetMaxMemoryCounts(args.History, args.Entity, args.Encounter);
|
|
|
|
if (!IsCountFlagValid(r.RibbonCountMemoryContest, r.HasContestMemoryRibbon, format, contest))
|
2022-08-16 04:04:30 +00:00
|
|
|
list.Add(CountMemoryContest);
|
2022-08-31 05:49:54 +00:00
|
|
|
if (!IsCountFlagValid(r.RibbonCountMemoryBattle, r.HasBattleMemoryRibbon, format, battle))
|
2022-08-16 04:04:30 +00:00
|
|
|
list.Add(CountMemoryBattle);
|
|
|
|
}
|
|
|
|
|
2022-08-31 05:49:54 +00:00
|
|
|
private static bool IsCountFlagValid(byte count, bool state, int format, byte max)
|
|
|
|
{
|
|
|
|
if (count > max)
|
|
|
|
return false;
|
|
|
|
bool expect = format >= 8 && count != 0; // Gen8+ use flag, Gen6/7 do not set it.
|
|
|
|
return state == expect;
|
|
|
|
}
|
|
|
|
|
2022-08-16 04:04:30 +00:00
|
|
|
private static void FlagContestAffection(IRibbonSetCommon6 r, ref RibbonResultList list, int current)
|
|
|
|
{
|
|
|
|
int expect = 0;
|
|
|
|
if (r.RibbonMasterCoolness && current < (expect += 20))
|
|
|
|
list.Add(MasterCoolness);
|
|
|
|
if (r.RibbonMasterBeauty && current < (expect += 20))
|
|
|
|
list.Add(MasterBeauty);
|
|
|
|
if (r.RibbonMasterCuteness && current < (expect += 20))
|
|
|
|
list.Add(MasterCuteness);
|
|
|
|
if (r.RibbonMasterCleverness && current < (expect += 20))
|
|
|
|
list.Add(MasterCleverness);
|
|
|
|
if (r.RibbonMasterToughness && current < (expect + 20))
|
|
|
|
list.Add(MasterToughness);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void FlagContest(IRibbonSetCommon6 r, ref RibbonResultList list)
|
|
|
|
{
|
|
|
|
if (r.RibbonContestStar)
|
|
|
|
list.Add(ContestStar);
|
|
|
|
if (r.RibbonMasterCoolness)
|
|
|
|
list.Add(MasterCoolness);
|
|
|
|
if (r.RibbonMasterBeauty)
|
|
|
|
list.Add(MasterBeauty);
|
|
|
|
if (r.RibbonMasterCuteness)
|
|
|
|
list.Add(MasterCuteness);
|
|
|
|
if (r.RibbonMasterCleverness)
|
|
|
|
list.Add(MasterCleverness);
|
|
|
|
if (r.RibbonMasterToughness)
|
|
|
|
list.Add(MasterToughness);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void CheckChampionMemory(RibbonVerifierArguments args, ref RibbonResultList list)
|
|
|
|
{
|
|
|
|
var pk = args.Entity;
|
|
|
|
var enc = args.Encounter;
|
|
|
|
bool hasChampMemory = GetHasGen6ChampMemory(pk, enc);
|
|
|
|
if (!hasChampMemory)
|
|
|
|
return;
|
|
|
|
|
|
|
|
var ribbon = pk.XY ? ChampionKalos : ChampionG6Hoenn;
|
|
|
|
list.Add(ribbon, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void CheckMaisonRibbons(IRibbonSetCommon6 r, RibbonVerifierArguments args, ref RibbonResultList list)
|
|
|
|
{
|
|
|
|
var pk = args.Entity;
|
|
|
|
var enc = args.Encounter;
|
|
|
|
|
|
|
|
if (!RibbonRules.IsAllowedBattleFrontier(pk.Species))
|
|
|
|
{
|
2022-09-03 15:25:12 +00:00
|
|
|
// Can get Memory without ribbon if it is in party.
|
|
|
|
if (r.RibbonBattlerSkillful)
|
2022-08-16 04:04:30 +00:00
|
|
|
list.Add(BattlerSkillful);
|
|
|
|
if (r.RibbonBattlerExpert)
|
|
|
|
list.Add(BattlerExpert);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-03 15:25:12 +00:00
|
|
|
bool hasChatelaine6Memory = GetHasGen6ChatelaineMemory(pk, enc);
|
2022-08-16 04:04:30 +00:00
|
|
|
if (!hasChatelaine6Memory)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (r.RibbonBattlerSkillful || r.RibbonBattlerExpert)
|
|
|
|
return;
|
|
|
|
|
|
|
|
list.Add(BattlerSkillful, true);
|
|
|
|
//list.Add(BattlerExpert, true); // overkill to flag both as required. One is sufficient.
|
|
|
|
}
|
|
|
|
|
|
|
|
private static bool GetHasGen6ChampMemory(PKM pk, IEncounterTemplate enc)
|
|
|
|
{
|
|
|
|
if (pk is not ITrainerMemories m)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Gen6 can get the memory with any party member when defeating the champion.
|
|
|
|
const int memChampion = 27;
|
|
|
|
return (enc.Generation == 6 && m.OT_Memory == memChampion)
|
|
|
|
|| (pk.Format < 8 && m.HT_Memory == memChampion);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static bool GetHasGen6ChatelaineMemory(PKM pk, IEncounterTemplate enc)
|
|
|
|
{
|
|
|
|
if (pk is not ITrainerMemories m)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Gen6 can get the memory on those who did not participate by being in the party with other participants.
|
|
|
|
// This includes those who cannot enter into the Maison; having memory and no ribbon.
|
|
|
|
const int memChatelaine = 30;
|
|
|
|
return (enc.Generation == 6 && m.OT_Memory == memChatelaine)
|
|
|
|
|| (pk.Format < 8 && m.HT_Memory == memChatelaine);
|
|
|
|
}
|
|
|
|
}
|