Skip to content

Commit

Permalink
PSEM fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacky720 committed Dec 6, 2023
1 parent 57491bf commit 7eb625b
Show file tree
Hide file tree
Showing 3 changed files with 384 additions and 80 deletions.
130 changes: 115 additions & 15 deletions UndertaleModLib/Models/UndertaleParticleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,21 @@ protected void OnPropertyChanged([CallerMemberName] string name = null)

public UndertaleString Name { get; set; }

// 2023.6
public bool Enabled { get; set; } = true;

public EmitMode Mode { get; set; }

public int EmitCount { get; set; } = 1;
public int EmitCount { get; set; } = 1; // Note: technically single in 2023.8

// 2023.8
public bool EmitRelative { get; set; }
public float DelayMin { get; set; }
public float DelayMax { get; set; }
public TimeUnitEnum DelayUnit { get; set; }
public float IntervalMin { get; set; }
public float IntervalMax { get; set; }
public TimeUnitEnum IntervalUnit { get; set; }

public DistributionEnum Distribution { get; set; }

Expand All @@ -104,6 +116,11 @@ protected void OnPropertyChanged([CallerMemberName] string name = null)

public float FrameIndex { get; set; }

// 2023.4
public bool Animate { get; set; }
public bool Stretch { get; set; }
public bool IsRandom { get; set; }

public uint StartColor { get; set; } = 0xFFFFFFFF;

public uint MidColor { get; set; } = 0xFFFFFFFF;
Expand All @@ -120,13 +137,23 @@ protected void OnPropertyChanged([CallerMemberName] string name = null)

public float ScaleY { get; set; } = 1;

public float SizeMin { get; set; } = 1;
// 2023.8
public float SizeMinX { get; set; } = 1;
public float SizeMaxX { get; set; } = 1;
public float SizeIncreaseX { get; set; }
public float SizeWiggleX { get; set; }
public float SizeMinY { get; set; } = 1;
public float SizeMaxY { get; set; } = 1;
public float SizeIncreaseY { get; set; }
public float SizeWiggleY { get; set; }

public float SizeMax { get; set; } = 1;
public float SizeMin { get => (SizeMinX + SizeMinY) / 2; set { SizeMinX = value; SizeMinY = value; } }

public float SizeIncrease { get; set; }
public float SizeMax { get => (SizeMaxX + SizeMaxY) / 2; set { SizeMaxX = value; SizeMaxY = value; } }

public float SizeWiggle { get; set; }
public float SizeIncrease { get => (SizeIncreaseX + SizeIncreaseY) / 2; set { SizeIncreaseX = value; SizeIncreaseY = value; } }

public float SizeWiggle { get => (SizeWiggleX + SizeWiggleY) / 2; set { SizeWiggleX = value; SizeWiggleY = value; } }

public float SpeedMin { get; set; } = 5;

Expand Down Expand Up @@ -170,8 +197,22 @@ protected void OnPropertyChanged([CallerMemberName] string name = null)
public void Serialize(UndertaleWriter writer)
{
writer.WriteUndertaleString(Name);
if (writer.undertaleData.IsVersionAtLeast(2023, 6))
writer.Write(Enabled);
writer.Write((int)Mode);
writer.Write(EmitCount);
if (writer.undertaleData.IsVersionAtLeast(2023, 8))
{
writer.Write((float)EmitCount);
writer.Write(EmitRelative);
writer.Write(DelayMin);
writer.Write(DelayMax);
writer.Write((int)DelayUnit);
writer.Write(IntervalMin);
writer.Write(IntervalMax);
writer.Write((int)IntervalUnit);
}
else
writer.Write(EmitCount);
writer.Write((int)Distribution);
writer.Write((int)Shape);
writer.Write(RegionX);
Expand All @@ -182,6 +223,12 @@ public void Serialize(UndertaleWriter writer)
writer.Write(_sprite.SerializeById(writer));
writer.Write((int)Texture);
writer.Write(FrameIndex);
if (writer.undertaleData.IsVersionAtLeast(2023, 4))
{
writer.Write(Animate);
writer.Write(Stretch);
writer.Write(IsRandom);
}
writer.Write(StartColor);
writer.Write(MidColor);
writer.Write(EndColor);
Expand All @@ -190,10 +237,24 @@ public void Serialize(UndertaleWriter writer)
writer.Write(LifetimeMax);
writer.Write(ScaleX);
writer.Write(ScaleY);
writer.Write(SizeMin);
writer.Write(SizeMax);
writer.Write(SizeIncrease);
writer.Write(SizeWiggle);
if (writer.undertaleData.IsVersionAtLeast(2023, 8))
{
writer.Write(SizeMinX);
writer.Write(SizeMaxX);
writer.Write(SizeMinY);
writer.Write(SizeMaxY);
writer.Write(SizeIncreaseX);
writer.Write(SizeIncreaseY);
writer.Write(SizeWiggleX);
writer.Write(SizeWiggleY);
}
else
{
writer.Write(SizeMin);
writer.Write(SizeMax);
writer.Write(SizeIncrease);
writer.Write(SizeWiggle);
}
writer.Write(SpeedMin);
writer.Write(SpeedMax);
writer.Write(SpeedIncrease);
Expand All @@ -220,8 +281,22 @@ public void Serialize(UndertaleWriter writer)
public void Unserialize(UndertaleReader reader)
{
Name = reader.ReadUndertaleString();
if (reader.undertaleData.IsVersionAtLeast(2023, 6))
Enabled = reader.ReadBoolean();
Mode = (EmitMode)reader.ReadInt32();
EmitCount = reader.ReadInt32();
if (reader.undertaleData.IsVersionAtLeast(2023, 8))
{
EmitCount = (int)reader.ReadSingle(); // The GUI still only allows integer input...
EmitRelative = reader.ReadBoolean(); // Always 0
DelayMin = reader.ReadSingle();
DelayMax = reader.ReadSingle();
DelayUnit = (TimeUnitEnum)reader.ReadInt32();
IntervalMin = reader.ReadSingle();
IntervalMax = reader.ReadSingle();
IntervalUnit = (TimeUnitEnum)reader.ReadInt32();
}
else
EmitCount = reader.ReadInt32();
Distribution = (DistributionEnum)reader.ReadInt32();
Shape = (EmitterShape)reader.ReadInt32();
RegionX = reader.ReadSingle();
Expand All @@ -233,6 +308,12 @@ public void Unserialize(UndertaleReader reader)
_sprite.Unserialize(reader);
Texture = (TextureEnum)reader.ReadInt32();
FrameIndex = reader.ReadSingle();
if (reader.undertaleData.IsVersionAtLeast(2023, 4))
{
Animate = reader.ReadBoolean();
Stretch = reader.ReadBoolean();
IsRandom = reader.ReadBoolean();
}
StartColor = reader.ReadUInt32();
MidColor = reader.ReadUInt32();
EndColor = reader.ReadUInt32();
Expand All @@ -241,10 +322,24 @@ public void Unserialize(UndertaleReader reader)
LifetimeMax = reader.ReadSingle();
ScaleX = reader.ReadSingle();
ScaleY = reader.ReadSingle();
SizeMin = reader.ReadSingle();
SizeMax = reader.ReadSingle();
SizeIncrease = reader.ReadSingle();
SizeWiggle = reader.ReadSingle();
if (reader.undertaleData.IsVersionAtLeast(2023, 8))
{
SizeMinX = reader.ReadSingle();
SizeMaxX = reader.ReadSingle();
SizeMinY = reader.ReadSingle();
SizeMaxY = reader.ReadSingle();
SizeIncreaseX = reader.ReadSingle();
SizeIncreaseY = reader.ReadSingle();
SizeWiggleX = reader.ReadSingle();
SizeWiggleY = reader.ReadSingle();
}
else
{
SizeMin = reader.ReadSingle();
SizeMax = reader.ReadSingle();
SizeIncrease = reader.ReadSingle();
SizeWiggle = reader.ReadSingle();
}
SpeedMin = reader.ReadSingle();
SpeedMax = reader.ReadSingle();
SpeedIncrease = reader.ReadSingle();
Expand Down Expand Up @@ -323,4 +418,9 @@ public enum TextureEnum
Smoke = 12,
Snow = 13
}
public enum TimeUnitEnum
{
Seconds,
Frames
}
}
94 changes: 94 additions & 0 deletions UndertaleModLib/UndertaleChunks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,93 @@ internal override uint UnserializeObjectCount(UndertaleReader reader)
public class UndertaleChunkPSEM : UndertaleListChunk<UndertaleParticleSystemEmitter>
{
public override string Name => "PSEM";
private static bool checkedPsemVersion;

private void CheckPsemVersion(UndertaleReader reader)
{
// Particle system emitters had the good grace to change three times in three versions
// Three versions which are only detectable by optional features
// This function checks for 2023.4, 2023.6, and 2023.8
if (reader.undertaleData.IsVersionAtLeast(2023, 8))
{
checkedPsemVersion = true;
return;
}

long positionToReturn = reader.AbsPosition;

uint count = reader.ReadUInt32();

if (count < 11) // 2023.2 automatically adds eleven, later versions don't
{
if (!reader.undertaleData.IsVersionAtLeast(2023, 4))
reader.undertaleData.SetGMS2Version(2023, 4);
}

if (count == 0) // Nothing more to do here, unfortunately
{
reader.AbsPosition = positionToReturn;
checkedPsemVersion = true;
return;
}

else if (count == 1) // Special case
{
// Fortunately, consistent padding means we need no parsing here
if (Length == 0xF8)
{
reader.undertaleData.SetGMS2Version(2023, 8);
}
else if (Length == 0xD8)
{
// This check is probably unnecessary since there's no 2023.7 so it would, at worst, change from 2023.6 to 2023.6
if (!reader.undertaleData.IsVersionAtLeast(2023, 6))
reader.undertaleData.SetGMS2Version(2023, 6);
}
else if (Length == 0xC8)
{
// This one is necessary, though, as it could already be 2023.6 at this point
if (!reader.undertaleData.IsVersionAtLeast(2023, 4))
reader.undertaleData.SetGMS2Version(2023, 4);
}
else
{
reader.AbsPosition = positionToReturn;
throw new IOException("Unrecognized PSEM size with only one element");
}

reader.AbsPosition = positionToReturn;
checkedPsemVersion = true;
return;
}

// More than one emitter
uint firstPtr = reader.ReadUInt32();
uint secondPtr = reader.ReadUInt32();
if (secondPtr - firstPtr == 0xEC)
{
reader.undertaleData.SetGMS2Version(2023, 8);
}
else if (secondPtr - firstPtr == 0xC0)
{
if (!reader.undertaleData.IsVersionAtLeast(2023, 6))
reader.undertaleData.SetGMS2Version(2023, 6);
}
else if (secondPtr - firstPtr == 0xBC)
{
if (!reader.undertaleData.IsVersionAtLeast(2023, 4))
reader.undertaleData.SetGMS2Version(2023, 4);
}
else if (secondPtr - firstPtr != 0xB0) // 2023.2
{
reader.AbsPosition = positionToReturn;
throw new IOException("Unrecognized PSEM size with " + count.ToString() + " elements");
}


reader.AbsPosition = positionToReturn;
checkedPsemVersion = true;
}

internal override void SerializeChunk(UndertaleWriter writer)
{
Expand All @@ -1826,11 +1913,16 @@ internal override void UnserializeChunk(UndertaleReader reader)
if (reader.ReadUInt32() != 1)
throw new IOException("Expected PSEM version 1");

if (!checkedPsemVersion)
CheckPsemVersion(reader);

base.UnserializeChunk(reader);
}

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
checkedPsemVersion = false;

if (!reader.undertaleData.IsVersionAtLeast(2023, 2))
throw new InvalidOperationException();

Expand All @@ -1841,6 +1933,8 @@ internal override uint UnserializeObjectCount(UndertaleReader reader)
if (version != 1)
throw new IOException("Expected PSEM version 1, got " + version.ToString());

CheckPsemVersion(reader);

return base.UnserializeObjectCount(reader);
}
}
Expand Down
Loading

0 comments on commit 7eb625b

Please sign in to comment.