/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <RumbleAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } var rumbleAsset = new GameDataTable.Asset(asset.Name, "rumble"); rumbleAsset["broadcast"] = header.Broadcast; rumbleAsset["camShakeDuration"] = header.CamShakeDuration; rumbleAsset["camShakeRange"] = header.CamShakeRange; rumbleAsset["camShakeScale"] = header.CamShakeScale; rumbleAsset["duration"] = header.Duration; rumbleAsset["fadeWithDistance"] = header.FadeWithDistance; rumbleAsset["pulseBoneTagPointer"] = instance.Game.GetString(header.PulseBoneTagStringIndex, instance); rumbleAsset["pulseRadiusOuter"] = header.PulseRadiusOuter; rumbleAsset["pulseScale"] = header.PulseScale; rumbleAsset["range"] = header.Range; rumbleAsset["lowrumblefile"] = WriteRumbleFile(header.LowRumbleFilePointer, instance); rumbleAsset["highrumblefile"] = WriteRumbleFile(header.HighRumbleFilePointer, instance); instance.GDTs["Physic"][rumbleAsset.Name] = rumbleAsset; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <StringTableAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } string path = Path.Combine("exported_files", instance.Game.Name, asset.Name); // Create path Directory.CreateDirectory(Path.GetDirectoryName(path)); // Read read table (raw size will = (RowCount * ColumnCount) * sizeof(StringTableCell) (which is 16) byte[] buffer = instance.Reader.ReadBytes(header.CellsPointer, (header.RowCount * header.ColumnCount) * 16); // Output result var result = new StringBuilder(); // Loop through rows for (int x = 0; x < header.RowCount; x++) { // Loop through columns for this row for (int y = 0; y < header.ColumnCount; y++) { // Add cell result.Append(instance.Reader.ReadNullTerminatedString(Bytes.BytesToStruct <StringTableAsset.Cell>(buffer, ((x * header.ColumnCount) + y) * 16).StringPointer) + ","); } // Create new line result.AppendLine(); } // Write result File.WriteAllText(path, result.ToString()); return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <TagFXAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } var tagFXAsset = new GameDataTable.Asset(asset.Name, "tagfx"); tagFXAsset["tagFXItemCount"] = header.ItemCount; var items = instance.Reader.ReadArray <TagFXItem>(header.ItemsPointer, header.ItemCount); for (int i = 0; i < items.Length; i++) { tagFXAsset["bolted" + (i + 1).ToString()] = items[i].Bolted; tagFXAsset["fx" + (i + 1).ToString()] = instance.Game.CleanAssetName(HydraAssetType.FX, instance.Game.GetAssetName(items[i].FXPointer, instance)); tagFXAsset["timeDelay" + (i + 1).ToString()] = items[i].Delay; tagFXAsset["tag" + (i + 1).ToString()] = instance.Game.GetString(items[i].TagNameIndex, instance); } instance.GDTs["Misc"][asset.Name] = tagFXAsset; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { string path = Path.Combine(instance.ExportFolder, asset.Name); Directory.CreateDirectory(Path.GetDirectoryName(path)); using (var writer = new StreamWriter(path)) { writer.WriteLine("VERSION \"1\""); writer.WriteLine("CONFIG \"C:\\projects\\cod\\t7\\bin\\StringEd.cfg\""); writer.WriteLine("FILENOTES \"Dumped via HydraX by Scobalula\""); writer.WriteLine(); var localizedStrings = instance.Reader.ReadArray <LocalizeAsset>(StartAddress, AssetCount); for (int i = 0; i < localizedStrings.Length; i++) { if (IsNullAsset(localizedStrings[i].LocalizePointer)) { continue; } writer.WriteLine("REFERENCE {0}", instance.Reader.ReadNullTerminatedString(localizedStrings[i].ReferencePointer)); writer.WriteLine("LANG_ENGLISH \"{0}\"", instance.Reader.ReadNullTerminatedString(localizedStrings[i].LocalizePointer)); writer.WriteLine(); } } return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <RawFileAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } string path = Path.Combine("exported_files", instance.Game.Name, asset.Name.Replace(".lua", ".luac")); Directory.CreateDirectory(Path.GetDirectoryName(path)); byte[] buffer; // Check for animation trees, as they are compressed using Deflate if (Path.GetExtension(path) == ".atr") { buffer = DecompressAnimTree(instance.Reader.ReadBytes(header.DataPointer + 4, (int)header.Size - 4)); } else { buffer = instance.Reader.ReadBytes(header.DataPointer, (int)header.Size); } File.WriteAllBytes(path, buffer); return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <StructuredTableAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } var data = instance.Reader.ReadArray <StructuredTableEntryData>(header.DataPointer, header.DataCount); var properties = instance.Reader.ReadArray <StructuredTableProperty>(header.PropertiesPointer, header.PropertyCount); var propertyNames = new string[header.PropertyCount]; for (int i = 0; i < propertyNames.Length; i++) { propertyNames[i] = instance.Reader.ReadNullTerminatedString(properties[i].StringPointer); } var structuredTableObj = new StructuredTableObj(header.EntryCount); for (int i = 0; i < header.EntryCount; i++) { structuredTableObj.Data[i] = new Dictionary <string, object>(); for (int j = 0; j < header.PropertyCount; j++) { var dataIndex = (i * header.PropertyCount) + j; // Switch by type, add if it's valid switch (data[dataIndex].DataType) { // Strings case EntryDataType.String: structuredTableObj.Data[i][propertyNames[j]] = instance.Reader.ReadNullTerminatedString(data[dataIndex].StringPointer); break; // Integer case EntryDataType.Int32: structuredTableObj.Data[i][propertyNames[j]] = data[dataIndex].IntegerValue; break; // Null default: break; } } } structuredTableObj.Save(Path.Combine(instance.ExportFolder, asset.Name)); // Done return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var buffer = instance.Reader.ReadBytes(asset.HeaderAddress, asset.Size); if (asset.Name != instance.Reader.ReadNullTerminatedString(BitConverter.ToInt64(buffer, 0))) { return(HydraStatus.MemoryChanged); } var result = GameDataTable.ConvertStructToGDTAsset(buffer, FootstepTableOffsets, instance); result.Type = "footsteptable"; instance.GDTs["Table"][asset.Name] = result; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <ScriptParseTreeAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } string path = Path.Combine("exported_files", instance.Game.Name, asset.Name.Replace(".gsc", ".gscc").Replace(".csc", ".cscc").Replace(".gsh", ".gshc").Replace(".lua", ".luac")); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllBytes(path, instance.Reader.ReadBytes(header.DataPointer, (int)header.Size)); return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var buffer = instance.Reader.ReadBytes(asset.HeaderAddress, asset.Size); if (asset.Name != instance.Reader.ReadNullTerminatedString(BitConverter.ToInt64(buffer, 0))) { return(HydraStatus.MemoryChanged); } var result = GameDataTable.ConvertStructToGDTAsset(buffer, VehicleFXDefOffsets, instance, HandleVehicleFXDefSettings); result.Type = "vehiclefxdef"; instance.GDTs["Misc"][asset.Name] = result; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var buffer = instance.Reader.ReadBytes(asset.HeaderAddress, asset.Size); if (asset.Name != instance.Reader.ReadNullTerminatedString(BitConverter.ToInt64(buffer, 0))) { return(HydraStatus.MemoryChanged); } var result = GameDataTable.ConvertStructToGDTAsset(buffer, AttachmentOffsets, instance, HandleAttachmentSettings); result.Type = "attachment"; // Add to GDT instance.GDTs["Weapon"][asset.Name] = result; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <AttachmentCosmeticVariantAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.FailedToFindGame); } var result = new GameDataTable.Asset(asset.Name, "attachmentcosmeticvariant"); var variants = instance.Reader.ReadArray <Variant>(header.VariantsPointer, header.VariantCount); for (int i = 0; i < variants.Length; i++) { for (int j = 0; j < variants[i].VariantModels.Length; j++) { result[string.Format("acv{0}_{1}_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = instance.Game.GetAssetName(variants[i].VariantModels[j].ModelPointer, instance); result[string.Format("acv{0}_{1}ADS_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = instance.Game.GetAssetName(variants[i].VariantModels[j].ADSModelPointer, instance); result[string.Format("acv{0}_{1}Tag_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = instance.Reader.ReadNullTerminatedString(variants[i].VariantModels[j].TagPointer); result[string.Format("acv{0}_{1}OffsetX_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = variants[i].VariantModels[j].Position.X; result[string.Format("acv{0}_{1}OffsetY_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = variants[i].VariantModels[j].Position.Y; result[string.Format("acv{0}_{1}OffsetZ_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = variants[i].VariantModels[j].Position.Z; result[string.Format("acv{0}_{1}OffsetPitch_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = variants[i].VariantModels[j].Rotation.X; result[string.Format("acv{0}_{1}OffsetYaw_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = variants[i].VariantModels[j].Rotation.Y; result[string.Format("acv{0}_{1}OffsetRoll_model{2}", i, ModelNames[j < 2 ? 0 : 1], j % 2)] = variants[i].VariantModels[j].Rotation.Z; } result[string.Format("acv{0}_description", i)] = instance.Reader.ReadNullTerminatedString(variants[i].DescriptionPointer); result[string.Format("acv{0}_displayNameShort", i)] = instance.Reader.ReadNullTerminatedString(variants[i].ShortDisplayNamePointer); result[string.Format("acv{0}_displayNameLong", i)] = instance.Reader.ReadNullTerminatedString(variants[i].LongDisplayNamePointer); result[string.Format("acv{0}_uiMaterial", i)] = instance.Game.GetAssetName(variants[i].MaterialPointer, instance, 0xF8); } instance.GDTs["Weapon"][asset.Name] = result; // Done return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <AnimationMappingTableAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.FailedToFindGame); } string path = Path.Combine(instance.AnimationTableFolder, asset.Name); Directory.CreateDirectory(Path.GetDirectoryName(path)); var maps = instance.Reader.ReadArray <AnimationMap>(header.MapsPointer, header.MapCount); using (StreamWriter writer = new StreamWriter(path)) { writer.WriteLine("#"); for (int i = 0; i < header.MapCount; i++) { writer.Write("{0},", instance.Game.GetString(maps[i].NameStringIndex, instance)); int[] indicesBuffer = instance.Reader.ReadArray <int>(maps[i].AnimationStringIndicesPointer, maps[i].AnimationCount); for (int j = 0; j < maps[i].AnimationCount; j++) { writer.Write("{0},", instance.Game.GetString(indicesBuffer[j], instance)); } writer.WriteLine(); } } // Done return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <XCamAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.FailedToFindGame); } var path = Path.Combine(instance.ExportFolder, "xanim_export", "hydra_xcams", asset.Name + ".xcam_export"); var gdtAsset = new GameDataTable.Asset(asset.Name, "xcam"); gdtAsset["hide_hud"] = header.Flags[0]; gdtAsset["is_looping"] = header.Flags[1]; gdtAsset["hide_local_player"] = header.Flags[2]; gdtAsset["use_firstperson_player"] = header.Flags[3]; gdtAsset["disableNearDof"] = header.Flags[4]; gdtAsset["autoMotionBlur"] = header.Flags[5]; gdtAsset["easeAnimationsOut"] = header.Flags[6]; gdtAsset["rightStickRotateOffsetX"] = header.RightStickRotationOffset.X; gdtAsset["rightStickRotateOffsetY"] = header.RightStickRotationOffset.Y; gdtAsset["rightStickRotateOffsetZ"] = header.RightStickRotationOffset.Z; gdtAsset["rightStickRotateMaxDegreesX"] = header.RightStickRotationDegrees.X; gdtAsset["rightStickRotateMaxDegreesY"] = header.RightStickRotationDegrees.Y; gdtAsset["parent_scene"] = instance.Reader.ReadNullTerminatedString(header.ParentScenePointer); gdtAsset["filename"] = Path.Combine("hydra_xcams", asset.Name + ".xcam_export"); instance.GDTs["XCams"][gdtAsset.Name] = gdtAsset; var xcam = new XCamObj { Cameras = new XCamObj.Camera[header.CameraCount], Notetracks = new XCamObj.Notetrack[header.NotetrackCount], CameraSwitches = new XCamObj.CameraSwitch[header.CameraSwitchPointer > 0 ? header.FrameCount : 0] }; var cameras = instance.Reader.ReadArray <XCamCamera>(header.CamerasPointer, header.CameraCount); for (int i = 0; i < cameras.Length; i++) { xcam.Cameras[i] = new XCamObj.Camera { Farz = cameras[i].FarZ, Name = instance.Game.GetString(cameras[i].NameStringIndex, instance), Animations = new XCamObj.CameraAnimation[cameras[i].AnimationCount] }; var animations = instance.Reader.ReadArray <XCamCameraAnimation>(cameras[i].AnimationsPointer, cameras[i].AnimationCount); for (int j = 0; j < animations.Length; j++) { xcam.Cameras[i].Animations[j] = new XCamObj.CameraAnimation(); Matrix matrix = new Quaternion() { X = animations[i].Rotation.X, Y = animations[i].Rotation.Y, Z = animations[i].Rotation.Z, W = animations[i].Rotation.W, }.ToMatrix(); xcam.Cameras[i].Animations[j].Dir[0] = matrix.X[0]; xcam.Cameras[i].Animations[j].Dir[1] = matrix.Y[0]; xcam.Cameras[i].Animations[j].Dir[2] = matrix.Z[0]; xcam.Cameras[i].Animations[j].Up[0] = matrix.X[2]; xcam.Cameras[i].Animations[j].Up[1] = matrix.Y[2]; xcam.Cameras[i].Animations[j].Up[2] = matrix.Z[2]; xcam.Cameras[i].Animations[j].Right[0] = matrix.X[1] * -1; xcam.Cameras[i].Animations[j].Right[1] = matrix.Y[1] * -1; xcam.Cameras[i].Animations[j].Right[2] = matrix.Z[1] * -1; xcam.Cameras[i].Animations[j].Origin[0] = animations[i].Origin.X; xcam.Cameras[i].Animations[j].Origin[1] = animations[i].Origin.Y; xcam.Cameras[i].Animations[j].Origin[2] = animations[i].Origin.Z; xcam.Cameras[i].Animations[j].FieldOfView = animations[i].FieldofView; xcam.Cameras[i].Animations[j].FocalLength = animations[i].FocalLength; xcam.Cameras[i].Animations[j].FDist = animations[i].FDist; xcam.Cameras[i].Animations[j].FStop = animations[i].FStop; xcam.Cameras[i].Animations[j].Frame = animations[i].Frame; if (j == 0) { xcam.Cameras[i].Origin = xcam.Cameras[i].Animations[j].Origin; xcam.Cameras[i].Dir = xcam.Cameras[i].Animations[j].Dir; xcam.Cameras[i].Up = xcam.Cameras[i].Animations[j].Up; xcam.Cameras[i].Right = xcam.Cameras[i].Animations[j].Right; xcam.Cameras[i].FieldOfView = xcam.Cameras[i].Animations[j].FieldOfView; xcam.Cameras[i].FocalLength = xcam.Cameras[i].Animations[j].FocalLength; xcam.Cameras[i].FDist = xcam.Cameras[i].Animations[j].FDist; xcam.Cameras[i].FStop = xcam.Cameras[i].Animations[j].FStop; } } } if (header.TargetModelRootBonePointer > 0) { var rootBone = instance.Reader.ReadStruct <XCamTargetModelRootBone>(header.TargetModelRootBonePointer); xcam.TargetModelBoneRoots = new XCamObj.TargetModelBoneRoot[1] { new XCamObj.TargetModelBoneRoot() { Name = instance.Game.GetString(rootBone.NameStringIndex, instance), Animation = new XCamObj.TargetModelBoneRootFrame[rootBone.AnimationCount] } }; var animations = instance.Reader.ReadArray <XCamTargetModelRootBoneAnimation>(rootBone.AnimationsPointer, rootBone.AnimationCount); for (int i = 0; i < rootBone.AnimationCount; i++) { Matrix matrix = new Quaternion() { X = animations[i].Rotation.X, Y = animations[i].Rotation.Y * -1, Z = animations[i].Rotation.Z * -1, W = animations[i].Rotation.W, }.ToMatrix(); xcam.TargetModelBoneRoots[0].Animation[i] = new XCamObj.TargetModelBoneRootFrame(); xcam.TargetModelBoneRoots[0].Animation[i].Offset[0] = animations[i].Origin.X; xcam.TargetModelBoneRoots[0].Animation[i].Offset[1] = animations[i].Origin.Y * -1; xcam.TargetModelBoneRoots[0].Animation[i].Offset[2] = animations[i].Origin.Z; xcam.TargetModelBoneRoots[0].Animation[i].Axis["x"] = matrix.X; xcam.TargetModelBoneRoots[0].Animation[i].Axis["y"] = matrix.Y; xcam.TargetModelBoneRoots[0].Animation[i].Axis["z"] = matrix.Z; xcam.TargetModelBoneRoots[0].Animation[i].Frame = i; } } var notetracks = instance.Reader.ReadArray <XCamNotetrack>(header.NotetracksPointer, header.NotetrackCount); for (int i = 0; i < notetracks.Length; i++) { xcam.Notetracks[i] = new XCamObj.Notetrack(instance.Game.GetString(notetracks[i].NameStringIndex, instance), notetracks[i].Frame); } if (header.CameraSwitchPointer > 0) { var switches = instance.Reader.ReadArray <XCamSwitch>(header.CameraSwitchPointer, header.FrameCount); for (int i = 0; i < switches.Length; i++) { xcam.CameraSwitches[i] = new XCamObj.CameraSwitch() { Cameras = new int[2] { switches[i].Camera1Index, switches[i].Camera2Index }, Dissolve = switches[i].Dissolve, Frame = switches[i].Frame }; } } xcam.Save(path); // Done return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <BehaviorTreeAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } BehaviorObj rootBehaviorObj = null; var behaviorObjs = new BehaviorObj[header.NodeCount]; var nodes = instance.Reader.ReadArray <Node>(header.NodesPointer, header.NodeCount); for (int i = 0; i < nodes.Length; i++) { behaviorObjs[i] = new BehaviorObj { Name = instance.Game.GetString(nodes[i].NameStringIndex, instance), Type = BehaviorTypes[nodes[i].Type], ChildIndices = instance.Reader.ReadArray <int>(nodes[i].ChildIndicesPointer, nodes[i].ChildCount), Children = nodes[i].ChildCount > 0 ? new BehaviorObj[nodes[i].ChildCount] : null }; switch (behaviorObjs[i].Type) { case "action": case "behavior_state_machine": behaviorObjs[i].ASMStateName = instance.Game.GetString(nodes[i].StringIndices[3], instance); behaviorObjs[i].ActionName = instance.Game.GetString(nodes[i].StringIndices[4], instance); behaviorObjs[i].ActionNotify = instance.Game.GetString(nodes[i].StringIndices[5], instance); behaviorObjs[i].StartFunction = instance.Game.GetString(nodes[i].StringIndices[6], instance); behaviorObjs[i].UpdateFunction = instance.Game.GetString(nodes[i].StringIndices[7], instance); behaviorObjs[i].TerminateFunction = instance.Game.GetString(nodes[i].StringIndices[8], instance); behaviorObjs[i].LoopingAction = BitConverter.ToInt32(nodes[i].Data, 0); behaviorObjs[i].ActionTimeMax = BitConverter.ToInt32(nodes[i].Data, 4); break; case "condition_script": case "condition_blackboard": case "condition_script_negate": case "condition_service_script": behaviorObjs[i].ScriptFunction = instance.Game.GetString(nodes[i].StringIndices[6], instance); behaviorObjs[i].InterruptName = instance.Game.GetString(nodes[i].StringIndices[7], instance); behaviorObjs[i].CoolDownMin = BitConverter.ToInt32(nodes[i].Data, 0); behaviorObjs[i].CooldDownMax = BitConverter.ToInt32(nodes[i].Data, 4); break; case "probability_selector": case "decorator_random": behaviorObjs[i].PercentChance = BitConverter.ToSingle(nodes[i].Data, 0); break; default: break; } if (nodes[i].ParentIndex == -1) { rootBehaviorObj = behaviorObjs[i]; } } foreach (var behaviorObj in behaviorObjs) { for (int i = 0; i < behaviorObj.ChildIndices.Length; i++) { behaviorObj.Children[i] = behaviorObjs[behaviorObj.ChildIndices[i]]; } } rootBehaviorObj.Save(Path.Combine(instance.BehaviorFolder, asset.Name)); return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <AnimationSelectorTableAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } string path = Path.Combine(instance.AnimationTableFolder, asset.Name); Directory.CreateDirectory(Path.GetDirectoryName(path)); var selectors = instance.Reader.ReadArray <AnimationSelector>(header.SelectorsPointer, header.SelectorCount); using (StreamWriter writer = new StreamWriter(path)) { for (int i = 0; i < selectors.Length; i++) { writer.WriteLine(instance.Game.GetString(selectors[i].NameStringIndex, instance)); var columns = instance.Reader.ReadArray <AnimationSelectorColumn>(selectors[i].ColumnsPointer, selectors[i].ColumnCount); for (int j = 0; j < columns.Length; j++) { writer.Write("{0},", instance.Game.GetString(columns[j].NameStringIndex, instance)); } writer.WriteLine(); var rows = instance.Reader.ReadArray <AnimationSelectorRow>(selectors[i].RowsPointer, selectors[i].RowCount); for (int j = 0; j < rows.Length; j++) { var rowColumns = instance.Reader.ReadArray <AnimationSelectorRowColumn>(rows[j].ColumnsPointer, rows[j].ColumnCount); for (int k = 0; k < columns.Length; k++) { string stringValue = instance.Game.GetString(rowColumns[k].StringIndex, instance).ToUpper(); switch (columns[k].DataType) { case ColumnDataType.String: case ColumnDataType.Enumerator: writer.Write("{0},", string.IsNullOrEmpty(stringValue) ? "*" : stringValue); break; case ColumnDataType.Int32: writer.Write("{0},", string.IsNullOrEmpty(stringValue) ? rowColumns[k].IntegerValue.ToString() : stringValue); break; case ColumnDataType.Float: case ColumnDataType.FloatMin: case ColumnDataType.FloatMax: writer.Write("{0},", string.IsNullOrEmpty(stringValue) ? rowColumns[k].FloatValue.ToString() : stringValue); break; } } writer.WriteLine(); } writer.WriteLine(","); } } // Done return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <ZBarrierAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } var zbarrierAsset = new GameDataTable.Asset(asset.Name, "zbarrier"); zbarrierAsset["generalRepairSound0"] = GetAliasByHash(header.GeneralRepairSoundHash); zbarrierAsset["generalRepairSound1"] = GetAliasByHash(header.SecondGeneralRepairSoundHash); zbarrierAsset["upgradedGeneralRepairSound0"] = GetAliasByHash(header.UpgradedGeneralRepairSoundHash); zbarrierAsset["upgradedGeneralRepairSound1"] = GetAliasByHash(header.SecondUpgradedGeneralRepairSoundHash); zbarrierAsset["useDelayBetweenGeneralRepSounds"] = header.DelayBetweenSounds.ToString(); zbarrierAsset["delayBetweenGeneralRepSounds"] = header.Delay.ToString(); zbarrierAsset["earthquakeOnRepair"] = header.EarthquakeOnRepair.ToString(); zbarrierAsset["earthquakeMinScale"] = header.EarthquakeMinScale.ToString(); zbarrierAsset["earthquakeMaxScale"] = header.EarthquakeMaxScale.ToString(); zbarrierAsset["earthquakeMinDuration"] = header.EarthquakeMinDuration.ToString(); zbarrierAsset["earthquakeMaxDuration"] = header.EarthquakeMaxDuration.ToString(); zbarrierAsset["earthquakeRadius"] = header.EarthquakeRadius.ToString(); zbarrierAsset["autoHideOpenPieces"] = header.AutoHideOpenPieces.ToString(); zbarrierAsset["taunts"] = header.ZombiesTaunt.ToString(); zbarrierAsset["reachThroughAttacks"] = header.ZombiesReachThrough.ToString(); zbarrierAsset["zombieTauntAnimState"] = instance.Game.GetString(header.AnimStateStringIndex, instance); zbarrierAsset["zombieReachThroughAnimState"] = instance.Game.GetString(header.AnimSubStateStringIndex, instance); zbarrierAsset["numAttackSlots"] = header.AttackSlotCount.ToString(); zbarrierAsset["attackSpotHorzOffset"] = header.AttackHorizontalOffset.ToString(); zbarrierAsset["collisionModel"] = instance.Game.GetAssetName(header.CollisionModelPointer, instance); for (int i = 0; i < header.PieceCount; i++) { // Add it to asset zbarrierAsset[string.Format("boardModel{0}", i + 1)] = instance.Game.GetAssetName(header.Pieces[i].PieceModelPointer, instance); zbarrierAsset[string.Format("upgradedBoardModel{0}", i + 1)] = instance.Game.GetAssetName(header.Pieces[i].UpgradedPieceModelPointer, instance); zbarrierAsset[string.Format("alternateBoardModel{0}", i + 1)] = instance.Game.GetAssetName(header.Pieces[i].AlternatePieceModelPointer, instance); zbarrierAsset[string.Format("boardAnim{0}", i + 1)] = instance.Reader.ReadNullTerminatedString(header.Pieces[i].ClosingAnimNamePointer); zbarrierAsset[string.Format("tearAnim{0}", i + 1)] = instance.Reader.ReadNullTerminatedString(header.Pieces[i].OpeningAnimNamePointer); zbarrierAsset[string.Format("boardRepairSound{0}", i + 1)] = GetAliasByHash(header.Pieces[i].BoardClosingSoundHash); zbarrierAsset[string.Format("boardRepairHoverSound{0}", i + 1)] = GetAliasByHash(header.Pieces[i].BoardClosingHoverSoundHash); zbarrierAsset[string.Format("repairFx{0}0", i + 1)] = instance.Game.CleanAssetName(HydraAssetType.FX, instance.Game.GetAssetName(header.Pieces[i].FirstClosingFXPointer, instance)); zbarrierAsset[string.Format("repairFx{0}1", i + 1)] = instance.Game.CleanAssetName(HydraAssetType.FX, instance.Game.GetAssetName(header.Pieces[i].SecondClosingFXPointer, instance)); zbarrierAsset[string.Format("OffsetRepairFxX{0}0", i + 1)] = header.Pieces[i].FirstClosingFXOffset.X.ToString(); zbarrierAsset[string.Format("OffsetRepairFxY{0}0", i + 1)] = header.Pieces[i].FirstClosingFXOffset.Y.ToString(); zbarrierAsset[string.Format("OffsetRepairFxZ{0}0", i + 1)] = header.Pieces[i].FirstClosingFXOffset.Z.ToString(); zbarrierAsset[string.Format("OffsetRepairFxX{0}1", i + 1)] = header.Pieces[i].SecondClosingFXOffset.X.ToString(); zbarrierAsset[string.Format("OffsetRepairFxY{0}1", i + 1)] = header.Pieces[i].SecondClosingFXOffset.Y.ToString(); zbarrierAsset[string.Format("OffsetRepairFxZ{0}1", i + 1)] = header.Pieces[i].SecondClosingFXOffset.Z.ToString(); zbarrierAsset[string.Format("zombieBoardTearAnimState{0}", i + 1)] = instance.Game.GetString(header.Pieces[i].AnimStateStringIndex, instance); zbarrierAsset[string.Format("zombieBoardTearAnimSubState{0}", i + 1)] = instance.Game.GetString(header.Pieces[i].AnimSubStateStringIndex, instance); zbarrierAsset[string.Format("pauseAndRepeatBoardRepairSound{0}", i + 1)] = header.Pieces[i].PauseAndRepeat.ToString(); zbarrierAsset[string.Format("pauseBetweenRepSoundsMin{0}", i + 1)] = header.Pieces[i].MinPause.ToString(); zbarrierAsset[string.Format("pauseBetweenRepSoundsMax{0}", i + 1)] = header.Pieces[i].MaxPause.ToString(); zbarrierAsset[string.Format("proBoardNumRepsToTear{0}", i + 1)] = header.Pieces[i].LoopAnimRepsCount.ToString(); } instance.GDTs["Misc"][asset.Name] = zbarrierAsset; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <BehaviorStateMachineAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } var machineObj = new BehaviorStateMachineObj() { States = new BehaviorStateMachineObj.StateObj[header.StateCount] }; var states = instance.Reader.ReadArray <State>(header.StatesPointer, header.StateCount); for (int i = 0; i < header.StateCount; i++) { machineObj.States[i] = new BehaviorStateMachineObj.StateObj() { Name = instance.Game.GetString(states[i].NameIndex, instance), AnimationStateName = instance.Game.GetString(states[i].ASMStateNameIndex, instance), EntryPointCondition = instance.Game.GetString(states[i].EntryPointConditionIndex, instance), StartFunction = !states[i].Flags.HasFlag(StateFlags.PlannerState) ? instance.Game.GetString(states[i].StartFunctionPlannerStateIndex, instance) : "", PlannerFunction = states[i].Flags.HasFlag(StateFlags.PlannerState) ? instance.Game.GetString(states[i].StartFunctionPlannerStateIndex, instance) : "", UpdateFunction = instance.Game.GetString(states[i].UpdateFunctionIndex, instance), TerminateFunction = instance.Game.GetString(states[i].TerminateFunctionIndex, instance), ActionNotify = instance.Game.GetString(states[i].ActionNotifyIndex, instance), Wildcard = states[i].Flags.HasFlag(StateFlags.WildCard), EvaluateStateForASM = states[i].Flags.HasFlag(StateFlags.EvaluateStateForASM), PlannerState = states[i].Flags.HasFlag(StateFlags.PlannerState), TerminalState = states[i].Flags.HasFlag(StateFlags.TerminalState), EntryState = states[i].Flags.HasFlag(StateFlags.EntryState), Connections = states[i].ConnectionCount > 0 ? new BehaviorStateMachineObj.ConnectionObj[states[i].ConnectionCount] : null }; var connections = instance.Reader.ReadArray <Connection>(states[i].ConnectionsPointer, states[i].ConnectionCount); for (int j = 0; j < connections.Length; j++) { machineObj.States[i].Connections[j] = new BehaviorStateMachineObj.ConnectionObj() { ToState = instance.Game.GetString(states[connections[j].ToStateIndex].NameIndex, instance), WaitTillStateFinish = connections[j].Flags.HasFlag(ConnectionFlags.WaitTillStateFinish), EvaluateDuringTransition = connections[j].Flags.HasFlag(ConnectionFlags.EvaluateDuringTransition), EvaluateOnStateFailure = connections[j].Flags.HasFlag(ConnectionFlags.EvaluateOnStateFailure), MinRunningStateTime = connections[j].MinRunningStateTime, }; } } machineObj.Save(Path.Combine(instance.BehaviorFolder, asset.Name)); // Done return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <WeaponCamoAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } var weaponCamos = instance.Reader.ReadArray <WeaponCamoEntry>(header.CamosPointer, header.CamoCount); var weaponCamoAssetNames = new string[10]; var weaponCamoAssetCount = (int)Math.Ceiling(weaponCamos.Length / 75.0); for (int i = 0; i < weaponCamoAssetCount; i++) { int camoCount = MathUtilities.Clamp(weaponCamos.Length - (i * 75), 75, 0); int baseIndex = i * 75; weaponCamoAssetNames[i] = string.Format("{0}{1}", asset.Name, i == 0 ? "_ship" : "_base" + (baseIndex + 1).ToString()); var weaponCamoAsset = new GameDataTable.Asset(weaponCamoAssetNames[i], "weaponcamo"); weaponCamoAsset.Properties["configstringFileType"] = "WEAPONCAMO"; weaponCamoAsset.Properties["baseIndex"] = baseIndex + 1; weaponCamoAsset.Properties["numCamos"] = camoCount; for (int j = 0; j < camoCount; j++) { var weaponCamoMaterial = weaponCamos[baseIndex + j]; var materials = instance.Reader.ReadArray <WeaponCamoMaterial>(weaponCamoMaterial.MaterialsCount == 0 ? 0 : weaponCamoMaterial.MaterialsPointer, weaponCamoMaterial.MaterialsCount == 0 ? 1 : weaponCamoMaterial.MaterialsCount); for (int k = 0; k < materials.Length; k++) { var weaponCamoBaseMaterials = instance.Reader.ReadArray <WeaponCamoBaseMaterial>(materials[k].BaseMaterialsPointer, materials[k].BaseMaterialCount); for (int l = 0; l < weaponCamoBaseMaterials.Length; l++) { weaponCamoAsset[string.Format("material{0}_{1}_base_material_{2}", k + 1, j + 1, l + 1)] = Path.GetFileNameWithoutExtension(instance.Game.GetAssetName(weaponCamoBaseMaterials[l].MaterialPointer, instance)); weaponCamoAsset[string.Format("material{0}_{1}_camo_mask_{2}", k + 1, j + 1, l + 1)] = instance.Game.GetAssetName(weaponCamoBaseMaterials[l].CamoMaskPointer, instance, 0xF8); } weaponCamoAsset[string.Format("material{0}_{1}_detail_normal_height", k + 1, j + 1)] = materials[k].NormalHeight; weaponCamoAsset[string.Format("material{0}_{1}_detail_normal_map", k + 1, j + 1)] = instance.Game.GetAssetName(materials[k].DetailNormalMapPointer, instance, 0xF8); weaponCamoAsset[string.Format("material{0}_{1}_detail_normal_scale_x", k + 1, j + 1)] = materials[k].NormalScale.X; weaponCamoAsset[string.Format("material{0}_{1}_detail_normal_scale_y", k + 1, j + 1)] = materials[k].NormalScale.Y; weaponCamoAsset[string.Format("material{0}_{1}_gloss_blend", k + 1, j + 1)] = materials[k].GlossMapBlend; weaponCamoAsset[string.Format("material{0}_{1}_normal_amount", k + 1, j + 1)] = materials[k].NormalBlend; weaponCamoAsset[string.Format("material{0}_{1}_material", k + 1, j + 1)] = Path.GetFileNameWithoutExtension(instance.Game.GetAssetName(materials[k].MaterialPointer, instance)); weaponCamoAsset[string.Format("material{0}_{1}_numBaseMaterials", k + 1, j + 1)] = materials[k].BaseMaterialCount; weaponCamoAsset[string.Format("material{0}_{1}_rotation", k + 1, j + 1)] = materials[k].Rotation; weaponCamoAsset[string.Format("material{0}_{1}_scale_x", k + 1, j + 1)] = materials[k].Scale.X; weaponCamoAsset[string.Format("material{0}_{1}_scale_y", k + 1, j + 1)] = materials[k].Scale.Y; weaponCamoAsset[string.Format("material{0}_{1}_trans_x", k + 1, j + 1)] = materials[k].Translation.X; weaponCamoAsset[string.Format("material{0}_{1}_trans_y", k + 1, j + 1)] = materials[k].Translation.Y; weaponCamoAsset[string.Format("material{0}_{1}_useGlossMap", k + 1, j + 1)] = materials[k].Flags.HasFlag(MaterialUsageFlags.GlossMap); weaponCamoAsset[string.Format("material{0}_{1}_useNormalMap", k + 1, j + 1)] = materials[k].Flags.HasFlag(MaterialUsageFlags.NormalMap); } } instance.GDTs["Weapon"][weaponCamoAssetNames[i]] = weaponCamoAsset; } var weaponCamoTableAsset = new GameDataTable.Asset(asset.Name, "weaponcamotable"); weaponCamoTableAsset["configstringFileType"] = "WEAPONCAMO"; weaponCamoTableAsset["numCamoTables"] = weaponCamoAssetNames.Count(x => x != null); for (int i = 0; i < weaponCamoAssetNames.Length; i++) { weaponCamoTableAsset[string.Format("table_{0:D2}_name", i + 1)] = weaponCamoAssetNames[i]; } instance.GDTs["Weapon"][asset.Name] = weaponCamoTableAsset; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <MaterialAsset>(asset.HeaderAddress); if (asset.Name != Path.GetFileNameWithoutExtension(instance.Reader.ReadNullTerminatedString(header.NamePointer).Split('|')[0])) { return(HydraStatus.MemoryChanged); } // We need the techset for buffer info var techset = instance.Reader.ReadStruct <MaterialTechniqueSet>(header.TechniquePointer); var mtlType = Path.GetFileNameWithoutExtension(instance.Reader.ReadNullTerminatedString(instance.Reader.ReadInt64(header.TechniquePointer)).Split('#')[0]); if (!instance.TechniqueSetCache.TryGetValue(mtlType, out var set)) { throw new ArgumentException("Unknown material type.", mtlType); } // Add base stuffs // Create asset var gdtAsset = new GameDataTable.Asset(asset.Name, "material"); // Set Default Properties gdtAsset.Properties.Add("surfaceType", SurfaceTypes.TryGetValue(BitConverter.ToUInt32(header.FlagsAndSettings, 28), out var surfaceType) ? surfaceType : "<none>"); gdtAsset.Properties.Add("template", "material.template"); gdtAsset.Properties.Add("materialCategory", set.Category); gdtAsset.Properties.Add("materialType", mtlType); gdtAsset.Properties.Add("textureAtlasRowCount", header.FlagsAndSettings[6].ToString()); gdtAsset.Properties.Add("textureAtlasColumnCount", header.FlagsAndSettings[7].ToString()); gdtAsset.Properties.Add("usage", "<not in editor>"); for (int i = 0; i < header.SettingsPointers.Length; i++) { if (header.SettingsPointers[i].SettingsPointer == 0) { continue; } var technique = instance.Reader.ReadStruct <MaterialTechnique>(techset.TechniquePointers[i]); var pass = instance.Reader.ReadStruct <MaterialTechniquePass>(technique.PassPointer); var settings = ParseDXBC(instance.Reader.ReadBytes(pass.ShaderPointer, pass.ShaderSize)); if (settings == null) { throw new ArgumentException("Failed to find $Globals in DirectX Byte Code RDEF part", "settings"); } var settingsInfo = instance.Reader.ReadStruct <MaterialSettingBuffer>(header.SettingsPointers[i].SettingsPointer); var settingsBuffer = instance.Reader.ReadBytes(settingsInfo.BufferPointer, (int)settingsInfo.Size); foreach (var setting in settings) { if (set.Settings.TryGetValue(setting.Key, out var gdtInfo)) { switch (gdtInfo.DataType) { case SettingDataType.Boolean: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = (int)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } break; } case SettingDataType.UInt1: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } break; } case SettingDataType.UInt2: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[1])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 04), gdtInfo.PostProcessor); } break; } case SettingDataType.UInt3: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[1])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 04), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[2])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 08), gdtInfo.PostProcessor); } break; } case SettingDataType.UInt4: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[1])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 04), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[2])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 08), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[3])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = (uint)PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 12), gdtInfo.PostProcessor); } break; } case SettingDataType.Float1: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } break; } case SettingDataType.Float2: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[1])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 04), gdtInfo.PostProcessor); } break; } case SettingDataType.Float3: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[1])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 04), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[2])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 08), gdtInfo.PostProcessor); } break; } case SettingDataType.Float4: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { gdtAsset[gdtInfo.GDTSlotNames[0]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[1])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 04), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[2])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 08), gdtInfo.PostProcessor); } if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[3])) { gdtAsset[gdtInfo.GDTSlotNames[1]] = PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 12), gdtInfo.PostProcessor); } break; } case SettingDataType.Color: { if (!gdtAsset.Properties.ContainsKey(gdtInfo.GDTSlotNames[0])) { var r = MathUtilities.Clamp(PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 00), gdtInfo.PostProcessor), 1.0, 0.0); var g = MathUtilities.Clamp(PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 04), gdtInfo.PostProcessor), 1.0, 0.0); var b = MathUtilities.Clamp(PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 08), gdtInfo.PostProcessor), 1.0, 0.0); var a = MathUtilities.Clamp(PerformPostProcess(BitConverter.ToSingle(settingsBuffer, setting.Value + 12), gdtInfo.PostProcessor), 1.0, 0.0); gdtAsset[gdtInfo.GDTSlotNames[0]] = string.Format("{0:0.000000} {1:0.000000} {2:0.000000} {3:0.000000}", r, g, b, a); } break; } } } } } for (int j = 0; j < header.Counts[0]; j++) { var materialImage = instance.Reader.ReadStruct <MaterialImage>(header.ImageTablePointer + (j * 0x20)); if (set.ImageSlots.TryGetValue(materialImage.SemanticHash, out string slot)) { gdtAsset.Properties[slot] = instance.Reader.ReadNullTerminatedString(instance.Reader.ReadInt64(materialImage.ImagePointer + 0xF8)); } } instance.GDTs["Misc"][asset.Name] = gdtAsset; return(HydraStatus.Success); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <CustomizationTableAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.MemoryChanged); } var customizationTable = new GameDataTable.Asset(asset.Name, "charactercustomizationtable"); customizationTable["bodyTypeCount"] = header.BodyCount; customizationTable["headCount"] = header.HeadCount; var playerHeads = instance.Reader.ReadArray <PlayerHeadAsset>(header.HeadsPointer, header.HeadCount); for (int i = 0; i < playerHeads.Length; i++) { string name = instance.Reader.ReadNullTerminatedString(playerHeads[i].NamePointer); var playerHead = new GameDataTable.Asset(name, "playerhead"); playerHead["displayName"] = instance.Reader.ReadNullTerminatedString(playerHeads[i].DisplayNamePointer); playerHead["iconImage"] = instance.Game.GetAssetName(playerHeads[i].IconPointer, instance, 0xF8); playerHead["model"] = instance.Game.GetAssetName(playerHeads[i].ModelPointer, instance); playerHead["gender"] = (int)playerHeads[i].Gender; customizationTable["head" + (i + 1).ToString("00")] = playerHead.Name; instance.GDTs["Character"][playerHead.Name] = playerHead; } var playerBodyTypes = instance.Reader.ReadArray <PlayerBodyTypeAsset>(header.BodiesPointer, header.BodyCount); for (int i = 0; i < playerBodyTypes.Length; i++) { var playerBodyType = new GameDataTable.Asset(instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].NamePointer), "playerbodytype"); playerBodyType["abilityCardBackDesc"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].AbilityCardBackDescPointer); playerBodyType["abilityCardBackIcon"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].AbilityCardBackIconPointer); playerBodyType["abilityCardBackSubIcon"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].AbilityCardBackSubIconPointer); playerBodyType["abilityIconEquipped"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].AbilityIconEquippedPointer); playerBodyType["abilityIconUnequipped"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].AbilityIconUnequippedPointer); playerBodyType["abilitySchema"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].AbilitySchemaPointer); playerBodyType["abilitySubItemDesc"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].AbilitySubItemDescPointer); playerBodyType["age"] = playerBodyTypes[i].Age; playerBodyType["background"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].BackgroundPointer); playerBodyType["backgroundWithCharacter"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].BackgroundWithCharacterPointer); playerBodyType["bio"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].BioPointer); playerBodyType["bodySoundContext"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].BodySoundContextPointer); playerBodyType["bodyStyleCount"] = playerBodyTypes[i].BodyStyleCount; playerBodyType["cardBackIcon"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].CardBackIconPointer); playerBodyType["characterFootstepsNPCLoud"] = instance.Game.GetAssetName(playerBodyTypes[i].CharacterFootstepsNPCLoudPointer, instance); playerBodyType["characterFootstepsNPC"] = instance.Game.GetAssetName(playerBodyTypes[i].CharacterFootstepsNPCPointer, instance); playerBodyType["characterFootstepsNPCQuiet"] = instance.Game.GetAssetName(playerBodyTypes[i].CharacterFootstepsNPCQuietPointer, instance); playerBodyType["characterFootsteps"] = instance.Game.GetAssetName(playerBodyTypes[i].CharacterFootstepsPointer, instance); playerBodyType["characterFootstepsQuiet"] = instance.Game.GetAssetName(playerBodyTypes[i].CharacterFootstepsQuietPointer, instance); playerBodyType["characterMovementFx"] = instance.Game.GetAssetName(playerBodyTypes[i].CharacterMovementFxPointer, instance); playerBodyType["characterMovementSounds"] = instance.Game.GetAssetName(playerBodyTypes[i].CharacterMovementSoundsPointer, instance); playerBodyType["defaultHeroRenderAbility"] = instance.Game.GetAssetName(playerBodyTypes[i].DefaultHeroRenderAbilityPointer, instance, 0xF8); playerBodyType["defaultHeroRender"] = instance.Game.GetAssetName(playerBodyTypes[i].DefaultHeroRenderPointer, instance, 0xF8); playerBodyType["description"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].DescriptionPointer); playerBodyType["disabled"] = playerBodyTypes[i].Disabled; playerBodyType["displayName"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].DisplayNamePointer); playerBodyType["dogTagEnemy"] = instance.Game.GetAssetName(playerBodyTypes[i].DogTagEnemyPointer, instance); playerBodyType["dogtagFriendly"] = instance.Game.GetAssetName(playerBodyTypes[i].DogtagFriendlyPointer, instance); playerBodyType["frontendVignetteStruct"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].FrontendVignetteStructPointer); playerBodyType["frontendVignetteWeaponModel"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].FrontendVignetteWeaponModelPointer); playerBodyType["frontendVignetteXAnim"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].FrontendVignetteXAnimPointer); playerBodyType["frontendVignetteXCam"] = instance.Game.GetAssetName(playerBodyTypes[i].FrontendVignetteXCamPointer, instance); playerBodyType["frozenMomentOverlay"] = instance.Game.GetAssetName(playerBodyTypes[i].FrozenMomentOverlayPointer, instance); playerBodyType["frozenMomentRender"] = instance.Game.GetAssetName(playerBodyTypes[i].FrozenMomentRenderPointer, instance); playerBodyType["gender"] = (int)playerBodyTypes[i].Gender; playerBodyType["genderString"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].GenderStringPointer); playerBodyType["helmetStyleCount"] = playerBodyTypes[i].HelmetStyleCount; playerBodyType["heroAbility"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].HeroAbilityPointer); playerBodyType["heroWeapon"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].HeroWeaponPointer); playerBodyType["lockedImage"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].LockedImagePointer); playerBodyType["mpDialog"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].MpDialogPointer); playerBodyType["personalizeRender"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].PersonalizeRenderPointer); playerBodyType["realName"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].RealNamePointer); playerBodyType["rewardIcon"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].RewardIconPointer); playerBodyType["weaponCardBackDesc"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].WeaponCardBackDescPointer); playerBodyType["weaponCardBackIcon"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].WeaponCardBackIconPointer); playerBodyType["weaponCardBackSubIcon"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].WeaponCardBackSubIconPointer); playerBodyType["weaponIconEquipped"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].WeaponIconEquippedPointer); playerBodyType["weaponIconUnequipped"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].WeaponIconUnequippedPointer); playerBodyType["weaponSchema"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].WeaponSchemaPointer); playerBodyType["weaponSubItemDesc"] = instance.Reader.ReadNullTerminatedString(playerBodyTypes[i].WeaponSubItemDescPointer); playerBodyType["zombiePlayerIcon"] = instance.Game.GetAssetName(playerBodyTypes[i].ZombiePlayerIconPointer, instance, 0xF8); var playerBodyStyles = instance.Reader.ReadArray <PlayerBodyStyleAsset>(playerBodyTypes[i].BodyStylesPointer, playerBodyTypes[i].BodyStyleCount); for (int j = 0; j < playerBodyStyles.Length; j++) { var playerBodyStyle = new GameDataTable.Asset(instance.Reader.ReadNullTerminatedString(playerBodyStyles[j].NamePointer), "playerbodystyle"); playerBodyStyle["accentColorCount"] = playerBodyStyles[j].AccentColorCount; playerBodyStyle["characterMovementFxOverride"] = instance.Game.GetAssetName(playerBodyStyles[j].CharacterMovementFxOverridePointer, instance); playerBodyStyle["displayName"] = instance.Reader.ReadNullTerminatedString(playerBodyStyles[j].DisplayNamePointer); playerBodyStyle["firstPersonCinematicModel"] = instance.Game.GetAssetName(playerBodyStyles[j].FirstPersonCinematicModelPointer, instance); playerBodyStyle["firstPersonLegsModel"] = instance.Game.GetAssetName(playerBodyStyles[j].FirstPersonLegsModelPointer, instance); playerBodyStyle["gibDef"] = instance.Game.GetAssetName(playerBodyStyles[j].GibDefPointer, instance); playerBodyStyle["gibLegsBoth"] = instance.Game.GetAssetName(playerBodyStyles[j].GibLegsBothPointer, instance); playerBodyStyle["gibLegsClean"] = instance.Game.GetAssetName(playerBodyStyles[j].GibLegsCleanPointer, instance); playerBodyStyle["gibLegsLeft"] = instance.Game.GetAssetName(playerBodyStyles[j].GibLegsLeftPointer, instance); playerBodyStyle["gibLegsRight"] = instance.Game.GetAssetName(playerBodyStyles[j].GibLegsRightPointer, instance); playerBodyStyle["gibTorsoClean"] = instance.Game.GetAssetName(playerBodyStyles[j].GibTorsoCleanPointer, instance); playerBodyStyle["gibTorsoLeft"] = instance.Game.GetAssetName(playerBodyStyles[j].GibTorsoLeftPointer, instance); playerBodyStyle["gibTorsoRight"] = instance.Game.GetAssetName(playerBodyStyles[j].GibTorsoRightPointer, instance); playerBodyStyle["iconImage"] = instance.Game.GetAssetName(playerBodyStyles[j].IconImagePointer, instance, 0xF8); playerBodyStyle["impactTypeCorpse"] = ImpactTypes[playerBodyStyles[j].ImpactTypeCorpse]; playerBodyStyle["impactType"] = ImpactTypes[playerBodyStyles[j].ImpactType]; playerBodyStyle["viewArmsModel"] = instance.Game.GetAssetName(playerBodyStyles[j].ViewArmsModelPointer, instance); playerBodyStyle["xmodel"] = instance.Game.GetAssetName(playerBodyStyles[j].XmodelPointer, instance); var accents = instance.Reader.ReadArray <PlayerAccent>(playerBodyStyles[j].AccentsPointer, playerBodyStyles[j].AccentColorCount); for (int k = 0; k < accents.Length; k++) { var accentOptions = instance.Reader.ReadArray <long>(accents[k].DataPointer, accents[k].DataCount); playerBodyStyle[string.Format("accentColor{0}OptionsCount", k + 1)] = accents[k].DataCount; for (int l = 0; l < accentOptions.Length; l++) { playerBodyStyle[string.Format("color_{0}_{1}", k + 1, l + 1)] = instance.Game.GetAssetName(accentOptions[l], instance); } } playerBodyType["bodyStyle" + (j + 1).ToString("00")] = playerBodyStyle.Name; instance.GDTs["Character"][playerBodyStyle.Name] = playerBodyStyle; } var playerHelmetStyles = instance.Reader.ReadArray <PlayerBodyStyleAsset>(playerBodyTypes[i].HelmetStylesPointer, playerBodyTypes[i].HelmetStyleCount); for (int j = 0; j < playerHelmetStyles.Length; j++) { var playerHelmetStyle = new GameDataTable.Asset(instance.Reader.ReadNullTerminatedString(playerHelmetStyles[j].NamePointer), "playerhelmetstyle"); playerHelmetStyle["accentColorCount"] = playerHelmetStyles[j].AccentColorCount; playerHelmetStyle["displayName"] = instance.Reader.ReadNullTerminatedString(playerHelmetStyles[j].DisplayNamePointer); playerHelmetStyle["iconImage"] = instance.Game.GetAssetName(playerHelmetStyles[j].IconImagePointer, instance, 0xF8); playerHelmetStyle["impactTypeCorpse"] = ImpactTypes[playerHelmetStyles[j].ImpactTypeCorpse]; playerHelmetStyle["impactType"] = ImpactTypes[playerHelmetStyles[j].ImpactType]; playerHelmetStyle["xmodel"] = instance.Game.GetAssetName(playerHelmetStyles[j].XmodelPointer, instance); var accents = instance.Reader.ReadArray <PlayerAccent>(playerHelmetStyles[j].AccentsPointer, playerHelmetStyles[j].AccentColorCount); for (int k = 0; k < accents.Length; k++) { var accentOptions = instance.Reader.ReadArray <long>(accents[k].DataPointer, accents[k].DataCount); playerHelmetStyle[string.Format("accentColor{0}OptionsCount", k + 1)] = accents[k].DataCount; for (int l = 0; l < accentOptions.Length; l++) { playerHelmetStyle[string.Format("color_{0}_{1}", k + 1, l + 1)] = instance.Game.GetAssetName(accentOptions[l], instance); } } playerBodyType["helmetStyle" + (j + 1).ToString("00")] = playerHelmetStyle.Name; instance.GDTs["Character"][playerHelmetStyle.Name] = playerHelmetStyle; } var dataBlocks = instance.Reader.ReadArray <KVPBlock>(playerBodyTypes[i].DataBlocksPointer, playerBodyTypes[i].DataBlockCount); for (int j = 0; j < dataBlocks.Length; j++) { // Determine type if we're int, since bool and int share same, but the pointer value will be different? (only 2 are bool anyway but just in case) var dataType = dataBlocks[i].DataType; if (dataType == DataTypes.Int && (dataBlocks[i].DataPointer & 0xFFFFFFFF) != dataBlocks[i].Data) { dataType = DataTypes.Bool; } string propertyName = string.Format("{0}_{1}", dataType.ToString().ToLower(), instance.Game.GetString(dataBlocks[i].DataNameStringIndex, instance)); playerBodyType[propertyName] = dataBlocks[i].DataType == DataTypes.Int ? dataBlocks[i].Data.ToString() : instance.Game.GetString(dataBlocks[i].DataStringIndex, instance); } customizationTable["bodyType" + (i + 1).ToString("00")] = playerBodyType.Name; instance.GDTs["Character"][playerBodyType.Name] = playerBodyType; } instance.GDTs["Character"][customizationTable.Name] = customizationTable; return(HydraStatus.Success); }
/// <summary> /// Checks if the given asset is a null slot /// </summary> public bool IsNullAsset(GameAsset asset) { return(IsNullAsset(asset.NameLocation)); }
/// <summary> /// Exports the given asset from this pool /// </summary> public HydraStatus Export(GameAsset asset, HydraInstance instance) { var header = instance.Reader.ReadStruct <AnimationStateMachineAsset>(asset.HeaderAddress); if (asset.Name != instance.Reader.ReadNullTerminatedString(header.NamePointer)) { return(HydraStatus.FailedToFindGame); } var transitionObjects = new AnimationStateMachineObj.StateObj[header.TransitionCount]; var transitions = instance.Reader.ReadArray <Transition>(header.TransitionsPointer, header.TransitionCount); for (int i = 0; i < header.TransitionCount; i++) { transitionObjects[i] = new AnimationStateMachineObj.StateObj() { Name = instance.Game.GetString(transitions[i].NameStringIndex, instance), AnimationSelector = instance.Game.GetString(transitions[i].AnimationSelectorStringIndex, instance), AimSelector = instance.Game.GetString(transitions[i].AimSelectorStringIndex, instance), ShootSelector = instance.Game.GetString(transitions[i].ShootSelectorStringIndex, instance), DeltaLayerFunction = instance.Game.GetString(transitions[i].DeltaLayerFunctionStringIndex, instance), ASMClientNotify = instance.Game.GetString(transitions[i].ASMClientNofityStringIndex, instance), RequiresRagdollNote = transitions[i].Requirements.HasFlag(Requirements.RequiresRagdollNotetrack), DeltaRequiresTranslation = transitions[i].Requirements.HasFlag(Requirements.DeltaRequiresTranslation), Terminal = transitions[i].Flags.HasFlag(Flags.Terminal), LoopSync = transitions[i].Flags.HasFlag(Flags.LoopSync), MultipleDelta = transitions[i].Flags.HasFlag(Flags.MultipleDelta), Parametric2D = transitions[i].Flags.HasFlag(Flags.Parametric2D), Coderate = transitions[i].Flags.HasFlag(Flags.Coderate), AllowTransDecAim = transitions[i].Flags.HasFlag(Flags.AllowTransDecAim), ForceFire = transitions[i].Flags.HasFlag(Flags.ForceFire), CleanLoop = transitions[i].Flags.HasFlag(Flags.CleanLoop), AnimDrivenLocmotion = transitions[i].Flags.HasFlag(Flags.AnimDrivenLocmotion), SpeedBlend = transitions[i].Flags.HasFlag(Flags.SpeedBlend), }; } var subStateObjects = new AnimationStateMachineObj.StateObj[header.SubStateCount]; var subStates = instance.Reader.ReadArray <SubState>(header.SubStatesPointer, header.SubStateCount); for (int i = 0; i < header.SubStateCount; i++) { subStateObjects[i] = new AnimationStateMachineObj.StateObj() { Name = instance.Game.GetString(subStates[i].NameStringIndex, instance), AnimationSelector = instance.Game.GetString(subStates[i].AnimationSelectorStringIndex, instance), AimSelector = instance.Game.GetString(subStates[i].AimSelectorStringIndex, instance), ShootSelector = instance.Game.GetString(subStates[i].ShootSelectorStringIndex, instance), TransitionDecorator = instance.Game.GetString(subStates[i].TransitionDecoratorStringIndex, instance), DeltaLayerFunction = instance.Game.GetString(subStates[i].DeltaLayerFunctionStringIndex, instance), TransDecLayerFunction = instance.Game.GetString(subStates[i].TransDecLayerFunctionStringIndex, instance), ASMClientNotify = instance.Game.GetString(subStates[i].ASMClientNofityStringIndex, instance), RequiresRagdollNote = subStates[i].Requirements.HasFlag(Requirements.RequiresRagdollNotetrack), DeltaRequiresTranslation = subStates[i].Requirements.HasFlag(Requirements.DeltaRequiresTranslation), Terminal = subStates[i].Flags.HasFlag(Flags.Terminal), LoopSync = subStates[i].Flags.HasFlag(Flags.LoopSync), MultipleDelta = subStates[i].Flags.HasFlag(Flags.MultipleDelta), Parametric2D = subStates[i].Flags.HasFlag(Flags.Parametric2D), Coderate = subStates[i].Flags.HasFlag(Flags.Coderate), AllowTransDecAim = subStates[i].Flags.HasFlag(Flags.AllowTransDecAim), ForceFire = subStates[i].Flags.HasFlag(Flags.ForceFire), CleanLoop = subStates[i].Flags.HasFlag(Flags.CleanLoop), AnimDrivenLocmotion = subStates[i].Flags.HasFlag(Flags.AnimDrivenLocmotion), SpeedBlend = subStates[i].Flags.HasFlag(Flags.SpeedBlend), Transitions = subStates[i].TransitionCount > 0 ? new Dictionary <string, AnimationStateMachineObj.StateObj>() : null, }; var indices = instance.Reader.ReadArray <int>(subStates[i].TransitionIndicesPointer, subStates[i].TransitionCount); foreach (var index in indices) { subStateObjects[i].Transitions[transitionObjects[index].Name] = transitionObjects[index]; } } var animStateMachine = new AnimationStateMachineObj { RootStates = new Dictionary <string, Dictionary <string, AnimationStateMachineObj.StateObj> >() }; var rootStates = instance.Reader.ReadArray <RootState>(header.RootStatesPointer, header.RootStateCount); for (int i = 0; i < rootStates.Length; i++) { var name = instance.Game.GetString(rootStates[i].NameStringIndex, instance); animStateMachine.RootStates[name] = new Dictionary <string, AnimationStateMachineObj.StateObj>(); var indices = instance.Reader.ReadArray <int>(rootStates[i].SubStateIndicesPointer, rootStates[i].SubStateCount); foreach (var index in indices) { animStateMachine.RootStates[name][subStateObjects[index].Name] = subStateObjects[index]; } } animStateMachine.Save(Path.Combine(instance.AnimationStateMachinesFolder, asset.Name)); // Done return(HydraStatus.Success); }