Skip to content

Commit

Permalink
Added Chain support to convert .35 to .48
Browse files Browse the repository at this point in the history
  • Loading branch information
keegars committed Jun 30, 2022
1 parent 87dee84 commit 5aa3ab5
Show file tree
Hide file tree
Showing 14 changed files with 1,363 additions and 6 deletions.
571 changes: 571 additions & 0 deletions MHR-Model-Converter/Chain/Chain.cs

Large diffs are not rendered by default.

102 changes: 102 additions & 0 deletions MHR-Model-Converter/Chain/ChainData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using MHR_Model_Converter.Helper;
using static MHR_Model_Converter.Chain.ChainEnums;

namespace MHR_Model_Converter.Chain
{
public class ChainData
{
public uint Version { get; set; } //Must be 35 or 48
public uint Magic { get; set; } //Typically 1851877475
public uint ErrFlags { get; set; } //Can be 0
public uint MasterSize { get; set; } //Can be 0
public ulong CollisionAttrAssetOffset { get; set; } //Can be 0
public ulong ModelCollisionTable { get; set; } //Collision Table Start Pointer - MUST BE UPDATED IF FILE CHANGES
public ulong ExtraDataOffset { get; set; } //Can be 0
public ulong GroupTablePointer { get; set; } //TODO - Check //Grouping Table Start Pointer - MUST BE UPDATED IF FILE CHANGES
public ulong LinkTablePointer { get; set; } //Can be 0
public ulong SettingTablePointer { get; set; } //Setting Table Start Pointer - MUST BE UPDATED IF FILE CHANGES
public ulong WindSettingTablePointer { get; set; } //Wind Setting Table Pointer - MUST BE UPDATED IF FILE CHANGES
public int GroupCount { get; set; }
public int SettingCount { get; set; }
public int ModelCollisionCount { get; set; }
public int WindSettingCount { get; set; }
public int LinkCount { get; set; }
public int RotationOrder { get; set; }
public int DefaultSettingIndex { get; set; }
public int CalculationMode { get; set; }
public uint ChainAttrFlags { get; set; }
public uint ChainParamFlags { get; set; }
public float CalculateStepTime { get; set; }
public bool ModelCollisionSearch { get; set; }
public int LegacyVersion { get; set; }
public ulong CollisionFilterHits { get; set; } //TODO - may need to change this to a list of ints, same length as the model collision count!!!

private ErrFlag _ErrFlags
{
get
{
try
{
var errFlag = (ErrFlag)ErrFlags;
return errFlag;
}
catch
{
return ErrFlag.ErrFlags_None;
}
}
}

public byte[] ExportSection(int size, ChainVersion version)
{
var bytesList = new List<byte>();

if (version == ChainVersion.v35)
{
Version = 35;
}
else if (version == ChainVersion.v48)
{
Version = 48;
}

//Add any specific chain version amendments here
bytesList.AddRange(Version.ToBytes());
bytesList.AddRange(Magic.ToBytes());
bytesList.AddRange(ErrFlags.ToBytes());
bytesList.AddRange(MasterSize.ToBytes());
bytesList.AddRange(CollisionAttrAssetOffset.ToBytes());
bytesList.AddRange(ModelCollisionTable.ToBytes());
bytesList.AddRange(ExtraDataOffset.ToBytes());
bytesList.AddRange(GroupTablePointer.ToBytes());
bytesList.AddRange(LinkTablePointer.ToBytes());
bytesList.AddRange(SettingTablePointer.ToBytes());
bytesList.AddRange(WindSettingTablePointer.ToBytes());
bytesList.AddRange(GroupCount.ToBytes());
bytesList.AddRange(SettingCount.ToBytes());
bytesList.AddRange(ModelCollisionCount.ToBytes());
bytesList.AddRange(WindSettingCount.ToBytes());
bytesList.AddRange(LinkCount.ToBytes());
bytesList.AddRange(RotationOrder.ToBytes());
bytesList.AddRange(DefaultSettingIndex.ToBytes());
bytesList.AddRange(CalculationMode.ToBytes());
bytesList.AddRange(ChainAttrFlags.ToBytes());
bytesList.AddRange(ChainParamFlags.ToBytes());
bytesList.AddRange(CalculateStepTime.ToBytes());
bytesList.AddRange(ModelCollisionSearch.ToBytes());
bytesList.AddRange(LegacyVersion.ToBytes());
bytesList.AddRange(ByteHelper.EmptyBytes(2)); // Add 2 random 0 bytes
bytesList.AddRange(CollisionFilterHits.ToBytes());
bytesList.AddRange(ByteHelper.EmptyBytes(8)); // Add 8 random 0 bytes

if (size != bytesList.Count)
{
throw new Exception($"Byte size {bytesList.Count} is not equal to expected size {size}");
}

return bytesList.ToArray();
}
}
}
19 changes: 19 additions & 0 deletions MHR-Model-Converter/Chain/ChainEnums.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace MHR_Model_Converter.Chain
{
public static class ChainEnums
{
public enum ChainVersion
{
v35,
v48
}

public enum ErrFlag
{
ErrFlags_None = 0,
ErrFlags_Empty = 1,
ErrFlags_NotFoundRefAsset = 2,
ErrFlags_NotFoundIncludeAsset = 4
}
}
}
95 changes: 95 additions & 0 deletions MHR-Model-Converter/Chain/ChainGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using MHR_Model_Converter.Helper;
using static MHR_Model_Converter.Chain.ChainEnums;

namespace MHR_Model_Converter.Chain
{
public class ChainGroup
{
public ulong TerminalNodeNameOffset { get; set; }
public ulong NodeTableOffset { get; set; }
public uint SettingId { get; set; }
public int NodeCount { get; set; }
public int ExecOrder { get; set; }
public int AutoBlendCheckNodeNo { get; set; }
public int WindId { get; set; }
public uint TerminalNameHash { get; set; }
public uint AttrFlags { get; set; }
public uint CollisionFilterFlags { get; set; }
public uint ExtraNodeLocalPosX { get; set; }
public uint ExtraNodeLocalPosY { get; set; }
public uint ExtraNodeLocalPosZ { get; set; }
public uint Tags1 { get; set; }
public uint Tags2 { get; set; }
public uint Tags3 { get; set; }
public uint Tags4 { get; set; }
public float DampingNoise0 { get; set; }
public float DampingNoise1 { get; set; }
public float EndRotConstMax { get; set; }
public int TagCount { get; set; }
public int AngleLimitDirectionMode { get; set; }

public ulong NextChainNameOffset0 { get; set; } = 0; //Can be empty
public uint UnknownBoneHash { get; set; } = 0; //Can be 0
public uint Unknown { get; set; } = 0; //Can be 0
public ulong Unknown64 { get; set; } = 0; //Can be 0
public ulong NextChainNameOffset1 { get; set; } = 0; //Set to the next chain offset

public List<ulong> TerminalNodeNameList { get; set; }

public List<ChainNodeData> ChainNodesData { get; set; }

public byte[] GetTerminalNodeName()
{
return TerminalNodeNameList.SelectMany(z => z.ToBytes()).ToArray();
}

public byte[] ExportSection(int size, ChainVersion version)
{
var bytesList = new List<byte>();

//Add any specific chain version amendments here
bytesList.AddRange(TerminalNodeNameOffset.ToBytes());
bytesList.AddRange(NodeTableOffset.ToBytes());
bytesList.AddRange(SettingId.ToBytes());
bytesList.AddRange(NodeCount.ToBytes());
bytesList.AddRange(ExecOrder.ToBytes());
bytesList.AddRange(AutoBlendCheckNodeNo.ToBytes());
bytesList.AddRange(WindId.ToBytes());
bytesList.AddRange(TerminalNameHash.ToBytes());
bytesList.AddRange(AttrFlags.ToBytes());
bytesList.AddRange(CollisionFilterFlags.ToBytes());
bytesList.AddRange(ExtraNodeLocalPosX.ToBytes());
bytesList.AddRange(ExtraNodeLocalPosY.ToBytes());
bytesList.AddRange(ExtraNodeLocalPosZ.ToBytes());
bytesList.AddRange(Tags1.ToBytes());
bytesList.AddRange(Tags2.ToBytes());
bytesList.AddRange(Tags3.ToBytes());
bytesList.AddRange(Tags4.ToBytes());
bytesList.AddRange(DampingNoise0.ToBytes());
bytesList.AddRange(DampingNoise1.ToBytes());
bytesList.AddRange(EndRotConstMax.ToBytes());
bytesList.AddRange(TagCount.ToBytes());
bytesList.AddRange(AngleLimitDirectionMode.ToBytes());
bytesList.AddRange(ByteHelper.EmptyBytes(2));

if (version == ChainVersion.v48)
{
bytesList.AddRange(NextChainNameOffset0.ToBytes());
bytesList.AddRange(UnknownBoneHash.ToBytes());
bytesList.AddRange(Unknown.ToBytes());
bytesList.AddRange(Unknown64.ToBytes());
bytesList.AddRange(NextChainNameOffset1.ToBytes());
}

if (size != bytesList.Count)
{
throw new Exception($"Byte size {bytesList.Count} is not equal to expected size {size}");
}

return bytesList.ToArray();
}
}
}
66 changes: 66 additions & 0 deletions MHR-Model-Converter/Chain/ChainNodeData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using MHR_Model_Converter.Helper;
using static MHR_Model_Converter.Chain.ChainEnums;

namespace MHR_Model_Converter.Chain
{
public class ChainNodeData
{
public float AngleLimitDirectionX { get; set; }
public float AngleLimitDirectionY { get; set; }
public float AngleLimitDirectionZ { get; set; }
public float AngleLimitDirectionW { get; set; }
public float AngleLimitRad { get; set; }
public float AngleLimitDistance { get; set; }
public float AngleLimitRestitution { get; set; }
public float AngleLimitRestitutionStopSpeed { get; set; }
public float CollisionRadius { get; set; }
public uint CollisionFilterFlags { get; set; }
public float CapsuleStretchRate0 { get; set; }
public float CapsuleStretchRate1 { get; set; }
public uint AttributeFlag { get; set; }
public uint ConstraintJntNameHash { get; set; }
public float WindCoEf { get; set; }
public int AngleMode { get; set; }
public int CollisionShape { get; set; }
public int AttachType { get; set; }
public int RotationType { get; set; }
public ulong JiggleData { get; set; }

public byte[] ExportSection(int size, ChainVersion version)
{
var bytesList = new List<byte>();

//Add any specific chain version amendments here
bytesList.AddRange(AngleLimitDirectionX.ToBytes());
bytesList.AddRange(AngleLimitDirectionY.ToBytes());
bytesList.AddRange(AngleLimitDirectionZ.ToBytes());
bytesList.AddRange(AngleLimitDirectionW.ToBytes());
bytesList.AddRange(AngleLimitRad.ToBytes());
bytesList.AddRange(AngleLimitDistance.ToBytes());
bytesList.AddRange(AngleLimitRestitution.ToBytes());
bytesList.AddRange(AngleLimitRestitutionStopSpeed.ToBytes());
bytesList.AddRange(CollisionRadius.ToBytes());
bytesList.AddRange(CollisionFilterFlags.ToBytes());
bytesList.AddRange(CapsuleStretchRate0.ToBytes());
bytesList.AddRange(CapsuleStretchRate1.ToBytes());
bytesList.AddRange(AttributeFlag.ToBytes());
bytesList.AddRange(ConstraintJntNameHash.ToBytes());
bytesList.AddRange(WindCoEf.ToBytes());
bytesList.AddRange(AngleMode.ToBytes());
bytesList.AddRange(CollisionShape.ToBytes());
bytesList.AddRange(AttachType.ToBytes());
bytesList.AddRange(RotationType.ToBytes());
bytesList.AddRange(JiggleData.ToBytes());
bytesList.AddRange(ByteHelper.EmptyBytes(8));

if (size != bytesList.Count)
{
throw new Exception($"Byte size {bytesList.Count} is not equal to expected size {size}");
}

return bytesList.ToArray();
}
}
}
Loading

0 comments on commit 5aa3ab5

Please sign in to comment.