2019-01-07 00:22:45 +00:00
using static PKHeX . Core . EvolutionType ;
2018-05-19 19:07:50 +00:00
namespace PKHeX.Core
{
/// <summary>
/// Criteria for evolving to this branch in the <see cref="EvolutionTree"/>
/// </summary>
2018-07-02 02:55:23 +00:00
public sealed class EvolutionMethod
2018-05-19 19:07:50 +00:00
{
2020-01-25 23:42:17 +00:00
/// <summary>
/// Evolution Method
/// </summary>
public readonly int Method ;
2018-05-19 19:07:50 +00:00
2020-01-25 23:42:17 +00:00
/// <summary>
/// Evolve to Species
/// </summary>
public readonly int Species ;
/// <summary>
/// Conditional Argument (different from <see cref="Level"/>)
/// </summary>
public readonly int Argument ;
/// <summary>
/// Conditional Argument (different from <see cref="Argument"/>)
/// </summary>
public readonly int Level ;
/// <summary>
/// Destination Form
/// </summary>
/// <remarks>Is <see cref="AnyForm"/> if the evolved form isn't modified. Special consideration for <see cref="LevelUpFormFemale1"/>, which forces 1.</remarks>
public readonly int Form ;
private const int AnyForm = - 1 ;
2019-12-07 01:36:36 +00:00
2019-01-07 00:22:45 +00:00
// Not stored in binary data
2019-12-06 06:32:47 +00:00
public bool RequiresLevelUp ; // tracks if this method requires a Level Up, lazily set
2018-05-19 19:07:50 +00:00
2020-01-25 23:42:17 +00:00
public EvolutionMethod ( int method , int species , int argument = 0 , int level = 0 , int form = AnyForm )
{
Method = method ;
Species = species ;
Argument = argument ;
Form = form ;
Level = level ;
}
/// <summary>
/// Returns the form that the Pok<6F> mon will have after evolution.
/// </summary>
/// <param name="form">Un-evolved Form ID</param>
2020-01-11 00:02:22 +00:00
public int GetDestinationForm ( int form )
{
if ( Method = = ( int ) LevelUpFormFemale1 )
return 1 ;
if ( Form = = AnyForm )
return form ;
return Form ;
}
2019-12-07 01:36:36 +00:00
2019-01-07 00:22:45 +00:00
/// <summary>
/// Checks the <see cref="EvolutionMethod"/> for validity by comparing against the <see cref="PKM"/> data.
/// </summary>
/// <param name="pkm">Entity to check</param>
/// <param name="lvl">Current level</param>
/// <param name="skipChecks">Option to skip some comparisons to return a 'possible' evolution.</param>
2019-12-06 06:32:47 +00:00
/// <returns>True if a evolution criteria is valid.</returns>
2018-05-19 19:07:50 +00:00
public bool Valid ( PKM pkm , int lvl , bool skipChecks )
{
RequiresLevelUp = false ;
2019-01-07 00:22:45 +00:00
switch ( ( EvolutionType ) Method )
2018-05-19 19:07:50 +00:00
{
2019-01-07 00:22:45 +00:00
case UseItem :
case UseItemWormhole :
2019-11-16 19:52:40 +00:00
case Crit3 :
case HPDownBy49 :
case SpinType :
2020-06-19 23:51:15 +00:00
case TowerOfDarkness :
case TowerOfWaters :
2018-05-19 19:07:50 +00:00
return true ;
2019-01-07 00:22:45 +00:00
case UseItemMale :
2018-05-19 19:07:50 +00:00
return pkm . Gender = = 0 ;
2019-01-07 00:22:45 +00:00
case UseItemFemale :
2018-05-19 19:07:50 +00:00
return pkm . Gender = = 1 ;
2019-01-07 00:22:45 +00:00
case Trade :
case TradeHeldItem :
case TradeSpecies :
2018-05-19 19:07:50 +00:00
return ! pkm . IsUntraded | | skipChecks ;
2020-01-25 23:42:17 +00:00
// Special Level Up Cases -- return false if invalid
2020-12-11 04:42:30 +00:00
case LevelUpNatureAmped when GetAmpLowKeyResult ( pkm . Nature ) ! = pkm . Form & & ! skipChecks :
case LevelUpNatureLowKey when GetAmpLowKeyResult ( pkm . Nature ) ! = pkm . Form & & ! skipChecks :
2019-11-16 19:01:00 +00:00
return false ;
2019-01-07 00:22:45 +00:00
case LevelUpBeauty when ! ( pkm is IContestStats s ) | | s . CNT_Beauty < Argument :
2018-08-28 03:48:57 +00:00
return skipChecks ;
2019-01-07 00:22:45 +00:00
case LevelUpMale when pkm . Gender ! = 0 :
2018-08-28 03:48:57 +00:00
return false ;
2019-01-07 00:22:45 +00:00
case LevelUpFemale when pkm . Gender ! = 1 :
2018-08-28 03:48:57 +00:00
return false ;
2020-12-11 04:42:30 +00:00
case LevelUpFormFemale1 when pkm . Gender ! = 1 | | pkm . Form ! = 1 :
2018-08-28 03:48:57 +00:00
return false ;
2018-05-19 19:07:50 +00:00
2019-01-07 00:22:45 +00:00
case LevelUpVersion when ( ( pkm . Version & 1 ) ! = ( Argument & 1 ) & & pkm . IsUntraded ) | | skipChecks :
case LevelUpVersionDay when ( ( pkm . Version & 1 ) ! = ( Argument & 1 ) & & pkm . IsUntraded ) | | skipChecks :
case LevelUpVersionNight when ( ( pkm . Version & 1 ) ! = ( Argument & 1 ) & & pkm . IsUntraded ) | | skipChecks :
2018-08-28 03:48:57 +00:00
return skipChecks ; // Version checks come in pairs, check for any pair match
2018-05-19 19:07:50 +00:00
2019-02-24 21:57:10 +00:00
// Level Up (any); the above Level Up (with condition) cases will reach here if they were valid
2018-05-19 19:07:50 +00:00
default :
if ( Level = = 0 & & lvl < 2 )
return false ;
if ( lvl < Level )
return false ;
RequiresLevelUp = true ;
if ( skipChecks )
return lvl > = Level ;
// Check Met Level for extra validity
2019-01-07 00:22:45 +00:00
return HasMetLevelIncreased ( pkm , lvl ) ;
}
}
private bool HasMetLevelIncreased ( PKM pkm , int lvl )
{
2020-12-11 04:42:30 +00:00
int origin = pkm . Generation ;
2019-01-07 00:22:45 +00:00
switch ( origin )
{
2019-02-24 21:57:10 +00:00
case 1 : // No met data in RBY
case 2 : // No met data in GS, Crystal met data can be reset
2019-01-07 00:22:45 +00:00
return true ;
case 3 :
case 4 :
if ( pkm . Format > origin ) // Pal Park / PokeTransfer updates Met Level
return true ;
return pkm . Met_Level < lvl ;
case 5 : // Bank keeps current level
case 6 :
case 7 :
2019-11-16 01:34:18 +00:00
case 8 :
2019-01-07 00:22:45 +00:00
return lvl > = Level & & ( ! pkm . IsNative | | pkm . Met_Level < lvl ) ;
default : return false ;
2018-05-19 19:07:50 +00:00
}
}
2019-12-06 06:32:47 +00:00
public EvoCriteria GetEvoCriteria ( int species , int form , int lvl )
2018-05-19 19:07:50 +00:00
{
2019-12-06 07:04:24 +00:00
return new EvoCriteria ( species , form )
2018-05-19 19:07:50 +00:00
{
Level = lvl ,
2019-12-06 06:32:47 +00:00
Method = Method ,
2018-05-19 19:07:50 +00:00
} ;
}
2019-11-16 19:01:00 +00:00
2019-11-18 06:04:41 +00:00
public static int GetAmpLowKeyResult ( int n )
2019-11-16 19:01:00 +00:00
{
if ( ( uint ) ( n - 1 ) > 22 )
return 0 ;
return ( 0x5BCA51 > > ( n - 1 ) ) & 1 ;
}
2018-05-19 19:07:50 +00:00
}
}