Extract logic from PKX

Extract Species Name logic to SpeciesName
Extract Language logic to Language
Remove FormConverter wrapper for string[] fetch
Rearrange some logic to more appropriate locations, update access
modifiers / types
Move some pkm array methods to arrayutil, make generic

PKX.GetVCLanguage was a dupe of _K12.GuessedLanguage() so just expose
the method

PKX is now back to pkm data manip only
This commit is contained in:
Kurt 2019-09-18 19:58:23 -07:00
parent 712a9cf4a0
commit b41f2a3062
51 changed files with 435 additions and 396 deletions

View file

@ -42,7 +42,7 @@ namespace PKHeX.Core
public static string ClearNickname(this PKM pk)
{
pk.IsNicknamed = false;
string nick = PKX.GetSpeciesNameGeneration(pk.Species, pk.Language, pk.Format);
string nick = SpeciesName.GetSpeciesNameGeneration(pk.Species, pk.Language, pk.Format);
pk.Nickname = nick;
if (pk is _K12 pk12)
pk12.SetNotNicknamed();

View file

@ -155,7 +155,7 @@ namespace PKHeX.Core
FormIndex = 0;
return;
}
string[] formStrings = PKX.GetFormList(Species, Strings.Types, Strings.forms, genderForms);
string[] formStrings = FormConverter.GetFormList(Species, Strings.Types, Strings.forms, genderForms, Format);
FormIndex = Math.Max(0, Array.FindIndex(formStrings, z => z.Contains(Form)));
}
@ -327,7 +327,7 @@ namespace PKHeX.Core
{
if (Nickname.Length == 0)
return specForm;
var name = PKX.GetSpeciesNameGeneration(Species, LanguageID, Format);
var name = SpeciesName.GetSpeciesNameGeneration(Species, LanguageID, Format);
if (name == Nickname)
return specForm;
return $"{Nickname} ({specForm})";
@ -408,7 +408,7 @@ namespace PKHeX.Core
Form = string.Empty;
return;
}
var Forms = PKX.GetFormList(Species, Strings.Types, Strings.forms, genderForms, Format);
var Forms = FormConverter.GetFormList(Species, Strings.Types, Strings.forms, genderForms, Format);
Form = FormIndex >= Forms.Length ? string.Empty : Forms[index];
}

View file

@ -62,24 +62,4 @@
/// </summary>
ChineseT = 10,
}
public static partial class Extensions
{
public static string GetLanguage2CharName(this LanguageID lang)
{
switch (lang)
{
default: return "en";
case LanguageID.Japanese: return "ja";
case LanguageID.French: return "fr";
case LanguageID.Italian: return "it";
case LanguageID.German: return "de";
case LanguageID.Spanish: return "es";
case LanguageID.Korean: return "ko";
case LanguageID.ChineseS:
case LanguageID.ChineseT: return "zh";
}
}
}
}

View file

@ -823,32 +823,6 @@ namespace PKHeX.Core
internal static bool HasVisitedUSUM(this PKM pkm) => pkm.InhabitedGeneration(7) && (pkm.USUM || !pkm.IsUntraded);
internal static bool IsMovesetRestricted(this PKM pkm) => (pkm.GG && pkm.Format == 7) || pkm.IsUntraded;
public static LanguageID GetSafeLanguage(int generation, LanguageID prefer, GameVersion game = GameVersion.Any)
{
switch (generation)
{
case 1:
case 2:
if (Languages_GB.Contains((int)prefer) && (prefer != LanguageID.Korean || game == GameVersion.C))
return prefer;
return LanguageID.English;
case 3:
if (Languages_3.Contains((int)prefer))
return prefer;
return LanguageID.English;
case 4:
case 5:
case 6:
if (Languages_46.Contains((int)prefer))
return prefer;
return LanguageID.English;
default:
if (Languages_7.Contains((int)prefer))
return prefer;
return LanguageID.English;
}
}
public static bool HasMetLocationUpdatedTransfer(int originalGeneration, int currentGeneration)
{
if (originalGeneration < 3)

View file

@ -34,7 +34,7 @@ namespace PKHeX.Core
SAV.ApplyToPKM(pk);
pk.Species = Species;
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, SAV.Language, gen);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, SAV.Language, gen);
pk.CurrentLevel = Level;
pk.Version = (int)version;
pk.Ball = 4;

View file

@ -59,7 +59,7 @@ namespace PKHeX.Core
public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
int lang = (int)Legal.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int level = LevelMin;
var pk = PKMConverter.GetBlank(Generation, Version);
SAV.ApplyToPKM(pk);
@ -68,7 +68,7 @@ namespace PKHeX.Core
pk.Language = lang;
pk.CurrentLevel = level;
pk.Version = (int)version;
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, lang, Generation);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation);
pk.Ball = (int)Type.GetBall();
pk.Language = lang;
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;

View file

@ -79,13 +79,13 @@ namespace PKHeX.Core
pk.Species = Species;
pk.AltForm = Form;
int lang = (int)Legal.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int level = LevelMin;
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
SanityCheckVersion(ref version);
pk.Language = lang = GetEdgeCaseLanguage(pk, lang);
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, lang, Generation);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation);
pk.CurrentLevel = level;
pk.Version = (int)version;

View file

@ -83,7 +83,7 @@ namespace PKHeX.Core
SAV.ApplyToPKM(pk);
var version = this.GetCompatibleVersion((GameVersion)SAV.Game);
int lang = (int)Legal.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)SAV.Language);
int level = CurrentLevel > 0 ? CurrentLevel : LevelMin;
if (level == 0)
level = 25; // avoid some cases

View file

@ -465,21 +465,6 @@ namespace PKHeX.Core
public static readonly int[] Games_3r = { 4, 5 };
public static readonly int[] Games_3s = { 15 };
public static readonly int[] Languages_GB =
{
(int) LanguageID.Japanese, (int) LanguageID.English, (int) LanguageID.French, (int) LanguageID.German, (int) LanguageID.Spanish,
(int) LanguageID.Italian,
(int) LanguageID.Korean // check Korean for the VC case, never possible to match string outside of this case
};
public static readonly int[] Languages_3 =
{
(int) LanguageID.Japanese, (int) LanguageID.English, (int) LanguageID.French, (int) LanguageID.German, (int) LanguageID.Spanish, (int) LanguageID.Italian,
};
public static readonly int[] Languages_46 = Languages_GB;
public static readonly int[] Languages_7 = Languages_46.Concat(new[] { (int)LanguageID.ChineseS, (int)LanguageID.ChineseT }).ToArray();
#endregion
}
}

View file

@ -226,10 +226,10 @@ namespace PKHeX.Core
data.AddLine(GetInvalid(LEncGiftVersionNotDistributed, GameOrigin));
return;
case WC6 wc6 when wc6.RestrictLanguage != 0 && wc6.Language != wc6.RestrictLanguage:
data.AddLine(GetInvalid(string.Format(LOTLanguage, wc6.RestrictLanguage, pkm.Language), Language));
data.AddLine(GetInvalid(string.Format(LOTLanguage, wc6.RestrictLanguage, pkm.Language), CheckIdentifier.Language));
return;
case WC7 wc7 when wc7.RestrictLanguage != 0 && wc7.Language != wc7.RestrictLanguage:
data.AddLine(GetInvalid(string.Format(LOTLanguage, wc7.RestrictLanguage, pkm.Language), Language));
data.AddLine(GetInvalid(string.Format(LOTLanguage, wc7.RestrictLanguage, pkm.Language), CheckIdentifier.Language));
return;
}
}

View file

@ -21,7 +21,7 @@ namespace PKHeX.Core
data.AddLine(GetInvalid(LNickLengthShort));
return;
}
if (pkm.Species > PKX.SpeciesLang[0].Length)
if (pkm.Species > SpeciesName.SpeciesLang[0].Count)
{
data.AddLine(Get(LNickLengthShort, Severity.Indeterminate));
return;
@ -67,9 +67,9 @@ namespace PKHeX.Core
{
if (pkm.IsNicknamed)
{
for (int i = 0; i < PKX.SpeciesLang.Length; i++)
for (int i = 0; i < SpeciesName.SpeciesLang.Count; i++)
{
if (!PKX.SpeciesDict[i].TryGetValue(nickname, out int index))
if (!SpeciesName.SpeciesDict[i].TryGetValue(nickname, out int index))
continue;
var msg = index == pkm.Species && i != pkm.Language ? LNickMatchNoOthersFail : LNickMatchLanguageFlag;
data.AddLine(Get(msg, Severity.Fishy));
@ -107,13 +107,13 @@ namespace PKHeX.Core
private bool IsNicknameValid(PKM pkm, IEncounterable EncounterMatch, string nickname)
{
if (PKX.GetSpeciesNameGeneration(pkm.Species, pkm.Language, pkm.Format) == nickname)
if (SpeciesName.GetSpeciesNameGeneration(pkm.Species, pkm.Language, pkm.Format) == nickname)
return true;
// Can't have another language name if it hasn't evolved or wasn't a language-traded egg.
bool evolved = EncounterMatch.Species != pkm.Species;
bool canHaveAnyLanguage = evolved || pkm.WasTradedEgg;
if (canHaveAnyLanguage && !PKX.IsNicknamedAnyLanguage(pkm.Species, nickname, pkm.Format))
if (canHaveAnyLanguage && !SpeciesName.IsNicknamedAnyLanguage(pkm.Species, nickname, pkm.Format))
return true;
switch (EncounterMatch)
@ -121,7 +121,7 @@ namespace PKHeX.Core
case WC7 wc7 when wc7.IsAshGreninjaWC7(pkm):
return true;
case ILangNick loc:
if (loc.Language != 0 && !loc.IsNicknamed && !PKX.IsNicknamedAnyLanguage(pkm.Species, nickname, pkm.Format))
if (loc.Language != 0 && !loc.IsNicknamed && !SpeciesName.IsNicknamedAnyLanguage(pkm.Species, nickname, pkm.Format))
return true; // fixed language without nickname, nice job event maker!
break;
}
@ -129,8 +129,8 @@ namespace PKHeX.Core
if (pkm.Format == 5 && !pkm.IsNative) // transfer
{
if (canHaveAnyLanguage)
return !PKX.IsNicknamedAnyLanguage(pkm.Species, nickname, 4);
return PKX.GetSpeciesNameGeneration(pkm.Species, pkm.Language, 4) == nickname;
return !SpeciesName.IsNicknamedAnyLanguage(pkm.Species, nickname, 4);
return SpeciesName.GetSpeciesNameGeneration(pkm.Species, pkm.Language, 4) == nickname;
}
return false;
@ -157,9 +157,9 @@ namespace PKHeX.Core
break;
}
if (pkm.Format == 2 && pkm.IsEgg && !PKX.IsNicknamedAnyLanguage(0, pkm.Nickname, 2))
if (pkm.Format == 2 && pkm.IsEgg && !SpeciesName.IsNicknamedAnyLanguage(0, pkm.Nickname, 2))
data.AddLine(GetValid(LNickMatchLanguageEgg, CheckIdentifier.Egg));
else if (PKX.GetSpeciesNameGeneration(0, pkm.Language, Info.Generation) != pkm.Nickname)
else if (SpeciesName.GetSpeciesNameGeneration(0, pkm.Language, Info.Generation) != pkm.Nickname)
data.AddLine(GetInvalid(LNickMatchLanguageEggFail, CheckIdentifier.Egg));
else
data.AddLine(GetValid(LNickMatchLanguageEgg, CheckIdentifier.Egg));

View file

@ -247,7 +247,7 @@ namespace PKHeX.Core
}
pk.IsNicknamed = IsNicknamed;
pk.Nickname = IsNicknamed ? Nickname : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
pk.Nickname = IsNicknamed ? Nickname : SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, Format);
SetPINGA(pk, criteria);
@ -264,7 +264,7 @@ namespace PKHeX.Core
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}

View file

@ -221,7 +221,7 @@ namespace PKHeX.Core
{
pk4.IsEgg = true;
pk4.IsNicknamed = false;
pk4.Nickname = PKX.GetSpeciesNameGeneration(0, pk4.Language, Format);
pk4.Nickname = SpeciesName.GetSpeciesNameGeneration(0, pk4.Language, Format);
pk4.MetDate = DateTime.Now;
}

View file

@ -382,7 +382,7 @@ namespace PKHeX.Core
pk.MetDate = Date ?? DateTime.Now;
pk.IsNicknamed = GetIsNicknamed(pk.Language);
pk.Nickname = pk.IsNicknamed ? GetNickname(pk.Language) : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
pk.Nickname = pk.IsNicknamed ? GetNickname(pk.Language) : SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, Format);
SetPINGA(pk, criteria);
@ -402,7 +402,7 @@ namespace PKHeX.Core
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}

View file

@ -109,7 +109,7 @@ namespace PKHeX.Core
if (IsEgg)
pk.IsEgg = true; // lang should be set to japanese by IsEgg setter
}
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, pk.Language, 3); // will be set to Egg nickname if appropriate by PK3 setter
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, 3); // will be set to Egg nickname if appropriate by PK3 setter
var pi = pk.PersonalInfo;
pk.OT_Friendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;

View file

@ -385,7 +385,7 @@ namespace PKHeX.Core
}
pk.IsNicknamed = IsNicknamed;
pk.Nickname = IsNicknamed ? Nickname : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
pk.Nickname = IsNicknamed ? Nickname : SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, Format);
SetPINGA(pk, criteria);
@ -401,7 +401,7 @@ namespace PKHeX.Core
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}

View file

@ -415,7 +415,7 @@ namespace PKHeX.Core
pk.MetDate = Date ?? DateTime.Now;
pk.IsNicknamed = IsNicknamed;
pk.Nickname = IsNicknamed ? Nickname : PKX.GetSpeciesNameGeneration(Species, pk.Language, Format);
pk.Nickname = IsNicknamed ? Nickname : SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, Format);
SetPINGA(pk, criteria);
@ -431,7 +431,7 @@ namespace PKHeX.Core
{
pk.IsEgg = true;
pk.EggMetDate = Date;
pk.Nickname = PKX.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(0, pk.Language, Format);
pk.IsNicknamed = true;
}

View file

@ -46,7 +46,7 @@ namespace PKHeX.Core
public override int Version { get => GetGBAVersionID(Data[0x08]); set => Data[0x08] = GetGCVersionID(value); }
public int CurrentRegion { get => Data[0x09]; set => Data[0x09] = (byte)value; }
public int OriginalRegion { get => Data[0x0A]; set => Data[0x0A] = (byte)value; }
public override int Language { get => PKX.GetMainLangIDfromGC(Data[0x0B]); set => Data[0x0B] = PKX.GetGCLangIDfromMain((byte)value); }
public override int Language { get => Core.Language.GetMainLangIDfromGC(Data[0x0B]); set => Data[0x0B] = Core.Language.GetGCLangIDfromMain((byte)value); }
public override int Met_Location { get => BigEndian.ToUInt16(Data, 0x0C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
public override int Met_Level { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
public override int Ball { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }

View file

@ -165,7 +165,7 @@ namespace PKHeX.Core
Geo1_Region = PKMConverter.Region
};
pk7.Language = TransferLanguage(PKMConverter.Language);
pk7.Nickname = PKX.GetSpeciesNameGeneration(pk7.Species, pk7.Language, pk7.Format);
pk7.Nickname = SpeciesName.GetSpeciesNameGeneration(pk7.Species, pk7.Language, pk7.Format);
if (otname[0] == StringConverter12.G1TradeOTCode) // Ingame Trade
pk7.OT_Name = Encounters1.TradeOTG1[pk7.Language];
pk7.OT_Friendship = pk7.HT_Friendship = PersonalTable.SM[Species].BaseFriendship;

View file

@ -164,7 +164,7 @@ namespace PKHeX.Core
Geo1_Region = PKMConverter.Region
};
pk7.Language = TransferLanguage(PKMConverter.Language);
pk7.Nickname = PKX.GetSpeciesNameGeneration(pk7.Species, pk7.Language, pk7.Format);
pk7.Nickname = SpeciesName.GetSpeciesNameGeneration(pk7.Species, pk7.Language, pk7.Format);
if (otname[0] == StringConverter12.G1TradeOTCode) // Ingame Trade
pk7.OT_Name = Encounters1.TradeOTG1[pk7.Language];
pk7.OT_Friendship = pk7.HT_Friendship = PersonalTable.SM[Species].BaseFriendship;

View file

@ -301,7 +301,7 @@ namespace PKHeX.Core
var trash = StringConverter345.G4TransferTrashBytes;
if (pk4.Language < trash.Length)
trash[pk4.Language].CopyTo(pk4.Data, 0x48 + 4);
pk4.Nickname = IsEgg ? PKX.GetSpeciesNameGeneration(pk4.Species, pk4.Language, 4) : Nickname;
pk4.Nickname = IsEgg ? SpeciesName.GetSpeciesNameGeneration(pk4.Species, pk4.Language, 4) : Nickname;
pk4.IsNicknamed = !IsEgg && IsNicknamed;
// Trash from the current string (Nickname) is in our string buffer. Slap the OT name over-top.

View file

@ -385,8 +385,8 @@ namespace PKHeX.Core
pk6.Nature = Nature;
// Apply trash bytes for species name of current app language -- default to PKM's language if no match
int curLang = PKX.GetSpeciesNameLanguage(Species, Nickname, Format);
pk6.Nickname = PKX.GetSpeciesNameGeneration(Species, curLang < 0 ? Language : curLang, pk6.Format);
int curLang = SpeciesName.GetSpeciesNameLanguage(Species, Nickname, Format);
pk6.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, curLang < 0 ? Language : curLang, pk6.Format);
if (IsNicknamed)
pk6.Nickname = Nickname;

View file

@ -232,8 +232,8 @@ namespace PKHeX.Core
{
if (!IsNicknamed)
{
int lang = PKX.GetSpeciesNameLanguage(Species, value, 7, Language);
if (lang == 9 || lang == 10)
int lang = SpeciesName.GetSpeciesNameLanguage(Species, Language, value, 7);
if (lang == (int)LanguageID.ChineseS || lang == (int)LanguageID.ChineseT)
{
StringConverter.SetString7(value, 12, lang, chinese: true).CopyTo(Data, 0x40);
return;

View file

@ -75,7 +75,7 @@ namespace PKHeX.Core
{
get
{
var spName = PKX.GetSpeciesNameGeneration(Species, GuessedLanguage(), Format);
var spName = SpeciesName.GetSpeciesNameGeneration(Species, GuessedLanguage(), Format);
return Nickname != spName;
}
}
@ -90,7 +90,7 @@ namespace PKHeX.Core
return (int)LanguageID.Korean;
if (StringConverter12.IsG12German(otname))
return (int)LanguageID.German; // german
int lang = PKX.GetSpeciesNameLanguage(Species, Nickname, Format);
int lang = SpeciesName.GetSpeciesNameLanguage(Species, Nickname, Format);
if (lang > 0)
return lang;
return 0;
@ -223,7 +223,7 @@ namespace PKHeX.Core
private IEnumerable<byte> GetNonNickname(int language)
{
var name = PKX.GetSpeciesNameGeneration(Species, language, Format);
var name = SpeciesName.GetSpeciesNameGeneration(Species, language, Format);
var bytes = SetString(name, StringLength);
var data = bytes.Concat(Enumerable.Repeat((byte)0x50, nick.Length - bytes.Length));
if (!Korean)
@ -231,7 +231,7 @@ namespace PKHeX.Core
return data;
}
protected int GuessedLanguage(int fallback = (int)LanguageID.English)
public int GuessedLanguage(int fallback = (int)LanguageID.English)
{
int lang = Language;
if (lang > 0)
@ -249,7 +249,7 @@ namespace PKHeX.Core
protected int TransferLanguage(int destLanguage)
{
// if the Species name of the destination language matches the current nickname, transfer with that language.
var expect = PKX.GetSpeciesNameGeneration(Species, destLanguage, 2);
var expect = SpeciesName.GetSpeciesNameGeneration(Species, destLanguage, 2);
if (Nickname == expect)
return destLanguage;
return GuessedLanguage(destLanguage);

View file

@ -29,7 +29,7 @@
public override uint EncryptionConstant { get => PID; set { } }
public override int Nature { get => (int)(PID % 25); set { } }
public override int AltForm { get => Species == 201 ? PKX.GetUnownForm(PID) : 0; set { } }
public override bool IsNicknamed { get => PKX.IsNicknamedAnyLanguage(Species, Nickname, Format); set { } }
public override bool IsNicknamed { get => SpeciesName.IsNicknamedAnyLanguage(Species, Nickname, Format); set { } }
public override int Gender { get => PKX.GetGenderFromPID(Species, PID); set { } }
public override int Characteristic => -1;
public override int CurrentFriendship { get => OT_Friendship; set => OT_Friendship = value; }

View file

@ -11,13 +11,13 @@ namespace PKHeX.Core
/// <summary>
/// Gets a list of formes that the species can have.
/// </summary>
/// <param name="species">National Dex number of the Pokémon.</param>
/// <param name="species"><see cref="Species"/> of the Pokémon.</param>
/// <param name="types">List of type names</param>
/// <param name="forms">List of form names</param>
/// <param name="genders">List of genders names</param>
/// <param name="generation">Generation number for exclusive formes</param>
/// <returns>A list of strings corresponding to the formes that a Pokémon can have.</returns>
internal static string[] GetFormList(int species, IReadOnlyList<string> types, IReadOnlyList<string> forms, IReadOnlyList<string> genders, int generation)
public static string[] GetFormList(int species, IReadOnlyList<string> types, IReadOnlyList<string> forms, IReadOnlyList<string> genders, int generation)
{
// Mega List
if (IsFormListSingleMega(species))
@ -667,7 +667,7 @@ namespace PKHeX.Core
}
}
private static string[] GetFormsTotem (int species, IReadOnlyList<string> types, IReadOnlyList<string> forms)
private static string[] GetFormsTotem (int species, IReadOnlyList<string> types, IReadOnlyList<string> forms)
{
if ((Species)species == Mimikyu) // Mimikyu
{
@ -742,12 +742,12 @@ namespace PKHeX.Core
/// Checks if the <see cref="PKM"/> data should have a drop-down selection visible for the <see cref="PKM.AltForm"/> value.
/// </summary>
/// <param name="pi">Game specific personal info</param>
/// <param name="species"><see cref="PKM.Species"/> ID</param>
/// <param name="species"><see cref="Species"/> ID</param>
/// <param name="format"><see cref="PKM.AltForm"/> ID</param>
/// <returns>True if has formes that can be provided by <see cref="GetFormList"/>, otherwise false for none.</returns>
public static bool HasFormSelection(PersonalInfo pi, int species, int format)
{
if (format <= 3 && species != 201)
if (format <= 3 && species != (int)Unown)
return false;
if (HasFormeValuesNotIndicatedByPersonal.Contains(species))
@ -759,9 +759,9 @@ namespace PKHeX.Core
private static readonly HashSet<int> HasFormeValuesNotIndicatedByPersonal = new HashSet<int>
{
201, // Unown
414, // Mothim (Burmy forme carried over, not cleared)
664, 665, // Vivillon pre-evos
(int)Unown,
(int)Mothim, // (Burmy forme carried over, not cleared)
(int)Scatterbug, (int)Spewpa, // Vivillon pre-evos
};
}
}

View file

@ -0,0 +1,122 @@
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
/// <summary>
/// Logic relating to <see cref="LanguageID"/> values.
/// </summary>
public static class Language
{
private static readonly int[] Languages_3 =
{
(int)LanguageID.Japanese,
(int)LanguageID.English,
(int)LanguageID.French,
(int)LanguageID.German,
(int)LanguageID.Spanish,
(int)LanguageID.Italian,
};
// check Korean for the VC case, never possible to match string outside of this case
private static readonly int[] Languages_GB = Languages_3.Concat(new[] {(int)LanguageID.Korean}).ToArray();
private static readonly int[] Languages_46 = Languages_GB;
private static readonly int[] Languages_7 = Languages_46.Concat(new[] {(int)LanguageID.ChineseS, (int)LanguageID.ChineseT}).ToArray();
public static IReadOnlyList<int> GetAvailableGameLanguages(int generation = PKX.Generation)
{
if (generation < 3)
return Languages_GB;
if (generation < 4)
return Languages_3;
if (generation < 7)
return Languages_46;
return Languages_7;
}
public static LanguageID GetSafeLanguage(int generation, LanguageID prefer, GameVersion game = GameVersion.Any)
{
switch (generation)
{
case 1:
case 2:
if (Languages_GB.Contains((int)prefer) && (prefer != LanguageID.Korean || game == GameVersion.C))
return prefer;
return LanguageID.English;
case 3:
if (Languages_3.Contains((int)prefer))
return prefer;
return LanguageID.English;
case 4:
case 5:
case 6:
if (Languages_46.Contains((int)prefer))
return prefer;
return LanguageID.English;
default:
if (Languages_7.Contains((int)prefer))
return prefer;
return LanguageID.English;
}
}
public static string GetLanguage2CharName(this LanguageID lang)
{
switch (lang)
{
default: return "en";
case LanguageID.Japanese: return "ja";
case LanguageID.French: return "fr";
case LanguageID.Italian: return "it";
case LanguageID.German: return "de";
case LanguageID.Spanish: return "es";
case LanguageID.Korean: return "ko";
case LanguageID.ChineseS:
case LanguageID.ChineseT: return "zh";
}
}
/// <summary>
/// Gets the Main Series language ID from a GameCube (C/XD) language ID.
/// </summary>
/// <param name="value">GameCube (C/XD) language ID.</param>
/// <returns>Main Series language ID.</returns>
public static byte GetMainLangIDfromGC(byte value)
{
if (value <= 2 || value > 7)
return value;
return (byte) GCtoMainSeries[(LanguageGC)value];
}
/// <summary>
/// Gets the GameCube (C/XD) language ID from a Main Series language ID.
/// </summary>
/// <param name="value">Main Series language ID.</param>
/// <returns>GameCube (C/XD) language ID.</returns>
public static byte GetGCLangIDfromMain(byte value)
{
if (value <= 2 || value > 7)
return value;
return (byte) MainSeriesToGC[(LanguageID)value];
}
private static readonly Dictionary<LanguageID, LanguageGC> MainSeriesToGC = new Dictionary<LanguageID, LanguageGC>
{
{LanguageID.German, LanguageGC.German},
{LanguageID.French, LanguageGC.French},
{LanguageID.Italian, LanguageGC.Italian},
{LanguageID.Spanish, LanguageGC.Spanish},
{LanguageID.UNUSED_6, LanguageGC.UNUSED_6},
};
private static readonly Dictionary<LanguageGC, LanguageID> GCtoMainSeries = new Dictionary<LanguageGC, LanguageID>
{
{LanguageGC.German, LanguageID.German},
{LanguageGC.French, LanguageID.French},
{LanguageGC.Italian, LanguageID.Italian},
{LanguageGC.Spanish, LanguageID.Spanish},
{LanguageGC.UNUSED_6, LanguageID.UNUSED_6},
};
}
}

View file

@ -276,7 +276,7 @@ namespace PKHeX.Core
// Invalid
case PK2 pk2 when pk.Species > Legal.MaxSpeciesID_1:
var lang = pk2.Japanese ? (int)LanguageID.Japanese : (int)LanguageID.English;
var name = PKX.GetSpeciesName(pk2.Species, lang);
var name = SpeciesName.GetSpeciesName(pk2.Species, lang);
comment = string.Format(MsgPKMConvertFailFormat, name, PKMType.Name);
return null;

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
namespace PKHeX.Core
@ -60,124 +59,6 @@ namespace PKHeX.Core
/// <returns>A <see cref="bool"/> indicating whether or not the length is valid for a <see cref="PKM"/>.</returns>
public static bool IsPKM(long len) => Sizes.Contains((int)len);
/// <summary>
/// Species name lists indexed by the <see cref="PKM.Language"/> value.
/// </summary>
public static readonly string[][] SpeciesLang =
{
Util.GetSpeciesList("ja"), // 0 (unused, invalid)
Util.GetSpeciesList("ja"), // 1
Util.GetSpeciesList("en"), // 2
Util.GetSpeciesList("fr"), // 3
Util.GetSpeciesList("it"), // 4
Util.GetSpeciesList("de"), // 5
Util.GetSpeciesList("es"), // 6 (reserved for Gen3 KO?, unused)
Util.GetSpeciesList("es"), // 7
Util.GetSpeciesList("ko"), // 8
Util.GetSpeciesList("zh"), // 9 Simplified
Util.GetSpeciesList("zh2"), // 10 Traditional
};
public static readonly Dictionary<string, int>[] SpeciesDict = SpeciesLang.Select(z => z
.Select((value, index) => new {value, index}).ToDictionary(pair => pair.value, pair => pair.index))
.ToArray();
/// <summary>
/// Gets a Pokémon's default name for the desired language ID.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="lang">Language ID of the Pokémon</param>
/// <returns>The Species name if within expected range, else an empty string.</returns>
/// <remarks>Should only be used externally for message displays; for accurate in-game names use <see cref="GetSpeciesNameGeneration"/>.</remarks>
public static string GetSpeciesName(int species, int lang)
{
if ((uint)lang >= SpeciesLang.Length)
return string.Empty;
var arr = SpeciesLang[lang];
if ((uint)species >= arr.Length)
return string.Empty;
return arr[species];
}
/// <summary>
/// Gets a Pokémon's default name for the desired language ID and generation.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="lang">Language ID of the Pokémon</param>
/// <param name="generation">Generation specific formatting option</param>
/// <returns>Generation specific default species name</returns>
public static string GetSpeciesNameGeneration(int species, int lang, int generation)
{
if (generation == 3 && species == 0)
return "タマゴ";
string nick = GetSpeciesName(species, lang);
if (generation == 2 && lang == (int)LanguageID.Korean)
return StringConverter2KOR.LocalizeKOR2(nick);
if (generation < 5 && (generation != 4 || species != 0)) // All caps GenIV and previous, except GenIV eggs.
{
nick = nick.ToUpper();
if (lang == (int)LanguageID.French)
nick = StringConverter4.StripDiacriticsFR4(nick); // strips accents on E and I
}
if (generation < 3)
nick = nick.Replace(" ", string.Empty);
return nick;
}
/// <summary>
/// Checks if a nickname matches the species name of any language.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="nick">Current name</param>
/// <param name="generation">Generation specific formatting option</param>
/// <returns>True if it does not match any language name, False if not nicknamed</returns>
public static bool IsNicknamedAnyLanguage(int species, string nick, int generation = Generation)
{
if (species == 083 && string.Equals(nick, "Farfetch'd", StringComparison.OrdinalIgnoreCase)) // stupid
return false;
var langs = GetAvailableGameLanguages(generation);
return langs.All(lang => GetSpeciesNameGeneration(species, lang, generation) != nick);
}
private static ICollection<int> GetAvailableGameLanguages(int generation = Generation)
{
if (generation < 3)
return Legal.Languages_GB;
if (generation < 4)
return Legal.Languages_3;
if (generation < 7)
return Legal.Languages_46;
return Legal.Languages_7;
}
/// <summary>
/// Gets the Species name Language ID for the current name and generation.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="nick">Current name</param>
/// <param name="generation">Generation specific formatting option</param>
/// <param name="priorlang">Language ID with a higher priority</param>
/// <returns>Language ID if it does not match any language name, -1 if no matches</returns>
public static int GetSpeciesNameLanguage(int species, string nick, int generation = Generation, int priorlang = -1)
{
var langs = GetAvailableGameLanguages(generation);
if (langs.Contains(priorlang) && GetSpeciesNameGeneration(species, priorlang, generation) == nick)
return priorlang;
foreach (var lang in langs)
{
if (GetSpeciesNameGeneration(species, lang, generation) == nick)
return lang;
}
return -1;
}
/// <summary>
/// Gets randomized EVs for a given generation format
/// </summary>
@ -555,20 +436,6 @@ namespace PKHeX.Core
return sb.ToString();
}
/// <summary>
/// Gets a list of formes that the species can have.
/// </summary>
/// <param name="species">National Dex number of the Pokémon.</param>
/// <param name="types">List of type names</param>
/// <param name="forms">List of form names</param>
/// <param name="genders">List of genders names</param>
/// <param name="generation">Generation number for exclusive formes</param>
/// <returns>A list of strings corresponding to the formes that a Pokémon can have.</returns>
public static string[] GetFormList(int species, IReadOnlyList<string> types, IReadOnlyList<string> forms, IReadOnlyList<string> genders, int generation = Generation)
{
return FormConverter.GetFormList(species, types, forms, genders, generation);
}
/// <summary>
/// Gets the Unown Forme ID from PID.
/// </summary>
@ -704,48 +571,6 @@ namespace PKHeX.Core
}
}
/// <summary>
/// Gets the Main Series language ID from a GameCube (C/XD) language ID.
/// </summary>
/// <param name="value">GameCube (C/XD) language ID.</param>
/// <returns>Main Series language ID.</returns>
public static byte GetMainLangIDfromGC(byte value)
{
if (value <= 2 || value > 7)
return value;
return (byte)GCtoMainSeries[(LanguageGC)value];
}
private static readonly Dictionary<LanguageGC, LanguageID> GCtoMainSeries = new Dictionary<LanguageGC, LanguageID>
{
{LanguageGC.German, LanguageID.German},
{LanguageGC.French, LanguageID.French},
{LanguageGC.Italian, LanguageID.Italian},
{LanguageGC.Spanish, LanguageID.Spanish},
{LanguageGC.UNUSED_6, LanguageID.UNUSED_6},
};
/// <summary>
/// Gets the GameCube (C/XD) language ID from a Main Series language ID.
/// </summary>
/// <param name="value">Main Series language ID.</param>
/// <returns>GameCube (C/XD) language ID.</returns>
public static byte GetGCLangIDfromMain(byte value)
{
if (value <= 2 || value > 7)
return value;
return (byte)MainSeriesToGC[(LanguageID)value];
}
private static readonly Dictionary<LanguageID, LanguageGC> MainSeriesToGC = new Dictionary<LanguageID, LanguageGC>
{
{LanguageID.German, LanguageGC.German},
{LanguageID.French, LanguageGC.French},
{LanguageID.Italian, LanguageGC.Italian},
{LanguageID.Spanish, LanguageGC.Spanish},
{LanguageID.UNUSED_6, LanguageGC.UNUSED_6},
};
/// <summary>
/// Gets an array of valid <see cref="PKM"/> file extensions.
/// </summary>
@ -797,79 +622,6 @@ namespace PKHeX.Core
return last == 'x' ? 6 : prefer;
}
/// <summary>
/// Copies a <see cref="PKM"/> list to the destination list, with an option to copy to a starting point.
/// </summary>
/// <param name="list">Source list to copy from</param>
/// <param name="dest">Destination list/array</param>
/// <param name="skip">Criteria for skipping a slot</param>
/// <param name="start">Starting point to copy to</param>
/// <returns>Count of <see cref="PKM"/> copied.</returns>
public static int CopyTo(this IEnumerable<PKM> list, IList<PKM> dest, Func<PKM, bool> skip, int start = 0)
{
int ctr = start;
int skipped = 0;
foreach (var z in list)
{
// seek forward to next open slot
int next = FindNextSlot(dest, skip, ctr);
if (next == -1)
break;
skipped += next - ctr;
ctr = next;
dest[ctr++] = z;
}
return ctr - start - skipped;
}
private static int FindNextSlot(IList<PKM> dest, Func<PKM, bool> skip, int ctr)
{
while (true)
{
if (ctr >= dest.Count)
return -1;
var exist = dest[ctr];
if (exist == null || !skip(exist))
return ctr;
ctr++;
}
}
/// <summary>
/// Copies an <see cref="Enumerable"/> list to the destination list, with an option to copy to a starting point.
/// </summary>
/// <typeparam name="T">Typed object to copy</typeparam>
/// <param name="list">Source list to copy from</param>
/// <param name="dest">Destination list/array</param>
/// <param name="start">Starting point to copy to</param>
/// <returns>Count of <see cref="T"/> copied.</returns>
public static int CopyTo<T>(this IEnumerable<T> list, IList<T> dest, int start = 0)
{
int ctr = start;
foreach (var z in list)
{
if (ctr >= dest.Count)
break;
dest[ctr++] = z;
}
return ctr - start;
}
/// <summary>
/// Detects the language of a <see cref="PK1"/> or <see cref="PK2"/> by checking the current Species name against possible names.
/// </summary>
/// <param name="pk">PKM to fetch language for</param>
/// <returns>Language ID best match (<see cref="LanguageID"/>)</returns>
public static int GetVCLanguage(PKM pk)
{
if (pk.Japanese)
return 1;
if (pk.Korean)
return 8;
int lang = GetSpeciesNameLanguage(pk.Species, pk.Nickname, pk.Format);
return lang > 0 ? lang : (int)LanguageID.English; // Default to ENG
}
internal static bool IsPKMPresentGB(byte[] data, int offset) => data[offset] != 0;
internal static bool IsPKMPresentGC(byte[] data, int offset) => BitConverter.ToUInt16(data, offset) != 0;
internal static bool IsPKMPresentGBA(byte[] data, int offset) => (data[offset + 0x13] & 0xFB) == 2; // ignore egg flag, must be FlagHasSpecies.
@ -886,7 +638,7 @@ namespace PKHeX.Core
/// Gets a function that can check a byte array (at an offset) to see if a <see cref="PKM"/> is possibly present.
/// </summary>
/// <param name="blank"></param>
/// <returns></returns>
/// <returns>Function that checks if a byte array (at an offset) has a <see cref="PKM"/> present</returns>
public static Func<byte[], int, bool> GetFuncIsPKMPresent(PKM blank)
{
if (blank.Format >= 4)

View file

@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
/// <summary>
/// Logic related to the name of a <see cref="Species"/>.
/// </summary>
public static class SpeciesName
{
/// <summary>
/// Species name lists indexed by the <see cref="LanguageID"/> value.
/// </summary>
public static readonly IReadOnlyList<IReadOnlyList<string>> SpeciesLang = new[]
{
Util.GetSpeciesList("ja"), // 0 (unused, invalid)
Util.GetSpeciesList("ja"), // 1
Util.GetSpeciesList("en"), // 2
Util.GetSpeciesList("fr"), // 3
Util.GetSpeciesList("it"), // 4
Util.GetSpeciesList("de"), // 5
Util.GetSpeciesList("es"), // 6 (reserved for Gen3 KO?, unused)
Util.GetSpeciesList("es"), // 7
Util.GetSpeciesList("ko"), // 8
Util.GetSpeciesList("zh"), // 9 Simplified
Util.GetSpeciesList("zh2"), // 10 Traditional
};
/// <summary>
/// <see cref="PKM.Nickname"/> to <see cref="Species"/> table for all <see cref="LanguageID"/> values.
/// </summary>
public static readonly IReadOnlyList<Dictionary<string, int>> SpeciesDict = Util.GetMultiDictionary(SpeciesLang);
/// <summary>
/// Gets a Pokémon's default name for the desired language ID.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="lang">Language ID of the Pokémon</param>
/// <returns>The Species name if within expected range, else an empty string.</returns>
/// <remarks>Should only be used externally for message displays; for accurate in-game names use <see cref="GetSpeciesNameGeneration"/>.</remarks>
public static string GetSpeciesName(int species, int lang)
{
if ((uint)lang >= SpeciesLang.Count)
return string.Empty;
var arr = SpeciesLang[lang];
if ((uint)species >= arr.Count)
return string.Empty;
return arr[species];
}
/// <summary>
/// Gets a Pokémon's default name for the desired language ID and generation.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="lang">Language ID of the Pokémon</param>
/// <param name="generation">Generation specific formatting option</param>
/// <returns>Generation specific default species name</returns>
public static string GetSpeciesNameGeneration(int species, int lang, int generation)
{
if (generation >= 5)
return GetSpeciesName(species, lang);
if (generation == 3 && species == 0)
return "タマゴ";
string nick = GetSpeciesName(species, lang);
if (generation == 2 && lang == (int)LanguageID.Korean)
return StringConverter2KOR.LocalizeKOR2(nick);
if (generation < 5 && (generation != 4 || species != 0)) // All caps GenIV and previous, except GenIV eggs.
{
nick = nick.ToUpper();
if (lang == (int)LanguageID.French)
nick = StringConverter4.StripDiacriticsFR4(nick); // strips accents on E and I
}
if (generation < 3)
nick = nick.Replace(" ", string.Empty);
return nick;
}
/// <summary>
/// Checks if a nickname matches the species name of any language.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="nick">Current name</param>
/// <param name="generation">Generation specific formatting option</param>
/// <returns>True if it does not match any language name, False if not nicknamed</returns>
public static bool IsNicknamedAnyLanguage(int species, string nick, int generation = PKX.Generation)
{
if (species == 083 && string.Equals(nick, "Farfetch'd", StringComparison.OrdinalIgnoreCase)) // stupid
return false;
var langs = Language.GetAvailableGameLanguages(generation);
return langs.All(lang => GetSpeciesNameGeneration(species, lang, generation) != nick);
}
/// <summary>
/// Gets the Species name Language ID for the current name and generation.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="priorityLanguage">Language ID with a higher priority</param>
/// <param name="nick">Current name</param>
/// <param name="generation">Generation specific formatting option</param>
/// <returns>Language ID if it does not match any language name, -1 if no matches</returns>
public static int GetSpeciesNameLanguage(int species, int priorityLanguage, string nick, int generation = PKX.Generation)
{
var langs = Language.GetAvailableGameLanguages(generation);
if (langs.Contains(priorityLanguage) && GetSpeciesNameGeneration(species, priorityLanguage, generation) == nick)
return priorityLanguage;
return GetSpeciesNameLanguage(species, nick, generation, langs);
}
/// <summary>
/// Gets the Species name Language ID for the current name and generation.
/// </summary>
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
/// <param name="nick">Current name</param>
/// <param name="generation">Generation specific formatting option</param>
/// <returns>Language ID if it does not match any language name, -1 if no matches</returns>
public static int GetSpeciesNameLanguage(int species, string nick, int generation = PKX.Generation)
{
var langs = Language.GetAvailableGameLanguages(generation);
return GetSpeciesNameLanguage(species, nick, generation, langs);
}
private static int GetSpeciesNameLanguage(int species, string nick, int generation, IReadOnlyList<int> langs)
{
foreach (var lang in langs)
{
if (GetSpeciesNameGeneration(species, lang, generation) == nick)
return lang;
}
return -1;
}
/// <summary>
/// Gets the Species ID for the specified <see cref="specName"/> and <see cref="language"/>.
/// </summary>
/// <param name="specName">Species Name</param>
/// <param name="language">Language the name is from</param>
/// <returns>Species ID</returns>
/// <remarks>Only use this for modern era name -> ID fetching.</remarks>
public static int GetSpeciesID(string specName, int language = (int)LanguageID.English)
{
return SpeciesDict[language].TryGetValue(specName, out var val) ? val : -1;
}
}
}

View file

@ -91,7 +91,7 @@ namespace PKHeX.Core
public override int Version { get => GetGBAVersionID(Data[0x34]); set => Data[0x34] = GetGCVersionID(value); }
public int CurrentRegion { get => Data[0x35]; set => Data[0x35] = (byte)value; }
public int OriginalRegion { get => Data[0x36]; set => Data[0x36] = (byte)value; }
public override int Language { get => PKX.GetMainLangIDfromGC(Data[0x37]); set => Data[0x37] = PKX.GetGCLangIDfromMain((byte)value); }
public override int Language { get => Core.Language.GetMainLangIDfromGC(Data[0x37]); set => Data[0x37] = Core.Language.GetGCLangIDfromMain((byte)value); }
public override string OT_Name { get => GetString(0x38, 20); set => SetString(value, 10).CopyTo(Data, 0x38); } // +2 terminator
public override string Nickname { get => GetString(0x4E, 20); set { SetString(value, 10).CopyTo(Data, 0x4E); Nickname2 = value; } } // +2 terminator
private string Nickname2 { get => GetString(0x64, 20); set => SetString(value, 10).CopyTo(Data, 0x64); } // +2 terminator

View file

@ -103,7 +103,7 @@ namespace PKHeX.Core
public string GenderString => (uint) Gender >= Genders.Count ? string.Empty : Genders[Gender];
public string ShinyString => IsShiny ? "★ " : string.Empty;
public string FormString => AltForm != 0 ? $"-{AltForm}" : string.Empty;
private string NickStr => string.IsNullOrWhiteSpace(Nickname) ? PKX.GetSpeciesNameGeneration(Species, (int)LanguageID.English, 7) : Nickname;
private string NickStr => string.IsNullOrWhiteSpace(Nickname) ? SpeciesName.GetSpeciesNameGeneration(Species, (int)LanguageID.English, 7) : Nickname;
public string FileName => $"{FileNameWithoutExtension}.gp1";
public string FileNameWithoutExtension
@ -151,7 +151,7 @@ namespace PKHeX.Core
}
else
{
pk.Nickname = PKX.GetSpeciesNameGeneration(Species, sav.Language, 7);
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, sav.Language, 7);
}
pk.IV_DEF = pk.IV_SPD = (IV3 * 2) + 1;

View file

@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace PKHeX.Core
{
/// <summary>
/// Byte array reusable logic
/// Array reusable logic
/// </summary>
public static class ArrayUtil
{
@ -75,5 +75,63 @@ namespace PKHeX.Core
SetBitFlagArray(data, 0, value);
return data;
}
/// <summary>
/// Copies a <see cref="T"/> list to the destination list, with an option to copy to a starting point.
/// </summary>
/// <param name="list">Source list to copy from</param>
/// <param name="dest">Destination list/array</param>
/// <param name="skip">Criteria for skipping a slot</param>
/// <param name="start">Starting point to copy to</param>
/// <returns>Count of <see cref="T"/> copied.</returns>
public static int CopyTo<T>(this IEnumerable<T> list, IList<T> dest, Func<T, bool> skip, int start = 0)
{
int ctr = start;
int skipped = 0;
foreach (var z in list)
{
// seek forward to next open slot
int next = FindNextValidIndex(dest, skip, ctr);
if (next == -1)
break;
skipped += next - ctr;
ctr = next;
dest[ctr++] = z;
}
return ctr - start - skipped;
}
public static int FindNextValidIndex<T>(IList<T> dest, Func<T, bool> skip, int ctr)
{
while (true)
{
if ((uint)ctr >= dest.Count)
return -1;
var exist = dest[ctr];
if (exist == null || !skip(exist))
return ctr;
ctr++;
}
}
/// <summary>
/// Copies an <see cref="IEnumerable{T}"/> list to the destination list, with an option to copy to a starting point.
/// </summary>
/// <typeparam name="T">Typed object to copy</typeparam>
/// <param name="list">Source list to copy from</param>
/// <param name="dest">Destination list/array</param>
/// <param name="start">Starting point to copy to</param>
/// <returns>Count of <see cref="T"/> copied.</returns>
public static int CopyTo<T>(this IEnumerable<T> list, IList<T> dest, int start = 0)
{
int ctr = start;
foreach (var z in list)
{
if ((uint)ctr >= dest.Count)
break;
dest[ctr++] = z;
}
return ctr - start;
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
@ -143,5 +144,18 @@ namespace PKHeX.Core
int index = input.IndexOf(c);
return index < 0 ? input : input.Substring(0, index);
}
public static Dictionary<string, int>[] GetMultiDictionary(IReadOnlyList<IReadOnlyList<string>> nameArray)
{
var result = new Dictionary<string, int>[nameArray.Count];
for (int i = 0; i < result.Length; i++)
{
var dict = result[i] = new Dictionary<string, int>();
var names = nameArray[i];
for (int j = 0; j < names.Count; j++)
dict.Add(names[j], j);
}
return result;
}
}
}

View file

@ -10,11 +10,11 @@ namespace PKHeX.WinForms.Controls
return;
LoadMisc1(pk1);
TID_Trainer.LoadIDValues(pkm);
TID_Trainer.LoadIDValues(pk1);
CR_PK1.LoadPK1(pk1);
// Attempt to detect language
CB_Language.SelectedValue = PKX.GetVCLanguage(pk1);
CB_Language.SelectedValue = pk1.GuessedLanguage();
LoadPartyStats(pk1);
UpdateStats();

View file

@ -12,13 +12,13 @@ namespace PKHeX.WinForms.Controls
LoadMisc1(pk2);
LoadMisc2(pk2);
TID_Trainer.LoadIDValues(pkm);
TID_Trainer.LoadIDValues(pk2);
TB_MetLevel.Text = pk2.Met_Level.ToString();
CB_MetLocation.SelectedValue = pk2.Met_Location;
CB_MetTimeOfDay.SelectedIndex = pk2.Met_TimeOfDay;
// Attempt to detect language
CB_Language.SelectedValue = PKX.GetVCLanguage(pk2);
CB_Language.SelectedValue = pk2.GuessedLanguage();
LoadPartyStats(pk2);
UpdateStats();

View file

@ -390,7 +390,7 @@ namespace PKHeX.WinForms.Controls
if (!hasForms)
return;
var ds = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, gendersymbols, pkm.Format);
var ds = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, gendersymbols, pkm.Format);
if (ds.Length == 1 && string.IsNullOrEmpty(ds[0])) // empty (Alolan Totems)
CB_Form.Enabled = CB_Form.Visible = Label_Form.Visible = false;
else
@ -1163,7 +1163,7 @@ namespace PKHeX.WinForms.Controls
if (CHK_IsEgg.Checked)
species = 0; // get the egg name.
if (PKX.IsNicknamedAnyLanguage(species, TB_Nickname.Text, pkm.Format))
if (SpeciesName.IsNicknamedAnyLanguage(species, TB_Nickname.Text, pkm.Format))
CHK_Nicknamed.Checked = true;
}
@ -1194,10 +1194,10 @@ namespace PKHeX.WinForms.Controls
species = 0; // get the egg name.
// If name is that of another language, don't replace the nickname
if (sender != CB_Language && species != 0 && !PKX.IsNicknamedAnyLanguage(species, TB_Nickname.Text, pkm.Format))
if (sender != CB_Language && species != 0 && !SpeciesName.IsNicknamedAnyLanguage(species, TB_Nickname.Text, pkm.Format))
return;
TB_Nickname.Text = PKX.GetSpeciesNameGeneration(species, lang, pkm.Format);
TB_Nickname.Text = SpeciesName.GetSpeciesNameGeneration(species, lang, pkm.Format);
if (pkm is _K12 pk)
pk.SetNotNicknamed();
}
@ -1282,7 +1282,7 @@ namespace PKHeX.WinForms.Controls
if (!CHK_Nicknamed.Checked)
{
TB_Nickname.Text = PKX.GetSpeciesNameGeneration(0, WinFormsUtil.GetIndex(CB_Language), pkm.Format);
TB_Nickname.Text = SpeciesName.GetSpeciesNameGeneration(0, WinFormsUtil.GetIndex(CB_Language), pkm.Format);
if (pkm.Format != 4) // eggs in gen4 do not have nickname flag
CHK_Nicknamed.Checked = true;
}
@ -1305,7 +1305,7 @@ namespace PKHeX.WinForms.Controls
GB_EggConditions.Enabled = false;
}
if (TB_Nickname.Text == PKX.GetSpeciesNameGeneration(0, WinFormsUtil.GetIndex(CB_Language), pkm.Format))
if (TB_Nickname.Text == SpeciesName.GetSpeciesNameGeneration(0, WinFormsUtil.GetIndex(CB_Language), pkm.Format))
CHK_Nicknamed.Checked = false;
}

View file

@ -142,7 +142,7 @@ namespace PKHeX.WinForms
private void B_ApplyTrash_Click(object sender, EventArgs e)
{
string species = PKX.GetSpeciesNameGeneration(WinFormsUtil.GetIndex(CB_Species),
string species = SpeciesName.GetSpeciesNameGeneration(WinFormsUtil.GetIndex(CB_Species),
WinFormsUtil.GetIndex(CB_Language), (int) NUD_Generation.Value);
if (string.IsNullOrEmpty(species)) // no result

View file

@ -1,5 +1,4 @@
using System;
using System.Drawing;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using PKHeX.Core;
@ -26,7 +25,10 @@ namespace PKHeX.WinForms
foreach (var pair in pairs)
{
var split = pair.Name.Split('_');
int species = Array.IndexOf(PKX.SpeciesLang[2], split[0].Substring(4));
var specName = split[0].Substring(4);
// convert species name to current localization language
int species = SpeciesName.GetSpeciesID(specName);
var pkmname = GameInfo.Strings.specieslist[species];
if (split.Length != 1)

View file

@ -153,7 +153,7 @@ namespace PKHeX.WinForms
private static string[] GetFormNames4Dex(int species)
{
string[] formNames = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, 4);
string[] formNames = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, 4);
if (species == 172)
formNames = new[] { MALE, FEMALE, formNames[1] }; // Spiky
return formNames;

View file

@ -705,7 +705,7 @@ namespace PKHeX.WinForms
L_Form.Visible = CB_Form.Enabled = CB_Form.Visible = hasForms;
CB_Form.InitializeBinding();
var list = PKX.GetFormList(slot.Species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
var list = FormConverter.GetFormList(slot.Species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
CB_Form.DataSource = new BindingSource(list, null);
}
}

View file

@ -140,7 +140,7 @@ namespace PKHeX.WinForms
int f = SAV is SAV5B2W2 ? DexFormUtil.GetDexFormIndexB2W2(species, fc) : DexFormUtil.GetDexFormIndexBW(species, fc);
if (f < 0)
return;
string[] forms = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
string[] forms = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
if (forms.Length < 1)
return;

View file

@ -341,7 +341,7 @@ namespace PKHeX.WinForms
else
{
// get language
TB_Nickname.Text = PKX.GetSpeciesNameGeneration(species, SAV.Language, 6);
TB_Nickname.Text = SpeciesName.GetSpeciesNameGeneration(species, SAV.Language, 6);
}
}
TB_Nickname.ReadOnly = !CHK_Nicknamed.Checked;
@ -356,7 +356,7 @@ namespace PKHeX.WinForms
CB_Form.Enabled = CB_Form.Visible = hasForms;
CB_Form.InitializeBinding();
CB_Form.DataSource = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
CB_Form.DataSource = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
}
private void UpdateSpecies(object sender, EventArgs e)

View file

@ -136,7 +136,7 @@ namespace PKHeX.WinForms
int f = DexFormUtil.GetDexFormIndexORAS(species, fc);
if (f < 0)
return;
string[] forms = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
string[] forms = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
if (forms.Length < 1)
return;

View file

@ -144,7 +144,7 @@ namespace PKHeX.WinForms
int f = DexFormUtil.GetDexFormIndexXY(species, fc);
if (f < 0)
return;
string[] forms = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
string[] forms = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
if (forms.Length < 1)
return;

View file

@ -446,7 +446,7 @@ namespace PKHeX.WinForms
CB_Form.Enabled = CB_Form.Visible = hasForms;
CB_Form.InitializeBinding();
CB_Form.DataSource = PKX.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
CB_Form.DataSource = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
}
private void UpdateSpecies(object sender, EventArgs e)

View file

@ -99,7 +99,7 @@ namespace PKHeX.WinForms
L_Vivillon.Text = GameInfo.Strings.specieslist[(int)Species.Vivillon] + ":";
CB_Vivillon.InitializeBinding();
CB_Vivillon.DataSource = PKX.GetFormList((int)Species.Vivillon, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, 6).ToList();
CB_Vivillon.DataSource = FormConverter.GetFormList((int)Species.Vivillon, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, 6);
}
private void GetBadges()

View file

@ -663,7 +663,7 @@ namespace PKHeX.WinForms
LoadFacility();
}
private string GetSpeciesNameFromPKM(PKM pkm) => PKX.GetSpeciesName(pkm.Species, SAV.Language);
private string GetSpeciesNameFromPKM(PKM pkm) => SpeciesName.GetSpeciesName(pkm.Species, SAV.Language);
private void B_ImportParty_Click(object sender, EventArgs e)
{

View file

@ -130,7 +130,7 @@ namespace PKHeX.WinForms
bool hasForms = FormConverter.HasFormSelection(SAV.Personal[bspecies], bspecies, 7);
LB_Forms.Enabled = hasForms;
if (!hasForms) return false;
var ds = PKX.GetFormList(bspecies, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
var ds = FormConverter.GetFormList(bspecies, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
if (ds.Count == 1 && string.IsNullOrEmpty(ds[0]))
{
// empty

View file

@ -124,7 +124,7 @@ namespace PKHeX.WinForms
LB_Forms.Enabled = hasForms;
if (!hasForms)
return false;
var ds = PKX.GetFormList(bspecies, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
var ds = FormConverter.GetFormList(bspecies, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
if (ds.Count == 1 && string.IsNullOrEmpty(ds[0]))
{
// empty

View file

@ -70,7 +70,7 @@ namespace PKHeX.WinForms
L_Vivillon.Text = GameInfo.Strings.Species[(int)Species.Vivillon] + ":";
CB_Vivillon.InitializeBinding();
CB_Vivillon.DataSource = PKX.GetFormList((int)Species.Vivillon, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).ToList();
CB_Vivillon.DataSource = FormConverter.GetFormList((int)Species.Vivillon, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation);
if (!(SAV is SAV7USUM))
BattleStyles.RemoveAt(BattleStyles.Count - 1); // remove Nihilist