public static void Save(ICLIFlags flags, STUMapHeader mapHeader, ulong key, string basePath) { string name = GetString(mapHeader.m_displayName) ?? "Title Screen"; //string name = map.m_506FA8D8; var variantName = GetString(mapHeader.m_1C706502); if (variantName != null) { name = variantName; } LoudLog($"Extracting map {name}\\{teResourceGUID.Index(key):X}"); name = GetValidFilename(name); // TODO: MAP11 HAS CHANGED // TODO: MAP10 TOO? string mapPath = Path.Combine(basePath, "Maps", name, teResourceGUID.Index(key).ToString("X")) + Path.DirectorySeparatorChar; CreateDirectoryFromFile(mapPath); FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo(); LoudLog("\tFinding"); FindLogic.Combo.Find(info, mapHeader.m_map); //for (ushort i = 0; i < 255; i++) { // using (Stream mapChunkStream = OpenFile(mapHeader.GetChunkKey((byte)i))) { // if (mapChunkStream == null) continue; // WriteFile(mapChunkStream, Path.Combine(mapPath, $"{(Enums.teMAP_PLACEABLE_TYPE)i}.0BC")); // } //} //return; teMapPlaceableData placeableModelGroups = GetPlaceableData(mapHeader, Enums.teMAP_PLACEABLE_TYPE.MODEL_GROUP); teMapPlaceableData placeableSingleModels = GetPlaceableData(mapHeader, Enums.teMAP_PLACEABLE_TYPE.SINGLE_MODEL); teMapPlaceableData placeableModel = GetPlaceableData(mapHeader, Enums.teMAP_PLACEABLE_TYPE.MODEL); teMapPlaceableData placeableLights = GetPlaceableData(mapHeader, Enums.teMAP_PLACEABLE_TYPE.LIGHT); teMapPlaceableData placeableEntities = GetPlaceableData(mapHeader, Enums.teMAP_PLACEABLE_TYPE.ENTITY); teMapPlaceableData placeableSounds = GetPlaceableData(mapHeader, Enums.teMAP_PLACEABLE_TYPE.SOUND); teMapPlaceableData placeableEffects = GetPlaceableData(mapHeader, Enums.teMAP_PLACEABLE_TYPE.EFFECT); OverwatchMap exportMap = new OverwatchMap(name, info, placeableSingleModels, placeableModelGroups, placeableModel, placeableEntities, placeableLights, placeableSounds, placeableEffects); using (Stream outputStream = File.OpenWrite(Path.Combine(mapPath, $"{name}.{exportMap.Extension}"))) { exportMap.Write(outputStream); } { FindLogic.Combo.Find(info, mapHeader.m_86C1CFAB); FindLogic.Combo.Find(info, mapHeader.m_9386E669); FindLogic.Combo.Find(info, mapHeader.m_C6599DEB); if (mapHeader.m_D608E9F3 != null) { foreach (teResourceGUID gamemodeGUID in mapHeader.m_D608E9F3) { STUGameMode gameMode = GetInstance <STUGameMode>(gamemodeGUID); if (gameMode == null) { continue; } FindLogic.Combo.Find(info, gameMode.m_6EB38130); // 004 FindLogic.Combo.Find(info, gameMode.m_CF63B633); // 01B FindLogic.Combo.Find(info, gameMode.m_7F5B54B2); // game mode voice set foreach (STUGameModeTeam team in gameMode.m_teams) { FindLogic.Combo.Find(info, team.m_bodyScript); // 01B FindLogic.Combo.Find(info, team.m_controllerScript); // 01B } } } } FindLogic.Combo.Find(info, mapHeader.m_announcerWelcome); info.SetEffectName(mapHeader.m_announcerWelcome, "AnnouncerWelcome"); FindLogic.Combo.Find(info, mapHeader.m_musicTease); info.SetEffectName(mapHeader.m_musicTease, "MusicTease"); ulong announcerVoiceSet = 0; using (Stream stream = OpenFile(mapHeader.m_map)) { if (stream != null) { using (BinaryReader reader = new BinaryReader(stream)) { teMap map = reader.Read <teMap>(); STUVoiceSetComponent voiceSetComponent = GetInstance <STUVoiceSetComponent>(map.EntityDefinition); announcerVoiceSet = voiceSetComponent?.m_voiceDefinition; FindLogic.Combo.Find(info, announcerVoiceSet); info.SetEffectVoiceSet(mapHeader.m_announcerWelcome, announcerVoiceSet); } } } LoudLog("\tSaving"); Combo.Save(flags, mapPath, info); Combo.SaveLooseTextures(flags, Path.Combine(mapPath, "Textures"), info); if (mapHeader.m_7F5B54B2 != 0) // map voice set. not announcer { FindLogic.Combo.Find(info, mapHeader.m_7F5B54B2); } if (announcerVoiceSet != 0) // whole thing in env mode, not here { info.VoiceSets.Remove(announcerVoiceSet); } Combo.SaveAllVoiceSets(flags, Path.Combine(mapPath, "VoiceSets"), info); Combo.SaveAllSoundFiles(flags, Path.Combine(mapPath, "Sound"), info); LoudLog("\tDone"); }
public static void Save(ICLIFlags flags, STUMap map, ulong key, string basePath) { string name = GetValidFilename(GetString(map.DisplayName)) ?? "Title Screen"; if (GetString(map.VariantName) != null) { name = GetValidFilename(GetString(map.VariantName)); } LoudLog($"Extracting map {name}\\{GUID.Index(key):X}"); // if (map.Gamemodes != null) { // foreach (Common.STUGUID gamemodeGUID in map.Gamemodes) { // STUGamemode gamemode = GetInstance<STUGamemode>(gamemodeGUID); // } // } // TODO: MAP11 HAS CHANGED // TODO: MAP10 TOO? string mapPath = Path.Combine(basePath, "Maps", name, GUID.Index(key).ToString("X")) + Path.DirectorySeparatorChar; CreateDirectoryFromFile(mapPath); // if (map.UnknownArray != null) { // Dictionary<ulong, List<TextureInfo>> textures = new Dictionary<ulong, List<TextureInfo>>(); // foreach (STUMap.STU_7D6D8405 stu_7D6D8405 in map?.UnknownArray) { // ISTU overrideStu = OpenSTUSafe(stu_7D6D8405.Override); // STUSkinOverride @override = GetInstance<STUSkinOverride>(stu_7D6D8405.Override); // textures = FindLogic.Texture.FindTextures(textures, @override.SkinImage); // } // SaveLogic.Texture.Save(flags, Path.Combine(mapPath, "override"), textures); // } OWMDLWriter modelWriter = new OWMDLWriter(); OWMap14Writer owmap = new OWMap14Writer(); FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo(); LoudLog("\tFinding"); FindLogic.Combo.Find(info, map.MapDataResource1); MapEnvironment?env = null; using (Stream data = OpenFile(map.MapDataResource1)) { if (data != null) { using (BinaryReader dataReader = new BinaryReader(data)) { env = dataReader.Read <MapEnvironment>(); } } } using (Stream mapStream = OpenFile(map.GetDataKey(1))) { STULib.Types.Map.Map mapData = new STULib.Types.Map.Map(mapStream, BuildVersion); using (Stream map2Stream = OpenFile(map.GetDataKey(2))) { if (map2Stream == null) { return; } STULib.Types.Map.Map map2Data = new STULib.Types.Map.Map(map2Stream, BuildVersion); using (Stream map8Stream = OpenFile(map.GetDataKey(8))) { STULib.Types.Map.Map map8Data = new STULib.Types.Map.Map(map8Stream, BuildVersion); using (Stream mapEntitiesStream = OpenFile(map.GetDataKey(0xB))) { STULib.Types.Map.Map mapEntities = new STULib.Types.Map.Map(mapEntitiesStream, BuildVersion, true); mapEntitiesStream.Position = (long)(Math.Ceiling(mapEntitiesStream.Position / 16.0f) * 16); // Future proofing (?) for (int i = 0; i < mapEntities.Records.Length; ++i) { if (mapEntities.Records[i] != null && mapEntities.Records[i].GetType() != typeof(MapEntity)) { continue; } MapEntity mapEntity = (MapEntity)mapEntities.Records[i]; if (mapEntity == null) { continue; } FindLogic.Combo.Find(info, mapEntity.Header.Entity); STUModelComponent component = GetInstance <STUModelComponent>(mapEntity.Header.Entity); if (component == null) { continue; } mapEntity.ModelLook = component.Look; mapEntity.Model = component.Model; mapEntities.Records[i] = mapEntity; } using (Stream mapLStream = OpenFile(map.GetDataKey(9))) { STULib.Types.Map.Map mapLData = new STULib.Types.Map.Map(mapLStream, BuildVersion); using (Stream outputStream = File.Open(Path.Combine(mapPath, $"{name}.owmap"), FileMode.Create, FileAccess.Write)) { owmap.Write(outputStream, mapData, map2Data, map8Data, mapEntities, mapLData, name, modelWriter, info); } } } } } } FindLogic.Combo.Find(info, map.EffectAnnouncer); info.SetEffectName(map.EffectAnnouncer, "LoadAnnouncer"); FindLogic.Combo.Find(info, map.EffectMusic); info.SetEffectName(map.EffectMusic, "LoadMusic"); if (map.VoiceSet != null) { FindLogic.Combo.Find(info, map.VoiceSet); } if (env != null) { FindLogic.Combo.Find(info, env.Value.EntityDefinition); STUVoiceSetComponent voiceSetComponent = GetInstance <STUVoiceSetComponent>(env.Value.EntityDefinition); if (voiceSetComponent != null) { FindLogic.Combo.Find(info, voiceSetComponent.VoiceSet); info.SetEffectVoiceSet(map.EffectAnnouncer, voiceSetComponent.VoiceSet); info.SetEffectVoiceSet(map.EffectMusic, voiceSetComponent.VoiceSet); } } LoudLog("\tSaving"); Combo.Save(flags, mapPath, info); string soundPath = Path.Combine(mapPath, "Sound"); string voiceSetsPath = Path.Combine(soundPath, "VoiceSets"); string otherSoundsPath = Path.Combine(soundPath, "SFX"); Combo.SaveVoiceSets(flags, voiceSetsPath, info); foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> sound in info.SoundFiles) { Combo.SaveSoundFile(flags, otherSoundsPath, info, sound.Key, false); } LoudLog("\tDone"); }