mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-10-02 09:38:34 -05:00
Add getter/setter for Sav Gen3/4 Trendy Word, Trainer Hill, Berry Blender, Accessory, Backdrop, Wallpaper (#4152)
This commit is contained in:
@@ -128,6 +128,9 @@ public override uint Coin
|
||||
private const int OFS_PouchBalls = 0x0650;
|
||||
private const int OFS_PouchTMHM = 0x0690;
|
||||
private const int OFS_PouchBerry = 0x0790;
|
||||
private const int OFS_BerryBlenderRecord = 0x9BC;
|
||||
private const int OFS_TrendyWord = 0x2E20;
|
||||
private const int OFS_TrainerHillRecord = 0x3718;
|
||||
|
||||
protected override InventoryPouch3[] GetItems()
|
||||
{
|
||||
@@ -185,6 +188,50 @@ public int SwarmIndex
|
||||
|
||||
protected override int ExternalEventData => 0x31B3;
|
||||
|
||||
/// <summary>
|
||||
/// Max RPM for 2, 3 and 4 players. Each value unit represents 0.01 RPM. Value 0 if no record.
|
||||
/// </summary>
|
||||
/// <remarks>2 players: index 0, 3 players: index 1, 4 players: index 2</remarks>
|
||||
public const int BerryBlenderRPMRecordCount = 3;
|
||||
|
||||
private Span<byte> GetBlenderRPMSpan(int index)
|
||||
{
|
||||
if ((uint)index >= BerryBlenderRPMRecordCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
return Large.AsSpan(OFS_BerryBlenderRecord + (index * 2));
|
||||
}
|
||||
|
||||
public ushort GetBerryBlenderRPMRecord(int index) => ReadUInt16LittleEndian(GetBlenderRPMSpan(index));
|
||||
|
||||
public void SetBerryBlenderRPMRecord(int index, ushort value)
|
||||
{
|
||||
WriteUInt16LittleEndian(GetBlenderRPMSpan(index), value);
|
||||
State.Edited = true;
|
||||
}
|
||||
|
||||
public bool GetTrendyWordUnlocked(TrendyWord3E word)
|
||||
{
|
||||
return GetFlag(OFS_TrendyWord + ((byte)word >> 3), (byte)word & 7);
|
||||
}
|
||||
|
||||
public void SetTrendyWordUnlocked(TrendyWord3E word, bool value)
|
||||
{
|
||||
SetFlag(OFS_TrendyWord + ((byte)word >> 3), (byte)word & 7, value);
|
||||
State.Edited = true;
|
||||
}
|
||||
|
||||
/** Each value unit represents 1/60th of a second. Value 0 if no record. */
|
||||
public uint GetTrainerHillRecord(TrainerHillMode3E mode)
|
||||
{
|
||||
return ReadUInt32LittleEndian(Large.AsSpan(OFS_TrainerHillRecord + (byte)mode * 4));
|
||||
}
|
||||
|
||||
public void SetTrainerHillRecord(TrainerHillMode3E mode, uint value)
|
||||
{
|
||||
WriteUInt32LittleEndian(Large.AsSpan(OFS_TrainerHillRecord + (byte)mode * 4), value);
|
||||
State.Edited = true;
|
||||
}
|
||||
|
||||
#region eBerry
|
||||
private const int OFFSET_EBERRY = 0x31F8;
|
||||
private const int SIZE_EBERRY = 0x34;
|
||||
|
||||
@@ -29,7 +29,8 @@ public SAV4Pt(byte[] data) : base(data, GeneralSize, StorageSize, GeneralSize)
|
||||
|
||||
public const int GeneralSize = 0xCF2C;
|
||||
private const int StorageSize = 0x121E4; // Start 0xCF2C, +4 starts box data
|
||||
private const int VillaFurnitureStart = 0x111F;
|
||||
|
||||
public const byte BACKDROP_POSITION_IF_NOT_UNLOCKED = 0x12;
|
||||
|
||||
protected override BlockInfo4[] ExtraBlocks =>
|
||||
[
|
||||
@@ -51,6 +52,12 @@ private void Initialize()
|
||||
protected override int EventFlag => 0xFEC;
|
||||
public override BattleFrontierFacility4 MaxFacility => BattleFrontierFacility4.Arcade;
|
||||
|
||||
private const int OFS_AccessoryMultiCount = 0x4E38; // 4 bits each
|
||||
private const int OFS_AccessorySingleCount = 0x4E58; // 1 bit each
|
||||
private const int OFS_Backdrop = 0x4E60;
|
||||
private const int OFS_ToughWord = 0xCEB4;
|
||||
private const int OFS_VillaFurniture = 0x111F;
|
||||
|
||||
private void GetSAVOffsets()
|
||||
{
|
||||
AdventureInfo = 0;
|
||||
@@ -78,6 +85,8 @@ private void GetSAVOffsets()
|
||||
}
|
||||
|
||||
#region Storage
|
||||
private const int OFS_Wallpaper = 0x121C6;
|
||||
|
||||
private static int AdjustWallpaper(int value, int shift)
|
||||
{
|
||||
// Pt's Special Wallpapers 1-8 are shifted by +0x8
|
||||
@@ -102,6 +111,25 @@ public override void SetBoxWallpaper(int box, int value)
|
||||
value = AdjustWallpaper(value, 0x08);
|
||||
Storage[GetBoxWallpaperOffset(box)] = (byte)value;
|
||||
}
|
||||
|
||||
public bool GetWallpaperUnlocked(Wallpaper4Pt wallpaperId)
|
||||
{
|
||||
if (wallpaperId < Wallpaper4Pt.Distortion)
|
||||
return true;
|
||||
|
||||
var unlockableWallpaperIdx = wallpaperId - Wallpaper4Pt.Distortion;
|
||||
return FlagUtil.GetFlag(Storage, OFS_Wallpaper + (unlockableWallpaperIdx >> 3), unlockableWallpaperIdx & 7);
|
||||
}
|
||||
|
||||
public void SetWallpaperUnlocked(Wallpaper4Pt wallpaperId, bool value)
|
||||
{
|
||||
if (wallpaperId < Wallpaper4Pt.Distortion)
|
||||
return; // Always unlocked
|
||||
|
||||
var unlockableWallpaperIdx = wallpaperId - Wallpaper4Pt.Distortion;
|
||||
FlagUtil.SetFlag(Storage, OFS_Wallpaper + (unlockableWallpaperIdx >> 3), unlockableWallpaperIdx & 7, value);
|
||||
State.Edited = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override IReadOnlyList<InventoryPouch> Inventory
|
||||
@@ -169,41 +197,112 @@ private Roamer4 GetRoamer(int index)
|
||||
return new Roamer4(mem);
|
||||
}
|
||||
|
||||
public bool GetVillaFurniturePurchased(VillaFurniture index)
|
||||
public byte GetAccessoryOwnedCount(Accessory4 accessory)
|
||||
{
|
||||
if (index > VillaFurniture.MAX)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
return FlagUtil.GetFlag(General, VillaFurnitureStart + ((byte)index >> 3), (byte)index & 7);
|
||||
if (accessory < Accessory4.ColoredParasol)
|
||||
{
|
||||
byte enumIdx = (byte)accessory;
|
||||
byte val = General[OFS_AccessoryMultiCount + (enumIdx / 2)];
|
||||
if (enumIdx % 2 == 0)
|
||||
return (byte)(val & 0x0F);
|
||||
return (byte)(val >> 4);
|
||||
}
|
||||
|
||||
// Otherwise, it's a single-count accessory
|
||||
var flagIdx = accessory - Accessory4.ColoredParasol;
|
||||
if (GetFlag(OFS_AccessorySingleCount + (flagIdx >> 3), flagIdx & 7))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetVillaFurniturePurchased(VillaFurniture index, bool value = true)
|
||||
public void SetAccessoryOwnedCount(Accessory4 accessory, byte count)
|
||||
{
|
||||
if (index > VillaFurniture.MAX)
|
||||
if (accessory < Accessory4.ColoredParasol)
|
||||
{
|
||||
if (count > 9)
|
||||
count = 9;
|
||||
|
||||
var enumIdx = (byte)accessory;
|
||||
var addr = OFS_AccessoryMultiCount + (enumIdx / 2);
|
||||
|
||||
if (enumIdx % 2 == 0)
|
||||
{
|
||||
General[addr] &= 0xF0; // Reset old count to 0
|
||||
General[addr] |= count; // Set new count
|
||||
}
|
||||
else
|
||||
{
|
||||
General[addr] &= 0x0F; // Reset old count to 0
|
||||
General[addr] |= (byte)(count << 4); // Set new count
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var flagIdx = accessory - Accessory4.ColoredParasol;
|
||||
SetFlag(OFS_AccessorySingleCount + (flagIdx >> 3), flagIdx & 7, count != 0);
|
||||
}
|
||||
|
||||
State.Edited = true;
|
||||
}
|
||||
|
||||
public byte GetBackdropPosition(Backdrop4 backdrop)
|
||||
{
|
||||
if (backdrop > Backdrop4.Theater)
|
||||
throw new ArgumentOutOfRangeException(nameof(backdrop), backdrop, null);
|
||||
return General[OFS_Backdrop + (byte)backdrop];
|
||||
}
|
||||
|
||||
public bool GetBackdropUnlocked(Backdrop4 backdrop)
|
||||
{
|
||||
return GetBackdropPosition(backdrop) != BACKDROP_POSITION_IF_NOT_UNLOCKED;
|
||||
}
|
||||
|
||||
public void RemoveBackdrop(Backdrop4 backdrop) => SetBackdropPosition(backdrop, BACKDROP_POSITION_IF_NOT_UNLOCKED);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position of a backdrop.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Every unlocked backdrop must have a different position.
|
||||
/// Use <see cref="RemoveBackdrop"/> to remove a backdrop.
|
||||
/// </remarks>
|
||||
public void SetBackdropPosition(Backdrop4 backdrop, byte position)
|
||||
{
|
||||
if (backdrop > Backdrop4.Theater)
|
||||
throw new ArgumentOutOfRangeException(nameof(backdrop), backdrop, null);
|
||||
if (position > BACKDROP_POSITION_IF_NOT_UNLOCKED)
|
||||
position = BACKDROP_POSITION_IF_NOT_UNLOCKED;
|
||||
General[OFS_Backdrop + (byte)backdrop] = position;
|
||||
State.Edited = true;
|
||||
}
|
||||
|
||||
public bool GetToughWordUnlocked(ToughWord4 word)
|
||||
{
|
||||
if (word > ToughWord4.REMSleep)
|
||||
throw new ArgumentOutOfRangeException(nameof(word), word, null);
|
||||
return GetFlag(OFS_ToughWord + ((byte)word >> 3), (byte)word & 7);
|
||||
}
|
||||
|
||||
public void SetToughWordUnlocked(ToughWord4 word, bool value)
|
||||
{
|
||||
if (word > ToughWord4.REMSleep)
|
||||
throw new ArgumentOutOfRangeException(nameof(word), word, null);
|
||||
SetFlag(OFS_ToughWord + ((byte)word >> 3), (byte)word & 7, value);
|
||||
State.Edited = true;
|
||||
}
|
||||
|
||||
public bool GetVillaFurniturePurchased(VillaFurniture4 index)
|
||||
{
|
||||
if (index > VillaFurniture4.Chandelier)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
FlagUtil.SetFlag(General, VillaFurnitureStart + ((byte)index >> 3), (byte)index & 7, value);
|
||||
return GetFlag(OFS_VillaFurniture + ((byte)index >> 3), (byte)index & 7);
|
||||
}
|
||||
|
||||
public void SetVillaFurniturePurchased(VillaFurniture4 index, bool value = true)
|
||||
{
|
||||
if (index > VillaFurniture4.Chandelier)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
SetFlag(OFS_VillaFurniture + ((byte)index >> 3), (byte)index & 7, value);
|
||||
State.Edited = true;
|
||||
}
|
||||
}
|
||||
|
||||
public enum VillaFurniture
|
||||
{
|
||||
BigSofa,
|
||||
SmallSofa,
|
||||
Bed,
|
||||
NightTable,
|
||||
TV,
|
||||
AudioSystem,
|
||||
Bookshelf,
|
||||
Rack,
|
||||
Houseplant,
|
||||
PCDesk,
|
||||
MusicBox,
|
||||
PokemonBust1,
|
||||
PokemonBust2,
|
||||
Piano,
|
||||
GuestSet,
|
||||
WallClock,
|
||||
Masterpiece,
|
||||
TeaSet,
|
||||
Chandelier,
|
||||
MAX = Chandelier,
|
||||
}
|
||||
|
||||
9
PKHeX.Core/Saves/Substructures/Gen3/TrainerHillMode3E.cs
Normal file
9
PKHeX.Core/Saves/Substructures/Gen3/TrainerHillMode3E.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum TrainerHillMode3E : byte
|
||||
{
|
||||
Normal = 0,
|
||||
Variety = 1,
|
||||
Unique = 2,
|
||||
Expert = 3,
|
||||
}
|
||||
38
PKHeX.Core/Saves/Substructures/Gen3/TrendyWord3E.cs
Normal file
38
PKHeX.Core/Saves/Substructures/Gen3/TrendyWord3E.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum TrendyWord3E : byte
|
||||
{
|
||||
KTHXBYE = 0,
|
||||
YESSIR = 1,
|
||||
AVANTGARDE = 2,
|
||||
COUPLE = 3,
|
||||
MUCHOBLIGED = 4,
|
||||
YEEHAW = 5,
|
||||
MEGA = 6,
|
||||
ONEHITKO = 7,
|
||||
DESTINY = 8,
|
||||
CANCEL = 9,
|
||||
NEW = 10,
|
||||
FLATTEN = 11,
|
||||
KIDDING = 12,
|
||||
LOSER = 13,
|
||||
LOSING = 14,
|
||||
HAPPENING = 15,
|
||||
HIPAND = 16,
|
||||
SHAKE = 17,
|
||||
SHADY = 18,
|
||||
UPBEAT = 19,
|
||||
MODERN = 20,
|
||||
SMELLYA = 21,
|
||||
BANG = 22,
|
||||
KNOCKOUT = 23,
|
||||
HASSLE = 24,
|
||||
WINNER = 25,
|
||||
FEVER = 26,
|
||||
WANNABE = 27,
|
||||
BABY = 28,
|
||||
HEART = 29,
|
||||
OLD = 30,
|
||||
YOUNG = 31,
|
||||
UGLY = 32,
|
||||
}
|
||||
107
PKHeX.Core/Saves/Substructures/Gen4/Accessory4.cs
Normal file
107
PKHeX.Core/Saves/Substructures/Gen4/Accessory4.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum Accessory4 : byte
|
||||
{
|
||||
WhiteFluff = 0,
|
||||
YellowFluff = 1,
|
||||
PinkFluff = 2,
|
||||
BrownFluff = 3,
|
||||
BlackFluff = 4,
|
||||
OrangeFluff = 5,
|
||||
RoundPebble = 6,
|
||||
GlitterBoulder = 7,
|
||||
SnaggyPebble = 8,
|
||||
JaggedBoulder = 9,
|
||||
BlackPebble = 10,
|
||||
MiniPebble = 11,
|
||||
PinkScale = 12,
|
||||
BlueScale = 13,
|
||||
GreenScale = 14,
|
||||
PurpleScale = 15,
|
||||
BigScale = 16,
|
||||
NarrowScale = 17,
|
||||
BlueFeather = 18,
|
||||
RedFeather = 19,
|
||||
YellowFeather = 20,
|
||||
WhiteFeather = 21,
|
||||
BlackMoustache = 22,
|
||||
WhiteMoustache = 23,
|
||||
BlackBeard = 24,
|
||||
WhiteBeard = 25,
|
||||
SmallLeaf = 26,
|
||||
BigLeaf = 27,
|
||||
NarrowLeaf = 28,
|
||||
ShedClaw = 29,
|
||||
ShedHorn = 30,
|
||||
ThinMushroom = 31,
|
||||
ThickMushroom = 32,
|
||||
Stump = 33,
|
||||
PrettyDewdrop = 34,
|
||||
SnowCrystal = 35,
|
||||
Sparks = 36,
|
||||
ShimmeringFire = 37,
|
||||
MysticFire = 38,
|
||||
Determination = 39,
|
||||
PeculiarSpoon = 40,
|
||||
PuffySmoke = 41,
|
||||
PoisonExtract = 42,
|
||||
WealthyCoin = 43,
|
||||
EerieThing = 44,
|
||||
Spring = 45,
|
||||
Seashell = 46,
|
||||
HummingNote = 47,
|
||||
ShinyPowder = 48,
|
||||
GlitterPowder = 49,
|
||||
RedFlower = 50,
|
||||
PinkFlower = 51,
|
||||
WhiteFlower = 52,
|
||||
BlueFlower = 53,
|
||||
OrangeFlower = 54,
|
||||
YellowFlower = 55,
|
||||
GooglySpecs = 56,
|
||||
BlackSpecs = 57,
|
||||
GorgeousSpecs = 58,
|
||||
SweetCandy = 59,
|
||||
Confetti = 60,
|
||||
|
||||
// For accessories below this point, only 1 copy can be owned at once
|
||||
ColoredParasol = 61,
|
||||
OldUmbrella = 62,
|
||||
Spotlight = 63,
|
||||
Cape = 64,
|
||||
StandingMike = 65,
|
||||
Surfboard = 66,
|
||||
Carpet = 67,
|
||||
RetroPipe = 68,
|
||||
FluffyBed = 69,
|
||||
MirrorBall = 70,
|
||||
PhotoBoard = 71,
|
||||
PinkBarrette = 72,
|
||||
RedBarrette = 73,
|
||||
BlueBarrette = 74,
|
||||
YellowBarrette = 75,
|
||||
GreenBarrette = 76,
|
||||
PinkBalloon = 77,
|
||||
RedBalloons = 78,
|
||||
BlueBalloons = 79,
|
||||
YellowBalloon = 80,
|
||||
GreenBalloons = 81,
|
||||
LaceHeadress = 82,
|
||||
TopHat = 83,
|
||||
SilkVeil = 84,
|
||||
HeroicHeadband = 85,
|
||||
ProfessorHat = 86,
|
||||
FlowerStage = 87,
|
||||
GoldPedestal = 88,
|
||||
GlassStage = 89,
|
||||
AwardPodium = 90,
|
||||
CubeStage = 91,
|
||||
TURTWIGMask = 92,
|
||||
CHIMCHARMask = 93,
|
||||
PIPLUPMask = 94,
|
||||
BigTree = 95,
|
||||
Flag = 96,
|
||||
Crown = 97,
|
||||
Tiara = 98,
|
||||
Comet = 99,
|
||||
}
|
||||
23
PKHeX.Core/Saves/Substructures/Gen4/Backdrop4.cs
Normal file
23
PKHeX.Core/Saves/Substructures/Gen4/Backdrop4.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum Backdrop4 : byte
|
||||
{
|
||||
DressUp = 0,
|
||||
Ranch = 1,
|
||||
CityatNight = 2,
|
||||
SnowyTown = 3,
|
||||
Fiery = 4,
|
||||
OuterSpace = 5,
|
||||
Desert = 6,
|
||||
CumulusCloud = 7,
|
||||
FlowerPatch = 8,
|
||||
FutureRoom = 9,
|
||||
OpenSea = 10,
|
||||
TotalDarkness = 11,
|
||||
TatamiRoom = 12,
|
||||
GingerbreadRoom = 13,
|
||||
Seafloor = 14,
|
||||
Underground = 15,
|
||||
Sky = 16,
|
||||
Theater = 17,
|
||||
}
|
||||
37
PKHeX.Core/Saves/Substructures/Gen4/ToughWord4.cs
Normal file
37
PKHeX.Core/Saves/Substructures/Gen4/ToughWord4.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum ToughWord4 : byte
|
||||
{
|
||||
EarthTones = 0,
|
||||
Implant = 1,
|
||||
GoldenRatio = 2,
|
||||
Omnibus = 3,
|
||||
Starboard = 4,
|
||||
MoneyRate = 5,
|
||||
Resolution = 6,
|
||||
Cadenza = 7,
|
||||
Education = 8,
|
||||
Cubism = 9,
|
||||
CrossStitch = 10,
|
||||
Artery = 11,
|
||||
BoneDensity = 12,
|
||||
Gommage = 13,
|
||||
Streaming = 14,
|
||||
Conductivity = 15,
|
||||
Copyright = 16,
|
||||
TwoStep = 17,
|
||||
Contour = 18,
|
||||
Neutrino = 19,
|
||||
Howling = 20,
|
||||
Spreadsheet = 21,
|
||||
GMT = 22,
|
||||
Irritability = 23,
|
||||
Fractals = 24,
|
||||
Flambe = 25,
|
||||
StockPrices = 26,
|
||||
PHBalance = 27,
|
||||
Vector = 28,
|
||||
Polyphenol = 29,
|
||||
Ubiquitous = 30,
|
||||
REMSleep = 31,
|
||||
}
|
||||
24
PKHeX.Core/Saves/Substructures/Gen4/VillaFurniture4.cs
Normal file
24
PKHeX.Core/Saves/Substructures/Gen4/VillaFurniture4.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum VillaFurniture4 : byte
|
||||
{
|
||||
BigSofa = 0,
|
||||
SmallSofa = 1,
|
||||
Bed = 2,
|
||||
NightTable = 3,
|
||||
TV = 4,
|
||||
AudioSystem = 5,
|
||||
Bookshelf = 6,
|
||||
Rack = 7,
|
||||
Houseplant = 8,
|
||||
PCDesk = 9,
|
||||
MusicBox = 10,
|
||||
PokemonBust1 = 11,
|
||||
PokemonBust2 = 12,
|
||||
Piano = 13,
|
||||
GuestSet = 14,
|
||||
WallClock = 15,
|
||||
Masterpiece = 16,
|
||||
TeaSet = 17,
|
||||
Chandelier = 18,
|
||||
}
|
||||
29
PKHeX.Core/Saves/Substructures/Gen4/Wallpaper4Pt.cs
Normal file
29
PKHeX.Core/Saves/Substructures/Gen4/Wallpaper4Pt.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum Wallpaper4Pt : byte
|
||||
{
|
||||
Forest = 0,
|
||||
City = 1,
|
||||
Desert = 2,
|
||||
Savanna = 3,
|
||||
Crag = 4,
|
||||
Volcano = 5,
|
||||
Snow = 6,
|
||||
Cave = 7,
|
||||
Beach = 8,
|
||||
Seafloor = 9,
|
||||
River = 10,
|
||||
Sky = 11,
|
||||
Checks = 12,
|
||||
PokeCenter = 13,
|
||||
Machine = 14,
|
||||
Simple = 15,
|
||||
Distortion = 16,
|
||||
Contest = 17,
|
||||
Nostalgic = 18,
|
||||
Croagunk = 19,
|
||||
trio = 20,
|
||||
PikaPika = 21,
|
||||
Legend = 22,
|
||||
Team_Galactic = 23,
|
||||
}
|
||||
Reference in New Issue
Block a user