2019-09-23 23:56:47 +00:00
using System ;
2020-09-06 17:53:13 +00:00
using System.Collections.Generic ;
2022-01-03 05:35:59 +00:00
using static System . Buffers . Binary . BinaryPrimitives ;
2019-09-23 23:56:47 +00:00
namespace PKHeX.Core
{
/// <summary>
/// <see cref="PersonalInfo"/> class with values from the <see cref="GameVersion.SWSH"/> games.
/// </summary>
2019-11-16 01:34:18 +00:00
public sealed class PersonalInfoSWSH : PersonalInfo
2019-09-23 23:56:47 +00:00
{
2020-06-19 23:51:15 +00:00
public const int SIZE = 0xB0 ;
2021-08-13 22:36:30 +00:00
public const int CountTM = 100 ;
public const int CountTR = 100 ;
2019-09-23 23:56:47 +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
public PersonalInfoSWSH ( byte [ ] data ) : base ( data )
2019-09-23 23:56:47 +00:00
{
2019-11-16 01:34:18 +00:00
TMHM = new bool [ 200 ] ;
2021-08-13 22:36:30 +00:00
for ( var i = 0 ; i < CountTR ; i + + )
2019-11-16 01:34:18 +00:00
{
2021-08-13 22:36:30 +00:00
TMHM [ i ] = FlagUtil . GetFlag ( Data , 0x28 + ( i > > 3 ) , i ) ;
TMHM [ i + CountTM ] = FlagUtil . GetFlag ( Data , 0x3C + ( i > > 3 ) , i ) ;
2019-11-16 01:34:18 +00:00
}
2019-11-17 19:13:52 +00:00
// 0x38-0x3B type tutors, but only 8 bits are valid flags.
var typeTutors = new bool [ 8 ] ;
for ( int i = 0 ; i < typeTutors . Length ; i + + )
typeTutors [ i ] = FlagUtil . GetFlag ( Data , 0x38 , i ) ;
TypeTutors = typeTutors ;
2020-06-19 23:51:15 +00:00
// 0xA8-0xAF are armor type tutors, one bit for each type
var armorTutors = new bool [ 18 ] ;
for ( int i = 0 ; i < armorTutors . Length ; i + + )
armorTutors [ i ] = FlagUtil . GetFlag ( Data , 0xA8 + ( i > > 3 ) , i ) ;
SpecialTutors = new [ ]
{
armorTutors ,
} ;
2019-09-23 23:56:47 +00:00
}
2019-11-16 01:34:18 +00:00
public override byte [ ] Write ( )
{
2021-08-13 22:36:30 +00:00
for ( var i = 0 ; i < CountTR ; i + + )
2019-11-16 01:34:18 +00:00
{
FlagUtil . SetFlag ( Data , 0x28 + ( i > > 3 ) , i , TMHM [ i ] ) ;
2021-08-13 22:36:30 +00:00
FlagUtil . SetFlag ( Data , 0x3C + ( i > > 3 ) , i , TMHM [ i + CountTM ] ) ;
2019-11-16 01:34:18 +00:00
}
2019-11-17 19:13:52 +00:00
for ( int i = 0 ; i < TypeTutors . Length ; i + + )
FlagUtil . SetFlag ( Data , 0x38 , i , TypeTutors [ i ] ) ;
2020-06-19 23:51:15 +00:00
for ( int i = 0 ; i < SpecialTutors [ 0 ] . Length ; i + + )
FlagUtil . SetFlag ( Data , 0xA8 + ( i > > 3 ) , i , SpecialTutors [ 0 ] [ i ] ) ;
2019-11-16 01:34:18 +00:00
return Data ;
}
public override int HP { get = > Data [ 0x00 ] ; set = > Data [ 0x00 ] = ( byte ) value ; }
public override int ATK { get = > Data [ 0x01 ] ; set = > Data [ 0x01 ] = ( byte ) value ; }
public override int DEF { get = > Data [ 0x02 ] ; set = > Data [ 0x02 ] = ( byte ) value ; }
public override int SPE { get = > Data [ 0x03 ] ; set = > Data [ 0x03 ] = ( byte ) value ; }
public override int SPA { get = > Data [ 0x04 ] ; set = > Data [ 0x04 ] = ( byte ) value ; }
public override int SPD { get = > Data [ 0x05 ] ; set = > Data [ 0x05 ] = ( byte ) value ; }
public override int Type1 { get = > Data [ 0x06 ] ; set = > Data [ 0x06 ] = ( byte ) value ; }
public override int Type2 { get = > Data [ 0x07 ] ; set = > Data [ 0x07 ] = ( byte ) value ; }
public override int CatchRate { get = > Data [ 0x08 ] ; set = > Data [ 0x08 ] = ( byte ) value ; }
public override int EvoStage { get = > Data [ 0x09 ] ; set = > Data [ 0x09 ] = ( byte ) value ; }
2022-01-03 05:35:59 +00:00
private int EVYield { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x0A ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x0A ) , ( ushort ) value ) ; }
2019-11-16 01:34:18 +00:00
public override int EV_HP { get = > EVYield > > 0 & 0x3 ; set = > EVYield = ( EVYield & ~ ( 0x3 < < 0 ) ) | ( value & 0x3 ) < < 0 ; }
public override int EV_ATK { get = > EVYield > > 2 & 0x3 ; set = > EVYield = ( EVYield & ~ ( 0x3 < < 2 ) ) | ( value & 0x3 ) < < 2 ; }
public override int EV_DEF { get = > EVYield > > 4 & 0x3 ; set = > EVYield = ( EVYield & ~ ( 0x3 < < 4 ) ) | ( value & 0x3 ) < < 4 ; }
public override int EV_SPE { get = > EVYield > > 6 & 0x3 ; set = > EVYield = ( EVYield & ~ ( 0x3 < < 6 ) ) | ( value & 0x3 ) < < 6 ; }
public override int EV_SPA { get = > EVYield > > 8 & 0x3 ; set = > EVYield = ( EVYield & ~ ( 0x3 < < 8 ) ) | ( value & 0x3 ) < < 8 ; }
public override int EV_SPD { get = > EVYield > > 10 & 0x3 ; set = > EVYield = ( EVYield & ~ ( 0x3 < < 10 ) ) | ( value & 0x3 ) < < 10 ; }
2022-01-03 05:35:59 +00:00
public int Item1 { get = > ReadInt16LittleEndian ( Data . AsSpan ( 0x0C ) ) ; set = > WriteInt16LittleEndian ( Data . AsSpan ( 0x0C ) , ( short ) value ) ; }
public int Item2 { get = > ReadInt16LittleEndian ( Data . AsSpan ( 0x0E ) ) ; set = > WriteInt16LittleEndian ( Data . AsSpan ( 0x0E ) , ( short ) value ) ; }
public int Item3 { get = > ReadInt16LittleEndian ( Data . AsSpan ( 0x10 ) ) ; set = > WriteInt16LittleEndian ( Data . AsSpan ( 0x10 ) , ( short ) value ) ; }
2019-11-16 01:34:18 +00:00
public override int Gender { get = > Data [ 0x12 ] ; set = > Data [ 0x12 ] = ( byte ) value ; }
public override int HatchCycles { get = > Data [ 0x13 ] ; set = > Data [ 0x13 ] = ( byte ) value ; }
public override int BaseFriendship { get = > Data [ 0x14 ] ; set = > Data [ 0x14 ] = ( byte ) value ; }
public override int EXPGrowth { get = > Data [ 0x15 ] ; set = > Data [ 0x15 ] = ( byte ) value ; }
public override int EggGroup1 { get = > Data [ 0x16 ] ; set = > Data [ 0x16 ] = ( byte ) value ; }
public override int EggGroup2 { get = > Data [ 0x17 ] ; set = > Data [ 0x17 ] = ( byte ) value ; }
2022-01-03 05:35:59 +00:00
public int Ability1 { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x18 ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x18 ) , ( ushort ) value ) ; }
public int Ability2 { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x1A ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x1A ) , ( ushort ) value ) ; }
public int AbilityH { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x1C ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x1C ) , ( ushort ) value ) ; }
2019-11-16 01:34:18 +00:00
public override int EscapeRate { get = > 0 ; set { } } // moved?
2022-01-03 05:35:59 +00:00
protected internal override int FormStatsIndex { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x1E ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x1E ) , ( ushort ) value ) ; }
public override int FormSprite { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x1E ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x1E ) , ( ushort ) value ) ; } // ???
2020-12-11 04:42:30 +00:00
public override int FormCount { get = > Data [ 0x20 ] ; set = > Data [ 0x20 ] = ( byte ) value ; }
2019-11-16 01:34:18 +00:00
public override int Color { get = > Data [ 0x21 ] & 0x3F ; set = > Data [ 0x21 ] = ( byte ) ( ( Data [ 0x21 ] & 0xC0 ) | ( value & 0x3F ) ) ; }
public bool IsPresentInGame { get = > ( ( Data [ 0x21 ] > > 6 ) & 1 ) = = 1 ; set = > Data [ 0x21 ] = ( byte ) ( ( Data [ 0x21 ] & ~ 0x40 ) | ( value ? 0x40 : 0 ) ) ; }
2020-12-11 04:42:30 +00:00
public bool SpriteForm { get = > ( ( Data [ 0x21 ] > > 7 ) & 1 ) = = 1 ; set = > Data [ 0x21 ] = ( byte ) ( ( Data [ 0x21 ] & ~ 0x80 ) | ( value ? 0x80 : 0 ) ) ; }
2022-01-03 05:35:59 +00:00
public override int BaseEXP { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x22 ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x22 ) , ( ushort ) value ) ; }
public override int Height { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x24 ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x24 ) , ( ushort ) value ) ; }
public override int Weight { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x26 ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x26 ) , ( ushort ) value ) ; }
2019-11-16 01:34:18 +00:00
2020-09-06 17:53:13 +00:00
public override IReadOnlyList < int > Items
2019-11-16 01:34:18 +00:00
{
get = > new [ ] { Item1 , Item2 , Item3 } ;
set
{
2020-09-06 17:53:13 +00:00
if ( value . Count ! = 3 ) return ;
2019-11-16 01:34:18 +00:00
Item1 = value [ 0 ] ;
Item2 = value [ 1 ] ;
Item3 = value [ 2 ] ;
}
}
2020-09-06 17:53:13 +00:00
public override IReadOnlyList < int > Abilities
2019-11-16 01:34:18 +00:00
{
get = > new [ ] { Ability1 , Ability2 , AbilityH } ;
set
{
2020-09-06 17:53:13 +00:00
if ( value . Count ! = 3 ) return ;
2019-11-16 01:34:18 +00:00
Ability1 = value [ 0 ] ;
Ability2 = value [ 1 ] ;
AbilityH = value [ 2 ] ;
}
}
2020-09-06 17:53:13 +00:00
public override int GetAbilityIndex ( int abilityID ) = > abilityID = = Ability1 ? 0 : abilityID = = Ability2 ? 1 : abilityID = = AbilityH ? 2 : - 1 ;
2022-01-03 05:35:59 +00:00
public int Species { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x4C ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x4C ) , ( ushort ) value ) ; }
2019-11-18 01:14:21 +00:00
2022-01-03 05:35:59 +00:00
public int HatchSpecies { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x56 ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x56 ) , ( ushort ) value ) ; }
public int LocalFormIndex { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x58 ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x58 ) , ( ushort ) value ) ; } // local region base form
public ushort RegionalFlags { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x5A ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x5A ) , value ) ; }
public bool IsRegionalForm { get = > ( RegionalFlags & 1 ) = = 1 ; set = > RegionalFlags = ( ushort ) ( ( RegionalFlags & 0xFFFE ) | ( value ? 1 : 0 ) ) ; }
public int PokeDexIndex { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x5C ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x5C ) , ( ushort ) value ) ; }
public int RegionalFormIndex { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0x5E ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0x5E ) , ( ushort ) value ) ; } // form index of this entry
public int ArmorDexIndex { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0xAC ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0xAC ) , ( ushort ) value ) ; }
public int CrownDexIndex { get = > ReadUInt16LittleEndian ( Data . AsSpan ( 0xAE ) ) ; set = > WriteUInt16LittleEndian ( Data . AsSpan ( 0xAE ) , ( ushort ) value ) ; }
2020-10-08 20:12:25 +00:00
/// <summary>
2021-07-26 21:14:39 +00:00
/// Gets the Form that any offspring will hatch with, assuming it is holding an Everstone.
2020-10-08 20:12:25 +00:00
/// </summary>
public int HatchFormIndexEverstone = > IsRegionalForm ? RegionalFormIndex : LocalFormIndex ;
2020-10-25 17:02:52 +00:00
/// <summary>
/// Checks if the entry shows up in any of the built-in Pokédex.
/// </summary>
public bool IsInDex = > PokeDexIndex ! = 0 | | ArmorDexIndex ! = 0 | | CrownDexIndex ! = 0 ;
2021-04-22 20:47:33 +00:00
public bool HasHiddenAbility = > AbilityH ! = Ability1 ;
2019-09-23 23:56:47 +00:00
}
2020-10-08 20:12:25 +00:00
}