mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-04-25 16:35:02 -05:00
Gen3: revise PCJP internal logic
deduplicates a little; renames the PID type label to something less confusing.
This commit is contained in:
parent
ed419c49bd
commit
79b3bd4f74
|
|
@ -28,7 +28,7 @@ internal static class EncountersWC3
|
|||
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(273,093,156,000), Language = (int)Japanese, Method = BACD_T2, ID32 = 30719, Shiny = Never, OriginalTrainerName = "ネガイボシ", OriginalTrainerGender = Only0 }, // Negai Boshi Jirachi
|
||||
new(385, 05, R) { Moves = new(273,093,156,000), Language = (int)Japanese, Method = BACD_TA, ID32 = 30719, Shiny = Never, OriginalTrainerName = "ネガイボシ", OriginalTrainerGender = Only0 }, // Negai Boshi Jirachi
|
||||
new(385, 05, RS){ Moves = new(273,093,156,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(273,093,156,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
|
||||
|
|
@ -183,16 +183,16 @@ internal static class EncountersWC3
|
|||
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_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
|
||||
new(172, 5, R, true) { Moves = new(084,204,298,000), Method = BACD_TS, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0, Shiny = Always }, // Pichu with Teeter Dance
|
||||
new(172, 5, R, true) { Moves = new(084,204,273,000), Method = BACD_TS, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0, Shiny = Always }, // Pichu with Wish
|
||||
new(172, 5, R, true) { Moves = new(084,204,298,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Pichu with Teeter Dance
|
||||
new(172, 5, R, true) { Moves = new(084,204,273,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Pichu with Wish
|
||||
new(280, 5, R, true) { Moves = new(045,204,000,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Ralts with Charm
|
||||
new(280, 5, R, true) { Moves = new(045,273,000,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Ralts with Wish
|
||||
new(359, 5, R, true) { Moves = new(010,043,180,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Absol with Spite
|
||||
new(359, 5, R, true) { Moves = new(010,043,273,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Absol with Wish
|
||||
new(371, 5, R, true) { Moves = new(099,044,334,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Bagon with Iron Defense
|
||||
new(371, 5, R, true) { Moves = new(099,044,273,000), Method = BACD_TA, OriginalTrainerName = PCJPEggTrainerName, OriginalTrainerGender = Only0 }, // Bagon with Wish
|
||||
|
||||
// Distributed event gifts for receipt in the Pokémon Center 2F call the same give egg script as the Hot Springs Wynaut.
|
||||
// Most often, the game has a VBlank interrupt between PID and IVs (potentially because the script does not lock when starting).
|
||||
|
|
|
|||
|
|
@ -334,11 +334,9 @@ public static void SetValuesFromSeedChannel(PK3 pk, uint seed)
|
|||
private uint GetSaneSeed(uint seed) => Method switch
|
||||
{
|
||||
BACD_RBCD => Math.Clamp(seed, 3, 213), // BCD digit sum
|
||||
BACD_T2 when Species is (ushort)Core.Species.Jirachi
|
||||
=> LCRNG.Next2(seed & 0xFFFF),
|
||||
BACD_T2
|
||||
=> LCRNG.Next2(PCJPFifthAnniversary.GetSeedForResult(Species, Shiny == Shiny.Always, Moves.Contains((ushort)Move.Wish), seed)),
|
||||
BACD_T3
|
||||
BACD_TA when Species is (ushort)Core.Species.Jirachi
|
||||
=> LCRNG.Next2(seed & 0xFFFF), // table rand, but table result identical
|
||||
BACD_TA or BACD_TS // shiny depends on encounter
|
||||
=> LCRNG.Next2(PCJPFifthAnniversary.GetSeedForResult(Species, Shiny == Shiny.Always, Moves.Contains((ushort)Move.Wish), seed)),
|
||||
|
||||
BACD_M => MystryMew.GetSeed(seed),
|
||||
|
|
@ -466,8 +464,8 @@ public RandomCorrelationRating IsCompatibleReviseReset(ref PIDIV value, PKM pk)
|
|||
BACD_R_A => IsRestrictedAnti(ref value, type),
|
||||
BACD_U_AX => IsUnrestrictedAntiX(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_TA => IsRestrictedTable2(ref value, type, Species, Moves.Contains((ushort)Move.Wish)),
|
||||
BACD_TS => 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),
|
||||
|
|
|
|||
|
|
@ -18,55 +18,52 @@ public static class CommonEvent3Checker
|
|||
/// <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))
|
||||
// Same method as IsRestrictedTable3, except shiny is disallowed.
|
||||
if (observed is not (BACD or BACD_A or BACD_EA)) // regular/anti-shiny, or anti-shiny before trade & hatch
|
||||
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;
|
||||
return IsRestrictedTableMatch(ref value, species, isWish, false);
|
||||
}
|
||||
|
||||
/// <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))
|
||||
// Same method as IsRestrictedTable2, except it should be shiny.
|
||||
if (observed is not (BACD_S or BACD_ES)) // shiny or shiny before trade & hatch
|
||||
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;
|
||||
return IsRestrictedTableMatch(ref value, species, isWish, 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)
|
||||
private static bool IsRestrictedTableMatch(ref PIDIV value, ushort species, bool isWish, bool isShiny)
|
||||
{
|
||||
var seed = value.OriginSeed;
|
||||
var origin = LCRNG.Prev2(seed);
|
||||
if (origin > ushort.MaxValue)
|
||||
return false;
|
||||
|
||||
// Only 2 events distributed with table rand.
|
||||
// Negai Boshi Jirachi was filled with the same entry.
|
||||
// PCJP Fifth Anniversary had a few entries, will need to check.
|
||||
if (species is not (ushort)Species.Jirachi)
|
||||
{
|
||||
// Otherwise, check the table to see if it is valid.
|
||||
if (!IsMatchTableRand(species, isWish, (ushort)origin, isShiny))
|
||||
return false;
|
||||
}
|
||||
value = value.AsMutated(BACD_R, origin);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsMatchTableRand(ushort species, bool isWish, ushort seed16, bool isShiny)
|
||||
{
|
||||
var index = PCJPFifthAnniversary.GetIndex(species);
|
||||
var result = PCJPFifthAnniversary.GetResult(seed16);
|
||||
if (result.Shiny != isShiny)
|
||||
return false;
|
||||
if (result.Index != index)
|
||||
return false;
|
||||
if (result.Wish != isWish)
|
||||
return false;
|
||||
value = value.AsMutated(BACD_R, prev3);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,15 @@ public static class PCJPFifthAnniversary
|
|||
private const uint MaxTableWeight = 1000;
|
||||
private const uint EntryWeight = 125;
|
||||
|
||||
/// <summary>
|
||||
/// Determines the result from the table, based on the input 16-bit random seed.
|
||||
/// </summary>
|
||||
public static (uint Index, bool Wish, bool Shiny) GetResult(ushort rand)
|
||||
{
|
||||
var u32 = WeightedTable3.GetRandom32(rand);
|
||||
return GetResult(u32);
|
||||
}
|
||||
|
||||
// Table:
|
||||
// Pichu 125 Teeter Dance (100-124 shiny)
|
||||
// Pichu 125 Wish (100-124 shiny)
|
||||
|
|
@ -23,8 +32,13 @@ public static class PCJPFifthAnniversary
|
|||
// 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)
|
||||
|
||||
/// <summary>
|
||||
/// Determines the result from the table, based on the input 32-bit random value.
|
||||
/// </summary>
|
||||
private static (uint Index, bool Wish, bool Shiny) GetResult(uint rand)
|
||||
{
|
||||
// Reduce the weight to a random number in the range of the table weight.
|
||||
var result = WeightedTable3.GetPeriodicWeight(rand, MaxTableWeight);
|
||||
var eighth = result / EntryWeight;
|
||||
var wish = (eighth & 1) == 1;
|
||||
|
|
@ -38,7 +52,7 @@ public static (uint Index, bool Wish, bool Shiny) GetResultPCJP(uint rand)
|
|||
/// </summary>
|
||||
/// <param name="species">Species ID</param>
|
||||
/// <returns>0-3</returns>
|
||||
public static uint GetIndexPCJP(ushort species)
|
||||
public static uint GetIndex(ushort species)
|
||||
{
|
||||
// Pichu: 172 = 0_10_10_11_00
|
||||
// Bagon: 371 = 1_01_11_00_11
|
||||
|
|
@ -54,21 +68,20 @@ public static uint GetIndexPCJP(ushort species)
|
|||
/// </summary>
|
||||
public static bool IsMatch(ushort species, bool shiny, bool wish, uint rand)
|
||||
{
|
||||
var index = GetIndexPCJP(species);
|
||||
var result = GetResultPCJP(rand);
|
||||
var index = GetIndex(species);
|
||||
var result = GetResult(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)
|
||||
public static ushort 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))
|
||||
var u16 = (ushort)seed; // restricted
|
||||
if (IsMatch(species, shiny, wish, u16))
|
||||
return u16;
|
||||
seed = LCRNG.Next(seed);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,10 +83,10 @@ public enum PIDType : byte
|
|||
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 restricted to 16bit Origin Seed, consuming 2 calls select the event gift index, anti-shiny. </summary>
|
||||
BACD_TA,
|
||||
/// <summary> Event Reversed Order PID restricted to 16bit Origin Seed, consuming 2 calls select the event gift index, force-shiny. </summary>
|
||||
BACD_TS,
|
||||
/// <summary> Event Reversed Order PID with Origin Seed restrictions, only using the Mystry Mew table. </summary>
|
||||
BACD_M,
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user