2017-01-04 04:51:33 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2016-02-23 06:52:48 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
2017-01-08 07:54:09 +00:00
|
|
|
|
namespace PKHeX.Core
|
2016-02-23 06:52:48 +00:00
|
|
|
|
{
|
|
|
|
|
public static partial class Legal
|
|
|
|
|
{
|
2017-06-19 05:27:40 +00:00
|
|
|
|
/// <summary> e-Reader Berry is Enigma or special berry </summary>
|
|
|
|
|
public static bool EReaderBerryIsEnigma { get; set; } = true;
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
/// <summary> e-Reader Berry Name </summary>
|
|
|
|
|
public static string EReaderBerryName { get; set; } = string.Empty;
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
/// <summary> e-Reader Berry Name formatted in Title Case </summary>
|
2018-10-05 01:52:00 +00:00
|
|
|
|
public static string EReaderBerryDisplayName => string.Format(LegalityCheckStrings.L_XEnigmaBerry_0, Util.ToTitleCase(EReaderBerryName.ToLower()));
|
2017-06-19 05:27:40 +00:00
|
|
|
|
|
2017-02-11 23:20:44 +00:00
|
|
|
|
// Gen 1
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
internal static readonly Learnset[] LevelUpRB = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_rb.pkl"), MaxSpeciesID_1);
|
|
|
|
|
internal static readonly Learnset[] LevelUpY = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_y.pkl"), MaxSpeciesID_1);
|
2017-02-11 23:20:44 +00:00
|
|
|
|
|
2017-02-25 20:37:01 +00:00
|
|
|
|
// Gen 2
|
2018-03-30 08:02:22 +00:00
|
|
|
|
internal static readonly EggMoves[] EggMovesGS = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_gs.pkl"), MaxSpeciesID_2);
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
internal static readonly Learnset[] LevelUpGS = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_gs.pkl"), MaxSpeciesID_2);
|
2018-03-30 08:02:22 +00:00
|
|
|
|
internal static readonly EggMoves[] EggMovesC = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_c.pkl"), MaxSpeciesID_2);
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
internal static readonly Learnset[] LevelUpC = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_c.pkl"), MaxSpeciesID_2);
|
2017-02-25 20:37:01 +00:00
|
|
|
|
|
2017-03-18 23:50:34 +00:00
|
|
|
|
// Gen 3
|
2020-03-20 22:18:59 +00:00
|
|
|
|
internal static readonly Learnset[] LevelUpE = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_e.pkl"), "em"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpRS = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_rs.pkl"), "rs"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpFR = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_fr.pkl"), "fr"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpLG = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_lg.pkl"), "lg"));
|
|
|
|
|
internal static readonly EggMoves6[] EggMovesRS = EggMoves6.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_rs.pkl"), "rs"));
|
2017-03-18 23:50:34 +00:00
|
|
|
|
|
|
|
|
|
// Gen 4
|
2020-03-20 22:18:59 +00:00
|
|
|
|
internal static readonly Learnset[] LevelUpDP = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_dp.pkl"), "dp"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpPt = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_pt.pkl"), "pt"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpHGSS = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_hgss.pkl"), "hs"));
|
|
|
|
|
internal static readonly EggMoves6[] EggMovesDPPt = EggMoves6.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_dppt.pkl"), "dp"));
|
|
|
|
|
internal static readonly EggMoves6[] EggMovesHGSS = EggMoves6.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_hgss.pkl"), "hs"));
|
2017-03-18 23:50:34 +00:00
|
|
|
|
|
|
|
|
|
// Gen 5
|
2020-03-20 22:18:59 +00:00
|
|
|
|
internal static readonly Learnset[] LevelUpBW = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_bw.pkl"), "51"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpB2W2 = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_b2w2.pkl"), "52"));
|
|
|
|
|
internal static readonly EggMoves6[] EggMovesBW = EggMoves6.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_bw.pkl"), "bw"));
|
2017-03-18 23:50:34 +00:00
|
|
|
|
|
2016-10-24 05:03:19 +00:00
|
|
|
|
// Gen 6
|
2020-03-20 22:18:59 +00:00
|
|
|
|
internal static readonly EggMoves6[] EggMovesXY = EggMoves6.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_xy.pkl"), "xy"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpXY = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_xy.pkl"), "xy"));
|
|
|
|
|
internal static readonly EggMoves6[] EggMovesAO = EggMoves6.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_ao.pkl"), "ao"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpAO = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_ao.pkl"), "ao"));
|
2016-10-24 05:03:19 +00:00
|
|
|
|
|
|
|
|
|
// Gen 7
|
2020-03-20 22:18:59 +00:00
|
|
|
|
internal static readonly EggMoves7[] EggMovesSM = EggMoves7.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_sm.pkl"), "sm"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpSM = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_sm.pkl"), "sm"));
|
|
|
|
|
internal static readonly EggMoves7[] EggMovesUSUM = EggMoves7.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_uu.pkl"), "uu"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpUSUM = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_uu.pkl"), "uu"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpGG = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_gg.pkl"), "gg"));
|
2016-10-24 05:03:19 +00:00
|
|
|
|
|
2019-09-23 23:56:47 +00:00
|
|
|
|
// Gen 8
|
2020-03-20 22:18:59 +00:00
|
|
|
|
internal static readonly EggMoves7[] EggMovesSWSH = EggMoves7.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_swsh.pkl"), "ss"));
|
|
|
|
|
internal static readonly Learnset[] LevelUpSWSH = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_swsh.pkl"), "ss"));
|
2019-09-23 23:56:47 +00:00
|
|
|
|
|
2020-01-12 20:06:33 +00:00
|
|
|
|
internal static IReadOnlyList<int>[] GetValidMovesAllGens(PKM pkm, IReadOnlyList<EvoCriteria>[] evoChains, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true)
|
2017-03-25 12:27:42 +00:00
|
|
|
|
{
|
2020-01-12 20:06:33 +00:00
|
|
|
|
var Moves = new IReadOnlyList<int>[evoChains.Length];
|
2017-03-25 12:27:42 +00:00
|
|
|
|
for (int i = 1; i < evoChains.Length; i++)
|
2018-07-04 16:15:20 +00:00
|
|
|
|
{
|
2018-06-23 00:59:02 +00:00
|
|
|
|
if (evoChains[i].Count != 0)
|
2017-06-18 01:37:19 +00:00
|
|
|
|
Moves[i] = GetValidMoves(pkm, evoChains[i], i, minLvLG1, minLvLG2, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM).ToList();
|
2017-03-26 05:23:54 +00:00
|
|
|
|
else
|
2020-01-12 20:06:33 +00:00
|
|
|
|
Moves[i] = Array.Empty<int>();
|
2018-07-04 16:15:20 +00:00
|
|
|
|
}
|
2017-03-25 12:27:42 +00:00
|
|
|
|
return Moves;
|
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-06-19 02:10:21 +00:00
|
|
|
|
internal static IEnumerable<int> GetValidMoves(PKM pkm, IReadOnlyList<EvoCriteria>[] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true)
|
2016-10-24 05:03:19 +00:00
|
|
|
|
{
|
2016-11-09 06:10:32 +00:00
|
|
|
|
GameVersion version = (GameVersion)pkm.Version;
|
2016-10-24 05:03:19 +00:00
|
|
|
|
if (!pkm.IsUntraded)
|
2016-11-09 06:10:32 +00:00
|
|
|
|
version = GameVersion.Any;
|
2018-06-09 23:04:06 +00:00
|
|
|
|
return GetValidMoves(pkm, version, evoChains, minLvLG1: 1, minLvLG2: 1, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM);
|
2017-02-15 22:33:59 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-06-19 02:10:21 +00:00
|
|
|
|
internal static IEnumerable<int> GetValidMoves(PKM pkm, IReadOnlyList<EvoCriteria> evoChain, int generation, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true)
|
2017-02-15 22:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
GameVersion version = (GameVersion)pkm.Version;
|
|
|
|
|
if (!pkm.IsUntraded)
|
|
|
|
|
version = GameVersion.Any;
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return GetValidMoves(pkm, version, evoChain, generation, minLvLG1: minLvLG1, minLvLG2: minLvLG2, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM);
|
2016-10-24 05:03:19 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-11-19 06:20:55 +00:00
|
|
|
|
internal static IEnumerable<int> GetValidRelearn(PKM pkm, int species, int form, GameVersion version = GameVersion.Any)
|
2019-05-11 17:12:14 +00:00
|
|
|
|
{
|
2019-11-19 06:20:55 +00:00
|
|
|
|
return GetValidRelearn(pkm, species, form, GetCanInheritMoves(species), version);
|
2019-05-11 17:12:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-19 06:20:55 +00:00
|
|
|
|
internal static IEnumerable<int> GetValidRelearn(PKM pkm, int species, int form, bool inheritlvlmoves, GameVersion version = GameVersion.Any)
|
2016-02-23 06:52:48 +00:00
|
|
|
|
{
|
2019-05-11 07:59:07 +00:00
|
|
|
|
if (pkm.GenNumber < 6)
|
2020-01-12 20:06:33 +00:00
|
|
|
|
return Array.Empty<int>();
|
2017-02-12 17:52:26 +00:00
|
|
|
|
|
2020-01-12 20:06:33 +00:00
|
|
|
|
var r = new List<int>();
|
2019-11-19 06:20:55 +00:00
|
|
|
|
r.AddRange(MoveEgg.GetRelearnLVLMoves(pkm, species, 1, form, version));
|
2016-11-12 06:13:40 +00:00
|
|
|
|
|
|
|
|
|
if (pkm.Format == 6 && pkm.Species != 678)
|
|
|
|
|
form = 0;
|
|
|
|
|
|
2018-06-19 04:56:30 +00:00
|
|
|
|
r.AddRange(MoveEgg.GetEggMoves(pkm, species, form, version));
|
2017-06-07 03:10:05 +00:00
|
|
|
|
if (inheritlvlmoves)
|
2019-11-19 06:20:55 +00:00
|
|
|
|
r.AddRange(MoveEgg.GetRelearnLVLMoves(pkm, species, 100, form, version));
|
2016-03-12 17:16:41 +00:00
|
|
|
|
return r.Distinct();
|
2016-02-23 06:52:48 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2020-01-12 22:34:29 +00:00
|
|
|
|
internal static int[] GetShedinjaEvolveMoves(PKM pkm, int generation, int lvl)
|
Shedinja evolution moves and some egg fixes (#1015)
* Add getMoves function with min level and max level, usefull for shedjina evolves moves (min level 20) and generation 1 moves ( no move reminder, min level is min encounter level + 1)
Also for gen1 encounters another function should be created to get by the encounter level the four moves that the pokemon learn by default, the last four in its movepool up until the encounter level
* getShedinjaEvolveMoves, function that return the moves that shedinja could learn from Ninjask move pool at the moment when Nincada evolves, in the same format that getValidMovesAllGens
* Add validation in parse moves for shedinja evolve moves.
Shedinja could have any gen3/4 moves from Ninjas learnset but only one is allowed
* Shedinja evolve moves text resources
* Fix egg moves pre-gen 6 validation:
Add skipoption variable to getEggMoves function from pre-gen6 games, to verify egg moves from split breed species
Flag illegal combinations of base egg moves and special egg moves
Return crystal egg moves for gen2 pokemon that can be tradeback to gen 1 games
* Fix for mix between event egg moves and base egg moves
* Changes just to make if there is only shedinja evolve move that is also the only base egg move change it from base egg move to evolve move, to avoid flag illegal if also the pokemon have a special egg move
* Revert "Changes just to make if there is only shedinja evolve move that is also the only base egg move change it from base egg move to evolve move, to avoid flag illegal if also the pokemon have a special egg move"
Revert the last change, i search in bulbapedia an there wasn't any nincada distributed with special moves in generation 3 nor 4, making this complicated validation unnecessary
This reverts commit 57f5ac1bbb75e32e417b575619339cae5e5d1ef2.
* Fix error
2017-04-01 00:40:30 +00:00
|
|
|
|
{
|
2020-01-12 22:34:29 +00:00
|
|
|
|
if (pkm.Species != (int)Species.Shedinja || lvl < 20)
|
2018-09-02 02:55:08 +00:00
|
|
|
|
return Array.Empty<int>();
|
2017-04-01 01:35:43 +00:00
|
|
|
|
|
2020-01-12 22:34:29 +00:00
|
|
|
|
// If Nincada evolves into Ninjask and learns a move after evolution from Ninjask's LevelUp data, Shedinja would appear with that move.
|
|
|
|
|
// Only one move above level 20 is allowed; check the count of Ninjask moves elsewhere.
|
|
|
|
|
return generation switch
|
Shedinja evolution moves and some egg fixes (#1015)
* Add getMoves function with min level and max level, usefull for shedjina evolves moves (min level 20) and generation 1 moves ( no move reminder, min level is min encounter level + 1)
Also for gen1 encounters another function should be created to get by the encounter level the four moves that the pokemon learn by default, the last four in its movepool up until the encounter level
* getShedinjaEvolveMoves, function that return the moves that shedinja could learn from Ninjask move pool at the moment when Nincada evolves, in the same format that getValidMovesAllGens
* Add validation in parse moves for shedinja evolve moves.
Shedinja could have any gen3/4 moves from Ninjas learnset but only one is allowed
* Shedinja evolve moves text resources
* Fix egg moves pre-gen 6 validation:
Add skipoption variable to getEggMoves function from pre-gen6 games, to verify egg moves from split breed species
Flag illegal combinations of base egg moves and special egg moves
Return crystal egg moves for gen2 pokemon that can be tradeback to gen 1 games
* Fix for mix between event egg moves and base egg moves
* Changes just to make if there is only shedinja evolve move that is also the only base egg move change it from base egg move to evolve move, to avoid flag illegal if also the pokemon have a special egg move
* Revert "Changes just to make if there is only shedinja evolve move that is also the only base egg move change it from base egg move to evolve move, to avoid flag illegal if also the pokemon have a special egg move"
Revert the last change, i search in bulbapedia an there wasn't any nincada distributed with special moves in generation 3 nor 4, making this complicated validation unnecessary
This reverts commit 57f5ac1bbb75e32e417b575619339cae5e5d1ef2.
* Fix error
2017-04-01 00:40:30 +00:00
|
|
|
|
{
|
2020-01-12 22:34:29 +00:00
|
|
|
|
3 when pkm.InhabitedGeneration(3) => LevelUpE[(int)Species.Ninjask].GetMoves(lvl, 20), // Same LevelUp data in all Gen3 games
|
|
|
|
|
4 when pkm.InhabitedGeneration(4) => LevelUpPt[(int)Species.Ninjask].GetMoves(lvl, 20), // Same LevelUp data in all Gen4 games
|
|
|
|
|
_ => Array.Empty<int>(),
|
|
|
|
|
};
|
2018-02-02 03:57:02 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-02-02 03:57:02 +00:00
|
|
|
|
internal static int GetShedinjaMoveLevel(int species, int move, int generation)
|
|
|
|
|
{
|
|
|
|
|
var src = generation == 4 ? LevelUpPt : LevelUpE;
|
|
|
|
|
var moves = src[species];
|
|
|
|
|
return moves.GetLevelLearnMove(move);
|
Shedinja evolution moves and some egg fixes (#1015)
* Add getMoves function with min level and max level, usefull for shedjina evolves moves (min level 20) and generation 1 moves ( no move reminder, min level is min encounter level + 1)
Also for gen1 encounters another function should be created to get by the encounter level the four moves that the pokemon learn by default, the last four in its movepool up until the encounter level
* getShedinjaEvolveMoves, function that return the moves that shedinja could learn from Ninjask move pool at the moment when Nincada evolves, in the same format that getValidMovesAllGens
* Add validation in parse moves for shedinja evolve moves.
Shedinja could have any gen3/4 moves from Ninjas learnset but only one is allowed
* Shedinja evolve moves text resources
* Fix egg moves pre-gen 6 validation:
Add skipoption variable to getEggMoves function from pre-gen6 games, to verify egg moves from split breed species
Flag illegal combinations of base egg moves and special egg moves
Return crystal egg moves for gen2 pokemon that can be tradeback to gen 1 games
* Fix for mix between event egg moves and base egg moves
* Changes just to make if there is only shedinja evolve move that is also the only base egg move change it from base egg move to evolve move, to avoid flag illegal if also the pokemon have a special egg move
* Revert "Changes just to make if there is only shedinja evolve move that is also the only base egg move change it from base egg move to evolve move, to avoid flag illegal if also the pokemon have a special egg move"
Revert the last change, i search in bulbapedia an there wasn't any nincada distributed with special moves in generation 3 nor 4, making this complicated validation unnecessary
This reverts commit 57f5ac1bbb75e32e417b575619339cae5e5d1ef2.
* Fix error
2017-04-01 00:40:30 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-11-19 06:20:55 +00:00
|
|
|
|
internal static int[] GetBaseEggMoves(PKM pkm, int species, int form, GameVersion gameSource, int lvl)
|
2016-03-06 19:19:09 +00:00
|
|
|
|
{
|
2016-10-24 05:03:19 +00:00
|
|
|
|
if (gameSource == GameVersion.Any)
|
2018-07-04 16:15:20 +00:00
|
|
|
|
gameSource = (GameVersion)pkm.Version;
|
2016-03-22 02:53:02 +00:00
|
|
|
|
|
2016-10-24 05:03:19 +00:00
|
|
|
|
switch (gameSource)
|
2016-03-22 02:53:02 +00:00
|
|
|
|
{
|
2018-06-11 14:23:48 +00:00
|
|
|
|
case GameVersion.GSC:
|
2017-03-26 02:57:38 +00:00
|
|
|
|
case GameVersion.GS:
|
2017-09-01 05:37:28 +00:00
|
|
|
|
// If checking back-transfer specimen (GSC->RBY), remove moves that must be deleted prior to transfer
|
|
|
|
|
int[] getRBYCompatibleMoves(int[] moves) => pkm.Format == 1 ? moves.Where(m => m <= MaxMoveID_1).ToArray() : moves;
|
2017-03-26 02:57:38 +00:00
|
|
|
|
if (pkm.InhabitedGeneration(2))
|
2017-09-01 05:37:28 +00:00
|
|
|
|
return getRBYCompatibleMoves(LevelUpGS[species].GetMoves(lvl));
|
2017-03-26 02:57:38 +00:00
|
|
|
|
break;
|
|
|
|
|
case GameVersion.C:
|
|
|
|
|
if (pkm.InhabitedGeneration(2))
|
2017-09-01 05:37:28 +00:00
|
|
|
|
return getRBYCompatibleMoves(LevelUpC[species].GetMoves(lvl));
|
2017-03-26 02:57:38 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2017-03-18 23:50:34 +00:00
|
|
|
|
case GameVersion.R:
|
|
|
|
|
case GameVersion.S:
|
|
|
|
|
case GameVersion.RS:
|
|
|
|
|
if (pkm.InhabitedGeneration(3))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpRS[species].GetMoves(lvl);
|
2017-03-18 23:50:34 +00:00
|
|
|
|
break;
|
|
|
|
|
case GameVersion.E:
|
|
|
|
|
if (pkm.InhabitedGeneration(3))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpE[species].GetMoves(lvl);
|
2017-03-18 23:50:34 +00:00
|
|
|
|
break;
|
|
|
|
|
case GameVersion.FR:
|
|
|
|
|
case GameVersion.LG:
|
|
|
|
|
case GameVersion.FRLG:
|
|
|
|
|
// only difference in FR/LG is deoxys which doesn't breed.
|
|
|
|
|
if (pkm.InhabitedGeneration(3))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpFR[species].GetMoves(lvl);
|
2017-03-18 23:50:34 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GameVersion.D:
|
|
|
|
|
case GameVersion.P:
|
|
|
|
|
case GameVersion.DP:
|
|
|
|
|
if (pkm.InhabitedGeneration(4))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpDP[species].GetMoves(lvl);
|
2017-03-18 23:50:34 +00:00
|
|
|
|
break;
|
|
|
|
|
case GameVersion.Pt:
|
|
|
|
|
if (pkm.InhabitedGeneration(4))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpPt[species].GetMoves(lvl);
|
2017-03-18 23:50:34 +00:00
|
|
|
|
break;
|
|
|
|
|
case GameVersion.HG:
|
|
|
|
|
case GameVersion.SS:
|
|
|
|
|
case GameVersion.HGSS:
|
|
|
|
|
if (pkm.InhabitedGeneration(4))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpHGSS[species].GetMoves(lvl);
|
2017-03-25 02:24:01 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GameVersion.B:
|
|
|
|
|
case GameVersion.W:
|
|
|
|
|
case GameVersion.BW:
|
|
|
|
|
if (pkm.InhabitedGeneration(5))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpBW[species].GetMoves(lvl);
|
2017-03-25 02:24:01 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GameVersion.B2:
|
|
|
|
|
case GameVersion.W2:
|
|
|
|
|
case GameVersion.B2W2:
|
|
|
|
|
if (pkm.InhabitedGeneration(5))
|
2018-06-11 00:55:03 +00:00
|
|
|
|
return LevelUpB2W2[species].GetMoves(lvl);
|
2017-03-18 23:50:34 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2016-10-24 05:03:19 +00:00
|
|
|
|
case GameVersion.X:
|
|
|
|
|
case GameVersion.Y:
|
|
|
|
|
case GameVersion.XY:
|
|
|
|
|
if (pkm.InhabitedGeneration(6))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpXY[species].GetMoves(lvl);
|
2016-10-24 05:03:19 +00:00
|
|
|
|
break;
|
2016-03-05 04:43:00 +00:00
|
|
|
|
|
2016-10-24 05:03:19 +00:00
|
|
|
|
case GameVersion.AS:
|
|
|
|
|
case GameVersion.OR:
|
|
|
|
|
case GameVersion.ORAS:
|
|
|
|
|
if (pkm.InhabitedGeneration(6))
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpAO[species].GetMoves(lvl);
|
2016-10-24 05:03:19 +00:00
|
|
|
|
break;
|
2016-03-22 02:53:02 +00:00
|
|
|
|
|
2016-10-24 05:03:19 +00:00
|
|
|
|
case GameVersion.SN:
|
|
|
|
|
case GameVersion.MN:
|
|
|
|
|
case GameVersion.SM:
|
2017-11-19 05:50:48 +00:00
|
|
|
|
if (species > MaxSpeciesID_7)
|
|
|
|
|
break;
|
2016-10-24 05:03:19 +00:00
|
|
|
|
if (pkm.InhabitedGeneration(7))
|
2017-09-01 05:37:28 +00:00
|
|
|
|
{
|
2019-11-19 06:20:55 +00:00
|
|
|
|
int index = PersonalTable.SM.GetFormeIndex(species, form);
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return LevelUpSM[index].GetMoves(lvl);
|
2017-09-01 05:37:28 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GameVersion.US:
|
|
|
|
|
case GameVersion.UM:
|
|
|
|
|
case GameVersion.USUM:
|
|
|
|
|
if (pkm.InhabitedGeneration(7))
|
|
|
|
|
{
|
2019-11-19 06:20:55 +00:00
|
|
|
|
int index = PersonalTable.USUM.GetFormeIndex(species, form);
|
2017-09-01 05:37:28 +00:00
|
|
|
|
return LevelUpUSUM[index].GetMoves(lvl);
|
|
|
|
|
}
|
2016-10-24 05:03:19 +00:00
|
|
|
|
break;
|
2019-09-23 23:56:47 +00:00
|
|
|
|
|
|
|
|
|
case GameVersion.SW:
|
|
|
|
|
case GameVersion.SH:
|
|
|
|
|
case GameVersion.SWSH:
|
|
|
|
|
if (pkm.InhabitedGeneration(8))
|
|
|
|
|
{
|
2019-11-19 06:20:55 +00:00
|
|
|
|
int index = PersonalTable.SWSH.GetFormeIndex(species, form);
|
2019-09-23 23:56:47 +00:00
|
|
|
|
return LevelUpSWSH[index].GetMoves(lvl);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2016-03-22 02:53:02 +00:00
|
|
|
|
}
|
2018-08-02 01:30:51 +00:00
|
|
|
|
return Array.Empty<int>();
|
2016-03-05 04:43:00 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-04-17 05:14:21 +00:00
|
|
|
|
internal static List<int> GetValidPostEvolutionMoves(PKM pkm, int species, IReadOnlyList<EvoCriteria>[] evoChains, GameVersion Version)
|
2017-04-23 12:54:52 +00:00
|
|
|
|
{
|
2018-05-12 15:13:39 +00:00
|
|
|
|
// Return moves that the pokemon could learn after evolving
|
2017-04-23 12:54:52 +00:00
|
|
|
|
var moves = new List<int>();
|
|
|
|
|
for (int i = 1; i < evoChains.Length; i++)
|
2018-07-27 02:34:27 +00:00
|
|
|
|
{
|
2018-06-23 00:59:02 +00:00
|
|
|
|
if (evoChains[i].Count != 0)
|
2019-04-17 05:14:21 +00:00
|
|
|
|
moves.AddRange(GetValidPostEvolutionMoves(pkm, species, evoChains[i], i, Version));
|
2018-07-27 02:34:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-23 12:54:52 +00:00
|
|
|
|
if (pkm.GenNumber >= 6)
|
|
|
|
|
moves.AddRange(pkm.RelearnMoves.Where(m => m != 0));
|
|
|
|
|
return moves.Distinct().ToList();
|
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-05-11 07:59:07 +00:00
|
|
|
|
private static List<int> GetValidPostEvolutionMoves(PKM pkm, int species, IReadOnlyList<EvoCriteria> evoChain, int generation, GameVersion Version)
|
2017-04-23 12:54:52 +00:00
|
|
|
|
{
|
|
|
|
|
var evomoves = new List<int>();
|
2019-04-17 05:14:21 +00:00
|
|
|
|
var index = EvolutionChain.GetEvoChainSpeciesIndex(evoChain, species);
|
2017-04-23 14:48:23 +00:00
|
|
|
|
for (int i = 0; i <= index; i++)
|
2017-04-23 12:54:52 +00:00
|
|
|
|
{
|
|
|
|
|
var evo = evoChain[i];
|
2019-11-24 06:48:02 +00:00
|
|
|
|
var moves = GetMoves(pkm, evo.Species, 1, 1, evo.Level, evo.Form, moveTutor: true, Version: Version, LVL: true, specialTutors: true, Machine: true, MoveReminder: true, RemoveTransferHM: false, generation: generation);
|
2017-04-23 14:48:23 +00:00
|
|
|
|
// Moves from Species or any species after in the evolution phase
|
|
|
|
|
evomoves.AddRange(moves);
|
2017-04-23 12:54:52 +00:00
|
|
|
|
}
|
|
|
|
|
return evomoves;
|
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-05-11 07:59:07 +00:00
|
|
|
|
internal static IEnumerable<int> GetExclusivePreEvolutionMoves(PKM pkm, int Species, IReadOnlyList<EvoCriteria> evoChain, int generation, GameVersion Version)
|
Split Breed Egg Moves improvements (#1058)
* Added method getBaseEggSpecies to get the base species when the pokemon was an egg, is needed because for format 1 pokemon with egg origin every time getBaseSpecies is called is returning the gen 1 base species obtaining invalid eggmoves and base egg moves
Also getBaseEggSpecies was using Evolves1 when format = 1 even when asking for a gen2 egg base species, returning Pikachu egg moves (empty list) instead of Pichu egg moves
* Fix ability checking for generation 3 pokemon, likea de Seadra from Issue #1011
pkm.AbilityNumber have a value assuming PID match ability like a generation 4 pokemon but the validation should be ignored if is a generation 3 pokemon with only one ability in generation 3
Also changed the validation for ingame trades with fixed abilities to check only with generation 3 abilities in the case the species has two abilities generation 3, if only one was possible any PID should be valid with the generation 3 ability
Encounter Trades
Also the check for evolution was wrong, the most evolved species is the first in the evochain, not the last
* Fix evoltuion chains for gen 3 pokemon in format 4
* Fix ability for generation 3 trades. Ability could not change if there were 2 abilities in generation 3, that means it is irrelevant if the pokemon evolved in gen 4-5, the ability number must match the encounter
* Added missing skipOption to a call to getBaseEggSpecies
* Functions to obtain moves excluvie to preevolutions, like moves that Azurill/Happiny could learn throught level up or TM but Marill/Chansey could not learn, icompatible with any Marill/Chansey egg moves
Also add functions to return egg moves and base egg moves for both possible species for split breed eggs
* Check both species from split breed egg at the same time to report moves incompatibilities
* Reduced generation 4-5 was egg game check
There is no need to check every possible generation game.
For every egg species HGSS learnset tables y egg moves table contains all the moves from the same species in DP and Pt, without any move exclusive to that games except in legendaries, and they cant breed
In generation 5 is the same with B2W2 except for Exxegutte, it have a exclusive level up move from B1W1, Psychic, but it can learn the move with TM, it wont count as an egg move
* Check incompatible split breed moves in verify relearn egg
* Fix generation 1 incompatibility moves check
SolarBeam removed from Exeggcute/Exeggutor incompatiblity, Exeggutor could learn it with a TM in generation 1
Removed Vaporeon Mist and Eevee Take Down incompatiblity, Vaporeon could learn Take Down with a TM in generation 1
2017-04-14 17:11:50 +00:00
|
|
|
|
{
|
|
|
|
|
var preevomoves = new List<int>();
|
|
|
|
|
var evomoves = new List<int>();
|
2018-06-23 00:59:02 +00:00
|
|
|
|
var index = EvolutionChain.GetEvoChainSpeciesIndex(evoChain, Species);
|
|
|
|
|
for (int i = 0; i < evoChain.Count; i++)
|
Split Breed Egg Moves improvements (#1058)
* Added method getBaseEggSpecies to get the base species when the pokemon was an egg, is needed because for format 1 pokemon with egg origin every time getBaseSpecies is called is returning the gen 1 base species obtaining invalid eggmoves and base egg moves
Also getBaseEggSpecies was using Evolves1 when format = 1 even when asking for a gen2 egg base species, returning Pikachu egg moves (empty list) instead of Pichu egg moves
* Fix ability checking for generation 3 pokemon, likea de Seadra from Issue #1011
pkm.AbilityNumber have a value assuming PID match ability like a generation 4 pokemon but the validation should be ignored if is a generation 3 pokemon with only one ability in generation 3
Also changed the validation for ingame trades with fixed abilities to check only with generation 3 abilities in the case the species has two abilities generation 3, if only one was possible any PID should be valid with the generation 3 ability
Encounter Trades
Also the check for evolution was wrong, the most evolved species is the first in the evochain, not the last
* Fix evoltuion chains for gen 3 pokemon in format 4
* Fix ability for generation 3 trades. Ability could not change if there were 2 abilities in generation 3, that means it is irrelevant if the pokemon evolved in gen 4-5, the ability number must match the encounter
* Added missing skipOption to a call to getBaseEggSpecies
* Functions to obtain moves excluvie to preevolutions, like moves that Azurill/Happiny could learn throught level up or TM but Marill/Chansey could not learn, icompatible with any Marill/Chansey egg moves
Also add functions to return egg moves and base egg moves for both possible species for split breed eggs
* Check both species from split breed egg at the same time to report moves incompatibilities
* Reduced generation 4-5 was egg game check
There is no need to check every possible generation game.
For every egg species HGSS learnset tables y egg moves table contains all the moves from the same species in DP and Pt, without any move exclusive to that games except in legendaries, and they cant breed
In generation 5 is the same with B2W2 except for Exxegutte, it have a exclusive level up move from B1W1, Psychic, but it can learn the move with TM, it wont count as an egg move
* Check incompatible split breed moves in verify relearn egg
* Fix generation 1 incompatibility moves check
SolarBeam removed from Exeggcute/Exeggutor incompatiblity, Exeggutor could learn it with a TM in generation 1
Removed Vaporeon Mist and Eevee Take Down incompatiblity, Vaporeon could learn Take Down with a TM in generation 1
2017-04-14 17:11:50 +00:00
|
|
|
|
{
|
|
|
|
|
var evo = evoChain[i];
|
2019-11-24 06:48:02 +00:00
|
|
|
|
var moves = GetMoves(pkm, evo.Species, 1, 1, evo.Level, evo.Form, moveTutor: true, Version: Version, LVL: true, specialTutors: true, Machine: true, MoveReminder: true, RemoveTransferHM: false, generation: generation);
|
2017-09-02 06:45:47 +00:00
|
|
|
|
var list = i >= index ? preevomoves : evomoves;
|
|
|
|
|
list.AddRange(moves);
|
Split Breed Egg Moves improvements (#1058)
* Added method getBaseEggSpecies to get the base species when the pokemon was an egg, is needed because for format 1 pokemon with egg origin every time getBaseSpecies is called is returning the gen 1 base species obtaining invalid eggmoves and base egg moves
Also getBaseEggSpecies was using Evolves1 when format = 1 even when asking for a gen2 egg base species, returning Pikachu egg moves (empty list) instead of Pichu egg moves
* Fix ability checking for generation 3 pokemon, likea de Seadra from Issue #1011
pkm.AbilityNumber have a value assuming PID match ability like a generation 4 pokemon but the validation should be ignored if is a generation 3 pokemon with only one ability in generation 3
Also changed the validation for ingame trades with fixed abilities to check only with generation 3 abilities in the case the species has two abilities generation 3, if only one was possible any PID should be valid with the generation 3 ability
Encounter Trades
Also the check for evolution was wrong, the most evolved species is the first in the evochain, not the last
* Fix evoltuion chains for gen 3 pokemon in format 4
* Fix ability for generation 3 trades. Ability could not change if there were 2 abilities in generation 3, that means it is irrelevant if the pokemon evolved in gen 4-5, the ability number must match the encounter
* Added missing skipOption to a call to getBaseEggSpecies
* Functions to obtain moves excluvie to preevolutions, like moves that Azurill/Happiny could learn throught level up or TM but Marill/Chansey could not learn, icompatible with any Marill/Chansey egg moves
Also add functions to return egg moves and base egg moves for both possible species for split breed eggs
* Check both species from split breed egg at the same time to report moves incompatibilities
* Reduced generation 4-5 was egg game check
There is no need to check every possible generation game.
For every egg species HGSS learnset tables y egg moves table contains all the moves from the same species in DP and Pt, without any move exclusive to that games except in legendaries, and they cant breed
In generation 5 is the same with B2W2 except for Exxegutte, it have a exclusive level up move from B1W1, Psychic, but it can learn the move with TM, it wont count as an egg move
* Check incompatible split breed moves in verify relearn egg
* Fix generation 1 incompatibility moves check
SolarBeam removed from Exeggcute/Exeggutor incompatiblity, Exeggutor could learn it with a TM in generation 1
Removed Vaporeon Mist and Eevee Take Down incompatiblity, Vaporeon could learn Take Down with a TM in generation 1
2017-04-14 17:11:50 +00:00
|
|
|
|
}
|
2018-06-10 17:44:05 +00:00
|
|
|
|
return preevomoves.Except(evomoves).Distinct();
|
Split Breed Egg Moves improvements (#1058)
* Added method getBaseEggSpecies to get the base species when the pokemon was an egg, is needed because for format 1 pokemon with egg origin every time getBaseSpecies is called is returning the gen 1 base species obtaining invalid eggmoves and base egg moves
Also getBaseEggSpecies was using Evolves1 when format = 1 even when asking for a gen2 egg base species, returning Pikachu egg moves (empty list) instead of Pichu egg moves
* Fix ability checking for generation 3 pokemon, likea de Seadra from Issue #1011
pkm.AbilityNumber have a value assuming PID match ability like a generation 4 pokemon but the validation should be ignored if is a generation 3 pokemon with only one ability in generation 3
Also changed the validation for ingame trades with fixed abilities to check only with generation 3 abilities in the case the species has two abilities generation 3, if only one was possible any PID should be valid with the generation 3 ability
Encounter Trades
Also the check for evolution was wrong, the most evolved species is the first in the evochain, not the last
* Fix evoltuion chains for gen 3 pokemon in format 4
* Fix ability for generation 3 trades. Ability could not change if there were 2 abilities in generation 3, that means it is irrelevant if the pokemon evolved in gen 4-5, the ability number must match the encounter
* Added missing skipOption to a call to getBaseEggSpecies
* Functions to obtain moves excluvie to preevolutions, like moves that Azurill/Happiny could learn throught level up or TM but Marill/Chansey could not learn, icompatible with any Marill/Chansey egg moves
Also add functions to return egg moves and base egg moves for both possible species for split breed eggs
* Check both species from split breed egg at the same time to report moves incompatibilities
* Reduced generation 4-5 was egg game check
There is no need to check every possible generation game.
For every egg species HGSS learnset tables y egg moves table contains all the moves from the same species in DP and Pt, without any move exclusive to that games except in legendaries, and they cant breed
In generation 5 is the same with B2W2 except for Exxegutte, it have a exclusive level up move from B1W1, Psychic, but it can learn the move with TM, it wont count as an egg move
* Check incompatible split breed moves in verify relearn egg
* Fix generation 1 incompatibility moves check
SolarBeam removed from Exeggcute/Exeggutor incompatiblity, Exeggutor could learn it with a TM in generation 1
Removed Vaporeon Mist and Eevee Take Down incompatiblity, Vaporeon could learn Take Down with a TM in generation 1
2017-04-14 17:11:50 +00:00
|
|
|
|
}
|
2016-10-24 05:03:19 +00:00
|
|
|
|
|
2019-07-26 00:42:15 +00:00
|
|
|
|
internal static bool GetCanBeEgg23(PKM pkm)
|
2017-02-28 04:57:24 +00:00
|
|
|
|
{
|
2017-03-26 22:11:09 +00:00
|
|
|
|
if (pkm.IsEgg)
|
|
|
|
|
return true;
|
2017-02-28 04:57:24 +00:00
|
|
|
|
if (pkm.Format > 2 && pkm.Ball != 4)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
int lvl = pkm.CurrentLevel;
|
|
|
|
|
if (lvl < 5)
|
|
|
|
|
return false;
|
|
|
|
|
|
2017-09-04 20:48:10 +00:00
|
|
|
|
if (pkm.Format > 3 && pkm.Met_Level < 5)
|
2017-03-26 22:11:09 +00:00
|
|
|
|
return false;
|
2017-03-27 19:10:30 +00:00
|
|
|
|
if (pkm.Format > 3 && pkm.FatefulEncounter)
|
|
|
|
|
return false;
|
2017-03-26 22:11:09 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return IsEvolutionValid(pkm);
|
2017-02-28 04:57:24 +00:00
|
|
|
|
}
|
2016-03-23 05:50:54 +00:00
|
|
|
|
|
2019-04-11 05:05:57 +00:00
|
|
|
|
public static IReadOnlyList<byte> GetPPTable(PKM pkm, int format)
|
2018-11-14 03:10:31 +00:00
|
|
|
|
{
|
2019-04-11 05:05:57 +00:00
|
|
|
|
if (format != 7)
|
|
|
|
|
return GetPPTable(format);
|
|
|
|
|
return pkm.GG ? MovePP_GG : MovePP_SM;
|
2018-11-14 03:10:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-11 05:05:57 +00:00
|
|
|
|
public static IReadOnlyList<byte> GetPPTable(int format)
|
2018-10-27 15:53:09 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return format switch
|
2018-10-27 15:53:09 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
1 => MovePP_RBY,
|
|
|
|
|
2 => MovePP_GSC,
|
|
|
|
|
3 => MovePP_RS,
|
|
|
|
|
4 => MovePP_DP,
|
|
|
|
|
5 => MovePP_BW,
|
|
|
|
|
6 => MovePP_XY,
|
|
|
|
|
7 => MovePP_SM,
|
|
|
|
|
8 => MovePP_SWSH,
|
|
|
|
|
_ => Array.Empty<byte>()
|
|
|
|
|
};
|
2018-10-27 15:53:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-30 21:08:35 +00:00
|
|
|
|
internal static ICollection<int> GetWildBalls(PKM pkm)
|
2016-11-08 16:43:57 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return pkm.GenNumber switch
|
2016-11-08 16:43:57 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
1 => WildPokeBalls1,
|
|
|
|
|
2 => WildPokeBalls2,
|
|
|
|
|
3 => WildPokeBalls3,
|
|
|
|
|
4 => (pkm.HGSS ? WildPokeBalls4_HGSS : WildPokeBalls4_DPPt),
|
|
|
|
|
5 => WildPokeBalls5,
|
|
|
|
|
6 => WildPokeballs6,
|
|
|
|
|
7 => (pkm.GG ? WildPokeballs7b : WildPokeballs7),
|
|
|
|
|
8 => WildPokeballs8,
|
2020-01-07 01:50:18 +00:00
|
|
|
|
_ => Array.Empty<int>()
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
2017-02-21 03:40:50 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-07-04 16:15:20 +00:00
|
|
|
|
internal static int GetEggHatchLevel(PKM pkm) => GetEggHatchLevel(pkm.Format);
|
|
|
|
|
internal static int GetEggHatchLevel(int gen) => gen <= 3 ? 5 : 1;
|
|
|
|
|
|
2019-01-21 05:55:28 +00:00
|
|
|
|
internal static ICollection<int> GetSplitBreedGeneration(int generation)
|
2017-03-26 13:39:09 +00:00
|
|
|
|
{
|
|
|
|
|
switch (generation)
|
|
|
|
|
{
|
|
|
|
|
case 3: return SplitBreed_3;
|
2019-09-23 23:56:47 +00:00
|
|
|
|
|
2018-06-22 03:13:41 +00:00
|
|
|
|
case 4:
|
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
2019-09-23 23:56:47 +00:00
|
|
|
|
case 7:
|
|
|
|
|
case 8:
|
|
|
|
|
return SplitBreed;
|
|
|
|
|
|
2019-01-21 05:55:28 +00:00
|
|
|
|
default: return Array.Empty<int>();
|
2017-03-26 13:39:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static int GetMaxSpeciesOrigin(PKM pkm)
|
2017-02-21 03:40:50 +00:00
|
|
|
|
{
|
2018-06-13 01:46:31 +00:00
|
|
|
|
if (pkm.Format == 1)
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return GetMaxSpeciesOrigin(1);
|
2018-06-13 01:46:31 +00:00
|
|
|
|
if (pkm.Format == 2 || pkm.VC)
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return GetMaxSpeciesOrigin(2);
|
|
|
|
|
return GetMaxSpeciesOrigin(pkm.GenNumber);
|
2017-02-21 03:40:50 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static int GetMaxSpeciesOrigin(int generation)
|
2017-02-21 03:40:50 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return generation switch
|
2017-02-21 03:40:50 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
1 => MaxSpeciesID_1,
|
|
|
|
|
2 => MaxSpeciesID_2,
|
|
|
|
|
3 => MaxSpeciesID_3,
|
|
|
|
|
4 => MaxSpeciesID_4,
|
|
|
|
|
5 => MaxSpeciesID_5,
|
|
|
|
|
6 => MaxSpeciesID_6,
|
|
|
|
|
7 => MaxSpeciesID_7b,
|
|
|
|
|
8 => MaxSpeciesID_8,
|
|
|
|
|
_ => -1
|
|
|
|
|
};
|
2017-02-21 03:40:50 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-01-21 05:55:28 +00:00
|
|
|
|
internal static ICollection<int> GetFutureGenEvolutions(int generation)
|
2017-02-21 03:40:50 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return generation switch
|
2017-02-21 03:40:50 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
1 => FutureEvolutionsGen1,
|
|
|
|
|
2 => FutureEvolutionsGen2,
|
|
|
|
|
3 => FutureEvolutionsGen3,
|
|
|
|
|
4 => FutureEvolutionsGen4,
|
|
|
|
|
5 => FutureEvolutionsGen5,
|
2020-01-07 01:50:18 +00:00
|
|
|
|
_ => Array.Empty<int>()
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
2017-02-21 03:40:50 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-01-10 23:40:33 +00:00
|
|
|
|
internal static int GetDebutGeneration(int species)
|
|
|
|
|
{
|
|
|
|
|
if (species <= MaxSpeciesID_1)
|
|
|
|
|
return 1;
|
|
|
|
|
if (species <= MaxSpeciesID_2)
|
|
|
|
|
return 2;
|
|
|
|
|
if (species <= MaxSpeciesID_3)
|
|
|
|
|
return 3;
|
|
|
|
|
if (species <= MaxSpeciesID_4)
|
|
|
|
|
return 4;
|
|
|
|
|
if (species <= MaxSpeciesID_5)
|
|
|
|
|
return 5;
|
|
|
|
|
if (species <= MaxSpeciesID_6)
|
|
|
|
|
return 6;
|
2018-11-14 03:10:31 +00:00
|
|
|
|
if (species <= MaxSpeciesID_7b)
|
2018-01-10 23:40:33 +00:00
|
|
|
|
return 7;
|
2019-09-23 23:56:47 +00:00
|
|
|
|
if (species <= MaxSpeciesID_8)
|
|
|
|
|
return 8;
|
2018-01-10 23:40:33 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2016-10-24 05:03:19 +00:00
|
|
|
|
|
2017-09-16 00:43:31 +00:00
|
|
|
|
internal static int GetMaxLanguageID(int generation)
|
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return generation switch
|
2017-09-16 00:43:31 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
1 => (int) LanguageID.Spanish, // 1-7 except 6
|
|
|
|
|
3 => (int) LanguageID.Spanish, // 1-7 except 6
|
|
|
|
|
2 => (int) LanguageID.Korean,
|
|
|
|
|
4 => (int) LanguageID.Korean,
|
|
|
|
|
5 => (int) LanguageID.Korean,
|
|
|
|
|
6 => (int) LanguageID.Korean,
|
|
|
|
|
7 => (int) LanguageID.ChineseT,
|
|
|
|
|
8 => (int) LanguageID.ChineseT,
|
|
|
|
|
_ => -1
|
|
|
|
|
};
|
2017-09-16 00:43:31 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private static bool IsEvolvedFormChange(PKM pkm)
|
2017-02-02 05:59:39 +00:00
|
|
|
|
{
|
2017-02-05 21:08:25 +00:00
|
|
|
|
if (pkm.IsEgg)
|
|
|
|
|
return false;
|
|
|
|
|
|
2020-02-21 06:11:48 +00:00
|
|
|
|
if (pkm.Format >= 7 && (AlolanVariantEvolutions12.Contains(pkm.Species) || GalarVariantFormEvolutions.Contains(pkm.Species)))
|
2017-02-02 05:59:39 +00:00
|
|
|
|
return pkm.AltForm == 1;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
if (pkm.Format >= 8)
|
|
|
|
|
{
|
|
|
|
|
if (GalarVariantFormEvolutions.Contains(pkm.Species))
|
|
|
|
|
return pkm.AltForm == 1;
|
|
|
|
|
if (GalarForm0Evolutions.TryGetValue(pkm.Species, out var orig))
|
|
|
|
|
return pkm.AltForm != orig; // bad compare?
|
2019-11-18 06:04:41 +00:00
|
|
|
|
if ((int) Species.Toxtricity == pkm.Species)
|
|
|
|
|
return pkm.AltForm == EvolutionMethod.GetAmpLowKeyResult(pkm.Nature);
|
2019-12-29 02:59:00 +00:00
|
|
|
|
if ((int) Species.Alcremie == pkm.Species)
|
|
|
|
|
return true;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
}
|
2019-11-18 06:04:41 +00:00
|
|
|
|
if ((pkm.Species == (int)Species.Meowstic || pkm.Species == (int)Species.Indeedee) && pkm.Gender == 1)
|
2017-02-02 05:59:39 +00:00
|
|
|
|
return pkm.AltForm == 1;
|
2018-07-27 02:34:27 +00:00
|
|
|
|
return pkm.Species == 773;
|
2017-02-02 05:59:39 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-04-18 03:06:23 +00:00
|
|
|
|
internal static bool IsEvolutionValid(PKM pkm, int minSpecies = -1, int minLevel = -1)
|
2016-04-08 01:19:21 +00:00
|
|
|
|
{
|
2019-07-02 15:34:28 +00:00
|
|
|
|
var curr = EvolutionChain.GetValidPreEvolutions(pkm, minLevel: minLevel);
|
2018-07-04 16:15:20 +00:00
|
|
|
|
var min = curr.FindLast(z => z.Species == minSpecies);
|
2018-04-18 03:06:23 +00:00
|
|
|
|
if (min != null && min.Level < minLevel)
|
|
|
|
|
return false;
|
2019-07-02 15:34:28 +00:00
|
|
|
|
var poss = EvolutionChain.GetValidPreEvolutions(pkm, lvl: 100, minLevel: minLevel, skipChecks: true);
|
2016-04-08 01:19:21 +00:00
|
|
|
|
|
2017-05-29 22:21:39 +00:00
|
|
|
|
if (minSpecies != -1)
|
2018-07-04 16:15:20 +00:00
|
|
|
|
{
|
|
|
|
|
int last = poss.FindLastIndex(z => z.Species == minSpecies);
|
|
|
|
|
return curr.Count >= last;
|
|
|
|
|
}
|
2019-01-21 05:55:28 +00:00
|
|
|
|
int gen = pkm.GenNumber;
|
2019-12-07 08:00:49 +00:00
|
|
|
|
if (gen >= 3 && GetSplitBreedGeneration(gen).Contains(GetBaseSpecies(poss, 1).Species))
|
2018-07-04 16:15:20 +00:00
|
|
|
|
return curr.Count >= poss.Count - 1;
|
|
|
|
|
return curr.Count >= poss.Count;
|
2016-04-08 01:19:21 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static bool IsEvolutionValidWithMove(PKM pkm, LegalInfo info)
|
2017-06-07 03:10:05 +00:00
|
|
|
|
{
|
|
|
|
|
// Exclude species that do not evolve leveling with a move
|
2017-06-07 03:52:21 +00:00
|
|
|
|
// Exclude gen 1-3 formats
|
2019-04-17 05:14:21 +00:00
|
|
|
|
// Exclude Mr. Mime and Snorlax for gen 1-3 games
|
|
|
|
|
var gen = info.Generation;
|
|
|
|
|
if (!SpeciesEvolutionWithMove.Contains(pkm.Species) || pkm.Format <= 3 || (BabyEvolutionWithMove.Contains(pkm.Species) && gen <= 3))
|
2017-06-07 03:10:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
var index = Array.FindIndex(SpeciesEvolutionWithMove, p => p == pkm.Species);
|
|
|
|
|
var levels = MinLevelEvolutionWithMove[index];
|
|
|
|
|
var moves = MoveEvolutionWithMove[index];
|
2019-04-17 05:14:21 +00:00
|
|
|
|
var allowegg = EggMoveEvolutionWithMove[index][gen];
|
2017-06-07 03:10:05 +00:00
|
|
|
|
|
2017-06-07 03:52:21 +00:00
|
|
|
|
// Get the minimum level in any generation when the pokemon could learn the evolve move
|
2017-06-07 03:10:05 +00:00
|
|
|
|
var LearnLevel = 101;
|
2019-04-17 05:14:21 +00:00
|
|
|
|
for (int g = gen; g <= pkm.Format; g++)
|
2018-07-27 02:34:27 +00:00
|
|
|
|
{
|
2017-06-07 03:52:21 +00:00
|
|
|
|
if (pkm.InhabitedGeneration(g) && levels[g] > 0)
|
2017-06-07 03:10:05 +00:00
|
|
|
|
LearnLevel = Math.Min(LearnLevel, levels[g]);
|
2018-07-27 02:34:27 +00:00
|
|
|
|
}
|
2017-06-07 03:10:05 +00:00
|
|
|
|
|
|
|
|
|
// Check also if the current encounter include the evolve move as an special move
|
|
|
|
|
// That means the pokemon have the move from the encounter level
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
if (info.EncounterMatch is IMoveset s && s.Moves.Any(m => moves.Contains(m)))
|
2017-06-07 03:10:05 +00:00
|
|
|
|
LearnLevel = Math.Min(LearnLevel, info.EncounterMatch.LevelMin);
|
|
|
|
|
|
|
|
|
|
// If the encounter is a player hatched egg check if the move could be an egg move or inherited level up move
|
|
|
|
|
if (info.EncounterMatch.EggEncounter && !pkm.WasGiftEgg && !pkm.WasEventEgg && allowegg)
|
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (IsMoveInherited(pkm, info, moves))
|
2019-04-17 05:14:21 +00:00
|
|
|
|
LearnLevel = Math.Min(LearnLevel, gen <= 3 ? 6 : 2);
|
2017-06-07 03:10:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-07 03:52:21 +00:00
|
|
|
|
// If has original met location the minimum evolution level is one level after met level
|
|
|
|
|
// Gen 3 pokemon in gen 4 games: minimum level is one level after transfer to generation 4
|
|
|
|
|
// VC pokemon: minimum level is one level after transfer to generation 7
|
2018-05-12 15:13:39 +00:00
|
|
|
|
// Sylveon: always one level after met level, for gen 4 and 5 eevees in gen 6 games minimum for evolution is one level after transfer to generation 5
|
2019-12-09 01:39:19 +00:00
|
|
|
|
if (pkm.HasOriginalMetLocation || (pkm.Format == 4 && pkm.Gen3) || pkm.VC || pkm.Species == (int)Species.Sylveon)
|
2017-06-07 23:15:13 +00:00
|
|
|
|
LearnLevel = Math.Max(pkm.Met_Level + 1, LearnLevel);
|
2017-06-07 03:10:05 +00:00
|
|
|
|
|
2017-06-07 23:15:13 +00:00
|
|
|
|
// Current level must be at least one the minimum learn level
|
|
|
|
|
// the level-up event that triggers the learning of the move also triggers evolution with no further level-up required
|
|
|
|
|
return pkm.CurrentLevel >= LearnLevel;
|
2017-06-07 03:10:05 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private static bool IsMoveInherited(PKM pkm, LegalInfo info, int[] moves)
|
2017-06-07 03:52:21 +00:00
|
|
|
|
{
|
|
|
|
|
// In 3DS games, the inherited move must be in the relearn moves.
|
2018-07-04 16:15:20 +00:00
|
|
|
|
if (info.Generation >= 6)
|
2017-06-07 03:52:21 +00:00
|
|
|
|
return pkm.RelearnMoves.Any(moves.Contains);
|
|
|
|
|
|
|
|
|
|
// In Pre-3DS games, the move is inherited if it has the move and it can be hatched with the move.
|
|
|
|
|
if (pkm.Moves.Any(moves.Contains))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// If the pokemon does not have the move, it still could be an egg move that was forgotten.
|
|
|
|
|
// This requires the pokemon to not have 4 other moves identified as egg moves or inherited level up moves.
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return 4 > info.Moves.Count(m => m.Source == MoveSource.EggMove || m.Source == MoveSource.InheritLevelUp);
|
2017-06-07 03:52:21 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-12-29 02:59:00 +00:00
|
|
|
|
/// <summary>Checks if the form may be different than the original encounter detail.</summary>
|
|
|
|
|
/// <param name="pkm">Pokémon</param>
|
|
|
|
|
/// <param name="species">Original species</param>
|
2018-02-04 05:12:36 +00:00
|
|
|
|
internal static bool IsFormChangeable(PKM pkm, int species)
|
2017-02-21 05:19:25 +00:00
|
|
|
|
{
|
|
|
|
|
if (FormChange.Contains(species))
|
|
|
|
|
return true;
|
2019-12-29 02:59:00 +00:00
|
|
|
|
if (species != pkm.Species && IsEvolvedFormChange(pkm))
|
2017-02-21 05:19:25 +00:00
|
|
|
|
return true;
|
2019-12-09 01:39:19 +00:00
|
|
|
|
if (species == (int)Species.Zygarde && pkm.InhabitedGeneration(7) && pkm.AltForm > 1)
|
2017-02-21 05:19:25 +00:00
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2018-06-19 04:56:30 +00:00
|
|
|
|
internal static bool GetCanInheritMoves(int species)
|
2017-09-15 01:52:31 +00:00
|
|
|
|
{
|
2018-06-19 04:56:30 +00:00
|
|
|
|
if (FixedGenderFromBiGender.Contains(species)) // Nincada -> Shedinja loses gender causing 'false', edge case
|
2017-09-15 01:52:31 +00:00
|
|
|
|
return true;
|
2018-06-19 04:56:30 +00:00
|
|
|
|
var pi = PKX.Personal[species];
|
|
|
|
|
if (!pi.Genderless && !pi.OnlyMale)
|
2017-09-15 01:52:31 +00:00
|
|
|
|
return true;
|
2018-06-19 04:56:30 +00:00
|
|
|
|
if (MixedGenderBreeding.Contains(species))
|
2017-09-15 01:52:31 +00:00
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static bool GetCanLearnMachineMove(PKM pkm, int move, int generation, GameVersion version = GameVersion.Any)
|
2017-02-15 22:33:59 +00:00
|
|
|
|
{
|
2018-06-20 00:14:22 +00:00
|
|
|
|
return GetValidMoves(pkm, version, EvolutionChain.GetValidPreEvolutions(pkm), generation, Machine: true).Contains(move);
|
2017-02-15 22:33:59 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static bool GetCanRelearnMove(PKM pkm, int move, int generation, GameVersion version = GameVersion.Any)
|
2016-05-10 01:19:31 +00:00
|
|
|
|
{
|
2018-06-20 00:14:22 +00:00
|
|
|
|
return GetValidMoves(pkm, version, EvolutionChain.GetValidPreEvolutions(pkm), generation, LVL: true, Relearn: true).Contains(move);
|
2016-05-10 02:24:52 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static bool GetCanKnowMove(PKM pkm, int move, int generation, GameVersion version = GameVersion.Any)
|
2016-05-10 02:24:52 +00:00
|
|
|
|
{
|
2019-12-09 01:39:19 +00:00
|
|
|
|
if (pkm.Species == (int)Species.Smeargle)
|
2019-03-20 05:05:13 +00:00
|
|
|
|
return !InvalidSketch.Contains(move);
|
2018-06-20 00:14:22 +00:00
|
|
|
|
return GetValidMoves(pkm, version, EvolutionChain.GetValidPreEvolutions(pkm), generation, LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move);
|
2016-05-10 01:19:31 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-11-19 04:26:11 +00:00
|
|
|
|
internal static EvoCriteria GetBaseEggSpecies(PKM pkm, int skipOption = 0)
|
2017-04-13 15:48:13 +00:00
|
|
|
|
{
|
|
|
|
|
if (pkm.Format == 1)
|
2018-06-10 17:44:05 +00:00
|
|
|
|
return GetBaseSpecies(pkm, generation: 2);
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return GetBaseSpecies(pkm, skipOption);
|
2017-04-13 15:48:13 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-11-19 04:26:11 +00:00
|
|
|
|
internal static EvoCriteria GetBaseSpecies(PKM pkm, int skipOption = 0, int generation = -1)
|
2016-02-23 06:52:48 +00:00
|
|
|
|
{
|
2017-07-29 18:54:52 +00:00
|
|
|
|
int tree = generation != -1 ? generation : pkm.Format;
|
2018-11-14 03:10:31 +00:00
|
|
|
|
var table = EvolutionTree.GetEvolutionTree(pkm, tree);
|
2018-05-10 03:37:11 +00:00
|
|
|
|
int maxSpeciesOrigin = generation != -1 ? GetMaxSpeciesOrigin(generation) : -1;
|
|
|
|
|
var evos = table.GetValidPreEvolutions(pkm, maxLevel: 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks: true);
|
2019-12-07 08:00:49 +00:00
|
|
|
|
return GetBaseSpecies(evos, skipOption);
|
2018-05-10 03:37:11 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-12-06 07:04:24 +00:00
|
|
|
|
private static readonly EvoCriteria Nincada = new EvoCriteria(290, 0)
|
2018-05-10 03:37:11 +00:00
|
|
|
|
{
|
2019-11-24 17:49:54 +00:00
|
|
|
|
Method = (int)EvolutionType.LevelUp,
|
2019-11-19 04:26:11 +00:00
|
|
|
|
MinLevel = 20, Level = 20,
|
|
|
|
|
RequiresLvlUp = true,
|
|
|
|
|
};
|
|
|
|
|
|
2019-12-07 01:21:38 +00:00
|
|
|
|
private static readonly EvoCriteria EvoEmpty = new EvoCriteria(0, 0)
|
2019-11-19 04:26:11 +00:00
|
|
|
|
{
|
|
|
|
|
Method = (int)EvolutionType.None,
|
|
|
|
|
};
|
|
|
|
|
|
2019-12-07 08:00:49 +00:00
|
|
|
|
internal static EvoCriteria GetBaseSpecies(IReadOnlyList<EvoCriteria> evos, int skipOption = 0)
|
2019-11-19 04:26:11 +00:00
|
|
|
|
{
|
2019-12-07 08:00:49 +00:00
|
|
|
|
int species = evos[0].Species;
|
2019-11-19 04:26:11 +00:00
|
|
|
|
if (species == (int)Species.Shedinja) // Shedinja
|
|
|
|
|
return Nincada; // Nincada
|
2019-01-21 05:55:28 +00:00
|
|
|
|
|
|
|
|
|
// skip n from end, return species if invalid index
|
|
|
|
|
int index = evos.Count - 1 - skipOption;
|
2019-11-19 04:26:11 +00:00
|
|
|
|
return (uint)index >= evos.Count ? EvoEmpty : evos[index];
|
2016-02-26 15:52:08 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private static int GetMaxLevelGeneration(PKM pkm)
|
2017-02-16 10:59:07 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return GetMaxLevelGeneration(pkm, pkm.GenNumber);
|
2017-02-16 10:59:07 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private static int GetMaxLevelGeneration(PKM pkm, int generation)
|
2017-02-16 10:59:07 +00:00
|
|
|
|
{
|
|
|
|
|
if (!pkm.InhabitedGeneration(generation))
|
2017-06-27 03:30:44 +00:00
|
|
|
|
return pkm.Met_Level;
|
2017-02-16 10:59:07 +00:00
|
|
|
|
|
|
|
|
|
if (pkm.Format <= 2)
|
|
|
|
|
{
|
|
|
|
|
if (generation == 1 && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species))
|
|
|
|
|
return pkm.CurrentLevel - 1;
|
|
|
|
|
return pkm.CurrentLevel;
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-09 01:39:19 +00:00
|
|
|
|
if (pkm.Species == (int)Species.Sylveon && generation == 5)
|
2017-02-16 10:59:07 +00:00
|
|
|
|
return pkm.CurrentLevel - 1;
|
|
|
|
|
|
2017-03-26 16:45:01 +00:00
|
|
|
|
if (pkm.Gen3 && pkm.Format > 4 && pkm.Met_Level == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUpGen4.Contains(pkm.Species))
|
2017-02-16 10:59:07 +00:00
|
|
|
|
return pkm.Met_Level - 1;
|
|
|
|
|
|
2017-02-21 03:40:50 +00:00
|
|
|
|
if (!pkm.HasOriginalMetLocation)
|
|
|
|
|
return pkm.Met_Level;
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2017-02-21 03:40:50 +00:00
|
|
|
|
return pkm.CurrentLevel;
|
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static int GetMinLevelEncounter(PKM pkm)
|
2017-02-21 03:40:50 +00:00
|
|
|
|
{
|
2018-07-27 02:34:27 +00:00
|
|
|
|
// Only for gen 3 pokemon in format 3, after transfer to gen 4 it should return transfer level
|
2017-03-26 16:05:58 +00:00
|
|
|
|
if (pkm.Format == 3 && pkm.WasEgg)
|
|
|
|
|
return 5;
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
|
|
|
|
// Only for gen 4 pokemon in format 4, after transfer to gen 5 it should return transfer level
|
2017-11-18 06:19:23 +00:00
|
|
|
|
if (pkm.Format == 4 && pkm.Gen4 && pkm.WasEgg)
|
2017-03-30 18:58:30 +00:00
|
|
|
|
return 1;
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return pkm.HasOriginalMetLocation ? pkm.Met_Level : GetMaxLevelGeneration(pkm);
|
2017-02-16 10:59:07 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-10-06 02:58:30 +00:00
|
|
|
|
internal static bool IsCatchRateHeldItem(int rate) => ParseSettings.AllowGen1Tradeback && HeldItems_GSC.Contains((ushort) rate);
|
2018-07-25 02:33:42 +00:00
|
|
|
|
|
2018-06-19 02:10:21 +00:00
|
|
|
|
private static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion Version, IReadOnlyList<IReadOnlyList<EvoCriteria>> vs, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true)
|
2016-05-10 02:03:58 +00:00
|
|
|
|
{
|
2019-05-11 17:12:14 +00:00
|
|
|
|
var r = new List<int> { 0 };
|
2017-02-21 03:40:50 +00:00
|
|
|
|
if (Relearn && pkm.Format >= 6)
|
|
|
|
|
r.AddRange(pkm.RelearnMoves);
|
|
|
|
|
|
2019-10-19 03:50:38 +00:00
|
|
|
|
int start = pkm.GenNumber;
|
|
|
|
|
if (start < 0)
|
|
|
|
|
start = pkm.Format; // be generous instead of returning nothing
|
|
|
|
|
|
|
|
|
|
for (int gen = start; gen <= pkm.Format; gen++)
|
2018-07-27 02:34:27 +00:00
|
|
|
|
{
|
2018-04-18 02:56:43 +00:00
|
|
|
|
if (vs[gen].Count != 0)
|
2017-06-18 01:37:19 +00:00
|
|
|
|
r.AddRange(GetValidMoves(pkm, Version, vs[gen], gen, minLvLG1: minLvLG1, minLvLG2: minLvLG2, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM));
|
2018-07-27 02:34:27 +00:00
|
|
|
|
}
|
2017-02-21 03:40:50 +00:00
|
|
|
|
|
2017-10-07 04:03:23 +00:00
|
|
|
|
return r.Distinct();
|
2017-02-15 22:33:59 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-05-11 07:59:07 +00:00
|
|
|
|
private static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion Version, IReadOnlyList<EvoCriteria> vs, int generation, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true)
|
2017-02-15 22:33:59 +00:00
|
|
|
|
{
|
2019-05-11 17:12:14 +00:00
|
|
|
|
var r = new List<int> { 0 };
|
2016-10-23 19:48:49 +00:00
|
|
|
|
int species = pkm.Species;
|
2016-10-24 05:03:19 +00:00
|
|
|
|
|
2016-05-10 02:03:58 +00:00
|
|
|
|
if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever)
|
|
|
|
|
{
|
2019-01-21 05:55:28 +00:00
|
|
|
|
// These don't evolve, so don't bother iterating for all entries in the evolution chain (should always be count==1).
|
|
|
|
|
int formcount;
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-10-28 04:59:31 +00:00
|
|
|
|
// In gen 3 deoxys has different forms depending on the current game, in the PersonalInfo there is no alternate form info
|
2019-12-09 01:39:19 +00:00
|
|
|
|
if (pkm.Format == 3 && species == (int)Species.Deoxys)
|
2017-03-30 19:34:48 +00:00
|
|
|
|
formcount = 4;
|
2019-01-21 05:55:28 +00:00
|
|
|
|
else
|
|
|
|
|
formcount = pkm.PersonalInfo.FormeCount;
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2016-05-10 02:03:58 +00:00
|
|
|
|
for (int i = 0; i < formcount; i++)
|
2019-05-11 07:59:07 +00:00
|
|
|
|
r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, vs[0].Level, i, Tutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, generation));
|
2018-06-09 23:04:06 +00:00
|
|
|
|
if (Relearn)
|
|
|
|
|
r.AddRange(pkm.RelearnMoves);
|
2017-03-17 04:20:06 +00:00
|
|
|
|
return r.Distinct();
|
2016-05-10 02:03:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-21 05:55:28 +00:00
|
|
|
|
// Special Type Tutors Availability
|
|
|
|
|
bool moveTutor = Tutor || MoveReminder; // Usually true, except when called for move suggestions (no tutored moves)
|
|
|
|
|
|
2018-04-18 02:56:43 +00:00
|
|
|
|
for (var i = 0; i < vs.Count; i++)
|
Gen 1 move analysis improvement. Adapted the valid moves to take into account that move deleter and move reminder do not exits in generation 1 (#1037)
* Fix getMoves with min level, when SkipWhile and TakeWhile is used together the index i in TakeWhile is calculated from the enumerator that results of the SkipWhile function, not the index of the initial array, those giving an incorrect index to check Levels array in the TakeWhile
* Fix getMoves when levelmin or levelmax is above max level in the levels array, TakeWhile and SkipWhile return empty list if the while goes beyond the last element of the array
* Include player hatched egg in the list of possible encounters for parseMoves only if the pokemon was an egg
Also change the valur of WasEgg for gen1,2,3 pokemon if the encounter analyzed is not an egg
add the non egg encounters to the list instead of checking the non-egg encounter inside parseMovesWasEggPreRelearn
* Fix for gen3 egg encounters
Remove non-egg encounters without special moves if there is an egg encounter because egg encounter already cover every possible move combination
Do not add daycare egg encounter for gen3 unhatched egg if there is another encounter, that means is an event or gift egg, not a daycare egg
Remove duplicate encounters
* Gift egg should not allow inherited moves even it they dont have special moves
Those gift eggs are hatched only with the species base moves
* Added getEncounterMoves functions, to be used for generation 1 encounters to find what moves have a pokemon at the moment of being caught because there is no move reminder in generation 1
* Added GBEncounterData, structure for refactor the tuples used in generation 1 and 2 encounters
* Add LevelMin and LevelMax to IEncounterable to get the encounter moves by the min level of the generation 1 EncounterLink
Add iGeneration to difference generation 1 and generation 2 encounters for GB Era pokemon
* Mark generation in gen 1 and 2 encounters
There is no need to mark the generation in gen 3 to 7 encounters because in that generations it match the pokemon generation number
* Add min level for generation 1 moves in getMoves functions
Add function to return the default moves for a GB encounters, for generation 1 games that included both moves from level up table and level 1 moves from personal table
Fix getMoves with min level when the moves list is empty, like Raichu generation 1
* Add maxSpecies to getBaseSpecies function for gen1 pokemon with a gen2 egg encounter
Refactor VC Encounter changing Tuples for GBData class
* Fixed for gen 2 Checks
Also do not search for generation1 encounter if the gen2 pokemon have met location from crystal
* Fix VC wild encounters, should be stored as array or else other verifyEncounter functions wont work
* Add generation 1 parse moves function including default moves
* Clean-up get encounters
* Verify empty moves for generation 1 encounters, in generation 1 does not exits move deleter
That means when a move slot have been used by a level up move or a TM/HM/Tutor move it cant be empty again
Does not apply if generation 2 tradeback is allowed, in generation 2 there is a move deleter
* Added two edge cases for pokemon that learn in red/blue and yellow different moves at the same level, this combinations can not exits until a later level when they learn again one of the levels in the other game, only happen for flareon and vaporeon
* Check incompatible moves between evolution species, it is for species that learn a move in a level as an evolved species and a move at a upper level as a preevolution
Also added most edge cases for the min slots used for generation 1 games, i think every weird combination is already covered
* Fix gen 1 eevee and evolutions move checks
* Cleanup
* Move the code to change valid moves for generation 1 to a function
* Fix getMoveMinLevelGBEncounter
* getUsedMoveSlots, removed wild Butterfree edge case, it is not possible
* Filter the min level of the encounter by the possible games the pokemon could be originated, yellow pikachu and kadabra can be detected
2017-04-09 00:17:20 +00:00
|
|
|
|
{
|
2018-06-19 02:10:21 +00:00
|
|
|
|
var evo = vs[i];
|
2019-05-11 07:59:07 +00:00
|
|
|
|
var moves = GetEvoMoves(pkm, Version, vs, generation, minLvLG1, minLvLG2, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, moveTutor, i, evo);
|
2018-06-09 23:04:06 +00:00
|
|
|
|
r.AddRange(moves);
|
Gen 1 move analysis improvement. Adapted the valid moves to take into account that move deleter and move reminder do not exits in generation 1 (#1037)
* Fix getMoves with min level, when SkipWhile and TakeWhile is used together the index i in TakeWhile is calculated from the enumerator that results of the SkipWhile function, not the index of the initial array, those giving an incorrect index to check Levels array in the TakeWhile
* Fix getMoves when levelmin or levelmax is above max level in the levels array, TakeWhile and SkipWhile return empty list if the while goes beyond the last element of the array
* Include player hatched egg in the list of possible encounters for parseMoves only if the pokemon was an egg
Also change the valur of WasEgg for gen1,2,3 pokemon if the encounter analyzed is not an egg
add the non egg encounters to the list instead of checking the non-egg encounter inside parseMovesWasEggPreRelearn
* Fix for gen3 egg encounters
Remove non-egg encounters without special moves if there is an egg encounter because egg encounter already cover every possible move combination
Do not add daycare egg encounter for gen3 unhatched egg if there is another encounter, that means is an event or gift egg, not a daycare egg
Remove duplicate encounters
* Gift egg should not allow inherited moves even it they dont have special moves
Those gift eggs are hatched only with the species base moves
* Added getEncounterMoves functions, to be used for generation 1 encounters to find what moves have a pokemon at the moment of being caught because there is no move reminder in generation 1
* Added GBEncounterData, structure for refactor the tuples used in generation 1 and 2 encounters
* Add LevelMin and LevelMax to IEncounterable to get the encounter moves by the min level of the generation 1 EncounterLink
Add iGeneration to difference generation 1 and generation 2 encounters for GB Era pokemon
* Mark generation in gen 1 and 2 encounters
There is no need to mark the generation in gen 3 to 7 encounters because in that generations it match the pokemon generation number
* Add min level for generation 1 moves in getMoves functions
Add function to return the default moves for a GB encounters, for generation 1 games that included both moves from level up table and level 1 moves from personal table
Fix getMoves with min level when the moves list is empty, like Raichu generation 1
* Add maxSpecies to getBaseSpecies function for gen1 pokemon with a gen2 egg encounter
Refactor VC Encounter changing Tuples for GBData class
* Fixed for gen 2 Checks
Also do not search for generation1 encounter if the gen2 pokemon have met location from crystal
* Fix VC wild encounters, should be stored as array or else other verifyEncounter functions wont work
* Add generation 1 parse moves function including default moves
* Clean-up get encounters
* Verify empty moves for generation 1 encounters, in generation 1 does not exits move deleter
That means when a move slot have been used by a level up move or a TM/HM/Tutor move it cant be empty again
Does not apply if generation 2 tradeback is allowed, in generation 2 there is a move deleter
* Added two edge cases for pokemon that learn in red/blue and yellow different moves at the same level, this combinations can not exits until a later level when they learn again one of the levels in the other game, only happen for flareon and vaporeon
* Check incompatible moves between evolution species, it is for species that learn a move in a level as an evolved species and a move at a upper level as a preevolution
Also added most edge cases for the min slots used for generation 1 games, i think every weird combination is already covered
* Fix gen 1 eevee and evolutions move checks
* Cleanup
* Move the code to change valid moves for generation 1 to a function
* Fix getMoveMinLevelGBEncounter
* getUsedMoveSlots, removed wild Butterfree edge case, it is not possible
* Filter the min level of the encounter by the possible games the pokemon could be originated, yellow pikachu and kadabra can be detected
2017-04-09 00:17:20 +00:00
|
|
|
|
}
|
2016-10-24 05:03:19 +00:00
|
|
|
|
|
2017-02-14 06:49:32 +00:00
|
|
|
|
if (pkm.Format <= 3)
|
2017-03-17 04:20:06 +00:00
|
|
|
|
return r.Distinct();
|
2018-06-09 23:04:06 +00:00
|
|
|
|
|
2017-02-15 23:56:54 +00:00
|
|
|
|
if (LVL)
|
2019-05-11 07:59:07 +00:00
|
|
|
|
MoveTutor.AddSpecialFormChangeMoves(r, pkm, generation, species);
|
2017-02-21 03:40:50 +00:00
|
|
|
|
if (Tutor)
|
2019-05-11 07:59:07 +00:00
|
|
|
|
MoveTutor.AddSpecialTutorMoves(r, pkm, generation, species);
|
|
|
|
|
if (Relearn && generation >= 6)
|
2017-02-21 03:40:50 +00:00
|
|
|
|
r.AddRange(pkm.RelearnMoves);
|
2017-03-17 04:20:06 +00:00
|
|
|
|
return r.Distinct();
|
2016-05-10 02:03:58 +00:00
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-05-11 07:59:07 +00:00
|
|
|
|
private static IEnumerable<int> GetEvoMoves(PKM pkm, GameVersion Version, IReadOnlyList<EvoCriteria> vs, int generation, int minLvLG1, int minLvLG2, bool LVL, bool Tutor, bool Machine, bool MoveReminder, bool RemoveTransferHM, bool moveTutor, int i, EvoCriteria evo)
|
2018-06-09 23:04:06 +00:00
|
|
|
|
{
|
2019-05-11 07:59:07 +00:00
|
|
|
|
int minlvlevo1 = GetEvoMoveMinLevel1(pkm, generation, minLvLG1, evo);
|
|
|
|
|
int minlvlevo2 = GetEvoMoveMinLevel2(pkm, generation, minLvLG2, evo);
|
2018-06-09 23:04:06 +00:00
|
|
|
|
var maxLevel = evo.Level;
|
|
|
|
|
if (i != 0 && vs[i - 1].RequiresLvlUp) // evolution
|
|
|
|
|
++maxLevel; // allow lvlmoves from the level it evolved to the next species
|
2019-11-24 06:48:02 +00:00
|
|
|
|
return GetMoves(pkm, evo.Species, minlvlevo1, minlvlevo2, maxLevel, evo.Form, Tutor, Version, LVL, moveTutor, Machine, MoveReminder, RemoveTransferHM, generation);
|
2018-06-09 23:04:06 +00:00
|
|
|
|
}
|
2018-07-26 03:40:57 +00:00
|
|
|
|
|
2019-01-21 05:55:28 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the minimum level the move can be learned at based on the species encounter level.
|
|
|
|
|
/// </summary>
|
2019-05-11 07:59:07 +00:00
|
|
|
|
private static int GetEvoMoveMinLevel1(PKM pkm, int generation, int minLvLG1, EvoCriteria evo)
|
2018-07-26 03:40:57 +00:00
|
|
|
|
{
|
2019-05-11 07:59:07 +00:00
|
|
|
|
if (generation != 1)
|
2018-07-26 03:40:57 +00:00
|
|
|
|
return 1;
|
2019-01-21 05:55:28 +00:00
|
|
|
|
// For evolutions, return the lower of the two; current level should legally be >=
|
2018-07-26 03:40:57 +00:00
|
|
|
|
if (evo.MinLevel > 1)
|
|
|
|
|
return Math.Min(pkm.CurrentLevel, evo.MinLevel);
|
|
|
|
|
return minLvLG1;
|
|
|
|
|
}
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2019-05-11 07:59:07 +00:00
|
|
|
|
private static int GetEvoMoveMinLevel2(PKM pkm, int generation, int minLvLG2, EvoCriteria evo)
|
2018-07-26 03:40:57 +00:00
|
|
|
|
{
|
2019-05-11 07:59:07 +00:00
|
|
|
|
if (generation != 2 || ParseSettings.AllowGen2MoveReminder(pkm))
|
2018-07-26 03:40:57 +00:00
|
|
|
|
return 1;
|
2019-01-21 05:55:28 +00:00
|
|
|
|
// For evolutions, return the lower of the two; current level should legally be >=
|
2018-07-26 03:40:57 +00:00
|
|
|
|
if (evo.MinLevel > 1)
|
|
|
|
|
return Math.Min(pkm.CurrentLevel, evo.MinLevel);
|
|
|
|
|
return minLvLG2;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-11 07:59:07 +00:00
|
|
|
|
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)
|
2016-10-24 05:03:19 +00:00
|
|
|
|
{
|
2019-05-11 17:12:14 +00:00
|
|
|
|
var r = new List<int>();
|
2018-06-09 03:37:35 +00:00
|
|
|
|
if (LVL)
|
2019-05-11 07:59:07 +00:00
|
|
|
|
r.AddRange(MoveLevelUp.GetMovesLevelUp(pkm, species, minlvlG1, minlvlG2, lvl, form, Version, MoveReminder, generation));
|
2018-06-09 03:37:35 +00:00
|
|
|
|
if (Machine)
|
2019-05-11 07:59:07 +00:00
|
|
|
|
r.AddRange(MoveTechnicalMachine.GetTMHM(pkm, species, form, generation, Version, RemoveTransferHM));
|
2018-06-09 03:37:35 +00:00
|
|
|
|
if (moveTutor)
|
2019-05-11 07:59:07 +00:00
|
|
|
|
r.AddRange(MoveTutor.GetTutorMoves(pkm, species, form, specialTutors, generation));
|
2018-06-10 17:44:05 +00:00
|
|
|
|
return r.Distinct();
|
2016-05-10 02:03:58 +00:00
|
|
|
|
}
|
2018-06-19 04:56:30 +00:00
|
|
|
|
|
2018-06-09 03:10:41 +00:00
|
|
|
|
internal const GameVersion NONE = GameVersion.Invalid;
|
|
|
|
|
internal static readonly LearnVersion LearnNONE = new LearnVersion(-1);
|
|
|
|
|
|
|
|
|
|
internal static bool HasVisitedB2W2(this PKM pkm) => pkm.InhabitedGeneration(5);
|
|
|
|
|
internal static bool HasVisitedORAS(this PKM pkm) => pkm.InhabitedGeneration(6) && (pkm.AO || !pkm.IsUntraded);
|
|
|
|
|
internal static bool HasVisitedUSUM(this PKM pkm) => pkm.InhabitedGeneration(7) && (pkm.USUM || !pkm.IsUntraded);
|
2020-02-13 04:25:39 +00:00
|
|
|
|
internal static bool IsMovesetRestricted(this PKM pkm, int gen) => (pkm.GG && gen == 7) || pkm.IsUntraded;
|
2018-06-09 03:10:41 +00:00
|
|
|
|
|
2018-05-20 17:35:58 +00:00
|
|
|
|
public static bool HasMetLocationUpdatedTransfer(int originalGeneration, int currentGeneration)
|
|
|
|
|
{
|
|
|
|
|
if (originalGeneration < 3)
|
|
|
|
|
return currentGeneration >= 3;
|
|
|
|
|
if (originalGeneration <= 4)
|
|
|
|
|
return currentGeneration != originalGeneration;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-26 21:40:02 +00:00
|
|
|
|
|
|
|
|
|
public static bool IsValidMissingLanguage(PKM pkm)
|
|
|
|
|
{
|
|
|
|
|
return pkm.Format == 5 && pkm.BW;
|
|
|
|
|
}
|
2018-06-23 16:49:04 +00:00
|
|
|
|
|
|
|
|
|
public static string GetG1OT_GFMew(int lang) => lang == (int)LanguageID.Japanese ? "ゲーフリ" : "GF";
|
|
|
|
|
public static string GetG5OT_NSparkle(int lang) => lang == (int)LanguageID.Japanese ? "N" : "N";
|
2018-08-03 14:38:29 +00:00
|
|
|
|
|
2020-02-04 04:10:07 +00:00
|
|
|
|
public const string Stadium1JP = "スタジアム";
|
|
|
|
|
|
2018-08-03 14:38:29 +00:00
|
|
|
|
public static string GetGBStadiumOTName(bool jp, GameVersion s)
|
|
|
|
|
{
|
|
|
|
|
if (jp)
|
2020-02-04 04:10:07 +00:00
|
|
|
|
return Stadium1JP;
|
2018-08-03 14:38:29 +00:00
|
|
|
|
return s == GameVersion.Stadium2 ? "Stadium" : "STADIUM";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int GetGBStadiumOTID(bool jp, GameVersion s)
|
|
|
|
|
{
|
|
|
|
|
if (jp)
|
2020-02-04 04:10:07 +00:00
|
|
|
|
return GetGBStadiumOTID_JPN(s);
|
2018-08-03 14:38:29 +00:00
|
|
|
|
return 2000;
|
|
|
|
|
}
|
2018-08-15 21:58:55 +00:00
|
|
|
|
|
2020-02-04 04:10:07 +00:00
|
|
|
|
public static int GetGBStadiumOTID_JPN(GameVersion s)
|
|
|
|
|
{
|
|
|
|
|
return s == GameVersion.Stadium2 ? 2000 : 1999;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-27 23:06:06 +00:00
|
|
|
|
public static int GetMaxLengthOT(int gen, LanguageID lang)
|
|
|
|
|
{
|
|
|
|
|
switch (lang)
|
|
|
|
|
{
|
|
|
|
|
case LanguageID.Korean:
|
|
|
|
|
case LanguageID.Japanese: return gen >= 6 ? 6 : 5;
|
|
|
|
|
default: return gen >= 6 ? 12 : 7;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int GetMaxLengthNickname(int gen, LanguageID lang)
|
2018-08-15 21:58:55 +00:00
|
|
|
|
{
|
|
|
|
|
switch (lang)
|
|
|
|
|
{
|
|
|
|
|
case LanguageID.Korean:
|
|
|
|
|
case LanguageID.Japanese: return gen >= 6 ? 6 : 5;
|
2018-08-15 22:26:42 +00:00
|
|
|
|
default: return gen >= 6 ? 12 : 10;
|
2018-08-15 21:58:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-05 18:51:41 +00:00
|
|
|
|
|
2019-05-15 19:07:48 +00:00
|
|
|
|
public static bool GetIsFixedIVSequenceValidSkipRand(IReadOnlyList<int> IVs, PKM pkm, int max = 31)
|
2019-01-05 18:51:41 +00:00
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 6; i++)
|
|
|
|
|
{
|
|
|
|
|
if ((uint) IVs[i] > max) // random
|
|
|
|
|
continue;
|
|
|
|
|
if (IVs[i] != pkm.GetIV(i))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool GetIsFixedIVSequenceValidNoRand(IReadOnlyList<int> IVs, PKM pkm)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 6; i++)
|
|
|
|
|
{
|
|
|
|
|
if (IVs[i] != pkm.GetIV(i))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-02-23 06:52:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|