refactor into projects

This commit is contained in:
bird_egop
2026-05-17 15:40:16 +03:00
parent a5a14ec4ed
commit 28d10f3ffa
25 changed files with 77 additions and 27 deletions
+14
View File
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\NResLib\NResLib.csproj" />
</ItemGroup>
</Project>
+260
View File
@@ -0,0 +1,260 @@
using Common;
namespace FxidLib;
/// <summary>
/// Static reader methods for parsing FXID effect definition structures from binary streams.
/// </summary>
public static class FxidReader
{
/// <summary>
/// Reads a Vector3 (3 floats: X, Y, Z) from the binary stream.
/// </summary>
public static Vector3 ReadVector3(BinaryReader br)
{
float x = br.ReadSingle();
float y = br.ReadSingle();
float z = br.ReadSingle();
return new Vector3(x, y, z);
}
/// <summary>
/// Reads the 60-byte effect header from the binary stream.
/// </summary>
public static EffectHeader ReadEffectHeader(BinaryReader br)
{
EffectHeader h;
h.ComponentCount = br.ReadUInt32();
h.TimeMode = br.ReadUInt32();
h.Duration = br.ReadSingle();
h.PhaseJitter = br.ReadSingle();
h.Flags = br.ReadUInt32();
h.SettingsId = br.ReadUInt32();
h.RandShiftX = br.ReadSingle();
h.RandShiftY = br.ReadSingle();
h.RandShiftZ = br.ReadSingle();
h.PivotX = br.ReadSingle();
h.PivotY = br.ReadSingle();
h.PivotZ = br.ReadSingle();
h.ScaleX = br.ReadSingle();
h.ScaleY = br.ReadSingle();
h.ScaleZ = br.ReadSingle();
return h;
}
/// <summary>
/// Reads a BillboardComponentData (type 1) from the binary stream.
/// </summary>
public static BillboardComponentData ReadBillboardComponent(BinaryReader br, uint typeAndFlags)
{
BillboardComponentData d;
d.TypeAndFlags = typeAndFlags;
d.Unknown04 = br.ReadSingle();
d.ScalarAMin = br.ReadSingle();
d.ScalarAMax = br.ReadSingle();
d.ScalarAExp = br.ReadSingle();
d.ActiveTimeStart = br.ReadSingle();
d.ActiveTimeEnd = br.ReadSingle();
d.SampleSpreadParam = br.ReadSingle();
d.Unknown20 = br.ReadUInt32();
d.PrimarySampleCount = br.ReadUInt32();
d.SecondarySampleCount = br.ReadUInt32();
d.ExtentVec0 = ReadVector3(br);
d.ExtentVec1 = ReadVector3(br);
d.ExtentVec2 = ReadVector3(br);
d.ExponentTriplet0 = ReadVector3(br);
d.RadiusTriplet0 = ReadVector3(br);
d.RadiusTriplet1 = ReadVector3(br);
d.RadiusTriplet2 = ReadVector3(br);
d.ExponentTriplet1 = ReadVector3(br);
d.NoiseAmplitude = br.ReadSingle();
d.Reserved = br.ReadBytes(0x50);
return d;
}
/// <summary>
/// Reads a SoundComponentData (type 2) from the binary stream.
/// </summary>
public static SoundComponentData ReadSoundComponent(BinaryReader br, uint typeAndFlags)
{
SoundComponentData d;
d.TypeAndFlags = typeAndFlags;
d.PlayMode = br.ReadUInt32();
d.StartTime = br.ReadSingle();
d.EndTime = br.ReadSingle();
d.Pos0 = ReadVector3(br);
d.Pos1 = ReadVector3(br);
d.Offset0 = ReadVector3(br);
d.Offset1 = ReadVector3(br);
d.Scalar0Min = br.ReadSingle();
d.Scalar0Max = br.ReadSingle();
d.Scalar1Min = br.ReadSingle();
d.Scalar1Max = br.ReadSingle();
d.SoundFlags = br.ReadUInt32();
d.SoundNameAndReserved = br.ReadBytes(0x40);
return d;
}
/// <summary>
/// Reads an AnimParticleComponentData (type 3) from the binary stream.
/// </summary>
public static AnimParticleComponentData ReadAnimParticleComponent(BinaryReader br, uint typeAndFlags)
{
AnimParticleComponentData d;
d.TypeAndFlags = typeAndFlags;
d.Unknown04 = br.ReadSingle();
d.ScalarAMin = br.ReadSingle();
d.ScalarAMax = br.ReadSingle();
d.ScalarAExp = br.ReadSingle();
d.ActiveTimeStart = br.ReadSingle();
d.ActiveTimeEnd = br.ReadSingle();
d.SampleSpreadParam = br.ReadSingle();
d.Unknown20 = br.ReadUInt32();
d.PrimarySampleCount = br.ReadUInt32();
d.SecondarySampleCount = br.ReadUInt32();
d.ExtentVec0 = ReadVector3(br);
d.ExtentVec1 = ReadVector3(br);
d.ExtentVec2 = ReadVector3(br);
d.ExponentTriplet0 = ReadVector3(br);
d.RadiusTriplet0 = ReadVector3(br);
d.RadiusTriplet1 = ReadVector3(br);
d.RadiusTriplet2 = ReadVector3(br);
d.ExponentTriplet1 = ReadVector3(br);
d.NoiseAmplitude = br.ReadSingle();
d.Reserved = br.ReadBytes(0x38);
return d;
}
/// <summary>
/// Reads an AnimBillboardComponentData (type 4) from the binary stream.
/// </summary>
public static AnimBillboardComponentData ReadAnimBillboardComponent(BinaryReader br, uint typeAndFlags)
{
AnimBillboardComponentData d;
d.TypeAndFlags = typeAndFlags;
d.Unknown04 = br.ReadSingle();
d.ScalarAMin = br.ReadSingle();
d.ScalarAMax = br.ReadSingle();
d.ScalarAExp = br.ReadSingle();
d.ActiveTimeStart = br.ReadSingle();
d.ActiveTimeEnd = br.ReadSingle();
d.SampleSpreadParam = br.ReadSingle();
d.Unknown20 = br.ReadUInt32();
d.PrimarySampleCount = br.ReadUInt32();
d.SecondarySampleCount = br.ReadUInt32();
d.ExtentVec0 = ReadVector3(br);
d.ExtentVec1 = ReadVector3(br);
d.ExtentVec2 = ReadVector3(br);
d.ExponentTriplet0 = ReadVector3(br);
d.RadiusTriplet0 = ReadVector3(br);
d.RadiusTriplet1 = ReadVector3(br);
d.RadiusTriplet2 = ReadVector3(br);
d.ExponentTriplet1 = ReadVector3(br);
d.NoiseAmplitude = br.ReadSingle();
d.Reserved = br.ReadBytes(0x3C);
return d;
}
/// <summary>
/// Reads a TrailComponentData (type 5) from the binary stream.
/// </summary>
public static TrailComponentData ReadTrailComponent(BinaryReader br, uint typeAndFlags)
{
TrailComponentData d;
d.TypeAndFlags = typeAndFlags;
d.Unknown04To10 = br.ReadBytes(0x10);
d.SegmentCount = br.ReadUInt32();
d.Param0 = br.ReadSingle();
d.Param1 = br.ReadSingle();
d.Unknown20 = br.ReadUInt32();
d.Unknown24 = br.ReadUInt32();
d.ActiveTimeStart = br.ReadSingle();
d.ActiveTimeEnd = br.ReadSingle();
d.TextureNameAndReserved = br.ReadBytes(0x40);
return d;
}
/// <summary>
/// Reads a PointComponentData (type 6) from the binary stream.
/// Note: Point components have no payload beyond the typeAndFlags header.
/// </summary>
public static PointComponentData ReadPointComponent(uint typeAndFlags)
{
PointComponentData d;
d.TypeAndFlags = typeAndFlags;
return d;
}
/// <summary>
/// Reads a PlaneComponentData (type 7) from the binary stream.
/// </summary>
public static PlaneComponentData ReadPlaneComponent(BinaryReader br, uint typeAndFlags)
{
PlaneComponentData d;
d.Base = ReadAnimParticleComponent(br, typeAndFlags);
d.ExtraPlaneParam0 = br.ReadUInt32();
d.ExtraPlaneParam1 = br.ReadUInt32();
return d;
}
/// <summary>
/// Reads a ModelComponentData (type 8) from the binary stream.
/// </summary>
public static ModelComponentData ReadModelComponent(BinaryReader br, uint typeAndFlags)
{
ModelComponentData d;
d.TypeAndFlags = typeAndFlags;
d.Unk04 = br.ReadBytes(0x14);
d.ActiveTimeStart = br.ReadSingle();
d.ActiveTimeEnd = br.ReadSingle();
d.Unknown20 = br.ReadUInt32();
d.InstanceCount = br.ReadUInt32();
d.BasePos = ReadVector3(br);
d.OffsetPos = ReadVector3(br);
d.ScatterExtent = ReadVector3(br);
d.Axis0 = ReadVector3(br);
d.Axis1 = ReadVector3(br);
d.Axis2 = ReadVector3(br);
d.Reserved70 = br.ReadBytes(0x18);
d.RadiusTriplet0 = ReadVector3(br);
d.RadiusTriplet1 = ReadVector3(br);
d.ReservedA0 = br.ReadBytes(0x18);
d.TextureNameAndFlags = br.ReadBytes(0x40);
return d;
}
/// <summary>
/// Reads an AnimModelComponentData (type 9) from the binary stream.
/// </summary>
public static AnimModelComponentData ReadAnimModelComponent(BinaryReader br, uint typeAndFlags)
{
AnimModelComponentData d;
d.TypeAndFlags = typeAndFlags;
d.AnimSpeed = br.ReadSingle();
d.MinTime = br.ReadSingle();
d.MaxTime = br.ReadSingle();
d.Exponent = br.ReadSingle();
d.Reserved14 = br.ReadBytes(0x14);
d.DirVec0 = ReadVector3(br);
d.Reserved34 = br.ReadBytes(0x0C);
d.RadiusTriplet0 = ReadVector3(br);
d.DirVec1 = ReadVector3(br);
d.RadiusTriplet1 = ReadVector3(br);
d.ExtentVec0 = ReadVector3(br);
d.ExtentVec1 = ReadVector3(br);
d.Reserved7C = br.ReadBytes(0x0C);
d.TextureNameAndFlags = br.ReadBytes(0x48);
return d;
}
/// <summary>
/// Reads a CubeComponentData (type 10) from the binary stream.
/// </summary>
public static CubeComponentData ReadCubeComponent(BinaryReader br, uint typeAndFlags)
{
CubeComponentData d;
d.Base = ReadAnimBillboardComponent(br, typeAndFlags);
d.ExtraCubeParam0 = br.ReadUInt32();
return d;
}
}
+258
View File
@@ -0,0 +1,258 @@
using Common;
namespace FxidLib;
/// <summary>
/// Effect-level header at the start of each FXID file (60 bytes total).
/// Parsed from CEffect_InitFromDef: defines component count, global duration/flags,
/// some unknown control fields, and the uniform scale vector applied to the effect.
/// </summary>
public record struct EffectHeader
{
/// <summary>FXID payload offset 0x00: command count.</summary>
public uint ComponentCount;
/// <summary>FXID payload offset 0x04: time mode used to compute effect alpha.</summary>
public uint TimeMode;
/// <summary>FXID payload offset 0x08: effect duration in seconds.</summary>
public float Duration;
/// <summary>FXID payload offset 0x0C: random phase shift amplitude.</summary>
public float PhaseJitter;
/// <summary>FXID payload offset 0x10: effect behavior flags.</summary>
public uint Flags;
/// <summary>FXID payload offset 0x14: settings/profile id.</summary>
public uint SettingsId;
/// <summary>FXID payload offset 0x18: random spatial shift X.</summary>
public float RandShiftX;
/// <summary>FXID payload offset 0x1C: random spatial shift Y.</summary>
public float RandShiftY;
/// <summary>FXID payload offset 0x20: random spatial shift Z.</summary>
public float RandShiftZ;
/// <summary>FXID payload offset 0x24: local pivot X.</summary>
public float PivotX;
/// <summary>FXID payload offset 0x28: local pivot Y.</summary>
public float PivotY;
/// <summary>FXID payload offset 0x2C: local pivot Z.</summary>
public float PivotZ;
/// <summary>FXID payload offset 0x30: base scale X.</summary>
public float ScaleX;
/// <summary>FXID payload offset 0x34: base scale Y.</summary>
public float ScaleY;
/// <summary>FXID payload offset 0x38: base scale Z.</summary>
public float ScaleZ;
}
/// <summary>
/// Shared on-disk definition layout for billboard-style components (type 1).
/// Used by CBillboardComponent_Initialize/Update/Render to drive size/color/alpha
/// curves and sample scattering within a 3D extent volume.
/// </summary>
public record struct BillboardComponentData
{
public uint TypeAndFlags; // type (low byte) and flags as seen in CEffect_InitFromDef
public float Unknown04; // mode / flag-like float, semantics not fully clear
public float ScalarAMin; // base scalar A (e.g. base radius)
public float ScalarAMax; // max scalar A
public float ScalarAExp; // exponent applied to scalar A curve
public float ActiveTimeStart; // activation window start (seconds)
public float ActiveTimeEnd; // activation window end (seconds)
public float SampleSpreadParam; // extra param used when scattering samples
public uint Unknown20; // used as integer param in billboard code, exact meaning unknown
public uint PrimarySampleCount; // number of samples along primary axis
public uint SecondarySampleCount; // number of samples along secondary axis
public Vector3 ExtentVec0; // base extent/origin vector
public Vector3 ExtentVec1; // extent center / offset
public Vector3 ExtentVec2; // extent size used for random boxing
public Vector3 ExponentTriplet0;// exponent triplet for size/color curve
public Vector3 RadiusTriplet0; // radius curve key 0
public Vector3 RadiusTriplet1; // radius curve key 1
public Vector3 RadiusTriplet2; // radius curve key 2
public Vector3 ExponentTriplet1;// second exponent triplet (e.g. alpha curve)
public float NoiseAmplitude; // per-sample noise amplitude
public byte[] Reserved; // 0x50-byte tail, currently not touched by billboard code
}
/// <summary>
/// 3D sound component definition (type 2).
/// Used by CSoundComponent_Initialize/Update to drive positional audio, playback
/// window, and scalar ranges (e.g. volume / pitch), plus a 0x40-byte sound name tail.
/// </summary>
public record struct SoundComponentData
{
public uint TypeAndFlags; // component type and flags
public uint PlayMode; // playback mode (looping, one-shot, etc.)
public float StartTime; // playback window start (seconds)
public float EndTime; // playback window end (seconds)
public Vector3 Pos0; // base 3D position or path start
public Vector3 Pos1; // secondary position / path end
public Vector3 Offset0; // random offset range 0
public Vector3 Offset1; // random offset range 1
public float Scalar0Min; // scalar range 0 min (e.g. volume)
public float Scalar0Max; // scalar range 0 max
public float Scalar1Min; // scalar range 1 min (e.g. pitch)
public float Scalar1Max; // scalar range 1 max
public uint SoundFlags; // misc sound control flags
public byte[] SoundNameAndReserved; // 0x40-byte tail; sound name plus padding/unused
}
/// <summary>
/// Animated particle component definition (type 3).
/// Prefix layout matches BillboardComponentData and is used to allocate a grid of
/// particle objects; the 0x38-byte tail is passed into CFxManager_LoadTexture.
/// </summary>
public record struct AnimParticleComponentData
{
public uint TypeAndFlags; // type (low byte) and flags as seen in CEffect_InitFromDef
public float Unknown04; // mode / flag-like float, semantics not fully clear
public float ScalarAMin; // base scalar A (e.g. base radius)
public float ScalarAMax; // max scalar A
public float ScalarAExp; // exponent applied to scalar A curve
public float ActiveTimeStart; // activation window start (seconds)
public float ActiveTimeEnd; // activation window end (seconds)
public float SampleSpreadParam; // extra param used when scattering particles
public uint Unknown20; // used as integer param in anim particle code, exact meaning unknown
public uint PrimarySampleCount; // number of particles along primary axis
public uint SecondarySampleCount; // number of particles along secondary axis
public Vector3 ExtentVec0; // base extent/origin vector
public Vector3 ExtentVec1; // extent center / offset
public Vector3 ExtentVec2; // extent size used for random boxing
public Vector3 ExponentTriplet0;// exponent triplet for size/color curve
public Vector3 RadiusTriplet0; // radius curve key 0
public Vector3 RadiusTriplet1; // radius curve key 1
public Vector3 RadiusTriplet2; // radius curve key 2
public Vector3 ExponentTriplet1;// second exponent triplet (e.g. alpha curve)
public float NoiseAmplitude; // per-particle noise amplitude
public byte[] Reserved; // 0x38-byte tail; forwarded to CFxManager_LoadTexture unchanged
}
/// <summary>
/// Animated billboard component definition (type 4).
/// Shares the same prefix layout as BillboardComponentData, including extents and
/// radius/exponent triplets, but uses a 0x3C-byte tail passed to CFxManager_LoadTexture.
/// </summary>
public record struct AnimBillboardComponentData
{
public uint TypeAndFlags; // type (low byte) and flags as seen in CEffect_InitFromDef
public float Unknown04; // mode / flag-like float, semantics not fully clear
public float ScalarAMin; // base scalar A (e.g. base radius)
public float ScalarAMax; // max scalar A
public float ScalarAExp; // exponent applied to scalar A curve
public float ActiveTimeStart; // activation window start (seconds)
public float ActiveTimeEnd; // activation window end (seconds)
public float SampleSpreadParam; // extra param used when scattering animated billboards
public uint Unknown20; // used as integer param in anim billboard code, exact meaning unknown
public uint PrimarySampleCount; // number of samples along primary axis
public uint SecondarySampleCount; // number of samples along secondary axis
public Vector3 ExtentVec0; // base extent/origin vector
public Vector3 ExtentVec1; // extent center / offset
public Vector3 ExtentVec2; // extent size used for random boxing
public Vector3 ExponentTriplet0;// exponent triplet for size/color curve
public Vector3 RadiusTriplet0; // radius curve key 0
public Vector3 RadiusTriplet1; // radius curve key 1
public Vector3 RadiusTriplet2; // radius curve key 2
public Vector3 ExponentTriplet1;// second exponent triplet (e.g. alpha curve)
public float NoiseAmplitude; // per-sample noise amplitude
public byte[] Reserved; // 0x3C-byte tail; forwarded to CFxManager_LoadTexture unchanged
}
/// <summary>
/// Compact definition for trail / ribbon components (type 5).
/// CTrailComponent_Initialize interprets this as segment count, width/alpha/UV
/// ranges, timing, and a shared texture name at +0x30.
/// </summary>
public record struct TrailComponentData
{
public uint TypeAndFlags; // component type and flags
public byte[] Unknown04To10; // 0x10 bytes at +4..+0x13, used only indirectly; types unknown
public uint SegmentCount; // number of trail segments (particles)
public float Param0; // first width/alpha/UV control value (start)
public float Param1; // second width/alpha/UV control value (end)
public uint Unknown20; // extra integer parameter, purpose unknown
public uint Unknown24; // extra integer parameter, purpose unknown
public float ActiveTimeStart; // trail activation start time (>= 0)
public float ActiveTimeEnd; // trail activation end time
public byte[] TextureNameAndReserved; // 0x40-byte tail containing texture name and padding/flags
}
/// <summary>
/// Simple point component definition (type 6).
/// Definition block is just the 4-byte typeAndFlags header; no extra data on disk.
/// </summary>
public record struct PointComponentData
{
public uint TypeAndFlags; // component type and flags; definition block has no payload
}
/// <summary>
/// Plane component definition (type 7).
/// Shares the same 0xC8-byte prefix layout as AnimParticleComponentData (type 3),
/// followed by two dwords of plane-specific data.
/// </summary>
public record struct PlaneComponentData
{
public AnimParticleComponentData Base; // shared 0xC8-byte prefix: time window, sample counts, extents, curves
public uint ExtraPlaneParam0; // plane-specific parameter, semantics not yet reversed
public uint ExtraPlaneParam1; // plane-specific parameter, semantics not yet reversed
}
/// <summary>
/// Static model component definition (type 8).
/// Layout fully matches the IDA typedef used by CModelComponent_Initialize:
/// time window, instance count, spatial extents/axes, radius triplets, and a
/// 0x40-byte texture name tail.
/// </summary>
public record struct ModelComponentData
{
public uint TypeAndFlags; // component type and flags
public byte[] Unk04; // 0x14-byte blob at +0x04..+0x17, purpose unclear
public float ActiveTimeStart; // activation window start (seconds), +0x18
public float ActiveTimeEnd; // activation window end (seconds), +0x1C
public uint Unknown20; // extra flags/int parameter at +0x20
public uint InstanceCount; // number of model instances to spawn at +0x24
public Vector3 BasePos; // base position of the emitter / origin, +0x28
public Vector3 OffsetPos; // positional offset applied per-instance, +0x34
public Vector3 ScatterExtent; // extent volume used for random scattering, +0x40
public Vector3 Axis0; // local axis 0 (orientation / shape), +0x4C
public Vector3 Axis1; // local axis 1 (orientation / shape), +0x58
public Vector3 Axis2; // local axis 2 (orientation / shape), +0x64
public byte[] Reserved70; // 0x18 bytes at +0x70..+0x87, not directly used
public Vector3 RadiusTriplet0; // radius / extent triplet 0 at +0x88
public Vector3 RadiusTriplet1; // radius / extent triplet 1 at +0x94
public byte[] ReservedA0; // 0x18 bytes at +0xA0..+0xB7, not directly used
public byte[] TextureNameAndFlags; // 0x40-byte tail at +0xB8: texture name + padding/flags
}
/// <summary>
/// Animated model component definition (type 9).
/// Layout derived from CAnimModelComponent_Initialize: time params, direction vectors,
/// radius triplets, extent vectors, and a 0x48-byte texture name tail.
/// </summary>
public record struct AnimModelComponentData
{
public uint TypeAndFlags; // component type and flags
public float AnimSpeed; // animation speed multiplier at +0x04
public float MinTime; // activation window start (clamped >= 0) at +0x08
public float MaxTime; // activation window end at +0x0C
public float Exponent; // exponent for time interpolation at +0x10
public byte[] Reserved14; // 0x14 bytes at +0x14..+0x27, padding
public Vector3 DirVec0; // normalized direction vector 0 at +0x28
public byte[] Reserved34; // 0x0C bytes at +0x34..+0x3F, padding
public Vector3 RadiusTriplet0; // radius triplet 0 at +0x40
public Vector3 DirVec1; // normalized direction vector 1 at +0x4C
public Vector3 RadiusTriplet1; // radius triplet 1 at +0x58
public Vector3 ExtentVec0; // extent vector 0 at +0x64
public Vector3 ExtentVec1; // extent vector 1 at +0x70
public byte[] Reserved7C; // 0x0C bytes at +0x7C..+0x87, padding
public byte[] TextureNameAndFlags; // 0x48-byte tail at +0x88: texture/model name + padding
}
/// <summary>
/// Cube component definition (type 10).
/// Shares the same 0xCC-byte prefix layout as AnimBillboardComponentData (type 4),
/// followed by one dword of cube-specific data.
/// </summary>
public record struct CubeComponentData
{
public AnimBillboardComponentData Base; // shared 0xCC-byte prefix: billboard-style time window, extents, curves
public uint ExtraCubeParam0; // cube-specific parameter, semantics not yet reversed
}