mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-03-21 17:48:28 -05:00
Rework Gen3 Event PIDIV detection & checks
Detect base algorithm (regular, regular-anti, anti, shiny) and check for sub-patterns that differ per encounter (such as OT gender). Implement PIDIV generators within the Gift3* template, remove old branches Add Table Weight detection (still need to test) for PCJP 5anniv Add PCJP GCEA campaign 1-6 templates Differentiate Mystry Mew seeds; disallow Mews that were deleted b4 cart cloning Need to double check some gen3 events (esp hadou titans), but is 99% there Thanks Sabresite, for your continued support
This commit is contained in:
parent
71c9c43eef
commit
b389cd3acd
|
|
@ -2,6 +2,7 @@
|
|||
using static PKHeX.Core.PIDType;
|
||||
using static PKHeX.Core.Shiny;
|
||||
using static PKHeX.Core.LanguageID;
|
||||
using static PKHeX.Core.GiftGender3;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
|
@ -14,236 +15,240 @@ namespace PKHeX.Core;
|
|||
/// </remarks>
|
||||
internal static class EncountersWC3
|
||||
{
|
||||
// Higher frequency of being checked/requested.
|
||||
private static readonly EncounterGift3[] Common =
|
||||
[
|
||||
new(151, 10, R) { Moves = new(001,144,000,000), Method = BACD_U, ID32 = 06930, Shiny = Never, OriginalTrainerName = "MYSTRY", OriginalTrainerGender = 3, Language = (int)English, FatefulEncounter = true }, // Mew
|
||||
new(151, 10, R) { Moves = new(001,144,000,000), Method = BACD_R, ID32 = 06930, Shiny = Never, OriginalTrainerName = "MYSTRY", OriginalTrainerGender = 3, Language = (int)English, FatefulEncounter = true }, // Mew
|
||||
new(385, 05, R) { Moves = new(273,093,156,000), Method = BACD_R, ID32 = 20043, Shiny = Random, OriginalTrainerName = "WISHMKR", OriginalTrainerGender = 0, Language = (int)English },
|
||||
new(385, 05, RS, false, met: 0) { Moves = new(273,093,156,000), Method = Channel, TID16 = 40122, Shiny = Random, OriginalTrainerName = "CHANNEL", OriginalTrainerGender = 3 },
|
||||
new(151, 10, R) { Moves = new(001,144,000,000), Method = BACD_M, ID32 = 06930, Shiny = Never, OriginalTrainerName = "MYSTRY", OriginalTrainerGender = RandD3, Language = (int)English, FatefulEncounter = true }, // Mew
|
||||
new(385, 05, R) { Moves = new(273,093,156,000), Method = BACD_R, ID32 = 20043, Shiny = Random, OriginalTrainerName = "WISHMKR", OriginalTrainerGender = Only0, Language = (int)English },
|
||||
new(385, 05, RS, false, met: 0) { Moves = new(273,093,156,000), Method = Channel, TID16 = 40122, Shiny = Random, OriginalTrainerName = "CHANNEL", OriginalTrainerGender = RandAlgo },
|
||||
];
|
||||
|
||||
private static readonly EncounterGift3[] Japan =
|
||||
[
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Method = BACD_R, ID32 = 30719, Shiny = Never, OriginalTrainerName = "ネガイボシ", OriginalTrainerGender = 0, Language = (int)Japanese }, // Negai Boshi Jirachi
|
||||
new(385, 05, RS){ Moves = new(001,144,000,000), Method = BACD_U_AX, ID32 = 30719, Shiny = Never, OriginalTrainerName = "ネガイボシ", OriginalTrainerGender = 3, Language = (int)Japanese }, // Negai Boshi Jirachi (Match Recipient)
|
||||
new(263, 05, S) { Moves = new(033,045,039,000), Method = BACD_R_S, ID32 = 21121, Shiny = Always, OriginalTrainerName = "ルビー", OriginalTrainerGender = 1, Language = (int)Japanese }, // Berry Fix Ruby
|
||||
new(263, 05, S) { Moves = new(033,045,039,000), Method = BACD_R_S, ID32 = 21121, Shiny = Always, OriginalTrainerName = "サファイア", OriginalTrainerGender = 0, Language = (int)Japanese }, // Berry Fix Sapphire
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Method = BACD_R, ID32 = 40707, Shiny = Never, OriginalTrainerName = "タナバタ", OriginalTrainerGender = 1, Language = (int)Japanese }, // Tanabata Jirachi (2004)
|
||||
new(025, 10, R) { Moves = new(019,084,039,086), Method = BACD_R, ID32 = 41205, Shiny = Never, OriginalTrainerName = "ANA", OriginalTrainerGender = 0, Language = (int)Japanese }, // ANA Pikachu
|
||||
new(052, 05, R) { Moves = new(010,045,000,000), Method = BACD_R, ID32 = 50318, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, Language = (int)Japanese }, // PokéPark Meowth
|
||||
new(025, 10, R) { Moves = new(084,045,086,057), Method = BACD_R, ID32 = 50319, Shiny = Never, OriginalTrainerName = "ヨコハマ", OriginalTrainerGender = 0, Language = (int)Japanese }, // Yokohama Pikachu
|
||||
new(151, 10, R) { Moves = new(001,144,000,000), Method = BACD_R, ID32 = 50716, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = 3, Language = (int)Japanese, FatefulEncounter = true }, // Hadou Mew
|
||||
new(025, 10, R) { Moves = new(045,039,086,019), Method = BACD_R, ID32 = 50425, Shiny = Never, OriginalTrainerName = "GW", OriginalTrainerGender = 3, Language = (int)Japanese }, // GW Pikachu
|
||||
new(025, 10, R) { Moves = new(045,039,086,019), Method = BACD_R, ID32 = 50701, Shiny = Never, OriginalTrainerName = "サッポロ", OriginalTrainerGender = 0, Language = (int)Japanese }, // Sapporo Pikachu
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Method = BACD_R, ID32 = 50707, Shiny = Never, OriginalTrainerName = "タナバタ", OriginalTrainerGender = 1, Language = (int)Japanese }, // Tanabata Jirachi (2005)
|
||||
new(375, 30, R) { Moves = new(036,093,232,287), Method = BACD_R, ID32 = 02005, Shiny = Never, OriginalTrainerName = "フェスタ", OriginalTrainerGender = 0, Language = (int)Japanese, RibbonNational = true }, // Festa Metang
|
||||
new(202, 05, R) { Moves = new(068,243,219,194), Method = BACD_R, ID32 = 50701, Shiny = Never, OriginalTrainerName = "サンデー", OriginalTrainerGender = 3, Language = (int)Japanese }, // Sunday Wobbuffet
|
||||
new(377, 40, R) { Moves = new(174,276,246,063), Method = BACD_R, ID32 = 50901, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = 3, Language = (int)Japanese }, // Regirock
|
||||
new(378, 40, R) { Moves = new(174,276,246,063), Method = BACD_R, ID32 = 50901, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = 3, Language = (int)Japanese }, // Regice
|
||||
new(379, 40, R) { Moves = new(174,276,246,063), Method = BACD_R, ID32 = 50901, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = 3, Language = (int)Japanese }, // Registeel
|
||||
new(151, 30, R) { Moves = new(001,144,005,118), Method = BACD_R, ID32 = 60510, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 3, Language = (int)Japanese, FatefulEncounter = true }, // PokéPark Mew
|
||||
new(251, 30, R) { Moves = new(215,219,246,248), Method = BACD_R, ID32 = 60623, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 3, Language = (int)Japanese }, // PokéPark Celebi
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Method = BACD_R, ID32 = 60707, Shiny = Never, OriginalTrainerName = "タナバタ", OriginalTrainerGender = 3, Language = (int)Japanese }, // Tanabata Jirachi (2006)
|
||||
new(251, 10, R) { Moves = new(073,105,215,219), Method = BACD_R, ID32 = 60720, Shiny = Never, OriginalTrainerName = "ミツリン", OriginalTrainerGender = 3, Language = (int)Japanese }, // Mitsurin Celebi (2006)
|
||||
new(385, 30, R) { Moves = new(273,094,270,156), Method = BACD_R, ID32 = 60731, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, Language = (int)Japanese }, // PokéPark Jirachi (2006)
|
||||
new(385, 30, R) { Moves = new(273,094,270,156), Method = BACD_R, ID32 = 60830, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, Language = (int)Japanese }, // PokéPark Jirachi (2006)
|
||||
new(263, 05, S) { Moves = new(033,045,039,000), Language = (int)Japanese, Method = BACD_RBCD, ID32 = 21121, Shiny = Always, OriginalTrainerName = "ルビー", OriginalTrainerGender = RandD3_1 }, // Berry Fix Ruby
|
||||
new(263, 05, S) { Moves = new(033,045,039,000), Language = (int)Japanese, Method = BACD_RBCD, ID32 = 21121, Shiny = Always, OriginalTrainerName = "サファイア", OriginalTrainerGender = RandD3_0 }, // Berry Fix Sapphire
|
||||
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Language = (int)Japanese, Method = BACD_T2, ID32 = 30719, Shiny = Never, OriginalTrainerName = "ネガイボシ", OriginalTrainerGender = Only0 }, // Negai Boshi Jirachi
|
||||
new(385, 05, RS){ Moves = new(001,144,000,000), Language = (int)Japanese, Method = BACD_U_AX, ID32 = 30719, Shiny = Never, OriginalTrainerName = "ネガイボシ", OriginalTrainerGender = Recipient }, // Negai Boshi Jirachi (Match Recipient)
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Language = (int)Japanese, Method = BACD_R_A, ID32 = 40707, Shiny = Never, OriginalTrainerName = "タナバタ", OriginalTrainerGender = Only1 }, // Tanabata Jirachi (2004)
|
||||
new(025, 10, R) { Moves = new(019,084,039,086), Language = (int)Japanese, Method = BACD_R_A, ID32 = 41205, Shiny = Never, OriginalTrainerName = "ANA", OriginalTrainerGender = Only0 }, // ANA Pikachu
|
||||
new(052, 05, R) { Moves = new(010,045,000,000), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50318, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0 }, // PokéPark Meowth
|
||||
new(025, 10, R) { Moves = new(084,045,086,057), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50319, Shiny = Never, OriginalTrainerName = "ヨコハマ", OriginalTrainerGender = Only0 }, // Yokohama Pikachu
|
||||
new(151, 10, R) { Moves = new(001,144,000,000), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50716, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = RandD3, FatefulEncounter = true }, // Hadou Mew
|
||||
new(025, 10, R) { Moves = new(045,039,086,019), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50425, Shiny = Never, OriginalTrainerName = "GW", OriginalTrainerGender = RandS3 }, // GW Pikachu
|
||||
new(025, 10, R) { Moves = new(045,039,086,019), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50701, Shiny = Never, OriginalTrainerName = "サッポロ", OriginalTrainerGender = Only0 }, // Sapporo Pikachu
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50707, Shiny = Never, OriginalTrainerName = "タナバタ", OriginalTrainerGender = Only1 }, // Tanabata Jirachi (2005)
|
||||
new(375, 30, R) { Moves = new(036,093,232,287), Language = (int)Japanese, Method = BACD_R_A, ID32 = 02005, Shiny = Never, OriginalTrainerName = "フェスタ", OriginalTrainerGender = Only0, RibbonNational = true }, // Festa Metang
|
||||
new(202, 05, R) { Moves = new(068,243,219,194), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50701, Shiny = Never, OriginalTrainerName = "サンデー", OriginalTrainerGender = RandS3 }, // Sunday Wobbuffet
|
||||
new(377, 40, R) { Moves = new(174,276,246,063), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50901, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = RandSG15 }, // Regirock
|
||||
new(378, 40, R) { Moves = new(174,276,246,063), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50901, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = RandSG15 }, // Regice
|
||||
new(379, 40, R) { Moves = new(174,276,246,063), Language = (int)Japanese, Method = BACD_R_A, ID32 = 50901, Shiny = Never, OriginalTrainerName = "ハドウ", OriginalTrainerGender = RandSG15 }, // Registeel
|
||||
new(151, 30, R) { Moves = new(001,144,005,118), Language = (int)Japanese, Method = BACD_R_A, ID32 = 60510, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = RandD3, FatefulEncounter = true }, // PokéPark Mew
|
||||
new(251, 30, R) { Moves = new(215,219,246,248), Language = (int)Japanese, Method = BACD_R_A, ID32 = 60623, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = RandS7 }, // PokéPark Celebi
|
||||
new(385, 05, R) { Moves = new(001,144,000,000), Language = (int)Japanese, Method = BACD_R_A, ID32 = 60707, Shiny = Never, OriginalTrainerName = "タナバタ", OriginalTrainerGender = RandS7 }, // Tanabata Jirachi (2006)
|
||||
new(251, 10, R) { Moves = new(073,105,215,219), Language = (int)Japanese, Method = BACD_R_A, ID32 = 60720, Shiny = Never, OriginalTrainerName = "ミツリン", OriginalTrainerGender = RandS7 }, // Mitsurin Celebi (2006)
|
||||
new(385, 30, R) { Moves = new(273,094,270,156), Language = (int)Japanese, Method = BACD_R_A, ID32 = 60731, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = RandD3 }, // PokéPark Jirachi (2006)
|
||||
new(385, 30, R) { Moves = new(273,094,270,156), Language = (int)Japanese, Method = BACD_R_A, ID32 = 60830, Shiny = Never, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = RandD3 }, // PokéPark Jirachi (2006)
|
||||
];
|
||||
|
||||
private static readonly EncounterGift3[] International =
|
||||
[
|
||||
// EBGames/GameStop (March 1, 2004, to April 22, 2007), also via multi-game discs
|
||||
new(263, 5, S) { Moves = new(033,045,039,000), Method = BACD_R_S, ID32 = 30317, Shiny = Always, OriginalTrainerName = "RUBY", OriginalTrainerGender = 1, Language = (int)English },
|
||||
new(263, 5, S) { Moves = new(033,045,039,000), Method = BACD_R_S, ID32 = 30317, Shiny = Always, OriginalTrainerName = "SAPHIRE", OriginalTrainerGender = 0, Language = (int)English },
|
||||
new(263, 5, S) { Moves = new(033,045,039,000), Method = BACD_RBCD, ID32 = 30317, Shiny = Always, OriginalTrainerName = "RUBY", OriginalTrainerGender = RandD3_1, Language = (int)English }, // Berry Fix Ruby
|
||||
new(263, 5, S) { Moves = new(033,045,039,000), Method = BACD_RBCD, ID32 = 30317, Shiny = Always, OriginalTrainerName = "SAPHIRE", OriginalTrainerGender = RandD3_0, Language = (int)English }, // Berry Fix Sapphire
|
||||
|
||||
// English
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)English }, // Latios
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Latios
|
||||
|
||||
// French
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = 3, Language = (int)French }, // Latios
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNIV", OriginalTrainerGender = RandS7, Language = (int)French }, // Latios
|
||||
|
||||
// German
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = 3, Language = (int)German }, // Latios
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10JAHRE", OriginalTrainerGender = RandS7, Language = (int)German }, // Latios
|
||||
|
||||
// Italian
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = 3, Language = (int)Italian }, // Latios
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANNI", OriginalTrainerGender = RandS7, Language = (int)Italian }, // Latios
|
||||
|
||||
// Spanish
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = 3, Language = (int)Spanish }, // Latios
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Charizard
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Pikachu
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Articuno
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Suicune
|
||||
new(249, 70, R) { Moves = new(105,056,240,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Lugia
|
||||
new(250, 70, R) { Moves = new(105,126,241,129), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Ho-Oh
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R_A, ID32 = 06227, Shiny = Never, OriginalTrainerName = "10ANIV", OriginalTrainerGender = RandS7, Language = (int)Spanish }, // Latios
|
||||
|
||||
// Aura Mew
|
||||
new(151, 10, R) { Moves = new(001,144,000,000), Method = BACD_R, ID32 = 20078, Shiny = Never, OriginalTrainerName = "Aura", OriginalTrainerGender = 3, FatefulEncounter = true }, // Mew
|
||||
new(151, 10, R) { Moves = new(001,144,000,000), Method = BACD_R_A, ID32 = 20078, Shiny = Never, OriginalTrainerName = "Aura", OriginalTrainerGender = RandS7, FatefulEncounter = true }, // Mew
|
||||
|
||||
// English Events
|
||||
new(375, 30, R) { Moves = new(036,093,232,287), Method = BACD_R, ID32 = 02005, Shiny = Never, OriginalTrainerName = "ROCKS", OriginalTrainerGender = 0, Language = (int)English, RibbonNational = true }, // Metang
|
||||
new(386, 70, R) { Moves = new(322,105,354,063), Method = BACD_R, ID32 = 28606, Shiny = Never, OriginalTrainerName = "DOEL", OriginalTrainerGender = 3, Language = (int)English, FatefulEncounter = true }, // Deoxys
|
||||
new(386, 70, R) { Moves = new(322,105,354,063), Method = BACD_R, ID32 = 00010, Shiny = Never, OriginalTrainerName = "SPACE C", OriginalTrainerGender = 3, Language = (int)English, FatefulEncounter = true }, // Deoxys
|
||||
new(375, 30, R) { Moves = new(036,093,232,287), Method = BACD_R_A, ID32 = 02005, Shiny = Never, OriginalTrainerName = "ROCKS", OriginalTrainerGender = Only0, Language = (int)English, RibbonNational = true }, // Metang
|
||||
new(386, 70, R) { Moves = new(322,105,354,063), Method = BACD_R_A, ID32 = 28606, Shiny = Never, OriginalTrainerName = "DOEL", OriginalTrainerGender = RandS7, Language = (int)English, FatefulEncounter = true }, // Deoxys
|
||||
new(386, 70, R) { Moves = new(322,105,354,063), Method = BACD_R_A, ID32 = 00010, Shiny = Never, OriginalTrainerName = "SPACE C", OriginalTrainerGender = RandS7, Language = (int)English, FatefulEncounter = true }, // Deoxys
|
||||
|
||||
// Party of the Decade
|
||||
new(001, 70, R) { Moves = new(230,074,076,235), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Bulbasaur
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Charizard
|
||||
new(009, 70, R) { Moves = new(182,240,130,056), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Blastoise
|
||||
new(025, 70, R) { Moves = new(085,087,113,019), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Pikachu (Fly)
|
||||
new(065, 70, R) { Moves = new(248,347,094,271), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Alakazam
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Articuno
|
||||
new(145, 70, R) { Moves = new(097,197,065,268), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Zapdos
|
||||
new(146, 70, R) { Moves = new(097,203,053,219), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Moltres
|
||||
new(149, 70, R) { Moves = new(097,219,017,200), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Dragonite
|
||||
new(157, 70, R) { Moves = new(098,172,129,053), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Typhlosion
|
||||
new(196, 70, R) { Moves = new(060,244,094,234), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Espeon
|
||||
new(197, 70, R) { Moves = new(185,212,103,236), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Umbreon
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Suicune
|
||||
new(248, 70, R) { Moves = new(037,184,242,089), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Tyranitar
|
||||
new(257, 70, R) { Moves = new(299,163,119,327), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Blaziken
|
||||
new(359, 70, R) { Moves = new(104,163,248,195), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Absol
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = 3, Language = (int)English }, // Latios
|
||||
new(001, 70, R) { Moves = new(230,074,076,235), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Bulbasaur
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Charizard
|
||||
new(009, 70, R) { Moves = new(182,240,130,056), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Blastoise
|
||||
new(025, 70, R) { Moves = new(085,087,113,019), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Pikachu (Fly)
|
||||
new(065, 70, R) { Moves = new(248,347,094,271), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Alakazam
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Articuno
|
||||
new(145, 70, R) { Moves = new(097,197,065,268), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Zapdos
|
||||
new(146, 70, R) { Moves = new(097,203,053,219), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Moltres
|
||||
new(149, 70, R) { Moves = new(097,219,017,200), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Dragonite
|
||||
new(157, 70, R) { Moves = new(098,172,129,053), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Typhlosion
|
||||
new(196, 70, R) { Moves = new(060,244,094,234), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Espeon
|
||||
new(197, 70, R) { Moves = new(185,212,103,236), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Umbreon
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Suicune
|
||||
new(248, 70, R) { Moves = new(037,184,242,089), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Tyranitar
|
||||
new(257, 70, R) { Moves = new(299,163,119,327), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Blaziken
|
||||
new(359, 70, R) { Moves = new(104,163,248,195), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Absol
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R_A, ID32 = 06808, Shiny = Never, OriginalTrainerName = "10 ANIV", OriginalTrainerGender = RandS7, Language = (int)English }, // Latios
|
||||
|
||||
// Journey Across America
|
||||
new(001, 70, R) { Moves = new(230,074,076,235), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Bulbasaur
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Charizard
|
||||
new(009, 70, R) { Moves = new(182,240,130,056), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Blastoise
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Pikachu (No Fly)
|
||||
new(065, 70, R) { Moves = new(248,347,094,271), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Alakazam
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Articuno
|
||||
new(145, 70, R) { Moves = new(097,197,065,268), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Zapdos
|
||||
new(146, 70, R) { Moves = new(097,203,053,219), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Moltres
|
||||
new(149, 70, R) { Moves = new(097,219,017,200), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Dragonite
|
||||
new(157, 70, R) { Moves = new(098,172,129,053), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Typhlosion
|
||||
new(196, 70, R) { Moves = new(060,244,094,234), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Espeon
|
||||
new(197, 70, R) { Moves = new(185,212,103,236), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Umbreon
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Suicune
|
||||
new(248, 70, R) { Moves = new(037,184,242,089), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Tyranitar
|
||||
new(251, 70, R) { Moves = new(246,248,226,195), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Celebi
|
||||
new(257, 70, R) { Moves = new(299,163,119,327), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Blaziken
|
||||
new(359, 70, R) { Moves = new(104,163,248,195), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Absol
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = 3, Language = (int)English }, // Latios
|
||||
new(001, 70, R) { Moves = new(230,074,076,235), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Bulbasaur
|
||||
new(006, 70, R) { Moves = new(017,163,082,083), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Charizard
|
||||
new(009, 70, R) { Moves = new(182,240,130,056), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Blastoise
|
||||
new(025, 70, R) { Moves = new(085,097,087,113), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Pikachu (No Fly)
|
||||
new(065, 70, R) { Moves = new(248,347,094,271), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Alakazam
|
||||
new(144, 70, R) { Moves = new(097,170,058,115), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Articuno
|
||||
new(145, 70, R) { Moves = new(097,197,065,268), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Zapdos
|
||||
new(146, 70, R) { Moves = new(097,203,053,219), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Moltres
|
||||
new(149, 70, R) { Moves = new(097,219,017,200), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Dragonite
|
||||
new(157, 70, R) { Moves = new(098,172,129,053), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Typhlosion
|
||||
new(196, 70, R) { Moves = new(060,244,094,234), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Espeon
|
||||
new(197, 70, R) { Moves = new(185,212,103,236), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Umbreon
|
||||
new(243, 70, R) { Moves = new(098,209,115,242), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Raikou
|
||||
new(244, 70, R) { Moves = new(083,023,053,207), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Entei
|
||||
new(245, 70, R) { Moves = new(016,062,054,243), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Suicune
|
||||
new(248, 70, R) { Moves = new(037,184,242,089), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Tyranitar
|
||||
new(251, 70, R) { Moves = new(246,248,226,195), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Celebi
|
||||
new(257, 70, R) { Moves = new(299,163,119,327), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Blaziken
|
||||
new(359, 70, R) { Moves = new(104,163,248,195), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Absol
|
||||
new(380, 70, R) { Moves = new(296,094,105,204), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Latias
|
||||
new(381, 70, R) { Moves = new(295,094,105,349), Method = BACD_R_A, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never, OriginalTrainerGender = RandS7, Language = (int)English }, // Latios
|
||||
];
|
||||
|
||||
public const string PCJPEggTrainerName = "オヤNAME";
|
||||
private const string M2WishEggOT = "";
|
||||
|
||||
private static readonly EncounterGift3[] Eggs =
|
||||
[
|
||||
// Pokémon Box -- Recipient
|
||||
new(333, 5, Gen3, true) { Moves = new(064,045,206,000), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = 1 }, // Swablu Egg with False Swipe
|
||||
new(263, 5, Gen3, true) { Moves = new(033,045,039,245), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = 1 }, // Zigzagoon Egg with Extreme Speed
|
||||
new(300, 5, Gen3, true) { Moves = new(045,033,039,006), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = 1 }, // Skitty Egg with Pay Day
|
||||
new(172, 5, Gen3, true) { Moves = new(084,204,057,000), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = 1 }, // Pichu Egg with Surf
|
||||
new(333, 5, Gen3, true) { Moves = new(064,045,206,000), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = Only1 }, // Swablu Egg with False Swipe
|
||||
new(263, 5, Gen3, true) { Moves = new(033,045,039,245), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = Only1 }, // Zigzagoon Egg with Extreme Speed
|
||||
new(300, 5, Gen3, true) { Moves = new(045,033,039,006), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = Only1 }, // Skitty Egg with Pay Day
|
||||
new(172, 5, Gen3, true) { Moves = new(084,204,057,000), Method = BACD_U, OriginalTrainerName = "AZUSA", OriginalTrainerGender = Only1 }, // Pichu Egg with Surf
|
||||
|
||||
// PCJP - Pokémon Center 5th Anniversary Eggs (April 25 to May 18, 2003)
|
||||
new(172, 5, R, true) { Moves = new(084,204,298,000), Method = BACD_R_S, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Pichu with Teeter Dance
|
||||
new(172, 5, R, true) { Moves = new(084,204,273,000), Method = BACD_R_S, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Pichu with Wish
|
||||
new(172, 5, R, true) { Moves = new(084,204,298,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Pichu with Teeter Dance
|
||||
new(172, 5, R, true) { Moves = new(084,204,273,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Pichu with Wish
|
||||
new(280, 5, R, true) { Moves = new(045,204,000,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Ralts with Charm
|
||||
new(280, 5, R, true) { Moves = new(045,273,000,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Ralts with Wish
|
||||
new(359, 5, R, true) { Moves = new(010,043,180,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Absol with Spite
|
||||
new(359, 5, R, true) { Moves = new(010,043,273,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Absol with Wish
|
||||
new(371, 5, R, true) { Moves = new(099,044,334,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Bagon with Iron Defense
|
||||
new(371, 5, R, true) { Moves = new(099,044,273,000), Method = BACD_R, OriginalTrainerName = "オヤNAME", OriginalTrainerGender = 0 }, // Bagon with Wish
|
||||
new(172, 5, R, true) { Moves = new(084,204,298,000), Method = BACD_T3, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0, Shiny = Always }, // Pichu with Teeter Dance
|
||||
new(172, 5, R, true) { Moves = new(084,204,273,000), Method = BACD_T3, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0, Shiny = Always }, // Pichu with Wish
|
||||
new(172, 5, R, true) { Moves = new(084,204,298,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Pichu with Teeter Dance
|
||||
new(172, 5, R, true) { Moves = new(084,204,273,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Pichu with Wish
|
||||
new(280, 5, R, true) { Moves = new(045,204,000,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Ralts with Charm
|
||||
new(280, 5, R, true) { Moves = new(045,273,000,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Ralts with Wish
|
||||
new(359, 5, R, true) { Moves = new(010,043,180,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Absol with Spite
|
||||
new(359, 5, R, true) { Moves = new(010,043,273,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Absol with Wish
|
||||
new(371, 5, R, true) { Moves = new(099,044,334,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Bagon with Iron Defense
|
||||
new(371, 5, R, true) { Moves = new(099,044,273,000), Method = BACD_T2, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Bagon with Wish
|
||||
|
||||
// Wondercard gifts call the same give egg script as the Hot Springs Wynaut, but the game has a vblank interrupt between PID and IVs (potentially because the script does not lock when starting).
|
||||
// Removing the vblank interrupt via ROM patch results in the scripts yielding a Method 1 PID/IV, so hopefully it's consistent enough to assume all are just Method 2 and no splits.
|
||||
|
||||
// PCJP Egg Pokémon Present Eggs - Wondercard (March 21 to April 4, 2004)
|
||||
new(043, 5, FRLG, true) { Moves = new(071,073,000,000), Method = Method_2, FatefulEncounter = true }, // Oddish with Leech Seed
|
||||
new(052, 5, FRLG, true) { Moves = new(010,045,080,000), Method = Method_2, FatefulEncounter = true }, // Meowth with Petal Dance
|
||||
new(060, 5, FRLG, true) { Moves = new(145,186,000,000), Method = Method_2, FatefulEncounter = true }, // Poliwag with Sweet Kiss
|
||||
new(069, 5, FRLG, true) { Moves = new(022,298,000,000), Method = Method_2, FatefulEncounter = true }, // Bellsprout with Teeter Dance
|
||||
new(043, 5, FRLG, true) { Moves = new(071,073,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Oddish with Leech Seed
|
||||
new(052, 5, FRLG, true) { Moves = new(010,045,080,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Meowth with Petal Dance
|
||||
new(060, 5, FRLG, true) { Moves = new(145,186,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Poliwag with Sweet Kiss
|
||||
new(069, 5, FRLG, true) { Moves = new(022,298,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Bellsprout with Teeter Dance
|
||||
|
||||
// PCNY Wish Eggs - Wondercard (December 16, 2004, to January 2, 2005)
|
||||
new(083, 5, FRLG, true) { Moves = new(281,273,000,000), Method = Method_2, FatefulEncounter = true }, // Farfetch'd with Wish & Yawn
|
||||
new(096, 5, FRLG, true) { Moves = new(187,273,000,000), Method = Method_2, FatefulEncounter = true }, // Drowzee with Wish & Belly Drum
|
||||
new(102, 5, FRLG, true) { Moves = new(230,273,000,000), Method = Method_2, FatefulEncounter = true }, // Exeggcute with Wish & Sweet Scent
|
||||
new(108, 5, FRLG, true) { Moves = new(215,273,000,000), Method = Method_2, FatefulEncounter = true }, // Lickitung with Wish & Heal Bell
|
||||
new(113, 5, FRLG, true) { Moves = new(230,273,000,000), Method = Method_2, FatefulEncounter = true }, // Chansey with Wish & Sweet Scent
|
||||
new(115, 5, FRLG, true) { Moves = new(281,273,000,000), Method = Method_2, FatefulEncounter = true }, // Kangaskhan with Wish & Yawn
|
||||
new(083, 5, FRLG, true) { Moves = new(281,273,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Farfetch'd with Wish & Yawn
|
||||
new(096, 5, FRLG, true) { Moves = new(187,273,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Drowzee with Wish & Belly Drum
|
||||
new(102, 5, FRLG, true) { Moves = new(230,273,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Exeggcute with Wish & Sweet Scent
|
||||
new(108, 5, FRLG, true) { Moves = new(215,273,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Lickitung with Wish & Heal Bell
|
||||
new(113, 5, FRLG, true) { Moves = new(230,273,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Chansey with Wish & Sweet Scent
|
||||
new(115, 5, FRLG, true) { Moves = new(281,273,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Kangaskhan with Wish & Yawn
|
||||
|
||||
// PokéPark Eggs - Wondercard (March 12 to May 8, 2005)
|
||||
new(054, 5, EFL, true) { Moves = new(346,010,039,300), Method = Method_2, FatefulEncounter = true }, // Psyduck with Mud Sport
|
||||
new(172, 5, EFL, true) { Moves = new(084,204,266,000), Method = Method_2, FatefulEncounter = true }, // Pichu with Follow me
|
||||
new(174, 5, EFL, true) { Moves = new(047,204,111,321), Method = Method_2, FatefulEncounter = true }, // Igglybuff with Tickle
|
||||
new(222, 5, EFL, true) { Moves = new(033,300,000,000), Method = Method_2, FatefulEncounter = true }, // Corsola with Mud Sport
|
||||
new(276, 5, EFL, true) { Moves = new(064,045,116,297), Method = Method_2, FatefulEncounter = true }, // Taillow with Feather Dance
|
||||
new(283, 5, EFL, true) { Moves = new(145,300,000,000), Method = Method_2, FatefulEncounter = true }, // Surskit with Mud Sport
|
||||
new(293, 5, EFL, true) { Moves = new(001,253,298,000), Method = Method_2, FatefulEncounter = true }, // Whismur with Teeter Dance
|
||||
new(300, 5, EFL, true) { Moves = new(045,033,039,205), Method = Method_2, FatefulEncounter = true }, // Skitty with Rollout
|
||||
new(311, 5, EFL, true) { Moves = new(045,086,346,000), Method = Method_2, FatefulEncounter = true }, // Plusle with Water Sport
|
||||
new(312, 5, EFL, true) { Moves = new(045,086,300,000), Method = Method_2, FatefulEncounter = true }, // Minun with Mud Sport
|
||||
new(325, 5, EFL, true) { Moves = new(150,253,000,000), Method = Method_2, FatefulEncounter = true }, // Spoink with Uproar
|
||||
new(327, 5, EFL, true) { Moves = new(033,253,047,000), Method = Method_2, FatefulEncounter = true }, // Spinda with Sing
|
||||
new(331, 5, EFL, true) { Moves = new(040,043,071,227), Method = Method_2, FatefulEncounter = true }, // Cacnea with Encore
|
||||
new(341, 5, EFL, true) { Moves = new(145,346,000,000), Method = Method_2, FatefulEncounter = true }, // Corphish with Water Sport
|
||||
new(360, 5, EFL, true) { Moves = new(150,204,227,321), Method = Method_2, FatefulEncounter = true }, // Wynaut with Tickle
|
||||
new(054, 5, EFL, true) { Moves = new(346,010,039,300), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Psyduck with Mud Sport
|
||||
new(172, 5, EFL, true) { Moves = new(084,204,266,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Pichu with Follow me
|
||||
new(174, 5, EFL, true) { Moves = new(047,204,111,321), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Igglybuff with Tickle
|
||||
new(222, 5, EFL, true) { Moves = new(033,300,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Corsola with Mud Sport
|
||||
new(276, 5, EFL, true) { Moves = new(064,045,116,297), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Taillow with Feather Dance
|
||||
new(283, 5, EFL, true) { Moves = new(145,300,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Surskit with Mud Sport
|
||||
new(293, 5, EFL, true) { Moves = new(001,253,298,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Whismur with Teeter Dance
|
||||
new(300, 5, EFL, true) { Moves = new(045,033,039,205), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Skitty with Rollout
|
||||
new(311, 5, EFL, true) { Moves = new(045,086,346,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Plusle with Water Sport
|
||||
new(312, 5, EFL, true) { Moves = new(045,086,300,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Minun with Mud Sport
|
||||
new(325, 5, EFL, true) { Moves = new(150,253,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Spoink with Uproar
|
||||
new(327, 5, EFL, true) { Moves = new(033,253,047,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Spinda with Sing
|
||||
new(331, 5, EFL, true) { Moves = new(040,043,071,227), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Cacnea with Encore
|
||||
new(341, 5, EFL, true) { Moves = new(145,346,000,000), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Corphish with Water Sport
|
||||
new(360, 5, EFL, true) { Moves = new(150,204,227,321), Method = Method_2, FatefulEncounter = true, OriginalTrainerName = M2WishEggOT }, // Wynaut with Tickle
|
||||
|
||||
// PokéPark Eggs - DS Download Play (March 12 to May 8, 2005)
|
||||
new(054, 5, R, true, 5) { Moves = new(346,010,039,300), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Psyduck with Mud Sport
|
||||
new(172, 5, R, true, 5) { Moves = new(084,204,266,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Pichu with Follow Me
|
||||
new(174, 5, R, true, 5) { Moves = new(047,204,111,321), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Igglybuff with Tickle
|
||||
new(222, 5, R, true, 5) { Moves = new(033,300,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Corsola with Mud Sport
|
||||
new(276, 5, R, true, 5) { Moves = new(064,045,116,297), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Taillow with Feather Dance
|
||||
new(283, 5, R, true, 5) { Moves = new(145,300,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Surskit with Mud Sport
|
||||
new(293, 5, R, true, 5) { Moves = new(001,253,298,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Whismur with Teeter Dance
|
||||
new(300, 5, R, true, 5) { Moves = new(045,033,039,205), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Skitty with Rollout
|
||||
new(311, 5, R, true, 5) { Moves = new(045,086,346,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Plusle with Water Sport
|
||||
new(312, 5, R, true, 5) { Moves = new(045,086,300,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Minun with Mud Sport
|
||||
new(325, 5, R, true, 5) { Moves = new(150,253,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Spoink with Uproar
|
||||
new(327, 5, R, true, 5) { Moves = new(033,253,047,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Spinda with Sing
|
||||
new(331, 5, R, true, 5) { Moves = new(040,043,071,227), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Cacnea with Encore
|
||||
new(341, 5, R, true, 5) { Moves = new(145,346,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Corphish with Water Sport
|
||||
new(360, 5, R, true, 5) { Moves = new(150,204,227,321), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = 0, ID32 = 50318 }, // Wynaut with Tickle
|
||||
new(054, 5, R, true, 5) { Moves = new(346,010,039,300), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Psyduck with Mud Sport
|
||||
new(172, 5, R, true, 5) { Moves = new(084,204,266,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Pichu with Follow Me
|
||||
new(174, 5, R, true, 5) { Moves = new(047,204,111,321), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Igglybuff with Tickle
|
||||
new(222, 5, R, true, 5) { Moves = new(033,300,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Corsola with Mud Sport
|
||||
new(276, 5, R, true, 5) { Moves = new(064,045,116,297), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Taillow with Feather Dance
|
||||
new(283, 5, R, true, 5) { Moves = new(145,300,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Surskit with Mud Sport
|
||||
new(293, 5, R, true, 5) { Moves = new(001,253,298,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Whismur with Teeter Dance
|
||||
new(300, 5, R, true, 5) { Moves = new(045,033,039,205), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Skitty with Rollout
|
||||
new(311, 5, R, true, 5) { Moves = new(045,086,346,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Plusle with Water Sport
|
||||
new(312, 5, R, true, 5) { Moves = new(045,086,300,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Minun with Mud Sport
|
||||
new(325, 5, R, true, 5) { Moves = new(150,253,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Spoink with Uproar
|
||||
new(327, 5, R, true, 5) { Moves = new(033,253,047,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Spinda with Sing
|
||||
new(331, 5, R, true, 5) { Moves = new(040,043,071,227), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Cacnea with Encore
|
||||
new(341, 5, R, true, 5) { Moves = new(145,346,000,000), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Corphish with Water Sport
|
||||
new(360, 5, R, true, 5) { Moves = new(150,204,227,321), Method = BACD_R, OriginalTrainerName = "ポケパーク", OriginalTrainerGender = Only0, ID32 = 50318 }, // Wynaut with Tickle
|
||||
];
|
||||
|
||||
internal static readonly EncounterGift3[] Encounter_WC3 = [..Common, ..International, .. Japan, ..Eggs];
|
||||
|
||||
internal static readonly EncounterGift3NY[] PCNY = EncounterGift3NY.GetArray(EncounterUtil.Get("pcny"));
|
||||
|
||||
internal static readonly EncounterGift3JPN[] PCJP = [];
|
||||
internal static readonly EncounterGift3JPN[] PCJP = Gen3PCJP.GetArray();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public IEnumerable<IEncounterable> GetEncounters(PKM pk, EvoCriteria[] chain, Le
|
|||
foreach (var enc in iterator)
|
||||
{
|
||||
var e = enc.Encounter;
|
||||
if (!IsTypeCompatible(e, pk, info.PIDIV.Type))
|
||||
if (!IsTypeCompatible(e, pk, ref info.GetPIDIVRef()))
|
||||
{
|
||||
defer.Update(DeferralType.PIDIV, e);
|
||||
continue;
|
||||
|
|
@ -76,26 +76,6 @@ public IEnumerable<IEncounterable> GetEncounters(PKM pk, EvoCriteria[] chain, Le
|
|||
}
|
||||
if (e is not EncounterSlot3 slot)
|
||||
{
|
||||
if (e is EncounterGift3 gift)
|
||||
{
|
||||
if (gift.TID16 == 40122) // CHANNEL Jirachi
|
||||
{
|
||||
var chk = ChannelJirachi.GetPossible(info.PIDIV.OriginSeed);
|
||||
if (chk.Pattern is not ChannelJirachiRandomResult.None)
|
||||
info.PIDIV = info.PIDIV.AsEncounteredVia(new(chk.Seed, LeadRequired.None));
|
||||
else
|
||||
info.ManualFlag = EncounterYieldFlag.InvalidPIDIV;
|
||||
yield return gift;
|
||||
yield break;
|
||||
}
|
||||
if (gift.TID16 == 06930) // MYSTRY Mew
|
||||
{
|
||||
if (!MystryMew.IsValidSeed(info.PIDIV.OriginSeed))
|
||||
info.ManualFlag = EncounterYieldFlag.InvalidPIDIV;
|
||||
yield return gift;
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
yield return e;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -134,8 +114,11 @@ public IEnumerable<IEncounterable> GetEncounters(PKM pk, EvoCriteria[] chain, Le
|
|||
_ => pk.Ball is not (byte)Ball.Safari,
|
||||
};
|
||||
|
||||
private static bool IsTypeCompatible(IEncounterTemplate enc, PKM pk, PIDType type)
|
||||
private static bool IsTypeCompatible(IEncounterTemplate enc, PKM pk, ref PIDIV pidiv)
|
||||
{
|
||||
if (enc is IRandomCorrelationEvent3 revise)
|
||||
return revise.IsCompatibleReviseReset(ref pidiv, pk);
|
||||
var type = pidiv.Type;
|
||||
if (enc is IRandomCorrelation r)
|
||||
return r.IsCompatible(type, pk);
|
||||
return type == PIDType.None;
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ private bool IsMatchPartial(PKM pk)
|
|||
}
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk) => val is PIDType.CXD;
|
||||
public bool IsCompatible(PIDType type, PKM pk) => type is PIDType.CXD;
|
||||
|
||||
public PIDType GetSuggestedCorrelation() => PIDType.CXD;
|
||||
|
||||
|
|
|
|||
|
|
@ -196,11 +196,11 @@ private bool IsMatchLocation(PKM pk)
|
|||
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (IsEReader)
|
||||
return true;
|
||||
return val is PIDType.CXD;
|
||||
return type is PIDType.CXD;
|
||||
}
|
||||
|
||||
public PIDType GetSuggestedCorrelation()
|
||||
|
|
|
|||
|
|
@ -142,11 +142,11 @@ private bool IsMatchPartial(PKM pk)
|
|||
}
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (IsColoStarter)
|
||||
return val is PIDType.CXD_ColoStarter;
|
||||
return val is PIDType.CXD;
|
||||
return type is PIDType.CXD_ColoStarter;
|
||||
return type is PIDType.CXD;
|
||||
}
|
||||
|
||||
public PIDType GetSuggestedCorrelation() => PIDType.CXD;
|
||||
|
|
|
|||
|
|
@ -120,11 +120,11 @@ public EncounterMatchRating GetMatchRating(PKM pk)
|
|||
private bool IsDeferredSafari3(bool IsSafariBall) => IsSafariBall != Locations.IsSafariZoneLocation3(Location);
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (Species != (int)Core.Species.Unown)
|
||||
return val is (Method_1 or Method_2 or Method_3 or Method_4);
|
||||
return val is (Method_1_Unown or Method_2_Unown or Method_3_Unown or Method_4_Unown);
|
||||
return type is (Method_1 or Method_2 or Method_3 or Method_4);
|
||||
return type is (Method_1_Unown or Method_2_Unown or Method_3_Unown or Method_4_Unown);
|
||||
}
|
||||
|
||||
public PIDType GetSuggestedCorrelation() => Species == (int)Core.Species.Unown ? Method_1_Unown : Method_1;
|
||||
|
|
|
|||
|
|
@ -176,15 +176,15 @@ private bool IsMatchPartial(PKM pk)
|
|||
}
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
var version = pk.Version;
|
||||
if (version is GameVersion.E)
|
||||
return val is PIDType.Method_1;
|
||||
return type is PIDType.Method_1;
|
||||
if (version is GameVersion.FR or GameVersion.LG)
|
||||
return Roaming ? IsRoamerPIDIV(val, pk) : val is PIDType.Method_1;
|
||||
return Roaming ? IsRoamerPIDIV(type, pk) : type is PIDType.Method_1;
|
||||
// RS, roamer glitch && RSBox s/w emulation => method 4 available
|
||||
return Roaming ? IsRoamerPIDIV(val, pk) : val is (PIDType.Method_1 or PIDType.Method_4);
|
||||
return Roaming ? IsRoamerPIDIV(type, pk) : type is (PIDType.Method_1 or PIDType.Method_4);
|
||||
}
|
||||
|
||||
private static bool IsRoamerPIDIV(PIDType val, PKM pk)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,34 @@ public static class Gen3PCJP
|
|||
private const string Fukuoka = "フクオカ";
|
||||
private const string Sapporo = "サッポロ";
|
||||
|
||||
private static ReadOnlySpan<ushort> Distro1 => [252, 255, 258];
|
||||
private static ReadOnlySpan<ushort> Distro2 => [152, 155, 158];
|
||||
private static ReadOnlySpan<ushort> Distro3 => [023, 025, 052, 058, 069, 079, 090, 113, 115, 123, 125, 126, 128, 198, 200, 211, 215, 225, 226];
|
||||
private static ReadOnlySpan<ushort> Distro4 => [1, 4, 7];
|
||||
private static ReadOnlySpan<ushort> Distro5 => [025, 270, 273, 283, 300, 302, 303, 307, 311, 312, 315, 335, 336, 337, 338, 358];
|
||||
private static ReadOnlySpan<ushort> Distro6 => [025, 163, 179, 190, 191, 202, 204, 207, 209, 213, 216, 228, 234, 235];
|
||||
|
||||
public static EncounterGift3JPN[] GetArray()
|
||||
{
|
||||
var size = Distro1.Length + Distro2.Length + Distro3.Length + Distro4.Length + Distro5.Length + Distro6.Length;
|
||||
var arr = new EncounterGift3JPN[size];
|
||||
var i = 0;
|
||||
|
||||
AddDistro(arr, ref i, Distro1, First);
|
||||
AddDistro(arr, ref i, Distro2, Second);
|
||||
AddDistro(arr, ref i, Distro3, Third);
|
||||
AddDistro(arr, ref i, Distro4, Fourth);
|
||||
AddDistro(arr, ref i, Distro5, Fifth);
|
||||
AddDistro(arr, ref i, Distro6, Sixth);
|
||||
return arr;
|
||||
|
||||
static void AddDistro(EncounterGift3JPN[] arr, ref int i, ReadOnlySpan<ushort> Distro, Distribution3JPN dist)
|
||||
{
|
||||
foreach (var species in Distro)
|
||||
arr[i++] = new EncounterGift3JPN(species, dist);
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort GetTrainerID(this Distribution3JPN dist) => dist switch
|
||||
{
|
||||
First => 51126,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
using System;
|
||||
using static PKHeX.Core.PIDType;
|
||||
using static PKHeX.Core.CommonEvent3;
|
||||
using static PKHeX.Core.CommonEvent3Checker;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
|
@ -6,7 +9,7 @@ namespace PKHeX.Core;
|
|||
/// Generation 3 Event Gift
|
||||
/// </summary>
|
||||
public sealed class EncounterGift3 : IEncounterable, IEncounterMatch, IMoveset, IFatefulEncounterReadOnly,
|
||||
IRibbonSetEvent3, IRandomCorrelation, IFixedTrainer, IMetLevel
|
||||
IRibbonSetEvent3, IRandomCorrelationEvent3, IFixedTrainer, IMetLevel
|
||||
{
|
||||
public ushort Species { get; }
|
||||
public byte Form => 0;
|
||||
|
|
@ -16,7 +19,6 @@ public sealed class EncounterGift3 : IEncounterable, IEncounterMatch, IMoveset,
|
|||
public bool IsEgg { get; }
|
||||
|
||||
private const ushort UnspecifiedID = ushort.MaxValue;
|
||||
private const byte UnspecifiedTrainerGender = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Matched <see cref="PIDIV"/> Type
|
||||
|
|
@ -24,8 +26,8 @@ public sealed class EncounterGift3 : IEncounterable, IEncounterMatch, IMoveset,
|
|||
public required PIDType Method { get; init; }
|
||||
|
||||
public required Moveset Moves { get; init; }
|
||||
public string OriginalTrainerName { get; init; } = string.Empty;
|
||||
public byte OriginalTrainerGender { get; init; } = UnspecifiedTrainerGender;
|
||||
public required string OriginalTrainerName { get; init; }
|
||||
public GiftGender3 OriginalTrainerGender { get; init; }
|
||||
public uint ID32 { get => (uint)(SID16 << 16 | TID16); init => (SID16, TID16) = ((ushort)(value >> 16), (ushort)value); }
|
||||
public ushort TID16 { get; init; } = UnspecifiedID;
|
||||
public ushort SID16 { get; init; } = UnspecifiedID;
|
||||
|
|
@ -67,17 +69,6 @@ public EncounterGift3(ushort species, byte level, GameVersion version, bool egg,
|
|||
MetLevel = met;
|
||||
}
|
||||
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (type == Method)
|
||||
return true;
|
||||
|
||||
// forced shiny eggs, when hatched, can lose their detectable correlation.
|
||||
if (!IsEgg || pk.IsEgg)
|
||||
return false;
|
||||
return type is PIDType.BACD_R_S or PIDType.BACD_U_S;
|
||||
}
|
||||
|
||||
PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted);
|
||||
PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria);
|
||||
|
||||
|
|
@ -108,6 +99,8 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
pk.SetMoves(Moves);
|
||||
pk.SetMaximumPPCurrent(Moves);
|
||||
|
||||
// Generate PIDIV
|
||||
var seed = SetPINGA(pk, criteria, pi);
|
||||
bool hatchedEgg = IsEgg && tr.Generation != 3;
|
||||
if (hatchedEgg)
|
||||
{
|
||||
|
|
@ -115,12 +108,12 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
}
|
||||
else
|
||||
{
|
||||
pk.OriginalTrainerGender = OriginalTrainerGender != 3 ? (byte)(OriginalTrainerGender & 1): tr.Gender;
|
||||
pk.ID32 = TID16;
|
||||
pk.SID16 = SID16;
|
||||
|
||||
pk.Language = (int)GetSafeLanguage((LanguageID)tr.Language);
|
||||
pk.OriginalTrainerName = !string.IsNullOrWhiteSpace(OriginalTrainerName) ? OriginalTrainerName : tr.OT;
|
||||
pk.OriginalTrainerGender = OriginalTrainerGender == GiftGender3.Recipient ? tr.Gender : (byte)GetGender(seed);
|
||||
|
||||
if (IsEgg)
|
||||
{
|
||||
pk.IsEgg = true; // lang should be set to japanese already
|
||||
|
|
@ -131,13 +124,28 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, 3); // will be set to Egg nickname if appropriate by PK3 setter
|
||||
pk.OriginalTrainerFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
|
||||
|
||||
// Generate PIDIV
|
||||
SetPINGA(pk, criteria);
|
||||
|
||||
pk.RefreshChecksum();
|
||||
return pk;
|
||||
}
|
||||
|
||||
private uint GetGender(uint seed) => OriginalTrainerGender switch
|
||||
{
|
||||
GiftGender3.Only0 or GiftGender3.RandD3_0 => 0,
|
||||
GiftGender3.Only1 or GiftGender3.RandD3_1 => 1,
|
||||
GiftGender3.RandD3 => GetGenderBit0(LCRNG.Next(seed) >> 16),
|
||||
GiftGender3.RandS3 => GetGenderBit3(LCRNG.Next(seed) >> 16),
|
||||
GiftGender3.RandS7 => GetGenderBit7(LCRNG.Next(seed) >> 16),
|
||||
GiftGender3.RandSG15 => GetGenderBit15(LCRNG.Next2(seed) >> 16),
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
private bool IsGenderSpecificMatch(byte value) => OriginalTrainerGender switch
|
||||
{
|
||||
GiftGender3.Only0 or GiftGender3.RandD3_0 => value == 0,
|
||||
GiftGender3.Only1 or GiftGender3.RandD3_1 => value == 1,
|
||||
_ => true, // Algorithmic check later.
|
||||
};
|
||||
|
||||
private void SetForceHatchDetails(PK3 pk, ITrainerInfo sav)
|
||||
{
|
||||
pk.Language = (int)GetSafeLanguageNotEgg((LanguageID)sav.Language);
|
||||
|
|
@ -168,20 +176,47 @@ private GameVersion GetVersion(ITrainerInfo tr)
|
|||
return GetRandomVersion(Version);
|
||||
}
|
||||
|
||||
private void SetPINGA(PK3 pk, EncounterCriteria _)
|
||||
private uint SetPINGA(PK3 pk, EncounterCriteria criteria, PersonalInfo3 pi)
|
||||
{
|
||||
var seed = Util.Rand32();
|
||||
seed = TID16 == 06930 ? MystryMew.GetSeed(seed, Method) : GetSaneSeed(seed);
|
||||
PIDGenerator.SetValuesFromSeed(pk, Method, seed);
|
||||
pk.RefreshAbility((int)(pk.EncryptionConstant & 1));
|
||||
var gr = pi.Gender;
|
||||
uint idXor = pk.TID16 ^ (uint)pk.SID16;
|
||||
while (true)
|
||||
{
|
||||
uint seed = Util.Rand32();
|
||||
seed = GetSaneSeed(seed);
|
||||
var pid = Shiny switch
|
||||
{
|
||||
Shiny.Never when Method is BACD_U_AX => GetAntishiny(ref seed, idXor),
|
||||
Shiny.Never => GetRegularAntishiny(ref seed, idXor),
|
||||
Shiny.Always => GetForceShiny(ref seed, idXor),
|
||||
_ => GetRegular(ref seed),
|
||||
};
|
||||
if (criteria.IsSpecifiedNature() && criteria.Nature != (Nature)(pid % 25))
|
||||
continue; // try again
|
||||
var gender = EntityGender.GetFromPIDAndRatio(pid, gr);
|
||||
if (!criteria.IsGenderSatisfied(gender))
|
||||
continue;
|
||||
|
||||
pk.PID = pid;
|
||||
PIDGenerator.SetIVsFromSeedSequentialLCRNG(ref seed, pk);
|
||||
pk.RefreshAbility((int)(pk.PID & 1));
|
||||
return seed;
|
||||
}
|
||||
}
|
||||
|
||||
private uint GetSaneSeed(uint seed) => Method switch
|
||||
{
|
||||
PIDType.BACD_R => seed & 0x0000FFFF, // u16
|
||||
PIDType.BACD_R_S => seed & 0x000000FF, // u8
|
||||
PIDType.Channel => ChannelJirachi.SkipToPIDIV(seed),
|
||||
_ => seed,
|
||||
BACD_RBCD => Math.Clamp(seed, 3, 213), // BCD digit sum
|
||||
Channel => ChannelJirachi.SkipToPIDIV(seed),
|
||||
BACD_T2 when Species is not (ushort)Core.Species.Jirachi
|
||||
=> PCJPFifthAnniversary.GetSeedForResult(Species, Shiny == Shiny.Always, Moves.Contains((ushort)Move.Wish), seed),
|
||||
BACD_T3
|
||||
=> PCJPFifthAnniversary.GetSeedForResult(Species, Shiny == Shiny.Always, Moves.Contains((ushort)Move.Wish), seed),
|
||||
|
||||
BACD_M => MystryMew.GetSeed(seed),
|
||||
_ when OriginalTrainerGender is GiftGender3.RandD3_0 => GetRandomRestrictedGenderBit0(seed, 0),
|
||||
_ when OriginalTrainerGender is GiftGender3.RandD3_1 => GetRandomRestrictedGenderBit0(seed, 1),
|
||||
_ => Method.IsRestricted() ? seed & 0x0000FFFF : seed,
|
||||
};
|
||||
|
||||
private LanguageID GetSafeLanguage(LanguageID hatchLang)
|
||||
|
|
@ -227,7 +262,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
|
|||
{
|
||||
if (SID16 != UnspecifiedID && SID16 != pk.SID16) return false;
|
||||
if (TID16 != UnspecifiedID && TID16 != pk.TID16) return false;
|
||||
if (OriginalTrainerGender < 3 && OriginalTrainerGender != pk.OriginalTrainerGender) return false;
|
||||
if (!IsGenderSpecificMatch(pk.OriginalTrainerGender)) return false;
|
||||
var wcOT = OriginalTrainerName;
|
||||
if (!string.IsNullOrEmpty(wcOT) && wcOT != pk.OriginalTrainerName)
|
||||
return false;
|
||||
|
|
@ -274,4 +309,71 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
|
|||
public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match;
|
||||
|
||||
public bool IsTrainerMatch(PKM pk, ReadOnlySpan<char> trainer, int language) => true; // checked in explicit match
|
||||
|
||||
public bool IsCompatible(PIDType type, PKM pk) => type == Method;
|
||||
|
||||
public bool IsCompatibleReviseReset(ref PIDIV value, PKM pk)
|
||||
{
|
||||
var prev = value.Mutated; // if previously revised, use that instead.
|
||||
var type = prev is 0 ? value.Type : prev;
|
||||
|
||||
if (type is BACD_EA or BACD_ES && !IsEgg)
|
||||
return false;
|
||||
|
||||
if (OriginalTrainerGender is not GiftGender3.Recipient && (!IsEgg || pk.IsEgg) && !IsMatchGender(pk, value.OriginSeed))
|
||||
return false;
|
||||
|
||||
return Method switch
|
||||
{
|
||||
BACD_U => true,
|
||||
BACD_R => IsRestrictedSimple(ref value, type),
|
||||
BACD_R_A => IsRestrictedAnti(ref value, type),
|
||||
|
||||
BACD_T2 => IsRestrictedTable2(ref value, type, Species, Moves.Contains((ushort)Move.Wish)),
|
||||
BACD_T3 => IsRestrictedTable3(ref value, type, Species, Moves.Contains((ushort)Move.Wish)),
|
||||
BACD_RBCD => IsBerryFixShiny(ref value, type),
|
||||
BACD_M => IsMystryMew(ref value, type),
|
||||
Channel => IsChannelJirachi(ref value, type),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
private bool IsMatchGender(PKM pk, uint seed)
|
||||
{
|
||||
var expect = OriginalTrainerGender is GiftGender3.RandD3_0 or GiftGender3.RandD3_1
|
||||
? GetGenderBit0(LCRNG.Next6(seed) >> 16)
|
||||
: GetGender(LCRNG.Next4(seed)); // another implicit advance inside the method
|
||||
return pk.OriginalTrainerGender == expect;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trainer Gender for Gift Events in Gen3
|
||||
/// </summary>
|
||||
/// <remarks>If random, determined after the PID/IV (and potentially item).</remarks>
|
||||
public enum GiftGender3 : byte
|
||||
{
|
||||
/// <summary> Match the recipient. Either 0 or 1. </summary>
|
||||
Recipient,
|
||||
/// <summary> Must be 0. </summary>
|
||||
Only0,
|
||||
/// <summary> Must be 1. </summary>
|
||||
Only1,
|
||||
|
||||
/// <summary> Determined by a separate algorithm and shouldn't be checked via regular logic. </summary>
|
||||
RandAlgo,
|
||||
|
||||
/// <summary> Divide by 3. </summary>
|
||||
RandD3,
|
||||
/// <summary> Shift by 3. </summary>
|
||||
RandS3,
|
||||
/// <summary> Shift by 7. </summary>
|
||||
RandS7,
|
||||
/// <summary> Shift by 15, after Item. </summary>
|
||||
RandSG15,
|
||||
|
||||
/// <summary> <see cref="RandD3"/>, but MUST be 0. Used for dual-OT events. </summary>
|
||||
RandD3_0,
|
||||
/// <summary> <see cref="RandD3"/>, but MUST be 1. Used for dual-OT events. </summary>
|
||||
RandD3_1,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace PKHeX.Core;
|
|||
/// </summary>
|
||||
/// <remarks>Specialized for the PCJP gift distribution machines.</remarks>
|
||||
public sealed class EncounterGift3JPN(ushort Species, Distribution3JPN Distribution)
|
||||
: IEncounterable, IEncounterMatch, IRandomCorrelation, IFixedTrainer
|
||||
: IEncounterable, IEncounterMatch, IRandomCorrelationEvent3, IFixedTrainer
|
||||
{
|
||||
public ushort Species { get; } = Species;
|
||||
public Distribution3JPN Distribution { get; } = Distribution;
|
||||
|
|
@ -15,6 +15,7 @@ public sealed class EncounterGift3JPN(ushort Species, Distribution3JPN Distribut
|
|||
|
||||
private const PIDType Method = PIDType.BACD_U_AX;
|
||||
public PIDType GetSuggestedCorrelation() => Method;
|
||||
|
||||
public byte Form => 0;
|
||||
public GameVersion Version => GameVersion.R;
|
||||
public byte Generation => 3;
|
||||
|
|
@ -29,10 +30,9 @@ public sealed class EncounterGift3JPN(ushort Species, Distribution3JPN Distribut
|
|||
public EntityContext Context => EntityContext.Gen3;
|
||||
public bool IsEgg => false;
|
||||
public bool IsFixedTrainer => true;
|
||||
public string Name => "PCNY Gift";
|
||||
public string Name => "PCJP Gift";
|
||||
public string LongName => Name;
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk) => val is Method;
|
||||
public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; // checked in explicit match
|
||||
public bool IsTrainerMatch(PKM pk, ReadOnlySpan<char> trainer, int language) => true; // checked in explicit match
|
||||
|
||||
|
|
@ -63,17 +63,33 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
};
|
||||
|
||||
// Generate PIDIV
|
||||
SetPINGA(pk, criteria);
|
||||
SetPINGA(pk, criteria, pi);
|
||||
EncounterUtil.SetEncounterMoves(pk, Version, LevelMin);
|
||||
pk.RefreshChecksum();
|
||||
return pk;
|
||||
}
|
||||
|
||||
private static void SetPINGA(PK3 pk, EncounterCriteria _)
|
||||
private static void SetPINGA(PK3 pk, EncounterCriteria criteria, PersonalInfo3 pi)
|
||||
{
|
||||
var seed = Util.Rand32();
|
||||
PIDGenerator.SetValuesFromSeed(pk, Method, seed);
|
||||
pk.RefreshAbility((int)(pk.EncryptionConstant & 1));
|
||||
uint seed = Util.Rand32();
|
||||
var gr = pi.Gender;
|
||||
var idXor = pk.TID16; // no SID
|
||||
while (true)
|
||||
{
|
||||
var pid = CommonEvent3.GetAntishiny(ref seed, idXor);
|
||||
if (criteria.IsSpecifiedNature() && criteria.Nature != (Nature)(pid % 25))
|
||||
continue; // try again
|
||||
var gender = EntityGender.GetFromPIDAndRatio(pid, gr);
|
||||
if (!criteria.IsGenderSatisfied(gender))
|
||||
continue;
|
||||
|
||||
PIDGenerator.SetIVsFromSeedSequentialLCRNG(ref seed, pk);
|
||||
|
||||
pk.PID = pid;
|
||||
pk.RefreshAbility((int)(pid & 1));
|
||||
pk.OriginalTrainerGender = (byte)GetGender(LCRNG.Next16(ref seed));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
|
@ -85,8 +101,10 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
|
|||
if (Version != 0 && !Version.Contains(pk.Version))
|
||||
return false;
|
||||
|
||||
if (pk.SID16 != 0) return false;
|
||||
if (!IsValidTrainerID(pk.TID16)) return false;
|
||||
if (pk.SID16 != 0)
|
||||
return false;
|
||||
if (!IsValidTrainerID(pk.TID16))
|
||||
return false;
|
||||
|
||||
Span<char> trainerName = stackalloc char[pk.TrashCharCountTrainer];
|
||||
int len = pk.LoadString(pk.OriginalTrainerTrash, trainerName);
|
||||
|
|
@ -99,7 +117,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
|
|||
if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context))
|
||||
return false;
|
||||
|
||||
if (pk.Language == (int)LanguageID.Japanese)
|
||||
if (pk.Language != (int)LanguageID.Japanese)
|
||||
return false;
|
||||
|
||||
if ((byte)FixedBall != pk.Ball)
|
||||
|
|
@ -123,4 +141,24 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsCompatible(PIDType type, PKM pk) => type is Method;
|
||||
|
||||
public bool IsCompatibleReviseReset(ref PIDIV value, PKM pk)
|
||||
{
|
||||
var prev = value.Mutated; // if previously revised, use that instead.
|
||||
var type = prev is 0 ? value.Type : prev;
|
||||
if (type is not PIDType.BACD_AX)
|
||||
return false;
|
||||
|
||||
var seed = value.OriginSeed;
|
||||
var rand5 = LCRNG.Next5(seed) >> 16;
|
||||
var expect = GetGender(rand5);
|
||||
if (pk.OriginalTrainerGender != expect)
|
||||
return false;
|
||||
|
||||
return true; // Table weight -> gift selection is a separate RNG, nothing to check!
|
||||
}
|
||||
|
||||
private static uint GetGender(uint rand16) => CommonEvent3.GetGenderBit7(rand16);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core;
|
|||
/// </summary>
|
||||
/// <remarks>Specialized for the PCNY gift distribution machines.</remarks>
|
||||
public sealed class EncounterGift3NY(ushort Species, Distribution3NY Distribution, byte Level, Moveset Moves)
|
||||
: IEncounterable, IEncounterMatch, IRandomCorrelation, IFixedTrainer, IMoveset
|
||||
: IEncounterable, IEncounterMatch, IRandomCorrelationEvent3, IFixedTrainer, IMoveset
|
||||
{
|
||||
public ushort Species { get; } = Species;
|
||||
public Distribution3NY Distribution { get; } = Distribution;
|
||||
|
|
@ -34,7 +34,6 @@ public sealed class EncounterGift3NY(ushort Species, Distribution3NY Distributio
|
|||
public string Name => "PCNY Gift";
|
||||
public string LongName => Name;
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk) => val is Method;
|
||||
public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; // checked in explicit match
|
||||
public bool IsTrainerMatch(PKM pk, ReadOnlySpan<char> trainer, int language) => true; // checked in explicit match
|
||||
|
||||
|
|
@ -65,17 +64,33 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
};
|
||||
|
||||
// Generate PIDIV
|
||||
SetPINGA(pk, criteria);
|
||||
SetPINGA(pk, criteria, pi);
|
||||
pk.SetMoves(Moves);
|
||||
pk.RefreshChecksum();
|
||||
return pk;
|
||||
}
|
||||
|
||||
private static void SetPINGA(PK3 pk, EncounterCriteria _)
|
||||
private static void SetPINGA(PK3 pk, EncounterCriteria criteria, PersonalInfo3 pi)
|
||||
{
|
||||
var seed = Util.Rand32();
|
||||
PIDGenerator.SetValuesFromSeed(pk, Method, seed);
|
||||
pk.RefreshAbility((int)(pk.EncryptionConstant & 1));
|
||||
uint seed = Util.Rand32();
|
||||
var gr = pi.Gender;
|
||||
var idXor = pk.TID16; // no SID
|
||||
while (true)
|
||||
{
|
||||
var pid = CommonEvent3.GetAntishiny(ref seed, idXor);
|
||||
if (criteria.IsSpecifiedNature() && criteria.Nature != (Nature)(pid % 25))
|
||||
continue; // try again
|
||||
var gender = EntityGender.GetFromPIDAndRatio(pid, gr);
|
||||
if (!criteria.IsGenderSatisfied(gender))
|
||||
continue;
|
||||
|
||||
PIDGenerator.SetIVsFromSeedSequentialLCRNG(ref seed, pk);
|
||||
|
||||
pk.PID = pid;
|
||||
pk.RefreshAbility((int)(pid & 1));
|
||||
pk.OriginalTrainerGender = (byte)GetGender(LCRNG.Next16(ref seed));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
|
@ -85,8 +100,10 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
|
|||
if (Version != 0 && !Version.Contains(pk.Version))
|
||||
return false;
|
||||
|
||||
if (pk.SID16 != 0) return false;
|
||||
if (!Distribution.IsValidTrainerID(pk.TID16)) return false;
|
||||
if (pk.SID16 != 0)
|
||||
return false;
|
||||
if (!Distribution.IsValidTrainerID(pk.TID16))
|
||||
return false;
|
||||
|
||||
Span<char> trainerName = stackalloc char[pk.TrashCharCountTrainer];
|
||||
int len = pk.LoadString(pk.OriginalTrainerTrash, trainerName);
|
||||
|
|
@ -139,4 +156,24 @@ internal static EncounterGift3NY[] GetArray(ReadOnlySpan<byte> readOnlySpan)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IsCompatible(PIDType type, PKM pk) => type is Method;
|
||||
|
||||
public bool IsCompatibleReviseReset(ref PIDIV value, PKM pk)
|
||||
{
|
||||
var prev = value.Mutated; // if previously revised, use that instead.
|
||||
var type = prev is 0 ? value.Type : prev;
|
||||
if (type is not PIDType.BACD_AX)
|
||||
return false;
|
||||
|
||||
var seed = value.OriginSeed;
|
||||
var rand5 = LCRNG.Next5(seed) >> 16;
|
||||
var expect = GetGender(rand5);
|
||||
if (pk.OriginalTrainerGender != expect)
|
||||
return false;
|
||||
|
||||
return true; // Table weight -> gift selection is a separate RNG, nothing to check!
|
||||
}
|
||||
|
||||
private static uint GetGender(uint rand16) => CommonEvent3.GetGenderBit7(rand16);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,6 +166,6 @@ private bool IsMatchLocation(PKM pk)
|
|||
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk) => val is PIDType.CXD or PIDType.CXDAnti;
|
||||
public bool IsCompatible(PIDType type, PKM pk) => type is PIDType.CXD or PIDType.CXDAnti;
|
||||
public PIDType GetSuggestedCorrelation() => PIDType.CXD;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,6 @@ private void SetPINGA(XK3 pk, EncounterCriteria criteria, PersonalInfo3 pi)
|
|||
public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match;
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk) => val == PIDType.PokeSpot;
|
||||
public bool IsCompatible(PIDType type, PKM pk) => type == PIDType.PokeSpot;
|
||||
public PIDType GetSuggestedCorrelation() => PIDType.PokeSpot;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,11 +143,11 @@ private bool IsMatchPartial(PKM pk)
|
|||
}
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (val is PIDType.CXD)
|
||||
if (type is PIDType.CXD)
|
||||
return true;
|
||||
return val is PIDType.CXDAnti && FatefulEncounter;
|
||||
return type is PIDType.CXDAnti && FatefulEncounter;
|
||||
}
|
||||
|
||||
public PIDType GetSuggestedCorrelation() => PIDType.CXD;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ private bool IsMatchPartial(PKM pk)
|
|||
}
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk) => val is PIDType.CXD;
|
||||
public bool IsCompatible(PIDType type, PKM pk) => type is PIDType.CXD;
|
||||
public PIDType GetSuggestedCorrelation() => PIDType.CXD;
|
||||
public bool IsTrainerMatch(PKM pk, ReadOnlySpan<char> trainer, int language)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -176,15 +176,15 @@ public EncounterMatchRating GetMatchRating(PKM pk)
|
|||
private bool IsDeferredWurmple(PKM pk) => Species == (int)Core.Species.Wurmple && pk.Species != (int)Core.Species.Wurmple && !WurmpleUtil.IsWurmpleEvoValid(pk);
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (val is PIDType.Method_1)
|
||||
if (type is PIDType.Method_1)
|
||||
return true;
|
||||
// Chain shiny with Poké Radar is only possible in D/P/Pt, in grass.
|
||||
// Safari Zone does not allow using the Poké Radar
|
||||
if (val is PIDType.ChainShiny)
|
||||
if (type is PIDType.ChainShiny)
|
||||
return pk.IsShiny && CanUseRadar;
|
||||
if (val is PIDType.CuteCharm)
|
||||
if (type is PIDType.CuteCharm)
|
||||
return MethodFinder.IsCuteCharm4Valid(this, pk);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,15 +275,15 @@ public static bool IsMatchRoamerLocation([ConstantExpected] uint permit, ushort
|
|||
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (Species == (int)Core.Species.Pichu)
|
||||
return val == PIDType.Pokewalker;
|
||||
return type == PIDType.Pokewalker;
|
||||
if (Shiny == Shiny.Always)
|
||||
return val == PIDType.ChainShiny;
|
||||
if (val is PIDType.Method_1)
|
||||
return type == PIDType.ChainShiny;
|
||||
if (type is PIDType.Method_1)
|
||||
return true;
|
||||
if (val is PIDType.CuteCharm)
|
||||
if (type is PIDType.CuteCharm)
|
||||
return MethodFinder.IsCuteCharm4Valid(this, pk);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,13 +183,13 @@ public EncounterMatchRating GetMatchRating(PKM pk)
|
|||
private bool IsMatchPartial(PKM pk) => pk.Ball != (byte)Ball.Poke || !IsMatchSeed(pk);
|
||||
#endregion
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (val is PIDType.Pokewalker)
|
||||
if (type is PIDType.Pokewalker)
|
||||
return true;
|
||||
|
||||
// Pokewalker can sometimes be confused with CuteCharm due to the PID creation routine. Double check if it is okay.
|
||||
if (val is PIDType.CuteCharm)
|
||||
if (type is PIDType.CuteCharm)
|
||||
return MethodFinder.IsCuteCharm(pk, pk.EncryptionConstant) && MethodFinder.IsCuteCharm4Valid(this, pk);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,30 @@ namespace PKHeX.Core;
|
|||
/// </summary>
|
||||
public interface IRandomCorrelation
|
||||
{
|
||||
bool IsCompatible(PIDType val, PKM pk);
|
||||
/// <summary>
|
||||
/// Checks if the given <see cref="PIDType"/> is compatible with the encounter restrictions.
|
||||
/// </summary>
|
||||
/// <param name="type">Observed <see cref="PIDType"/> of the <see cref="pk"/></param>
|
||||
/// <param name="pk">Entity to compare against for other details</param>
|
||||
/// <returns>True if all details are compatible</returns>
|
||||
bool IsCompatible(PIDType type, PKM pk);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the suggested <see cref="PIDType"/> for the encounter.
|
||||
/// </summary>
|
||||
PIDType GetSuggestedCorrelation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specialized interface for mutating a <see cref="PIDIV"/> value to a derived type.
|
||||
/// </summary>
|
||||
public interface IRandomCorrelationEvent3 : IRandomCorrelation
|
||||
{
|
||||
/// <summary>
|
||||
/// Mutates the <see cref="PIDIV"/> value to a derived type, if possible.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to check and mutate</param>
|
||||
/// <param name="pk">Entity to compare against</param>
|
||||
/// <returns>True if Compatible. Revision of the ref value is not returned.</returns>
|
||||
bool IsCompatibleReviseReset(ref PIDIV value, PKM pk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,19 @@ public static void AddEncounterInfoPIDIV(LegalityAnalysis la, List<string> lines
|
|||
private static void AddEncounterInfoPIDIV(List<string> lines, LegalInfo info)
|
||||
{
|
||||
var pidiv = info.PIDIV;
|
||||
lines.Add(string.Format(L_FPIDType_0, pidiv.Type));
|
||||
var type = string.Format(L_FPIDType_0, pidiv.Type);
|
||||
if (info is { EncounterMatch: IRandomCorrelationEvent3 enc})
|
||||
{
|
||||
var mainType = enc.GetSuggestedCorrelation();
|
||||
if (mainType != pidiv.Type)
|
||||
type += $" [{mainType}]";
|
||||
if (enc is EncounterGift3 { Method: PIDType.BACD_M } && info.PIDIVMatches) // mystry
|
||||
{
|
||||
var detail = MystryMew.GetSeedIndexes(pidiv.OriginSeed);
|
||||
type += $" ({detail.Index}-{detail.SubIndex})";
|
||||
}
|
||||
}
|
||||
lines.Add(type);
|
||||
if (pidiv.NoSeed)
|
||||
return;
|
||||
|
||||
|
|
@ -139,6 +151,8 @@ private static void AddEncounterInfoPIDIV(List<string> lines, LegalInfo info)
|
|||
{
|
||||
var seed = pidiv.OriginSeed;
|
||||
var line = string.Format(L_FOriginSeed_0, seed.ToString("X8"));
|
||||
if (info is { EncounterMatch: IRandomCorrelationEvent3 } && pidiv.Mutated is not 0 && pidiv.OriginSeed != pidiv.EncounterSeed)
|
||||
line += $" [{pidiv.EncounterSeed:X8}]";
|
||||
lines.Add(line);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public static class LCRNG
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next (uint seed) => (seed * Mult ) + Add ;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next2(uint seed) => (seed * Mult2) + Add2;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next3(uint seed) => (seed * Mult3) + Add3;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next4(uint seed) => (seed * Mult4) + Add5;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next4(uint seed) => (seed * Mult4) + Add4;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next5(uint seed) => (seed * Mult5) + Add5;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next6(uint seed) => (seed * Mult6) + Add6;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Next7(uint seed) => (seed * Mult7) + Add7;
|
||||
|
|
@ -88,7 +88,7 @@ public static class LCRNG
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Prev9(uint seed) => (seed * rMult9) + rAdd9;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next 16 bits of the next RNG seed.
|
||||
/// Gets the upper 16 bits of the next RNG seed.
|
||||
/// </summary>
|
||||
/// <param name="seed">Seed to advance one step.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -99,9 +99,9 @@ public static uint Next16(ref uint seed)
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the previous 16 bits of the previous RNG seed.
|
||||
/// Gets the upper 16 bits of the previous RNG seed.
|
||||
/// </summary>
|
||||
/// <param name="seed">Seed to advance one step.</param>
|
||||
/// <param name="seed">Seed to reverse one step.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static uint Prev16(ref uint seed)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public static class XDRNG
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Prev12(uint seed) => (seed * rMult12) + rAdd12;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next 16 bits of the next RNG seed.
|
||||
/// Gets the upper 16 bits of the next RNG seed.
|
||||
/// </summary>
|
||||
/// <param name="seed">Seed to advance one step.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -106,7 +106,7 @@ public static uint Next16(ref uint seed)
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next 16 bits of the next RNG seed.
|
||||
/// Gets the upper 0x7FFF bits of the next RNG seed.
|
||||
/// </summary>
|
||||
/// <param name="seed">Seed to advance one step.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -117,9 +117,9 @@ public static uint Next15(ref uint seed)
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the previous 16 bits of the previous RNG seed.
|
||||
/// Gets the upper 16 bits of the previous RNG seed.
|
||||
/// </summary>
|
||||
/// <param name="seed">Seed to advance one step.</param>
|
||||
/// <param name="seed">Seed to reverse one step.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static uint Prev16(ref uint seed)
|
||||
{
|
||||
|
|
|
|||
240
PKHeX.Core/Legality/RNG/ClassicEra/Gen3/CommonEvent3.cs
Normal file
240
PKHeX.Core/Legality/RNG/ClassicEra/Gen3/CommonEvent3.cs
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for calculating and detecting Generation 3 Event PIDs.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Commonly referred to as B-A-C-D, the actual call order of the PID may be different.
|
||||
/// We still call them B-A-C-D just to keep them lumped together.
|
||||
/// </remarks>
|
||||
public static class CommonEvent3
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard calculation for the BA-CD PID generation.
|
||||
/// </summary>
|
||||
/// <param name="a16">First rand16 call, placed in the upper bits of the PID.</param>
|
||||
/// <param name="b16">Second rand16 call, placed in the lower bits of the PID.</param>
|
||||
/// <returns>32bit PID</returns>
|
||||
public static uint GetRegular(uint a16, uint b16) => (a16 << 16) | b16;
|
||||
|
||||
/// <summary>
|
||||
/// Alternate PID generation method for events, notably used in the PC-NY Gotta Catch 'Em All events.
|
||||
/// </summary>
|
||||
/// <param name="a16">First rand16 call, placed in the upper bits of the PID.</param>
|
||||
/// <param name="b16">Second rand16 call, placed in the lower bits of the PID.</param>
|
||||
/// <param name="idXor">Trainer ID xor value.</param>
|
||||
/// <remarks><see cref="a16"/> must be greater than 7.</remarks>
|
||||
/// <returns>32bit PID</returns>
|
||||
public static uint GetAntishiny(uint a16, uint b16, uint idXor) => ((a16 ^ (idXor ^ b16)) << 16) | b16;
|
||||
|
||||
/// <summary>
|
||||
/// Alternate PID generation method for events, notably used by the Berry Glitch Fix (Zigzagoon).
|
||||
/// </summary>
|
||||
/// <param name="x16">First rand16 call, placed in the upper bits of the PID.</param>
|
||||
/// <param name="b16">Second rand16 call, placed in the lower bits of the PID.</param>
|
||||
/// <param name="idXor">Trainer ID xor value.</param>
|
||||
/// <remarks><see cref="x16"/> instead of a16, this is 1 frame earlier. The a16 call is unused.</remarks>
|
||||
/// <returns>32bit PID</returns>
|
||||
public static uint GetForceShiny(uint x16, uint b16, uint idXor) => (x16 << 16) | (((idXor ^ x16) & 0xFFF8) | (b16 & 0b111));
|
||||
|
||||
/// <summary>
|
||||
/// Regular PID generation method for events, that changes the PID to be non-shiny if it were shiny.
|
||||
/// </summary>
|
||||
/// <param name="pid">Calculated 32-bit PID from the regular generation method.</param>
|
||||
/// <returns>Revised 32-bit PID</returns>
|
||||
private static uint GetRegularAntishiny(uint pid) => (pid + 8) & 0xFFFFFFF8;
|
||||
|
||||
/// <inheritdoc cref="GetRegularAntishiny(uint)"/>
|
||||
/// <param name="a16">First rand16 call, placed in the upper bits of the PID.</param>
|
||||
/// <param name="b16">Second rand16 call, placed in the lower bits of the PID.</param>
|
||||
/// <param name="idXor">Trainer ID xor value.</param>
|
||||
public static uint GetRegularAntishiny(uint a16, uint b16, uint idXor)
|
||||
{
|
||||
var pid = GetRegular(a16, b16);
|
||||
if (ShinyUtil.GetIsShiny(idXor, pid, 8))
|
||||
pid = GetRegularAntishiny(pid);
|
||||
return pid;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="GetRegular(uint, uint)"/>
|
||||
/// <param name="seed">Seed to roll forward to generate the PID.</param>
|
||||
public static uint GetRegular(ref uint seed)
|
||||
{
|
||||
var a16 = LCRNG.Next16(ref seed);
|
||||
var b16 = LCRNG.Next16(ref seed);
|
||||
return GetRegular(a16, b16);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="GetAntishiny(uint, uint, uint)"/>
|
||||
/// <param name="seed">Seed to roll forward to generate the PID.</param>
|
||||
/// <param name="idXor">Trainer ID xor value.</param>
|
||||
public static uint GetAntishiny(ref uint seed, uint idXor)
|
||||
{
|
||||
uint a16;
|
||||
do a16 = LCRNG.Next16(ref seed); // If it were, it would result in a shiny. We need any bits that won't yield a shiny.
|
||||
while ((a16 & ~0b111) == 0);
|
||||
|
||||
var b16 = LCRNG.Next16(ref seed);
|
||||
return GetAntishiny(a16, b16, idXor);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="GetForceShiny(uint, uint, uint)"/>
|
||||
/// <param name="seed">Seed to roll forward to generate the PID.</param>
|
||||
/// <param name="idXor">Trainer ID xor value.</param>
|
||||
public static uint GetForceShiny(ref uint seed, uint idXor)
|
||||
{
|
||||
var x16 = LCRNG.Next16(ref seed);
|
||||
_ = LCRNG.Next16(ref seed); // A (ends up unused)
|
||||
var b16 = LCRNG.Next16(ref seed);
|
||||
return GetForceShiny(x16, b16, idXor);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="GetRegularAntishiny(uint, uint, uint)"/>
|
||||
/// <param name="seed">Seed to roll forward to generate the PID.</param>
|
||||
/// <param name="idXor">Trainer ID xor value.</param>
|
||||
public static uint GetRegularAntishiny(ref uint seed, uint idXor)
|
||||
{
|
||||
var a16 = LCRNG.Next16(ref seed);
|
||||
var b16 = LCRNG.Next16(ref seed);
|
||||
return GetRegularAntishiny(a16, b16, idXor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is a regular PID generated from the given a16 and b16 values.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="GetRegular(uint,uint)"/>
|
||||
public static bool IsRegular(uint pid, uint a16, uint b16)
|
||||
{
|
||||
uint result = GetRegular(a16, b16);
|
||||
return result == pid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is an anti-shiny PID generated from the given a16 and b16 values.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IsForceAntishiny(uint,uint,uint,uint)"/>
|
||||
public static bool IsForceAntishiny(uint pid, uint a16, uint b16, uint idXor)
|
||||
{
|
||||
// First RNG call should be sought to be above 7 to ensure a shiny is not generated.
|
||||
if ((a16 & ~0b111) == 0)
|
||||
return false; // If it were, it would result in a shiny. We need any bits that won't yield a shiny.
|
||||
|
||||
// 0-Origin
|
||||
// A-PIDH component (>= 8)
|
||||
// B-PIDL
|
||||
uint result = GetAntishiny(a16, b16, idXor);
|
||||
return result == pid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is an anti-shiny PID generated from the given a16 and b16 values.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="GetForceShiny(uint,uint,uint)"/>
|
||||
public static bool IsForceShiny(uint pid, uint x16, uint b16, uint idXor)
|
||||
{
|
||||
// The mutation algorithm doesn't end up using the 'B' portion of the PID.
|
||||
if (x16 != pid >> 16)
|
||||
return false; // eager check to avoid the more expensive calculation.
|
||||
|
||||
// 0-Origin
|
||||
// X-PIDH
|
||||
// A-PIDL (ends up unused)
|
||||
// B-FORCEBITS
|
||||
uint result = GetForceShiny(x16, b16, idXor);
|
||||
return result == pid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is a regular anti-shiny PID generated from the given a16 and b16 values.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="GetRegularAntishiny(uint,uint,uint)"/>
|
||||
public static bool IsRegularAntishiny(uint pid, uint a16, uint b16, uint idXor)
|
||||
{
|
||||
uint result = GetRegularAntishiny(a16, b16, idXor);
|
||||
return result == pid;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IsRegularAntishiny(uint,uint,uint,uint)"/>
|
||||
/// <param name="expectPID">Regular BA PID that is expected from the correlation, no corrections.</param>
|
||||
/// <param name="actualPID">The actual PID of the Pokémon.</param>
|
||||
public static bool IsRegularAntishiny(uint actualPID, uint expectPID)
|
||||
{
|
||||
var result = GetRegularAntishiny(expectPID);
|
||||
return result == actualPID;
|
||||
}
|
||||
|
||||
/// <summary>Checks for eggs hatched with the regular Anti-shiny correlation, but originating from an unknown ID xor. </summary>
|
||||
/// <inheritdoc cref="IsRegularAntishiny(uint,uint,uint,uint)"/>
|
||||
/// <remarks>Only call this method when the Pokémon is SHINY.</remarks>
|
||||
/// <param name="expectPID">Regular BA PID that is expected from the correlation, no corrections.</param>
|
||||
/// <param name="actualPID">The actual PID of the Pokémon.</param>
|
||||
public static bool IsRegularAntishinyDifferentOT(uint actualPID, uint expectPID)
|
||||
{
|
||||
// The mutation algorithm basically adds until it is non-shiny.
|
||||
if ((actualPID & 0b111) != 0)
|
||||
return false; // eager check to avoid the more expensive calculation.
|
||||
var delta = actualPID - expectPID;
|
||||
return delta is (not 0) and < 8;
|
||||
}
|
||||
|
||||
/// <summary>Checks for eggs hatched with the Force Anti-shiny correlation, but originating from an unknown ID xor. </summary>
|
||||
/// <inheritdoc cref="IsForceAntishiny"/>
|
||||
/// <remarks>Only call this method when the Pokémon is SHINY.</remarks>
|
||||
public static bool IsForceAntishinyDifferentOT(uint pid, uint a16, uint b16, uint idXor)
|
||||
{
|
||||
// First RNG call should be sought to be above 7 to ensure a shiny is not generated.
|
||||
if ((a16 & ~0b111) == 0)
|
||||
return false; // If it were, it would result in a shiny. We need any bits that won't yield a shiny.
|
||||
if ((pid & 0xFFFF) != b16)
|
||||
return false;
|
||||
|
||||
// The ID xor is used in the top half. Since we need a different OT, these must be different.
|
||||
// Be sure to ignore the 3 bits of TSV (bit-shift 19 bits instead of 16).
|
||||
uint result = GetAntishiny(a16, b16, idXor);
|
||||
return result >> 19 != pid >> 19;
|
||||
}
|
||||
|
||||
/// <summary>Checks for eggs hatched with the Force Shiny correlation, but originating from an unknown ID xor. </summary>
|
||||
/// <inheritdoc cref="IsForceShiny"/>
|
||||
/// <remarks>Only call this method when the Pokémon is NOT SHINY.</remarks>
|
||||
public static bool IsForceShinyDifferentOT(uint pid, uint x16, uint b16, uint idXor)
|
||||
{
|
||||
if (x16 != pid >> 16)
|
||||
return false; // eager check to avoid the more expensive calculation.
|
||||
|
||||
// Due to the nature of the Force Shiny algorithm, bits 0-2 are from b16, and x16 is the high bits.
|
||||
if ((pid & 0b111) != (b16 & 0b111))
|
||||
return false;
|
||||
// Bits 3-15 are from the ID xor, which is x16 ^ idXor. But we don't know the original.
|
||||
// However, it must not be the same as the hatching OT xor. Because this method is only called when not shiny.
|
||||
var low = (idXor ^ x16) & 0xFFF8;
|
||||
var actual = (pid & 0xFFF8);
|
||||
return low != actual;
|
||||
}
|
||||
|
||||
public static uint GetGenderBit0(uint rand16) => (rand16 / 3) & 1;
|
||||
public static uint GetGenderBit3(uint rand16) => (rand16 >> 3) & 1;
|
||||
public static uint GetGenderBit7(uint rand16) => (rand16 >> 7) & 1;
|
||||
public static uint GetGenderBit15(uint rand16) => (rand16 >> 15) & 1;
|
||||
public static uint GetGenderBit0(ref uint seed) => GetGenderBit0(LCRNG.Next16(ref seed));
|
||||
public static uint GetGenderBit3(ref uint seed) => GetGenderBit3(LCRNG.Next16(ref seed));
|
||||
public static uint GetGenderBit7(ref uint seed) => GetGenderBit7(LCRNG.Next16(ref seed));
|
||||
public static uint GetGenderBit15(ref uint seed) => GetGenderBit15(LCRNG.Next2(seed) >> 15);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random restricted (16-bit) seed that respects the gender correlation.
|
||||
/// </summary>
|
||||
/// <param name="seed">Seed that generates the PID/IV then gender.</param>
|
||||
/// <param name="gender5">Requested gender</param>
|
||||
public static uint GetRandomRestrictedGenderBit0(uint seed, byte gender5)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var u16 = seed & 0xFFFF;
|
||||
var rand5 = LCRNG.Next5(seed) >> 16;
|
||||
if (GetGenderBit0(rand5) == gender5)
|
||||
return u16;
|
||||
seed = LCRNG.Next(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
153
PKHeX.Core/Legality/RNG/ClassicEra/Gen3/CommonEvent3Checker.cs
Normal file
153
PKHeX.Core/Legality/RNG/ClassicEra/Gen3/CommonEvent3Checker.cs
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
using static PKHeX.Core.PIDType;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic to revise a <see cref="PIDIV"/> based on observed <see cref="PIDType"/> and constraining <see cref="PIDType"/>
|
||||
/// </summary>
|
||||
public static class CommonEvent3Checker
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the observed type and seed value match the constraints of the encounter.
|
||||
/// </summary>
|
||||
/// <remarks>Regular Antishiny Table constraint.</remarks>
|
||||
/// <param name="value">PID/IV observed</param>
|
||||
/// <param name="observed">Observed PID Type</param>
|
||||
/// <param name="species">Encounter Species</param>
|
||||
/// <param name="isWish">Encounter moveset contains the move Wish</param>
|
||||
/// <returns>True if is match; mutation not indicated.</returns>
|
||||
public static bool IsRestrictedTable2(ref PIDIV value, PIDType observed, ushort species, bool isWish)
|
||||
{
|
||||
if (observed is not (BACD or BACD_A or BACD_EA))
|
||||
return false;
|
||||
|
||||
var seed = value.OriginSeed;
|
||||
var prev2 = LCRNG.Prev2(seed);
|
||||
if (prev2 > ushort.MaxValue)
|
||||
return false;
|
||||
if (species is (ushort)Species.Jirachi)
|
||||
return true;
|
||||
|
||||
var index = PCJPFifthAnniversary.GetIndexPCJP(species);
|
||||
var combined = WeightedTable3.GetRandom32(prev2);
|
||||
var result = PCJPFifthAnniversary.GetResultPCJP(combined);
|
||||
if (result.Shiny)
|
||||
return false;
|
||||
if (result.Index != index)
|
||||
return false;
|
||||
if (result.Wish != isWish)
|
||||
return false;
|
||||
value = value.AsMutated(BACD_R, prev2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>Force Shiny Table constraint.</remarks>
|
||||
/// <inheritdoc cref="IsRestrictedTable2"/>
|
||||
public static bool IsRestrictedTable3(ref PIDIV value, PIDType observed, ushort species, bool isWish)
|
||||
{
|
||||
if (observed is not (BACD_S or BACD_ES))
|
||||
return false;
|
||||
var seed = value.OriginSeed;
|
||||
var prev3 = LCRNG.Prev2(seed);
|
||||
if (prev3 > ushort.MaxValue)
|
||||
return false;
|
||||
if (species is (ushort)Species.Jirachi)
|
||||
return true;
|
||||
|
||||
var index = PCJPFifthAnniversary.GetIndexPCJP(species);
|
||||
seed = prev3;
|
||||
var rand1 = LCRNG.Next16(ref seed);
|
||||
var rand2 = LCRNG.Next16(ref seed);
|
||||
var combined = (rand1 << 16) | rand2;
|
||||
var result = PCJPFifthAnniversary.GetResultPCJP(combined);
|
||||
if (result.Shiny)
|
||||
return false;
|
||||
if (result.Index != index)
|
||||
return false;
|
||||
if (result.Wish != isWish)
|
||||
return false;
|
||||
value = value.AsMutated(BACD_R, prev3);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>Mystry Mew constraint.</remarks>
|
||||
/// <inheritdoc cref="IsRestrictedTable2"/>
|
||||
public static bool IsMystryMew(ref PIDIV value, PIDType observed)
|
||||
{
|
||||
if (observed is not BACD)
|
||||
return false;
|
||||
var seed = value.OriginSeed;
|
||||
// Reverse back to origin seed.
|
||||
var info = MystryMew.GetSeedIndexes(seed);
|
||||
if (info.Index == -1)
|
||||
return false;
|
||||
seed = MystryMew.IsRestrictedIndex0th(info.SubIndex) ? seed : MystryMew.GetSeed(info.Index);
|
||||
if (!MystryMew.IsValidSeed(seed, info.SubIndex))
|
||||
return false;
|
||||
value = value.AsMutated(BACD_R, seed);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>CHANNEL Jirachi constraint.</remarks>
|
||||
/// <inheritdoc cref="IsRestrictedTable2"/>
|
||||
public static bool IsChannelJirachi(ref PIDIV value, PIDType observed)
|
||||
{
|
||||
if (observed is not Channel)
|
||||
return false;
|
||||
var seed = value.OriginSeed;
|
||||
|
||||
var chk = ChannelJirachi.GetPossible(seed);
|
||||
if (chk.Pattern is ChannelJirachiRandomResult.None)
|
||||
return false;
|
||||
value = value.AsMutated(Channel, chk.Seed);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>Regular BACD (WISHMKR Jirachi, Eggs) constraint.</remarks>
|
||||
/// <inheritdoc cref="IsRestrictedTable2"/>
|
||||
public static bool IsRestrictedSimple(ref PIDIV value, PIDType observed)
|
||||
{
|
||||
if (observed is not BACD)
|
||||
return false;
|
||||
if (value.OriginSeed > ushort.MaxValue)
|
||||
return false;
|
||||
value = value.AsMutated(BACD_R);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>Regular Antishiny without seed restriction constraint.</remarks>
|
||||
/// <inheritdoc cref="IsRestrictedTable2"/>
|
||||
public static bool IsUnrestrictedAnti(ref PIDIV value, PIDType observed)
|
||||
{
|
||||
if (observed is not (BACD or BACD_A or BACD_EA))
|
||||
return false;
|
||||
if (value.OriginSeed > ushort.MaxValue)
|
||||
return false;
|
||||
value = value.AsMutated(BACD_U);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>Regular Antishiny with seed restriction constraint.</remarks>
|
||||
/// <inheritdoc cref="IsRestrictedTable2"/>
|
||||
public static bool IsRestrictedAnti(ref PIDIV value, PIDType observed)
|
||||
{
|
||||
if (observed is not (BACD or BACD_A or BACD_EA))
|
||||
return false;
|
||||
if (value.OriginSeed > ushort.MaxValue)
|
||||
return false;
|
||||
value = value.AsMutated(BACD_R);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>Berry Fix Zigzagoon seed restriction constraint.</remarks>
|
||||
/// <inheritdoc cref="IsRestrictedTable2"/>
|
||||
public static bool IsBerryFixShiny(ref PIDIV value, PIDType observed)
|
||||
{
|
||||
if (observed is not BACD_S)
|
||||
return false;
|
||||
if (value.OriginSeed is < 3 or > 213) // Binary Coded Decimal sum of timestamp must be possible.
|
||||
return false;
|
||||
value = value.AsMutated(BACD_R);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,22 @@ public static class MystryMew
|
|||
];
|
||||
|
||||
private const int MewPerRestrictedSeed = 5;
|
||||
private const int RestrictedIndex = 0;
|
||||
|
||||
/// <summary> 01_34 of this set were released by the event organizer. </summary>
|
||||
private const ushort ReleasedSeed = 0x6065;
|
||||
private const byte ReleasedSeedKeptIndex = 2; // 2nd sibling is the only valid one.
|
||||
private const uint ReleasedSeedKeptSeed = 0xE8D1A0BF; // Next5(Next5(ReleasedSeed))
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the seed was unreleased.
|
||||
/// </summary>
|
||||
public static bool IsUnreleased(uint seed, int subIndex) => seed is ReleasedSeed && subIndex is not ReleasedSeedKeptIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the seed index (of the returned tuple) is referring to the oldest (first) sibling of the 5-per-seed.
|
||||
/// </summary>
|
||||
public static bool IsRestrictedIndex0th(int index) => index == RestrictedIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random valid seed based on the input <see cref="random"/> value.
|
||||
|
|
@ -43,6 +59,8 @@ public static uint GetSeed(uint random, PIDType type = PIDType.BACD_U)
|
|||
var seeds = Seeds;
|
||||
uint restricted = random % (uint)seeds.Length;
|
||||
var seed = (uint)seeds[(int)restricted];
|
||||
if (seed is ReleasedSeed)
|
||||
return ReleasedSeedKeptSeed;
|
||||
if (type == PIDType.BACD_R)
|
||||
return seed;
|
||||
|
||||
|
|
@ -53,13 +71,22 @@ public static uint GetSeed(uint random, PIDType type = PIDType.BACD_U)
|
|||
return seed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the seed at (sorted) <see cref="index"/>.
|
||||
/// </summary>
|
||||
public static uint GetSeed(int index) => Seeds[(uint)index >= Seeds.Length ? 0 : index];
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the seed is a known seed.
|
||||
/// </summary>
|
||||
/// <param name="seed">Origin seed (for the PID/IV)</param>
|
||||
/// <returns>True if the seed is known.</returns>
|
||||
public static bool IsValidSeed(uint seed) => GetSeedIndex(seed) != -1;
|
||||
|
||||
/// <param name="seed">Origin seed (for the PID/IV)</param>
|
||||
/// <param name="subIndex">Sub-index (if not a restricted seed).</param>
|
||||
/// <inheritdoc cref="IsValidSeed(uint)"/>
|
||||
public static bool IsValidSeed(uint seed, int subIndex) => !IsUnreleased(seed, subIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the seed is a known seed.
|
||||
/// </summary>
|
||||
|
|
@ -80,7 +107,7 @@ public static int GetSeedIndex(uint seed)
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the index and subindex of the seed in the known seed list.
|
||||
/// Get the index and sub-index of the seed in the known seed list.
|
||||
/// </summary>
|
||||
/// <param name="seed">Origin seed (for the PID/IV)</param>
|
||||
/// <returns>Tuple of indexes; -1 if not found.</returns>
|
||||
|
|
@ -90,9 +117,9 @@ public static (int Index, int SubIndex) GetSeedIndexes(uint seed)
|
|||
if (seed <= ushort.MaxValue)
|
||||
{
|
||||
var index = seeds.BinarySearch((ushort)seed);
|
||||
return (index, -1);
|
||||
return (index, RestrictedIndex);
|
||||
}
|
||||
for (int i = 0; i < MewPerRestrictedSeed; i++)
|
||||
for (int i = RestrictedIndex + 1; i < RestrictedIndex + MewPerRestrictedSeed; i++)
|
||||
{
|
||||
seed = LCRNG.Prev5(seed); // BACD{?}
|
||||
if (seed <= ushort.MaxValue)
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for determining the PCJP Fifth Anniversary event gift received.
|
||||
/// </summary>
|
||||
public static class PCJPFifthAnniversary
|
||||
{
|
||||
private const uint MaxTableWeight = 1000;
|
||||
private const uint EntryWeight = 125;
|
||||
|
||||
// Table:
|
||||
// Pichu 125 Teeter Dance (100-124 shiny)
|
||||
// Pichu 125 Wish (100-124 shiny)
|
||||
// Bagon 125 Iron Defense
|
||||
// Bagon 125 Wish
|
||||
// Absol 125 Spite
|
||||
// Absol 125 Wish
|
||||
// Ralts 125 Charm
|
||||
// Ralts 125 Wish
|
||||
|
||||
// As we can see from the above table, there are 4 different species, with Wish being the second set of moves.
|
||||
// From a rand(1000) result, we can determine the species and the moveset with the following branch-less operations:
|
||||
// Species index: (result / 250)
|
||||
// Moveset index: (result / 125) % 2
|
||||
// Shiny: if Pichu, (result % 125) >= 100
|
||||
public static (uint Index, bool Wish, bool Shiny) GetResultPCJP(uint rand)
|
||||
{
|
||||
var result = WeightedTable3.GetPeriodicWeight(rand, MaxTableWeight);
|
||||
var eighth = result / EntryWeight;
|
||||
var wish = (eighth & 1) == 1;
|
||||
var index = eighth >> 1;
|
||||
var shiny = index == 0 && (result % EntryWeight) >= 100;
|
||||
return (index, wish, shiny);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Species index within the PCJP table.
|
||||
/// </summary>
|
||||
/// <param name="species">Species ID</param>
|
||||
/// <returns>0-3</returns>
|
||||
public static uint GetIndexPCJP(ushort species)
|
||||
{
|
||||
// Pichu: 172 = 0_10_10_11_00
|
||||
// Bagon: 371 = 1_01_11_00_11
|
||||
// Absol: 359 = 1_01_10_01_11
|
||||
// Ralts: 280 = 1_00_01_10_00
|
||||
// To get the index of the species (0-3) from the above table, we can do some bitwise magic:
|
||||
// Bits 2 & 3 are different across species, and conveniently in sequential order! We can just shift right by 2 add 1, then clamp to 0-3.
|
||||
return (((uint)species >> 2) + 1) & 3u;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given species, shiny, and wish moveset status match the given rand result.
|
||||
/// </summary>
|
||||
public static bool IsMatch(ushort species, bool shiny, bool wish, uint rand)
|
||||
{
|
||||
var index = GetIndexPCJP(species);
|
||||
var result = GetResultPCJP(rand);
|
||||
return index == result.Index && wish == result.Wish && shiny == result.Shiny;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random 16-bit seed that will return the desired table result.
|
||||
/// </summary>
|
||||
public static uint GetSeedForResult(ushort species, bool shiny, bool wish, uint seed)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var u16 = seed & 0xFFFF; // restricted
|
||||
var u32 = WeightedTable3.GetRandom32(u16);
|
||||
if (IsMatch(species, shiny, wish, u32))
|
||||
return u16;
|
||||
seed = LCRNG.Next(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
PKHeX.Core/Legality/RNG/ClassicEra/Gen3/WeightedTable3.cs
Normal file
37
PKHeX.Core/Legality/RNG/ClassicEra/Gen3/WeightedTable3.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Generation 3 Event Table Weighting Algorithm.
|
||||
/// </summary>
|
||||
public static class WeightedTable3
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the random weight value, with a periodic frequency of repeating (*about* every 0x8000).
|
||||
/// </summary>
|
||||
/// <param name="rand">32-bit random number</param>
|
||||
/// <param name="max">Exclusive maximum value that can be returned</param>
|
||||
/// <returns>[0, max)</returns>
|
||||
public static uint GetPeriodicWeight(uint rand, [ConstantExpected] uint max)
|
||||
{
|
||||
var high = rand >> 16;
|
||||
var first = ((high << 2) & 0xFFFF) + high;
|
||||
var second = ((rand & 0xFFFF) << 1) + (first >> 16);
|
||||
second += high + (second >> 16);
|
||||
return (max * (second & 0xFFFF)) >> 16;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="GetRandom32(ref uint)"/>
|
||||
public static uint GetRandom32(uint seed) => GetRandom32(ref seed);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a 32-bit random number from the given seed to use as the table random selector.
|
||||
/// </summary>
|
||||
public static uint GetRandom32(ref uint seed)
|
||||
{
|
||||
var rand1 = LCRNG.Next16(ref seed);
|
||||
var rand2 = LCRNG.Next16(ref seed);
|
||||
return (rand1 << 16) | rand2;
|
||||
}
|
||||
}
|
||||
|
|
@ -86,32 +86,42 @@ private static bool GetModified8BitMatch(PKM pk, uint pid, out PIDIV pidiv)
|
|||
|
||||
public static bool GetLCRNGMethod1Match(PKM pk, out uint result)
|
||||
{
|
||||
var pid = pk.EncryptionConstant;
|
||||
|
||||
var top = pid & 0xFFFF0000;
|
||||
var bot = pid << 16;
|
||||
|
||||
Span<uint> temp = stackalloc uint[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
temp[i] = (uint)pk.GetIV(i);
|
||||
ReadOnlySpan<uint> IVs = temp;
|
||||
return GetLCRNGMethod1Match(pk.EncryptionConstant, temp, out result);
|
||||
}
|
||||
|
||||
const int maxResults = LCRNG.MaxCountSeedsIV;
|
||||
Span<uint> seeds = stackalloc uint[maxResults];
|
||||
var count = LCRNGReversal.GetSeeds(seeds, bot, top);
|
||||
var reg = seeds[..count];
|
||||
public static bool GetLCRNGMethod1Match(uint pid, ReadOnlySpan<uint> IVs, out uint result)
|
||||
{
|
||||
var iv1 = GetIVChunk(IVs[..3]);
|
||||
var iv2 = GetIVChunk(IVs[3..]);
|
||||
return GetLCRNGMethod1Match(pid, iv1, iv2, out result);
|
||||
}
|
||||
|
||||
public static bool GetLCRNGMethod1Match(uint pid, uint iv1, uint iv2, out uint result)
|
||||
{
|
||||
var bot = pid << 16;
|
||||
var top = pid & 0xFFFF0000;
|
||||
return GetLCRNGMethod1Match(bot, top, iv1, iv2, out result);
|
||||
}
|
||||
|
||||
public static bool GetLCRNGMethod1Match(uint a, uint b, uint c, uint d, out uint result)
|
||||
{
|
||||
const int maxResults = LCRNG.MaxCountSeedsIV;
|
||||
Span<uint> seeds = stackalloc uint[maxResults];
|
||||
var count = LCRNGReversal.GetSeeds(seeds, a, b);
|
||||
var reg = seeds[..count];
|
||||
|
||||
foreach (var seed in reg)
|
||||
{
|
||||
var C = LCRNG.Next3(seed);
|
||||
var ivC = C >> 16 & 0x7FFF;
|
||||
if (iv1 != ivC)
|
||||
if (c != ivC)
|
||||
continue;
|
||||
var D = LCRNG.Next(C);
|
||||
var ivD = D >> 16 & 0x7FFF;
|
||||
if (iv2 != ivD)
|
||||
if (d != ivD)
|
||||
continue;
|
||||
// ABCD
|
||||
result = seed;
|
||||
|
|
@ -521,75 +531,71 @@ public static bool IsChainShinyValid(ITrainerID32 pk, uint pid, uint seed, out u
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool GetBACDMatch(Span<uint> seeds, PKM pk, uint pid, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
private static bool GetBACDMatch<T>(Span<uint> seeds, T pk, uint actualPID, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
where T : ITrainerID32
|
||||
{
|
||||
var bot = GetIVChunk(IVs[..3]) << 16;
|
||||
var top = GetIVChunk(IVs[3..]) << 16;
|
||||
|
||||
var count = LCRNGReversal.GetSeedsIVs(seeds, bot, top);
|
||||
var reg = seeds[..count];
|
||||
PIDType type = BACD_U;
|
||||
foreach (var seed in reg)
|
||||
PIDType type = BACD;
|
||||
uint idXor = (uint)(pk.TID16 ^ pk.SID16);
|
||||
foreach (var x in reg)
|
||||
{
|
||||
var B = seed;
|
||||
var A = LCRNG.Prev(B);
|
||||
var low = B >> 16;
|
||||
// Check for the expected BA(CD) pattern -- the expected PID.
|
||||
var seed = x;
|
||||
var b16 = seed >> 16;
|
||||
var a16 = LCRNG.Prev16(ref seed);
|
||||
|
||||
var PID = (A & 0xFFFF0000) | low;
|
||||
if (PID != pid)
|
||||
var expectPID = CommonEvent3.GetRegular(a16, b16);
|
||||
if (expectPID != actualPID)
|
||||
{
|
||||
uint idxor = (uint)(pk.TID16 ^ pk.SID16);
|
||||
bool isShiny = (idxor ^ PID >> 16 ^ (PID & 0xFFFF)) < 8;
|
||||
if (!isShiny)
|
||||
// Check for the alternate event types that force shiny state.
|
||||
bool isShiny = ShinyUtil.GetIsShiny(idXor, actualPID, 8);
|
||||
if (!isShiny) // most likely, branch prediction!
|
||||
{
|
||||
if (!pk.IsShiny) // check for nyx antishiny
|
||||
{
|
||||
if (!IsBACD_U_AX(idxor, pid, low, A, ref type))
|
||||
continue;
|
||||
}
|
||||
else // check for force shiny pk
|
||||
{
|
||||
if (!IsBACD_U_S(idxor, pid, low, ref A, ref type))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!IsBACD_U_AX(idxor, pid, low, A, ref type))
|
||||
{
|
||||
if ((PID + 8 & 0xFFFFFFF8) != pid)
|
||||
if (CommonEvent3.IsRegularAntishiny(actualPID, expectPID))
|
||||
type = BACD_A;
|
||||
else if (CommonEvent3.IsForceAntishiny(actualPID, a16, b16, idXor))
|
||||
type = BACD_AX;
|
||||
else if (CommonEvent3.IsForceShinyDifferentOT(actualPID, LCRNG.Prev16(ref seed), b16, idXor))
|
||||
type = BACD_ES; // was shiny, hatched by different OT.
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else // Shiny
|
||||
{
|
||||
if (CommonEvent3.IsRegularAntishinyDifferentOT(actualPID, expectPID))
|
||||
type = BACD_EA; // was not-shiny, hatched by different OT.
|
||||
else if (CommonEvent3.IsForceAntishinyDifferentOT(actualPID, a16, b16, idXor))
|
||||
type = BACD_EAX; // was not-shiny, hatched by different OT.
|
||||
else if (CommonEvent3.IsForceShiny(actualPID, LCRNG.Prev16(ref seed), b16, idXor))
|
||||
type = BACD_S;
|
||||
else
|
||||
continue;
|
||||
type = BACD_U_A;
|
||||
}
|
||||
}
|
||||
var s = LCRNG.Prev(A);
|
||||
|
||||
// Check for prior Restricted seed
|
||||
var sn = s;
|
||||
for (int i = 0; i < 3; i++, sn = LCRNG.Prev(sn))
|
||||
{
|
||||
if ((sn & 0xFFFF0000) != 0)
|
||||
continue;
|
||||
// shift from unrestricted enum val to restricted enum val
|
||||
pidiv = new PIDIV(--type, sn);
|
||||
return true;
|
||||
}
|
||||
// no restricted seed found, thus unrestricted
|
||||
pidiv = new PIDIV(type, s);
|
||||
// Unroll one final time to get the origin seed.
|
||||
var origin = LCRNG.Prev(seed);
|
||||
pidiv = new PIDIV(type, origin);
|
||||
return true;
|
||||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetPokewalkerMatch(PKM pk, uint pid, out PIDIV pidiv)
|
||||
private static bool GetPokewalkerMatch(PKM pk, uint actualPID, out PIDIV pidiv)
|
||||
{
|
||||
// check surface compatibility
|
||||
// Bits 8-24 must all be zero or all be one.
|
||||
const uint midMask = 0x00FFFF00;
|
||||
var mid = pid & midMask;
|
||||
var mid = actualPID & midMask;
|
||||
if (mid is not (0 or midMask))
|
||||
return GetNonMatch(out pidiv);
|
||||
|
||||
// Quirky Nature is not possible with the algorithm.
|
||||
var nature = pid % 25;
|
||||
var nature = actualPID % 25;
|
||||
if (nature == 24)
|
||||
return GetNonMatch(out pidiv);
|
||||
|
||||
|
|
@ -599,10 +605,10 @@ private static bool GetPokewalkerMatch(PKM pk, uint pid, out PIDIV pidiv)
|
|||
var gr = pk.PersonalInfo.Gender;
|
||||
if (pk.Species == (int)Species.Froslass)
|
||||
gr = 0x7F; // Snorunt
|
||||
var expect = PokewalkerRNG.GetPID(pk.TID16, pk.SID16, nature, gender, gr);
|
||||
if (expect != pid)
|
||||
var expectPID = PokewalkerRNG.GetPID(pk.TID16, pk.SID16, nature, gender, gr);
|
||||
if (expectPID != actualPID)
|
||||
{
|
||||
if (!(gender == 0 && IsAzurillEdgeCaseM(pk, nature, pid)))
|
||||
if (!(gender == 0 && IsAzurillEdgeCaseM(pk, nature, actualPID)))
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
pidiv = PIDIV.Pokewalker;
|
||||
|
|
@ -610,7 +616,7 @@ private static bool GetPokewalkerMatch(PKM pk, uint pid, out PIDIV pidiv)
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsAzurillEdgeCaseM(PKM pk, uint nature, uint oldpid)
|
||||
private static bool IsAzurillEdgeCaseM(PKM pk, uint nature, uint actualPID)
|
||||
{
|
||||
// check for Azurill evolution edge case... 75% F-M is now 50% F-M; was this a Female->Male bend?
|
||||
ushort species = pk.Species;
|
||||
|
|
@ -618,12 +624,12 @@ private static bool IsAzurillEdgeCaseM(PKM pk, uint nature, uint oldpid)
|
|||
return false;
|
||||
|
||||
const byte AzurillGenderRatio = 0xBF;
|
||||
var gender = EntityGender.GetFromPIDAndRatio(pk.EncryptionConstant, AzurillGenderRatio);
|
||||
var gender = EntityGender.GetFromPIDAndRatio(actualPID, AzurillGenderRatio);
|
||||
if (gender != 1)
|
||||
return false;
|
||||
|
||||
var pid = PokewalkerRNG.GetPID(pk.TID16, pk.SID16, nature, 1, AzurillGenderRatio);
|
||||
return pid == oldpid;
|
||||
return pid == actualPID;
|
||||
}
|
||||
|
||||
private static bool GetColoStarterMatch(Span<uint> seeds, PKM pk, uint top, uint bot, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
|
|
@ -665,67 +671,8 @@ private static bool GetNonMatch(out PIDIV pidiv)
|
|||
pidiv = PIDIV.None;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is a <see cref="PIDType.BACD_U_S"></see> match.
|
||||
/// </summary>
|
||||
/// <param name="idXor"><see cref="PKM.TID16"/> ^ <see cref="PKM.SID16"/></param>
|
||||
/// <param name="pid">Full actual PID</param>
|
||||
/// <param name="low">Low portion of PID (B)</param>
|
||||
/// <param name="A">First RNG call</param>
|
||||
/// <param name="type">PID Type is updated if successful</param>
|
||||
/// <returns>True/False if the PID matches</returns>
|
||||
/// <remarks>First RNG call is unrolled once if the PID is valid with this correlation</remarks>
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsBACD_U_S(uint idXor, uint pid, uint low, ref uint A, ref PIDType type)
|
||||
{
|
||||
// 0-Origin
|
||||
// 1-PIDH
|
||||
// 2-PIDL (ends up unused)
|
||||
// 3-FORCEBITS
|
||||
// PID = PIDH << 16 | (SID16 ^ TID16 ^ PIDH)
|
||||
|
||||
var X = LCRNG.Prev(A); // unroll once as there's 3 calls instead of 2
|
||||
uint PID = (X & 0xFFFF0000) | (idXor ^ X >> 16);
|
||||
PID &= 0xFFFFFFF8;
|
||||
PID |= low & 0x7; // lowest 3 bits
|
||||
|
||||
if (PID != pid)
|
||||
return false;
|
||||
A = X; // keep the unrolled seed
|
||||
type = BACD_U_S;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is a <see cref="PIDType.BACD_U_AX"></see> match.
|
||||
/// </summary>
|
||||
/// <param name="idxor"><see cref="PKM.TID16"/> ^ <see cref="PKM.SID16"/></param>
|
||||
/// <param name="pid">Full actual PID</param>
|
||||
/// <param name="low">Low portion of PID (B)</param>
|
||||
/// <param name="A">First RNG call</param>
|
||||
/// <param name="type">PID Type is updated if successful</param>
|
||||
/// <returns>True/False if the PID matches</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsBACD_U_AX(uint idxor, uint pid, uint low, uint A, ref PIDType type)
|
||||
{
|
||||
if ((pid & 0xFFFF) != low)
|
||||
return false;
|
||||
|
||||
// 0-Origin
|
||||
// 1-ushort rnd, do until >8
|
||||
// 2-PIDL
|
||||
|
||||
uint rnd = A >> 16;
|
||||
if (rnd < 8)
|
||||
return false;
|
||||
uint PID = ((rnd ^ idxor ^ low) << 16) | low;
|
||||
if (PID != pid)
|
||||
return false;
|
||||
type = BACD_U_AX;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PIDIV AnalyzeGB(PKM _)
|
||||
{
|
||||
// not implemented; correlation between IVs and RNG hasn't been converted to code.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using static PKHeX.Core.PIDType;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
|
@ -11,72 +12,60 @@ private static void SetValuesFromSeedLCRNG(PKM pk, PIDType type, uint seed)
|
|||
{
|
||||
var A = LCRNG.Next(seed);
|
||||
var B = LCRNG.Next(A);
|
||||
var skipBetweenPID = type is PIDType.Method_3 or PIDType.Method_3_Unown;
|
||||
var skipBetweenPID = type is Method_3 or Method_3_Unown;
|
||||
if (skipBetweenPID) // VBlank skip between PID rand() [RARE]
|
||||
B = LCRNG.Next(B);
|
||||
|
||||
var swappedPIDHalves = type is >= PIDType.Method_1_Unown and <= PIDType.Method_4_Unown;
|
||||
var swappedPIDHalves = type is >= Method_1_Unown and <= Method_4_Unown;
|
||||
if (swappedPIDHalves) // switched order of PID halves, "BA**"
|
||||
pk.PID = (A & 0xFFFF0000) | (B >> 16);
|
||||
else
|
||||
pk.PID = (B & 0xFFFF0000) | (A >> 16);
|
||||
|
||||
var C = LCRNG.Next(B);
|
||||
var skipIV1Frame = type is PIDType.Method_2 or PIDType.Method_2_Unown;
|
||||
var skipIV1Frame = type is Method_2 or Method_2_Unown;
|
||||
if (skipIV1Frame) // VBlank skip after PID
|
||||
C = LCRNG.Next(C);
|
||||
|
||||
var D = LCRNG.Next(C);
|
||||
var skipIV2Frame = type is PIDType.Method_4 or PIDType.Method_4_Unown;
|
||||
var skipIV2Frame = type is Method_4 or Method_4_Unown;
|
||||
if (skipIV2Frame) // VBlank skip between IVs
|
||||
D = LCRNG.Next(D);
|
||||
|
||||
Span<int> IVs = stackalloc int[6];
|
||||
MethodFinder.GetIVsInt32(IVs, C >> 16, D >> 16);
|
||||
if (type == PIDType.Method_1_Roamer)
|
||||
if (type == Method_1_Roamer)
|
||||
{
|
||||
// Only store lowest 8 bits of IV data; zero out the other bits.
|
||||
IVs[1] &= 7;
|
||||
for (int i = 2; i < 6; i++)
|
||||
IVs[i] = 0;
|
||||
IVs[2..].Clear();
|
||||
}
|
||||
pk.SetIVs(IVs);
|
||||
}
|
||||
|
||||
private static void SetValuesFromSeedBACD(PKM pk, PIDType type, uint seed)
|
||||
{
|
||||
bool shiny = type is PIDType.BACD_R_S or PIDType.BACD_U_S;
|
||||
uint X = shiny ? LCRNG.Next(seed) : seed;
|
||||
var A = LCRNG.Next(X);
|
||||
var B = LCRNG.Next(A);
|
||||
var C = LCRNG.Next(B);
|
||||
var D = LCRNG.Next(C);
|
||||
uint idxor = pk.TID16 ^ (uint)pk.SID16;
|
||||
pk.PID = GetPIDFromSeedBACD(ref seed, type, idxor);
|
||||
SetIVsFromSeedSequentialLCRNG(ref seed, pk);
|
||||
pk.RefreshAbility((int)(pk.PID & 1));
|
||||
}
|
||||
|
||||
if (shiny)
|
||||
{
|
||||
uint PID = (X & 0xFFFF0000) | ((X >> 16) ^ pk.TID16 ^ pk.SID16);
|
||||
PID &= 0xFFFFFFF8;
|
||||
PID |= (B >> 16) & 0x7; // lowest 3 bits
|
||||
|
||||
pk.PID = PID;
|
||||
}
|
||||
else if (type is PIDType.BACD_R_AX or PIDType.BACD_U_AX)
|
||||
{
|
||||
uint low = B >> 16;
|
||||
pk.PID = ((A & 0xFFFF0000) ^ ((low ^ pk.TID16 ^ pk.SID16) << 16)) | low;
|
||||
}
|
||||
else
|
||||
{
|
||||
pk.PID = (A & 0xFFFF0000) | (B >> 16);
|
||||
}
|
||||
private static uint GetPIDFromSeedBACD(ref uint seed, PIDType type, uint idXor) => type switch
|
||||
{
|
||||
BACD => CommonEvent3.GetRegular(ref seed),
|
||||
BACD_S => CommonEvent3.GetForceShiny(ref seed, idXor),
|
||||
BACD_AX => CommonEvent3.GetAntishiny(ref seed, idXor),
|
||||
_ => CommonEvent3.GetRegularAntishiny(ref seed, idXor),
|
||||
};
|
||||
|
||||
public static void SetIVsFromSeedSequentialLCRNG(ref uint seed, PKM pk)
|
||||
{
|
||||
var c16 = LCRNG.Next16(ref seed);
|
||||
var d16 = LCRNG.Next16(ref seed);
|
||||
Span<int> IVs = stackalloc int[6];
|
||||
MethodFinder.GetIVsInt32(IVs, C >> 16, D >> 16);
|
||||
MethodFinder.GetIVsInt32(IVs, c16, d16);
|
||||
pk.SetIVs(IVs);
|
||||
|
||||
bool antishiny = type is PIDType.BACD_R_A or PIDType.BACD_U_A;
|
||||
while (antishiny && pk.IsShiny)
|
||||
pk.PID = unchecked(pk.PID + 1);
|
||||
}
|
||||
|
||||
private static void SetValuesFromSeedXDRNG(PKM pk, uint seed)
|
||||
|
|
@ -96,26 +85,27 @@ private static void SetValuesFromSeedXDRNG(PKM pk, uint seed)
|
|||
seed = XDRNG.Next2(seed); // fake PID
|
||||
break;
|
||||
}
|
||||
var A = XDRNG.Next(seed); // IV1
|
||||
var B = XDRNG.Next(A); // IV2
|
||||
var C = XDRNG.Next(B); // Ability
|
||||
var a16 = XDRNG.Next15(ref seed); // IV1
|
||||
var b16 = XDRNG.Next15(ref seed); // IV2
|
||||
|
||||
Span<int> IVs = stackalloc int[6];
|
||||
MethodFinder.GetIVsInt32(IVs, a16, b16);
|
||||
pk.SetIVs(IVs);
|
||||
|
||||
_ = XDRNG.Next16(ref seed); // Ability
|
||||
|
||||
if (species is (int)Species.Umbreon or (int)Species.Espeon)
|
||||
{
|
||||
// Reuse existing logic.
|
||||
pk.PID = LockFinder.GenerateStarterPID(ref C, pk.TID16, pk.SID16);
|
||||
pk.PID = LockFinder.GenerateStarterPID(ref seed, pk.TID16, pk.SID16);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate PID.
|
||||
var D = XDRNG.Next(C); // PID
|
||||
var E = XDRNG.Next(D); // PID
|
||||
pk.PID = (D & 0xFFFF0000) | (E >> 16);
|
||||
var d16 = XDRNG.Next16(ref seed); // PID
|
||||
var e16 = XDRNG.Next16(ref seed); // PID
|
||||
pk.PID = (d16 << 16) | e16;
|
||||
}
|
||||
|
||||
Span<int> IVs = stackalloc int[6];
|
||||
MethodFinder.GetIVsInt32(IVs, A >> 16, B >> 16);
|
||||
pk.SetIVs(IVs);
|
||||
}
|
||||
|
||||
public static void SetValuesFromSeedXDRNG_EReader(PKM pk, uint seed)
|
||||
|
|
@ -128,27 +118,21 @@ public static void SetValuesFromSeedXDRNG_EReader(PKM pk, uint seed)
|
|||
|
||||
private static void SetValuesFromSeedChannel(PKM pk, uint seed)
|
||||
{
|
||||
var O = XDRNG.Next(seed); // SID16
|
||||
var A = XDRNG.Next(O); // PID
|
||||
var B = XDRNG.Next(A); // PID
|
||||
var C = XDRNG.Next(B); // Held Item
|
||||
var D = XDRNG.Next(C); // Version
|
||||
var E = XDRNG.Next(D); // OT Gender
|
||||
|
||||
const ushort TID16 = 40122;
|
||||
pk.ID32 = (O & 0xFFFF0000) | TID16;
|
||||
var SID16 = O >> 16;
|
||||
var pid1 = A >> 16;
|
||||
var pid2 = B >> 16;
|
||||
var sid = XDRNG.Next16(ref seed);
|
||||
pk.ID32 = (sid << 16) | TID16;
|
||||
|
||||
var pid1 = XDRNG.Next16(ref seed);
|
||||
var pid2 = XDRNG.Next16(ref seed);
|
||||
var pid = (pid1 << 16) | pid2;
|
||||
if ((pid2 > 7 ? 0 : 1) != (pid1 ^ SID16 ^ TID16))
|
||||
if ((pid2 > 7 ? 0 : 1) != (pid1 ^ sid ^ TID16))
|
||||
pid ^= 0x80000000;
|
||||
pk.PID = pid;
|
||||
pk.HeldItem = (ushort)(C >> 31) + 169; // 0-Ganlon, 1-Salac
|
||||
pk.Version = GameVersion.S + (byte)(D >> 31); // 0-Sapphire, 1-Ruby
|
||||
pk.OriginalTrainerGender = (byte)(E >> 31);
|
||||
pk.HeldItem = (ushort)(XDRNG.Next16(ref seed) >> 15) + 169; // 0-Ganlon, 1-Salac
|
||||
pk.Version = GameVersion.S + (byte)(XDRNG.Next16(ref seed) >> 15); // 0-Sapphire, 1-Ruby
|
||||
pk.OriginalTrainerGender = (byte)(XDRNG.Next16(ref seed) >> 15);
|
||||
Span<int> ivs = stackalloc int[6];
|
||||
XDRNG.GetSequentialIVsInt32(E, ivs);
|
||||
XDRNG.GetSequentialIVsInt32(seed, ivs);
|
||||
pk.SetIVs(ivs);
|
||||
}
|
||||
|
||||
|
|
@ -162,34 +146,29 @@ public static void SetValuesFromSeed(PKM pk, PIDType type, uint seed)
|
|||
{
|
||||
switch (t)
|
||||
{
|
||||
case PIDType.Channel:
|
||||
case Channel:
|
||||
return SetValuesFromSeedChannel;
|
||||
case PIDType.CXD:
|
||||
case CXD:
|
||||
return SetValuesFromSeedXDRNG;
|
||||
|
||||
case PIDType.Method_1 or PIDType.Method_2 or PIDType.Method_3 or PIDType.Method_4:
|
||||
case PIDType.Method_1_Unown or PIDType.Method_2_Unown or PIDType.Method_3_Unown or PIDType.Method_4_Unown:
|
||||
case PIDType.Method_1_Roamer:
|
||||
case Method_1 or Method_2 or Method_3 or Method_4:
|
||||
case Method_1_Unown or Method_2_Unown or Method_3_Unown or Method_4_Unown:
|
||||
case Method_1_Roamer:
|
||||
return (pk, seed) => SetValuesFromSeedLCRNG(pk, t, seed);
|
||||
|
||||
case PIDType.BACD_R:
|
||||
case PIDType.BACD_R_A:
|
||||
case PIDType.BACD_R_S:
|
||||
case PIDType.BACD_R_AX:
|
||||
return (pk, seed) => SetValuesFromSeedBACD(pk, t, seed & 0xFFFF);
|
||||
case PIDType.BACD_U:
|
||||
case PIDType.BACD_U_A:
|
||||
case PIDType.BACD_U_S:
|
||||
case PIDType.BACD_U_AX:
|
||||
case BACD:
|
||||
case BACD_S:
|
||||
case BACD_A:
|
||||
case BACD_AX:
|
||||
return (pk, seed) => SetValuesFromSeedBACD(pk, t, seed);
|
||||
|
||||
case PIDType.PokeSpot:
|
||||
case PokeSpot:
|
||||
return SetRandomPokeSpotPID;
|
||||
|
||||
case PIDType.G5MGShiny:
|
||||
case G5MGShiny:
|
||||
return SetValuesFromSeedMG5Shiny;
|
||||
|
||||
case PIDType.Pokewalker:
|
||||
case Pokewalker:
|
||||
return (pk, seed) =>
|
||||
{
|
||||
var pid = pk.PID = PokewalkerRNG.GetPID(pk.TID16, pk.SID16, seed % 24, pk.Gender, pk.PersonalInfo.Gender);
|
||||
|
|
@ -197,11 +176,11 @@ public static void SetValuesFromSeed(PKM pk, PIDType type, uint seed)
|
|||
};
|
||||
|
||||
// others: unimplemented
|
||||
case PIDType.CuteCharm:
|
||||
case CuteCharm:
|
||||
break;
|
||||
case PIDType.ChainShiny:
|
||||
case ChainShiny:
|
||||
return SetRandomChainShinyPID;
|
||||
case PIDType.G4MGAntiShiny:
|
||||
case G4MGAntiShiny:
|
||||
break;
|
||||
}
|
||||
return (_, _) => { };
|
||||
|
|
@ -210,12 +189,7 @@ public static void SetValuesFromSeed(PKM pk, PIDType type, uint seed)
|
|||
public static void SetRandomChainShinyPID(PKM pk, uint seed)
|
||||
{
|
||||
pk.PID = ClassicEraRNG.GetChainShinyPID(ref seed, pk.ID32);
|
||||
|
||||
Span<int> IVs = stackalloc int[6];
|
||||
var rand1 = LCRNG.Next16(ref seed);
|
||||
var rand2 = LCRNG.Next16(ref seed);
|
||||
MethodFinder.GetIVsInt32(IVs, rand1, rand2);
|
||||
pk.SetIVs(IVs);
|
||||
SetIVsFromSeedSequentialLCRNG(ref seed, pk);
|
||||
}
|
||||
|
||||
private static void SetRandomPokeSpotPID(PKM pk, uint seed)
|
||||
|
|
@ -291,7 +265,7 @@ public static bool IsValidCriteria4(PKM pk, Nature nature, int ability, byte gen
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void SetRandomWildPID5(PKM pk, Nature nature, int ability, byte gender, PIDType specific = PIDType.None)
|
||||
public static void SetRandomWildPID5(PKM pk, Nature nature, int ability, byte gender, PIDType specific = None)
|
||||
{
|
||||
var tidbit = (pk.TID16 ^ pk.SID16) & 1;
|
||||
pk.RefreshAbility(ability);
|
||||
|
|
@ -305,7 +279,7 @@ public static void SetRandomWildPID5(PKM pk, Nature nature, int ability, byte ge
|
|||
while (true)
|
||||
{
|
||||
uint seed = rnd.Rand32();
|
||||
if (specific == PIDType.G5MGShiny)
|
||||
if (specific == G5MGShiny)
|
||||
{
|
||||
SetValuesFromSeedMG5Shiny(pk, seed);
|
||||
seed = pk.PID;
|
||||
|
|
|
|||
|
|
@ -13,23 +13,18 @@ namespace PKHeX.Core;
|
|||
internal static readonly PIDIV Pokewalker = new(PIDType.Pokewalker);
|
||||
internal static readonly PIDIV G5MGShiny = new(PIDType.G5MGShiny);
|
||||
|
||||
/// <summary>The RNG seed which immediately generates the PIDIV (starting with PID or IVs, whichever comes first)</summary>
|
||||
[field: FieldOffset(0)]
|
||||
public uint OriginSeed { get; }
|
||||
/// <summary>The RNG seed which immediately generates the PID/IV (starting with PID or IVs, whichever comes first)</summary>
|
||||
[field: FieldOffset(0)] public uint OriginSeed { get; }
|
||||
/// <summary>The RNG seed which starts the encounter generation routine.</summary>
|
||||
[field: FieldOffset(4)]
|
||||
public uint EncounterSeed { get; init; }
|
||||
[field: FieldOffset(4)] public uint EncounterSeed { get; init; }
|
||||
|
||||
/// <summary>The RNG seed which immediately generates the PIDIV (starting with PID or IVs, whichever comes first)</summary>
|
||||
[field: FieldOffset(0)]
|
||||
public ulong Seed64 { get; }
|
||||
/// <summary>The RNG seed which immediately generates the PID/IV (starting with PID or IVs, whichever comes first)</summary>
|
||||
[field: FieldOffset(0)] public ulong Seed64 { get; }
|
||||
|
||||
/// <summary>Type of PIDIV correlation</summary>
|
||||
[field: FieldOffset(8)]
|
||||
public PIDType Type { get; }
|
||||
|
||||
[field: FieldOffset(9)]
|
||||
public LeadRequired Lead { get; init; }
|
||||
[field: FieldOffset(8)] public PIDType Type { get; }
|
||||
[field: FieldOffset(9)] public LeadRequired Lead { get; init; }
|
||||
[field: FieldOffset(9)] public PIDType Mutated { get; init; }
|
||||
|
||||
public PIDIV(PIDType type, uint seed = 0)
|
||||
{
|
||||
|
|
@ -43,7 +38,7 @@ public PIDIV(PIDType type, ulong seed)
|
|||
Seed64 = seed;
|
||||
}
|
||||
|
||||
/// <remarks> Some PIDIVs may be generated without a single seed, but may follow a traceable pattern. </remarks>
|
||||
/// <remarks> Some PID/IVs may be generated without a single seed, but may follow a traceable pattern. </remarks>
|
||||
/// <summary> Indicates that there is no <see cref="OriginSeed"/> to refer to. </summary>
|
||||
public bool NoSeed => Type is PIDType.None or PIDType.Pokewalker or PIDType.G5MGShiny;
|
||||
|
||||
|
|
@ -54,4 +49,6 @@ public PIDIV(PIDType type, ulong seed)
|
|||
public bool IsSeed64() => Type is PIDType.Xoroshiro;
|
||||
|
||||
public PIDIV AsEncounteredVia(LeadSeed condition) => this with { Lead = condition.Lead, EncounterSeed = condition.Seed };
|
||||
public PIDIV AsMutated(PIDType type, uint Origin) => this with { Mutated = type, EncounterSeed = Origin };
|
||||
public PIDIV AsMutated(PIDType type) => this with { Mutated = type, EncounterSeed = OriginSeed };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,53 +49,48 @@ public enum PIDType : byte
|
|||
/// <remarks><see cref="LCRNG"/></remarks>
|
||||
Method_1_Roamer,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID restricted to 16bit Origin Seed
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/> seed is clamped to 16bits.</remarks>
|
||||
BACD_R,
|
||||
#region BACD Event
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/></remarks>
|
||||
#region Internal Matching Tagging
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions </summary>
|
||||
BACD,
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions, anti-shiny (add). </summary>
|
||||
BACD_A,
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions, anti-shiny (xor) </summary>
|
||||
BACD_AX,
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions, shiny </summary>
|
||||
BACD_S,
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions, anti-shiny (add). </summary>
|
||||
#endregion
|
||||
|
||||
#region Egg-Only Internal Matching Tagging
|
||||
BACD_EA,
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions, anti-shiny (xor) </summary>
|
||||
BACD_EAX,
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions, shiny </summary>
|
||||
BACD_ES,
|
||||
#endregion
|
||||
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions </summary>
|
||||
BACD_U,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID restricted to 16bit Origin Seed, anti-shiny.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/> seed is clamped to 16bits.</remarks>
|
||||
BACD_R_A,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions, anti-shiny.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/></remarks>
|
||||
BACD_U_A,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID restricted to 8bit Origin Seed, shiny
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/> seed is clamped to 16bits.</remarks>
|
||||
BACD_R_S,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions, shiny
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/></remarks>
|
||||
BACD_U_S,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID restricted to 16bit Origin Seed, anti-shiny (nyx)
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/> seed is clamped to 16bits.</remarks>
|
||||
BACD_R_AX,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions, anti-shiny (nyx)
|
||||
/// </summary>
|
||||
/// <remarks><see cref="LCRNG"/></remarks>
|
||||
/// <summary> Event Reversed Order PID without Origin Seed restrictions, anti-shiny (xor) </summary>
|
||||
BACD_U_AX,
|
||||
// BACD_U_A and BACD_U_S were never generated by any event.
|
||||
|
||||
/// <summary> Event Reversed Order PID restricted to 16bit Origin Seed </summary>
|
||||
BACD_R,
|
||||
/// <summary> Event Reversed Order PID restricted to 16bit Origin Seed, anti-shiny. </summary>
|
||||
BACD_R_A,
|
||||
/// <summary> Event Reversed Order PID restricted to [0,213] Origin Seed, shiny </summary>
|
||||
BACD_RBCD,
|
||||
/// <summary> Event Reversed Order PID with Origin Seed restrictions, consuming 2 calls to the RNG before the PID is generated. </summary>
|
||||
BACD_T2,
|
||||
/// <summary> Event Reversed Order PID with Origin Seed restrictions, consuming 3 calls to the RNG before the PID is generated. </summary>
|
||||
BACD_T3,
|
||||
/// <summary> Event Reversed Order PID with Origin Seed restrictions, only using the Mystry Mew table. </summary>
|
||||
BACD_M,
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Generation 4 Cute Charm PID, which is forced to an 8 bit PID value based on the gender & gender ratio value.
|
||||
|
|
@ -206,4 +201,6 @@ public static class PIDTypeExtensions
|
|||
public static bool IsClassicMethod(this PIDType type) => type
|
||||
is Method_1 or Method_2 or Method_3 or Method_4
|
||||
or Method_1_Unown or Method_2_Unown or Method_3_Unown or Method_4_Unown;
|
||||
|
||||
public static bool IsRestricted(this PIDType type) => type is >= BACD_R and <= BACD_M;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ internal set
|
|||
|
||||
public bool PIDParsed { get; private set; }
|
||||
private PIDIV _pidiv;
|
||||
internal ref PIDIV GetPIDIVRef() => ref _pidiv;
|
||||
|
||||
public EncounterYieldFlag ManualFlag { get; internal set; }
|
||||
public bool FrameMatches => ManualFlag != EncounterYieldFlag.InvalidFrame;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.Species;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
|
@ -16,11 +15,19 @@ public static class FormInfo
|
|||
/// <param name="form">Entity form</param>
|
||||
/// <param name="format">Current generation format</param>
|
||||
/// <returns>True if it can only exist in a battle, false if it can exist outside of battle.</returns>
|
||||
public static bool IsBattleOnlyForm(ushort species, byte form, byte format) => BattleOnly.Contains(species) && species switch
|
||||
public static bool IsBattleOnlyForm(ushort species, byte form, byte format)
|
||||
{
|
||||
if (BattleMegas.Contains(species))
|
||||
return IsBattleMegaForm(species, form);
|
||||
if (BattleForms.Contains(species))
|
||||
return IsBattleForm(species, form);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsBattleForm(ushort species, byte form) => species switch
|
||||
{
|
||||
// Only continue checking if the species is in the list of Battle Only forms.
|
||||
// Some species have battle only forms as well as out-of-battle forms (other than base form).
|
||||
(ushort)Slowbro => form == 1, // Mega
|
||||
(ushort)Darmanitan => (form & 1) == 1, // Zen
|
||||
(ushort)Zygarde => form == 4, // Zygarde Complete
|
||||
(ushort)Minior => form < 7, // Minior Shields-Down
|
||||
|
|
@ -30,6 +37,13 @@ public static class FormInfo
|
|||
_ => form != 0,
|
||||
};
|
||||
|
||||
private static bool IsBattleMegaForm(ushort species, byte form)
|
||||
{
|
||||
if (species is (ushort)Slowbro)
|
||||
return form == 1; // Mega
|
||||
return form != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverts the Battle Form to the form it would have outside of Battle.
|
||||
/// </summary>
|
||||
|
|
@ -131,7 +145,7 @@ public static bool IsFormChangeable(ushort species, byte oldForm, byte newForm,
|
|||
/// Species that can change between their forms, regardless of origin.
|
||||
/// </summary>
|
||||
/// <remarks>Excludes Zygarde as it has special conditions. Check separately.</remarks>
|
||||
private static readonly HashSet<ushort> FormChange =
|
||||
private static ReadOnlySpan<ushort> FormChange =>
|
||||
[
|
||||
(int)Burmy,
|
||||
(int)Furfrou,
|
||||
|
|
@ -225,21 +239,6 @@ public static bool IsFormChangeable(ushort species, byte oldForm, byte newForm,
|
|||
(int)Audino, (int)Diancie,
|
||||
];
|
||||
|
||||
private static readonly HashSet<ushort> BattleOnly = GetBattleFormSet();
|
||||
|
||||
private static HashSet<ushort> GetBattleFormSet()
|
||||
{
|
||||
var reg = BattleForms;
|
||||
var mega = BattleMegas;
|
||||
var count = reg.Length + mega.Length + 2;
|
||||
var hs = new HashSet<ushort>(count);
|
||||
foreach (var species in reg)
|
||||
hs.Add(species);
|
||||
foreach (var species in mega)
|
||||
hs.Add(species);
|
||||
return hs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Species has a Totem form in Gen7 (S/M & US/UM) that can be captured and owned.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public override string CardTitle
|
|||
public override ushort Location { get => (ushort)(IsEgg ? 0 : Gift.EggLocation + 3000); set { } }
|
||||
public override ushort EggLocation { get => (ushort)(IsEgg ? Gift.EggLocation + 3000 : 0); set { } }
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk) => Gift.IsCompatible(val, pk);
|
||||
public bool IsCompatible(PIDType type, PKM pk) => Gift.IsCompatible(type, pk);
|
||||
public PIDType GetSuggestedCorrelation() => Gift.GetSuggestedCorrelation();
|
||||
|
||||
public bool GiftEquals(PGT pgt)
|
||||
|
|
|
|||
|
|
@ -293,13 +293,13 @@ public static bool IsRangerManaphy(PKM pk)
|
|||
public bool RibbonChampionWorld { get => PK.RibbonChampionWorld; set => PK.RibbonChampionWorld = value; }
|
||||
public bool RibbonSouvenir { get => PK.RibbonSouvenir; set => PK.RibbonSouvenir = value; }
|
||||
|
||||
public bool IsCompatible(PIDType val, PKM pk)
|
||||
public bool IsCompatible(PIDType type, PKM pk)
|
||||
{
|
||||
if (IsManaphyEgg)
|
||||
return IsG4ManaphyPIDValid(val, pk);
|
||||
if (PK.PID != 1 && val == PIDType.G5MGShiny)
|
||||
return IsG4ManaphyPIDValid(type, pk);
|
||||
if (PK.PID != 1 && type == PIDType.G5MGShiny)
|
||||
return true;
|
||||
return val == PIDType.None;
|
||||
return type == PIDType.None;
|
||||
}
|
||||
|
||||
public PIDType GetSuggestedCorrelation()
|
||||
|
|
|
|||
|
|
@ -83,35 +83,39 @@ public void PIDIVMatchingTest3Event()
|
|||
{
|
||||
// Restricted: TID16/SID16 are zero.
|
||||
var pkR = new PK3 {PID = 0x0000E97E, IVs = [17, 19, 20, 16, 13, 12]};
|
||||
MethodFinder.Analyze(pkR).Type.Should().Be(PIDType.BACD_R);
|
||||
var result = MethodFinder.Analyze(pkR);
|
||||
(result is { Type: PIDType.BACD, OriginSeed: <= ushort.MaxValue }).Should().BeTrue();
|
||||
|
||||
// Restricted Antishiny: PID is incremented 2 times to lose shininess.
|
||||
var pkRA = new PK3 {PID = 0x0000E980, IVs = [17, 19, 20, 16, 13, 12], TID16 = 01337, SID16 = 60486};
|
||||
MethodFinder.Analyze(pkRA).Type.Should().Be(PIDType.BACD_R_A);
|
||||
result = MethodFinder.Analyze(pkRA);
|
||||
(result is { Type: PIDType.BACD_A, OriginSeed: <= ushort.MaxValue }).Should().BeTrue();
|
||||
|
||||
// Unrestricted: TID16/SID16 are zero.
|
||||
var pkU = new PK3 {PID = 0x67DBFC33, IVs = [12, 25, 27, 30, 02, 31]};
|
||||
MethodFinder.Analyze(pkU).Type.Should().Be(PIDType.BACD_U);
|
||||
result = MethodFinder.Analyze(pkU);
|
||||
(result is { Type: PIDType.BACD }).Should().BeTrue();
|
||||
|
||||
// Unrestricted Antishiny: PID is incremented 5 times to lose shininess.
|
||||
var pkUA = new PK3 {PID = 0x67DBFC38, IVs = [12, 25, 27, 30, 02, 31], TID16 = 01337, SID16 = 40657};
|
||||
MethodFinder.Analyze(pkUA).Type.Should().Be(PIDType.BACD_U_A);
|
||||
result = MethodFinder.Analyze(pkUA);
|
||||
(result is { Type: PIDType.BACD_A }).Should().BeTrue();
|
||||
|
||||
// berry fix zigzagoon: seed 0x0020
|
||||
const ushort bfix = 0x20;
|
||||
var pkRS = new PK3 {PID = 0x38CA4EA0, IVs = [00, 20, 28, 11, 19, 00], TID16 = 30317, SID16 = 00000};
|
||||
var a_pkRS = MethodFinder.Analyze(pkRS);
|
||||
a_pkRS.Type.Should().Be(PIDType.BACD_R_S);
|
||||
a_pkRS.OriginSeed.Should().Be(0x0020);
|
||||
result = MethodFinder.Analyze(pkRS);
|
||||
(result is { Type: PIDType.BACD_S, OriginSeed: bfix }).Should().BeTrue();
|
||||
|
||||
var gkRS = new PK3 { TID16 = 30317, SID16 = 00000 };
|
||||
PIDGenerator.SetValuesFromSeed(gkRS, PIDType.BACD_R_S, a_pkRS.OriginSeed);
|
||||
PIDGenerator.SetValuesFromSeed(gkRS, PIDType.BACD_S, bfix);
|
||||
gkRS.PID.Should().Be(pkRS.PID);
|
||||
gkRS.IVs.SequenceEqual(pkRS.IVs).Should().BeTrue();
|
||||
|
||||
// Unrestricted Antishiny nyx
|
||||
var nyxUA = new PK3 {PID = 0xBD3DF676, IVs = [00, 15, 05, 04, 21, 05], TID16 = 80, SID16 = 0};
|
||||
var nyx_pkUA = MethodFinder.Analyze(nyxUA);
|
||||
nyx_pkUA.Type.Should().Be(PIDType.BACD_U_AX);
|
||||
var nyxUA = new PK3 {PID = 0xBD3DF676, IVs = [00, 15, 05, 04, 21, 05], TID16 = 00080, SID16 = 00000};
|
||||
result = MethodFinder.Analyze(nyxUA);
|
||||
(result is { Type: PIDType.BACD_AX }).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user