Add genloc checks for gen8 memories 1,2,3

Can definitely be refined as these memories can restrict to capture/hatch/gift encounters. The multi-value arrays can also be restricted for non-hatches too (maybe first element if WasEgg?)

Co-Authored-By: Lusamine <30205550+Lusamine@users.noreply.github.com>
This commit is contained in:
Kurt 2021-08-22 01:40:08 -07:00
parent 28e7473f1a
commit 40d1249f1e
2 changed files with 188 additions and 1 deletions

View file

@ -150,6 +150,189 @@ namespace PKHeX.Core
#endregion
#region Tables for Gen8
public static bool IsInvalidGenLoc8(int memory, int loc, byte arg)
{
if (!IsGeneralLocationMemoryMet(memory))
return false;
if (arg > 255)
return true;
if (loc > 255)
return true;
if (SingleGenLocAreas.TryGetValue((byte)loc, out var val))
return arg != val;
if (MultiGenLocAreas.TryGetValue((byte)loc, out var arr))
return !arr.Contains(arg);
return false;
}
// {met, values allowed}
private static readonly Dictionary<byte, byte[]> MultiGenLocAreas = new()
{
// town of Postwick
// first town, at home, friend's house
{6, new byte[] {1, 2, 3}},
// town of Wedgehurst
// someone's house, boutique, simple town, Pokémon Center
{14, new byte[] {4, 6, 8, 9}},
// Route 2
// lab, tranquil road, lakeside road
{18, new byte[] {16, 44, 71}},
// city of Motostoke
// boutique, Pokémon Center, hotel, Pokémon Gym, stylish café, hair salon, town with a mysterious air
{20, new byte[] {6, 9, 11, 20, 24, 30, 35}},
// Motostoke Stadium
// Pokémon Gym, stadium
{24, new byte[] {20, 73}},
// town of Turffield
// Pokémon Center, town with a mysterious air
{34, new byte[] {9, 12}},
// Route 5
// tranquil road, Pokémon Nursery
{40, new byte[] {44, 74}},
// town of Hulbury
// someones house, Pokémon Center, restaurant, seaside town
{44, new byte[] {4, 9, 31, 33}},
// city of Hammerlocke
// someones house, boutique, Pokémon Center, Pokémon Gym, stylish café, hair salon, town with a mysterious air
{56, new byte[] {4, 6, 9, 20, 24, 30, 35}},
// town of Stow-on-Side
// someones house, Pokémon Center, town in the mountains
{70, new byte[] {4, 9, 76}},
// town of Ballonlea
// someones house, Pokémon Center, town with a mysterious air
{78, new byte[] {4, 9, 12}},
// town of Circhester
// someones house, boutique, Pokémon Center, hotel, hair salon, restaurant, snowcapped town
{96, new byte[] {4, 6, 9, 11, 30, 31, 37}},
// town of Spikemuth
// Pokémon Center, run-down town
{102, new byte[] {9, 77}},
// city of Wyndon
// someones house, boutique, Pokémon Center, hotel, large town, stylish café, hair salon
{110, new byte[] {4, 6, 9, 11, 22, 24, 30}},
// town of Freezington
// someones house, snowcapped town
{206, new byte[] {04, 37}},
};
// {met, value allowed}
private static readonly Dictionary<byte, byte> SingleGenLocAreas = new()
{
{008, 41}, // Slumbering Weald, forest
{012, 44}, // Route 1, tranquil road
{016, 28}, // Wedgehurst Station, train station
{022, 28}, // Motostoke Station, train station
{028, 44}, // Route 3, tranquil road
{030, 75}, // Galar Mine, mine
{032, 44}, // Route 4, tranquil road
{036, 73}, // Turffield Stadium, stadium
{046, 28}, // Hulbury Station, train station
{048, 73}, // Hulbury Stadium, stadium
{052, 35}, // Motostoke Outskirts, town with a mysterious air
{054, 75}, // Galar Mine No. 2, mine
{058, 28}, // Hammerlocke Station, train station
{060, 73}, // Hammerlocke Stadium, stadium
{064, 79}, // Energy Plant, dangerous place
{066, 79}, // the tower summit, dangerous place
{068, 47}, // Route 6, rugged mountain pass
{072, 73}, // Stow-on-Side Stadium, stadium
{076, 41}, // Glimwood Tangle, forest
{080, 73}, // Ballonlea Stadium, stadium
{084, 44}, // Route 7, tranquil road
{086, 47}, // Route 8, rugged mountain pass
{088, 53}, // Route 8 (on Steamdrift Way), snow-swept road
{090, 53}, // Route 9, snow-swept road
{092, 53}, // Route 9 (in Circhester Bay), snow-swept road
{094, 53}, // Route 9 (in Outer Spikemuth), snow-swept road
{098, 73}, // Circhester Stadium, stadium
{104, 78}, // Route 9 Tunnel, tunnel
{106, 53}, // Route 10, snow-swept road
{108, 28}, // White Hill Station, train station
{112, 28}, // Wyndon Station, train station
{114, 38}, // Wyndon Stadium (at the Pokémon League HQ), Pokémon League
{116, 38}, // Wyndon Stadium (in a locker room), Pokémon League
{120, 44}, // Meetup Spot, tranquil road
{122, 72}, // Rolling Fields, vast field
{124, 72}, // Dappled Grove, vast field
{126, 72}, // Watchtower Ruins, vast field
{128, 72}, // East Lake Axewell, vast field
{130, 72}, // West Lake Axewell, vast field
{132, 72}, // Axews Eye, vast field
{134, 72}, // South Lake Miloch, vast field
{136, 72}, // near the Giants Seat, vast field
{138, 72}, // North Lake Miloch, vast field
{140, 72}, // Motostoke Riverbank, vast field
{142, 72}, // Bridge Field, vast field
{144, 72}, // Stony Wilderness, vast field
{146, 72}, // Dusty Bowl, vast field
{148, 72}, // around the Giants Mirror, vast field
{150, 72}, // the Hammerlocke Hills, vast field
{152, 72}, // near the Giants Cap, vast field
{154, 72}, // Lake of Outrage, vast field
{156, 28}, // Wild Area Station, train station
{158, 34}, // Battle Tower, tall building
{160, 34}, // Rose Tower, tall building
{164, 72}, // Fields of Honor, vast field
{166, 50}, // Soothing Wetlands, muddy road
{168, 41}, // Forest of Focus, forest
{170, 49}, // Challenge Beach, seaside road
{172, 40}, // Brawlers Cave, cave
{174, 76}, // Challenge Road, town in the mountains
{176, 40}, // Courageous Cavern, cave
{178, 49}, // Loop Lagoon, seaside road
{180, 72}, // Training Lowlands, vast field
{182, 40}, // Warm-Up Tunnel, cave
{184, 51}, // Potbottom Desert, sand-swept road
{186, 49}, // Workout Sea, seaside road
{188, 49}, // Stepping-Stone Sea, seaside road
{190, 49}, // Insular Sea, seaside road
{192, 49}, // Honeycalm Sea, seaside road
{194, 49}, // Honeycalm Island, seaside road
{196, 29}, // Master Dojo, battling spot
{198, 34}, // Tower of Darkness, tall building
{200, 34}, // Tower of Waters, tall building
{202, 28}, // Armor Station, train station
{204, 53}, // Slippery Slope, snow-swept road
{208, 53}, // Frostpoint Field, snow-swept road
{210, 72}, // Giants Bed, vast field
{212, 48}, // Old Cemetery, stone-lined area
{214, 53}, // Snowslide Slope, snow-swept road
{216, 40}, // Tunnel to the Top, cave
{218, 53}, // the Path to the Peak, snow-swept road
{220, 65}, // Crown Shrine, mystical place
{222, 44}, // Giants Foot, tranquil road
{224, 40}, // Roaring-Sea Caves, cave
{226, 49}, // Frigid Sea, seaside road
{228, 72}, // Three-Point Pass, vast field
{230, 72}, // Ballimere Lake, vast field
{232, 40}, // Lakeside Cave, cave
{234, 72}, // Dyna Tree Hill, vast field
{236, 65}, // Rock Peak Ruins, mystical place
{238, 65}, // Iceberg Ruins, mystical place
{240, 65}, // Iron Ruins, mystical place
{242, 65}, // Split-Decision Ruins, mystical place
{244, 40}, // Max Lair, cave
{246, 28}, // Crown Tundra Station, train station
};
#endregion
private static bool IsGeneralLocationMemoryMet(int memory) => memory is (1 or 2 or 3);
private static readonly HashSet<int> MemoryGeneral = new() { 1, 2, 3, 4, 19, 24, 31, 32, 33, 35, 36, 37, 38, 39, 42, 52, 59, 70, 86 };
private static readonly HashSet<int> MemorySpecific = new() { 6 };
private static readonly HashSet<int> MemoryMove = new() { 12, 16, 48, 49, 80, 81, 89 };

View file

@ -33,6 +33,9 @@ namespace PKHeX.Core
switch (memory.MemoryID)
{
case 1 or 2 or 3 when gen == 8 && Memories.IsInvalidGenLoc8(memory.MemoryID, pkm.Met_Location, (byte)memory.Variable):
return GetInvalid(string.Format(LMemoryArgBadLocation, memory.Handler));
// {0} saw {2} carrying {1} on its back. {4} that {3}.
case 21 when gen != 6 || !GetCanLearnMachineMove(new PK6 {Species = memory.Variable, EXP = Experience.GetEXP(100, PersonalTable.XY.GetFormIndex(memory.Variable, 0))}, (int)Move.Fly, 6):
return GetInvalid(string.Format(LMemoryArgBadMove, memory.Handler));
@ -134,6 +137,7 @@ namespace PKHeX.Core
var mem = (ITrainerMemories)pkm;
var Info = data.Info;
// If the encounter has a memory from the OT that could never have it replaced, ensure it was not modified.
switch (data.EncounterMatch)
{
case WC6 {IsEgg: false} g when g.OTGender != 3:
@ -146,7 +150,7 @@ namespace PKHeX.Core
VerifyOTMemoryIs(data, g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling);
return;
case IMemoryOT t when t is not MysteryGift: // Ignore Mystery Gift cases (covered above)
case IMemoryOT t and not MysteryGift: // Ignore Mystery Gift cases (covered above)
VerifyOTMemoryIs(data, t.OT_Memory, t.OT_Intensity, t.OT_TextVar, t.OT_Feeling);
return;
}