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 ;
}
2021-06-06 18:49:41 +00:00
public override string ToString ( ) = > $"{(Species) Species}-{Form} [{Argument}] @ {Level}{(RequiresLevelUp ? " X " : " ")}" ;
2020-01-25 23:42:17 +00:00
/// <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
{
2020-12-25 18:58:33 +00:00
case UseItem or UseItemWormhole :
2021-09-16 12:53:14 +00:00
case CriticalHitsInBattle or HitPointsLostInBattle or Spin :
2020-12-25 18:58:33 +00:00
case TowerOfDarkness or 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 ;
2021-09-16 12:53:14 +00:00
case Trade or TradeHeldItem or TradeShelmetKarrablast :
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-25 18:58:33 +00:00
case LevelUpNatureAmped or LevelUpNatureLowKey when GetAmpLowKeyResult ( pkm . Nature ) ! = pkm . Form & & ! skipChecks :
2019-11-16 19:01:00 +00:00
return false ;
2020-12-22 01:12:39 +00:00
case LevelUpBeauty when pkm is not 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
2020-12-25 18:58:33 +00:00
case LevelUpVersion or LevelUpVersionDay or 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 ;
2020-12-25 18:58:33 +00:00
return origin switch
2019-01-07 00:22:45 +00:00
{
2020-12-25 18:58:33 +00:00
// No met data in RBY; No met data in GS, Crystal met data can be reset
1 or 2 = > true ,
// Pal Park / PokeTransfer updates Met Level
3 or 4 = > pkm . Format > origin | | pkm . Met_Level < lvl ,
// 5=>6 and later transfers keep current level
> = 5 = > lvl > = Level & & ( ! pkm . IsNative | | pkm . Met_Level < lvl ) ,
_ = > false ,
} ;
2018-05-19 19:07:50 +00:00
}
2021-12-05 01:56:56 +00:00
public EvoCriteria GetEvoCriteria ( int species , int form , int lvl ) = > new ( species , form )
2018-05-19 19:07:50 +00:00
{
2021-12-05 01:56:56 +00:00
Level = lvl ,
Method = Method ,
} ;
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
{
2021-01-31 03:58:05 +00:00
var index = n - 1 ;
if ( ( uint ) index > 22 )
2019-11-16 19:01:00 +00:00
return 0 ;
2021-01-31 03:58:05 +00:00
return ( 0 b_0101_1011_1100_1010_0101_0001 > > index ) & 1 ;
2019-11-16 19:01:00 +00:00
}
2018-05-19 19:07:50 +00:00
}
2021-01-31 03:58:05 +00:00
}