mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-14 16:27:21 +00:00
Specify full movesets & course for Pokewalker encs
Didn't trust the existing manual transcribing, and both Bulbapedia and Serebii contain errors that don't match the original raw data. So, let's rip the raw data ourselves and use our own parse pickle (just raw bytes) instead of 162 manual entries.
For ripping logic, see: 203874da12
Partial match if language cannot access walker course
Re-do language override for EncounterStatic->pkm:
- Override gen1/2 event OT/language only if requested language is not possible
- Override walker OT/language if requested language is not possible (->japanese)
Closes #3594
This commit is contained in:
parent
f42b8609c1
commit
583f96a598
4 changed files with 90 additions and 182 deletions
|
@ -16,185 +16,14 @@ internal static class Encounters4
|
|||
internal static readonly EncounterArea4[] SlotsHG = EncounterArea4.GetAreas(Get("hg", "hg"), HG);
|
||||
internal static readonly EncounterArea4[] SlotsSS = EncounterArea4.GetAreas(Get("ss", "ss"), SS);
|
||||
|
||||
private static readonly EncounterStatic4Pokewalker[] Encounter_PokeWalker = EncounterStatic4Pokewalker.GetAll(Util.GetBinaryResource("encounter_walker4.pkl"));
|
||||
|
||||
static Encounters4()
|
||||
{
|
||||
MarkEncounterTradeStrings(TradeGift_DPPt, TradeDPPt);
|
||||
MarkEncounterTradeStrings(TradeGift_HGSS, TradeHGSS);
|
||||
}
|
||||
|
||||
#region Pokéwalker Encounter
|
||||
// all pk are in Poke Ball and have a met location of "PokeWalker"
|
||||
private static readonly EncounterStatic4Pokewalker[] Encounter_PokeWalker =
|
||||
{
|
||||
// Some pk has a pre-level move, an egg move or even a special move, it might be also available via HM/TM/Tutor
|
||||
// Johto/Kanto Courses
|
||||
new(084, 1, 08), // Doduo
|
||||
new(115, 1, 08), // Kangaskhan
|
||||
new(029, 1, 05), // Nidoran♀
|
||||
new(032, 0, 05), // Nidoran♂
|
||||
new(016, 0, 05), // Pidgey
|
||||
new(161, 1, 05), // Sentret
|
||||
new(202, 1, 15), // Wobbuffet
|
||||
new(069, 1, 08), // Bellsprout
|
||||
new(046, 1, 06), // Paras
|
||||
new(048, 0, 06), // Venonat
|
||||
new(021, 0, 05), // Spearow
|
||||
new(043, 1, 05), // Oddish
|
||||
new(095, 0, 09), // Onix
|
||||
new(240, 0, 09) { Moves = new(241) }, // Magby: Sunny Day
|
||||
new(066, 1, 07), // Machop
|
||||
new(077, 1, 07), // Ponyta
|
||||
new(074, 1, 08) { Moves = new(189) }, // Geodude: Mud-Slap
|
||||
new(163, 1, 06), // Hoothoot
|
||||
new(054, 1, 10), // Psyduck
|
||||
new(120, 2, 10), // Staryu
|
||||
new(060, 0, 08), // Poliwag
|
||||
new(079, 0, 08), // Slowpoke
|
||||
new(191, 1, 06), // Sunkern
|
||||
new(194, 0, 06), // Wooper
|
||||
new(081, 2, 11), // Magnemite
|
||||
new(239, 0, 11) { Moves = new(009) }, // Elekid: Thunder Punch
|
||||
new(081, 2, 08), // Magnemite
|
||||
new(198, 1, 11), // Murkrow
|
||||
new(019, 1, 07), // Rattata
|
||||
new(163, 1, 07), // Hoothoot
|
||||
new(092, 1, 15) { Moves = new(194) }, // Gastly: Destiny Bond
|
||||
new(238, 1, 12) { Moves = new(419) }, // Smoochum: Avalanche
|
||||
new(092, 1, 10), // Gastly
|
||||
new(095, 0, 10), // Onix
|
||||
new(041, 0, 08), // Zubat
|
||||
new(066, 0, 08), // Machop
|
||||
new(060, 1, 15) { Moves = new(187) }, // Poliwag: Belly Drum
|
||||
new(147, 1, 10), // Dratini
|
||||
new(090, 1, 12), // Shellder
|
||||
new(098, 0, 12) { Moves = new(152) }, // Krabby: Crabhammer
|
||||
new(072, 1, 09), // Tentacool
|
||||
new(118, 1, 09), // Goldeen
|
||||
new(063, 1, 15), // Abra
|
||||
new(100, 2, 15), // Voltorb
|
||||
new(088, 0, 13), // Grimer
|
||||
new(109, 1, 13) { Moves = new(120) }, // Koffing: Self-Destruct
|
||||
new(019, 1, 16), // Rattata
|
||||
new(162, 0, 15), // Furret
|
||||
// Hoenn Courses
|
||||
new(264, 1, 30), // Linoone
|
||||
new(300, 1, 30), // Skitty
|
||||
new(313, 0, 25), // Volbeat
|
||||
new(314, 1, 25), // Illumise
|
||||
new(263, 1, 17), // Zigzagoon
|
||||
new(265, 1, 15), // Wurmple
|
||||
new(298, 1, 20), // Azurill
|
||||
new(320, 1, 31), // Wailmer
|
||||
new(116, 1, 20), // Horsea
|
||||
new(318, 1, 26), // Carvanha
|
||||
new(118, 1, 22) { Moves = new(401) }, // Goldeen: Aqua Tail
|
||||
new(129, 1, 15), // Magikarp
|
||||
new(218, 1, 31), // Slugma
|
||||
new(307, 0, 32), // Meditite
|
||||
new(111, 0, 25), // Rhyhorn
|
||||
new(228, 0, 27), // Houndour
|
||||
new(074, 0, 29), // Geodude
|
||||
new(077, 1, 19), // Ponyta
|
||||
new(351, 1, 30), // Castform
|
||||
new(352, 0, 30), // Kecleon
|
||||
new(203, 1, 28), // Girafarig
|
||||
new(234, 1, 28), // Stantler
|
||||
new(044, 1, 14), // Gloom
|
||||
new(070, 0, 13), // Weepinbell
|
||||
new(105, 1, 30) { Moves = new(037) }, // Marowak: Thrash
|
||||
new(128, 0, 30), // Tauros
|
||||
new(042, 0, 33), // Golbat
|
||||
new(177, 1, 24), // Natu
|
||||
new(066, 0, 13) { Moves = new(418) }, // Machop: Bullet Punch
|
||||
new(092, 1, 15), // Gastly
|
||||
// Sinnoh Courses
|
||||
new(415, 0, 30), // Combee
|
||||
new(439, 0, 29), // Mime Jr.
|
||||
new(403, 1, 33), // Shinx
|
||||
new(406, 0, 30), // Budew
|
||||
new(399, 1, 13), // Bidoof
|
||||
new(401, 0, 15), // Kricketot
|
||||
new(361, 1, 28), // Snorunt
|
||||
new(459, 0, 31) { Moves = new(452) }, // Snover: Wood Hammer
|
||||
new(215, 0, 28) { Moves = new(306) }, // Sneasel: Crash Claw
|
||||
new(436, 2, 20), // Bronzor
|
||||
new(179, 1, 15), // Mareep
|
||||
new(220, 1, 16), // Swinub
|
||||
new(357, 1, 35), // Tropius
|
||||
new(438, 0, 30), // Bonsly
|
||||
new(114, 1, 30), // Tangela
|
||||
new(400, 1, 30), // Bibarel
|
||||
new(102, 1, 17), // Exeggcute
|
||||
new(179, 0, 19), // Mareep
|
||||
new(200, 1, 32) { Moves = new(194) }, // Misdreavus: Destiny Bond
|
||||
new(433, 0, 22) { Moves = new(105) }, // Chingling: Recover
|
||||
new(093, 0, 25), // Haunter
|
||||
new(418, 0, 28) { Moves = new(226) }, // Buizel: Baton Pass
|
||||
new(170, 1, 17), // Chinchou
|
||||
new(223, 1, 19), // Remoraid
|
||||
new(422, 1, 30) { Moves = new(243) }, // Shellos: Mirror Coat
|
||||
new(456, 1, 26), // Finneon
|
||||
new(086, 1, 27), // Seel
|
||||
new(129, 1, 30), // Magikarp
|
||||
new(054, 1, 22) { Moves = new(281) }, // Psyduck: Yawn
|
||||
new(090, 0, 20), // Shellder
|
||||
new(025, 1, 30), // Pikachu
|
||||
new(417, 1, 33) { Moves = new(175) }, // Pachirisu: Flail
|
||||
new(035, 1, 31), // Clefairy
|
||||
new(039, 1, 30), // Jigglypuff
|
||||
new(183, 1, 25), // Marill
|
||||
new(187, 1, 25), // Hoppip
|
||||
new(442, 0, 31), // Spiritomb
|
||||
new(446, 0, 33), // Munchlax
|
||||
new(349, 0, 30), // Feebas
|
||||
new(433, 1, 26), // Chingling
|
||||
new(042, 0, 33), // Golbat
|
||||
new(164, 1, 30), // Noctowl
|
||||
// Special Courses
|
||||
new(120, 2, 18) { Moves = new(113) }, // Staryu: Light Screen
|
||||
new(224, 1, 19) { Moves = new(324) }, // Octillery: Signal Beam
|
||||
new(116, 0, 15), // Horsea
|
||||
new(222, 1, 16), // Corsola
|
||||
new(170, 1, 12), // Chinchou
|
||||
new(223, 0, 14), // Remoraid
|
||||
new(035, 0, 08) { Moves = new(236) }, // Clefairy: Moonlight
|
||||
new(039, 0, 10), // Jigglypuff
|
||||
new(041, 0, 09), // Zubat
|
||||
new(163, 1, 06), // Hoothoot
|
||||
new(074, 0, 05), // Geodude
|
||||
new(095, 1, 05) { Moves = new(088) }, // Onix: Rock Throw
|
||||
new(025, 0, 15) { Moves = new(019) }, // Pikachu: Fly
|
||||
new(025, 1, 14) { Moves = new(057) }, // Pikachu: Surf
|
||||
new(025, 1, 12) { Moves = new(344, 252) }, // Pikachu: Volt Tackle, Fake Out
|
||||
new(025, 0, 13) { Moves = new(175) }, // Pikachu: Flail
|
||||
new(025, 0, 10), // Pikachu
|
||||
new(025, 1, 10), // Pikachu
|
||||
new(302, 1, 15), // Sableye
|
||||
new(441, 0, 15), // Chatot
|
||||
new(025, 1, 10), // Pikachu
|
||||
new(453, 0, 10), // Croagunk
|
||||
new(417, 0, 05), // Pachirisu
|
||||
new(427, 1, 05), // Buneary
|
||||
new(133, 0, 10), // Eevee
|
||||
new(255, 0, 10), // Torchic
|
||||
new(061, 1, 15) { Moves = new(003) }, // Poliwhirl: Double Slap
|
||||
new(279, 0, 15), // Pelipper
|
||||
new(025, 1, 08), // Pikachu
|
||||
new(052, 0, 10), // Meowth
|
||||
new(374, 2, 05) { Moves = new(428,334,442) }, // Beldum: Zen Headbutt, Iron Defense & Iron Head.
|
||||
new(446, 0, 05) { Moves = new(120) }, // Munchlax: Self-Destruct
|
||||
new(116, 0, 05) { Moves = new(330) }, // Horsea: Muddy Water
|
||||
new(355, 0, 05) { Moves = new(286) }, // Duskull: Imprison
|
||||
new(129, 0, 05) { Moves = new(340) }, // Magikarp: Bounce
|
||||
new(436, 2, 05) { Moves = new(433) }, // Bronzor: Trick Room
|
||||
new(239, 0, 05) { Moves = new(9) }, // Elekid: Thunder Punch (can be tutored)
|
||||
new(240, 0, 05) { Moves = new(7) }, // Magby: Fire Punch (can be tutored)
|
||||
new(238, 1, 05) { Moves = new(8) }, // Smoochum: Ice Punch (can be tutored)
|
||||
new(440, 1, 05) { Moves = new(215) }, // Happiny: Heal Bell
|
||||
new(173, 1, 05) { Moves = new(118) }, // Cleffa: Metronome
|
||||
new(174, 0, 05) { Moves = new(273) }, // Igglybuff: Wish
|
||||
};
|
||||
#endregion
|
||||
#region Static Encounter/Gift Tables
|
||||
private static readonly EncounterStatic4[] Encounter_DPPt =
|
||||
{
|
||||
|
|
|
@ -185,21 +185,30 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM
|
|||
switch (this)
|
||||
{
|
||||
// Cannot trade between languages
|
||||
case IFixedGBLanguage e:
|
||||
return e.Language == EncounterGBLanguage.Japanese ? 1 : 2;
|
||||
case IFixedGBLanguage { Language: EncounterGBLanguage.Japanese } when lang != 1:
|
||||
pk.OT_Name = "ゲーフリ";
|
||||
return (int)LanguageID.Japanese;
|
||||
case IFixedGBLanguage { Language: not EncounterGBLanguage.Japanese } when lang == 1:
|
||||
pk.OT_Name = "GF";
|
||||
return (int)LanguageID.English;
|
||||
|
||||
// E-Reader was only available to Japanese games.
|
||||
case EncounterStaticShadow {EReader: true}:
|
||||
case EncounterStaticShadow { EReader: true } when lang != 1:
|
||||
// Old Sea Map was only distributed to Japanese games.
|
||||
case EncounterStatic3 when Species == (int)Core.Species.Mew:
|
||||
case EncounterStatic3 { Species: (int)Core.Species.Mew } when lang != 1:
|
||||
pk.OT_Name = "ゲーフリ";
|
||||
return (int)LanguageID.Japanese;
|
||||
|
||||
// Deoxys for Emerald was not available for Japanese games.
|
||||
case EncounterStatic3 when Species == (int)Core.Species.Deoxys && Version == GameVersion.E && lang == 1:
|
||||
case EncounterStatic3 { Species: (ushort)Core.Species.Deoxys, Version: GameVersion.E } when lang == 1:
|
||||
pk.OT_Name = "GF";
|
||||
return (int)LanguageID.English;
|
||||
|
||||
// Some Pokewalker courses are only available in Japanese(/Korean) games.
|
||||
case EncounterStatic4Pokewalker p when !p.IsCourseAvailable(lang):
|
||||
pk.OT_Name = "ゲーフリ";
|
||||
return (int)LanguageID.Japanese;
|
||||
|
||||
default:
|
||||
return lang;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
|
@ -8,12 +11,21 @@ public sealed record EncounterStatic4Pokewalker : EncounterStatic
|
|||
{
|
||||
public override int Generation => 4;
|
||||
public override EntityContext Context => EntityContext.Gen4;
|
||||
public PokewalkerCourse4 Course { get; }
|
||||
|
||||
public EncounterStatic4Pokewalker(ushort species, sbyte gender, byte level) : base(GameVersion.HGSS)
|
||||
public EncounterStatic4Pokewalker(ReadOnlySpan<byte> data, PokewalkerCourse4 course) : base(GameVersion.HGSS)
|
||||
{
|
||||
Species = species;
|
||||
Gender = gender;
|
||||
Level = level;
|
||||
Species = ReadUInt16LittleEndian(data);
|
||||
Level = data[2];
|
||||
Gender = (sbyte)data[3];
|
||||
Course = course;
|
||||
var move1 = ReadUInt16LittleEndian(data[0x4..]);
|
||||
var move2 = ReadUInt16LittleEndian(data[0x6..]);
|
||||
var move3 = ReadUInt16LittleEndian(data[0x8..]);
|
||||
var move4 = ReadUInt16LittleEndian(data[0xA..]);
|
||||
Moves = new(move1, move2, move3, move4);
|
||||
|
||||
// All obtained entities are in Poke Ball and have a met location of "PokeWalker"
|
||||
Gift = true;
|
||||
Location = Locations.PokeWalker4;
|
||||
}
|
||||
|
@ -37,9 +49,19 @@ public sealed record EncounterStatic4Pokewalker : EncounterStatic
|
|||
{
|
||||
if (Gift && pk.Ball != Ball)
|
||||
return true;
|
||||
if (!IsCourseAvailable(pk.Language))
|
||||
return true;
|
||||
return base.IsMatchPartial(pk);
|
||||
}
|
||||
|
||||
public bool IsCourseAvailable(int language) => Course switch
|
||||
{
|
||||
PokewalkerCourse4.Rally => language is (int)LanguageID.Japanese,
|
||||
PokewalkerCourse4.Sightseeing => language is (int)LanguageID.Japanese or (int)LanguageID.Korean,
|
||||
PokewalkerCourse4.AmityMeadow => language is (int)LanguageID.Japanese,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
protected override void SetPINGA(PKM pk, EncounterCriteria criteria)
|
||||
{
|
||||
var pi = pk.PersonalInfo;
|
||||
|
@ -52,4 +74,52 @@ public sealed record EncounterStatic4Pokewalker : EncounterStatic
|
|||
PIDGenerator.SetRandomPIDPokewalker(pk, nature, gender);
|
||||
criteria.SetRandomIVs(pk);
|
||||
}
|
||||
|
||||
public static EncounterStatic4Pokewalker[] GetAll(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 0xC;
|
||||
var count = data.Length / size;
|
||||
System.Diagnostics.Debug.Assert(count == 6 * (int)PokewalkerCourse4.MAX_COUNT);
|
||||
var result = new EncounterStatic4Pokewalker[count];
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var offset = i * size;
|
||||
var slice = data[offset..];
|
||||
var course = (PokewalkerCourse4)(i / 6);
|
||||
result[i] = new(slice, course);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public enum PokewalkerCourse4 : byte
|
||||
{
|
||||
RefreshingField = 0,
|
||||
NoisyForest = 1,
|
||||
RuggedRoad = 2,
|
||||
BeautifulBeach = 3,
|
||||
SuburbanArea = 4,
|
||||
DimCave = 5,
|
||||
BlueLake = 6,
|
||||
TownOutskirts = 7,
|
||||
HoennField = 8,
|
||||
WarmBeach = 9,
|
||||
VolcanoPath = 10,
|
||||
Treehouse = 11,
|
||||
ScaryCave = 12,
|
||||
SinnohField = 13,
|
||||
IcyMountainRoad = 14,
|
||||
BigForest = 15,
|
||||
WhiteLake = 16,
|
||||
StormyBeach = 17,
|
||||
Resort = 18,
|
||||
QuietCave = 19,
|
||||
BeyondTheSea = 20,
|
||||
NightSkysEdge = 21,
|
||||
YellowForest = 22,
|
||||
Rally = 23, // JPN Exclusive
|
||||
Sightseeing = 24, // JPN/KOR Exclusive
|
||||
WinnersPath = 25,
|
||||
AmityMeadow = 26, // JPN Exclusive
|
||||
MAX_COUNT,
|
||||
}
|
||||
|
|
BIN
PKHeX.Core/Resources/legality/wild/Gen4/encounter_walker4.pkl
Normal file
BIN
PKHeX.Core/Resources/legality/wild/Gen4/encounter_walker4.pkl
Normal file
Binary file not shown.
Loading…
Reference in a new issue