public void Write(Stream stream) { using (BinaryWriter writer = new BinaryWriter(stream)) { writer.Write(Extension); // type identifier writer.Write(VersionMajor); writer.Write(VersionMinor); writer.Write(Entity.GetNameIndex()); if (Entity.m_modelGUID != 0) { FindLogic.Combo.ModelAsset modelInfo = Info.m_models[Entity.m_modelGUID]; writer.Write(modelInfo.GetName()); } else { writer.Write("null"); } if (Entity.m_effectGUID != 0) { FindLogic.Combo.EffectInfoCombo effectInfo = Info.m_effects[Entity.m_effectGUID]; writer.Write(effectInfo.GetName()); } else { writer.Write("null"); } writer.Write(teResourceGUID.Index(Entity.m_GUID)); writer.Write(teResourceGUID.Index(Entity.m_modelGUID)); writer.Write(teResourceGUID.Index(Entity.m_effectGUID)); if (Entity.Children == null) { writer.Write(0); return; } writer.Write(Entity.Children.Count(x => x.m_defGUID != 0)); foreach (FindLogic.Combo.ChildEntityReference childEntityReference in Entity.Children.Where(x => x.m_defGUID != 0)) { FindLogic.Combo.EntityAsset childEntityInfo = Info.m_entities[childEntityReference.m_defGUID]; writer.Write(childEntityInfo.GetName()); writer.Write(childEntityReference.m_hardpointGUID); writer.Write(childEntityReference.m_identifier); writer.Write(teResourceGUID.Index(childEntityReference.m_hardpointGUID)); writer.Write(teResourceGUID.Index(childEntityReference.m_identifier)); if (childEntityReference.m_hardpointGUID != 0) { writer.Write(OverwatchModel.IdToString("hardpoint", teResourceGUID.Index(childEntityReference.m_hardpointGUID))); } else { writer.Write("null"); // erm, k } } } }
public override void Write(Stream stream) { using (BinaryWriter writer = new BinaryWriter(stream)) { writer.Write(Extension); writer.Write(AnimVersionMajor); writer.Write(AnimVersionMinor); writer.Write(teResourceGUID.Index(Animation.m_GUID)); writer.Write(Animation.m_fps); writer.Write((int)OWAnimType.Data); FindLogic.Combo.ModelAsset modelInfo = Info.m_models[Model]; writer.Write($"Models\\{modelInfo.GetName()}\\Animations\\{Animation.m_priority}\\{Animation.GetNameIndex()}.seanim"); writer.Write($"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}.owmdl"); // wrap oweffect WriteEffect(writer); } }
public void Write(Stream stream) { using (BinaryWriter writer = new BinaryWriter(stream)) { writer.Write(Extension); // identifier writer.Write(OverwatchAnimationEffect.AnimVersionMajor); writer.Write(OverwatchAnimationEffect.AnimVersionMinor); writer.Write(teResourceGUID.Index(Animation.m_GUID)); writer.Write(Animation.m_fps); writer.Write((int)OverwatchAnimationEffect.OWAnimType.Reference); FindLogic.Combo.ModelAsset modelInfo = Info.m_models[Model]; writer.Write($"Models\\{modelInfo.GetName()}\\{OverwatchAnimationEffect.AnimationEffectDir}\\{Animation.GetNameIndex()}\\{Animation.GetNameIndex()}.{Extension}"); // so I can change it in DataTool and not go mad } }
protected void WriteEffect(BinaryWriter writer) { writer.Write("oweffect"); writer.Write(EffectVersionMajor); writer.Write(EffectVersionMinor); EffectParser.EffectInfo effect = EffectInfo.Effect; writer.Write(teResourceGUID.Index(effect.GUID)); writer.Write(effect.EffectLength); writer.Write(effect.DMCEs.Count); writer.Write(effect.CECEs.Count); writer.Write(effect.NECEs.Count); writer.Write(effect.RPCEs.Count); writer.Write(effect.FECEs.Count); writer.Write(effect.OSCEs.Count); writer.Write(effect.SVCEs.Count); foreach (EffectParser.DMCEInfo dmceInfo in effect.DMCEs) { WriteTime(writer, dmceInfo.PlaybackInfo); writer.Write(dmceInfo.Animation); writer.Write(dmceInfo.Material); writer.Write(dmceInfo.Model); FindLogic.Combo.ModelAsset modelInfo = Info.m_models[dmceInfo.Model]; writer.Write($"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}.owmdl"); if (dmceInfo.Animation == 0) { writer.Write("null"); } else { FindLogic.Combo.AnimationAsset animationInfo = Info.m_animations[dmceInfo.Animation]; writer.Write($"Models\\{modelInfo.GetName()}\\{OverwatchAnimationEffect.AnimationEffectDir}\\{animationInfo.GetNameIndex()}\\{animationInfo.GetNameIndex()}.owanim"); } } foreach (EffectParser.CECEInfo ceceInfo in effect.CECEs) { WriteTime(writer, ceceInfo.PlaybackInfo); writer.Write((byte)ceceInfo.Action); writer.Write(ceceInfo.Animation); writer.Write(ceceInfo.Identifier); writer.Write(teResourceGUID.Index(ceceInfo.Identifier)); if (ceceInfo.Animation != 0) { FindLogic.Combo.AnimationAsset animationInfo = Info.m_animations[ceceInfo.Animation]; writer.Write($"{OverwatchAnimationEffect.AnimationEffectDir}\\{animationInfo.GetNameIndex()}\\{animationInfo.GetNameIndex()}.owanim"); } else { writer.Write("null"); } } foreach (EffectParser.NECEInfo neceInfo in effect.NECEs) { WriteTime(writer, neceInfo.PlaybackInfo); writer.Write(neceInfo.GUID); writer.Write(teResourceGUID.Index(neceInfo.Identifier)); FindLogic.Combo.EntityAsset entityInfo = Info.m_entities[neceInfo.GUID]; writer.Write($"Entities\\{entityInfo.GetName()}\\{entityInfo.GetName()}.owentity"); } foreach (EffectParser.RPCEInfo rpceInfo in effect.RPCEs) { WriteTime(writer, rpceInfo.PlaybackInfo); writer.Write(rpceInfo.Model); // todo: make the materials work writer.Write(rpceInfo.Material); FindLogic.Combo.ModelAsset modelInfo = Info.m_models[rpceInfo.Model]; //writer.Write(rpceInfo.TextureDefiniton); writer.Write($"Models\\{modelInfo.GetName()}\\{modelInfo.GetName()}.owmdl"); } foreach (EffectParser.SVCEInfo svceInfo in effect.SVCEs) { WriteTime(writer, svceInfo.PlaybackInfo); writer.Write(teResourceGUID.Index(svceInfo.VoiceStimulus)); if (VoiceStimuli.ContainsKey(svceInfo.VoiceStimulus)) { HashSet <FindLogic.Combo.VoiceLineInstanceInfo> lines = VoiceStimuli[svceInfo.VoiceStimulus]; writer.Write(lines.Count); foreach (FindLogic.Combo.VoiceLineInstanceInfo voiceLineInstance in lines) { writer.Write(voiceLineInstance.SoundFiles.Count); foreach (ulong soundFile in voiceLineInstance.SoundFiles) { FindLogic.Combo.SoundFileAsset soundFileInfo = Info.m_voiceSoundFiles[soundFile]; writer.Write($"Sounds\\{soundFileInfo.GetNameIndex()}.ogg"); } } } else { writer.Write(0); } } }
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 void Write(Stream output) { using (BinaryWriter writer = new BinaryWriter(output)) { writer.Write((ushort)1); // version major writer.Write((ushort)2); // version minor if (Name.Length == 0) { writer.Write((byte)0); } else { writer.Write(Name); } writer.Write(ModelGroups.Header.PlaceableCount); // nr objects int entitiesWithModelCount = 0; STUModelComponent[][] modelComponentSets = new STUModelComponent[Entities.Header.PlaceableCount][]; for (int i = 0; i < Entities.Header.PlaceableCount; i++) { // todo: wtf is this code teMapPlaceableEntity entity = (teMapPlaceableEntity)Entities.Placeables[i]; var modelComponents = GetInstances <STUModelComponent>(entity.Header.EntityDefinition).Where(component => teResourceGUID.Index(component.m_model) > 1); if (modelComponents.Count() == 0) { foreach (STUComponentInstanceData instanceData in entity.InstanceData) { if (instanceData is STUStatescriptComponentInstanceData statescriptComponentInstanceData) { if (statescriptComponentInstanceData.m_6D10093E != null) { foreach (STUStatescriptGraphWithOverrides graphWithOverrides in statescriptComponentInstanceData.m_6D10093E) { FindLogic.Combo.Find(Info, graphWithOverrides); } } if (statescriptComponentInstanceData.m_2D9815BA != null) { // todo: ?? } } } continue; } modelComponentSets[i] = new STUModelComponent[modelComponents.Count()]; entitiesWithModelCount += modelComponentSets[i].Length; modelComponentSets[i] = modelComponents.ToArray(); } writer.Write((uint)(SingleModels.Header.PlaceableCount + Models.Header.PlaceableCount + entitiesWithModelCount)); // nr details writer.Write(Lights.Header.PlaceableCount); // nr Lights foreach (IMapPlaceable mapPlaceable in ModelGroups.Placeables ?? Array.Empty <IMapPlaceable>()) { teMapPlaceableModelGroup modelGroup = (teMapPlaceableModelGroup)mapPlaceable; FindLogic.Combo.Find(Info, modelGroup.Header.Model); FindLogic.Combo.ModelAsset modelInfo = Info.m_models[modelGroup.Header.Model]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}.owmdl"; writer.Write(modelFn); writer.Write(modelGroup.Header.GroupCount); for (int j = 0; j < modelGroup.Header.GroupCount; ++j) { teMapPlaceableModelGroup.Group group = modelGroup.Groups[j]; FindLogic.Combo.Find(Info, group.ModelLook, null, new FindLogic.Combo.ComboContext { Model = modelGroup.Header.Model }); FindLogic.Combo.ModelLookAsset modelLookInfo = Info.m_modelLooks[group.ModelLook]; string materialFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; writer.Write(materialFn); writer.Write(group.EntryCount); for (int k = 0; k < group.EntryCount; ++k) { teMapPlaceableModelGroup.Entry record = modelGroup.Entries[j][k]; writer.Write(record.Translation); writer.Write(record.Scale); writer.Write(record.Rotation); } } } foreach (IMapPlaceable mapPlaceable in SingleModels.Placeables ?? Array.Empty <IMapPlaceable>()) { teMapPlaceableSingleModel singleModel = (teMapPlaceableSingleModel)mapPlaceable; FindLogic.Combo.Find(Info, singleModel.Header.Model); FindLogic.Combo.Find(Info, singleModel.Header.ModelLook, null, new FindLogic.Combo.ComboContext { Model = singleModel.Header.Model }); FindLogic.Combo.ModelAsset modelInfo = Info.m_models[singleModel.Header.Model]; FindLogic.Combo.ModelLookAsset modelLookInfo = Info.m_modelLooks[singleModel.Header.ModelLook]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}.owmdl"; string matFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; writer.Write(modelFn); writer.Write(matFn); writer.Write(singleModel.Header.Translation); writer.Write(singleModel.Header.Scale); writer.Write(singleModel.Header.Rotation); } foreach (IMapPlaceable mapPlaceable in Models.Placeables ?? Array.Empty <IMapPlaceable>()) { teMapPlaceableModel placeableModel = (teMapPlaceableModel)mapPlaceable; FindLogic.Combo.Find(Info, placeableModel.Header.Model); FindLogic.Combo.Find(Info, placeableModel.Header.ModelLook, null, new FindLogic.Combo.ComboContext { Model = placeableModel.Header.Model }); FindLogic.Combo.ModelAsset modelInfo = Info.m_models[placeableModel.Header.Model]; FindLogic.Combo.ModelLookAsset modelLookInfo = Info.m_modelLooks[placeableModel.Header.ModelLook]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}.owmdl"; string matFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; writer.Write(modelFn); writer.Write(matFn); writer.Write(placeableModel.Header.Translation); writer.Write(placeableModel.Header.Scale); writer.Write(placeableModel.Header.Rotation); } for (int i = 0; i < Entities.Placeables?.Length; i++) { var entity = (teMapPlaceableEntity)Entities.Placeables[i]; STUModelComponent[] modelComponents = modelComponentSets[i]; if (modelComponents == null) { continue; } FindLogic.Combo.Find(Info, entity.Header.EntityDefinition); foreach (var modelComponent in modelComponents) { ulong model = modelComponent.m_model; var modelLookSet = new List <ulong> { modelComponent.m_look }; foreach (STUComponentInstanceData instanceData in entity.InstanceData) { if (!(instanceData is STUModelComponentInstanceData modelComponentInstanceData)) { continue; } if (modelComponentInstanceData.m_look != 0) { modelLookSet.Add(modelComponentInstanceData.m_look); } } FindLogic.Combo.Find(Info, model); foreach (var modelLook in modelLookSet) { FindLogic.Combo.Find(Info, modelLook, null, new FindLogic.Combo.ComboContext { Model = model }); } FindLogic.Combo.ModelAsset modelInfo = Info.m_models[model]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}.owmdl"; if (Info.m_entities.ContainsKey(entity.Header.EntityDefinition)) { modelFn = $"Entities\\{Info.m_entities[entity.Header.EntityDefinition].GetName()}\\{Info.m_entities[entity.Header.EntityDefinition].GetName()}.owentity"; } string matFn = "null"; try { FindLogic.Combo.ModelLookAsset modelLookInfo = Info.m_modelLooks[modelLookSet.First(x => x > 0)]; matFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; } catch { } writer.Write(modelFn); writer.Write(matFn); writer.Write(entity.Header.Translation); writer.Write(entity.Header.Scale); writer.Write(entity.Header.Rotation); } } // Extension 1.1 - Lights foreach (IMapPlaceable mapPlaceable in Lights.Placeables ?? Array.Empty <IMapPlaceable>()) { var light = (teMapPlaceableLight)mapPlaceable; writer.Write(light.Header.Translation); writer.Write(light.Header.Rotation); writer.Write((uint)light.Header.Type); writer.Write(light.Header.LightFOV); writer.Write(light.Header.Color); writer.Write(light.Header.Unknown1A); writer.Write(light.Header.Unknown1B); writer.Write(light.Header.Unknown2A); writer.Write(light.Header.Unknown2B); writer.Write(light.Header.Unknown2C); writer.Write(light.Header.Unknown2D); writer.Write(light.Header.Unknown3A); writer.Write(light.Header.Unknown3B); writer.Write(light.Header.UnknownPos1); writer.Write(light.Header.UnknownQuat1); writer.Write(light.Header.UnknownPos2); writer.Write(light.Header.UnknownQuat2); writer.Write(light.Header.UnknownPos3); writer.Write(light.Header.UnknownQuat3); writer.Write(light.Header.Unknown4A); writer.Write(light.Header.Unknown4B); writer.Write(light.Header.Unknown5); writer.Write(light.Header.Unknown6A); writer.Write(light.Header.Unknown6B); writer.Write(light.Header.Unknown7A); writer.Write(light.Header.Unknown7B); } writer.Write(Sounds.Header.PlaceableCount); // nr Sounds // Extension 1.2 - Sounds foreach (IMapPlaceable mapPlaceable in Sounds.Placeables ?? Array.Empty <IMapPlaceable>()) { var sound = (teMapPlaceableSound)mapPlaceable; FindLogic.Combo.Find(Info, sound.Header.Sound); writer.Write(sound.Header.Translation); if (!Info.m_sounds.ContainsKey(sound.Header.Sound) || Info.m_sounds[sound.Header.Sound].SoundFiles == null) { writer.Write(0); continue; } writer.Write(Info.m_sounds[sound.Header.Sound].SoundFiles.Count); foreach (var soundfile in Info.m_sounds[sound.Header.Sound].SoundFiles?.Values) { writer.Write($@"Sounds\{Info.m_soundFiles[soundfile].GetName()}.ogg"); } } // Extension 1.3 - Effects foreach (IMapPlaceable mapPlaceable in Effects.Placeables ?? Array.Empty <IMapPlaceable>()) { var effect = (teMapPlaceableEffect)mapPlaceable; FindLogic.Combo.Find(Info, effect.Header.Effect); // todo: wtf } } }