public void Write(ICLIFlags flags, Stream output, FindLogic.Combo.ComboInfo info, FindLogic.Combo.ModelInfoNew modelInfo, Stream modelStream, Stream refposeStream) { bool doRefpose = false; if (flags is ExtractFlags extractFlags) { doRefpose = extractFlags.ExtractRefpose; } // erm, we need to wrap for now using (Chunked modelChunked = new Chunked(modelStream)) { string materialPath = ""; OWMatWriter14 materialWriter = new OWMatWriter14(); if (modelInfo.ModelLooks.Count > 0) { FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[modelInfo.ModelLooks.First()]; materialPath = Path.Combine("ModelLooks", modelLookInfo.GetNameIndex() + materialWriter.Format); } // data is object[] { bool exportAttachments, string materialReference, string modelName, bool onlyOneLOD, bool skipCollision } Write(flags, modelChunked, output, new List <byte>(new byte[] { 0, 1, 0xFF }), new object[] { true, materialPath, $"Model {GetFileName(modelInfo.GUID)}", null, true }, modelInfo); if (!doRefpose) { return; } RefPoseWriter refPoseWriter = new RefPoseWriter(); refPoseWriter.Write(modelChunked, refposeStream, true); refposeStream.Position = 0; } }
public static void SaveOWMaterialModelLookFile(string path, FindLogic.Combo.ModelLookInfo modelLookInfo, Model.OWMatWriter14 materialWriter, FindLogic.Combo.ComboInfo info) { string modelLookPath = Path.Combine(path, "ModelLooks", $"{modelLookInfo.GetNameIndex()}{materialWriter.Format}"); CreateDirectoryFromFile(modelLookPath); using (Stream modelLookOutputStream = File.OpenWrite(modelLookPath)) { modelLookOutputStream.SetLength(0); materialWriter.Write(modelLookOutputStream, info, modelLookInfo); } }
public static void SaveOWMaterialModelLookFile(string path, FindLogic.Combo.ModelLookInfo modelLookInfo, FindLogic.Combo.ComboInfo info) { Model.OverwatchModelLook modelLook = new Model.OverwatchModelLook(info, modelLookInfo); string modelLookPath = Path.Combine(path, "ModelLooks", $"{modelLookInfo.GetNameIndex()}.{modelLook.Extension}"); CreateDirectoryFromFile(modelLookPath); using (Stream modelLookOutputStream = File.OpenWrite(modelLookPath)) { modelLookOutputStream.SetLength(0); modelLook.Write(modelLookOutputStream); } }
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 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.ModelInfoNew modelInfo = Info.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.ModelLookInfo modelLookInfo = Info.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.ModelInfoNew modelInfo = Info.Models[singleModel.Header.Model]; FindLogic.Combo.ModelLookInfo modelLookInfo = Info.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.ModelInfoNew modelInfo = Info.Models[placeableModel.Header.Model]; FindLogic.Combo.ModelLookInfo modelLookInfo = Info.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.ModelInfoNew modelInfo = Info.Models[model]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}.owmdl"; if (Info.Entities.ContainsKey(entity.Header.EntityDefinition)) { modelFn = $"Entities\\{Info.Entities[entity.Header.EntityDefinition].GetName()}\\{Info.Entities[entity.Header.EntityDefinition].GetName()}.owentity"; } string matFn = "null"; try { FindLogic.Combo.ModelLookInfo modelLookInfo = Info.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.Sounds.ContainsKey(sound.Header.Sound) || Info.Sounds[sound.Header.Sound].SoundFiles == null) { writer.Write(0); continue; } writer.Write(Info.Sounds[sound.Header.Sound].SoundFiles.Count); foreach (var soundfile in Info.Sounds[sound.Header.Sound].SoundFiles?.Values) { writer.Write($@"Sounds\{Info.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 } } }
public void Write(Stream output, STULib.Types.Map.Map map, STULib.Types.Map.Map detail1, STULib.Types.Map.Map detail2, STULib.Types.Map.Map entities, STULib.Types.Map.Map lights, string name, IDataWriter modelFormat, FindLogic.Combo.ComboInfo info) { if (modelFormat == null) { modelFormat = new OWMDLWriter(); } using (BinaryWriter writer = new BinaryWriter(output)) { writer.Write((ushort)1); // version major writer.Write((ushort)1); // version minor if (name.Length == 0) { writer.Write((byte)0); } else { writer.Write(name); } uint size = 0; foreach (IMapFormat t in map.Records) { if (t != null && t.GetType() != typeof(Map01)) { continue; } size++; } writer.Write(size); // nr objects size = 1; foreach (IMapFormat t in detail1.Records) { if (t != null && t.GetType() != typeof(Map02)) { continue; } size++; } foreach (IMapFormat t in detail2.Records) { if (t != null && t.GetType() != typeof(Map08)) { continue; } size++; } foreach (IMapFormat t in entities.Records) { if (t != null && t.GetType() != typeof(MapEntity)) { continue; } if (((MapEntity)t).Model == 0) { continue; } size++; } writer.Write(size); // nr details // Extension 1.1 - Lights size = 0; foreach (IMapFormat t in lights.Records) { if (t != null && t.GetType() != typeof(Map09)) { continue; } size++; } writer.Write(size); // nr Lights foreach (IMapFormat t in map.Records) { if (t != null && t.GetType() != typeof(Map01)) { continue; } Map01 obj = (Map01)t; FindLogic.Combo.Find(info, obj.Header.Model); FindLogic.Combo.ModelInfoNew modelInfo = info.Models[obj.Header.Model]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}"; writer.Write(modelFn); writer.Write(obj.Header.groupCount); for (int j = 0; j < obj.Header.groupCount; ++j) { Map01.Map01Group group = obj.Groups[j]; FindLogic.Combo.Find(info, group.ModelLook, null, new FindLogic.Combo.ComboContext { Model = obj.Header.Model }); string materialFn; if (!info.ModelLooks.ContainsKey(group.ModelLook)) { materialFn = ""; // encrypted } else { FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[group.ModelLook]; materialFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; } writer.Write(materialFn); writer.Write(group.recordCount); for (int k = 0; k < group.recordCount; ++k) { Map01.Map01GroupRecord record = obj.Records[j][k]; writer.Write(record.position.x); writer.Write(record.position.y); writer.Write(record.position.z); writer.Write(record.scale.x); writer.Write(record.scale.y); writer.Write(record.scale.z); writer.Write(record.rotation.x); writer.Write(record.rotation.y); writer.Write(record.rotation.z); writer.Write(record.rotation.w); } } } // todo: broken? writer.Write($"Models\\physics\\physics.{modelFormat.Format}"); writer.Write((byte)0); writer.Write(0.0f); writer.Write(0.0f); writer.Write(0.0f); writer.Write(1.0f); writer.Write(1.0f); writer.Write(1.0f); writer.Write(0.0f); writer.Write(0.0f); writer.Write(0.0f); writer.Write(1.0f); foreach (IMapFormat t in detail1.Records) { if (t != null && t.GetType() != typeof(Map02)) { continue; } Map02 obj = (Map02)t; FindLogic.Combo.Find(info, obj.Header.Model); FindLogic.Combo.Find(info, obj.Header.ModelLook, null, new FindLogic.Combo.ComboContext { Model = obj.Header.Model }); FindLogic.Combo.ModelInfoNew modelInfo = info.Models[obj.Header.Model]; FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[obj.Header.ModelLook]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}"; string matFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; writer.Write(modelFn); writer.Write(matFn); writer.Write(obj.Header.position.x); writer.Write(obj.Header.position.y); writer.Write(obj.Header.position.z); writer.Write(obj.Header.scale.x); writer.Write(obj.Header.scale.y); writer.Write(obj.Header.scale.z); writer.Write(obj.Header.rotation.x); writer.Write(obj.Header.rotation.y); writer.Write(obj.Header.rotation.z); writer.Write(obj.Header.rotation.w); } foreach (IMapFormat t in detail2.Records) { if (t != null && t.GetType() != typeof(Map08)) { continue; } Map08 obj = (Map08)t; FindLogic.Combo.Find(info, obj.Header.Model); FindLogic.Combo.Find(info, obj.Header.ModelLook, null, new FindLogic.Combo.ComboContext { Model = obj.Header.Model }); FindLogic.Combo.ModelInfoNew modelInfo = info.Models[obj.Header.Model]; FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[obj.Header.ModelLook]; string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}"; string matFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; writer.Write(modelFn); writer.Write(matFn); writer.Write(obj.Header.position.x); writer.Write(obj.Header.position.y); writer.Write(obj.Header.position.z); writer.Write(obj.Header.scale.x); writer.Write(obj.Header.scale.y); writer.Write(obj.Header.scale.z); writer.Write(obj.Header.rotation.x); writer.Write(obj.Header.rotation.y); writer.Write(obj.Header.rotation.z); writer.Write(obj.Header.rotation.w); } foreach (IMapFormat t in entities.Records) { if (t != null && t.GetType() != typeof(MapEntity)) { continue; } MapEntity mapEntity = (MapEntity)t; if (mapEntity.Model == 0) { continue; } ulong modelLook = mapEntity.ModelLook; foreach (object container in mapEntity.STUContainers) { ISTU realContainer = (ISTU)container; foreach (Common.STUInstance instance in realContainer.Instances) { if (instance is STUModelComponentInstanceData modelComponentInstanceData) { if (modelComponentInstanceData.Look != 0) { modelLook = modelComponentInstanceData.Look; } } } } FindLogic.Combo.Find(info, mapEntity.Model); FindLogic.Combo.Find(info, modelLook, null, new FindLogic.Combo.ComboContext { Model = mapEntity.Model }); FindLogic.Combo.ModelInfoNew modelInfo = info.Models[mapEntity.Model]; string matFn = ""; if (info.ModelLooks.ContainsKey(modelLook)) { FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[modelLook]; matFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat"; } string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}"; writer.Write(modelFn); writer.Write(matFn); writer.Write(mapEntity.Header.Position.x); writer.Write(mapEntity.Header.Position.y); writer.Write(mapEntity.Header.Position.z); writer.Write(mapEntity.Header.Scale.x); writer.Write(mapEntity.Header.Scale.y); writer.Write(mapEntity.Header.Scale.z); writer.Write(mapEntity.Header.Rotation.x); writer.Write(mapEntity.Header.Rotation.y); writer.Write(mapEntity.Header.Rotation.z); writer.Write(mapEntity.Header.Rotation.w); } // Extension 1.1 - Lights foreach (IMapFormat t in lights.Records) { if (t != null && t.GetType() != typeof(Map09)) { continue; } Map09 obj = (Map09)t; writer.Write(obj.Header.position.x); writer.Write(obj.Header.position.y); writer.Write(obj.Header.position.z); writer.Write(obj.Header.rotation.x); writer.Write(obj.Header.rotation.y); writer.Write(obj.Header.rotation.z); writer.Write(obj.Header.rotation.w); writer.Write(obj.Header.LightType); writer.Write(obj.Header.LightFOV); writer.Write(obj.Header.Color.x); writer.Write(obj.Header.Color.y); writer.Write(obj.Header.Color.z); writer.Write(obj.Header.unknown1A); writer.Write(obj.Header.unknown1B); writer.Write(obj.Header.unknown2A); writer.Write(obj.Header.unknown2B); writer.Write(obj.Header.unknown2C); writer.Write(obj.Header.unknown2D); writer.Write(obj.Header.unknown3A); writer.Write(obj.Header.unknown3B); writer.Write(obj.Header.unknownPos1.x); writer.Write(obj.Header.unknownPos1.y); writer.Write(obj.Header.unknownPos1.z); writer.Write(obj.Header.unknownQuat1.x); writer.Write(obj.Header.unknownQuat1.y); writer.Write(obj.Header.unknownQuat1.z); writer.Write(obj.Header.unknownQuat1.w); writer.Write(obj.Header.unknownPos2.x); writer.Write(obj.Header.unknownPos2.y); writer.Write(obj.Header.unknownPos2.z); writer.Write(obj.Header.unknownQuat2.x); writer.Write(obj.Header.unknownQuat2.y); writer.Write(obj.Header.unknownQuat2.z); writer.Write(obj.Header.unknownQuat2.w); writer.Write(obj.Header.unknownPos3.x); writer.Write(obj.Header.unknownPos3.y); writer.Write(obj.Header.unknownPos3.z); writer.Write(obj.Header.unknownQuat3.x); writer.Write(obj.Header.unknownQuat3.y); writer.Write(obj.Header.unknownQuat3.z); writer.Write(obj.Header.unknownQuat3.w); writer.Write(obj.Header.unknown4A); writer.Write(obj.Header.unknown4B); writer.Write(obj.Header.unknown5); writer.Write(obj.Header.unknown6A); writer.Write(obj.Header.unknown6B); writer.Write(obj.Header.unknown7A); writer.Write(obj.Header.unknown7B); } } }
public void Write(Stream output) { using (BinaryWriter writer = new BinaryWriter(output)) { writer.Write((ushort)1); // version major writer.Write((ushort)1); // 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[] modelComponents = new STUModelComponent[Entities.Header.PlaceableCount]; for (int i = 0; i < Entities.Header.PlaceableCount; i++) { teMapPlaceableEntity entity = (teMapPlaceableEntity)Entities.Placeables[i]; STUModelComponent component = GetInstance <STUModelComponent>(entity.Header.EntityDefinition); if (component != null && teResourceGUID.Index(component.m_model) > 1 && teResourceGUID.Index(component.m_look) > 1) { entitiesWithModelCount++; modelComponents[i] = component; } } 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.ModelInfoNew modelInfo = Info.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.ModelLookInfo modelLookInfo = Info.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.ModelInfoNew modelInfo = Info.Models[singleModel.Header.Model]; FindLogic.Combo.ModelLookInfo modelLookInfo = Info.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.ModelInfoNew modelInfo = Info.Models[placeableModel.Header.Model]; FindLogic.Combo.ModelLookInfo modelLookInfo = Info.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 modelComponent = modelComponents[i]; if (modelComponent == null) { continue; } ulong model = modelComponent.m_model; ulong modelLook = modelComponent.m_look; foreach (STUComponentInstanceData instanceData in entity.InstanceData) { if (!(instanceData is STUModelComponentInstanceData modelComponentInstanceData)) { continue; } if (modelComponentInstanceData.m_look != 0) { modelLook = modelComponentInstanceData.m_look; } } FindLogic.Combo.Find(Info, model); FindLogic.Combo.Find(Info, modelLook, null, new FindLogic.Combo.ComboContext { Model = model }); FindLogic.Combo.ModelInfoNew modelInfo = Info.Models[model]; FindLogic.Combo.ModelLookInfo modelLookInfo = Info.ModelLooks[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(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); } } }