Misc updates

ZA: Check ability number values (users were setting to 0 and it wasn't flagged)
ZA: Add Mable status for overall completion
ZA: Allow mutable slots of stored sub-event entities (such as gogoat/shuppet)
XY: Allow old man's slot to be modified (he's dead, who cares lol)
This commit is contained in:
Kurt 2025-10-28 23:47:05 -05:00
parent bf9f585b77
commit 70a6658835
4 changed files with 32 additions and 4 deletions

View File

@ -103,7 +103,7 @@ private static List<SlotInfoMisc> GetExtraSlots6XY(SAV6XY sav)
[
new(sav.GTS.Upload, 0) {Type = StorageSlotType.GTS},
new(sav.Fused[0], 0) {Type = StorageSlotType.FusedKyurem},
new(sav.SUBE.GiveSlot, 0) {Type = StorageSlotType.Misc}, // Old Man
new(sav.SUBE.GiveSlot, 0, Mutable: true) {Type = StorageSlotType.Misc}, // Old Man
new(sav.BattleBox[0], 0) {Type = StorageSlotType.BattleBox},
new(sav.BattleBox[1], 1) {Type = StorageSlotType.BattleBox},
@ -265,7 +265,7 @@ private static List<SlotInfoMisc> GetExtraSlots9a(SAV9ZA sav)
var ofs = (i * size) + 8;
var entry = giveAway.Raw.Slice(ofs, PokeCrypto.SIZE_9PARTY);
if (EntityDetection.IsPresent(entry.Span))
list.Add(new(entry, i, true) { Type = StorageSlotType.Misc });
list.Add(new(entry, i, true, Mutable: true) { Type = StorageSlotType.Misc });
else
break;
}

View File

@ -465,7 +465,11 @@ private CheckResult VerifyBirthAbility(LegalityAnalysis data, PA9 pa9)
{
var enc = data.EncounterMatch;
var pi = PersonalTable.ZA[enc.Species, enc.Form];
var index = pa9.AbilityNumber >> 1;
var bitNum = pa9.AbilityNumber;
if (!IsValidAbilityBits(bitNum))
return INVALID;
var index = bitNum >> 1;
var expect = pi.GetAbilityAtIndex(index);
if (pa9.Ability != expect)
return GetInvalid(AbilityMismatch);

View File

@ -34,6 +34,8 @@ public sealed class SaveBlockAccessor9ZA(SAV9ZA sav) : SCBlockAccessor
public EventWorkValueStorage WorkSpawn { get; } = new(sav, Block(sav, KEventWorkSpawn));
public EventWorkFlagStorage Flags { get; } = new(sav, Block(sav, KEventFlagsOther));
public MableStatus9a Mable { get; } = new(sav, Block(sav, KStatusMable));
private const uint KBox = 0x0d66012c; // Box Data
private const uint KParty = 0x3AA1A9AD; // Party Data
private const uint KItem = 0x21C9BD44; // Items
@ -60,7 +62,7 @@ public sealed class SaveBlockAccessor9ZA(SAV9ZA sav) : SCBlockAccessor
private const uint KEventWorkMable = 0x03913534; // momiji_work (u64,u64)[1024] - Mable Tasks Status
private const uint KEventCountMable = 0x8D80EC0F; // momiji_count (u64,u64)[64] - Mable Tasks Counts
private const uint KEventCountTitle = 0x2C2C6964; // TITLE_COUNT_XXXX (u64,u64)[64], such as total Money earned/spent (TITLE=TOTAL/placeholder title?)
private const uint KEventCountTitle = 0x2C2C6964; // title_count (u64,u64)[64] - Player earned display titles
private const uint KEventWorkSpawn = 0x53FD0223; // Overworld Spawner 0x46500 small values (u64,u64)[18000]
// 7C896A83 0x2000 unused
// B25E7EE5 0x400 unused
@ -132,4 +134,6 @@ public sealed class SaveBlockAccessor9ZA(SAV9ZA sav) : SCBlockAccessor
private const uint KNightRoyalePostBattleRewards = 0x356087AD; // object
private const uint KNightRoyaleTrainerStatus = 0x718B8CB1; // object
private const uint KNightRoyaleBonusCards = 0x2A07F494; // object
private const uint KStatusMable = 0x85DBDCE9; // Mable Overall Status
}

View File

@ -0,0 +1,20 @@
using PKHeX.Core;
using static System.Buffers.Binary.BinaryPrimitives;
public sealed class MableStatus9a(SAV9ZA sav, SCBlock block) : SaveBlock<SAV9ZA>(sav, block.Raw)
{
/// <summary>
/// Current level achieved for Mable's Research.
/// </summary>
public uint LevelCurrent { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); }
/// <summary>
/// Last viewed/claimed level for Mable's Research.
/// </summary>
public uint LevelViewed { get => ReadUInt32LittleEndian(Data[0x04..]); set => WriteUInt32LittleEndian(Data[0x04..], value); }
/// <summary>
/// Research Points accumulated for Mable's Research.
/// </summary>
public uint Points { get => ReadUInt32LittleEndian(Data[0x08..]); set => WriteUInt32LittleEndian(Data[0x08..], value); }
}