Add Ditto distribution raids 👛

Adds a helper method for SCBlock to measure a size from header.
This commit is contained in:
Kurt 2023-04-06 19:28:10 -07:00
parent 340578b671
commit 0dfb012e5c
3 changed files with 47 additions and 5 deletions

View File

@ -154,7 +154,7 @@ public static EncounterDist9[] GetArray(ReadOnlySpan<byte> data)
private EncounterDist9() : base(GameVersion.SV) { }
private const int SerializedSize = WeightStart + (sizeof(ushort) * 2 * 2 * 4) + 2;
private const int SerializedSize = WeightStart + (sizeof(ushort) * 2 * 2 * 4) + 10;
private const int WeightStart = 0x14;
private static EncounterDist9 ReadEncounter(ReadOnlySpan<byte> data) => new()
{
@ -195,8 +195,10 @@ private static EncounterDist9 ReadEncounter(ReadOnlySpan<byte> data) => new()
RandRate3TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 14))..]),
RandRate3TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 15))..]),
ScaleType = (SizeType9)data[0x34],
Scale = data[0x35],
// 0x34 reserved
IVs = new IndividualValueSet((sbyte)data[0x35], (sbyte)data[0x36], (sbyte)data[0x37], (sbyte)data[0x38], (sbyte)data[0x39], (sbyte)data[0x3A], (IndividualValueSetType)data[0x3B]),
ScaleType = (SizeType9)data[0x3C],
Scale = data[0x3D],
};
private static AbilityPermission GetAbility(byte b) => b switch
@ -239,6 +241,9 @@ protected override bool IsMatchPartial(PKM pk)
return true;
}
if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pk))
return true;
var seed = Tera9RNG.GetOriginalSeed(pk);
if (pk is ITeraType t && !Tera9RNG.IsMatchTeraType(seed, TeraType, Species, Form, (byte)t.TeraTypeOriginal))
return true;
@ -246,7 +251,7 @@ protected override bool IsMatchPartial(PKM pk)
return true;
var pi = PersonalTable.SV.GetFormEntry(Species, Form);
var param = new GenerateParam9(Species, pi.Gender, FlawlessIVCount, 1, 0, 0, ScaleType, Scale, Ability, Shiny);
var param = new GenerateParam9(Species, pi.Gender, FlawlessIVCount, 1, 0, 0, ScaleType, Scale, Ability, Shiny, Nature, IVs);
if (!Encounter9RNG.IsMatch(pk, param, seed))
return true;
return base.IsMatchPartial(pk);
@ -268,7 +273,7 @@ protected override void SetPINGA(PKM pk, EncounterCriteria criteria)
var pi = PersonalTable.SV.GetFormEntry(Species, Form);
var param = new GenerateParam9(Species, pi.Gender, FlawlessIVCount, rollCount,
undefinedSize, undefinedSize, ScaleType, Scale,
Ability, Shiny);
Ability, Shiny, Nature, IVs);
var init = Util.Rand.Rand64();
var success = this.TryApply32(pk9, init, param, criteria);

View File

@ -139,6 +139,43 @@ public void WriteBlock(BinaryWriter bw)
bw.Write((byte)(b ^ xk.Next()));
}
/// <summary>
/// Gets the total length of an encoded data block. The input <see cref="data"/> must be at least 10 bytes long to ensure all block types are correctly parsed.
/// </summary>
/// <param name="data">Data the header exists in.</param>
/// <remarks>This method is useful if you do not know the exact size of a block yet; e.g. fetching the data is an expensive operation.</remarks>
public static int GetTotalLength(ReadOnlySpan<byte> data)
{
int offset = 0;
var key = ReadUInt32LittleEndian(data[offset..]);
offset += 4;
var xk = new SCXorShift32(key);
var type = (SCTypeCode)(data[offset++] ^ xk.Next());
switch (type)
{
case SCTypeCode.Bool1:
case SCTypeCode.Bool2:
case SCTypeCode.Bool3:
Debug.Assert(type != SCTypeCode.Bool3); // invalid type, haven't seen it used yet
return offset;
case SCTypeCode.Object: // Cast raw bytes to Object
var length = ReadInt32LittleEndian(data[offset..]) ^ (int)xk.Next32();
offset += 4;
return offset + length;
case SCTypeCode.Array: // Cast raw bytes to SubType[]
var count = ReadInt32LittleEndian(data[offset..]) ^ (int)xk.Next32();
offset += 4;
type = (SCTypeCode)(data[offset++] ^ xk.Next());
return offset + (type.GetTypeSize() * count);
default: // Single Value Storage
return offset + type.GetTypeSize();
}
}
/// <summary>
/// Reads a new <see cref="SCBlock"/> object from the <see cref="data"/>, determining the <see cref="Type"/> and <see cref="SubType"/> during read.
/// </summary>