diff --git a/PKHeX.Core/Legality/Analysis.cs b/PKHeX.Core/Legality/Analysis.cs
index c3fa7dfa3..b338ab2c5 100644
--- a/PKHeX.Core/Legality/Analysis.cs
+++ b/PKHeX.Core/Legality/Analysis.cs
@@ -219,7 +219,7 @@ namespace PKHeX.Core
if (pkm.Format == 2 || pkm.VC2)
{
// check for impossible tradeback scenarios
- if (pkm.IsEgg || pkm.HasOriginalMetLocation || pkm.Species > Legal.MaxSpeciesID_1 && !Legal.FutureEvolutionsGen1.Contains(pkm.Species))
+ if (pkm.Korean || pkm.IsEgg || pkm.HasOriginalMetLocation || pkm.Species > Legal.MaxSpeciesID_1 && !Legal.FutureEvolutionsGen1.Contains(pkm.Species))
pkm.TradebackStatus = TradebackType.Gen2_NotTradeback;
else
pkm.TradebackStatus = TradebackType.Any;
diff --git a/PKHeX.Core/Legality/Checks.cs b/PKHeX.Core/Legality/Checks.cs
index ea489acb5..3326ba9ed 100644
--- a/PKHeX.Core/Legality/Checks.cs
+++ b/PKHeX.Core/Legality/Checks.cs
@@ -153,6 +153,24 @@ namespace PKHeX.Core
if (!valid)
AddLine(Severity.Invalid, xorPID ? V215 : V216, CheckIdentifier.EC);
}
+ #region verifyLanguage
+ private bool verifyLanguage()
+ {
+ int maxLanguageID = Legal.GetMaxLanguageID(Info.Generation);
+ if (pkm.Language == 6 || pkm.Language > maxLanguageID)
+ {
+ AddLine(Severity.Invalid, string.Format(V5, "<=" + maxLanguageID, pkm.Language), CheckIdentifier.Language);
+ return false;
+ }
+ if(pkm.Format == 4 && pkm.Gen4 && (pkm.Language == 8) != (Legal.SavegameLanguage == 8))
+ {
+ AddLine(Severity.Invalid, pkm.Language == 8 ? V610 : V611, CheckIdentifier.Language);
+ return false;
+ }
+
+ return true;
+ }
+ #endregion
#region verifyNickname
private void VerifyNickname()
{
@@ -181,12 +199,8 @@ namespace PKHeX.Core
if (!Encounter.Valid)
return;
- int maxLanguageID = Legal.GetMaxLanguageID(Info.Generation);
- if (pkm.Language == 6 || pkm.Language > maxLanguageID)
- {
- AddLine(Severity.Indeterminate, string.Format(V5, "<=" + maxLanguageID, pkm.Language), CheckIdentifier.Language);
+ if (!verifyLanguage())
return;
- }
if (Type == typeof(EncounterTrade))
{
diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs
index b5948437b..8269a55e2 100644
--- a/PKHeX.Core/Legality/Core.cs
+++ b/PKHeX.Core/Legality/Core.cs
@@ -36,11 +36,13 @@ namespace PKHeX.Core
public static bool AllowGen1Tradeback { get; set; }
public static bool AllowGen2VCTransfer => true;
public static bool AllowGen2VCCrystal => false;
- public static bool AllowGen2Crystal => AllowGBCartEra || AllowGen2VCCrystal;
- public static bool AllowGen2MoveReminder => AllowGBCartEra;
+ public static bool AllowGen2Crystal(bool Korean) => Korean && (AllowGBCartEra || AllowGen2VCCrystal);
+ public static bool AllowGen2Crystal(PKM pkm) => AllowGen2Crystal(pkm.Korean);
+ public static bool AllowGen2MoveReminder(PKM pkm) => !pkm.Korean && AllowGBCartEra;
public static bool CheckWordFilter { get; set; } = true;
+ public static int SavegameLanguage { get; set; }
/// e-Reader Berry originates from a Japanese SaveFile
public static bool SavegameJapanese { get; set; }
/// e-Reader Berry is Enigma or special berry
@@ -243,11 +245,11 @@ namespace PKHeX.Core
}
return r;
}
- internal static List[] GetExclusiveMoves(int species1, int species2, int Generation, IEnumerable tmhm, IEnumerable moves)
+ internal static List[] GetExclusiveMoves(int species1, int species2, int Generation, IEnumerable tmhm, IEnumerable moves, bool korean)
{
// Return from two species the exclusive moves that only one could learn and also the current pokemon have it in its current moveset
- var moves1 = GetLvlMoves(species1, 0, Generation, 1, 100).Distinct().ToList();
- var moves2 = GetLvlMoves(species2, 0, Generation, 1, 100).Distinct().ToList();
+ var moves1 = GetLvlMoves(species1, 0, Generation, 1, 100, korean).Distinct().ToList();
+ var moves2 = GetLvlMoves(species2, 0, Generation, 1, 100, korean).Distinct().ToList();
// Remove common moves and remove tmhm, remove not learned moves
var common = new HashSet(moves1.Intersect(moves2).Concat(tmhm));
@@ -256,7 +258,7 @@ namespace PKHeX.Core
moves2.RemoveAll(x => !hashMoves.Contains(x) || common.Contains(x));
return new[] { moves1, moves2 };
}
- private static IEnumerable GetLvlMoves(int species, int form, int Generation, int minlvl, int lvl, GameVersion Version = GameVersion.Any)
+ private static IEnumerable GetLvlMoves(int species, int form, int Generation, int minlvl, int lvl, bool korean, GameVersion Version = GameVersion.Any)
{
var r = new List();
var ver = Version;
@@ -285,7 +287,7 @@ namespace PKHeX.Core
if (index == 0)
return r;
r.AddRange(LevelUpGS[index].GetMoves(lvl));
- if (AllowGen2Crystal)
+ if (AllowGen2Crystal(korean))
r.AddRange(LevelUpC[index].GetMoves(lvl));
break;
}
@@ -585,7 +587,7 @@ namespace PKHeX.Core
for (int i = 0; i <= index; i++)
{
var evo = evoChain[i];
- var moves = GetMoves(pkm, evo.Species, 1, 1, evo.Level, pkm.AltForm, moveTutor: true, Version: Version, LVL: true, specialTutors: true, Machine: true, MoveReminder: true, RemoveTransferHM: false, Generation: Generation);
+ var moves = GetMoves(pkm, evo.Species, 1, 1, evo.Level, pkm.AltForm, moveTutor: true, Version: Version, LVL: true, specialTutors: true, Machine: true, MoveReminder: true, RemoveTransferHM: false, Generation: Generation, Korean: pkm.Korean);
// Moves from Species or any species after in the evolution phase
evomoves.AddRange(moves);
}
@@ -599,7 +601,7 @@ namespace PKHeX.Core
for (int i = 0; i < evoChain.Length; i++)
{
var evo = evoChain[i];
- var moves = GetMoves(pkm, evo.Species, 1, 1, evo.Level, pkm.AltForm, moveTutor: true, Version: Version, LVL: true, specialTutors: true, Machine: true, MoveReminder: true, RemoveTransferHM: false, Generation: Generation);
+ var moves = GetMoves(pkm, evo.Species, 1, 1, evo.Level, pkm.AltForm, moveTutor: true, Version: Version, LVL: true, specialTutors: true, Machine: true, MoveReminder: true, RemoveTransferHM: false, Generation: Generation, Korean: pkm.Korean);
var list = i >= index ? preevomoves : evomoves;
list.AddRange(moves);
}
@@ -607,9 +609,9 @@ namespace PKHeX.Core
}
// Encounter
- internal static IEnumerable GetGen2Versions(LegalInfo Info)
+ internal static IEnumerable GetGen2Versions(LegalInfo Info, bool Korean)
{
- if (AllowGen2Crystal && Info.Game == GameVersion.C)
+ if (AllowGen2Crystal(Korean) && Info.Game == GameVersion.C)
yield return GameVersion.C;
// Any encounter marked with version GSC is for pokemon with the same moves in GS and C
@@ -841,7 +843,7 @@ namespace PKHeX.Core
}
return minlevel <= pk.CurrentLevel
- ? GetLvlMoves(basespecies, 0, 1, minlevel, maxlevel).Where(m => m != 0).Distinct().ToList()
+ ? GetLvlMoves(basespecies, 0, 1, minlevel, maxlevel, pk.Korean).Where(m => m != 0).Distinct().ToList()
: new List();
}
@@ -971,7 +973,7 @@ namespace PKHeX.Core
}
private static IEnumerable GetEncounterStaticTableGSC(PKM pkm)
{
- if (!AllowGen2Crystal)
+ if (!AllowGen2Crystal(pkm))
return StaticGS;
if (pkm.Format != 2)
return StaticGSC;
@@ -982,7 +984,7 @@ namespace PKHeX.Core
}
private static IEnumerable GetEncounterTableGSC(PKM pkm)
{
- if (!AllowGen2Crystal)
+ if (!AllowGen2Crystal(pkm))
return SlotsGS;
if (pkm.Format != 2)
@@ -1106,15 +1108,15 @@ namespace PKHeX.Core
switch (generation)
{
case 1:
- case 2:
- case 7:
- return 10; // VC -> Gen7
case 3:
return 7; // 1-7 except 6
+ case 2:
case 4:
case 5:
case 6:
return 8;
+ case 7:
+ return 10;
}
return -1;
}
@@ -1653,7 +1655,7 @@ namespace PKHeX.Core
// In gen 3 deoxys has different forms depending on the current game, in personal info there is no alter form info
formcount = 4;
for (int i = 0; i < formcount; i++)
- r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, vs.First().Level, i, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation));
+ r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, vs.First().Level, i, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation, pkm.Korean));
if (Relearn) r.AddRange(pkm.RelearnMoves);
return r.Distinct();
}
@@ -1670,13 +1672,13 @@ namespace PKHeX.Core
if (evo.MinLevel > 1)
minlvlevo1 = Math.Min(pkm.CurrentLevel, evo.MinLevel);
}
- if (Generation == 2 && !AllowGen2MoveReminder)
+ if (Generation == 2 && !AllowGen2MoveReminder(pkm))
{
minlvlevo2 = minLvLG2;
if (evo.MinLevel > 1)
minlvlevo2 = Math.Min(pkm.CurrentLevel, evo.MinLevel);
}
- r.AddRange(GetMoves(pkm, evo.Species, minlvlevo1, minlvlevo2, evo.Level, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation));
+ r.AddRange(GetMoves(pkm, evo.Species, minlvlevo1, minlvlevo2, evo.Level, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation, pkm.Korean));
}
if (pkm.Format <= 3)
@@ -1710,7 +1712,7 @@ namespace PKHeX.Core
r.AddRange(pkm.RelearnMoves);
return r.Distinct();
}
- private static IEnumerable GetMoves(PKM pkm, int species, int minlvlG1, int minlvlG2, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder, bool RemoveTransferHM, int Generation)
+ private static IEnumerable GetMoves(PKM pkm, int species, int minlvlG1, int minlvlG2, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder, bool RemoveTransferHM, int Generation,bool Korean)
{
List r = new List();
@@ -1752,7 +1754,7 @@ namespace PKHeX.Core
if (LVL)
{
r.AddRange(LevelUpGS[index].GetMoves(lvl, minlvlG2));
- if (AllowGen2Crystal)
+ if (AllowGen2Crystal(pkm))
r.AddRange(LevelUpC[index].GetMoves(lvl, minlvlG2));
}
if (Machine)
@@ -1964,7 +1966,7 @@ namespace PKHeX.Core
{
case 1:
case 2:
- if (!AllowGen2Crystal)
+ if (!AllowGen2Crystal(pkm))
return EggMovesGS[species].Moves;
if (pkm.Format != 2)
return EggMovesC[species].Moves;
diff --git a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs
index effc4db79..14e2faed3 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs
@@ -162,7 +162,7 @@ namespace PKHeX.Core
if (WasEgg)
{
int eggspec = GetBaseEggSpecies(pkm);
- if (AllowGen2Crystal)
+ if (AllowGen2Crystal(pkm))
yield return new GBEncounterData(eggspec, GameVersion.C); // gen2 egg
yield return new GBEncounterData(eggspec, GameVersion.GS); // gen2 egg
}
diff --git a/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs b/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs
index ba3e48e99..b972b7700 100644
--- a/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs
+++ b/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs
@@ -45,7 +45,7 @@ namespace PKHeX.Core
UptateGen1LevelUpMoves(pkm, info.EncounterMoves, info.EncounterMoves.MinimumLevelGen1, EncounterMatchGen.Generation, info);
// The same for Generation 2; if move reminder from Stadium 2 is not allowed
- if (!Legal.AllowGen2MoveReminder && pkm.InhabitedGeneration(2))
+ if (!Legal.AllowGen2MoveReminder(pkm) && pkm.InhabitedGeneration(2))
UptateGen2LevelUpMoves(pkm, info.EncounterMoves, info.EncounterMoves.MinimumLevelGen2, EncounterMatchGen.Generation, info);
}
@@ -135,7 +135,7 @@ namespace PKHeX.Core
int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
return ParseMovesIsEggPreRelearn(pkm, Moves, SpecialMoves, egg);
}
- var NoMoveReminder = (info.EncounterMatch as IGeneration)?.Generation == 1 || (info.EncounterMatch as IGeneration)?.Generation == 2 && !Legal.AllowGen2MoveReminder;
+ var NoMoveReminder = (info.EncounterMatch as IGeneration)?.Generation == 1 || (info.EncounterMatch as IGeneration)?.Generation == 2 && !Legal.AllowGen2MoveReminder(pkm);
if (info.Generation <= 2 && NoMoveReminder)
return ParseMovesGenGB(pkm, Moves, info);
if (info.EncounterMatch is EncounterEgg e)
@@ -151,7 +151,7 @@ namespace PKHeX.Core
return ParseMovesSpecialMoveset(pkm, Moves, info);
var InitialMoves = new int[0];
int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
- IEnumerable games = (info.EncounterMatch as IGeneration)?.Generation == 1 ? Legal.GetGen1Versions(info) : Legal.GetGen2Versions(info);
+ IEnumerable games = (info.EncounterMatch as IGeneration)?.Generation == 1 ? Legal.GetGen1Versions(info) : Legal.GetGen2Versions(info, pkm.Korean);
foreach (GameVersion ver in games)
{
var VerInitialMoves = Legal.GetInitialMovesGBEncounter(G1Encounter.Species, G1Encounter.LevelMin, ver).ToArray();
@@ -522,7 +522,7 @@ namespace PKHeX.Core
if (134 <= pkm.Species && pkm.Species <= 136)
{
previousspecies = species[133];
- var ExclusiveMoves = Legal.GetExclusiveMoves(133, pkm.Species, 1, tmhm, moves);
+ var ExclusiveMoves = Legal.GetExclusiveMoves(133, pkm.Species, 1, tmhm, moves, pkm.Korean);
var EeveeLevels = Legal.GetMinLevelLearnMove(133, 1, ExclusiveMoves[0]);
var EvoLevels = Legal.GetMaxLevelLearnMove(pkm.Species, 1, ExclusiveMoves[1]);
diff --git a/PKHeX.Core/Legality/LegalityCheckStrings.cs b/PKHeX.Core/Legality/LegalityCheckStrings.cs
index ac9519f2c..8fff3cef3 100644
--- a/PKHeX.Core/Legality/LegalityCheckStrings.cs
+++ b/PKHeX.Core/Legality/LegalityCheckStrings.cs
@@ -414,6 +414,8 @@ namespace PKHeX.Core
public static string V607 { get; set; } = "Kanto Route 14 fishing encounter. Unreachable Water tiles.";
public static string V608 { get; set; } = "National Park fishing encounter. Unreachable Water tiles.";
public static string V609 { get; set; } = "Generation 2 Safari Zone fishing encounter. Unreachable zone.";
+ public static string V610 { get; set; } = "Korean gen4 pokemon in non-korean savegame."; // Invalid
+ public static string V611 { get; set; } = "Non-korean gen4 pokemon in korean savegame."; // Invalid
#endregion
}
diff --git a/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs b/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs
index 7d0a7d71c..99082e965 100644
--- a/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs
+++ b/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs
@@ -20,7 +20,7 @@ namespace PKHeX.Core
public ValidEncounterMoves(PKM pkm, LegalInfo info)
{
MinimumLevelGen1 = pkm.GenNumber <= 2 ? info.EncounterMatch.LevelMin + 1 : 0;
- MinimumLevelGen2 = Legal.AllowGen2MoveReminder ? 1 : info.EncounterMatch.LevelMin + 1;
+ MinimumLevelGen2 = Legal.AllowGen2MoveReminder(pkm) ? 1 : info.EncounterMatch.LevelMin + 1;
EncounterSpecies = info.EncounterMatch.Species;
EvolutionChains = info.EvoChainsAllGens;
LevelUpMoves = Legal.GetValidMovesAllGens(pkm, EvolutionChains, minLvLG1: MinimumLevelGen1, minLvLG2: MinimumLevelGen2, Tutor: false, Machine: false, RemoveTransferHM: false);
diff --git a/PKHeX.Core/PKM/PK1.cs b/PKHeX.Core/PKM/PK1.cs
index e584b0dee..7f3cf4218 100644
--- a/PKHeX.Core/PKM/PK1.cs
+++ b/PKHeX.Core/PKM/PK1.cs
@@ -31,7 +31,8 @@ namespace PKHeX.Core
public override int Format => 1;
- public bool Japanese => otname.Length == STRLEN_J;
+ public override bool Japanese => otname.Length == STRLEN_J;
+ public override bool Korean => false;
public override string FileName => $"{Species:000} - {Nickname} - {SaveUtil.CRC16_CCITT(Encrypt()):X4}.{Extension}";
diff --git a/PKHeX.Core/PKM/PK2.cs b/PKHeX.Core/PKM/PK2.cs
index 881810f52..eda3492df 100644
--- a/PKHeX.Core/PKM/PK2.cs
+++ b/PKHeX.Core/PKM/PK2.cs
@@ -21,7 +21,7 @@ namespace PKHeX.Core
internal const int STRLEN_J = 6;
internal const int STRLEN_U = 11;
private int StringLength => Japanese ? STRLEN_J : STRLEN_U;
- public bool Korean => otname[0] <= 0xB;
+ public override bool Korean => otname[0] <= 0xB;
public override string GetString(int Offset, int Count)
{
@@ -43,7 +43,7 @@ namespace PKHeX.Core
public override int Format => 2;
- public bool Japanese => otname.Length == STRLEN_J;
+ public override bool Japanese => otname.Length == STRLEN_J;
public override string FileName
{
get
diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs
index 263bda352..85ae02827 100644
--- a/PKHeX.Core/PKM/PKM.cs
+++ b/PKHeX.Core/PKM/PKM.cs
@@ -142,6 +142,8 @@ namespace PKHeX.Core
public abstract int Met_Location { get; set; }
public abstract int Egg_Location { get; set; }
public abstract int OT_Friendship { get; set; }
+ public virtual bool Japanese => Language == 1;
+ public virtual bool Korean => Language == 8;
// Future Properties
public virtual int Met_Year { get => 0; set { } }
diff --git a/PKHeX.Core/Resources/text/en/LegalityCheckStrings_en.txt b/PKHeX.Core/Resources/text/en/LegalityCheckStrings_en.txt
index 7df60feb4..ebaa16e3d 100644
--- a/PKHeX.Core/Resources/text/en/LegalityCheckStrings_en.txt
+++ b/PKHeX.Core/Resources/text/en/LegalityCheckStrings_en.txt
@@ -351,3 +351,5 @@ V606 = Could not find a tree for Crystal headbutt encounter that matches OTID.
V607 = Kanto Route 14 fishing encounter. Unreachable Water tiles.
V608 = National Park fishing encounter. Unreachable Water tiles.
V609 = Generation 2 Safari Zone fishing encounter. Unreachable zone.
+V610 = Korean gen4 pokemon in non-korean savegame.
+V611 = Non-korean gen4 pokemon in korean savegame.
\ No newline at end of file
diff --git a/PKHeX.Core/Resources/text/ko/LegalityCheckStrings_ko.txt b/PKHeX.Core/Resources/text/ko/LegalityCheckStrings_ko.txt
index 2861ec8db..d08243a8f 100644
--- a/PKHeX.Core/Resources/text/ko/LegalityCheckStrings_ko.txt
+++ b/PKHeX.Core/Resources/text/ko/LegalityCheckStrings_ko.txt
@@ -351,3 +351,5 @@ V606 = 크리스탈 버전 어버이 ID와 일치하는 박치기 인카운터
V607 = 관동 14번 도로의 낚시 인카운터입니다. 물 타일에 접근할 수 없는 지역입니다.
V608 = 자연공원의 낚시 인카운터입니다. 물 타일에 접근할 수 없는 지역입니다.
V609 = 2세대 사파리존의 낚시 인카운터입니다. 접근할 수 없는 지역입니다.
+V610 = Korean gen4 pokemon in non-korean savegame.
+V611 = Non-korean gen4 pokemon in korean savegame.
diff --git a/PKHeX.Core/Resources/text/zh/LegalityCheckStrings_zh.txt b/PKHeX.Core/Resources/text/zh/LegalityCheckStrings_zh.txt
index 54fcd380e..9ab8c6a16 100644
--- a/PKHeX.Core/Resources/text/zh/LegalityCheckStrings_zh.txt
+++ b/PKHeX.Core/Resources/text/zh/LegalityCheckStrings_zh.txt
@@ -351,3 +351,5 @@ V606 = 无法在水晶版找到头锤遇敌的树符合初训家ID。
V607 = 关都14号道路钓鱼遇敌。无法到达的水域。
V608 = 自然公园钓鱼遇敌。无法到达的水域。
V609 = 第二世代狩猎区钓鱼遇敌。无法到达的区域。
+V610 = Korean gen4 pokemon in non-korean savegame.
+V611 = Non-korean gen4 pokemon in korean savegame.
\ No newline at end of file
diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs
index 349bdf167..7b3e72136 100644
--- a/PKHeX.WinForms/MainWindow/Main.cs
+++ b/PKHeX.WinForms/MainWindow/Main.cs
@@ -710,6 +710,7 @@ namespace PKHeX.WinForms
private static void StoreLegalSaveGameData(SaveFile sav)
{
+ Legal.SavegameLanguage= sav.Language;
Legal.SavegameJapanese = sav.Japanese;
Legal.EReaderBerryIsEnigma = sav.IsEBerryIsEnigma;
Legal.EReaderBerryName = sav.EBerryName;