mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-09-17 22:57:24 +08:00
2312 lines
64 KiB
C#
2312 lines
64 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using TC = System.ComponentModel.TypeConverterAttribute;
|
|
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
|
|
|
namespace CodeWalker.GameFiles
|
|
{
|
|
[TC(typeof(EXP))] public class MrfFile : GameFile, PackedFile
|
|
{
|
|
public byte[] RawFileData { get; set; }
|
|
public uint Magic { get; set; } = 0x45566F4D; // 'MoVE'
|
|
public uint Version { get; set; } = 2;
|
|
public uint HeaderUnk1 { get; set; } = 0;
|
|
public uint HeaderUnk2 { get; set; } = 0;
|
|
public uint HeaderUnk3 { get; set; } = 0;
|
|
public uint DataLength { get; set; }
|
|
public uint FlagsCount { get; set; }
|
|
public uint Unk1_Count { get; set; }
|
|
public uint Unk2_Count { get; set; }
|
|
public uint Unk3_Count { get; set; }
|
|
|
|
public MrfStructHeaderUnk1[] Unk1_Items { get; set; }
|
|
public MrfStructHeaderUnk2[] Unk2_Items { get; set; }
|
|
public MrfStructHeaderUnk3[] Unk3_Items { get; set; }
|
|
public byte[] FlagsItems { get; set; }
|
|
|
|
public MrfNode[] AllNodes { get; set; }
|
|
public MrfNode RootNode { get; set; }
|
|
|
|
public MrfFile() : base(null, GameFileType.Mrf)
|
|
{
|
|
}
|
|
|
|
public MrfFile(RpfFileEntry entry) : base(entry, GameFileType.Mrf)
|
|
{
|
|
RpfFileEntry = entry;
|
|
}
|
|
|
|
public void Load(byte[] data, RpfFileEntry entry)
|
|
{
|
|
RawFileData = data;
|
|
if (entry != null)
|
|
{
|
|
RpfFileEntry = entry;
|
|
Name = entry.Name;
|
|
}
|
|
|
|
using (MemoryStream ms = new MemoryStream(data))
|
|
{
|
|
DataReader r = new DataReader(ms, Endianess.LittleEndian);
|
|
|
|
Read(r);
|
|
};
|
|
}
|
|
|
|
public byte[] Save()
|
|
{
|
|
MemoryStream s = new MemoryStream();
|
|
DataWriter w = new DataWriter(s);
|
|
|
|
Write(w);
|
|
|
|
var buf = new byte[s.Length];
|
|
s.Position = 0;
|
|
s.Read(buf, 0, buf.Length);
|
|
return buf;
|
|
}
|
|
|
|
private void Write(DataWriter w)
|
|
{
|
|
if (Magic != 0x45566F4D || Version != 2 || HeaderUnk1 != 0 || HeaderUnk2 != 0)
|
|
throw new Exception("Failed to write MRF, header is invalid!");
|
|
|
|
w.Write(Magic);
|
|
w.Write(Version);
|
|
w.Write(HeaderUnk1);
|
|
w.Write(HeaderUnk2);
|
|
w.Write(HeaderUnk3);
|
|
w.Write(DataLength);
|
|
w.Write(FlagsCount);
|
|
|
|
// Unused in final game
|
|
w.Write(Unk1_Count);
|
|
|
|
if (Unk1_Count > 0)
|
|
{
|
|
foreach (var entry in Unk1_Items)
|
|
{
|
|
w.Write(entry.Size);
|
|
w.Write(entry.Bytes);
|
|
}
|
|
}
|
|
|
|
w.Write(Unk2_Count);
|
|
|
|
if (Unk2_Count > 0)
|
|
{
|
|
foreach (var entry in Unk2_Items)
|
|
{
|
|
w.Write(entry.Unk1);
|
|
w.Write(entry.Unk2);
|
|
}
|
|
}
|
|
|
|
w.Write(Unk3_Count);
|
|
|
|
if (Unk3_Count > 0)
|
|
{
|
|
foreach (var entry in Unk3_Items)
|
|
{
|
|
w.Write(entry.Unk1);
|
|
w.Write(entry.Unk2);
|
|
}
|
|
}
|
|
|
|
if (AllNodes != null)
|
|
{
|
|
foreach (var node in AllNodes)
|
|
node.Write(w);
|
|
}
|
|
|
|
for (int i = 0; i < FlagsCount; i++)
|
|
w.Write(FlagsItems[i]);
|
|
}
|
|
|
|
private void Read(DataReader r)
|
|
{
|
|
Magic = r.ReadUInt32(); // Should be 'MoVE'
|
|
Version = r.ReadUInt32(); // GTA5 = 2, RDR3 = 11
|
|
HeaderUnk1 = r.ReadUInt32(); // Should be 0
|
|
HeaderUnk2 = r.ReadUInt32();
|
|
HeaderUnk3 = r.ReadUInt32(); // Should be 0
|
|
DataLength = r.ReadUInt32();
|
|
FlagsCount = r.ReadUInt32();
|
|
|
|
if (Magic != 0x45566F4D || Version != 2 || HeaderUnk1 != 0 || HeaderUnk2 != 0)
|
|
throw new Exception("Failed to read MRF, header is invalid!");
|
|
|
|
// Unused in final game
|
|
Unk1_Count = r.ReadUInt32();
|
|
if (Unk1_Count > 0)
|
|
{
|
|
Unk1_Items = new MrfStructHeaderUnk1[Unk1_Count];
|
|
|
|
for (int i = 0; i < Unk1_Count; i++)
|
|
Unk1_Items[i] = new MrfStructHeaderUnk1(r);
|
|
}
|
|
|
|
Unk2_Count = r.ReadUInt32();
|
|
if (Unk2_Count > 0)
|
|
{
|
|
Unk2_Items = new MrfStructHeaderUnk2[Unk2_Count];
|
|
|
|
for (int i = 0; i < Unk2_Count; i++)
|
|
Unk2_Items[i] = new MrfStructHeaderUnk2(r);
|
|
}
|
|
|
|
Unk3_Count = r.ReadUInt32();
|
|
if (Unk3_Count > 0)
|
|
{
|
|
Unk3_Items = new MrfStructHeaderUnk3[Unk3_Count];
|
|
|
|
for (int i = 0; i < Unk3_Count; i++)
|
|
Unk3_Items[i] = new MrfStructHeaderUnk3(r);
|
|
}
|
|
|
|
var nodes = new List<MrfNode>();
|
|
|
|
while (true)
|
|
{
|
|
var index = nodes.Count;
|
|
var offset = (int)r.Position;
|
|
|
|
var node = ReadNode(r);
|
|
|
|
if (node == null) break;
|
|
|
|
node.FileIndex = index;
|
|
node.FileOffset = offset;
|
|
node.FileDataSize = ((int)r.Position) - offset;
|
|
|
|
nodes.Add(node);
|
|
}
|
|
|
|
AllNodes = nodes.ToArray();
|
|
|
|
if (FlagsCount != 0)
|
|
{
|
|
FlagsItems = new byte[FlagsCount];
|
|
|
|
for (int i = 0; i < FlagsCount; i++)
|
|
FlagsItems[i] = r.ReadByte();
|
|
}
|
|
|
|
|
|
BuildNodeHierarchy();
|
|
|
|
|
|
if (r.Position != r.Length)
|
|
throw new Exception($"Failed to read MRF ({r.Position} / {r.Length})");
|
|
}
|
|
|
|
private MrfNode ReadNode(DataReader r)
|
|
{
|
|
var startPos = r.Position;
|
|
var nodeType = (MrfNodeType)r.ReadUInt16();
|
|
r.Position = startPos;
|
|
|
|
if (nodeType <= MrfNodeType.None || nodeType >= MrfNodeType.Max)
|
|
{
|
|
if (r.Position != r.Length)//should only be at EOF
|
|
{ }
|
|
return null;
|
|
}
|
|
|
|
var node = CreateNode(nodeType);
|
|
|
|
node.Read(r);
|
|
|
|
return node;
|
|
}
|
|
|
|
private MrfNode CreateNode(MrfNodeType infoType)
|
|
{
|
|
switch (infoType)
|
|
{
|
|
case MrfNodeType.StateMachineClass:
|
|
return new MrfNodeStateMachineClass();
|
|
case MrfNodeType.Tail:
|
|
return new MrfNodeTail();
|
|
case MrfNodeType.InlinedStateMachine:
|
|
return new MrfNodeInlinedStateMachine();
|
|
case MrfNodeType.Unk4:
|
|
return new MrfNodeUnk4();
|
|
case MrfNodeType.Blend:
|
|
return new MrfNodeBlend();
|
|
case MrfNodeType.AddSubtract:
|
|
return new MrfNodeAddSubstract();
|
|
case MrfNodeType.Filter:
|
|
return new MrfNodeFilter();
|
|
case MrfNodeType.Unk8:
|
|
return new MrfNodeUnk8();
|
|
case MrfNodeType.Frame:
|
|
return new MrfNodeFrame();
|
|
case MrfNodeType.Unk10:
|
|
return new MrfNodeUnk10();
|
|
case MrfNodeType.BlendN:
|
|
return new MrfNodeBlendN();
|
|
case MrfNodeType.Clip:
|
|
return new MrfNodeClip();
|
|
case MrfNodeType.Unk17:
|
|
return new MrfNodeUnk17();
|
|
case MrfNodeType.Unk18:
|
|
return new MrfNodeUnk18();
|
|
case MrfNodeType.Expression:
|
|
return new MrfNodeExpression();
|
|
case MrfNodeType.Unk20:
|
|
return new MrfNodeUnk20();
|
|
case MrfNodeType.Proxy:
|
|
return new MrfNodeProxy();
|
|
case MrfNodeType.AddN:
|
|
return new MrfNodeAddN();
|
|
case MrfNodeType.Identity:
|
|
return new MrfNodeIdentity();
|
|
case MrfNodeType.Unk24:
|
|
return new MrfNodeUnk24();
|
|
case MrfNodeType.Unk25:
|
|
return new MrfNodeUnk25();
|
|
case MrfNodeType.MergeN:
|
|
return new MrfNodeMergeN();
|
|
case MrfNodeType.State:
|
|
return new MrfNodeState();
|
|
case MrfNodeType.Invalid:
|
|
return new MrfNodeInvalid();
|
|
case MrfNodeType.Unk29:
|
|
return new MrfNodeUnk29();
|
|
case MrfNodeType.SubNetworkClass:
|
|
return new MrfNodeSubNetworkClass();
|
|
case MrfNodeType.Unk31:
|
|
return new MrfNodeUnk31();
|
|
}
|
|
|
|
throw new Exception($"A handler for ({infoType}) mrf node type is not valid");
|
|
}
|
|
|
|
|
|
private int BuildNodeHierarchy(MrfNode node = null, int index = 0)
|
|
{
|
|
if (AllNodes == null) return 0;
|
|
if (AllNodes.Length <= index) return 0;
|
|
|
|
if (node == null)
|
|
{
|
|
var rlist = new List<MrfNode>();
|
|
for (int i = 0; i < AllNodes.Length; i++)
|
|
{
|
|
var rnode = AllNodes[i];
|
|
rlist.Add(rnode);
|
|
i += BuildNodeHierarchy(rnode, i);
|
|
}
|
|
|
|
var smlist = new List<MrfNodeStateMachineClass>();
|
|
var imlist = new List<MrfNodeInlinedStateMachine>();
|
|
var snlist = new List<MrfNodeState>();
|
|
foreach (var n in AllNodes)
|
|
{
|
|
if (n is MrfNodeStateMachineClass sm)
|
|
{
|
|
smlist.Add(sm);
|
|
if (sm.ChildNodes != null) for (int i = 0; i < sm.ChildNodes.Length; i++) if (sm.ChildNodes[i].NodeIndex != i)
|
|
{ }//sanity check - don't get here
|
|
}
|
|
if (n is MrfNodeInlinedStateMachine im)
|
|
{
|
|
imlist.Add(im);
|
|
if (im.ChildNodes != null) for (int i = 0; i < im.ChildNodes.Length; i++) if (im.ChildNodes[i].NodeIndex != i)
|
|
{ }//sanity check - don't get here
|
|
}
|
|
if (n is MrfNodeState sn)
|
|
{
|
|
snlist.Add(sn);
|
|
if (sn.ChildNodes != null) for (int i = 0; i < sn.ChildNodes.Length; i++) if (sn.ChildNodes[i].NodeIndex != i)
|
|
{ }//sanity check - don't get here
|
|
}
|
|
}
|
|
|
|
if (rlist.Count > 0)
|
|
{
|
|
RootNode = rlist[0];
|
|
}
|
|
if (rlist.Count != 1)
|
|
{ }//sanity check - don't get here
|
|
if (AllNodes.Length > 1000)
|
|
{ }
|
|
return 0;
|
|
}
|
|
|
|
if (node is MrfNodeStateBase snode)
|
|
{
|
|
var c = 0;
|
|
var clist = new List<MrfNode>();
|
|
int ccount = snode.StateChildCount;
|
|
if (ccount == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
for (int i = 0; i <= ccount; i++)
|
|
{
|
|
if ((i == ccount) && (node is MrfNodeState))
|
|
{ break; }
|
|
var cind = index + c + i + 1;
|
|
if (cind >= AllNodes.Length)
|
|
{
|
|
if (i != ccount)
|
|
{ }//don't get here (tried to continue past the end of the array!)
|
|
break;
|
|
}
|
|
var cnode = AllNodes[cind];
|
|
if (cnode is MrfNodeTail)
|
|
{
|
|
i--;
|
|
c++;
|
|
if (clist.Count > 0)
|
|
{
|
|
var prevnode = clist[clist.Count - 1];
|
|
if (prevnode is MrfNodeStateBase sprevnode)
|
|
{
|
|
if (sprevnode.TailNode != null)
|
|
{ }//don't get here (tail node was already assigned?!?)
|
|
sprevnode.TailNode = cnode;
|
|
if (clist.Count == ccount)
|
|
{ break; }//list is full, don't continue
|
|
}
|
|
else
|
|
{ }//don't get here (previous node isn't a state??)
|
|
}
|
|
else
|
|
{ }//don't get here (can't have tail without a previous node!)
|
|
continue;
|
|
}
|
|
else if (clist.Count == ccount)
|
|
{ break; }//this node isn't a tail, but the list is already full, so it must belong to another node
|
|
if (cnode.NodeIndex != i)
|
|
{ break; }//don't get here (node index mismatch!)
|
|
clist.Add(cnode);
|
|
c += BuildNodeHierarchy(cnode, cind);//recurse...
|
|
}
|
|
if (clist.Count != ccount)
|
|
{ }//don't get here (sanity check)
|
|
snode.ChildNodes = clist.ToArray();
|
|
return c + clist.Count;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unused node indexes by GTAV: 11, 12, 14, 16
|
|
// Exist in GTAV but not used in MRFs: 4, 8, 10, 17, 21, 22, 28, 29, 31, 32
|
|
public enum MrfNodeType : ushort
|
|
{
|
|
None = 0,
|
|
StateMachineClass = 1,
|
|
Tail = 2,
|
|
InlinedStateMachine = 3,
|
|
Unk4 = 4,
|
|
Blend = 5,
|
|
AddSubtract = 6,
|
|
Filter = 7,
|
|
Unk8 = 8,
|
|
Frame = 9,
|
|
Unk10 = 10,
|
|
BlendN = 13,
|
|
Clip = 15,
|
|
Unk17 = 17,
|
|
Unk18 = 18,
|
|
Expression = 19,
|
|
Unk20 = 20,
|
|
Proxy = 21,
|
|
AddN = 22,
|
|
Identity = 23,
|
|
Unk24 = 24,
|
|
Unk25 = 25,
|
|
MergeN = 26,
|
|
State = 27,
|
|
Invalid = 28,
|
|
Unk29 = 29,
|
|
SubNetworkClass = 30,
|
|
Unk31 = 31,
|
|
Max = 32
|
|
}
|
|
|
|
#region mrf node abstractions
|
|
|
|
[TC(typeof(EXP))] public abstract class MrfNode
|
|
{
|
|
public MrfNodeType NodeType { get; set; }
|
|
public ushort NodeIndex { get; set; } //index in the parent node
|
|
|
|
public int FileIndex { get; set; } //index in the file
|
|
public int FileOffset { get; set; } //offset in the file
|
|
public int FileDataSize { get; set; } //number of bytes read from the file (this node only)
|
|
|
|
public virtual void Read(DataReader r)
|
|
{
|
|
NodeType = (MrfNodeType)r.ReadUInt16();
|
|
NodeIndex = r.ReadUInt16();
|
|
}
|
|
|
|
public virtual void Write(DataWriter w)
|
|
{
|
|
w.Write((ushort)NodeType);
|
|
w.Write(NodeIndex);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return /* FileIndex.ToString() + ":" + FileOffset.ToString() + "+" + FileDataSize.ToString() + ": " + */
|
|
NodeType.ToString() + " - " + NodeIndex.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public abstract class MrfNodeNameFlagsBase : MrfNode
|
|
{
|
|
public MetaHash NameHash { get; set; }
|
|
public uint Flags { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
NameHash = new MetaHash(r.ReadUInt32());
|
|
Flags = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
w.Write(NameHash);
|
|
w.Write(Flags);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return base.ToString() + " - " + NameHash.ToString() + " - " + Flags.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public abstract class MrfNodeStateBase : MrfNode
|
|
{
|
|
public MetaHash NameHash { get; set; } // Used as an identifier for transitions
|
|
public uint StateByteCount { get; set; }
|
|
public uint StateUnk3 { get; set; }
|
|
public byte StateUnk4 { get; set; }
|
|
public byte StateUnk5 { get; set; }
|
|
public byte StateChildCount { get; set; }
|
|
public byte StateSectionCount { get; set; }
|
|
public uint StateUnk8 { get; set; }
|
|
public uint StateUnk9 { get; set; }
|
|
public uint StateFlags { get; set; }
|
|
|
|
public MrfNode[] ChildNodes { get; set; }
|
|
public MrfNode TailNode { get; set; }
|
|
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
NameHash = new MetaHash(r.ReadUInt32());
|
|
StateByteCount = r.ReadUInt32();
|
|
StateUnk3 = r.ReadUInt32();
|
|
StateUnk4 = r.ReadByte();
|
|
StateUnk5 = r.ReadByte();
|
|
StateChildCount = r.ReadByte();
|
|
StateSectionCount = r.ReadByte();
|
|
StateUnk8 = r.ReadUInt32();
|
|
StateUnk9 = r.ReadUInt32();
|
|
StateFlags = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
w.Write(NameHash);
|
|
w.Write(StateByteCount);
|
|
w.Write(StateUnk3);
|
|
w.Write(StateUnk4);
|
|
w.Write(StateUnk5);
|
|
w.Write(StateChildCount);
|
|
w.Write(StateSectionCount);
|
|
w.Write(StateUnk8);
|
|
w.Write(StateUnk9);
|
|
w.Write(StateFlags);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return base.ToString() + " - " + NameHash.ToString()
|
|
+ " - BC:" + StateByteCount.ToString()
|
|
+ " - CC:" + StateChildCount.ToString()
|
|
+ " - SC:" + StateSectionCount.ToString()
|
|
+ " - " + StateUnk3.ToString()
|
|
+ " - " + StateUnk4.ToString()
|
|
+ " - " + StateUnk5.ToString()
|
|
+ " - " + StateUnk8.ToString()
|
|
+ " - " + StateUnk9.ToString()
|
|
+ " - F:" + StateFlags.ToString();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[TC(typeof(EXP))] public abstract class MrfNodeValueBase : MrfNode
|
|
{
|
|
public MetaHash Value { get; set; }//maybe not an actual hash
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
Value = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
w.Write(Value);
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public abstract class MrfNodeBlendAddSubtractBase : MrfNodeNameFlagsBase
|
|
{
|
|
public int Unk1 { get; set; }
|
|
public int Unk2 { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
public MetaHash Unk4 { get; set; }
|
|
public MetaHash Unk5 { get; set; }
|
|
public MetaHash Unk6 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadInt32();
|
|
Unk2 = r.ReadInt32();
|
|
|
|
if ((Flags & 0x180000) == 0x80000)
|
|
Unk3 = r.ReadUInt32();
|
|
|
|
if ((Flags & 3) != 0)
|
|
Unk4 = new MetaHash(r.ReadUInt32());
|
|
|
|
switch ((Flags >> 2) & 3)
|
|
{
|
|
case 1:
|
|
Unk5 = new MetaHash(r.ReadUInt32());
|
|
Unk6 = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
case 2:
|
|
Unk6 = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
|
|
if ((Flags & 0x180000) == 0x80000)
|
|
w.Write(Unk3);
|
|
|
|
if ((Flags & 3) != 0)
|
|
w.Write(Unk4);
|
|
|
|
switch ((Flags >> 2) & 3)
|
|
{
|
|
case 1:
|
|
w.Write(Unk5);
|
|
w.Write(Unk6);
|
|
break;
|
|
case 2:
|
|
w.Write(Unk6);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public abstract class MrfNodeFilterUnkBase : MrfNodeNameFlagsBase
|
|
{
|
|
public uint Unk1 { get; set; }
|
|
public MetaHash Unk2 { get; set; }
|
|
public MetaHash Unk3 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
Unk2 = new MetaHash(r.ReadUInt32()); // Filter Frame dict hash
|
|
Unk3 = new MetaHash(r.ReadUInt32()); // Filter Frame name hash
|
|
break;
|
|
case 2:
|
|
Unk3 = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
w.Write(Unk2);
|
|
w.Write(Unk3);
|
|
break;
|
|
case 2:
|
|
w.Write(Unk3);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public abstract class MrfNodeNegativeBase : MrfNodeNameFlagsBase
|
|
{
|
|
public uint Unk1 { get; set; }
|
|
public byte[] Unk2 { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
public uint Unk4 { get; set; }
|
|
public uint Unk5 { get; set; }
|
|
public uint Unk6 { get; set; }
|
|
public int[] Unk7 { get; set; }
|
|
public MrfStructNegativeDataUnk7[] Unk7_Items { get; set; }
|
|
public uint[] Unk8 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
var unkTypeFlag1 = Flags & 3;
|
|
var unkTypeFlag2 = (Flags >> 2) & 3;
|
|
var unk7Count = Flags >> 26;
|
|
|
|
if ((Flags & 0x180000) == 0x80000)
|
|
Unk1 = r.ReadUInt32();
|
|
|
|
if (unkTypeFlag1 == 1)
|
|
Unk2 = r.ReadBytes(76); // Unused?
|
|
else if (unkTypeFlag1 == 2)
|
|
Unk3 = r.ReadUInt32();
|
|
|
|
if (unkTypeFlag2 == 1)
|
|
{
|
|
Unk4 = r.ReadUInt32();
|
|
Unk5 = r.ReadUInt32();
|
|
}
|
|
else if (unkTypeFlag2 == 2)
|
|
Unk6 = r.ReadUInt32();
|
|
|
|
if (unk7Count != 0)
|
|
{
|
|
Unk7 = new int[unk7Count];
|
|
|
|
for (int i = 0; i < unk7Count; i++)
|
|
Unk7[i] = r.ReadInt32();
|
|
}
|
|
|
|
var unk8Count = (((2 * unk7Count) | 7) + 1) >> 3;
|
|
|
|
if (unk8Count != 0)
|
|
{
|
|
Unk8 = new uint[unk8Count];
|
|
|
|
for (int i = 0; i < unk8Count; i++)
|
|
Unk8[i] = r.ReadUInt32();
|
|
}
|
|
|
|
if (unk7Count == 0)
|
|
return;
|
|
|
|
Unk7_Items = new MrfStructNegativeDataUnk7[unk7Count];
|
|
int iteration = 0;
|
|
|
|
for (int i = 0; i < unk7Count; i++)
|
|
{
|
|
var unk8Value = Unk8[iteration >> 3];
|
|
var unk7Flag = unk8Value >> (4 * (iteration & 7));
|
|
var unkTypeFlag3 = (unk7Flag >> 4) & 3;
|
|
|
|
var item = new MrfStructNegativeDataUnk7();
|
|
|
|
if ((unk7Flag & 3) != 0)
|
|
item.Unk1 = r.ReadUInt32();
|
|
|
|
if (unkTypeFlag3 == 1)
|
|
{
|
|
item.Unk2 = r.ReadUInt32();
|
|
item.Unk3 = r.ReadUInt32();
|
|
}
|
|
else if (unkTypeFlag3 == 2)
|
|
item.Unk4 = r.ReadUInt32();
|
|
|
|
Unk7_Items[i] = item;
|
|
|
|
iteration += 2;
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
var unkTypeFlag1 = Flags & 3;
|
|
var unkTypeFlag2 = (Flags >> 2) & 3;
|
|
var unk7Count = Flags >> 26;
|
|
|
|
if ((Flags & 0x180000) == 0x80000)
|
|
w.Write(Unk1);
|
|
|
|
if (unkTypeFlag1 == 1)
|
|
w.Write(Unk2);
|
|
else if (unkTypeFlag1 == 2)
|
|
w.Write(Unk3);
|
|
|
|
if (unkTypeFlag2 == 1)
|
|
{
|
|
w.Write(Unk4);
|
|
w.Write(Unk5);
|
|
}
|
|
else if (unkTypeFlag2 == 2)
|
|
w.Write(Unk6);
|
|
|
|
if (unk7Count > 0)
|
|
{
|
|
foreach (var value in Unk7)
|
|
w.Write(value);
|
|
}
|
|
|
|
var unk8Count = (((2 * unk7Count) | 7) + 1) >> 3;
|
|
|
|
if (unk8Count > 0)
|
|
{
|
|
foreach (var value in Unk8)
|
|
w.Write(value);
|
|
}
|
|
|
|
if (unk7Count == 0)
|
|
return;
|
|
|
|
int iteration = 0;
|
|
|
|
foreach (var item in Unk7_Items)
|
|
{
|
|
var unk8Value = Unk8[iteration >> 3];
|
|
var unk7Flag = unk8Value >> (4 * (iteration & 7));
|
|
var unkTypeFlag3 = (unk7Flag >> 4) & 3;
|
|
|
|
if ((unk7Flag & 3) != 0)
|
|
w.Write(item.Unk1);
|
|
|
|
if (unkTypeFlag3 == 1)
|
|
{
|
|
w.Write(item.Unk2);
|
|
w.Write(item.Unk3);
|
|
}
|
|
else if (unkTypeFlag3 == 2)
|
|
w.Write(item.Unk4);
|
|
|
|
iteration += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#region mrf node structs
|
|
|
|
public abstract class MrfStruct
|
|
{
|
|
public abstract void Write(DataWriter w);
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructHeaderUnk1 : MrfStruct
|
|
{
|
|
public uint Size { get; set; }
|
|
public byte[] Bytes { get; set; }
|
|
|
|
public MrfStructHeaderUnk1(DataReader r)
|
|
{
|
|
Size = r.ReadUInt32();
|
|
Bytes = r.ReadBytes((int)Size);
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Size);
|
|
w.Write(Bytes);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Size.ToString() + " bytes";
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructHeaderUnk2 : MrfStruct
|
|
{
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
|
|
public MrfStructHeaderUnk2(DataReader r)
|
|
{
|
|
Unk1 = r.ReadUInt32();
|
|
Unk2 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Unk1.ToString() + " - " + Unk2.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructHeaderUnk3 : MrfStruct
|
|
{
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
|
|
public MrfStructHeaderUnk3(DataReader r)
|
|
{
|
|
Unk1 = r.ReadUInt32();
|
|
Unk2 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Unk1.ToString() + " - " + Unk2.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateMainSection : MrfStruct
|
|
{
|
|
//maybe Transition ..?
|
|
|
|
public uint Unk1 { get; set; }
|
|
public int Unk2 { get; set; }
|
|
public float Unk3 { get; set; }
|
|
public uint Unk4 { get; set; }
|
|
public uint Unk5 { get; set; }
|
|
public uint Unk6 { get; set; }
|
|
public uint Unk7 { get; set; }
|
|
public uint Unk8 { get; set; }
|
|
public MrfStructStateCondition[] Conditions { get; set; }
|
|
|
|
public MrfStructStateMainSection(DataReader r)
|
|
{
|
|
Unk1 = r.ReadUInt32();
|
|
Unk2 = r.ReadInt32();
|
|
Unk3 = r.ReadSingle();
|
|
Unk4 = r.ReadUInt32();
|
|
Unk5 = r.ReadUInt32();
|
|
Unk6 = r.ReadUInt32();
|
|
|
|
uint flags = Unk1 & 0xFFFBFFFF;
|
|
var numconds = (flags >> 20) & 0xF;
|
|
|
|
if (numconds > 0)
|
|
{
|
|
Conditions = new MrfStructStateCondition[numconds];
|
|
for (int i = 0; i < numconds; i++)
|
|
{
|
|
Conditions[i] = new MrfStructStateCondition(r);
|
|
}
|
|
}
|
|
|
|
if ((flags & 0x40000000) != 0)
|
|
{
|
|
Unk7 = r.ReadUInt32();
|
|
Unk8 = r.ReadUInt32();
|
|
}
|
|
else
|
|
{
|
|
Unk7 = 0;
|
|
Unk8 = 0;
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
w.Write(Unk3);
|
|
w.Write(Unk4);
|
|
w.Write(Unk5);
|
|
w.Write(Unk6);
|
|
|
|
// FIXME: might be broken if changed without flags, see "numconds"
|
|
if (Conditions != null)
|
|
for (int i = 0; i < Conditions.Length; i++)
|
|
Conditions[i].Write(w);
|
|
|
|
// FIXME: might be broken if changed without flags
|
|
uint flags = Unk1 & 0xFFFBFFFF;
|
|
|
|
if ((flags & 0x40000000) != 0)
|
|
{
|
|
w.Write(Unk7);
|
|
w.Write(Unk8);
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Unk1.ToString() + " - " + Unk2.ToString() + " - " + FloatUtil.ToString(Unk3)
|
|
+ " - " + Unk4.ToString()
|
|
+ " - " + Unk5.ToString()
|
|
+ " - " + Unk6.ToString()
|
|
+ " - " + Unk7.ToString()
|
|
+ " - " + Unk8.ToString()
|
|
+ " - " + (Conditions?.Length ?? 0).ToString() + " conditions";
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateCondition : MrfStruct
|
|
{
|
|
public short UnkType { get; }
|
|
public short UnkIndex { get; }
|
|
public uint Unk1_1 { get; }
|
|
public uint Unk1_2 { get; }
|
|
public uint Unk1_3 { get; }
|
|
public uint Unk2_1 { get; }
|
|
public uint Unk3_1 { get; }
|
|
public uint Unk3_2 { get; }
|
|
|
|
public MrfStructStateCondition(DataReader r)
|
|
{
|
|
Unk1_1 = 0;
|
|
Unk1_2 = 0;
|
|
Unk1_3 = 0;
|
|
Unk2_1 = 0;
|
|
Unk3_1 = 0;
|
|
Unk3_2 = 0;
|
|
|
|
UnkType = r.ReadInt16();
|
|
UnkIndex = r.ReadInt16();
|
|
|
|
switch (UnkType)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
{
|
|
Unk1_1 = r.ReadUInt32();
|
|
Unk1_2 = r.ReadUInt32();
|
|
Unk1_3 = r.ReadUInt32();
|
|
break;
|
|
}
|
|
case 9:
|
|
case 10:
|
|
{
|
|
Unk2_1 = r.ReadUInt32();
|
|
break;
|
|
}
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 11:
|
|
case 12:
|
|
{
|
|
Unk3_1 = r.ReadUInt32();
|
|
Unk3_2 = r.ReadUInt32();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(UnkType);
|
|
w.Write(UnkIndex);
|
|
|
|
// FIXME: might be broken if changed outside
|
|
switch (UnkType)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
{
|
|
w.Write(Unk1_1);
|
|
w.Write(Unk1_2);
|
|
w.Write(Unk1_3);
|
|
break;
|
|
}
|
|
case 9:
|
|
case 10:
|
|
{
|
|
w.Write(Unk2_1);
|
|
break;
|
|
}
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 11:
|
|
case 12:
|
|
{
|
|
w.Write(Unk3_1);
|
|
w.Write(Unk3_2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return UnkType.ToString() + " - " + UnkIndex.ToString()
|
|
+ " - " + Unk1_1.ToString()
|
|
+ " - " + Unk1_2.ToString()
|
|
+ " - " + Unk1_3.ToString()
|
|
+ " - " + Unk2_1.ToString()
|
|
+ " - " + Unk3_1.ToString()
|
|
+ " - " + Unk3_2.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateVariable : MrfStruct
|
|
{
|
|
public MetaHash VariableName { get; }
|
|
public ushort Unk2 { get; }
|
|
public ushort Unk3 { get; }
|
|
public uint Unk4 { get; }
|
|
|
|
public MrfStructStateVariable(DataReader r)
|
|
{
|
|
VariableName = new MetaHash(r.ReadUInt32());
|
|
Unk2 = r.ReadUInt16();
|
|
Unk3 = r.ReadUInt16();
|
|
Unk4 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(VariableName);
|
|
w.Write(Unk2);
|
|
w.Write(Unk3);
|
|
w.Write(Unk4);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return VariableName.ToString() + " - " + Unk2.ToString() + " - " + Unk3.ToString() + " - " + Unk4.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateEvent : MrfStruct
|
|
{
|
|
public ushort Unk1 { get; }
|
|
public ushort Unk2 { get; }
|
|
public MetaHash NameHash { get; }
|
|
|
|
public MrfStructStateEvent(DataReader r)
|
|
{
|
|
Unk1 = r.ReadUInt16();
|
|
Unk2 = r.ReadUInt16();
|
|
NameHash = new MetaHash(r.ReadUInt32());
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
w.Write(NameHash);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Unk1.ToString() + " - " + Unk2.ToString() + " - " + NameHash.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateUnk6 : MrfStruct
|
|
{
|
|
public MetaHash Unk1 { get; }
|
|
public ushort Unk2 { get; }
|
|
public ushort Unk3 { get; }
|
|
public uint Unk4 { get; }
|
|
|
|
public MrfStructStateUnk6(DataReader r)
|
|
{
|
|
Unk1 = new MetaHash(r.ReadUInt32());
|
|
Unk2 = r.ReadUInt16();
|
|
Unk3 = r.ReadUInt16();
|
|
Unk4 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
w.Write(Unk3);
|
|
w.Write(Unk4);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Unk1.ToString() + " - " + Unk2.ToString() + " - " + Unk3.ToString() + " - " + Unk4.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateMachineState : MrfStruct
|
|
{
|
|
public MetaHash StateName { get; }
|
|
public uint UnkValue { get; }
|
|
|
|
public MrfStructStateMachineState(DataReader r)
|
|
{
|
|
StateName = new MetaHash(r.ReadUInt32());
|
|
UnkValue = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(StateName);
|
|
w.Write(UnkValue);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return StateName.ToString() + " - " + UnkValue.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateSignalVariable : MrfStruct
|
|
{
|
|
public float Value { get; }//always 0 - probably float?
|
|
public float Default { get; }
|
|
public float RangeMin { get; }
|
|
public float RangeMax { get; }
|
|
|
|
public MrfStructStateSignalVariable(DataReader r)
|
|
{
|
|
Value = r.ReadSingle();
|
|
Default = r.ReadSingle();
|
|
RangeMin = r.ReadSingle();
|
|
RangeMax = r.ReadSingle();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Value);
|
|
w.Write(Default);
|
|
w.Write(RangeMin);
|
|
w.Write(RangeMax);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Value.ToString() + " - " + Default.ToString() + " - (" + RangeMin.ToString() + " - " + RangeMax.ToString() + ")";
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateSignalData : MrfStruct
|
|
{
|
|
public uint Type { get; set; } //0, 2, 4, 5
|
|
public uint NameHash { get; set; } //only for Type==2, always 0 otherwise
|
|
public uint Unk1 { get; set; } //only for Type==5, always 4
|
|
public float Unk2 { get; set; } //only for Type==5, values: 0.0, 0.95, 0.8, 1.4, 1.8, 2.2, 0.2, 0.5 - maybe min value? always less than Unk3 when nonzero
|
|
public float Unk3 { get; set; } //only for Type==5, values: 1.0, 1.4, 1.8, 2.2, 2.95, 0.8, 0.5 - maybe max value?
|
|
public uint ItemCount { get; set; } //only for Type==5
|
|
public uint Unk4 { get; set; } //only for Type==5, always 4
|
|
|
|
public MrfStructStateSignalVariable[] Items { get; set; }
|
|
|
|
public MrfStructStateSignalData(DataReader r)
|
|
{
|
|
Type = r.ReadUInt32();
|
|
if (Type == 5)
|
|
{
|
|
Unk1 = r.ReadUInt32();
|
|
Unk2 = r.ReadSingle();
|
|
Unk3 = r.ReadSingle();
|
|
ItemCount = r.ReadUInt32();
|
|
Unk4 = r.ReadUInt32();
|
|
Items = new MrfStructStateSignalVariable[ItemCount];
|
|
for (int i = 0; i < ItemCount; i++)
|
|
{
|
|
Items[i] = new MrfStructStateSignalVariable(r);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NameHash = r.ReadUInt32();
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Type);
|
|
if (Type == 5)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
w.Write(Unk3);
|
|
w.Write(ItemCount);
|
|
w.Write(Unk4);
|
|
|
|
// FIXME: might be broken if changed outside
|
|
foreach (var item in Items)
|
|
item.Write(w);
|
|
}
|
|
else
|
|
{
|
|
w.Write(NameHash);
|
|
}
|
|
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Type.ToString() + " - " + NameHash.ToString() + " - " +
|
|
Unk1.ToString() + " - " + Unk2.ToString() + " - " + FloatUtil.ToString(Unk3) + " - " + Unk4.ToString() + " - C:" + ItemCount.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfStructStateSignal : MrfStruct
|
|
{
|
|
public ushort Unk1 { get; }
|
|
public ushort Unk2 { get; }
|
|
public ushort Unk3 { get; }//Items.Length * 8
|
|
public ushort Unk4 { get; }
|
|
public MrfStructStateSignalData[] Items { get; }
|
|
|
|
public MrfStructStateSignal(DataReader r)
|
|
{
|
|
Unk1 = r.ReadUInt16();
|
|
Unk2 = r.ReadUInt16();
|
|
Unk3 = r.ReadUInt16();
|
|
Unk4 = r.ReadUInt16();
|
|
|
|
var itemsList = new List<MrfStructStateSignalData>();
|
|
|
|
while (true)
|
|
{
|
|
var item = new MrfStructStateSignalData(r);
|
|
itemsList.Add(item);
|
|
if (item.Type == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Items = itemsList.ToArray();
|
|
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
w.Write(Unk3);
|
|
w.Write(Unk4);
|
|
|
|
foreach (var item in Items)
|
|
item.Write(w);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Unk1.ToString() + " - " + Unk2.ToString() + " - " + Unk3.ToString() + " - " + Unk4.ToString() + " - " +
|
|
(Items?.Length ?? 0).ToString() + " items";
|
|
}
|
|
}
|
|
|
|
|
|
// FIXME: most likely broken
|
|
|
|
[TC(typeof(EXP))] public class MrfStructNegativeDataUnk7 : MrfStruct
|
|
{
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
public uint Unk4 { get; set; }
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
w.Write(Unk3);
|
|
w.Write(Unk4);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Unk1.ToString() + " - " + Unk2.ToString() + " - " + Unk3.ToString() + " - " + Unk4.ToString();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region mrf node classes
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeStateMachineClass : MrfNodeStateBase
|
|
{
|
|
// rage__mvNodeStateMachineClass (1)
|
|
|
|
public MrfStructStateMachineState[] States { get; set; }
|
|
public MrfStructStateMainSection[] Sections { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
|
|
if (StateChildCount > 0)
|
|
{
|
|
States = new MrfStructStateMachineState[StateChildCount];
|
|
for (int i = 0; i < StateChildCount; i++)
|
|
States[i] = new MrfStructStateMachineState(r);
|
|
}
|
|
|
|
if (StateSectionCount > 0)
|
|
{
|
|
Sections = new MrfStructStateMainSection[StateSectionCount];
|
|
for (int i = 0; i < StateSectionCount; i++)
|
|
Sections[i] = new MrfStructStateMainSection(r);
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
if (States != null)
|
|
foreach (var state in States)
|
|
state.Write(w);
|
|
|
|
if (Sections != null)
|
|
foreach(var section in Sections)
|
|
section.Write(w);
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeTail : MrfNodeValueBase
|
|
{
|
|
// rage__mvNodeTail (2)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeInlinedStateMachine : MrfNodeStateBase
|
|
{
|
|
// rage__mvNodeInlinedStateMachine (3)
|
|
|
|
public int Unk { get; set; } //usually(always?) negative, seems to be a byte offset maybe to parent node
|
|
public MrfStructStateMachineState[] States { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk = r.ReadInt32();
|
|
|
|
if (StateChildCount > 0)
|
|
{
|
|
States = new MrfStructStateMachineState[StateChildCount];
|
|
for (int i = 0; i < StateChildCount; i++)
|
|
States[i] = new MrfStructStateMachineState(r);
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk);
|
|
|
|
if (States != null)
|
|
foreach (var item in States)
|
|
item.Write(w);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return base.ToString() + " - " + Unk.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk4 : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNode* (4) not used in final game
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2_Count { get; set; }
|
|
public byte[] Unk2_Bytes { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
public uint Unk4 { get; set; }
|
|
public uint Unk5 { get; set; }
|
|
public uint Unk6 { get; set; }
|
|
public uint Unk7 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
{
|
|
Unk2_Count = r.ReadUInt32();
|
|
Unk2_Bytes = r.ReadBytes((int)Unk2_Count);
|
|
break;
|
|
}
|
|
case 2:
|
|
Unk1 = r.ReadUInt32();
|
|
break;
|
|
}
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
Unk3 = r.ReadUInt32();
|
|
|
|
if (((Flags >> 4) & 3) != 0)
|
|
Unk4 = r.ReadUInt32();
|
|
|
|
if (((Flags >> 6) & 3) != 0)
|
|
Unk5 = r.ReadUInt32();
|
|
|
|
if (((Flags >> 8) & 3) != 0)
|
|
Unk6 = r.ReadUInt32();
|
|
|
|
if (((Flags >> 10) & 3) != 0)
|
|
Unk7 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
{
|
|
w.Write(Unk2_Count);
|
|
w.Write(Unk2_Bytes);
|
|
break;
|
|
}
|
|
case 2:
|
|
w.Write(Unk1);
|
|
break;
|
|
}
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
w.Write(Unk3);
|
|
|
|
if (((Flags >> 4) & 3) != 0)
|
|
w.Write(Unk4);
|
|
|
|
if (((Flags >> 6) & 3) != 0)
|
|
w.Write(Unk5);
|
|
|
|
if (((Flags >> 8) & 3) != 0)
|
|
w.Write(Unk6);
|
|
|
|
if (((Flags >> 10) & 3) != 0)
|
|
w.Write(Unk7);
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeBlend : MrfNodeBlendAddSubtractBase
|
|
{
|
|
// rage__mvNodeBlend (5)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeAddSubstract : MrfNodeBlendAddSubtractBase
|
|
{
|
|
// rage__mvNodeAddSubtract (6)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeFilter : MrfNodeFilterUnkBase
|
|
{
|
|
// rage__mvNodeFilter (7)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk8 : MrfNodeFilterUnkBase
|
|
{
|
|
// rage__mvNode* (8)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeFrame : MrfNode
|
|
{
|
|
// rage__mvNodeFrame (9)
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint Flags { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
Flags = r.ReadUInt32();
|
|
|
|
if ((Flags & 3) != 0)
|
|
Unk2 = r.ReadUInt32();
|
|
|
|
if ((Flags & 0x30) != 0)
|
|
Unk3 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
w.Write(Flags);
|
|
|
|
if ((Flags & 3) != 0)
|
|
w.Write(Unk2);
|
|
|
|
if ((Flags & 0x30) != 0)
|
|
w.Write(Unk3);
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk10 : MrfNodeValueBase
|
|
{
|
|
// rage__mvNode* (10)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeBlendN : MrfNodeNegativeBase
|
|
{
|
|
// rage__mvNodeBlendN (13)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeClip : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNodeClip (15)
|
|
|
|
//eg "Clip_XXX" (lowercase hash, XXX number eg 012)
|
|
//?- delta supplement
|
|
//?- delta
|
|
//?- looped
|
|
//?- phase
|
|
//?- rate
|
|
|
|
|
|
public MetaHash VariableName { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
public MetaHash DictName { get; set; }
|
|
public MetaHash ClipName { get; set; }
|
|
public MetaHash Unk5 { get; set; }
|
|
public MetaHash Unk6 { get; set; }
|
|
public uint Unk7 { get; set; }
|
|
public uint Unk8 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
{
|
|
Unk2 = r.ReadUInt32();
|
|
DictName = new MetaHash(r.ReadUInt32());
|
|
|
|
if (Unk2 != 3)
|
|
ClipName = new MetaHash(r.ReadUInt32());
|
|
|
|
break;
|
|
}
|
|
case 2:
|
|
VariableName = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
}
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
Unk5 = new MetaHash(r.ReadUInt32());
|
|
|
|
if (((Flags >> 4) & 3) != 0)
|
|
Unk6 = new MetaHash(r.ReadUInt32());
|
|
|
|
if (((Flags >> 6) & 3) != 0)
|
|
Unk7 = r.ReadUInt32();
|
|
|
|
if (((Flags >> 8) & 3) != 0)
|
|
Unk8 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
{
|
|
w.Write(Unk2);
|
|
w.Write(DictName);
|
|
|
|
if (Unk2 != 3)
|
|
w.Write(ClipName);
|
|
|
|
break;
|
|
}
|
|
case 2:
|
|
w.Write(VariableName);
|
|
break;
|
|
}
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
w.Write(Unk5);
|
|
|
|
if (((Flags >> 4) & 3) != 0)
|
|
w.Write(Unk6);
|
|
|
|
if (((Flags >> 6) & 3) != 0)
|
|
w.Write(Unk7);
|
|
|
|
if (((Flags >> 8) & 3) != 0)
|
|
w.Write(Unk8);
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk17 : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNode* (17)
|
|
|
|
public uint Unk1_Count { get; set; }
|
|
public byte[] Unk1_Bytes { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
public uint Unk4 { get; set; }
|
|
public uint Unk5 { get; set; }
|
|
public uint[] Unk6 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
if ((Flags & 3) == 1)
|
|
{
|
|
Unk1_Count = r.ReadUInt32();
|
|
Unk1_Bytes = r.ReadBytes((int)Unk1_Count);
|
|
}
|
|
else if ((Flags & 3) == 2)
|
|
Unk2 = r.ReadUInt32();
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
Unk3 = r.ReadUInt32();
|
|
|
|
if (((Flags >> 4) & 3) != 0)
|
|
Unk4 = r.ReadUInt32();
|
|
|
|
if ((Flags >> 6) != 0)
|
|
Unk5 = r.ReadUInt32();
|
|
|
|
var flags = Flags >> 19;
|
|
var unk6Count = (Flags >> 10) & 0xF;
|
|
|
|
Unk6 = new uint[unk6Count];
|
|
|
|
for (int i = 0; i < unk6Count; i++)
|
|
{
|
|
if ((flags & 3) != 0)
|
|
Unk6[i] = r.ReadUInt32();
|
|
|
|
flags >>= 2;
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
if ((Flags & 3) == 1)
|
|
{
|
|
w.Write(Unk1_Count);
|
|
w.Write(Unk1_Bytes);
|
|
}
|
|
else if ((Flags & 3) == 2)
|
|
w.Write(Unk2);
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
w.Write(Unk3);
|
|
|
|
if (((Flags >> 4) & 3) != 0)
|
|
w.Write(Unk4);
|
|
|
|
if ((Flags >> 6) != 0)
|
|
w.Write(Unk5);
|
|
|
|
var unk6Count = (Flags >> 10) & 0xF;
|
|
|
|
if (unk6Count > 0)
|
|
{
|
|
foreach (var value in Unk6)
|
|
w.Write(value);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk18 : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNode* (18)
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
|
|
if ((Flags & 3) != 0)
|
|
Unk2 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
|
|
if ((Flags & 3) != 0)
|
|
w.Write(Unk2);
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeExpression : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNodeExpression (19)
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
public MetaHash ExpressionDict { get; set; }
|
|
public MetaHash ExpressionName { get; set; }
|
|
public MetaHash VariableName { get; set; }
|
|
public uint Unk6 { get; set; }
|
|
public uint[][] Unk7 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
ExpressionDict = new MetaHash(r.ReadUInt32());
|
|
ExpressionName = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
case 2:
|
|
VariableName = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
}
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
Unk6 = r.ReadUInt32();
|
|
|
|
var unk7Count = (Flags >> 28);
|
|
|
|
if (unk7Count == 0)
|
|
return;
|
|
|
|
var unkHeaderFlag = (Flags >> 4) & 0xFFFFFF;
|
|
var offset = 0;
|
|
|
|
Unk7 = new uint[unk7Count][];
|
|
|
|
for (int i = 0; i < unk7Count; i++)
|
|
{
|
|
var unkTypeFlag = (unkHeaderFlag >> offset) & 3;
|
|
|
|
var value1 = r.ReadUInt32();
|
|
uint value2 = 0;
|
|
|
|
if (unkTypeFlag == 2 || unkTypeFlag == 1)
|
|
value2 = r.ReadUInt32();
|
|
|
|
Unk7[i] = new uint[2] { value1, value2 };
|
|
|
|
offset += 2;
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
w.Write(ExpressionDict);
|
|
w.Write(ExpressionName);
|
|
break;
|
|
case 2:
|
|
w.Write(VariableName);
|
|
break;
|
|
}
|
|
|
|
if (((Flags >> 2) & 3) != 0)
|
|
w.Write(Unk6);
|
|
|
|
var unk7Count = (Flags >> 28);
|
|
|
|
if (unk7Count == 0)
|
|
return;
|
|
|
|
var unkHeaderFlag = (Flags >> 4) & 0xFFFFFF;
|
|
var offset = 0;
|
|
|
|
foreach (var item in Unk7)
|
|
{
|
|
var unkTypeFlag = (unkHeaderFlag >> offset) & 3;
|
|
|
|
w.Write(item[0]);
|
|
|
|
if (unkTypeFlag == 2 || unkTypeFlag == 1)
|
|
w.Write(item[1]);
|
|
|
|
offset += 2;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk20 : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNode* (20)
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
|
|
if ((Flags & 3) != 0)
|
|
Unk2 = r.ReadUInt32();
|
|
|
|
if ((Flags & 0x30) != 0)
|
|
Unk3 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
|
|
if ((Flags & 3) != 0)
|
|
w.Write(Unk2);
|
|
|
|
if ((Flags & 0x30) != 0)
|
|
w.Write(Unk3);
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeProxy : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNodeProxy (21)
|
|
|
|
//?- node
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeAddN : MrfNodeNegativeBase
|
|
{
|
|
// rage__mvNodeAddN (22)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeIdentity : MrfNodeValueBase
|
|
{
|
|
// rage__mvNodeIdentity (23)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk24 : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNode* (24)
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2 { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
public MetaHash Unk4 { get; set; }
|
|
public MetaHash Unk5 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
Unk2 = r.ReadUInt32();
|
|
|
|
if ((Flags & 0x180000) == 0x80000)
|
|
Unk3 = r.ReadUInt32();
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
Unk4 = new MetaHash(r.ReadUInt32());
|
|
Unk5 = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
case 2:
|
|
Unk5 = new MetaHash(r.ReadUInt32());
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
w.Write(Unk2);
|
|
|
|
if ((Flags & 0x180000) == 0x80000)
|
|
w.Write(Unk3);
|
|
|
|
switch (Flags & 3)
|
|
{
|
|
case 1:
|
|
w.Write(Unk4);
|
|
w.Write(Unk5);
|
|
break;
|
|
case 2:
|
|
w.Write(Unk5);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk25 : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNode* (25)
|
|
|
|
public uint Unk1 { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
if ((Flags & 3) != 0)
|
|
Unk1 = r.ReadUInt32();
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
if ((Flags & 3) != 0)
|
|
w.Write(Unk1);
|
|
}
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeMergeN : MrfNodeNegativeBase
|
|
{
|
|
// rage__mvNodeMergeN (26)
|
|
|
|
//?- filter
|
|
//?- input filter
|
|
//?- weight
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeState : MrfNodeStateBase
|
|
{
|
|
// rage__mvNodeState (27)
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint VariablesCount { get; set; }
|
|
public uint Unk3 { get; set; }
|
|
public uint EventsCount { get; set; }
|
|
public uint Unk5 { get; set; }
|
|
public uint Unk6Count { get; set; }
|
|
public uint Unk7 { get; set; }
|
|
public uint SignalsCount { get; set; }
|
|
|
|
public MrfStructStateMainSection[] Sections { get; set; }
|
|
public MrfStructStateVariable[] Variables { get; set; }
|
|
public MrfStructStateEvent[] Events { get; set; }
|
|
public MrfStructStateUnk6[] Unk6Items { get; set; }
|
|
public MrfStructStateSignal[] Signals { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
VariablesCount = r.ReadUInt32();
|
|
Unk3 = r.ReadUInt32();
|
|
EventsCount = r.ReadUInt32();
|
|
Unk5 = r.ReadUInt32();
|
|
Unk6Count = r.ReadUInt32();
|
|
Unk7 = r.ReadUInt32();
|
|
SignalsCount = r.ReadUInt32();
|
|
|
|
|
|
if (StateSectionCount > 0)
|
|
{
|
|
Sections = new MrfStructStateMainSection[StateSectionCount];
|
|
for (int i = 0; i < StateSectionCount; i++)
|
|
Sections[i] = new MrfStructStateMainSection(r);
|
|
}
|
|
|
|
if (VariablesCount > 0)
|
|
{
|
|
Variables = new MrfStructStateVariable[VariablesCount];
|
|
for (int i = 0; i < VariablesCount; i++)
|
|
Variables[i] = new MrfStructStateVariable(r);
|
|
}
|
|
|
|
if (EventsCount > 0)
|
|
{
|
|
Events = new MrfStructStateEvent[EventsCount];
|
|
for (int i = 0; i < EventsCount; i++)
|
|
Events[i] = new MrfStructStateEvent(r);
|
|
}
|
|
|
|
if (Unk6Count > 0)
|
|
{
|
|
Unk6Items = new MrfStructStateUnk6[Unk6Count];
|
|
for (int i = 0; i < Unk6Count; i++)
|
|
Unk6Items[i] = new MrfStructStateUnk6(r);
|
|
}
|
|
|
|
if (SignalsCount > 0)
|
|
{
|
|
Signals = new MrfStructStateSignal[SignalsCount];
|
|
for (int i = 0; i < SignalsCount; i++)
|
|
Signals[i] = new MrfStructStateSignal(r);
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
w.Write(VariablesCount);
|
|
w.Write(Unk3);
|
|
w.Write(EventsCount);
|
|
w.Write(Unk5);
|
|
w.Write(Unk6Count);
|
|
w.Write(Unk7);
|
|
w.Write(SignalsCount);
|
|
|
|
if (Sections != null)
|
|
foreach (var section in Sections)
|
|
section.Write(w);
|
|
|
|
if (Variables != null)
|
|
foreach (var item in Variables)
|
|
item.Write(w);
|
|
|
|
if (Events != null)
|
|
foreach (var item in Events)
|
|
item.Write(w);
|
|
|
|
if (Unk6Items != null)
|
|
foreach (var item in Unk6Items)
|
|
item.Write(w);
|
|
|
|
if (Signals != null)
|
|
foreach (var item in Signals)
|
|
item.Write(w);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return base.ToString() + " --- " + Unk1.ToString() + " - " + Unk3.ToString() + " - " + Unk5.ToString() + " - " + Unk7.ToString();
|
|
}
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeInvalid : MrfNodeValueBase
|
|
{
|
|
// rage__mvNodeInvalid (28)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk29 : MrfNodeFilterUnkBase
|
|
{
|
|
// rage__mvNode* (29)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeSubNetworkClass : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNodeSubNetworkClass (30)
|
|
|
|
}
|
|
|
|
[TC(typeof(EXP))] public class MrfNodeUnk31 : MrfNodeNameFlagsBase
|
|
{
|
|
// rage__mvNode* (31)
|
|
|
|
public uint Unk1 { get; set; }
|
|
public uint Unk2_Count { get; set; }
|
|
public uint[][] Unk2_Items { get; set; }
|
|
public uint Unk3_Count { get; set; }
|
|
public uint[][] Unk3_Items { get; set; }
|
|
public uint Unk4_Count { get; set; }
|
|
public uint[][] Unk4_Items { get; set; }
|
|
public uint Unk5_Count { get; set; }
|
|
public uint[][] Unk5_Items { get; set; }
|
|
|
|
public override void Read(DataReader r)
|
|
{
|
|
base.Read(r);
|
|
|
|
Unk1 = r.ReadUInt32();
|
|
Unk2_Count = r.ReadUInt32();
|
|
Unk3_Count = r.ReadUInt32();
|
|
Unk4_Count = r.ReadUInt32();
|
|
Unk5_Count = r.ReadUInt32();
|
|
|
|
if (Unk3_Count > 0)
|
|
{
|
|
Unk3_Items = new uint[Unk3_Count][];
|
|
|
|
for (int i = 0; i < Unk3_Count; i++)
|
|
{
|
|
var value1 = r.ReadUInt32();
|
|
var value2 = r.ReadUInt32();
|
|
Unk3_Items[i] = new uint[] { value1, value2 };
|
|
}
|
|
}
|
|
|
|
if (Unk4_Count > 0)
|
|
{
|
|
Unk4_Items = new uint[Unk4_Count][];
|
|
|
|
for (int i = 0; i < Unk4_Count; i++)
|
|
{
|
|
var value1 = r.ReadUInt32();
|
|
var value2 = r.ReadUInt32();
|
|
Unk4_Items[i] = new uint[] { value1, value2 };
|
|
}
|
|
}
|
|
|
|
if (Unk5_Count > 0)
|
|
{
|
|
Unk5_Items = new uint[Unk5_Count][];
|
|
|
|
for (int i = 0; i < Unk5_Count; i++)
|
|
{
|
|
var value1 = r.ReadUInt32();
|
|
var value2 = r.ReadUInt32();
|
|
Unk5_Items[i] = new uint[] { value1, value2 };
|
|
}
|
|
}
|
|
|
|
if (Unk2_Count > 0)
|
|
{
|
|
Unk2_Items = new uint[Unk2_Count][];
|
|
|
|
for (int i = 0; i < Unk2_Count; i++)
|
|
{
|
|
var value1 = r.ReadUInt32();
|
|
var value2 = r.ReadUInt32();
|
|
var value3 = r.ReadUInt32();
|
|
Unk2_Items[i] = new uint[] { value1, value2, value3 };
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Write(DataWriter w)
|
|
{
|
|
base.Write(w);
|
|
|
|
w.Write(Unk1);
|
|
w.Write(Unk2_Count);
|
|
w.Write(Unk3_Count);
|
|
w.Write(Unk4_Count);
|
|
w.Write(Unk5_Count);
|
|
|
|
if (Unk3_Count > 0)
|
|
{
|
|
foreach (var entry in Unk3_Items)
|
|
{
|
|
w.Write(entry[0]);
|
|
w.Write(entry[1]);
|
|
}
|
|
}
|
|
|
|
if (Unk4_Count > 0)
|
|
{
|
|
foreach (var entry in Unk4_Items)
|
|
{
|
|
w.Write(entry[0]);
|
|
w.Write(entry[1]);
|
|
}
|
|
}
|
|
|
|
if (Unk5_Count > 0)
|
|
{
|
|
foreach (var entry in Unk5_Items)
|
|
{
|
|
w.Write(entry[0]);
|
|
w.Write(entry[1]);
|
|
}
|
|
}
|
|
|
|
if (Unk2_Count > 0)
|
|
{
|
|
foreach (var entry in Unk2_Items)
|
|
{
|
|
w.Write(entry[0]);
|
|
w.Write(entry[1]);
|
|
w.Write(entry[2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|