diff --git a/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs b/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs new file mode 100644 index 000000000..f0cd809d4 --- /dev/null +++ b/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs @@ -0,0 +1,40 @@ +namespace PKHeX.Core +{ + /// + /// Logic for applying a value. + /// + public static class CatchRateApplicator + { + public static int GetSuggestedCatchRate(PK1 pk1, SaveFile sav) + { + var la = new LegalityAnalysis(pk1); + return GetSuggestedCatchRate(pk1, sav, la); + } + + public static int GetSuggestedCatchRate(PK1 pk1, SaveFile sav, LegalityAnalysis la) + { + if (la.Valid) + return pk1.Catch_Rate; + + if (la.Info.Generation == 2) + return 0; + + var v = la.EncounterOriginal; + switch (v) + { + case EncounterTrade1 c: + return c.GetInitialCatchRate(); + case EncounterStatic s when s.Version == GameVersion.Stadium && s.Species == (int)Species.Psyduck: + return pk1.Japanese ? 167 : 168; // Amnesia Psyduck has different catch rates depending on language + default: + { + if (sav.Version.Contains(v.Version) || v.Version.Contains(sav.Version)) + return sav.Personal[v.Species].CatchRate; + if (!GameVersion.RB.Contains(v.Version)) + return PersonalTable.Y[v.Species].CatchRate; + return PersonalTable.RB[v.Species].CatchRate; + } + } + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs index 424c18228..f130982a5 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs @@ -252,7 +252,7 @@ namespace PKHeX.Core return result; } - internal static void MarkEncounterTradeStrings(EncounterTrade[] table, string[][] strings) + internal static void MarkEncounterTradeStrings(T[] table, string[][] strings) where T : EncounterTrade { int half = strings[1].Length / 2; for (int i = 0; i < half; i++) diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs index 39b827d38..981964dcc 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using static PKHeX.Core.EncounterUtil; namespace PKHeX.Core @@ -19,7 +18,7 @@ namespace PKHeX.Core MarkEncountersGeneration(1, SlotsRBY); MarkEncountersGeneration(1, StaticRBY, TradeGift_RBY_NoTradeback, TradeGift_RBY_Tradeback); - var trades = TradeGift_RBY_Common.Concat(TradeGift_RBY_NoTradeback).Concat(TradeGift_RBY_Tradeback); + var trades = ArrayUtil.ConcatAll(TradeGift_RBY_Common, TradeGift_RBY_NoTradeback, TradeGift_RBY_Tradeback); foreach (var t in trades) { t.TrainerNames = TradeOTG1; @@ -136,74 +135,73 @@ namespace PKHeX.Core new EncounterStatic { Species = 151, Level = 5, IVs = new [] {15,15,15,15,15,15}, Version = GameVersion.VCEvents }, // Event Mew }; - internal static readonly EncounterTrade[] TradeGift_RBY_Common = + internal static readonly EncounterTrade1[] TradeGift_RBY_Common = { // Species & Minimum level (legal) possible to acquire at. //new EncounterTrade { Species = 122, Level = 06 }, // Mr. Mime - Game Corner Abra - new EncounterTrade { Species = 032, Level = 02, Version = GameVersion.RD }, // Nidoran♂ - Wild Nidoran♀ - new EncounterTrade { Species = 029, Level = 02, Version = GameVersion.BU }, // Nidoran♀ - Wild Nidoran♂ - new EncounterTrade { Species = 030, Level = 16, Version = GameVersion.RB }, // Nidorina - Evolve Nidorino - new EncounterTrade { Species = 030, Level = 16, Version = GameVersion.YW }, // Nidorina - Evolve Nidorino (Different initial moves) - new EncounterTrade { Species = 108, Level = 15, Version = GameVersion.RBY }, // Lickitung - Surf Slowbro - new EncounterTrade { Species = 083, Level = 02, Version = GameVersion.RBY }, // Farfetch’d - Wild Spearow - new EncounterTrade { Species = 101, Level = 03, Version = GameVersion.RBY }, // Electrode - Wild Raichu + new EncounterTrade1(032, 02) { Version = GameVersion.RD }, // Nidoran♂ - Wild Nidoran♀ + new EncounterTrade1(029, 02) { Version = GameVersion.BU }, // Nidoran♀ - Wild Nidoran♂ + new EncounterTrade1(030, 16) { Version = GameVersion.RB }, // Nidorina - Evolve Nidorino + new EncounterTrade1(030, 16) { Version = GameVersion.YW }, // Nidorina - Evolve Nidorino (Different initial moves) + new EncounterTrade1(108, 15) { Version = GameVersion.RBY }, // Lickitung - Surf Slowbro + new EncounterTrade1(083, 02) { Version = GameVersion.RBY }, // Farfetch’d - Wild Spearow + new EncounterTrade1(101, 03) { Version = GameVersion.RBY }, // Electrode - Wild Raichu - new EncounterTrade { Species = 122, Level = 03, Version = GameVersion.RBY }, // Mr. Mime - Wild Jigglypuff - new EncounterTrade { Species = 060, Level = 02, Version = GameVersion.RBY }, // Poliwag - Wild Rattata + new EncounterTrade1(122, 03) { Version = GameVersion.RBY }, // Mr. Mime - Wild Jigglypuff + new EncounterTrade1(060, 02) { Version = GameVersion.RBY }, // Poliwag - Wild Rattata //new EncounterTrade { Species = 083, Level = 02 }, // Farfetch’d - Wild Pidgey - new EncounterTradeCatchRate { Species = 093, Level = 28, Catch_Rate = 45, EvolveOnTrade = true, Version = GameVersion.RBY }, // Haunter - Evolve Machop->Machoke - new EncounterTradeCatchRate { Species = 075, Level = 16, Catch_Rate = 45, EvolveOnTrade = true, Version = GameVersion.RBY }, // Graveler - Evolve Abra->Kadabra + new EncounterTrade1(093, 28, 45) { EvolveOnTrade = true, Version = GameVersion.RBY }, // Haunter - Evolve Machop->Machoke + new EncounterTrade1(075, 16, 45) { EvolveOnTrade = true, Version = GameVersion.RBY }, // Graveler - Evolve Abra->Kadabra }; - internal static readonly EncounterTrade[] TradeGift_RBY_NoTradeback = TradeGift_RBY_Common.Concat(new[] + internal static readonly EncounterTrade1[] TradeGift_RBY_NoTradeback = ArrayUtil.ConcatAll(TradeGift_RBY_Common, new[] { // Species & Minimum level (legal) possible to acquire at. - new EncounterTrade { Species = 124, Level = 15, Version = GameVersion.RBY }, // Jynx - Fish Poliwhirl (GSC: 10) - new EncounterTrade { Species = 114, Level = 13, Version = GameVersion.RBY }, // Tangela - Wild Venonat (GSC: 5) No different moves at level 13 - new EncounterTrade { Species = 086, Level = 28, Version = GameVersion.RBY }, // Seel - Wild Ponyta (GSC: 5) + new EncounterTrade1(124, 15) { Version = GameVersion.RBY }, // Jynx - Fish Poliwhirl (GSC: 10) + new EncounterTrade1(114, 13) { Version = GameVersion.RBY }, // Tangela - Wild Venonat (GSC: 5) No different moves at level 13 + new EncounterTrade1(086, 28) { Version = GameVersion.RBY }, // Seel - Wild Ponyta (GSC: 5) - new EncounterTrade { Species = 115, Level = 15, Version = GameVersion.RBY }, // Kangaskhan - Trade Rhydon (GSC: 10) - new EncounterTrade { Species = 128, Level = 28, Version = GameVersion.RBY }, // Tauros - Evolve Persian (GSC: 18) - new EncounterTradeCatchRate { Species = 098, Level = 15, Catch_Rate = 204, Version = GameVersion.RBY }, // Krabby - Wild Growlithe (GSC: 5) + new EncounterTrade1(115, 15) { Version = GameVersion.RBY }, // Kangaskhan - Trade Rhydon (GSC: 10) + new EncounterTrade1(128, 28) { Version = GameVersion.RBY }, // Tauros - Evolve Persian (GSC: 18) + new EncounterTrade1(098, 15, 204) { Version = GameVersion.RBY }, // Krabby - Wild Growlithe (GSC: 5) //new EncounterTrade { Species = 122, Level = 08 }, // Mr. Mime - Wild Clefairy (GSC: 6) - new EncounterTrade { Species = 067, Level = 16, Version = GameVersion.RBY, EvolveOnTrade = true }, // Machoke - Wild Cubone (GSC: 5) - new EncounterTrade { Species = 112, Level = 15, Version = GameVersion.RBY }, // Rhydon - Surf Golduck (GSC: 10) - new EncounterTrade { Species = 087, Level = 15, Version = GameVersion.RBY }, // Dewgong - Wild Growlithe (GSC: 5) - new EncounterTrade { Species = 089, Level = 25, Version = GameVersion.RBY }, // Muk - Wild Kangaskhan (GSC: 5) + new EncounterTrade1(067, 16) { Version = GameVersion.RBY, EvolveOnTrade = true }, // Machoke - Wild Cubone (GSC: 5) + new EncounterTrade1(112, 15) { Version = GameVersion.RBY }, // Rhydon - Surf Golduck (GSC: 10) + new EncounterTrade1(087, 15) { Version = GameVersion.RBY }, // Dewgong - Wild Growlithe (GSC: 5) + new EncounterTrade1(089, 25) { Version = GameVersion.RBY }, // Muk - Wild Kangaskhan (GSC: 5) + new EncounterTrade1(079, 22) { Version = GameVersion.RBY }, // Slowpoke - Wild Seel (GSC 5) + new EncounterTrade1(051, 15) { Version = GameVersion.RBY }, // Dugtrio - Trade Lickitung (GSC 5) + new EncounterTrade1(047, 13) { Version = GameVersion.RBY }, // Parasect - Trade Tangela (GSC 5) + }); - new EncounterTrade { Species = 079, Level = 22, Version = GameVersion.RBY }, // Slowpoke - Wild Seel (GSC 5) - new EncounterTrade { Species = 051, Level = 15, Version = GameVersion.RBY }, // Dugtrio - Trade Lickitung (GSC 5) - new EncounterTrade { Species = 047, Level = 13, Version = GameVersion.RBY }, // Parasect - Trade Tangela (GSC 5) - }).ToArray(); - - internal static readonly EncounterTrade[] TradeGift_RBY_Tradeback = TradeGift_RBY_Common.Concat(new[] + internal static readonly EncounterTrade1[] TradeGift_RBY_Tradeback = ArrayUtil.ConcatAll(TradeGift_RBY_Common, new[] { // Trade gifts that can be obtained at a lower level due to the requested Pokémon being a lower level in GSC - new EncounterTrade { Species = 124, Level = 10, Version = GameVersion.RBY }, // Jynx - Fish Poliwhirl (RBY: 15) - new EncounterTrade { Species = 114, Level = 05, Version = GameVersion.RBY }, // Tangela - Wild Venonat (RBY: 13) - new EncounterTrade { Species = 086, Level = 05, Version = GameVersion.RBY }, // Seel - Egg Ponyta (RBY: 28) + new EncounterTrade1(124, 10) { Version = GameVersion.RBY }, // Jynx - Fish Poliwhirl (RBY: 15) + new EncounterTrade1(114, 05) { Version = GameVersion.RBY }, // Tangela - Wild Venonat (RBY: 13) + new EncounterTrade1(086, 05) { Version = GameVersion.RBY }, // Seel - Egg Ponyta (RBY: 28) - new EncounterTrade { Species = 115, Level = 10, Version = GameVersion.RBY }, // Kangaskhan - Trade Rhydon (RBY: 42) - new EncounterTrade { Species = 128, Level = 18, Version = GameVersion.RBY }, // Tauros - Evolve Persian (RBY: 28) - new EncounterTradeCatchRate { Species = 098, Level = 05, Catch_Rate = 204, Version = GameVersion.RBY }, // Krabby - Egg Growlithe (RBY: 15) + new EncounterTrade1(115, 10) { Version = GameVersion.RBY }, // Kangaskhan - Trade Rhydon (RBY: 42) + new EncounterTrade1(128, 18) { Version = GameVersion.RBY }, // Tauros - Evolve Persian (RBY: 28) + new EncounterTrade1(098, 05, 204) { Version = GameVersion.RBY }, // Krabby - Egg Growlithe (RBY: 15) - //new EncounterTrade { Species = 122, Level = 08 }, // Mr. Mime - Wild Clefairy (RBY: 6) - new EncounterTrade { Species = 067, Level = 05, Version = GameVersion.RBY, EvolveOnTrade = true }, // Machoke - Egg Cubone (RBY: 20) - new EncounterTrade { Species = 112, Level = 10, Version = GameVersion.RBY }, // Rhydon - Surf Golduck (RBY: 15) - new EncounterTrade { Species = 087, Level = 05, Version = GameVersion.RBY }, // Dewgong - Egg Growlithe (RBY: 15) - new EncounterTrade { Species = 089, Level = 05, Version = GameVersion.RBY }, // Muk - Egg Kangaskhan (RBY: 25) + //new EncounterTrade1(122, 08), // Mr. Mime - Wild Clefairy (RBY: 6) + new EncounterTrade1(067, 05) { Version = GameVersion.RBY, EvolveOnTrade = true }, // Machoke - Egg Cubone (RBY: 20) + new EncounterTrade1(112, 10) { Version = GameVersion.RBY }, // Rhydon - Surf Golduck (RBY: 15) + new EncounterTrade1(087, 05) { Version = GameVersion.RBY }, // Dewgong - Egg Growlithe (RBY: 15) + new EncounterTrade1(089, 05) { Version = GameVersion.RBY }, // Muk - Egg Kangaskhan (RBY: 25) - new EncounterTrade { Species = 079, Level = 05, Version = GameVersion.RBY }, // Slowpoke - Wild Seel (GSC 5) - new EncounterTrade { Species = 051, Level = 05, Version = GameVersion.RBY }, // Dugtrio - Trade Lickitung (GSC 5) - new EncounterTrade { Species = 047, Level = 05, Version = GameVersion.RBY }, // Parasect - Trade Tangela (GSC 5) - }).ToArray(); + new EncounterTrade1(079, 05) { Version = GameVersion.RBY }, // Slowpoke - Wild Seel (GSC 5) + new EncounterTrade1(051, 05) { Version = GameVersion.RBY }, // Dugtrio - Trade Lickitung (GSC 5) + new EncounterTrade1(047, 05) { Version = GameVersion.RBY }, // Parasect - Trade Tangela (GSC 5) + }); private static readonly EncounterArea1 FishOldGood_RBY = new EncounterArea1 { Location = -1, - Slots = new[] + Slots = new EncounterSlot[] { new EncounterSlot1 {Species = 129, LevelMin = 05, LevelMax = 05, Type = SlotType.Old_Rod, Rate = -1, Version = GameVersion.RBY }, // Magikarp new EncounterSlot1 {Species = 118, LevelMin = 10, LevelMax = 10, Type = SlotType.Good_Rod, Rate = -1, Version = GameVersion.RBY }, // Goldeen diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs index 061a26b3f..4f5374c0c 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs @@ -10,7 +10,7 @@ namespace PKHeX.Core internal static class Encounters2 { internal static readonly EncounterArea2[] SlotsGSC, SlotsGS, SlotsC; - internal static readonly EncounterStatic[] StaticGSC, StaticGS, StaticC; + internal static readonly EncounterStatic2[] StaticGSC, StaticGS, StaticC; private static readonly TreesArea[] HeadbuttTreesC = TreesArea.GetArray(BinLinker.Unpack(Util.GetBinaryResource("trees_h_c.pkl"), "ch")); static Encounters2() @@ -94,13 +94,6 @@ namespace PKHeX.Core return extra; } - private static readonly int[] Roaming_MetLocation_GSC_Grass = - { - // Routes 29, 30-31, 33, 34, 35, 36-37, 38-39, 42, 43, 44, 45-46 can be encountered in grass - 2, 4, 5, 8, 11, 15, 18, 20, 21, - 25, 26, 34, 37, 39, 43, 45, - }; - private static readonly EncounterArea2[] EncounterBCC_GSC = { new EncounterArea2 { Location = 19, Slots = new EncounterSlot[] @@ -135,84 +128,84 @@ namespace PKHeX.Core } }}; - private static readonly EncounterStatic[] Encounter_GSC_Common = + private static readonly EncounterStatic2[] Encounter_GSC_Common = { - new EncounterStatic { Species = 152, Level = 05, Location = 001, Version = GameVersion.GSC }, // Chikorita @ New Bark Town - new EncounterStatic { Species = 155, Level = 05, Location = 001, Version = GameVersion.GSC }, // Cyndaquil @ New Bark Town - new EncounterStatic { Species = 158, Level = 05, Location = 001, Version = GameVersion.GSC }, // Totodile @ New Bark Town + new EncounterStatic2(152, 05) { Location = 001, Version = GameVersion.GSC }, // Chikorita @ New Bark Town + new EncounterStatic2(155, 05) { Location = 001, Version = GameVersion.GSC }, // Cyndaquil @ New Bark Town + new EncounterStatic2(158, 05) { Location = 001, Version = GameVersion.GSC }, // Totodile @ New Bark Town - new EncounterStatic { Species = 175, Level = 05, Version = GameVersion.GSC, EggLocation = 256 }, // Togepi - new EncounterStatic { Species = 131, Level = 20, Location = 010, Version = GameVersion.GSC }, // Lapras @ Union Cave - new EncounterStatic { Species = 133, Level = 20, Location = 016, Version = GameVersion.GSC }, // Eevee @ Goldenrod City + new EncounterStatic2(175, 05) { Version = GameVersion.GSC, EggLocation = 256 }, // Togepi + new EncounterStatic2(131, 20) { Location = 010, Version = GameVersion.GSC }, // Lapras @ Union Cave + new EncounterStatic2(133, 20) { Location = 016, Version = GameVersion.GSC }, // Eevee @ Goldenrod City - new EncounterStatic { Species = 185, Level = 20, Location = 020, Version = GameVersion.GSC }, // Sudowoodo @ Route 36 - new EncounterStatic { Species = 236, Level = 10, Location = 035, Version = GameVersion.GSC }, // Tyrogue @ Mt. Mortar + new EncounterStatic2(185, 20) { Location = 020, Version = GameVersion.GSC }, // Sudowoodo @ Route 36 + new EncounterStatic2(236, 10) { Location = 035, Version = GameVersion.GSC }, // Tyrogue @ Mt. Mortar - new EncounterStatic { Species = 130, Level = 30, Location = 038, Version = GameVersion.GSC, Shiny = Shiny.Always, }, // Gyarados @ Lake of Rage - new EncounterStatic { Species = 074, Level = 21, Location = 036, Version = GameVersion.GSC }, // Geodude @ Rocket Hideout (Mahogany Town) - new EncounterStatic { Species = 109, Level = 21, Location = 036, Version = GameVersion.GSC }, // Koffing @ Rocket Hideout (Mahogany Town) - new EncounterStatic { Species = 100, Level = 23, Location = 036, Version = GameVersion.GSC }, // Voltorb @ Rocket Hideout (Mahogany Town) - new EncounterStatic { Species = 101, Level = 23, Location = 036, Version = GameVersion.GSC }, // Electrode @ Rocket Hideout (Mahogany Town) - new EncounterStatic { Species = 143, Level = 50, Location = 061, Version = GameVersion.GSC }, // Snorlax @ Vermillion City + new EncounterStatic2(130, 30) { Location = 038, Version = GameVersion.GSC, Shiny = Shiny.Always, }, // Gyarados @ Lake of Rage + new EncounterStatic2(074, 21) { Location = 036, Version = GameVersion.GSC }, // Geodude @ Rocket Hideout (Mahogany Town) + new EncounterStatic2(109, 21) { Location = 036, Version = GameVersion.GSC }, // Koffing @ Rocket Hideout (Mahogany Town) + new EncounterStatic2(100, 23) { Location = 036, Version = GameVersion.GSC }, // Voltorb @ Rocket Hideout (Mahogany Town) + new EncounterStatic2(101, 23) { Location = 036, Version = GameVersion.GSC }, // Electrode @ Rocket Hideout (Mahogany Town) + new EncounterStatic2(143, 50) { Location = 061, Version = GameVersion.GSC }, // Snorlax @ Vermillion City - new EncounterStatic { Species = 211, Level = 05, Location = 008, Version = GameVersion.GSC }, // Qwilfish Swarm @ Route 32 (Old Rod) - new EncounterStatic { Species = 211, Level = 20, Location = 008, Version = GameVersion.GSC }, // Qwilfish Swarm @ Route 32 (Good Rod) - new EncounterStatic { Species = 211, Level = 40, Location = 008, Version = GameVersion.GSC }, // Qwilfish Swarm @ Route 32 (Super Rod) + new EncounterStatic2(211, 05) { Location = 008, Version = GameVersion.GSC }, // Qwilfish Swarm @ Route 32 (Old Rod) + new EncounterStatic2(211, 20) { Location = 008, Version = GameVersion.GSC }, // Qwilfish Swarm @ Route 32 (Good Rod) + new EncounterStatic2(211, 40) { Location = 008, Version = GameVersion.GSC }, // Qwilfish Swarm @ Route 32 (Super Rod) - new EncounterStatic { Species = 083, Level = 05, Moves = new [] { 226, 14, 97, 163 }, Version = GameVersion.Stadium2 }, // Stadium 2 Baton Pass Farfetch'd - new EncounterStatic { Species = 207, Level = 05, Moves = new [] { 89, 68, 17 }, Version = GameVersion.Stadium2 }, // Stadium 2 Earthquake Gligar + new EncounterStatic2(083, 05) { Moves = new [] { 226, 14, 97, 163 }, Version = GameVersion.Stadium2 }, // Stadium 2 Baton Pass Farfetch'd + new EncounterStatic2(207, 05) { Moves = new [] { 89, 68, 17 }, Version = GameVersion.Stadium2 }, // Stadium 2 Earthquake Gligar // Gen2 Events // Pokémon Center Mystery Egg #1 (December 15, 2001 to January 14, 2002) - new EncounterStatic { Species = 152, Level = 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Chikorita Petal Dance - new EncounterStatic { Species = 173, Level = 05, Moves = new [] { 129 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Cleffa Swift - new EncounterStatic { Species = 194, Level = 05, Moves = new [] { 187 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Wooper Belly Drum - new EncounterStatic { Species = 231, Level = 05, Moves = new [] { 227 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Phanpy Encore - new EncounterStatic { Species = 238, Level = 05, Moves = new [] { 118 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Smoochum Metronome + new EncounterStatic2(152, 05) { Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Chikorita Petal Dance + new EncounterStatic2(173, 05) { Moves = new [] { 129 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Cleffa Swift + new EncounterStatic2(194, 05) { Moves = new [] { 187 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Wooper Belly Drum + new EncounterStatic2(231, 05) { Moves = new [] { 227 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Phanpy Encore + new EncounterStatic2(238, 05) { Moves = new [] { 118 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Smoochum Metronome // Pokémon Center Mystery Egg #2 (March 16 to April 7, 2002) - new EncounterStatic { Species = 047, Level = 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Psyduck Petal Dance - // new EncounterStatic { Species = 152, Level = 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Chikorita Petal Dance - new EncounterStatic { Species = 172, Level = 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Pichu Petal Dance - new EncounterStatic { Species = 173, Level = 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Cleffa Petal Dance - new EncounterStatic { Species = 174, Level = 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Igglybuff Petal Dance - new EncounterStatic { Species = 238, Level = 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Smoochum Petal Dance + new EncounterStatic2(047, 05) { Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Psyduck Petal Dance + // new EncounterStatic(152, 05, Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Chikorita Petal Dance + new EncounterStatic2(172, 05) { Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Pichu Petal Dance + new EncounterStatic2(173, 05) { Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Cleffa Petal Dance + new EncounterStatic2(174, 05) { Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Igglybuff Petal Dance + new EncounterStatic2(238, 05) { Moves = new [] { 080 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Smoochum Petal Dance // Pokémon Center Mystery Egg #3 (April 27 to May 12, 2002) - new EncounterStatic { Species = 001, Level = 05, Moves = new [] { 246 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Bulbasaur Ancientpower - new EncounterStatic { Species = 004, Level = 05, Moves = new [] { 242 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Charmander Crunch - new EncounterStatic { Species = 158, Level = 05, Moves = new [] { 066 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Totodile Submission - new EncounterStatic { Species = 163, Level = 05, Moves = new [] { 101 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Hoot-Hoot Night Shade - new EncounterStatic { Species = 158, Level = 05, Moves = new [] { 047 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Pichu Sing + new EncounterStatic2(001, 05) { Moves = new [] { 246 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Bulbasaur Ancientpower + new EncounterStatic2(004, 05) { Moves = new [] { 242 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Charmander Crunch + new EncounterStatic2(158, 05) { Moves = new [] { 066 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Totodile Submission + new EncounterStatic2(163, 05) { Moves = new [] { 101 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Hoot-Hoot Night Shade + new EncounterStatic2(158, 05) { Moves = new [] { 047 }, Version = GameVersion.EventsGBGen2, EggLocation = 256 }, // Pichu Sing }; - private static readonly EncounterStatic[] Encounter_GS_Exclusive = + private static readonly EncounterStatic2[] Encounter_GS_Exclusive = { - new EncounterStatic { Species = 245, Level = 40, Version = GameVersion.GS }, // Suicune + new EncounterStatic2(245, 40) { Version = GameVersion.GS }, // Suicune - new EncounterStatic { Species = 249, Level = 70, Version = GameVersion.GD }, // Lugia @ Whirl Islands - new EncounterStatic { Species = 249, Level = 40, Version = GameVersion.SV }, // Lugia @ Whirl Islands + new EncounterStatic2(249, 70) { Version = GameVersion.GD }, // Lugia @ Whirl Islands + new EncounterStatic2(249, 40) { Version = GameVersion.SV }, // Lugia @ Whirl Islands - new EncounterStatic { Species = 250, Level = 40, Version = GameVersion.GD }, // Ho-Oh @ Tin Tower - new EncounterStatic { Species = 250, Level = 70, Version = GameVersion.SV }, // Ho-Oh @ Tin Tower + new EncounterStatic2(250, 40) { Version = GameVersion.GD }, // Ho-Oh @ Tin Tower + new EncounterStatic2(250, 70) { Version = GameVersion.SV }, // Ho-Oh @ Tin Tower - new EncounterStatic { Species = 137, Level = 15, Version = GameVersion.GS }, // Porygon @ Celadon Game Corner - new EncounterStatic { Species = 133, Level = 15, Version = GameVersion.GS }, // Eevee @ Celadon Game Corner - new EncounterStatic { Species = 122, Level = 15, Version = GameVersion.GS }, // Mr. Mime @ Celadon Game Corner + new EncounterStatic2(137, 15) { Version = GameVersion.GS }, // Porygon @ Celadon Game Corner + new EncounterStatic2(133, 15) { Version = GameVersion.GS }, // Eevee @ Celadon Game Corner + new EncounterStatic2(122, 15) { Version = GameVersion.GS }, // Mr. Mime @ Celadon Game Corner - new EncounterStatic { Species = 063, Level = 10, Version = GameVersion.GS }, // Abra @ Goldenrod City (Game Corner) - new EncounterStatic { Species = 147, Level = 10, Version = GameVersion.GS }, // Dratini @ Goldenrod City (Game Corner) - new EncounterStatic { Species = 023, Level = 10, Version = GameVersion.GS }, // Ekans @ Goldenrod City (Game Corner) (Gold) - new EncounterStatic { Species = 027, Level = 10, Version = GameVersion.GS }, // Sandshrew @ Goldenrod City (Game Corner) (Silver) + new EncounterStatic2(063, 10) { Version = GameVersion.GS }, // Abra @ Goldenrod City (Game Corner) + new EncounterStatic2(147, 10) { Version = GameVersion.GS }, // Dratini @ Goldenrod City (Game Corner) + new EncounterStatic2(023, 10) { Version = GameVersion.GS }, // Ekans @ Goldenrod City (Game Corner) (Gold) + new EncounterStatic2(027, 10) { Version = GameVersion.GS }, // Sandshrew @ Goldenrod City (Game Corner) (Silver) - new EncounterStatic { Species = 223, Level = 05, Version = GameVersion.GS }, // Remoraid Swarm @ Route 44 (Old Rod) - new EncounterStatic { Species = 223, Level = 20, Version = GameVersion.GS }, // Remoraid Swarm @ Route 44 (Good Rod) - new EncounterStatic { Species = 223, Level = 40, Version = GameVersion.GS }, // Remoraid Swarm @ Route 44 (Super Rod) + new EncounterStatic2(223, 05) { Version = GameVersion.GS }, // Remoraid Swarm @ Route 44 (Old Rod) + new EncounterStatic2(223, 20) { Version = GameVersion.GS }, // Remoraid Swarm @ Route 44 (Good Rod) + new EncounterStatic2(223, 40) { Version = GameVersion.GS }, // Remoraid Swarm @ Route 44 (Super Rod) }; - private static readonly EncounterStatic[] Encounter_C_Exclusive = + private static readonly EncounterStatic2[] Encounter_C_Exclusive = { - new EncounterStatic { Species = 245, Level = 40, Location = 023, Version = GameVersion.C }, // Suicune @ Tin Tower + new EncounterStatic2(245, 40) { Location = 023, Version = GameVersion.C }, // Suicune @ Tin Tower new EncounterStatic2Odd(172), // Pichu Dizzy Punch new EncounterStatic2Odd(173), // Cleffa Dizzy Punch @@ -222,48 +215,48 @@ namespace PKHeX.Core new EncounterStatic2Odd(239), // Elekid Dizzy Punch new EncounterStatic2Odd(240), // Magby Dizzy Punch - new EncounterStatic { Species = 147, Level = 15, Location = 042, Version = GameVersion.C, Moves = new [] {245} }, // Dratini ExtremeSpeed + new EncounterStatic2(147, 15) { Location = 042, Version = GameVersion.C, Moves = new [] {245} }, // Dratini ExtremeSpeed - new EncounterStatic { Species = 249, Level = 60, Location = 031, Version = GameVersion.C }, // Lugia @ Whirl Islands - new EncounterStatic { Species = 250, Level = 60, Location = 023, Version = GameVersion.C }, // Ho-Oh @ Tin Tower - new EncounterStatic { Species = 251, Level = 30, Location = 014, Version = GameVersion.C }, // Celebi @ Ilex Forest (VC) - new EncounterStatic { Species = 251, Level = 30, Location = 014, Version = GameVersion.EventsGBGen2 }, // Celebi @ Ilex Forest (GBC) + new EncounterStatic2(249, 60) { Location = 031, Version = GameVersion.C }, // Lugia @ Whirl Islands + new EncounterStatic2(250, 60) { Location = 023, Version = GameVersion.C }, // Ho-Oh @ Tin Tower + new EncounterStatic2(251, 30) { Location = 014, Version = GameVersion.C }, // Celebi @ Ilex Forest (VC) + new EncounterStatic2(251, 30) { Location = 014, Version = GameVersion.EventsGBGen2 }, // Celebi @ Ilex Forest (GBC) - new EncounterStatic { Species = 137, Level = 15, Location = 071, Version = GameVersion.C }, // Porygon @ Celadon Game Corner - new EncounterStatic { Species = 025, Level = 25, Location = 071, Version = GameVersion.C }, // Pikachu @ Celadon Game Corner - new EncounterStatic { Species = 246, Level = 40, Location = 071, Version = GameVersion.C }, // Larvitar @ Celadon Game Corner + new EncounterStatic2(137, 15) { Location = 071, Version = GameVersion.C }, // Porygon @ Celadon Game Corner + new EncounterStatic2(025, 25) { Location = 071, Version = GameVersion.C }, // Pikachu @ Celadon Game Corner + new EncounterStatic2(246, 40) { Location = 071, Version = GameVersion.C }, // Larvitar @ Celadon Game Corner - new EncounterStatic { Species = 063, Level = 05, Location = 016, Version = GameVersion.C }, // Abra @ Goldenrod City (Game Corner) - new EncounterStatic { Species = 104, Level = 15, Location = 016, Version = GameVersion.C }, // Cubone @ Goldenrod City (Game Corner) - new EncounterStatic { Species = 202, Level = 15, Location = 016, Version = GameVersion.C }, // Wobbuffet @ Goldenrod City (Game Corner) + new EncounterStatic2(063, 05) { Location = 016, Version = GameVersion.C }, // Abra @ Goldenrod City (Game Corner) + new EncounterStatic2(104, 15) { Location = 016, Version = GameVersion.C }, // Cubone @ Goldenrod City (Game Corner) + new EncounterStatic2(202, 15) { Location = 016, Version = GameVersion.C }, // Wobbuffet @ Goldenrod City (Game Corner) }; - private static readonly EncounterStatic[] Encounter_GSC_Roam = + private static readonly EncounterStatic2[] Encounter_GSC_Roam = { - new EncounterStatic { Species = 243, Level = 40, Roaming = true }, // Raikou - new EncounterStatic { Species = 244, Level = 40, Roaming = true }, // Entei - new EncounterStatic { Species = 245, Level = 40, Roaming = true, Version = GameVersion.GS }, // Suicune + new EncounterStatic2Roam(243, 40) { Version = GameVersion.GSC }, // Raikou + new EncounterStatic2Roam(244, 40) { Version = GameVersion.GSC }, // Entei + new EncounterStatic2Roam(245, 40) { Version = GameVersion.GS }, // Suicune }; - private static readonly EncounterStatic[] Encounter_GS = Encounter_GSC_Common.Concat(Encounter_GS_Exclusive).Concat(Encounter_GSC_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_GSC_Grass))).ToArray(); - private static readonly EncounterStatic[] Encounter_C = Encounter_GSC_Common.Concat(Encounter_C_Exclusive).Concat(Encounter_GSC_Roam.Take(2).SelectMany(e => e.Clone(Roaming_MetLocation_GSC_Grass))).ToArray(); - private static readonly EncounterStatic[] Encounter_GSC = Encounter_GSC_Common.Concat(Encounter_GS_Exclusive).Concat(Encounter_C_Exclusive).Concat(Encounter_GSC_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_GSC_Grass))).ToArray(); + private static readonly EncounterStatic2[] Encounter_GS = Encounter_GSC_Common.Concat(Encounter_GS_Exclusive).Concat(Encounter_GSC_Roam).ToArray(); + private static readonly EncounterStatic2[] Encounter_C = Encounter_GSC_Common.Concat(Encounter_C_Exclusive).Concat(Encounter_GSC_Roam.Slice(0, 2)).ToArray(); + private static readonly EncounterStatic2[] Encounter_GSC = Encounter_GSC_Common.Concat(Encounter_GS_Exclusive).Concat(Encounter_C_Exclusive).Concat(Encounter_GSC_Roam).ToArray(); - internal static readonly EncounterTrade[] TradeGift_GSC = + internal static readonly EncounterTradeGB[] TradeGift_GSC = { - new EncounterTrade { Species = 095, Level = 03, Gender = 0, TID = 48926, IVs = new[] {08, 09, 06, 06, 06, 06} }, // Onix @ Violet City for Bellsprout [wild] - new EncounterTrade { Species = 066, Level = 05, Gender = 1, TID = 37460, IVs = new[] {12, 03, 07, 06, 06, 06} }, // Machop @ Goldenrod City for Drowzee [wild 9, hatched egg 5] - new EncounterTrade { Species = 100, Level = 05, Gender = 2, TID = 29189, IVs = new[] {08, 09, 08, 08, 08, 08} }, // Voltorb @ Olivine City for Krabby [egg] - new EncounterTrade { Species = 112, Level = 10, Gender = 1, TID = 00283, IVs = new[] {12, 07, 07, 06, 06, 06} }, // Rhydon @ Blackthorn City for Dragonair [wild] - new EncounterTrade { Species = 142, Level = 05, Gender = 0, TID = 26491, IVs = new[] {08, 09, 06, 06, 06, 06}, OTGender = 1}, // Aerodactyl @ Route 14 for Chansey [egg] - new EncounterTrade { Species = 078, Level = 14, Gender = 0, TID = 15616, IVs = new[] {08, 09, 06, 06, 06, 06} }, // Rapidash @ Pewter City for Gloom [wild] + new EncounterTrade2(095, 03, 48926) { Gender = 0, IVs = new[] {08, 09, 06, 06, 06, 06} }, // Onix @ Violet City for Bellsprout [wild] + new EncounterTrade2(066, 05, 37460) { Gender = 1, IVs = new[] {12, 03, 07, 06, 06, 06} }, // Machop @ Goldenrod City for Drowzee [wild 9, hatched egg 5] + new EncounterTrade2(100, 05, 29189) { Gender = 2, IVs = new[] {08, 09, 08, 08, 08, 08} }, // Voltorb @ Olivine City for Krabby [egg] + new EncounterTrade2(112, 10, 00283) { Gender = 1, IVs = new[] {12, 07, 07, 06, 06, 06} }, // Rhydon @ Blackthorn City for Dragonair [wild] + new EncounterTrade2(142, 05, 26491) { Gender = 0, IVs = new[] {08, 09, 06, 06, 06, 06}, OTGender = 1}, // Aerodactyl @ Route 14 for Chansey [egg] + new EncounterTrade2(078, 14, 15616) { Gender = 0, IVs = new[] {08, 09, 06, 06, 06, 06} }, // Rapidash @ Pewter City for Gloom [wild] - new EncounterTrade { Species = 085, Level = 10, Gender = 1, TID = 00283, IVs = new[] {12, 07, 07, 06, 06, 06}, OTGender = 1}, // Dodrio @ Blackthorn City for Dragonair [wild] - new EncounterTrade { Species = 178, Level = 15, Gender = 0, TID = 15616, IVs = new[] {08, 09, 06, 08, 06, 06} }, // Xatu @ Pewter City for Haunter [wild] - new EncounterTrade { Species = 082, Level = 05, Gender = 2, TID = 50082, IVs = new[] {08, 09, 06, 06, 06, 06} }, // Magneton @ Power Plant for Dugtrio [traded for Lickitung] + new EncounterTrade2(085, 10, 00283) { Gender = 1, IVs = new[] {12, 07, 07, 06, 06, 06}, OTGender = 1}, // Dodrio @ Blackthorn City for Dragonair [wild] + new EncounterTrade2(178, 15, 15616) { Gender = 0, IVs = new[] {08, 09, 06, 08, 06, 06} }, // Xatu @ Pewter City for Haunter [wild] + new EncounterTrade2(082, 05, 50082) { Gender = 2, IVs = new[] {08, 09, 06, 06, 06, 06} }, // Magneton @ Power Plant for Dugtrio [traded for Lickitung] - new EncounterTrade { Species = 021, Level = 10, TID = 01001, Moves = new[] {64,45,43} }, // Spearow @ Goldenrod City for free - new EncounterTrade { Species = 213, Level = 15, TID = 00518 }, // Shuckle @ Cianwood City for free + new EncounterTrade2(021, 10, 01001) { Moves = new[] {64,45,43} }, // Spearow @ Goldenrod City for free + new EncounterTrade2(213, 15, 00518), // Shuckle @ Cianwood City for free }; private const string tradeGSC = "tradegsc"; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs index 8b9055e86..5549dcb50 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs @@ -156,18 +156,15 @@ namespace PKHeX.Core pk.EggMetDate = today; } - private void SetMetData(PKM pk, int level, DateTime today) + protected virtual void SetMetData(PKM pk, int level, DateTime today) { - if (pk.Format > 2 || Version == GameVersion.C) - { - pk.Met_Location = Location; - pk.Met_Level = level; - if (Version == GameVersion.C && pk is PK2 pk2) - pk2.Met_TimeOfDay = EncounterTime.Any.RandomValidTime(); + if (pk.Format <= 2) + return; - if (pk.Format >= 4) - pk.MetDate = today; - } + pk.Met_Location = Location; + pk.Met_Level = level; + if (pk.Format >= 4) + pk.MetDate = today; } private void SetEncounterMoves(PKM pk, GameVersion version, int level) @@ -297,43 +294,13 @@ namespace PKHeX.Core return Form == pkm.AltForm || Legal.IsFormChangeable(pkm, Species, Form); } - private bool IsMatchEggLocation(PKM pkm, ref int lvl) + protected virtual bool IsMatchEggLocation(PKM pkm, ref int lvl) { if (Generation == 3 && EggLocation != 0) // Gen3 Egg { if (pkm.Format == 3 && pkm.IsEgg && EggLocation != pkm.Met_Location) return false; } - else if (Generation <= 2 && EggLocation != 0) // Gen2 Egg - { - if (pkm.Format > 2) - return true; - - if (pkm.IsEgg) - { - if (pkm.Met_Location != 0 && pkm.Met_Level != 0) - return false; - if (pkm.OT_Friendship > EggCycles) // Dizzy Punch eggs start with below-normal hatch counters. - return false; - } - else - { - switch (pkm.Met_Level) - { - case 0 when pkm.Met_Location != 0: - return false; - case 1 when pkm.Met_Location == 0: - return false; - default: - if (pkm.Met_Location == 0 && pkm.Met_Level != 0) - return false; - break; - } - } - - if (pkm.Met_Level == 1) // Gen2 Eggs are met at 1, and hatch at level 5. - lvl = 5; - } else if (EggLocation != pkm.Egg_Location) { if (pkm.IsEgg) // unhatched @@ -353,7 +320,7 @@ namespace PKHeX.Core if (!Locations.IsPtHGSSLocationEgg(EggLocation)) // non-Pt/HGSS egg gift return false; // transferring 4->5 clears pt/hgss location value and keeps Faraway Place - if (pkm.Egg_Location != 3002) // Faraway Place + if (pkm.Egg_Location != Locations.Faraway4) // Faraway Place return false; } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2.cs new file mode 100644 index 000000000..fa114f889 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2.cs @@ -0,0 +1,104 @@ +using System; +using System.Linq; + +namespace PKHeX.Core +{ + public class EncounterStatic2 : EncounterStatic + { + public sealed override int Level { get; set; } + + public EncounterStatic2(int species, int level) + { + Species = species; + Level = level; + } + + protected override bool IsMatchEggLocation(PKM pkm, ref int lvl) + { + if (pkm.Format > 2) + return true; + + if (pkm.IsEgg) + { + if (pkm.Met_Location != 0 && pkm.Met_Level != 0) + return false; + if (pkm.OT_Friendship > EggCycles) // Dizzy Punch eggs start with below-normal hatch counters. + return false; + } + else + { + switch (pkm.Met_Level) + { + case 0 when pkm.Met_Location != 0: + return false; + case 1 when pkm.Met_Location == 0: + return false; + default: + if (pkm.Met_Location == 0 && pkm.Met_Level != 0) + return false; + break; + } + } + + if (pkm.Met_Level == 1) // Gen2 Eggs are met at 1, and hatch at level 5. + lvl = 5; + + return true; + } + + protected override void SetMetData(PKM pk, int level, DateTime today) + { + pk.Met_Location = Location; + pk.Met_Level = level; + if (Version == GameVersion.C && pk is PK2 pk2) + pk2.Met_TimeOfDay = EncounterTime.Any.RandomValidTime(); + } + } + + public sealed class EncounterStatic2Odd : EncounterStatic2 + { + private const int Dizzy = 146; + private static readonly int[] _dizzy = { Dizzy }; + + public EncounterStatic2Odd(int species) : base(species, 5) + { + Version = GameVersion.C; + Moves = _dizzy; + EggLocation = 256; + EggCycles = 20; + } + + public override bool IsMatch(PKM pkm, int lvl) + { + // Let it get picked up as regular EncounterEgg under other conditions. + if (pkm.Format > 2) + return false; + if (pkm.Move1 != Dizzy && pkm.Move2 != Dizzy && pkm.Move3 != Dizzy && pkm.Move4 != Dizzy) + return false; + if (pkm.IsEgg && pkm.EXP != 125) + return false; + return base.IsMatch(pkm, lvl); + } + } + + public sealed class EncounterStatic2Roam : EncounterStatic2 + { + private static readonly int[] Roaming_MetLocation_GSC_Grass = + { + // Routes 29, 30-31, 33, 34, 35, 36-37, 38-39, 42, 43, 44, 45-46 can be encountered in grass + 2, 4, 5, 8, 11, 15, 18, 20, 21, + 25, 26, 34, 37, 39, 43, 45, + }; + + public override int Location => Roaming_MetLocation_GSC_Grass[0]; + + public EncounterStatic2Roam(int species, int level) : base(species, level) { } + + protected override bool IsMatchLocation(PKM pkm) + { + if (!pkm.HasOriginalMetLocation) + return true; + return Roaming_MetLocation_GSC_Grass.Contains(Location); + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2Odd.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2Odd.cs deleted file mode 100644 index 0638f40ca..000000000 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2Odd.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace PKHeX.Core -{ - public sealed class EncounterStatic2Odd : EncounterStatic - { - private const int Dizzy = 146; - private static readonly int[] _dizzy = { Dizzy }; - - public EncounterStatic2Odd(int species) - { - Species = species; - Level = 5; - Version = GameVersion.C; - Moves = _dizzy; - EggLocation = 256; - EggCycles = 20; - } - - public override bool IsMatch(PKM pkm, int lvl) - { - // Let it get picked up as regular EncounterEgg under other conditions. - if (pkm.Format > 2) - return false; - if (pkm.Move1 != Dizzy && pkm.Move2 != Dizzy && pkm.Move3 != Dizzy && pkm.Move4 != Dizzy) - return false; - if (pkm.IsEgg && pkm.EXP != 125) - return false; - return base.IsMatch(pkm, lvl); - } - } -} \ No newline at end of file diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs index 3cc0ea30b..c0735ae26 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs @@ -130,9 +130,6 @@ namespace PKHeX.Core if (EggLocation != 0) SetEggMetData(pk, time); - if (pk is PK1 pk1 && this is EncounterTradeCatchRate c) - pk1.Catch_Rate = (int) c.Catch_Rate; - if (pk is IContestStats s) this.CopyContestStatsTo(s); @@ -304,144 +301,5 @@ namespace PKHeX.Core return true; } - - public bool IsMatchVC1(PKM pkm) - { - if (Level > pkm.CurrentLevel) // minimum required level - return false; - if (!(pkm is PK1 pk1)|| !pkm.Gen1_NotTradeback) - return true; - - // Even if the in game trade uses the tables with source pokemon allowing generation 2 games, the traded pokemon could be a non-tradeback pokemon - var rate = pk1.Catch_Rate; - if (this is EncounterTradeCatchRate r) - { - if (rate != r.Catch_Rate) - return false; - } - else - { - if (Version == GameVersion.YW && rate != PersonalTable.Y[Species].CatchRate) - return false; - if (Version != GameVersion.YW && rate != PersonalTable.RB[Species].CatchRate) - return false; - } - return true; - } - - public bool IsMatchVC2(PKM pkm) - { - if (Level > pkm.CurrentLevel) // minimum required level - return false; - if (TID != pkm.TID) - return false; - if (pkm.Format <= 2) - { - if (Gender >= 0 && Gender != pkm.Gender) - return false; - if (IVs.Count != 0 && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pkm)) - return false; - } - if (pkm.Met_Location != 0 && pkm.Format == 2 && pkm.Met_Location != 126) - return false; - - if (!IsValidTradeOT12Gender(pkm)) - return false; - return IsValidTradeOT12(pkm); - } - - private bool IsValidTradeOT12Gender(PKM pkm) - { - if (OTGender == 1) - { - // Female, can be cleared if traded to RBY (clears met location) - if (pkm.Format <= 2) - return pkm.OT_Gender == (pkm.Met_Location != 0 ? 1 : 0); - return pkm.OT_Gender == 0 || !pkm.VC1; // require male except if transferred from GSC - } - return pkm.OT_Gender == 0; - } - - private bool IsValidTradeOT12(PKM pkm) - { - var OT = pkm.OT_Name; - if (pkm.Japanese) - return TrainerNames[(int)LanguageID.Japanese] == OT; - if (pkm.Korean) - return TrainerNames[(int)LanguageID.Korean] == OT; - - if (pkm.Format >= 7) - { - switch (Species) - { - case (int)Core.Species.Voltorb: - // Spanish FALCÁN trade loses the accented A on transfer - if (OT == "FALCÁN") - return false; - if (OT == "FALC N") - return true; - break; - case (int)Core.Species.Shuckle: - // Spanish MANÍA trade loses the accented I on transfer - if (OT == "MANÍA") - return false; - if (OT == "MAN A") - return true; - break; - } - } - - const int start = (int)LanguageID.English; - const int end = (int)LanguageID.Spanish; - - for (int i = start; i <= end; i++) - { - if (TrainerNames[i] == OT) - return true; - } - return false; - } - } - - public sealed class EncounterTrade6 : EncounterTrade, IMemoryOT - { - public int OT_Memory { get; } - public int OT_Intensity { get; } - public int OT_Feeling { get; } - public int OT_TextVar { get; } - - public EncounterTrade6(int m, int i, int f, int v) - { - OT_Memory = m; - OT_Intensity = i; - OT_Feeling = f; - OT_TextVar = v; - } - - protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) - { - base.ApplyDetails(sav, criteria, pk); - pk.OT_Memory = OT_Memory; - pk.OT_Intensity = OT_Intensity; - pk.OT_Feeling = OT_Feeling; - pk.OT_TextVar = OT_TextVar; - } - } - - public sealed class EncounterTrade7 : EncounterTrade, IMemoryOT - { - public int OT_Memory => 1; - public int OT_Intensity => 3; - public int OT_Feeling => 5; - public int OT_TextVar => 40; - - protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) - { - base.ApplyDetails(sav, criteria, pk); - pk.OT_Memory = OT_Memory; - pk.OT_Intensity = OT_Intensity; - pk.OT_Feeling = OT_Feeling; - pk.OT_TextVar = OT_TextVar; - } } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade1.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade1.cs new file mode 100644 index 000000000..6c53c6839 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade1.cs @@ -0,0 +1,52 @@ +namespace PKHeX.Core +{ + /// + /// Trade Encounter data with a fixed Catch Rate + /// + /// + /// Generation 1 specific value used in detecting unmodified/untraded Generation 1 Trade Encounter data. + /// + public sealed class EncounterTrade1 : EncounterTradeGB + { + /// + /// value the encounter is found with. + /// + /// + /// Gen1 Pokémon have a Catch Rate value when created by the game; depends on the origin version. + /// Few encounters use a value not from the game's Personal data. + /// + private readonly byte Catch_Rate; + + private bool HasOddCatchRate => Catch_Rate != 0; + + public EncounterTrade1(int species, int level, byte rate) : this(species, level) => Catch_Rate = rate; + public EncounterTrade1(int species, int level) : base(species, level) { } + + public byte GetInitialCatchRate() + { + if (HasOddCatchRate) + return Catch_Rate; + + var pt = Version == GameVersion.YW ? PersonalTable.Y : PersonalTable.RB; + return (byte)pt[Species].CatchRate; + } + + protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) + { + base.ApplyDetails(sav, criteria, pk); + var pk1 = (PK1)pk; + pk1.Catch_Rate = GetInitialCatchRate(); + } + + public override bool IsMatch(PKM pkm) + { + if (Level > pkm.CurrentLevel) // minimum required level + return false; + if (!(pkm is PK1 pk1) || !pkm.Gen1_NotTradeback) + return true; + + var req = GetInitialCatchRate(); + return req == pk1.Catch_Rate; + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs new file mode 100644 index 000000000..3564bd4c1 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs @@ -0,0 +1,86 @@ +using static PKHeX.Core.Species; + +namespace PKHeX.Core +{ + public sealed class EncounterTrade2 : EncounterTradeGB + { + public EncounterTrade2(int species, int level, int tid) : base(species, level) + { + TID = tid; + } + + public override bool IsMatch(PKM pkm) + { + if (Level > pkm.CurrentLevel) // minimum required level + return false; + if (TID != pkm.TID) + return false; + + if (pkm.Format <= 2) + { + if (Gender >= 0 && Gender != pkm.Gender) + return false; + if (IVs.Count != 0 && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pkm)) + return false; + if (pkm.Format == 2 && pkm.Met_Location != 0 && pkm.Met_Location != 126) + return false; + } + + if (!IsValidTradeOTGender(pkm)) + return false; + return IsValidTradeOTName(pkm); + } + + private bool IsValidTradeOTGender(PKM pkm) + { + if (OTGender == 1) + { + // Female, can be cleared if traded to RBY (clears met location) + if (pkm.Format <= 2) + return pkm.OT_Gender == (pkm.Met_Location != 0 ? 1 : 0); + return pkm.OT_Gender == 0 || !pkm.VC1; // require male except if transferred from GSC + } + return pkm.OT_Gender == 0; + } + + private bool IsValidTradeOTName(PKM pkm) + { + var OT = pkm.OT_Name; + if (pkm.Japanese) + return GetOT((int)LanguageID.Japanese) == OT; + if (pkm.Korean) + return GetOT((int)LanguageID.Korean) == OT; + + if (pkm.Format >= 7) + { + switch (Species) + { + case (int)Voltorb: + // Spanish FALCÁN trade loses the accented A on transfer + if (OT == "FALCÁN") + return false; + if (OT == "FALC N") + return true; + break; + case (int)Shuckle: + // Spanish MANÍA trade loses the accented I on transfer + if (OT == "MANÍA") + return false; + if (OT == "MAN A") + return true; + break; + } + } + + const int start = (int)LanguageID.English; + const int end = (int)LanguageID.Spanish; + + for (int i = start; i <= end; i++) + { + if (TrainerNames[i] == OT) + return true; + } + return false; + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade6.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade6.cs new file mode 100644 index 000000000..8d423d9b5 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade6.cs @@ -0,0 +1,27 @@ +namespace PKHeX.Core +{ + public sealed class EncounterTrade6 : EncounterTrade, IMemoryOT + { + public int OT_Memory { get; } + public int OT_Intensity { get; } + public int OT_Feeling { get; } + public int OT_TextVar { get; } + + public EncounterTrade6(int m, int i, int f, int v) + { + OT_Memory = m; + OT_Intensity = i; + OT_Feeling = f; + OT_TextVar = v; + } + + protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) + { + base.ApplyDetails(sav, criteria, pk); + pk.OT_Memory = OT_Memory; + pk.OT_Intensity = OT_Intensity; + pk.OT_Feeling = OT_Feeling; + pk.OT_TextVar = OT_TextVar; + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade7.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade7.cs new file mode 100644 index 000000000..7e86a4782 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade7.cs @@ -0,0 +1,19 @@ +namespace PKHeX.Core +{ + public sealed class EncounterTrade7 : EncounterTrade, IMemoryOT + { + public int OT_Memory => 1; + public int OT_Intensity => 3; + public int OT_Feeling => 5; + public int OT_TextVar => 40; + + protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) + { + base.ApplyDetails(sav, criteria, pk); + pk.OT_Memory = OT_Memory; + pk.OT_Intensity = OT_Intensity; + pk.OT_Feeling = OT_Feeling; + pk.OT_TextVar = OT_TextVar; + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTradeCatchRate.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTradeCatchRate.cs deleted file mode 100644 index 52b530cab..000000000 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTradeCatchRate.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace PKHeX.Core -{ - /// - /// Trade Encounter data with a fixed Catch Rate - /// - /// - /// Generation 1 specific value used in detecting unmodified/untraded Generation 1 Trade Encounter data. - /// - public sealed class EncounterTradeCatchRate : EncounterTrade - { - /// - /// value the encounter is found with. - /// - public uint Catch_Rate; - } -} \ No newline at end of file diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTradeGB.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTradeGB.cs new file mode 100644 index 000000000..3725ebece --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTradeGB.cs @@ -0,0 +1,13 @@ +namespace PKHeX.Core +{ + public abstract class EncounterTradeGB : EncounterTrade + { + public EncounterTradeGB(int species, int level) + { + Species = species; + Level = level; + } + + public abstract bool IsMatch(PKM pkm); + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs index 60cf53fbf..514a55112 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs @@ -36,7 +36,7 @@ namespace PKHeX.Core int lvl = IsNotTrade(pkm); if (lvl <= 0) - return Enumerable.Empty(); + return Array.Empty(); var poss = GetPossibleNonVC(pkm, chain, gameSource); return poss.Where(z => z.IsMatch(pkm, lvl)); @@ -47,26 +47,26 @@ namespace PKHeX.Core if (gameSource == GameVersion.Any) gameSource = (GameVersion)pkm.Version; - if (pkm.VC || pkm.Format <= 2) + if (GetIsFromGB(pkm)) return GetValidEncounterTradesVC(pkm, chain, gameSource); var table = GetEncounterTradeTable(pkm); return table.Where(f => chain.Any(r => r.Species == f.Species)); } - private static IEnumerable GetPossibleVC(IReadOnlyList chain, GameVersion gameSource = GameVersion.Any) + private static IEnumerable GetPossibleVC(IReadOnlyList chain, GameVersion gameSource = GameVersion.Any) { var table = GetEncounterTradeTableVC(gameSource); - return table.Where(f => chain.Any(r => r.Species == f.Species)); + return table.Where(f => chain.Any(r => r.Species == f.Species && r.Form == 0)); } - private static IEnumerable GetEncounterTradeTableVC(GameVersion gameSource) + private static IEnumerable GetEncounterTradeTableVC(GameVersion gameSource) { if (GameVersion.RBY.Contains(gameSource)) return !ParseSettings.AllowGen1Tradeback ? Encounters1.TradeGift_RBY_NoTradeback : Encounters1.TradeGift_RBY_Tradeback; if (GameVersion.GSC.Contains(gameSource)) return Encounters2.TradeGift_GSC; - return Array.Empty(); + return Array.Empty(); } private static IEnumerable GetEncounterTradeTable(PKM pkm) @@ -83,12 +83,10 @@ namespace PKHeX.Core }; } - private static IEnumerable GetValidEncounterTradesVC(PKM pkm, IReadOnlyList chain, GameVersion gameSource) + private static IEnumerable GetValidEncounterTradesVC(PKM pkm, IReadOnlyList chain, GameVersion gameSource) { var poss = GetPossibleVC(chain, gameSource); - if (gameSource == GameVersion.RBY) - return poss.Where(z => z.IsMatchVC1(pkm)); - return poss.Where(z => z.IsMatchVC2(pkm)); + return poss.Where(z => z.IsMatch(pkm)); } private static bool GetIsFromGB(PKM pkm) => pkm.VC || pkm.Format <= 2; diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs index cccf27b7f..ad0065ce4 100644 --- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs @@ -135,7 +135,7 @@ namespace PKHeX.Core CheckResult GetWasNotTradeback() { - if ((e is EncounterStatic s && s.Version == GameVersion.Stadium) || e is EncounterTradeCatchRate) + if ((e is EncounterStatic s && s.Version == GameVersion.Stadium) || e is EncounterTrade1) return GetValid(LG1CatchRateMatchPrevious); // Encounters detected by the catch rate, cant be invalid if match this encounters if ((pk1.Species == 149 && catch_rate == PersonalTable.Y[149].CatchRate) || (GBRestrictions.Species_NotAvailable_CatchRate.Contains(pk1.Species) && catch_rate == PersonalTable.RB[pk1.Species].CatchRate)) return GetInvalid(LG1CatchRateEvo); diff --git a/PKHeX.WinForms/Controls/PKM Editor/CatchRate.cs b/PKHeX.WinForms/Controls/PKM Editor/CatchRate.cs index 842195355..3fc705f3d 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/CatchRate.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/CatchRate.cs @@ -16,36 +16,7 @@ namespace PKHeX.WinForms.Controls private void Reset(object sender, EventArgs e) { var sav = WinFormsUtil.FindFirstControlOfType(this).RequestSaveFile; - NUD_CatchRate.Value = GetSuggestedPKMCatchRate(pk1, sav); - } - - private static int GetSuggestedPKMCatchRate(PK1 pk1, SaveFile sav) - { - var la = new LegalityAnalysis(pk1); - if (la.Valid) - return pk1.Catch_Rate; - - if (la.Info.Generation == 2) - return 0; - - var enc = la.EncounterOriginal; - switch (enc) - { - case EncounterTradeCatchRate c: - return (int)c.Catch_Rate; - case EncounterStatic s when s.Version == GameVersion.Stadium && s.Species == (int)Species.Psyduck: - return pk1.Japanese ? 167 : 168; // Amnesia Psyduck has different catch rates depending on language - case IVersion v: - { - if (sav.Version.Contains(v.Version) || v.Version.Contains(sav.Version)) - return sav.Personal[enc.Species].CatchRate; - if (!GameVersion.RB.Contains(v.Version)) - return PersonalTable.Y[enc.Species].CatchRate; - return PersonalTable.RB[enc.Species].CatchRate; - } - default: - return sav.Personal[enc.Species].CatchRate; - } + NUD_CatchRate.Value = CatchRateApplicator.GetSuggestedPKMCatchRate(pk1, sav); } } }