2018-06-13 01:35:56 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2018-06-09 03:10:41 +00:00
|
|
|
|
|
|
|
|
|
using static PKHeX.Core.Legal;
|
2018-06-13 05:15:06 +00:00
|
|
|
|
using static PKHeX.Core.GameVersion;
|
2018-06-09 03:10:41 +00:00
|
|
|
|
|
|
|
|
|
namespace PKHeX.Core
|
|
|
|
|
{
|
|
|
|
|
internal static class MoveLevelUp
|
|
|
|
|
{
|
2018-11-12 06:49:17 +00:00
|
|
|
|
private static readonly LearnLookup
|
2019-09-23 23:56:47 +00:00
|
|
|
|
LearnSWSH = new LearnLookup(PersonalTable.SWSH, LevelUpSWSH, SWSH),
|
2019-02-02 07:08:03 +00:00
|
|
|
|
LearnSM = new LearnLookup(PersonalTable.SM, LevelUpSM, SM),
|
|
|
|
|
LearnUSUM = new LearnLookup(PersonalTable.USUM, LevelUpUSUM, USUM),
|
|
|
|
|
LearnGG = new LearnLookup(PersonalTable.GG, LevelUpGG, GG),
|
|
|
|
|
LearnXY = new LearnLookup(PersonalTable.XY, LevelUpXY, XY),
|
|
|
|
|
LearnAO = new LearnLookup(PersonalTable.AO, LevelUpAO, ORAS),
|
|
|
|
|
LearnBW = new LearnLookup(PersonalTable.BW, LevelUpBW, BW),
|
|
|
|
|
LearnB2W2 = new LearnLookup(PersonalTable.B2W2, LevelUpB2W2, B2W2),
|
|
|
|
|
LearnDP = new LearnLookup(PersonalTable.DP, LevelUpDP, DP),
|
|
|
|
|
LearnPt = new LearnLookup(PersonalTable.Pt, LevelUpPt, Pt),
|
|
|
|
|
LearnHGSS = new LearnLookup(PersonalTable.HGSS, LevelUpHGSS, HGSS),
|
|
|
|
|
LearnRSE = new LearnLookup(PersonalTable.RS, LevelUpRS, RSE),
|
|
|
|
|
LearnFRLG = new LearnLookup(PersonalTable.LG, LevelUpLG, FRLG),
|
|
|
|
|
LearnGS = new LearnLookup(PersonalTable.GS, LevelUpGS, GS),
|
|
|
|
|
LearnC = new LearnLookup(PersonalTable.C, LevelUpC, C),
|
|
|
|
|
LearnRB = new LearnLookup(PersonalTable.RB, LevelUpRB, RB),
|
2018-06-13 05:15:06 +00:00
|
|
|
|
LearnY = new LearnLookup(PersonalTable.Y, LevelUpY, YW);
|
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
public static LearnVersion GetIsLevelUpMove(PKM pkm, int species, int form, int lvl, int generation, int move, int minlvlG1, int minlvlG2, GameVersion version = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (pkm.IsMovesetRestricted())
|
|
|
|
|
version = (GameVersion)pkm.Version;
|
2018-11-12 06:49:17 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
switch (generation)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-18 04:54:04 +00:00
|
|
|
|
case 1: return GetIsLevelUp1(species, move, lvl, form, minlvlG1, version);
|
2018-06-15 01:52:43 +00:00
|
|
|
|
case 2: if (move > MaxMoveID_1 && pkm.LearnMovesNew2Disallowed()) return LearnNONE;
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return GetIsLevelUp2(species, move, lvl, form, minlvlG2, pkm.Korean, version);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
case 3: return GetIsLevelUp3(species, move, lvl, form, version);
|
|
|
|
|
case 4: return GetIsLevelUp4(species, move, lvl, form, version);
|
|
|
|
|
case 5: return GetIsLevelUp5(species, move, lvl, form, version);
|
|
|
|
|
case 6: return GetIsLevelUp6(species, move, lvl, form, version);
|
|
|
|
|
case 7: return GetIsLevelUp7(species, move, form, version);
|
2019-09-23 23:56:47 +00:00
|
|
|
|
case 8: return GetIsLevelUp8(species, move, form, version);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 04:56:30 +00:00
|
|
|
|
public static LearnVersion GetIsLevelUp1(int species, int move, int max, int form, int min, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (move > MaxMoveID_1)
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
switch (ver)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
case Any: case RBY:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
var first = LearnRB.GetIsLevelUpG1(species, form, move, max, min);
|
2018-06-19 04:56:30 +00:00
|
|
|
|
var second = LearnY.GetIsLevelUpG1(species, form, move, max, min);
|
|
|
|
|
if (!first.IsLevelUp)
|
|
|
|
|
return second;
|
|
|
|
|
if (!second.IsLevelUp)
|
2018-06-13 05:15:06 +00:00
|
|
|
|
return first;
|
2018-06-19 04:56:30 +00:00
|
|
|
|
return first.Level > second.Level ? second : first;
|
2018-06-13 05:15:06 +00:00
|
|
|
|
|
|
|
|
|
case RD: case BU: case GN: case RB:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnRB.GetIsLevelUpG1(species, form, move, max, min);
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case YW:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnY.GetIsLevelUpG1(species, form, move, max, min);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-18 04:54:04 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp2(int species, int move, int max, int form, int min, bool korean, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
// No Korean Crystal
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
case Any: case GSC:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
var first = LearnGS.GetIsLevelUpMin(species, move, max, min, form);
|
2018-06-13 05:15:06 +00:00
|
|
|
|
if (first.IsLevelUp || korean)
|
|
|
|
|
return first;
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnC.GetIsLevelUpMin(species, move, max, min, form);
|
2018-06-13 05:15:06 +00:00
|
|
|
|
|
|
|
|
|
case GD: case SV: case GS:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnGS.GetIsLevelUpMin(species, move, max, min, form);
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case C when !korean:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnC.GetIsLevelUpMin(species, move, max, min, form);
|
2018-06-13 05:15:06 +00:00
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp3(int species, int move, int lvl, int form, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
if (species == 386)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return GetIsLevelUp3Deoxys(form, move, lvl);
|
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
// Emerald level up tables are equal to R/S level up tables
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
|
|
|
|
case Any:
|
|
|
|
|
var first = LearnRSE.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
if (first.IsLevelUp)
|
|
|
|
|
return first;
|
|
|
|
|
return LearnFRLG.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
|
|
|
|
|
case R: case S: case E: case RS: case RSE:
|
|
|
|
|
return LearnRSE.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
case FR: case LG: case FRLG:
|
|
|
|
|
return LearnFRLG.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp4(int species, int move, int lvl, int form, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
case Any: case DPPt:
|
2018-06-13 05:15:06 +00:00
|
|
|
|
var first = LearnDP.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
if (first.IsLevelUp)
|
|
|
|
|
return first;
|
|
|
|
|
var second = LearnPt.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
if (second.IsLevelUp)
|
|
|
|
|
return second;
|
|
|
|
|
if (ver == DPPt) // stop here
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
return LearnHGSS.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
|
|
|
|
|
case D: case P: case DP:
|
|
|
|
|
return LearnDP.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
case Pt:
|
|
|
|
|
return LearnPt.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
case HG: case SS: case HGSS:
|
|
|
|
|
return LearnHGSS.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2019-02-02 07:08:03 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp5(int species, int move, int lvl, int form, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
switch (ver)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case Any:
|
|
|
|
|
var first = LearnBW.GetIsLevelUp(species, form, move, lvl);
|
2018-08-04 17:05:47 +00:00
|
|
|
|
if (first.IsLevelUp && species != 646) // Kyurem moves are same for both versions, but forme movepool not present.
|
2018-06-13 05:15:06 +00:00
|
|
|
|
return first;
|
|
|
|
|
return LearnB2W2.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
case B: case W: case BW:
|
|
|
|
|
return LearnBW.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
case B2: case W2: case B2W2:
|
|
|
|
|
return LearnB2W2.GetIsLevelUp(species, form, move, lvl);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp6(int species, int move, int lvl, int form, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case Any:
|
|
|
|
|
var first = LearnXY.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
if (first.IsLevelUp)
|
|
|
|
|
return first;
|
|
|
|
|
return LearnAO.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
|
|
|
|
|
case X: case Y: case XY:
|
|
|
|
|
return LearnXY.GetIsLevelUp(species, form, move, lvl);
|
|
|
|
|
case OR: case AS: case ORAS:
|
|
|
|
|
return LearnAO.GetIsLevelUp(species, form, move, lvl);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp7(int species, int move, int form, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
2018-11-15 01:40:11 +00:00
|
|
|
|
case GP: case GE: case GG: case GO:
|
2018-11-12 06:49:17 +00:00
|
|
|
|
return LearnGG.GetIsLevelUp(species, form, move);
|
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case Any:
|
|
|
|
|
if (species > MaxSpeciesID_7)
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
var first = LearnSM.GetIsLevelUp(species, form, move);
|
|
|
|
|
if (first.IsLevelUp)
|
|
|
|
|
return first;
|
|
|
|
|
if (species > MaxSpeciesID_7_USUM)
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
return LearnUSUM.GetIsLevelUp(species, form, move);
|
|
|
|
|
|
|
|
|
|
case SN: case MN: case SM:
|
|
|
|
|
if (species > MaxSpeciesID_7)
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
return LearnSM.GetIsLevelUp(species, form, move);
|
|
|
|
|
|
|
|
|
|
case US: case UM: case USUM:
|
|
|
|
|
if (species > MaxSpeciesID_7_USUM)
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
return LearnUSUM.GetIsLevelUp(species, form, move);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-23 23:56:47 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp8(int species, int move, int form, GameVersion ver = Any)
|
|
|
|
|
{
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
|
|
|
|
case Any:
|
|
|
|
|
case SW: case SH:
|
|
|
|
|
if (species > MaxSpeciesID_8)
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
return LearnSWSH.GetIsLevelUp(species, form, move);
|
|
|
|
|
}
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-09 03:10:41 +00:00
|
|
|
|
private static LearnVersion GetIsLevelUp3Deoxys(int form, int move, int lvl)
|
|
|
|
|
{
|
|
|
|
|
var moveset = GetDeoxysLearn3(form);
|
|
|
|
|
if (moveset == null)
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
var lv = moveset.GetLevelLearnMove(move);
|
|
|
|
|
if (lv >= 0 && lv <= lvl)
|
|
|
|
|
return new LearnVersion(lv, GetDeoxysGameVersion3(form));
|
|
|
|
|
return LearnNONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static GameVersion GetDeoxysGameVersion3(int form)
|
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return form switch
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
0 => RS,
|
|
|
|
|
1 => FR,
|
|
|
|
|
2 => LG,
|
|
|
|
|
3 => E,
|
|
|
|
|
_ => Invalid
|
|
|
|
|
};
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
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
|
|
|
|
private static Learnset? GetDeoxysLearn3(int form, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2019-06-01 17:22:49 +00:00
|
|
|
|
const int index = (int)Species.Deoxys;
|
2018-06-13 05:15:06 +00:00
|
|
|
|
if (ver == Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return form switch
|
2018-08-03 03:11:42 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
0 => LevelUpRS[index], // Normal
|
|
|
|
|
1 => LevelUpFR[index], // Attack
|
|
|
|
|
2 => LevelUpLG[index], // Defense
|
|
|
|
|
3 => LevelUpE[index], // Speed
|
|
|
|
|
_ => null,
|
|
|
|
|
};
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-13 01:35:56 +00:00
|
|
|
|
var gen = ver.GetGeneration();
|
|
|
|
|
if (gen != 3)
|
|
|
|
|
return GetDeoxysLearn3(form);
|
2019-06-01 17:22:49 +00:00
|
|
|
|
return GameData.GetLearnsets(ver)[index];
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-10 21:45:25 +00:00
|
|
|
|
public static IEnumerable<int> GetMovesLevelUp(PKM pkm, int species, int minlvlG1, int minlvlG2, int lvl, int form, GameVersion version, bool MoveReminder, int Generation)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (pkm.IsMovesetRestricted())
|
|
|
|
|
version = (GameVersion)pkm.Version;
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return Generation switch
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
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
|
|
|
|
1 => GetMovesLevelUp1(species, form, lvl, minlvlG1, version),
|
2019-10-08 01:40:09 +00:00
|
|
|
|
2 => GetMovesLevelUp2(species, form, lvl, minlvlG2, pkm.Korean, pkm.LearnMovesNew2Disallowed(), version),
|
|
|
|
|
3 => GetMovesLevelUp3(species, form, lvl, version),
|
|
|
|
|
4 => GetMovesLevelUp4(species, form, lvl, version),
|
|
|
|
|
5 => GetMovesLevelUp5(species, form, lvl, version),
|
|
|
|
|
6 => GetMovesLevelUp6(species, form, lvl, version),
|
|
|
|
|
7 => GetMovesLevelUp7(species, form, lvl, MoveReminder, version),
|
|
|
|
|
8 => GetMovesLevelUp8(species, form, lvl, MoveReminder, version),
|
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
|
|
|
|
_ => (IEnumerable<int>)Array.Empty<int>()
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-15 01:52:43 +00:00
|
|
|
|
private static bool LearnMovesNew2Disallowed(this PKM pkm) => pkm.Format == 1 || (pkm.Format >= 7 && pkm.VC);
|
|
|
|
|
|
2018-06-18 04:54:04 +00:00
|
|
|
|
internal static List<int> GetMovesLevelUp1(int species, int form, int max, int min, GameVersion ver = Any)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return AddMovesLevelUp1(new List<int>(), ver, species, form, max, min);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-18 04:54:04 +00:00
|
|
|
|
private static List<int> GetMovesLevelUp2(int species, int form, int max, int min, bool korean, bool removeNewGSCMoves, GameVersion ver = Any)
|
2018-06-14 05:03:58 +00:00
|
|
|
|
{
|
2018-06-18 04:54:04 +00:00
|
|
|
|
var moves = AddMovesLevelUp2(new List<int>(), ver, species, form, max, min, korean);
|
2018-06-15 01:52:43 +00:00
|
|
|
|
if (removeNewGSCMoves)
|
2018-06-14 05:03:58 +00:00
|
|
|
|
moves.RemoveAll(m => m > MaxMoveID_1);
|
|
|
|
|
return moves;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> GetMovesLevelUp3(int species, int form, int max, GameVersion ver = Any)
|
|
|
|
|
{
|
|
|
|
|
return AddMovesLevelUp3(new List<int>(), ver, species, max, form);
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> GetMovesLevelUp4(int species, int form, int max, GameVersion ver = Any)
|
|
|
|
|
{
|
|
|
|
|
return AddMovesLevelUp4(new List<int>(), ver, species, max, form);
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> GetMovesLevelUp5(int species, int form, int max, GameVersion ver = Any)
|
|
|
|
|
{
|
|
|
|
|
return AddMovesLevelUp5(new List<int>(), ver, species, max, form);
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> GetMovesLevelUp6(int species, int form, int max, GameVersion ver = Any)
|
|
|
|
|
{
|
|
|
|
|
return AddMovesLevelUp6(new List<int>(), ver, species, max, form);
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> GetMovesLevelUp7(int species, int form, int max, bool MoveReminder, GameVersion ver = Any)
|
|
|
|
|
{
|
|
|
|
|
return AddMovesLevelUp7(new List<int>(), ver, species, max, form, MoveReminder);
|
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
|
2019-09-23 23:56:47 +00:00
|
|
|
|
private static List<int> GetMovesLevelUp8(int species, int form, int max, bool MoveReminder, GameVersion ver = Any)
|
|
|
|
|
{
|
|
|
|
|
return AddMovesLevelUp8(new List<int>(), ver, species, max, form, MoveReminder);
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-18 04:54:04 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp1(List<int> moves, GameVersion ver, int species, int form, int max, int min)
|
2018-06-14 05:03:58 +00:00
|
|
|
|
{
|
2018-06-13 01:35:56 +00:00
|
|
|
|
switch (ver)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case Any: case RBY:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
LearnRB.AddMoves1(moves, species, form, max, min);
|
|
|
|
|
return LearnY.AddMoves1(moves, species, form, max, min);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
|
|
|
|
|
case RD: case BU: case GN: case RB:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnRB.AddMoves1(moves, species, form, max, min);
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case YW:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnY.AddMoves1(moves, species, form, max, min);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
return moves;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-18 04:54:04 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp2(List<int> moves, GameVersion ver, int species, int form, int max, int min, bool korean)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
|
|
|
|
case Any: case GSC:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
LearnGS.AddMoves(moves, species, form, max, min);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (korean)
|
|
|
|
|
return moves;
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnC.AddMoves(moves, species, form, max, min);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
|
|
|
|
|
case GD: case SV: case GS:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnGS.AddMoves(moves, species, form, max, min);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
case C when !korean:
|
2018-06-18 04:54:04 +00:00
|
|
|
|
return LearnC.AddMoves(moves, species, form, max, min);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
}
|
|
|
|
|
return moves;
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp3(List<int> moves, GameVersion ver, int species, int max, int form)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
|
|
|
|
if (species == 386)
|
|
|
|
|
{
|
2018-06-13 01:35:56 +00:00
|
|
|
|
var learn = GetDeoxysLearn3(form, ver);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
if (learn != null)
|
2018-06-14 05:03:58 +00:00
|
|
|
|
moves.AddRange(learn.GetMoves(max));
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return moves;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
// Emerald level up tables are equal to R/S level up tables
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
|
|
|
|
case Any:
|
|
|
|
|
LearnRSE.AddMoves(moves, species, form, max);
|
|
|
|
|
return LearnFRLG.AddMoves(moves, species, form, max);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
case R: case S: case E: case RS: case RSE:
|
|
|
|
|
return LearnRSE.AddMoves(moves, species, form, max);
|
|
|
|
|
case FR: case LG: case FRLG:
|
|
|
|
|
return LearnFRLG.AddMoves(moves, species, form, max);
|
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return moves;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp4(List<int> moves, GameVersion ver, int species, int max, int form)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
|
|
|
|
case Any: case DPPt:
|
|
|
|
|
LearnDP.AddMoves(moves, species, form, max);
|
|
|
|
|
LearnPt.AddMoves(moves, species, form, max);
|
|
|
|
|
if (ver == DPPt) // stop here
|
|
|
|
|
return moves;
|
|
|
|
|
return LearnHGSS.AddMoves(moves, species, form, max);
|
|
|
|
|
|
|
|
|
|
case D: case P: case DP:
|
|
|
|
|
return LearnDP.AddMoves(moves, species, form, max);
|
|
|
|
|
case Pt:
|
|
|
|
|
return LearnPt.AddMoves(moves, species, form, max);
|
|
|
|
|
case HG: case SS: case HGSS:
|
|
|
|
|
return LearnHGSS.AddMoves(moves, species, form, max);
|
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return moves;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp5(List<int> moves, GameVersion ver, int species, int max, int form)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
|
|
|
|
case Any:
|
2018-08-03 14:46:53 +00:00
|
|
|
|
if (species != 646) // Kyurem moves are same for both versions, but forme movepool not present.
|
2019-02-02 18:19:41 +00:00
|
|
|
|
LearnBW.AddMoves(moves, species, form, max);
|
2018-06-14 05:03:58 +00:00
|
|
|
|
return LearnB2W2.AddMoves(moves, species, form, max);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
case B: case W: case BW:
|
|
|
|
|
return LearnBW.AddMoves(moves, species, form, max);
|
|
|
|
|
case B2: case W2: case B2W2:
|
|
|
|
|
return LearnB2W2.AddMoves(moves, species, form, max);
|
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
return moves;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp6(List<int> moves, GameVersion ver, int species, int max, int form)
|
2018-06-09 03:10:41 +00:00
|
|
|
|
{
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case Any:
|
2018-06-14 05:03:58 +00:00
|
|
|
|
LearnXY.AddMoves(moves, species, form, max);
|
|
|
|
|
return LearnAO.AddMoves(moves, species, form, max);
|
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case X: case Y: case XY:
|
2018-06-14 05:03:58 +00:00
|
|
|
|
return LearnXY.AddMoves(moves, species, form, max);
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case AS: case OR: case ORAS:
|
2018-06-14 05:03:58 +00:00
|
|
|
|
return LearnAO.AddMoves(moves, species, form, max);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
return moves;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-14 05:03:58 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp7(List<int> moves, GameVersion ver, int species, int max, int form, bool MoveReminder)
|
2018-06-13 01:35:56 +00:00
|
|
|
|
{
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (MoveReminder)
|
|
|
|
|
max = 100; // Move reminder can teach any level in movepool now!
|
2018-06-09 03:10:41 +00:00
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
2018-11-15 01:40:11 +00:00
|
|
|
|
case GP: case GE: case GG: case GO:
|
2018-11-12 06:49:17 +00:00
|
|
|
|
return LearnGG.AddMoves(moves, species, form, max);
|
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case Any:
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (species > MaxSpeciesID_7_USUM)
|
|
|
|
|
return moves;
|
|
|
|
|
LearnUSUM.AddMoves(moves, species, form, max);
|
|
|
|
|
if (species > MaxSpeciesID_7)
|
|
|
|
|
return moves;
|
|
|
|
|
return LearnSM.AddMoves(moves, species, form, max);
|
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case SN: case MN: case SM:
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (species > MaxSpeciesID_7)
|
|
|
|
|
return moves;
|
|
|
|
|
return LearnSM.AddMoves(moves, species, form, max);
|
|
|
|
|
|
2018-06-13 05:15:06 +00:00
|
|
|
|
case US: case UM: case USUM:
|
2018-06-14 05:03:58 +00:00
|
|
|
|
if (species > MaxSpeciesID_7_USUM)
|
|
|
|
|
return moves;
|
|
|
|
|
LearnUSUM.AddMoves(moves, species, form, max);
|
2018-06-09 03:10:41 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return moves;
|
|
|
|
|
}
|
2018-06-11 00:55:03 +00:00
|
|
|
|
|
2019-09-23 23:56:47 +00:00
|
|
|
|
private static List<int> AddMovesLevelUp8(List<int> moves, GameVersion ver, int species, int max, int form, bool MoveReminder)
|
|
|
|
|
{
|
|
|
|
|
if (MoveReminder)
|
|
|
|
|
max = 100; // Move reminder can teach any level in movepool now!
|
|
|
|
|
switch (ver)
|
|
|
|
|
{
|
|
|
|
|
case Any:
|
|
|
|
|
case SW: case SH: case SWSH:
|
|
|
|
|
if (species > MaxSpeciesID_8)
|
|
|
|
|
return moves;
|
|
|
|
|
return LearnSWSH.AddMoves(moves, species, form, max);
|
|
|
|
|
}
|
|
|
|
|
return moves;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-11 00:55:03 +00:00
|
|
|
|
public static int[] GetEncounterMoves(PKM pk, int level, GameVersion version)
|
|
|
|
|
{
|
2018-06-18 03:49:03 +00:00
|
|
|
|
if (version <= 0)
|
|
|
|
|
version = (GameVersion)pk.Version;
|
2018-06-11 00:55:03 +00:00
|
|
|
|
return GetEncounterMoves(pk.Species, pk.AltForm, level, version);
|
|
|
|
|
}
|
2018-06-13 01:35:56 +00:00
|
|
|
|
|
|
|
|
|
private static int[] GetEncounterMoves1(int species, int level, GameVersion version)
|
|
|
|
|
{
|
|
|
|
|
var learn = GameData.GetLearnsets(version);
|
|
|
|
|
var table = GameData.GetPersonal(version);
|
|
|
|
|
var index = table.GetFormeIndex(species, 0);
|
|
|
|
|
var lvl0 = (int[])((PersonalInfoG1) table[index]).Moves.Clone();
|
|
|
|
|
int start = Math.Max(0, Array.FindIndex(lvl0, z => z == 0));
|
|
|
|
|
|
|
|
|
|
return learn[index].GetEncounterMoves(level, lvl0, start);
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-19 02:57:32 +00:00
|
|
|
|
private static int[] GetEncounterMoves2(int species, int level, GameVersion version)
|
|
|
|
|
{
|
|
|
|
|
var learn = GameData.GetLearnsets(version);
|
|
|
|
|
var table = GameData.GetPersonal(version);
|
|
|
|
|
var index = table.GetFormeIndex(species, 0);
|
|
|
|
|
var lvl0 = learn[species].GetEncounterMoves(1);
|
|
|
|
|
int start = Math.Max(0, Array.FindIndex(lvl0, z => z == 0));
|
|
|
|
|
|
|
|
|
|
return learn[index].GetEncounterMoves(level, lvl0, start);
|
|
|
|
|
}
|
2018-06-13 01:35:56 +00:00
|
|
|
|
|
2018-06-11 00:55:03 +00:00
|
|
|
|
public static int[] GetEncounterMoves(int species, int form, int level, GameVersion version)
|
|
|
|
|
{
|
2018-06-19 02:57:32 +00:00
|
|
|
|
if (RBY.Contains(version))
|
|
|
|
|
return GetEncounterMoves1(species, level, version);
|
|
|
|
|
if (GSC.Contains(version))
|
|
|
|
|
return GetEncounterMoves2(species, level, version);
|
2018-06-11 00:55:03 +00:00
|
|
|
|
var learn = GameData.GetLearnsets(version);
|
|
|
|
|
var table = GameData.GetPersonal(version);
|
|
|
|
|
var index = table.GetFormeIndex(species, form);
|
|
|
|
|
return learn[index].GetEncounterMoves(level);
|
|
|
|
|
}
|
2018-06-09 03:10:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|