public static void SaveModel(ICLIFlags flags, string path, SaveContext info, ulong modelGUID) { bool convertModels = true; bool doRefpose = false; bool doStu = false; byte lod = 1; if (flags is ExtractFlags extractFlags) { convertModels = !extractFlags.RawModels && !extractFlags.Raw; doRefpose = extractFlags.ExtractRefpose; doStu = extractFlags.ExtractModelStu; lod = extractFlags.LOD; if (extractFlags.SkipModels) { return; } } FindLogic.Combo.ModelAsset modelInfo = info.m_info.m_models[modelGUID]; string modelDirectory = Path.Combine(path, "Models", modelInfo.GetName()); if (convertModels) { string modelPath = Path.Combine(modelDirectory, $"{modelInfo.GetNameIndex()}.owmdl"); using (Stream modelStream = OpenFile(modelInfo.m_GUID)) { if (modelStream == null) { return; } CreateDirectoryFromFile(modelPath); teChunkedData chunkedData = new teChunkedData(modelStream); OverwatchModel model = new OverwatchModel(chunkedData, modelInfo.m_GUID, (sbyte)lod); if (modelInfo.m_modelLooks.Count > 0) { FindLogic.Combo.ModelLookAsset modelLookInfo = info.m_info.m_modelLooks[modelInfo.m_modelLooks.First()]; model.ModelLookFileName = Path.Combine("ModelLooks", modelLookInfo.GetNameIndex() + ".owmat"); } using (Stream fileStream = File.OpenWrite(modelPath)) { fileStream.SetLength(0); model.Write(fileStream); } if (doRefpose) { string refposePath = Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".smd"); using (Stream fileStream = File.OpenWrite(refposePath)) { fileStream.SetLength(0); var refpose = new RefPoseSkeleton(chunkedData); refpose.Write(fileStream); } } if (doStu) { var stu = chunkedData.GetChunks <teModelChunk_STU>().Select(x => x.StructuredData).ToArray(); string stuPath = Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".json"); JSONTool.OutputJSONAlt(stu, new ListFlags { Output = stuPath }, false); } } } else { using (Stream modelStream = OpenFile(modelInfo.m_GUID)) { WriteFile(modelStream, Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".00C")); } } foreach (ulong modelModelLook in modelInfo.m_modelLooks) { SaveModelLook(flags, modelDirectory, info, modelModelLook); } foreach (ulong looseMaterial in modelInfo.m_looseMaterials) { SaveMaterial(flags, modelDirectory, info, looseMaterial); } foreach (ulong modelAnimation in modelInfo.n_animations) { SaveAnimation(flags, modelDirectory, info, modelAnimation, modelGUID); } }
public static void SaveModel(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong modelGUID) { bool convertModels = true; bool doRefpose = false; byte lod = 1; if (flags is ExtractFlags extractFlags) { convertModels = extractFlags.ConvertModels && !extractFlags.Raw; doRefpose = extractFlags.ExtractRefpose; lod = extractFlags.LOD; if (extractFlags.SkipModels) { return; } } FindLogic.Combo.ModelInfoNew modelInfo = info.Models[modelGUID]; string modelDirectory = Path.Combine(path, "Models", modelInfo.GetName()); if (convertModels) { string modelPath = Path.Combine(modelDirectory, $"{modelInfo.GetNameIndex()}.owmdl"); CreateDirectoryFromFile(modelPath); using (Stream modelStream = OpenFile(modelInfo.GUID)) { teChunkedData chunkedData = new teChunkedData(modelStream); OverwatchModel model = new OverwatchModel(chunkedData, modelInfo.GUID, (sbyte)lod); if (modelInfo.ModelLooks.Count > 0) { FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[modelInfo.ModelLooks.First()]; model.ModelLookFileName = Path.Combine("ModelLooks", modelLookInfo.GetNameIndex() + ".owmat"); } using (Stream fileStream = File.OpenWrite(modelPath)) { fileStream.SetLength(0); model.Write(fileStream); } if (doRefpose) { string refposePath = Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".smd"); using (Stream fileStream = File.OpenWrite(refposePath)) { fileStream.SetLength(0); var refpose = new RefPoseSkeleton(chunkedData); refpose.Write(fileStream); } } } } else { using (Stream modelStream = OpenFile(modelInfo.GUID)) { WriteFile(modelStream, Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".00C")); } } foreach (ulong modelModelLook in modelInfo.ModelLooks) { SaveModelLook(flags, modelDirectory, info, modelModelLook); } foreach (ulong looseMaterial in modelInfo.LooseMaterials) { SaveMaterial(flags, modelDirectory, info, looseMaterial); } foreach (ulong modelAnimation in modelInfo.Animations) { SaveAnimation(flags, modelDirectory, info, modelAnimation, modelGUID); } }
public static void TryConvertFile(Stream stream, string convertDir, string md5) { using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true)) { uint magic = reader.ReadUInt32(); stream.Position = 0; if (magic == teChunkedData.Magic) { teChunkedData chunkedData = new teChunkedData(reader); if (chunkedData.Header.StringIdentifier == "MODL") { OverwatchModel model = new OverwatchModel(chunkedData, 0); using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + ".owmdl")) { file.SetLength(0); model.Write(file); } } } else if (magic == 0x4D4F5649) // MOVI { stream.Position = 128; using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + ".bk2")) { file.SetLength(0); stream.CopyTo(file); } } else { // ok might be a heckin bundle /*int i = 0; * while (reader.BaseStream.Position < reader.BaseStream.Length) { * try { * magic = reader.ReadUInt32(); * if (magic != teChunkedData.Magic) { * reader.BaseStream.Position -= 3; * continue; * } * reader.BaseStream.Position -= 4; * teChunkedData chunkedData = new teChunkedData(reader); * if (chunkedData.Header.StringIdentifier == "MODL") { * OverwatchModel model = new OverwatchModel(chunkedData, 0); * using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + $"-{i}.owmdl")) { * file.SetLength(0); * model.Write(file); * } * } * * i++; * } catch (Exception) { * // fine * } * }*/ try { //teStructuredData structuredData =new teStructuredData(stream, true); teTexture texture = new teTexture(reader); if (!texture.PayloadRequired && texture.Header.DataSize <= stream.Length && (texture.Header.Flags == teTexture.Flags.Tex1D || texture.Header.Flags == teTexture.Flags.Tex2D || texture.Header.Flags == teTexture.Flags.Tex3D || texture.Header.Flags == teTexture.Flags.Cube || texture.Header.Flags == teTexture.Flags.Array || texture.Header.Flags == teTexture.Flags.Unk16 || texture.Header.Flags == teTexture.Flags.Unk32 || texture.Header.Flags == teTexture.Flags.Unk128) && texture.Header.Height < 10000 && texture.Header.Width < 10000 && texture.Header.DataSize > 68) { using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + ".dds")) { file.SetLength(0); texture.SaveToDDS(file, false, texture.Header.MipCount); } } } catch (Exception) { // fine } try { stream.Position = 0; teStructuredData structuredData = new teStructuredData(stream, true); if (structuredData.GetInstance <STUResourceKey>() != null) { var key = structuredData.GetInstance <STUResourceKey>(); Console.Out.WriteLine("found key"); var longKey = ulong.Parse(key.m_keyID, NumberStyles.HexNumber); var longRevKey = BitConverter.ToUInt64(BitConverter.GetBytes(longKey).Reverse().ToArray(), 0); var keyValueString = BitConverter.ToString(key.m_key).Replace("-", string.Empty); var keyNameProper = longRevKey.ToString("X16"); Console.Out.WriteLine("Added Encryption Key {0}, Value: {1}", keyNameProper, keyValueString); } // if (structuredData.GetInstance<STUHero>() != null) { // // } } catch (Exception) { // fine } } } }