using System.Numerics; namespace KeepersCompound.LGS.Database.Chunks; public class Property { public int objectId; public int length; public virtual void Read(BinaryReader reader) { objectId = reader.ReadInt32(); length = (int)reader.ReadUInt32(); } public virtual void Write(BinaryWriter writer) { writer.Write(objectId); writer.Write((uint)length); } } public class PropertyChunk : IChunk, IMergable where T : Property, new() { public ChunkHeader Header { get; set; } public List properties; public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry) { properties = new List(); while (reader.BaseStream.Position < entry.Offset + entry.Size + 24) { var prop = new T(); prop.Read(reader); properties.Add(prop); } } public void WriteData(BinaryWriter writer) { foreach (var prop in properties) { prop.Write(writer); } } public void Merge(IMergable other) { properties.AddRange(((PropertyChunk)other).properties); } } public class PropGeneric : Property { public byte[] data; public override void Read(BinaryReader reader) { base.Read(reader); data = reader.ReadBytes(length); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(data); } } public class PropBool : Property { public bool value; public override void Read(BinaryReader reader) { base.Read(reader); value = reader.ReadInt32() != 0; } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(value ? 1 : 0); } } public class PropInt : Property { public int value; public override void Read(BinaryReader reader) { base.Read(reader); value = reader.ReadInt32(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(value); } } public class PropLabel : Property { public string value; public override void Read(BinaryReader reader) { base.Read(reader); value = reader.ReadNullString(length); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.WriteNullString(value, length); } } public class PropString : Property { public int stringLength; public string value; public override void Read(BinaryReader reader) { base.Read(reader); stringLength = reader.ReadInt32(); value = reader.ReadNullString(stringLength); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(stringLength); writer.WriteNullString(value, stringLength); } } public class PropFloat : Property { public float value; public override void Read(BinaryReader reader) { base.Read(reader); value = reader.ReadSingle(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(value); } } public class PropVector : Property { public Vector3 value; public override void Read(BinaryReader reader) { base.Read(reader); value = reader.ReadVec3(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.WriteVec3(value); } } public class PropRenderType : Property { public enum Mode { Normal, NotRendered, Unlit, EditorOnly, CoronaOnly, } public Mode mode; public override void Read(BinaryReader reader) { base.Read(reader); mode = (Mode)reader.ReadUInt32(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write((uint)mode); } } public class PropSlayResult : Property { public enum Effect { Normal, NoEffect, Terminate, Destroy, } public Effect effect; public override void Read(BinaryReader reader) { base.Read(reader); effect = (Effect)reader.ReadUInt32(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write((uint)effect); } } public class PropInventoryType : Property { public enum Slot { Junk, Item, Weapon, } public Slot type; public override void Read(BinaryReader reader) { base.Read(reader); type = (Slot)reader.ReadUInt32(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write((uint)type); } } public class PropCollisionType : Property { public bool Bounce; public bool DestroyOnImpact; public bool SlayOnImpact; public bool NoCollisionSound; public bool NoResult; public bool FullCollisionSound; public override void Read(BinaryReader reader) { base.Read(reader); var flags = reader.ReadUInt32(); Bounce = (flags & 0x1) != 0; DestroyOnImpact = (flags & (0x1 << 1)) != 0; SlayOnImpact = (flags & (0x1 << 2)) != 0; NoCollisionSound = (flags & (0x1 << 3)) != 0; NoResult = (flags & (0x1 << 4)) != 0; FullCollisionSound = (flags & (0x1 << 5)) != 0; } public override void Write(BinaryWriter writer) { base.Write(writer); var flags = 0u; if (Bounce) flags += 1; if (DestroyOnImpact) flags += 2; if (SlayOnImpact) flags += 4; if (NoCollisionSound) flags += 8; if (NoResult) flags += 16; if (FullCollisionSound) flags += 32; writer.Write(flags); } } public class PropPosition : Property { public Vector3 Location; public Vector3 Rotation; public override void Read(BinaryReader reader) { base.Read(reader); Location = reader.ReadVec3(); reader.ReadBytes(4); // Runtime Cell/Hint in editor Rotation = reader.ReadRotation(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.WriteVec3(Location); writer.Write(new byte[4]); writer.WriteRotation(Rotation); } } public class PropLight : Property { public float Brightness; public Vector3 Offset; public float Radius; public float InnerRadius; public bool QuadLit; public override void Read(BinaryReader reader) { base.Read(reader); Brightness = reader.ReadSingle(); Offset = reader.ReadVec3(); Radius = reader.ReadSingle(); QuadLit = reader.ReadBoolean(); reader.ReadBytes(3); InnerRadius = reader.ReadSingle(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(Brightness); writer.WriteVec3(Offset); writer.Write(Radius); writer.Write(QuadLit); writer.Write(new byte[3]); writer.Write(InnerRadius); } } public class PropAnimLight : Property { public enum AnimMode { FlipMinMax, SlideSmoothly, Random, MinBrightness, MaxBrightness, ZeroBrightness, SmoothlyBrighten, SmoothlyDim, RandomButCoherent, FlickerMinMax, } // Standard light props public float Brightness; public Vector3 Offset; public float Radius; public float InnerRadius; public bool QuadLit; public bool Dynamic; // Animation public AnimMode Mode; public int MsToBrighten; public int MsToDim; public float MinBrightness; public float MaxBrightness; // Start state public float CurrentBrightness; public bool Rising; public int Timer; public bool Inactive; // World rep info public bool Refresh; // Not relevant to us. It's used to tell dromed it needs to relight public ushort LightTableMapIndex; public ushort LightTableLightIndex; public ushort CellsReached; private int _unknown; public override void Read(BinaryReader reader) { base.Read(reader); Brightness = reader.ReadSingle(); Offset = reader.ReadVec3(); Refresh = reader.ReadBoolean(); reader.ReadBytes(3); LightTableMapIndex = reader.ReadUInt16(); CellsReached = reader.ReadUInt16(); LightTableLightIndex = reader.ReadUInt16(); Mode = (AnimMode)reader.ReadUInt16(); MsToBrighten = reader.ReadInt32(); MsToDim = reader.ReadInt32(); MinBrightness = reader.ReadSingle(); MaxBrightness = reader.ReadSingle(); CurrentBrightness = reader.ReadSingle(); Rising = reader.ReadBoolean(); reader.ReadBytes(3); Timer = reader.ReadInt32(); Inactive = reader.ReadBoolean(); reader.ReadBytes(3); Radius = reader.ReadSingle(); _unknown = reader.ReadInt32(); QuadLit = reader.ReadBoolean(); reader.ReadBytes(3); InnerRadius = reader.ReadSingle(); Dynamic = reader.ReadBoolean(); reader.ReadBytes(3); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(Brightness); writer.WriteVec3(Offset); writer.Write(Refresh); writer.Write(new byte[3]); writer.Write(LightTableMapIndex); writer.Write(CellsReached); writer.Write(LightTableLightIndex); writer.Write((ushort)Mode); writer.Write(MsToBrighten); writer.Write(MsToDim); writer.Write(MinBrightness); writer.Write(MaxBrightness); writer.Write(CurrentBrightness); writer.Write(Rising); writer.Write(new byte[3]); writer.Write(Timer); writer.Write(Inactive); writer.Write(new byte[3]); writer.Write(Radius); writer.Write(_unknown); writer.Write(QuadLit); writer.Write(new byte[3]); writer.Write(InnerRadius); writer.Write(Dynamic); writer.Write(new byte[3]); } } public class PropLightColor : Property { public float Hue; public float Saturation; public override void Read(BinaryReader reader) { base.Read(reader); Hue = reader.ReadSingle(); Saturation = reader.ReadSingle(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(Hue); writer.Write(Saturation); } } public class PropSpotlight : Property { public float InnerAngle; public float OuterAngle; public override void Read(BinaryReader reader) { base.Read(reader); InnerAngle = reader.ReadSingle(); OuterAngle = reader.ReadSingle(); reader.ReadBytes(4); // Z is unused } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(InnerAngle); writer.Write(OuterAngle); writer.Write(new byte[4]); } } public class PropSpotlightAndAmbient : Property { public float InnerAngle; public float OuterAngle; public float SpotBrightness; public override void Read(BinaryReader reader) { base.Read(reader); InnerAngle = reader.ReadSingle(); OuterAngle = reader.ReadSingle(); SpotBrightness = reader.ReadSingle(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(InnerAngle); writer.Write(OuterAngle); writer.Write(SpotBrightness); } } public class PropJointPos : Property { public float[] Positions; public override void Read(BinaryReader reader) { base.Read(reader); Positions = new float[6]; for (var i = 0; i < 6; i++) { Positions[i] = reader.ReadSingle(); } } public override void Write(BinaryWriter writer) { base.Write(writer); foreach (var position in Positions) { writer.Write(position); } } }