2018-03-11 02:03:09 +00:00
using System ;
using System.Linq ;
namespace PKHeX.Core
{
/// <summary>
/// Contains extension logic for modifying <see cref="PKM"/> data.
/// </summary>
public static class CommonEdits
{
2019-02-24 21:57:10 +00:00
/// <summary>
2020-04-12 20:05:29 +00:00
/// Setting which enables/disables automatic manipulation of <see cref="PKM.Markings"/> when importing from a <see cref="IBattleTemplate"/>.
2019-02-24 21:57:10 +00:00
/// </summary>
2018-03-13 00:40:09 +00:00
public static bool ShowdownSetIVMarkings { get ; set ; } = true ;
2020-03-19 20:47:25 +00:00
/// <summary>
/// Setting which causes the <see cref="PKM.StatNature"/> to the <see cref="PKM.Nature"/> in Gen8+ formats.
/// </summary>
2020-04-12 20:05:29 +00:00
public static bool ShowdownSetBehaviorNature { get ; set ; }
2020-03-19 20:47:25 +00:00
2018-03-11 02:03:09 +00:00
/// <summary>
/// Sets the <see cref="PKM.Nickname"/> to the provided value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="nick"><see cref="PKM.Nickname"/> to set. If no nickname is provided, the <see cref="PKM.Nickname"/> is set to the default value for its current language and format.</param>
2019-02-12 05:49:05 +00:00
public static void SetNickname ( this PKM pk , string nick )
2018-03-11 02:03:09 +00:00
{
2019-02-12 05:49:05 +00:00
if ( string . IsNullOrWhiteSpace ( nick ) )
2018-03-11 02:03:09 +00:00
{
2019-02-12 05:49:05 +00:00
pk . ClearNickname ( ) ;
return ;
2018-03-11 02:03:09 +00:00
}
2019-02-12 05:49:05 +00:00
pk . IsNicknamed = true ;
pk . Nickname = nick ;
}
2019-02-24 21:57:10 +00:00
/// <summary>
/// Clears the <see cref="PKM.Nickname"/> to the default value.
/// </summary>
/// <param name="pk"></param>
2019-05-30 05:40:07 +00:00
public static string ClearNickname ( this PKM pk )
2019-02-12 05:49:05 +00:00
{
pk . IsNicknamed = false ;
2019-09-19 02:58:23 +00:00
string nick = SpeciesName . GetSpeciesNameGeneration ( pk . Species , pk . Language , pk . Format ) ;
2019-05-30 05:40:07 +00:00
pk . Nickname = nick ;
2019-10-26 19:42:33 +00:00
if ( pk is GBPKM pk12 )
2019-02-12 05:49:05 +00:00
pk12 . SetNotNicknamed ( ) ;
2019-05-30 05:40:07 +00:00
return nick ;
2018-03-11 02:03:09 +00:00
}
/// <summary>
/// Sets the <see cref="PKM.AltForm"/> value, with special consideration for <see cref="PKM.Format"/> values which derive the <see cref="PKM.AltForm"/> value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="form">Desired <see cref="PKM.AltForm"/> value to set.</param>
public static void SetAltForm ( this PKM pk , int form )
{
switch ( pk . Format )
{
case 2 :
while ( pk . AltForm ! = form )
pk . SetRandomIVs ( ) ;
break ;
case 3 :
pk . SetPIDUnown3 ( form ) ;
break ;
default :
pk . AltForm = form ;
break ;
}
}
/// <summary>
/// Sets the <see cref="PKM.Ability"/> value by sanity checking the provided <see cref="PKM.Ability"/> against the possible pool of abilities.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="abil">Desired <see cref="PKM.Ability"/> to set.</param>
public static void SetAbility ( this PKM pk , int abil )
{
2018-04-26 01:45:31 +00:00
if ( abil < 0 )
return ;
2020-09-06 17:53:13 +00:00
var index = pk . PersonalInfo . GetAbilityIndex ( abil ) ;
2020-06-17 02:46:22 +00:00
index = Math . Max ( 0 , index ) ;
pk . SetAbilityIndex ( index ) ;
2018-09-03 17:30:35 +00:00
}
2018-03-11 02:03:09 +00:00
2018-09-03 17:30:35 +00:00
/// <summary>
/// Sets the <see cref="PKM.Ability"/> value based on the provided ability index (0-2)
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
2020-06-17 02:46:22 +00:00
/// <param name="index">Desired <see cref="PKM.AbilityNumber"/> (shifted by 1) to set.</param>
public static void SetAbilityIndex ( this PKM pk , int index )
2018-09-03 17:30:35 +00:00
{
2020-06-17 02:46:22 +00:00
if ( pk is PK5 pk5 & & index = = 2 )
2018-03-11 02:03:09 +00:00
pk5 . HiddenAbility = true ;
else if ( pk . Format < = 5 )
2020-06-17 02:46:22 +00:00
pk . PID = PKX . GetRandomPID ( Util . Rand , pk . Species , pk . Gender , pk . Version , pk . Nature , pk . AltForm , ( uint ) ( index * 0x10001 ) ) ;
pk . RefreshAbility ( index ) ;
2018-03-11 02:03:09 +00:00
}
/// <summary>
/// Sets a Random <see cref="PKM.EncryptionConstant"/> value. The <see cref="PKM.EncryptionConstant"/> is not updated if the value should match the <see cref="PKM.PID"/> instead.
/// </summary>
2018-09-03 17:30:35 +00:00
/// <remarks>Accounts for Wurmple evolutions.</remarks>
2018-03-11 02:03:09 +00:00
/// <param name="pk">Pokémon to modify.</param>
public static void SetRandomEC ( this PKM pk )
{
int gen = pk . GenNumber ;
2019-05-11 21:25:58 +00:00
if ( 2 < gen & & gen < 6 )
{
2018-03-11 02:03:09 +00:00
pk . EncryptionConstant = pk . PID ;
2019-05-11 21:25:58 +00:00
return ;
}
int wIndex = WurmpleUtil . GetWurmpleEvoGroup ( pk . Species ) ;
if ( wIndex ! = - 1 )
{
2020-06-17 02:46:22 +00:00
pk . EncryptionConstant = WurmpleUtil . GetWurmpleEncryptionConstant ( wIndex ) ;
2019-05-11 21:25:58 +00:00
return ;
}
pk . EncryptionConstant = Util . Rand32 ( ) ;
2018-03-11 02:03:09 +00:00
}
/// <summary>
/// Sets the <see cref="PKM.IsShiny"/> derived value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="shiny">Desired <see cref="PKM.IsShiny"/> state to set.</param>
/// <returns></returns>
2018-10-27 15:53:09 +00:00
public static bool SetIsShiny ( this PKM pk , bool shiny ) = > shiny ? SetShiny ( pk ) : pk . SetUnshiny ( ) ;
2018-03-11 02:03:09 +00:00
/// <summary>
/// Makes a <see cref="PKM"/> shiny.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
2020-06-12 18:45:56 +00:00
/// <param name="type">Shiny type to force. Only use Always* or Random</param>
2018-04-04 16:53:48 +00:00
/// <returns>Returns true if the <see cref="PKM"/> data was modified.</returns>
2020-06-12 18:45:56 +00:00
public static bool SetShiny ( PKM pk , Shiny type = Shiny . Random )
2018-03-11 02:03:09 +00:00
{
if ( pk . IsShiny )
return false ;
2020-06-19 23:51:15 +00:00
if ( pk . FatefulEncounter | | pk . Version = = ( int ) GameVersion . GO | | type = = Shiny . Random )
2019-11-21 04:38:05 +00:00
{
pk . SetShiny ( ) ;
2020-06-12 18:45:56 +00:00
return true ;
}
2019-11-21 04:38:05 +00:00
2020-06-12 18:45:56 +00:00
while ( true )
{
pk . SetShiny ( ) ;
2020-02-21 23:02:16 +00:00
2019-11-21 04:38:05 +00:00
var xor = pk . ShinyXor ;
2020-06-12 18:45:56 +00:00
if ( type = = Shiny . AlwaysSquare ? xor = = 0 : xor ! = 0 )
2019-11-21 04:38:05 +00:00
return true ;
}
2018-03-11 02:03:09 +00:00
}
/// <summary>
/// Makes a <see cref="PKM"/> not-shiny.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
2018-04-04 16:53:48 +00:00
/// <returns>Returns true if the <see cref="PKM"/> data was modified.</returns>
2018-03-11 02:03:09 +00:00
public static bool SetUnshiny ( this PKM pk )
{
if ( ! pk . IsShiny )
return false ;
pk . SetPIDGender ( pk . Gender ) ;
return true ;
}
/// <summary>
/// Sets the <see cref="PKM.Nature"/> value, with special consideration for the <see cref="PKM.Format"/> values which derive the <see cref="PKM.Nature"/> value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="nature">Desired <see cref="PKM.Nature"/> value to set.</param>
public static void SetNature ( this PKM pk , int nature )
{
2019-05-30 05:40:07 +00:00
var value = Math . Min ( ( int ) Nature . Quirky , Math . Max ( ( int ) Nature . Hardy , nature ) ) ;
2019-11-16 01:34:18 +00:00
if ( pk . Format > = 8 )
pk . StatNature = value ;
else if ( pk . Format < = 4 )
2019-05-30 05:40:07 +00:00
pk . SetPIDNature ( value ) ;
2018-03-11 02:03:09 +00:00
else
2019-05-30 05:40:07 +00:00
pk . Nature = value ;
2018-03-11 02:03:09 +00:00
}
/// <summary>
2020-04-12 20:05:29 +00:00
/// Copies <see cref="IBattleTemplate"/> details to the <see cref="PKM"/>.
2018-03-11 02:03:09 +00:00
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
2020-04-12 20:05:29 +00:00
/// <param name="Set"><see cref="IBattleTemplate"/> details to copy from.</param>
public static void ApplySetDetails ( this PKM pk , IBattleTemplate Set )
2018-03-11 02:03:09 +00:00
{
2018-05-07 01:40:51 +00:00
pk . Species = Math . Min ( pk . MaxSpeciesID , Set . Species ) ;
pk . SetMoves ( Set . Moves , true ) ;
2018-04-26 01:45:31 +00:00
pk . ApplyHeldItem ( Set . HeldItem , Set . Format ) ;
2018-03-11 02:03:09 +00:00
pk . CurrentLevel = Set . Level ;
pk . CurrentFriendship = Set . Friendship ;
pk . IVs = Set . IVs ;
2020-09-07 17:56:25 +00:00
// In Generation 1/2 Format sets, when EVs are not specified at all, it implies maximum EVs instead!
// Under this scenario, just apply maximum EVs (65535).
if ( pk is GBPKM gb & & Set . EVs . All ( z = > z = = 0 ) )
gb . EV_HP = gb . EV_ATK = gb . EV_DEF = gb . EV_SPC = gb . EV_SPE = gb . MaxEV ;
else
pk . EVs = Set . EVs ;
2018-03-11 02:03:09 +00:00
2020-08-15 04:49:01 +00:00
// IVs have no side effects such as hidden power type in gen 8
// therefore all specified IVs are deliberate and should not be HT'd over for pokemon met in gen 8
if ( ! pk . Gen8 )
pk . SetSuggestedHyperTrainingData ( Set . IVs ) ;
2018-03-13 00:40:09 +00:00
if ( ShowdownSetIVMarkings )
pk . SetMarkings ( ) ;
2018-03-11 02:03:09 +00:00
pk . SetNickname ( Set . Nickname ) ;
pk . SetAltForm ( Set . FormIndex ) ;
2018-05-12 04:48:58 +00:00
pk . SetGender ( Set . Gender ) ;
2018-03-20 00:32:45 +00:00
pk . SetMaximumPPUps ( Set . Moves ) ;
2018-03-11 02:03:09 +00:00
pk . SetAbility ( Set . Ability ) ;
pk . SetNature ( Set . Nature ) ;
pk . SetIsShiny ( Set . Shiny ) ;
pk . SetRandomEC ( ) ;
2018-11-11 04:21:36 +00:00
if ( pk is IAwakened a )
2018-11-20 02:26:46 +00:00
{
2018-11-11 04:21:36 +00:00
a . SetSuggestedAwakenedValues ( pk ) ;
2018-11-21 07:57:38 +00:00
if ( pk is PB7 b )
2018-11-20 02:26:46 +00:00
{
for ( int i = 0 ; i < 6 ; i + + )
pk . SetEV ( i , 0 ) ;
2018-11-21 07:57:38 +00:00
b . ResetCalculatedValues ( ) ;
2018-11-20 02:26:46 +00:00
}
}
2019-11-26 01:32:10 +00:00
2019-11-19 23:57:08 +00:00
if ( pk is IGigantamax c )
c . CanGigantamax = Set . CanGigantamax ;
2020-05-16 22:15:41 +00:00
if ( pk is IDynamaxLevel d )
d . DynamaxLevel = ( byte ) ( d . CanHaveDynamaxLevel ( pk ) ? 10 : 0 ) ;
2018-11-11 04:21:36 +00:00
2019-11-24 14:06:08 +00:00
pk . ClearRecordFlags ( ) ;
pk . SetRecordFlags ( Set . Moves ) ;
2020-03-19 20:47:25 +00:00
if ( ShowdownSetBehaviorNature & & pk . Format > = 8 )
pk . Nature = pk . StatNature ;
2018-03-11 02:03:09 +00:00
var legal = new LegalityAnalysis ( pk ) ;
2018-04-21 23:42:45 +00:00
if ( legal . Parsed & & legal . Info . Relearn . Any ( z = > ! z . Valid ) )
2019-10-25 01:11:25 +00:00
pk . SetRelearnMoves ( legal . GetSuggestedRelearnMoves ( ) ) ;
2019-11-26 01:32:10 +00:00
pk . ResetPartyStats ( ) ;
2018-04-22 00:47:32 +00:00
pk . RefreshChecksum ( ) ;
2018-03-11 02:03:09 +00:00
}
2018-04-26 01:45:31 +00:00
/// <summary>
2018-10-31 20:52:09 +00:00
/// Sets the <see cref="PKM.HeldItem"/> value depending on the current format and the provided item index & format.
2018-04-26 01:45:31 +00:00
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="item">Held Item to apply</param>
/// <param name="format">Format required for importing</param>
public static void ApplyHeldItem ( this PKM pk , int item , int format )
{
2020-06-17 02:46:22 +00:00
item = ItemConverter . GetItemForFormat ( item , format , pk . Format ) ;
2019-02-12 05:49:05 +00:00
pk . HeldItem = ( ( uint ) item > pk . MaxItemID ) ? 0 : item ;
2018-04-26 01:45:31 +00:00
}
2018-03-11 02:03:09 +00:00
/// <summary>
/// Sets one of the <see cref="PKM.EVs"/> based on its index within the array.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="index">Index to set to</param>
/// <param name="value">Value to set</param>
public static void SetEV ( this PKM pk , int index , int value )
{
switch ( index )
{
case 0 : pk . EV_HP = value ; break ;
case 1 : pk . EV_ATK = value ; break ;
case 2 : pk . EV_DEF = value ; break ;
case 3 : pk . EV_SPE = value ; break ;
case 4 : pk . EV_SPA = value ; break ;
case 5 : pk . EV_SPD = value ; break ;
default :
throw new ArgumentOutOfRangeException ( nameof ( index ) ) ;
}
}
2018-07-29 20:27:48 +00:00
2018-03-11 02:03:09 +00:00
/// <summary>
/// Sets one of the <see cref="PKM.IVs"/> based on its index within the array.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="index">Index to set to</param>
/// <param name="value">Value to set</param>
public static void SetIV ( this PKM pk , int index , int value )
{
switch ( index )
{
case 0 : pk . IV_HP = value ; break ;
case 1 : pk . IV_ATK = value ; break ;
case 2 : pk . IV_DEF = value ; break ;
case 3 : pk . IV_SPE = value ; break ;
case 4 : pk . IV_SPA = value ; break ;
case 5 : pk . IV_SPD = value ; break ;
default :
throw new ArgumentOutOfRangeException ( nameof ( index ) ) ;
}
}
/// <summary>
/// Fetches the highest value the provided <see cref="PKM.EVs"/> index can be while considering others.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="index">Index to fetch for</param>
/// <returns>Highest value the value can be.</returns>
public static int GetMaximumEV ( this PKM pk , int index )
{
if ( pk . Format < 3 )
return ushort . MaxValue ;
2020-06-17 02:46:22 +00:00
var sum = pk . EVTotal - pk . GetEV ( index ) ;
2018-03-11 02:03:09 +00:00
int remaining = 510 - sum ;
2018-08-26 23:29:52 +00:00
return Math . Min ( Math . Max ( remaining , 0 ) , 252 ) ;
2018-03-11 02:03:09 +00:00
}
/// <summary>
/// Fetches the highest value the provided <see cref="PKM.IVs"/>.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="index">Index to fetch for</param>
2020-06-17 02:46:22 +00:00
/// <param name="allow30">Causes the returned value to be dropped down -1 if the value is already at a maximum.</param>
2018-03-11 02:03:09 +00:00
/// <returns>Highest value the value can be.</returns>
2019-12-27 02:47:31 +00:00
public static int GetMaximumIV ( this PKM pk , int index , bool allow30 = false )
2018-03-11 02:03:09 +00:00
{
2019-12-27 02:47:31 +00:00
if ( pk . GetIV ( index ) = = pk . MaxIV & & allow30 )
2018-03-11 02:03:09 +00:00
return pk . MaxIV - 1 ;
return pk . MaxIV ;
}
2018-04-22 19:43:18 +00:00
/// <summary>
/// Force hatches a PKM by applying the current species name and a valid Met Location from the origin game.
/// </summary>
2019-12-27 02:47:31 +00:00
/// <param name="pk">PKM to apply hatch details to</param>
2018-04-22 19:43:18 +00:00
/// <param name="reHatch">Re-hatch already hatched <see cref="PKM"/> inputs</param>
2019-12-27 02:47:31 +00:00
public static void ForceHatchPKM ( this PKM pk , bool reHatch = false )
2018-04-22 19:43:18 +00:00
{
2019-12-27 02:47:31 +00:00
if ( ! pk . IsEgg & & ! reHatch )
2018-04-22 19:43:18 +00:00
return ;
2019-12-27 02:47:31 +00:00
pk . IsEgg = false ;
pk . ClearNickname ( ) ;
pk . CurrentFriendship = pk . PersonalInfo . BaseFriendship ;
if ( pk . IsTradedEgg )
pk . Egg_Location = pk . Met_Location ;
var loc = EncounterSuggestion . GetSuggestedEggMetLocation ( pk ) ;
2018-04-22 19:43:18 +00:00
if ( loc > = 0 )
2019-12-27 02:47:31 +00:00
pk . Met_Location = loc ;
pk . MetDate = DateTime . Today ;
if ( pk . Gen6 )
pk . SetHatchMemory6 ( ) ;
2018-04-22 19:43:18 +00:00
}
2018-12-30 06:19:44 +00:00
/// <summary>
/// Force hatches a PKM by applying the current species name and a valid Met Location from the origin game.
/// </summary>
2019-12-27 02:47:31 +00:00
/// <param name="pk">PKM to apply hatch details to</param>
2018-12-30 06:19:44 +00:00
/// <param name="origin">Game the egg originated from</param>
/// <param name="dest">Game the egg is currently present on</param>
2019-12-27 02:47:31 +00:00
public static void SetEggMetData ( this PKM pk , GameVersion origin , GameVersion dest )
2018-12-30 06:19:44 +00:00
{
bool traded = origin = = dest ;
2019-12-27 02:47:31 +00:00
var today = pk . MetDate = DateTime . Today ;
pk . Egg_Location = EncounterSuggestion . GetSuggestedEncounterEggLocationEgg ( pk , traded ) ;
pk . EggMetDate = today ;
2018-12-30 06:19:44 +00:00
}
2018-05-02 02:24:47 +00:00
/// <summary>
/// Maximizes the <see cref="PKM.CurrentFriendship"/>. If the <see cref="PKM.IsEgg"/>, the hatch counter is set to 1.
/// </summary>
2019-12-27 02:47:31 +00:00
/// <param name="pk">PKM to apply hatch details to</param>
public static void MaximizeFriendship ( this PKM pk )
2018-05-02 02:24:47 +00:00
{
2019-12-27 02:47:31 +00:00
if ( pk . IsEgg )
pk . OT_Friendship = 1 ;
2018-05-02 02:24:47 +00:00
else
2019-12-27 02:47:31 +00:00
pk . CurrentFriendship = byte . MaxValue ;
if ( pk is PB7 pb )
2018-11-21 20:31:05 +00:00
pb . ResetCP ( ) ;
2018-05-02 02:24:47 +00:00
}
/// <summary>
/// Maximizes the <see cref="PKM.CurrentLevel"/>. If the <see cref="PKM.IsEgg"/>, the <see cref="PKM"/> is ignored.
/// </summary>
2019-12-27 02:47:31 +00:00
/// <param name="pk">PKM to apply hatch details to</param>
public static void MaximizeLevel ( this PKM pk )
2018-05-02 02:24:47 +00:00
{
2019-12-27 02:47:31 +00:00
if ( pk . IsEgg )
2018-05-02 02:24:47 +00:00
return ;
2019-12-27 02:47:31 +00:00
pk . CurrentLevel = 100 ;
if ( pk is PB7 pb )
2018-11-21 20:31:05 +00:00
pb . ResetCP ( ) ;
2018-05-02 02:24:47 +00:00
}
2018-06-01 02:49:47 +00:00
/// <summary>
/// Sets the <see cref="PKM.Nickname"/> to its default value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="la">Precomputed optional</param>
2019-09-10 07:21:51 +00:00
public static void SetDefaultNickname ( this PKM pk , LegalityAnalysis la )
2018-06-01 02:49:47 +00:00
{
if ( la . Parsed & & la . EncounterOriginal is EncounterTrade t & & t . HasNickname )
pk . SetNickname ( t . GetNickname ( pk . Language ) ) ;
else
2019-02-12 05:49:05 +00:00
pk . ClearNickname ( ) ;
2018-06-01 02:49:47 +00:00
}
2018-07-14 22:08:14 +00:00
2019-09-10 07:21:51 +00:00
/// <summary>
/// Sets the <see cref="PKM.Nickname"/> to its default value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
public static void SetDefaultNickname ( this PKM pk ) = > pk . SetDefaultNickname ( new LegalityAnalysis ( pk ) ) ;
2018-07-14 22:08:14 +00:00
private static readonly string [ ] PotentialUnicode = { "★☆☆☆" , "★★☆☆" , "★★★☆" , "★★★★" } ;
private static readonly string [ ] PotentialNoUnicode = { "+" , "++" , "+++" , "++++" } ;
/// <summary>
/// Gets the Potential evaluation of the input <see cref="pk"/>.
/// </summary>
/// <param name="pk">Pokémon to analyze.</param>
/// <param name="unicode">Returned value is unicode or not</param>
/// <returns>Potential string</returns>
public static string GetPotentialString ( this PKM pk , bool unicode = true )
{
var arr = unicode ? PotentialUnicode : PotentialNoUnicode ;
return arr [ pk . PotentialRating ] ;
}
2019-04-30 00:36:29 +00:00
// Extensions
/// <summary>
/// Gets the Location Name for the <see cref="PKM"/>
/// </summary>
/// <param name="pk">PKM to fetch data for</param>
/// <param name="eggmet">Location requested is the egg obtained location, not met location.</param>
/// <returns>Location string</returns>
public static string GetLocationString ( this PKM pk , bool eggmet )
{
if ( pk . Format < 2 )
return string . Empty ;
2020-06-17 02:46:22 +00:00
int location = eggmet ? pk . Egg_Location : pk . Met_Location ;
return GameInfo . GetLocationName ( eggmet , location , pk . Format , pk . GenNumber , ( GameVersion ) pk . Version ) ;
2019-04-30 00:36:29 +00:00
}
2018-03-11 02:03:09 +00:00
}
}