diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 1908f8b71..a5a4b1911 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -954,6 +954,18 @@ private static SAV3GCMemoryCard CheckGCMemoryCard(byte[] Data, string path) return MC; } + private void StoreLegalSaveGameData(SaveFile sav) + { + Legal.SavegameJapanese = sav.Japanese; + Legal.EReaderBerryIsEnigma = sav.eBerryIsEnigma; + Legal.EReaderBerryName = sav.eBerryName; + Legal.Savegame_Gender = sav.Gender; + Legal.Savegame_TID = sav.TID; + Legal.Savegame_SID = sav.SID; + Legal.Savegame_OT = sav.OT; + Legal.Savegame_Version = sav.Version; + } + private void openSAV(SaveFile sav, string path) { if (sav == null || sav.Version == GameVersion.Invalid) @@ -1033,9 +1045,7 @@ private void openSAV(SaveFile sav, string path) sav.Japanese = drJP == DialogResult.No; } - Legal.SavegameJapanese = sav.Japanese; - Legal.EReaderBerryIsEnigma = sav.eBerryIsEnigma; - Legal.EReaderBerryName = sav.eBerryName; + StoreLegalSaveGameData(sav); loadingSAV = true; // clean fields diff --git a/PKHeX/Legality/Analysis.cs b/PKHeX/Legality/Analysis.cs index cb5c8d6b3..a4d097eb2 100644 --- a/PKHeX/Legality/Analysis.cs +++ b/PKHeX/Legality/Analysis.cs @@ -236,8 +236,10 @@ private void updateTradebackG12() // Dragonite's Catch Rate is different than Dragonair's in Yellow, but there is no Dragonite encounter. var RGBCatchRate = Lineage.Any(s => catch_rate == PersonalTable.RB[s].CatchRate); var YCatchRate = Lineage.Any(s => s != 149 && catch_rate == PersonalTable.Y[s].CatchRate); - - bool matchAny = RGBCatchRate || YCatchRate; + // Krabby encounter trade special catch rate + var TradeCatchRate = ((pkm.Species == 098 || pkm.Species == 099) && catch_rate == 204); + var StadiumCatchRate = Legal.Stadium_GiftSpecies.Contains(pkm.Species) && Legal.Stadium_CatchRate.Contains(catch_rate); + bool matchAny = RGBCatchRate || YCatchRate || TradeCatchRate || StadiumCatchRate; // If the catch rate value has been modified, the item has either been removed or swapped in Generation 2. var HeldItemCatchRate = catch_rate == 0 || Legal.HeldItems_GSC.Any(h => h == catch_rate); @@ -250,7 +252,7 @@ private void updateTradebackG12() // Update the editing settings for the PKM to acknowledge the tradeback status if the species is changed. - ((PK1)pkm).CatchRateIsItem = !pkm.Gen1_NotTradeback && HeldItemCatchRate && matchAny; + ((PK1)pkm).CatchRateIsItem = !pkm.Gen1_NotTradeback && HeldItemCatchRate && !matchAny; } else if (pkm.Format == 2 || pkm.VC2) { @@ -276,7 +278,11 @@ private void updateTypeInfo() if (pkm.VC && pkm.Format == 7) EncounterMatch = Legal.getRBYStaticTransfer(pkm.Species); - MatchedType = Type = (EncounterOriginalGB ?? EncounterMatch ?? pkm.Species).GetType(); + if (pkm.GenNumber <= 2 && pkm.TradebackStatus == TradebackType.Any && EncountersGBMatch.All(e => e.Generation != pkm.GenNumber)) + // Example: GSC Pokemon with only possible encounters in RBY, like the legendary birds + pkm.TradebackStatus = TradebackType.WasTradeback; + + MatchedType = Type = (EncounterOriginalGB ?? EncounterMatch ?? pkm.Species)?.GetType(); var bt = Type.BaseType; if (bt != null && !(bt == typeof(Array) || bt == typeof(object) || bt.IsPrimitive)) // a parent exists Type = bt; // use base type diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index e9d232946..5f24ab662 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -500,6 +500,15 @@ private void verifyG1OT() if (tr != "GF" && tr != "ゲーフリ") // if there are more events with special OTs, may be worth refactoring AddLine(Severity.Invalid, V39, CheckIdentifier.Trainer); } + if((EncounterMatch as EncounterStatic)?.Version == GameVersion.Stadium) + { + if(tr == "STADIUM" && pkm.TID == 2000) + AddLine(Severity.Valid, V403, CheckIdentifier.Trainer); + else if (tr == "スタジアム" && pkm.TID == 1999) + AddLine(Severity.Valid, V404, CheckIdentifier.Trainer); + else + AddLine(Severity.Invalid, V402, CheckIdentifier.Trainer); + } } #endregion private void verifyHyperTraining() @@ -739,6 +748,8 @@ private CheckResult verifyEncounterStatic() switch (pkm.GenNumber) { case 3: + if ((( EncounterMatch as EncounterStaticShadow)?.EReader ?? false) && pkm.Language != 1) // Non-JP E-reader Pokemon + return new CheckResult(Severity.Invalid, V406, CheckIdentifier.Encounter); if (pkm.Species == 151 && s.Location == 201 && pkm.Language != 1) // Non-JP Mew (Old Sea Map) return new CheckResult(Severity.Invalid, V353, CheckIdentifier.Encounter); break; @@ -769,6 +780,16 @@ private CheckResult verifyEncounterStatic() } private CheckResult verifyEncounterTrade() { + var trade = (EncounterTrade)EncounterMatch; + if (trade.Species == pkm.Species && trade.EvolveOnTrade) + { + // Pokemon that evolve on trade can not be in the phase evolution after the trade + // If the trade holds an everstone EvolveOnTrade will be false for the encounter + var species = specieslist; + var unevolved = species[pkm.Species]; + var evolved = species[pkm.Species + 1]; + return new CheckResult(Severity.Invalid, string.Format(V401, unevolved, evolved), CheckIdentifier.Encounter); + } return new CheckResult(Severity.Valid, V76, CheckIdentifier.Encounter); } private CheckResult verifyEncounterG12() @@ -782,7 +803,7 @@ private CheckResult verifyEncounterG12() pkm.WasEgg = true; return verifyEncounterEgg(); } - EncounterMatch = EncounterOriginalGB = EncountersGBMatch.FirstOrDefault()?.Encounter; + EncounterMatch = EncounterOriginalGB = EncountersGBMatch?.FirstOrDefault()?.Encounter; if (EncounterMatch is EncounterSlot) return new CheckResult(Severity.Valid, V68, CheckIdentifier.Encounter); if (EncounterMatch is EncounterStatic) @@ -831,14 +852,8 @@ private void verifyEncounterType() if (EncounterMatch is EncounterStaticTyped) type = ((EncounterStaticTyped)EncounterMatch).TypeEncounter; } - if (type == EncounterType.Any) - { - // Temp analysis until all generation 4 static encounters have defined their encounter type values - AddLine(Severity.NotImplemented, V382, CheckIdentifier.Encounter); - return; - } - if (type != (EncounterType)pkm.EncounterType) + if (!type.Contains(pkm.EncounterType)) AddLine(Severity.Invalid, V381, CheckIdentifier.Encounter); else AddLine(Severity.Valid, V380, CheckIdentifier.Encounter); @@ -1126,6 +1141,20 @@ private void verifyLevel() AddLine(Severity.Fishy, V87, CheckIdentifier.Level); else AddLine(Severity.Valid, V88, CheckIdentifier.Level); + + // Machoke, Graveler, Haunter and Kadabra captured in the second phase evolution, exclude in-game trade, is already checked + if (Type != typeof(EncounterTrade) && pkm.Format <=2 && EncounterSpecies == pkm.Species && Legal.Trade_Evolution1.Contains(EncounterSpecies)) + { + var mustevolve = pkm.TradebackStatus == TradebackType.WasTradeback || (pkm.Format == 1 && Legal.IsOutsider(pkm)); + if (mustevolve) + { + // Pokemon have been traded but it is not evolved + var species = specieslist; + var unevolved = species[pkm.Species]; + var evolved = species[pkm.Species + 1]; + AddLine(Severity.Invalid, string.Format(V405, unevolved, evolved), CheckIdentifier.Level); + } + } } #region verifyMedals private void verifyMedals() @@ -2413,6 +2442,9 @@ private void verifyMiscG1() goto case TradebackType.Gen1_NotTradeback; break; case TradebackType.Gen1_NotTradeback: + if ((EncounterMatch as EncounterStatic)?.Version == GameVersion.Stadium || EncounterMatch as EncounterTradeCatchRate != null) + // Encounters detected by the catch rate, cant be invalid if match this encounters + { AddLine(Severity.Valid, V398, CheckIdentifier.Misc); } if ( ((pkm.Species == 149) && (catch_rate == PersonalTable.Y[149].CatchRate)) || (Legal.Species_NotAvailable_CatchRate.Contains(pkm.Species) && (catch_rate == PersonalTable.RB[pkm.Species].CatchRate))) { AddLine(Severity.Invalid, V396, CheckIdentifier.Misc); } @@ -2589,9 +2621,16 @@ private List GetEncounterMovesGBEra() if (pkm.WasEgg) encounters.Add(null); if (EncountersGBMatch != null) - // Add non egg encounters, start with generation 2 - // generation 1 will change valid gen 1 lvl moves for every encounter - encounters.AddRange(EncountersGBMatch.Where(t => t.Type != GBEncounterType.EggEncounter).OrderByDescending(t => t.Generation).Select(e => e.Encounter)); + { + if (EncountersGBMatch.First().Generation == 1) + // If the first encounter if from generation 1 that means encounter from generation 2 will not return any valid move that is not valid in gen1 encounter + // but it is needed to determine if pokemon could be from only one generation to check tradeback status + encounters.Add(EncountersGBMatch.First().Encounter); + else + // Add non egg encounters, start with generation 2 + // generation 1 will change valid gen 1 lvl moves for every encounter + encounters.AddRange(EncountersGBMatch.Where(t => t.Type != GBEncounterType.EggEncounter).Select(e => e.Encounter)); + } return encounters; } private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any) @@ -2694,6 +2733,7 @@ private CheckResult[] parseMovesForEncounters(GameVersion game, int[] Moves) var EncounterMatchGen = EncounterMatch as IGeneration; var defaultG1LevelMoves = EncounterMoves.validLevelUpMoves[1]; + var defaultTradeback = pkm.TradebackStatus; if (EncounterMatchGen != null) // Generation 1 can have different minimum level in different encounter of the same species; update valid level moves UptateGen1LevelUpMoves(EncounterMoves, EncounterMoves.minLvlG1, EncounterMatchGen.Generation); @@ -2707,6 +2747,7 @@ private CheckResult[] parseMovesForEncounters(GameVersion game, int[] Moves) if (EncounterMatchGen?.Generation == 1) // not valid, restore generation 1 moves EncounterMoves.validLevelUpMoves[1] = defaultG1LevelMoves; + pkm.TradebackStatus = defaultTradeback; } return res; } @@ -3052,6 +3093,8 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, IncenseMovesLearned.Add(m); if (res[m].Valid && gen == 1) Gen1MovesLearned.Add(m); + if (res[m].Valid && gen <= 2 && pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber != gen) + pkm.TradebackStatus = TradebackType.WasTradeback; } if (gen == generations.Last()) @@ -3075,6 +3118,8 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, else res[m] = new CheckResult(Severity.Valid, V345, CheckIdentifier.Move); LvlupEggMovesLearned.Add(m); + if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1) + pkm.TradebackStatus = TradebackType.WasTradeback; if (issplitbreed) { // Only add to split breed lists learned moves that can be from one of the egg species, ignore common moves @@ -3106,6 +3151,8 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, else res[m] = new CheckResult(Severity.Valid, V171, CheckIdentifier.Move) { Flag = true }; EggMovesLearned.Add(m); + if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1) + pkm.TradebackStatus = TradebackType.WasTradeback; if (issplitbreed) { // Only add to split breed lists egg moves that can be from one of the egg species, ignore common moves @@ -3128,6 +3175,8 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, else res[m] = new CheckResult(Severity.Valid, V333, CheckIdentifier.Move) { Flag = true }; } + if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1) + pkm.TradebackStatus = TradebackType.WasTradeback; EventEggMovesLearned.Add(m); } diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 520b9b9e3..a83f97779 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -21,6 +21,11 @@ public static partial class Legal public static string EReaderBerryName = string.Empty; public static string EReaderBerryDisplayName => string.Format(V372, CultureInfo.CurrentCulture.TextInfo.ToTitleCase(EReaderBerryName.ToLower())); public static bool SavegameJapanese = false; + public static string Savegame_OT = string.Empty; + public static int Savegame_TID = 0; + public static int Savegame_SID = 0; + public static int Savegame_Gender = 0; + public static GameVersion Savegame_Version = GameVersion.Any; // Gen 1 private static readonly Learnset[] LevelUpRB = Learnset1.getArray(Resources.lvlmove_rb, MaxSpeciesID_1); @@ -316,17 +321,17 @@ private static EncounterType GetEncounterTypeBySlotDPPt( SlotType Type, Encounte case SlotType.Surf: case SlotType.Old_Rod: case SlotType.Good_Rod: - case SlotType.Super_Rod: return EncounterType.Surfing_Fishing; - case SlotType.Grass_Safari: + case SlotType.Super_Rod: case SlotType.Surf_Safari: case SlotType.Old_Rod_Safari: case SlotType.Good_Rod_Safari: - case SlotType.Super_Rod_Safari: return EncounterType.MarshSafari; + case SlotType.Super_Rod_Safari: return EncounterType.Surfing_Fishing; + case SlotType.Grass_Safari: return EncounterType.MarshSafari; case SlotType.HoneyTree: return EncounterType.None; } return EncounterType.None; } - private static EncounterType GetEncounterTypeBySlotHGSS(SlotType Type, EncounterType GrassType) + private static EncounterType GetEncounterTypeBySlotHGSS(SlotType Type, EncounterType GrassType, EncounterType HeadbuttType) { switch (Type) { @@ -344,41 +349,66 @@ private static EncounterType GetEncounterTypeBySlotHGSS(SlotType Type, Encounter case SlotType.Super_Rod_Safari: return EncounterType.Surfing_Fishing; case SlotType.Rock_Smash: case SlotType.Rock_Smash_Safari: return EncounterType.RockSmash; - case SlotType.Headbutt: return EncounterType.None; + case SlotType.Headbutt: return HeadbuttType; + case SlotType.Headbutt_Special: return EncounterType.None; } return EncounterType.None; } - private static void MarkDPPtEncounterTypeSlots_Route209(ref EncounterArea[] Areas) + private static void MarkDPPtEncounterTypeSlots_MultipleTypes(ref EncounterArea[] Areas, int Location, int SpecialEncounterFile, EncounterType NormalEncounterType) { - // Route 209 have two different encounter type for grass encounters - // The first area with location 24 is the proper Route 209 with tall grass encounters - // The other areas with the same location in the raw file is the lost tower, all encounters inside the tower are buildiing encounter - bool FirstArea = true; - foreach (EncounterArea Area in Areas.Where(x => x.Location == 24)) + // Area with two different encounter type for grass encounters + // SpecialEncounterFile is tall grass encounter type, the other files have the normal encounter type for this location + var numfile = 0; + foreach (EncounterArea Area in Areas.Where(x => x.Location == Location)) { - var GrassType = FirstArea ? EncounterType.TallGrass : EncounterType.Building_EnigmaStone; - if (FirstArea) - FirstArea = false; + numfile++; + var GrassType = numfile == SpecialEncounterFile ? EncounterType.TallGrass : NormalEncounterType; foreach (EncounterSlot Slot in Area.Slots) { Slot.TypeEncounter = GetEncounterTypeBySlotDPPt(Slot.Type, GrassType); } } } - private static void MarkHGSSEncounterTypeSlots_RuinsofAlph(ref EncounterArea[] Areas) + private static void MarkDPPtEncounterTypeSlots_MultipleTypes(ref EncounterArea[] Areas, int Location, int[] SpecialEncounterFiles, EncounterType NormalEncounterType) { - // Ruins of Alph have two different encounter type for grass encounters - // The first area with location 209 is the outside area of the ruins with tall grass encounters - // The other areas with the same location in the raw file is the inside of the ruins, all encounters inside are cave encounters - bool FirstArea = true; - foreach (EncounterArea Area in Areas.Where(x => x.Location == 209)) + var numfile = 0; + foreach (EncounterArea Area in Areas.Where(x => x.Location == Location)) { - var GrassType = FirstArea ? EncounterType.TallGrass : EncounterType.Cave_HallOfOrigin; - if (FirstArea) - FirstArea = false; + numfile++; + var GrassType = SpecialEncounterFiles.Contains(numfile) ? EncounterType.TallGrass : NormalEncounterType; foreach (EncounterSlot Slot in Area.Slots) { - Slot.TypeEncounter = GetEncounterTypeBySlotHGSS(Slot.Type, GrassType); + Slot.TypeEncounter = GetEncounterTypeBySlotDPPt(Slot.Type, GrassType); + } + } + } + private static void MarkHGSSEncounterTypeSlots_MultipleTypes(ref EncounterArea[] Areas, int Location, int SpecialEncounterFile, EncounterType NormalEncounterType) + { + // Area with two different encounter type for grass encounters + // SpecialEncounterFile is taall grass encounter type, the other files have the normal encounter type for this location + var HeadbuttType = getHeadbuttEncounter(Location); + var numfile = 0; + foreach (EncounterArea Area in Areas.Where(x => x.Location == Location)) + { + numfile++; + var GrassType = numfile == SpecialEncounterFile ? EncounterType.TallGrass : NormalEncounterType; + foreach (EncounterSlot Slot in Area.Slots) + { + Slot.TypeEncounter = GetEncounterTypeBySlotHGSS(Slot.Type, GrassType, HeadbuttType); + } + } + } + private static void MarkHGSSEncounterTypeSlots_MultipleTypes(ref EncounterArea[] Areas, int Location, int[] SpecialEncounterFiles, EncounterType NormalEncounterType) + { + var HeadbuttType = getHeadbuttEncounter(Location); + var numfile = 0; + foreach (EncounterArea Area in Areas.Where(x => x.Location == Location)) + { + numfile++; + var GrassType = SpecialEncounterFiles.Contains(numfile) ? EncounterType.TallGrass : NormalEncounterType; + foreach (EncounterSlot Slot in Area.Slots) + { + Slot.TypeEncounter = GetEncounterTypeBySlotHGSS(Slot.Type, GrassType, HeadbuttType); } } } @@ -386,7 +416,7 @@ private static void MarkDPPtEncounterTypeSlots(ref EncounterArea[] Areas) { foreach(EncounterArea Area in Areas) { - if (Area.Location == 24) + if (DPPt_MixInteriorExteriorLocations.Contains(Area.Location)) continue; var GrassType = (Area.Location == 70) ? EncounterType.Building_EnigmaStone :// Old Chateau DPPt_CaveLocations.Contains(Area.Location) ? EncounterType.Cave_HallOfOrigin : @@ -397,16 +427,40 @@ private static void MarkDPPtEncounterTypeSlots(ref EncounterArea[] Areas) } } } + private static EncounterType getHeadbuttEncounter(int Location) + { + // Routes with trees adjacent to water tiles + var allowsurf= HGSS_SurfingHeadbutt_Locations.Contains(Location); + // Cities + if (HGSS_CityLocations.Contains(Location)) + { + return allowsurf ? EncounterType.Headbutt_CitySurf : EncounterType.Building_EnigmaStone; + } + // Caves with no exterior zones + if (!HGSS_MixInteriorExteriorLocations.Contains(Location) && HGSS_CaveLocations.Contains(Location)) + { + return allowsurf ? EncounterType.Headbutt_CaveSurf : EncounterType.Cave_HallOfOrigin; + } + // Routes and exterior areas + // Routes with trees adjacent to grass tiles + var allowgrass = HGSS_GrassHeadbutt_Locations.Contains(Location); + return allowgrass && allowsurf ? EncounterType.Headbutt_GrassSurf : + allowgrass ? EncounterType.Headbutt_Grass : + allowsurf ? EncounterType.Headbutt_Surf : + EncounterType.None; + } + private static void MarkHGSSEncounterTypeSlots(ref EncounterArea[] Areas) { foreach (EncounterArea Area in Areas) { - if (Area.Location == 209) + if (HGSS_MixInteriorExteriorLocations.Contains(Area.Location)) continue; var GrassType = HGSS_CaveLocations.Contains(Area.Location) ? EncounterType.Cave_HallOfOrigin: EncounterType.TallGrass; + var HeadbuttType = getHeadbuttEncounter(Area.Location); foreach (EncounterSlot Slot in Area.Slots) { - Slot.TypeEncounter = GetEncounterTypeBySlotHGSS(Slot.Type, GrassType); + Slot.TypeEncounter = GetEncounterTypeBySlotHGSS(Slot.Type, GrassType, HeadbuttType); } } } @@ -655,11 +709,26 @@ private static EncounterArea[] getTables2(GameVersion Version) MarkG4AltFormSlots(ref Pt_Slots, 422, 1, Shellos_EastSeaLocation_Pt); MarkG4AltFormSlots(ref Pt_Slots, 423, 1, Gastrodon_EastSeaLocation_Pt); - MarkDPPtEncounterTypeSlots_Route209(ref D_Slots); - MarkDPPtEncounterTypeSlots_Route209(ref P_Slots); - MarkDPPtEncounterTypeSlots_Route209(ref Pt_Slots); - MarkHGSSEncounterTypeSlots_RuinsofAlph(ref HG_Slots); - MarkHGSSEncounterTypeSlots_RuinsofAlph(ref SS_Slots); + // Route 209 + MarkDPPtEncounterTypeSlots_MultipleTypes(ref D_Slots, 24, 1, EncounterType.Building_EnigmaStone); + MarkDPPtEncounterTypeSlots_MultipleTypes(ref P_Slots, 24, 1, EncounterType.Building_EnigmaStone); + MarkDPPtEncounterTypeSlots_MultipleTypes(ref Pt_Slots, 24, 1, EncounterType.Building_EnigmaStone); + + // Stark Mountain + MarkDPPtEncounterTypeSlots_MultipleTypes(ref D_Slots, 84, 1, EncounterType.Cave_HallOfOrigin); + MarkDPPtEncounterTypeSlots_MultipleTypes(ref P_Slots, 84, 1, EncounterType.Cave_HallOfOrigin); + MarkDPPtEncounterTypeSlots_MultipleTypes(ref Pt_Slots, 84, 1, EncounterType.Cave_HallOfOrigin); + // Mt Coronet + MarkDPPtEncounterTypeSlots_MultipleTypes(ref D_Slots, 50, DPPt_MtCoronetExteriorEncounters, EncounterType.Cave_HallOfOrigin); + MarkDPPtEncounterTypeSlots_MultipleTypes(ref P_Slots, 50, DPPt_MtCoronetExteriorEncounters, EncounterType.Cave_HallOfOrigin); + MarkDPPtEncounterTypeSlots_MultipleTypes(ref Pt_Slots, 50, DPPt_MtCoronetExteriorEncounters, EncounterType.Cave_HallOfOrigin); + + // Ruins of Alph + MarkHGSSEncounterTypeSlots_MultipleTypes(ref HG_Slots, 209, 1, EncounterType.Cave_HallOfOrigin); + MarkHGSSEncounterTypeSlots_MultipleTypes(ref SS_Slots, 209, 1, EncounterType.Cave_HallOfOrigin); + // Mt Silver Cave + MarkHGSSEncounterTypeSlots_MultipleTypes(ref HG_Slots, 219, HGSS_MtSilverCaveExteriorEncounters, EncounterType.Cave_HallOfOrigin); + MarkHGSSEncounterTypeSlots_MultipleTypes(ref SS_Slots, 219, HGSS_MtSilverCaveExteriorEncounters, EncounterType.Cave_HallOfOrigin); MarkG4Slots(ref D_Slots); MarkG4Slots(ref P_Slots); @@ -1338,7 +1407,7 @@ internal static EncounterSlot[] getValidWildEncounters(PKM pkm, GameVersion game if (s.Count <= 1 || pkm.Format == 7) return s.Any() ? s.ToArray() : null; - var s_EncounterTypes = s.Where(slot => slot.TypeEncounter == (EncounterType)pkm.EncounterType).ToList(); + var s_EncounterTypes = s.Where(slot => slot.TypeEncounter.Contains(pkm.EncounterType)).ToList(); if (s_EncounterTypes.Any()) return s_EncounterTypes.ToArray(); @@ -1360,12 +1429,17 @@ internal static List getValidStaticEncounter(PKM pkm, GameVersi var enc = getMatchingStaticEncounters(pkm, poss, lvl); // Filter for encounter types - if (pkm.Gen4 && pkm.Format < 7) // type is cleared on 6->7 + if (pkm.Gen4 && pkm.Format < 7 && enc.Count() > 1) // type is cleared on 6->7 { int type = pkm.EncounterType; - enc = type == 0 + var enctype = type == 0 ? enc.Where(z => !(z is EncounterStaticTyped)) // no typed encounters - : enc.Where(z => z is EncounterStaticTyped && (int) ((EncounterStaticTyped)z).TypeEncounter == type); + : enc.Where(z => z is EncounterStaticTyped && ((EncounterStaticTyped)z).TypeEncounter.Contains(type)); + + // Filter only if there are encounters that match types and encounters that do not match types, like wild encounters + // IF there is only one of the two possibilities encounter type check will detect encounter type does not match encounter + if (enctype.Any()) + enc = enctype; } var result = enc.ToList(); return result.Count == 0 ? null : result; @@ -1403,12 +1477,23 @@ private static IEnumerable getMatchingStaticEncounters(PKM pkm, if (pkm.Format == 1 && pkm.Gen1_NotTradeback) { var catch_rate = (pkm as PK1).Catch_Rate; + var japanese = (pkm as PK1).Japanese; // Pure gen 1, trades can be filter by catch rate if ((pkm.Species == 25 || pkm.Species == 26) && catch_rate == 190) // Red Blue Pikachu, is not a static encounter continue; - if (catch_rate != PersonalTable.RB[e.Species].CatchRate && catch_rate != PersonalTable.Y[e.Species].CatchRate) + if (e.Version == GameVersion.Stadium) + { + if (e.Species != 054 && !Stadium_CatchRate.Contains(catch_rate)) + continue; + // Amnesia Psyduck have different catch rate in japanese stadium and international stadium + if (e.Species == 054 && japanese && catch_rate != 167) + continue; + if (e.Species == 054 && !japanese && catch_rate != 168) + continue; + } + else if (catch_rate != PersonalTable.RB[e.Species].CatchRate && catch_rate != PersonalTable.Y[e.Species].CatchRate) continue; } @@ -1811,8 +1896,13 @@ private static EncounterTrade getValidEncounterTradeVC1(PKM pkm, DexLevel[] p, E { // Even if the in game trade use the tables with source pokemon allowing generaion 2 games, the traded pokemon could be a non-tradeback pokemon var catch_rate = (pkm as PK1).Catch_Rate; - if (catch_rate != PersonalTable.RB[z.Species].CatchRate && catch_rate != PersonalTable.Y[z.Species].CatchRate) - return null; + if (z is EncounterTradeCatchRate) + { + if (catch_rate != ((EncounterTradeCatchRate)z).Catch_Rate) + return null; + } + else if (catch_rate != PersonalTable.RB[z.Species].CatchRate && catch_rate != PersonalTable.Y[z.Species].CatchRate) + return null; } return z; } @@ -1837,6 +1927,11 @@ private static GBEncounterData getEncounter12(PKM pkm, GameVersion game) DexLevel[] vs = getValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin).ToArray(); var s = getValidStaticEncounter(pkm, game); + + // Valid stadium and non-stadium encounters, return only non-stadium encounters, they are less restrictive + if (s != null && game == GameVersion.RBY && s.Any(st => st.Species != 54 && st.Version == GameVersion.Stadium) && s.Any(st => st.Species != 54 && st.Version != GameVersion.Stadium)) + s = s.Where(st => st.Version != GameVersion.Stadium).ToList(); + var e = getValidWildEncounters(pkm, game); var t = getValidIngameTrade(pkm, game); @@ -1884,7 +1979,8 @@ internal static List getEncounter12(PKM pkm) // Both generations can provide an encounter. Return highest preference g1.MoveLevel = getMoveMinLevelGBEncounter(g1.Species, g1.Level, getGen1GameEncounter(pkm)); if (g1.Type > g2.Type) - return new List { g1 }; + // Return also generation 2 encounters, is only needed to determine that pokemon is not exclusive from generation 1 + return new List { g1, g2 }; if (g1.Type <= g2.Type || // Return lowest level encounter g2.MoveLevel < g1.MoveLevel) @@ -1892,7 +1988,7 @@ internal static List getEncounter12(PKM pkm) // Return also generation 1 moves, it could have different encounter moves return new List { g2, g1 }; } - return new List { g1 }; + return new List { g1, g2 }; } internal static bool getEncounterTrade1Valid(PKM pkm) { @@ -3695,5 +3791,17 @@ internal static List[] GetEmptyEggMovesList() emptyegg[0] = new List(); return emptyegg; } + + internal static bool IsOutsider(PKM pkm) + { + var Outsider = Savegame_TID != pkm.TID || Savegame_OT != pkm.OT_Name; + if (pkm.Format <= 2) + return Outsider; + Outsider |= Savegame_SID != pkm.SID; + if (pkm.Format == 3) // Generation 3 does not check ot geneder nor pokemon version + return Outsider; + Outsider |= Savegame_Gender != pkm.OT_Gender || Savegame_Version != (GameVersion) pkm.Version; + return Outsider; + } } } diff --git a/PKHeX/Legality/LegalityCheckStrings.cs b/PKHeX/Legality/LegalityCheckStrings.cs index 2324d217e..1e3dbe49f 100644 --- a/PKHeX/Legality/LegalityCheckStrings.cs +++ b/PKHeX/Legality/LegalityCheckStrings.cs @@ -72,6 +72,8 @@ public static class LegalityCheckStrings public static string V393 { get; set; } = "Valid Type B, match species type."; public static string V394 { get; set; } = "Catch rate match a valid held item from generation 2"; public static string V398 { get; set; } = "Catch Rate match a species from pokemon evolution chain."; + public static string V403 { get; set; } = "Valid International Stadium OT."; + public static string V404 { get; set; } = "Valid Japanese Stadium OT."; #endregion #region Legality Check Result Strings @@ -392,9 +394,11 @@ public static class LegalityCheckStrings public static string V396 {get; set;} = "Catch rate match species without encounters. Expected a preevolution catch rate."; public static string V397 {get; set;} = "Catch rate does not match any species from pokemon evolution chain."; public static string V399 {get; set;} = "Catch rate does not match any species from pokemon evolution chain or any generation 2 held items."; - public static string V400 {get; set;} = "Unable to match encounter conditions to a possible RNG frame."; - + public static string V401 {get; set;} = "In-game trade {0} should have evolved into {1}."; + public static string V402 {get; set;} = "Incorrect Stadium OT."; + public static string V405 {get; set;} = "Outsider {0} should have evolved into {1}."; + public static string V406 {get; set;} = "Non japanese Shadow E-reader Pokémon. Unreleased encounter."; #endregion } diff --git a/PKHeX/Legality/Structures/EncounterArea.cs b/PKHeX/Legality/Structures/EncounterArea.cs index 1fc6c22e3..7220949f4 100644 --- a/PKHeX/Legality/Structures/EncounterArea.cs +++ b/PKHeX/Legality/Structures/EncounterArea.cs @@ -586,7 +586,7 @@ private static EncounterArea getArea4HGSS_Headbutt(byte[] data) Species = Species, LevelMin = data[8 + i*4], LevelMax = data[9 + i*4], - Type = SlotType.Headbutt + Type = i <= 11 ? SlotType.Headbutt : SlotType.Headbutt_Special }); } diff --git a/PKHeX/Legality/Structures/EncounterStatic.cs b/PKHeX/Legality/Structures/EncounterStatic.cs index a88207bf3..1657d5291 100644 --- a/PKHeX/Legality/Structures/EncounterStatic.cs +++ b/PKHeX/Legality/Structures/EncounterStatic.cs @@ -125,7 +125,7 @@ public string Name public class EncounterStaticTyped : EncounterStatic { - public EncounterType TypeEncounter = EncounterType.Any; + public EncounterType TypeEncounter = EncounterType.None; protected override EncounterStatic Clone(int location) { @@ -164,6 +164,7 @@ public class EncounterStaticShadow : EncounterStatic { public EncounterLock[] Locks = new EncounterLock[0]; public int Gauge; + public bool EReader = false; protected override EncounterStatic Clone(int location) { diff --git a/PKHeX/Legality/Structures/EncounterTrade.cs b/PKHeX/Legality/Structures/EncounterTrade.cs index 7ebd9dfd6..3fd55d3d8 100644 --- a/PKHeX/Legality/Structures/EncounterTrade.cs +++ b/PKHeX/Legality/Structures/EncounterTrade.cs @@ -22,6 +22,7 @@ public class EncounterTrade : IEncounterable, IMoveset, IGeneration public int Gender = -1; public int OTGender = -1; public bool EggEncounter => false; + public bool EvolveOnTrade = false; public string Name => "In-game Trade"; @@ -35,4 +36,9 @@ public class EncounterTradePID : EncounterTrade { public uint PID; } + + public class EncounterTradeCatchRate : EncounterTrade + { + public uint Catch_Rate; + } } diff --git a/PKHeX/Legality/Structures/EncounterType.cs b/PKHeX/Legality/Structures/EncounterType.cs index b2cc13c25..c68a9154c 100644 --- a/PKHeX/Legality/Structures/EncounterType.cs +++ b/PKHeX/Legality/Structures/EncounterType.cs @@ -2,7 +2,11 @@ { public enum EncounterType { - Any = -1, + Headbutt_Grass = -1, // None or TallGrass + Headbutt_Surf = -2, // None or Surfing_Fishing + Headbutt_GrassSurf = -3, // None, TallGrass or Surfing_Fishing + Headbutt_CitySurf = -4, // Building_EnigmaStone or Surfing_Fishing + Headbutt_CaveSurf = -5, // Cave_HallOfOrigin or Surfing_Fishing None = 0, RockSmash = 1, TallGrass = 2, @@ -15,4 +19,27 @@ public enum EncounterType DistortionWorld_Pt = 23, Starter_Fossil_Gift_Pt_DPTrio = 24, } + + public static class EncounterTypeExtension + { + public static bool Contains(this EncounterType g1, int g2) + { + return g1.Contains((EncounterType)g2); + } + public static bool Contains(this EncounterType g1, EncounterType g2) + { + if (g1 == EncounterType.Headbutt_Grass) + return g2 == EncounterType.None || g2 == EncounterType.TallGrass; + if (g1 == EncounterType.Headbutt_Surf) + return g2 == EncounterType.None || g2 == EncounterType.Surfing_Fishing; + if (g1 == EncounterType.Headbutt_GrassSurf) + return EncounterType.Headbutt_Grass.Contains(g2) || g2 == EncounterType.Surfing_Fishing; + if (g1 == EncounterType.Headbutt_CitySurf) + return g2 == EncounterType.Building_EnigmaStone || g2 == EncounterType.Surfing_Fishing; + if (g1 == EncounterType.Headbutt_CaveSurf) + return g2 == EncounterType.Cave_HallOfOrigin || g2 == EncounterType.Surfing_Fishing; + + return g1 == g2; + } + } } diff --git a/PKHeX/Legality/Structures/SlotType.cs b/PKHeX/Legality/Structures/SlotType.cs index a144c49ba..e83358d3a 100644 --- a/PKHeX/Legality/Structures/SlotType.cs +++ b/PKHeX/Legality/Structures/SlotType.cs @@ -19,6 +19,7 @@ public enum SlotType SOS, Swarm, Headbutt, + Headbutt_Special, Pokeradar, HoneyTree, HiddenGrotto, diff --git a/PKHeX/Legality/Tables1.cs b/PKHeX/Legality/Tables1.cs index 967a59641..5bd4eddb4 100644 --- a/PKHeX/Legality/Tables1.cs +++ b/PKHeX/Legality/Tables1.cs @@ -110,6 +110,14 @@ public static partial class Legal // new EncounterStatic { Species = 007, Level = 10, Version = GameVersion.YW }, // Squirtle (Vermillion City) new EncounterStatic { Species = 054, Level = 15, Moves = new [] { 133, 10 }, Version = GameVersion.Stadium }, // Stadium Psyduck (Amnesia) + new EncounterStatic { Species = 001, Level = 05, Version = GameVersion.Stadium }, // Bulbasaur + new EncounterStatic { Species = 004, Level = 05, Version = GameVersion.Stadium }, // Charmander + new EncounterStatic { Species = 071, Level = 05, Version = GameVersion.Stadium }, // Squirtle + new EncounterStatic { Species = 106, Level = 20, Version = GameVersion.Stadium }, // Hitmonlee + new EncounterStatic { Species = 107, Level = 20, Version = GameVersion.Stadium }, // Hitmonchan + new EncounterStatic { Species = 133, Level = 25, Version = GameVersion.Stadium }, // Eevee + new EncounterStatic { Species = 138, Level = 20, Version = GameVersion.Stadium }, // Omanyte + new EncounterStatic { Species = 140, Level = 20, Version = GameVersion.Stadium }, // Kabuto 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 = @@ -140,9 +148,9 @@ public static partial class Legal new EncounterTrade { Species = 115, Generation = 1, Level = 42 }, // Kangaskhan - Evolve Rhydon (GSC: 30) new EncounterTrade { Species = 128, Generation = 1, Level = 28 }, // Tauros - Evolve Persian (GSC: 18) - new EncounterTrade { Species = 093, Generation = 1, Level = 20 }, // Haunter - Trade Machoke (GSC: 10) - new EncounterTrade { Species = 075, Generation = 1, Level = 16 }, // Graveler - Evolve Kadabra (GSC: 15) - new EncounterTrade { Species = 098, Generation = 1, Level = 15 }, // Krabby - Wild Growlithe (GSC: 5) + new EncounterTradeCatchRate { Species = 093, Generation = 1, Level = 20, Catch_Rate = 45, EvolveOnTrade = true }, // Haunter - Trade Machoke (GSC: 10) + new EncounterTradeCatchRate { Species = 075, Generation = 1, Level = 16, Catch_Rate = 45, EvolveOnTrade = true }, // Graveler - Evolve Kadabra (GSC: 15) + new EncounterTradeCatchRate { Species = 098, Generation = 1, Level = 15, Catch_Rate = 204 }, // Krabby - Wild Growlithe (GSC: 5) //new EncounterTrade { Species = 122, Generation = 1, Level = 08 }, // Mr. Mime - Wild Clefairy (GSC: 6) new EncounterTrade { Species = 067, Generation = 1, Level = 20 }, // Machoke - Wild Cubone (GSC: 10) @@ -159,9 +167,9 @@ public static partial class Legal new EncounterTrade { Species = 115, Generation = 1, Level = 30 }, // Kangaskhan - Evolve Rhydon (RBY: 42) new EncounterTrade { Species = 128, Generation = 1, Level = 18 }, // Tauros - Evolve Persian (RBY: 28) - new EncounterTrade { Species = 093, Generation = 1, Level = 10 }, // Haunter - Trade Machoke (RBY: 20) - new EncounterTrade { Species = 075, Generation = 1, Level = 15 }, // Graveler - Evolve Kadabra (RBY: 16) - new EncounterTrade { Species = 098, Generation = 1, Level = 05 }, // Krabby - Egg Growlithe (RBY: 15) + new EncounterTradeCatchRate { Species = 093, Generation = 1, Level = 10, Catch_Rate = 45, EvolveOnTrade = true }, // Haunter - Trade Machoke (RBY: 20) + new EncounterTradeCatchRate { Species = 075, Generation = 1, Level = 15, Catch_Rate = 45, EvolveOnTrade = true }, // Graveler - Evolve Kadabra (RBY: 16) + new EncounterTradeCatchRate { Species = 098, Generation = 1, Level = 05, Catch_Rate = 204 }, // Krabby - Egg Growlithe (RBY: 15) //new EncounterTrade { Species = 122, Generation = 1, Level = 08 }, // Mr. Mime - Wild Clefairy (RBY: 6) new EncounterTrade { Species = 067, Generation = 1, Level = 05 }, // Machoke - Egg Cubone (RBY: 20) @@ -196,7 +204,31 @@ public static partial class Legal }; internal static readonly int[] Species_NotAvailable_CatchRate = { - 12, 18, 31, 34, 36, 38, 45, 53, 59, 62, 65, 68, 71, 76, 78, 91, 94, 103, 121 + 12, 18, 31, 34, 36, 38, 45, 53, 59, 62, 65, 68, 71, 78, 91, 103, 121 + }; + internal static readonly int[] Stadium_CatchRate = + { + 167, // Normal Box + 168, // Gorgeous Box + }; + internal static readonly int[] Stadium_GiftSpecies = + { + 001, // Bulbasaur + 004, // Charmander + 007, // Squirtle + 054, // Psyduck (Amnesia) + 106, // Hitmonlee + 107, // Hitmonchan + 133, // Eevee + 138, // Omanyte + 140, // Kabuto + }; + internal static readonly int[] Trade_Evolution1 = + { + 064, + 067, + 075, + 093 }; } } diff --git a/PKHeX/Legality/Tables3.cs b/PKHeX/Legality/Tables3.cs index 5e58f21b6..55c7c9ba5 100644 --- a/PKHeX/Legality/Tables3.cs +++ b/PKHeX/Legality/Tables3.cs @@ -719,9 +719,9 @@ public static partial class Legal new EncounterStaticShadow { Species = 217, Level = 45, Gauge = 07000, Moves = new[] {185,313,122,163}, Location = 132 }, // Ursaring: Team Snagem Agrev @ Snagem Hideout new EncounterStaticShadow { Species = 213, Level = 45, Gauge = 07000, Moves = new[] {219,227,156,117}, Location = 125 }, // Shuckle: Deep King Agnol @ Deep Colosseum new EncounterStaticShadow { Species = 176, Level = 20, Gauge = 05000, Moves = new[] {118,204,186,281}, Location = 001 }, // Togetic: Cipher Peon Fein @ Outskirt Stand - new EncounterStaticShadow { Species = 175, Level = 20, Gauge = 00000, Moves = new[] {118,204,186,281}, IVs = new[] {0,0,0,0,0,0} }, // Togepi: Chaser ボデス @ Card e Room (Japanese games only) - new EncounterStaticShadow { Species = 179, Level = 37, Gauge = 00000, Moves = new[] {087,084,086,178}, IVs = new[] {0,0,0,0,0,0} }, // Mareep: Hunter ホル @ Card e Room (Japanese games only) - new EncounterStaticShadow { Species = 212, Level = 50, Gauge = 00000, Moves = new[] {210,232,014,163}, IVs = new[] {0,0,0,0,0,0} }, // Scizor: Bodybuilder ワーバン @ Card e Room (Japanese games only) + new EncounterStaticShadow { Species = 175, Level = 20, Gauge = 00000, Moves = new[] {118,204,186,281}, IVs = new[] {0,0,0,0,0,0}, EReader = true }, // Togepi: Chaser ボデス @ Card e Room (Japanese games only) + new EncounterStaticShadow { Species = 179, Level = 37, Gauge = 00000, Moves = new[] {087,084,086,178}, IVs = new[] {0,0,0,0,0,0}, EReader = true }, // Mareep: Hunter ホル @ Card e Room (Japanese games only) + new EncounterStaticShadow { Species = 212, Level = 50, Gauge = 00000, Moves = new[] {210,232,014,163}, IVs = new[] {0,0,0,0,0,0}, EReader = true }, // Scizor: Bodybuilder ワーバン @ Card e Room (Japanese games only) }; #endregion diff --git a/PKHeX/Legality/Tables4.cs b/PKHeX/Legality/Tables4.cs index 690549a34..413b7a727 100644 --- a/PKHeX/Legality/Tables4.cs +++ b/PKHeX/Legality/Tables4.cs @@ -220,6 +220,17 @@ public static partial class Legal 69, // Iron Island 84, // Stark Mountain }; + internal static readonly int[] DPPt_MixInteriorExteriorLocations = + { + 24, // Route 209 (Lost Tower) + 50, // Mt Coronet + 70, // Old Chateau + 84, // Stark Mountain + }; + internal static readonly int[] DPPt_MtCoronetExteriorEncounters = + { + 4, 5 + }; internal static readonly int[] HGSS_CaveLocations = { 197, // DIGLETT's Cave @@ -245,9 +256,105 @@ public static partial class Legal 228, // Cliff Cave 234, // Cliff Edge Gate }; + internal static readonly int[] HGSS_CityLocations = + { + 126, // New Bark Town + 127, // Cherrygrove City + 128, // Violet City + 129, // Azalea Town + 130, // Cianwood City + 131, // Goldenrod City + 132, // Olivine City + 133, // Ecruteak City + 134, // Mahogany Town + 136, // Blackthorn City + 138, // Pallet Town + 139, // Viridian City + 140, // Pewter City + 141, // Cerulean City + 142, // Lavender Town + 143, // Vermilion City + 144, // Celadon City + 145, // Fuchsia City + 146, // Cinnabar Island + 147, // Indigo Plateau + 148, // Saffron City + 227, // Safari Zone Gate + }; + internal static readonly int[] HGSS_SurfingHeadbutt_Locations = + { // Locations with headbutt trees adjacent to water tiles + 126, // New Bark Town + 128, // Violet City + 133, // Ecruteak City + 135, // Lake of Rage + 138, // Pallet Town + 139, // Viridian City + 160, // Route 12 + 169, // Route 21 + 170, // Route 22 + 174, // Route 26 + 175, // Route 27 + 176, // Route 28 + 178, // Route 30 + 179, // Route 31 + 180, // Route 32 + 182, // Route 34 + 183, // Route 35 + 190, // Route 42 + 191, // Route 43 + 192, // Route 44 + 214, // Ilex Forest + }; + internal static readonly int[] HGSS_GrassHeadbutt_Locations = + { // Locations with headbutt trees adjacent to tall grass tiles + 137, // Mt. Silver + 149, // Route 1 + 150, // Route 2 + 151, // Route 3 + 152, // Route 4 + 153, // Route 5 + 154, // Route 6 + 155, // Route 7 + 159, // Route 11 + 161, // Route 13 + 163, // Route 15 + 164, // Route 16 + 169, // Route 21 + 170, // Route 22 + 174, // Route 26 + 175, // Route 27 + 176, // Route 28 + 177, // Route 29 + 178, // Route 30 + 179, // Route 31 + 180, // Route 32 + 181, // Route 33 + 182, // Route 34 + 183, // Route 35 + 184, // Route 36 + 185, // Route 37 + 186, // Route 38 + 187, // Route 39 + 191, // Route 43 + 192, // Route 44 + 194, // Route 46 + 195, // Route 47 + 196, // Route 48 + 219, // Mt. Silver Cave + 224, // Viridian Forest + }; + internal static readonly int[] HGSS_MtSilverCaveExteriorEncounters = + { + 2, 3 + }; + internal static readonly int[] HGSS_MixInteriorExteriorLocations = + { + 209, // Ruins of Alph + 219, // Mt. Silver Cave + }; #endregion #region Pokéwalker Encounter - // all pkm are in Poke Ball and have a met location of "PokeWalker" + // all pkm are in Poke Ball and have a met location of "PokeWalker" internal static readonly EncounterStatic[] Encounter_PokeWalker = { // Some pkm has a pre-level move, an egg move or even a special move, it might be also available via HM/TM/Tutor diff --git a/PKHeX/Legality/Tables7.cs b/PKHeX/Legality/Tables7.cs index 67b78380d..2baa9e7dc 100644 --- a/PKHeX/Legality/Tables7.cs +++ b/PKHeX/Legality/Tables7.cs @@ -299,7 +299,7 @@ public static partial class Legal new EncounterTrade { Species = 761, Form = 0, Level = 16, Ability = 1, TID = 20683, SID = 00009, OTGender = 0, Gender = 1, Nature = Nature.Adamant, }, // Bounsweet new EncounterTrade { Species = 061, Form = 0, Level = 22, Ability = 2, TID = 01092, SID = 00009, OTGender = 1, Gender = 1, Nature = Nature.Naughty, }, // Poliwhirl new EncounterTrade { Species = 440, Form = 0, Level = 27, Ability = 2, TID = 10913, SID = 00000, OTGender = 1, Gender = 1, Nature = Nature.Calm, }, // Happiny - new EncounterTrade { Species = 075, Form = 1, Level = 32, Ability = 1, TID = 20778, SID = 00009, OTGender = 0, Gender = 0, Nature = Nature.Impish, }, // Graveler-1 + new EncounterTrade { Species = 075, Form = 1, Level = 32, Ability = 1, TID = 20778, SID = 00009, OTGender = 0, Gender = 0, Nature = Nature.Impish, EvolveOnTrade = true }, // Graveler-1 new EncounterTrade { Species = 762, Form = 0, Level = 43, Ability = 1, TID = 20679, SID = 00009, OTGender = 1, Gender = 1, Nature = Nature.Careful, }, // Steenee new EncounterTrade { Species = 663, Form = 0, Level = 59, Ability = 4, TID = 56734, SID = 00008, OTGender = 0, Gender = 0, Nature = Nature.Jolly, }, // Talonflame }; diff --git a/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt b/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt index 821975bed..5f57a86ac 100644 --- a/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt +++ b/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt @@ -40,6 +40,8 @@ V392 = Valid Type A, match species type. V393 = Valid Type B, match species type. V394 = Catch rate match a valid held item from generation 2. V398 = Catch Rate match any species from pokemon evolution chain. +V403 = Valid International Stadium OT. +V404 = Valid Japanese Stadium OT. V203 = Genderless Pokémon should not have a gender. V201 = Encryption Constant is not set. V204 = Held item is unreleased. @@ -328,4 +330,9 @@ V390 = Invalid Type B, does not match species type. V395 = Catch rate does not match a valid held item from generation 2. V396 = Catch rate match species without encounters. Expected a preevolution catch rate. V397 = Catch rate does not match any species from pokemon evolution chain. -V399 = Catch rate does not match any species from pokemon evolution chain or any generation 2 held items. \ No newline at end of file +V399 = Catch rate does not match any species from pokemon evolution chain or any generation 2 held items. +V400 = Unable to match encounter conditions to a possible RNG frame. +V401 = In-game trade {0} should have evolved into {1}. +V402 = Incorrect Stadium OT. +V405 = Outsider {0} should have evolved into {1}. +V406 = Non japanese Shadow E-reader Pokémon. Unreleased encounter. \ No newline at end of file diff --git a/PKHeX/Resources/text/ko/LegalityCheckStrings_ko.txt b/PKHeX/Resources/text/ko/LegalityCheckStrings_ko.txt index ebed5ff74..92f65f636 100644 --- a/PKHeX/Resources/text/ko/LegalityCheckStrings_ko.txt +++ b/PKHeX/Resources/text/ko/LegalityCheckStrings_ko.txt @@ -41,6 +41,8 @@ V392 = Valid Type A, match species type. V393 = Valid Type B, match species type. V394 = Catch rate match a valid held item from generation 2. V398 = Catch rate match any species from pokemon evolution chain. +V403 = Valid International Stadium OT. +V404 = Valid Japanese Stadium OT. V203 = 무성 포켓몬은 성별을 가질 수 없습니다. V201 = 암호화 상수가 설정되어 있지 않습니다. V204 = 지닌 물건이 배포되지 않은 물건입니다. @@ -329,4 +331,9 @@ V390 = Invalid Type B, does not match species type. V395 = Catch rate does not match a valid held item from generation 2. V396 = Catch rate match species without encounters. Expected a preevolution catch rate. V397 = Catch rate does not match any species from pokemon evolution chain. -V399 = Catch rate does not match any species from pokemon evolution chain or any generation 2 held items. \ No newline at end of file +V399 = Catch rate does not match any species from pokemon evolution chain or any generation 2 held items. +V400 = Unable to match encounter conditions to a possible RNG frame. +V401 = In-game trade {0} should have evolved into {1}. +V402 = Incorrect Stadium OT. +V405 = Outsider {0} should have evolved into {1}. +V406 = Non japanese Shadow E-reader Pokémon. Unreleased encounter. \ No newline at end of file diff --git a/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt b/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt index c483ec371..51f88f03b 100644 --- a/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt +++ b/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt @@ -41,6 +41,8 @@ V392 = Valid Type A, match species type. V393 = Valid Type B, match species type. V394 = Catch rate match a valid held item from generation 2 V398 = Catch rate match any species from pokemon evolution chain. +V403 = Valid International Stadium OT. +V404 = Valid Japanese Stadium OT. V203 = 无性别宝可梦不能有性别。 V201 = 未设置加密常数。 V204 = 持有物未解禁。 @@ -329,4 +331,9 @@ V390 = Invalid Type B, does not match species type. V395 = Catch rate does not match a valid held item from generation 2. V396 = Catch rate match species without encounters. Expected a preevolution catch rate. V397 = Catch rate does not match any species from pokemon evolution chain. -V399 = Catch rate does not match any species from pokemon evolution chain or any generation 2 held items. \ No newline at end of file +V399 = Catch rate does not match any species from pokemon evolution chain or any generation 2 held items. +V400 = Unable to match encounter conditions to a possible RNG frame. +V401 = In-game trade {0} should have evolved into {1}. +V402 = Incorrect Stadium OT. +V405 = Outsider {0} should have evolved into {1}. +V406 = Non japanese Shadow E-reader Pokémon. Unreleased encounter. \ No newline at end of file