Merge pull request #1486 from javierhimura/KoreanRestrictions

Korean and Chinese restrictions
This commit is contained in:
Kurt 2017-09-23 16:03:49 -07:00 committed by GitHub
commit cc70939dc2
14 changed files with 68 additions and 38 deletions

View File

@ -219,7 +219,8 @@ private void UpdateTradebackG12()
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))
// Korean gen2 games can't tradeback because there is no gen1 korean games released
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;

View File

@ -153,6 +153,25 @@ private void VerifyTransferEC()
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))
{
// Korean gen 4 games can not trade with non-korean gen 4 games, but can use palpark with any gen3 game
AddLine(Severity.Invalid, pkm.Language == 8 ? V610 : V611, CheckIdentifier.Language);
return false;
}
return true;
}
#endregion
#region verifyNickname
private void VerifyNickname()
{
@ -181,12 +200,8 @@ private void VerifyNickname()
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))
{

View File

@ -36,11 +36,13 @@ public static partial class Legal
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); // Pokemon Crystal was never released in Korea
public static bool AllowGen2Crystal(PKM pkm) => AllowGen2Crystal(pkm.Korean);
public static bool AllowGen2MoveReminder(PKM pkm) => !pkm.Korean && AllowGBCartEra; // Pokemon Stadium 2 was never released in Korea
public static bool CheckWordFilter { get; set; } = true;
public static int SavegameLanguage { get; set; }
/// <summary> e-Reader Berry originates from a Japanese SaveFile </summary>
public static bool SavegameJapanese { get; set; }
/// <summary> e-Reader Berry is Enigma or special berry </summary>
@ -243,11 +245,11 @@ internal static int[] GetMaxLevelLearnMove(int species, int Generation, List<int
}
return r;
}
internal static List<int>[] GetExclusiveMoves(int species1, int species2, int Generation, IEnumerable<int> tmhm, IEnumerable<int> moves)
internal static List<int>[] GetExclusiveMoves(int species1, int species2, int Generation, IEnumerable<int> tmhm, IEnumerable<int> 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<int>(moves1.Intersect(moves2).Concat(tmhm));
@ -256,7 +258,7 @@ internal static List<int>[] GetExclusiveMoves(int species1, int species2, int Ge
moves2.RemoveAll(x => !hashMoves.Contains(x) || common.Contains(x));
return new[] { moves1, moves2 };
}
private static IEnumerable<int> GetLvlMoves(int species, int form, int Generation, int minlvl, int lvl, GameVersion Version = GameVersion.Any)
private static IEnumerable<int> GetLvlMoves(int species, int form, int Generation, int minlvl, int lvl, bool korean, GameVersion Version = GameVersion.Any)
{
var r = new List<int>();
var ver = Version;
@ -285,7 +287,7 @@ private static IEnumerable<int> GetLvlMoves(int species, int form, int Generatio
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 @@ private static IEnumerable<int> GetValidPostEvolutionMoves(PKM pkm, int Species,
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 @@ internal static IEnumerable<int> GetExclusivePreEvolutionMoves(PKM pkm, int Spec
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 @@ internal static IEnumerable<int> GetExclusivePreEvolutionMoves(PKM pkm, int Spec
}
// Encounter
internal static IEnumerable<GameVersion> GetGen2Versions(LegalInfo Info)
internal static IEnumerable<GameVersion> 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 @@ private static List<int> GetRequiredMoveCountLevel(PKM pk)
}
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<int>();
}
@ -971,7 +973,7 @@ internal static IEnumerable<EncounterArea> GetEncounterTable(PKM pkm, GameVersio
}
private static IEnumerable<EncounterStatic> GetEncounterStaticTableGSC(PKM pkm)
{
if (!AllowGen2Crystal)
if (!AllowGen2Crystal(pkm))
return StaticGS;
if (pkm.Format != 2)
return StaticGSC;
@ -982,7 +984,7 @@ private static IEnumerable<EncounterStatic> GetEncounterStaticTableGSC(PKM pkm)
}
private static IEnumerable<EncounterArea> GetEncounterTableGSC(PKM pkm)
{
if (!AllowGen2Crystal)
if (!AllowGen2Crystal(pkm))
return SlotsGS;
if (pkm.Format != 2)
@ -1106,15 +1108,15 @@ internal static int GetMaxLanguageID(int generation)
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 @@ private static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion Version, DexL
// 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 @@ private static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion Version, DexL
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 @@ private static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion Version, DexL
r.AddRange(pkm.RelearnMoves);
return r.Distinct();
}
private static IEnumerable<int> 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<int> 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<int> r = new List<int>();
@ -1752,7 +1754,7 @@ private static IEnumerable<int> GetMoves(PKM pkm, int species, int minlvlG1, int
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 @@ internal static int[] GetEggMoves(PKM pkm, int species, int formnum)
{
case 1:
case 2:
if (!AllowGen2Crystal)
if (!AllowGen2Crystal(pkm))
return EggMovesGS[species].Moves;
if (pkm.Format != 2)
return EggMovesC[species].Moves;

View File

@ -162,7 +162,7 @@ private static IEnumerable<GBEncounterData> GenerateRawEncounters12(PKM pkm, Gam
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
}

View File

@ -45,7 +45,7 @@ private static CheckMoveResult[] ParseMovesForEncounters(PKM pkm, LegalInfo info
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 @@ private static CheckMoveResult[] ParseMovesPre3DS(PKM pkm, int[] Moves, LegalInf
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 @@ private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo
return ParseMovesSpecialMoveset(pkm, Moves, info);
var InitialMoves = new int[0];
int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
IEnumerable<GameVersion> games = (info.EncounterMatch as IGeneration)?.Generation == 1 ? Legal.GetGen1Versions(info) : Legal.GetGen2Versions(info);
IEnumerable<GameVersion> 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 @@ private static void ParseEvolutionsIncompatibleMoves(PKM pkm, IList<CheckMoveRes
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]);

View File

@ -414,6 +414,8 @@ public static class LegalityCheckStrings
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
}

View File

@ -20,7 +20,7 @@ public class ValidEncounterMoves
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);

View File

@ -31,7 +31,8 @@ public class PK1 : PKM
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}";

View File

@ -21,7 +21,7 @@ public class PK2 : PKM
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 @@ public override byte[] SetString(string value, int maxLength)
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

View File

@ -142,6 +142,8 @@ private byte[] Write()
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 { } }

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -710,6 +710,7 @@ private static SAV3GCMemoryCard CheckGCMemoryCard(byte[] Data, string path)
private static void StoreLegalSaveGameData(SaveFile sav)
{
Legal.SavegameLanguage= sav.Language;
Legal.SavegameJapanese = sav.Japanese;
Legal.EReaderBerryIsEnigma = sav.IsEBerryIsEnigma;
Legal.EReaderBerryName = sav.EBerryName;