private static bool SaveSet(ICLIFlags flags, string basePath, ulong entityMain, string heroFileName, string skin, ref STUVoiceSetComponent voiceSetComponent, ref Combo.ComboInfo info, STUVoiceSetComponent baseComponent = null, Combo.ComboInfo baseCombo = null, Dictionary <ulong, ulong> replacements = null) { voiceSetComponent = GetInstance <STUVoiceSetComponent>(Combo.GetReplacement(entityMain, replacements)); if (voiceSetComponent?.m_voiceDefinition == null) { Debugger.Log(0, "DataTool.SaveLogic.Unlock.VoiceLine", "[DataTool.SaveLogic.Unlock.VoiceLine]: VoiceSet not found"); return(false); } info = new Combo.ComboInfo(); Combo.Find(info, Combo.GetReplacement(voiceSetComponent.m_voiceDefinition, replacements), replacements); if (baseComponent != null && baseCombo != null) { if (!Combo.RemoveDuplicateVoiceSetEntries(baseCombo, ref info, baseComponent.m_voiceDefinition, Combo.GetReplacement(voiceSetComponent.m_voiceDefinition, replacements))) { return(false); } } Log($"\tSaving {skin}"); var context = new SaveLogic.Combo.SaveContext(info); SaveLogic.Combo.SaveVoiceSet(flags, Path.Combine(basePath, Container, heroFileName, skin), context, Combo.GetReplacement(voiceSetComponent.m_voiceDefinition, replacements)); context.Wait(); return(true); }
public void Parse(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } Combo.ComboInfo info = new Combo.ComboInfo(); foreach (ulong key in TrackedFiles[0x4]) { Combo.Find(info, key); } Log($"Preparing to save roughly {info.m_textures.Count()} textures."); Log($"This will take a long time and take up a lot of space."); var saveContext = new SaveLogic.Combo.SaveContext(info); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, "004Dump"), saveContext); saveContext.Wait(); }
public static bool SaveSet(ICLIFlags flags, string basePath, ulong entityMain, string heroFileName, string skin, ref STUVoiceSetComponent soundSetComponentContainer, ref Combo.ComboInfo info, STUVoiceSetComponent baseComponent = null, Combo.ComboInfo baseCombo = null, Dictionary <ulong, ulong> replacements = null) { soundSetComponentContainer = GetInstance <STUVoiceSetComponent>(Combo.GetReplacement(entityMain, replacements)); if (soundSetComponentContainer?.VoiceSet == null) { Debugger.Log(0, "DataTool.SaveLogic.Unlock.VoiceLine", "[DataTool.SaveLogic.Unlock.VoiceLine]: VoiceSet not found"); return(false); } info = new Combo.ComboInfo(); Combo.Find(info, Combo.GetReplacement(soundSetComponentContainer.VoiceSet, replacements), replacements); if (baseComponent != null && baseCombo != null) { if (!Combo.RemoveDuplicateVoiceSetEntries(baseCombo, ref info, baseComponent.VoiceSet, Combo.GetReplacement(soundSetComponentContainer.VoiceSet, replacements))) { return(false); } } Log("Saving {0}", skin); SaveLogic.Combo.SaveVoiceSet(flags, Path.Combine(basePath, Container, heroFileName, skin), info, Combo.GetReplacement(soundSetComponentContainer.VoiceSet, replacements)); return(true); }
public void Parse(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = Path.Combine(flags.OutputPath, Container); } else { throw new Exception("no output path"); } foreach (var guid in Program.TrackedFiles[0x5F]) { var voiceSet = GetInstance <STUVoiceSet>(guid); if (voiceSet == null) { continue; } var npcName = GetValidFilename(GetString(voiceSet.m_269FC4E9)); if (npcName == null) { continue; } Logger.Log($"Processing NPC {npcName}"); var info = new Combo.ComboInfo(); var ignoreGroups = !WhitelistedNPCs.Contains(npcName); ExtractHeroVoiceBetter.SaveVoiceSet(flags, basePath, npcName, guid, ref info, ignoreGroups: ignoreGroups); } }
public void ExtractNewEntities(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string ver = "60993"; //var contentHashes = GetContentHashes($@"D:\ow\resources\verdata\{ver}.cmfhashes"); var guids = GetGUIDs($@"D:\ow\resources\verdata\{ver}.guids"); const string container = "DebugNewEntities2"; Combo.ComboInfo info = new Combo.ComboInfo(); AddNewByGUID(info, guids, 0x4, 0x7C, 0x3F, 0xB2); SaveLogic.Combo.Save(flags, Path.Combine(basePath, container), info); SaveLogic.Combo.SaveAllSoundFiles(flags, Path.Combine(basePath, container, "Sounds"), info); SaveLogic.Combo.SaveAllVoiceSoundFiles(flags, Path.Combine(basePath, container, "VoiceSounds"), info); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, container, "LooseTex"), info); SaveLogic.Combo.SaveAllStrings(flags, Path.Combine(basePath, container, "Strings"), info); }
public void GetSubtitles() { Combo.ComboInfo comboInfo = new Combo.ComboInfo(); HashSet <KeyValuePair <ulong, ulong> > done = new HashSet <KeyValuePair <ulong, ulong> >(); foreach (ulong key in TrackedFiles[0x5F]) { Combo.Find(comboInfo, key); if (!comboInfo.VoiceSets.ContainsKey(key)) { continue; } Combo.VoiceSetInfo voiceSetInfo = comboInfo.VoiceSets[key]; if (voiceSetInfo.VoiceLineInstances == null) { continue; } foreach (KeyValuePair <ulong, HashSet <Combo.VoiceLineInstanceInfo> > lineInstance in voiceSetInfo.VoiceLineInstances) { foreach (Combo.VoiceLineInstanceInfo lineInstanceInfo in lineInstance.Value) { if (lineInstanceInfo.Subtitle != 0) { foreach (ulong soundInfoSound in lineInstanceInfo.SoundFiles) { PrintSubtitle(done, key, soundInfoSound, lineInstanceInfo.Subtitle); } } } } } }
public void Parse(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = Path.Combine(flags.OutputPath, Container); } else { throw new Exception("no output path"); } // Do normal heroes first then NPCs, this is because NPCs have a lot of duplicate sounds and normal heroes (should) have none // so any duplicate sounds would only come up while processing NPCs which can be ignored as they (probably) belong to heroes var heroes = Program.TrackedFiles[0x75] .Select(x => new Hero(x)) .OrderBy(x => !x.IsHero) .ThenBy(x => x.GUID.GUID) .ToArray(); foreach (var hero in heroes) { var heroStu = GetInstance <STUHero>(hero.GUID); string heroName = GetValidFilename((GetString(heroStu.m_0EDCE350) ?? $"Unknown{teResourceGUID.Index(hero.GUID)}").TrimEnd(' ')); Logger.Log($"Processing {heroName}"); Combo.ComboInfo baseInfo = default; var heroVoiceSetGuid = GetInstance <STUVoiceSetComponent>(heroStu.m_gameplayEntity)?.m_voiceDefinition; if (SaveVoiceSet(flags, basePath, heroName, heroVoiceSetGuid, ref baseInfo)) { var skins = new ProgressionUnlocks(heroStu).GetUnlocksOfType(UnlockType.Skin); foreach (var unlock in skins) { TACTLib.Logger.Debug("Tool", $"Processing skin {unlock.Name}"); if (!(unlock.STU is STUUnlock_SkinTheme unlockSkinTheme)) { return; } if (unlockSkinTheme.m_0B1BA7C1 != 0) { continue; } Combo.ComboInfo info = default; var skinTheme = GetInstance <STUSkinTheme>(unlockSkinTheme.m_skinTheme); if (skinTheme == null) { continue; } SaveVoiceSet(flags, basePath, heroName, heroVoiceSetGuid, ref info, baseInfo, SkinTheme.GetReplacements(skinTheme)); } } } }
public void ExtractHeroes(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "DebugCombo"; foreach (ulong key in TrackedFiles[0x75]) { // if (GUID.Index(key) != 0xDEADBEEF) continue; STUHero hero = GetInstance <STUHero>(key); string heroName = GetString(hero.Name); if (heroName != "Tracer") { continue; } Stopwatch stopwatch = Stopwatch.StartNew(); Combo.ComboInfo info = new Combo.ComboInfo(); Combo.Find(info, hero.EntityHeroSelect); Combo.Find(info, hero.EntityHighlightIntro); Combo.Find(info, hero.EntityMain); Combo.Find(info, hero.EntityPlayable); Combo.Find(info, hero.EntityThirdPerson); info.SetEntityName(hero.EntityHeroSelect, $"{heroName}-HeroSelect"); info.SetEntityName(hero.EntityHighlightIntro, $"{heroName}-HighlightIntro"); info.SetEntityName(hero.EntityMain, $"{heroName}-Main"); info.SetEntityName(hero.EntityPlayable, $"{heroName}-Playable"); info.SetEntityName(hero.EntityThirdPerson, $"{heroName}-Thirdperson"); stopwatch.Stop(); long newTime = stopwatch.ElapsedMilliseconds; SaveLogic.Combo.Save(flags, Path.Combine(basePath, heroName), info); // stopwatch.Reset(); // stopwatch.Start(); // // HashSet<ModelInfo> models = new HashSet<ModelInfo>(); // Model.FindModels(models, hero.EntityHeroSelect); // Model.FindModels(models, hero.EntityHighlightIntro); // Model.FindModels(models, hero.EntityMain); // Model.FindModels(models, hero.EntityPlayable); // Model.FindModels(models, hero.EntityThirdPerson); // stopwatch.Stop(); // long oldTime = stopwatch.ElapsedMilliseconds; } }
public void AddNewByGUID(Combo.ComboInfo info, HashSet <ulong> lastVerGuids, ushort type) { foreach (ulong key in TrackedFiles[type]) { if (lastVerGuids.Contains(key)) { continue; } Combo.Find(info, key); } }
public void AddNew(Combo.ComboInfo info, List <ulong> all, ushort type) { foreach (ulong key in TrackedFiles[type]) { if (all.Contains(key)) { continue; } Combo.Find(info, key); } }
public void AddAdded(Combo.ComboInfo info, List <string> added, ushort type) { foreach (ulong key in TrackedFiles[type]) { string name = GetFileName(key); if (!added.Contains(name)) { continue; } Combo.Find(info, key); } }
public void ExtractMapImages(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } //flags.ConvertTexturesType = "dds"; const string container = "DebugMapImages"; foreach (ulong key in TrackedFiles[0x2]) { string dir = Path.Combine(basePath, container, GetFileName(key)); Combo.ComboInfo info = new Combo.ComboInfo(); using (Stream stream = OpenFile(key)) { using (Stream file = File.OpenWrite(Path.Combine(dir, "data.002"))) { stream.CopyTo(file); stream.Position = 0; } using (BinaryReader reader = new BinaryReader(stream)) { Map map = reader.Read <Map>(); Combo.Find(info, map.Texture); info.SetTextureName(map.Texture, nameof(Map.Texture)); Combo.Find(info, map.TextureB); info.SetTextureName(map.TextureB, nameof(Map.TextureB)); Combo.Find(info, map.TextureC); info.SetTextureName(map.TextureC, nameof(Map.TextureC)); Combo.Find(info, map.TextureD); info.SetTextureName(map.TextureD, nameof(Map.TextureD)); Combo.Find(info, map.TextureE); info.SetTextureName(map.TextureE, nameof(Map.TextureE)); Combo.Find(info, map.TextureF); info.SetTextureName(map.TextureF, nameof(Map.TextureF)); } SaveLogic.Combo.SaveLooseTextures(flags, dir, info); } } }
public void SaveTextureDef(ICLIFlags flags, string path, ulong texDef, ImageDefinition imageDefinition) { string thePath = Path.Combine(path, GetFileName(texDef)); CreateDirectoryFromFile(thePath + "\\poo"); Combo.ComboInfo info = new Combo.ComboInfo(); foreach (ImageLayer layer in imageDefinition.Layers) { Combo.Find(info, layer.Key); } SaveLogic.Combo.SaveLooseTextures(flags, thePath, info); }
public void GetLootboxes(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } foreach (ulong key in TrackedFiles[0xCF]) { STULootBox lootbox = GetInstance <STULootBox>(key); if (lootbox == null) { continue; } string name = LootBox.GetName(lootbox.m_lootboxType); Combo.ComboInfo info = Combo.Find(null, lootbox.m_baseEntity); // 003 Combo.Find(info, lootbox.m_chestEntity); // 003 Combo.Find(info, lootbox.m_idleEffect); // 00D Combo.Find(info, lootbox.m_FEC3ED62); // 00D Combo.Find(info, lootbox.m_FFE7768F); // 00D Combo.Find(info, lootbox.m_baseModelLook); // 01A Combo.Find(info, lootbox.m_modelLook); Combo.Find(info, 0x400000000001456); // coin chest, todo // 00000000315A.00C in 000000001456.003 (288230376151716950) if (lootbox.m_shopCards != null) { foreach (STULootBoxShopCard lootboxShopCard in lootbox.m_shopCards) { Combo.Find(info, lootboxShopCard.m_cardTexture); // 004 } } var context = new SaveLogic.Combo.SaveContext(info); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, Container, name, "ShopCards"), context); SaveLogic.Combo.Save(flags, Path.Combine(basePath, Container, name), context); context.Wait(); SaveScratchDatabase(); } }
public void ExtractNewEntities(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } if (flags.Positionals.Length != 4) { throw new Exception("incorrect params provided"); } var file = flags.Positionals[3]; const string container = "DebugNewEntities2"; Combo.ComboInfo info = new Combo.ComboInfo(); var types = new ushort[] { 0x4, 0x7C, 0x3F, 0xB2 }; if (file.EndsWith("guids")) { var guids = GetGUIDs(file); AddNewByGUID(info, guids, types); } else if (file.EndsWith("cmfhashes")) { // does this even still work? var contentHashes = GetContentHashes(file); AddNewByContentHash(info, contentHashes, types); } else { throw new Exception("unknown file type"); } var context = new SaveLogic.Combo.SaveContext(info); SaveLogic.Combo.Save(flags, Path.Combine(basePath, container), context); SaveLogic.Combo.SaveAllSoundFiles(flags, Path.Combine(basePath, container, "Sounds"), context); SaveLogic.Combo.SaveAllVoiceSoundFiles(flags, Path.Combine(basePath, container, "VoiceSounds"), context); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, container, "LooseTex"), context); SaveLogic.Combo.SaveAllStrings(flags, Path.Combine(basePath, container, "Strings"), info); context.Wait(); }
public static void SaveSkin(ICLIFlags flags, ulong skinResource, string basePath, STUHero hero, string heroFileName, string name, STUVoiceSetComponent baseComponent, Combo.ComboInfo baseInfo) { STUSkinTheme skin = GetInstance <STUSkinTheme>(skinResource); if (skin == null) { return; } STUVoiceSetComponent component = default; Combo.ComboInfo info = default; SaveSet(flags, basePath, hero.m_gameplayEntity, heroFileName, GetValidFilename(name), ref component, ref info, baseComponent, baseInfo, SkinTheme.GetReplacements(skin)); }
public void Extract0EE(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "Debug0EE"; string path = Path.Combine(basePath, container); foreach (ulong key in TrackedFiles[0xEE]) { using (Stream stream = OpenFile(key)) { teStructuredData structuredData = new teStructuredData(stream); STU_E3594B8E inst = structuredData.GetMainInstance <STU_E3594B8E>(); if (inst == null) { continue; //inst = structuredData.GetMainInstance<STU_598579A3>(); } string name = $"{GetString(inst.m_name)}_{teResourceGUID.Index(key):X}"; string description = GetString(inst.m_description); Combo.ComboInfo info = new Combo.ComboInfo(); Combo.Find(info, (ulong)inst.m_21EB3E73); info.SetTextureName((ulong)inst.m_21EB3E73, name); OpenSTUTest(inst.m_7B7CCF55); // ux1 OpenSTUTest(inst.m_E81C5302); // ux2 OpenSTUTest(inst.m_FD9B53F4); // ux3 //{ // teStructuredData uxScreenData = new teStructuredData(); //} SaveLogic.Combo.SaveLooseTextures(flags, path, info); } } }
public void ExtractNewEntities(ICLIFlags toolFlags) { string basePath; // sorry if this isn't useful for anyone but me. // data.json has a list under the key "added_raw" that contains all of the added files. //const string dataPath = "D:\\ow\\OverwatchDataManager\\versions\\1.18.1.2.42076\\data.json"; const string dataPath = "D:\\ow\\OverwatchDataManager\\versions\\1.20.0.2.43435\\data.json"; List <string> added = GetAddedFiles(dataPath); if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "DebugNewEntities"; Combo.ComboInfo info = new Combo.ComboInfo(); Combo.Find(info, 288230376151717278); // 00000000159E.003 //Combo.Find(info, 0x40000000000146C); // 00000000146C.003 //Combo.Find(info, 288230376151716993); // 000000001481.003 //Combo.Find(info, 288230376151716994); // 000000001482.003 //Combo.Find(info, 288230376151716950); // 000000001456.003 //Combo.Find(info, 288230376151716972); // 00000000146C.003 //Combo.Find(info, 288230376151716953); // 000000001459.003 //Combo.Find(info, 288230376151716948); // 000000001454.003 //Combo.Find(info, 288230376151716949); // 000000001455.003 //foreach (ulong key in TrackedFiles[0x3]) { // string name = GetFileName(key); // if (!added.Contains(name)) continue; // Combo.Find(info, key); //} AddAdded(info, added, 0x8F); AddAdded(info, added, 0x8E); SaveLogic.Combo.Save(flags, Path.Combine(basePath, container), info); }
public static void SaveSkin(ICLIFlags flags, ulong skinResource, string basePath, STUHero hero, string heroFileName, string name, STUVoiceSetComponent baseComponent, Combo.ComboInfo baseInfo) { STUSkinOverride skin = GetInstance <STUSkinOverride>(skinResource); if (skin == null) { return; } STUVoiceSetComponent component = default(STUVoiceSetComponent); Combo.ComboInfo info = default(Combo.ComboInfo); if (SaveSet(flags, basePath, hero.EntityMain, heroFileName, GetValidFilename(name), ref component, ref info, baseComponent, baseInfo, skin.ProperReplacements)) { return; } }
public void GetLootboxes(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } foreach (ulong key in TrackedFiles[0xCF]) { STULootbox lootbox = GetInstance <STULootbox>(key); if (lootbox == null) { continue; } string name = GetValidFilename(lootbox.Event.ToString()) ?? $"Unknown{GUID.Index(key):X}"; Combo.ComboInfo info = Combo.Find(null, lootbox.Entity); Combo.Find(info, lootbox.Entity2); Combo.Find(info, lootbox.Effect1); Combo.Find(info, lootbox.Effect2); Combo.Find(info, lootbox.Effect3); Combo.Find(info, lootbox.ModelLook); Combo.Find(info, lootbox.Look2); Combo.Find(info, 288230376151716950); // coin chest, todo // 00000000315A.00C in 000000001456.003 (288230376151716950) foreach (STULootBoxShopCard lootboxShopCard in lootbox.ShopCards) { Combo.Find(info, lootboxShopCard.Texture); } SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, Container, name, "ShopCards"), info); SaveLogic.Combo.Save(flags, Path.Combine(basePath, Container, name), info); } }
public void ExtractVoiceSets(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "DebugVoiceSet"; foreach (ulong key in TrackedFiles[0x5F]) { if (teResourceGUID.Index(key) != 0x19F) { continue; } string voiceMaterDir = Path.Combine(basePath, container, GetFileName(key)); Combo.ComboInfo info = new Combo.ComboInfo(); var context = new SaveLogic.Combo.SaveContext(info); Combo.Find(info, key); SaveLogic.Combo.SaveVoiceSet(flags, voiceMaterDir, context, key); context.Wait(); // foreach (STUVoiceLineInstance voiceLineInstance in voiceSet.VoiceLineInstances) { // if (voiceLineInstance?.SoundDataContainer == null) continue; // // Combo.ComboInfo info = new Combo.ComboInfo(); // // Combo.Find(info, voiceLineInstance.SoundDataContainer.SoundbankMasterResource); // // foreach (ulong soundInfoNew in info.Sounds.Keys) { // SaveLogic.Combo.SaveSound(flags, voiceMaterDir, info, soundInfoNew); // } // } } }
public static void SaveAbilities(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string folderName = "Abilities"; foreach (ulong key in TrackedFiles[0x9E]) { STULoadout loadout = GetInstance <STULoadout>(key); if (loadout == null) { continue; } string name = GetValidFilename(GetString(loadout.m_name)?.TrimEnd().Replace(".", "_")) ?? $"Unknown{teResourceGUID.Index(key):X}"; Combo.ComboInfo info = new Combo.ComboInfo(); Combo.Find(info, loadout.m_texture); var context = new SaveLogic.Combo.SaveContext(info); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, folderName, name), context); context.Wait(); using (Stream videoStream = OpenFile(loadout.m_infoMovie)) { if (videoStream != null) { videoStream.Position = 128; // wrapped in "MOVI" for some reason WriteFile(videoStream, Path.Combine(basePath, folderName, name, $"{teResourceGUID.LongKey(loadout.m_infoMovie):X12}.bk2")); } } } }
public void ExtractVoiceSets(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "DebugVoiceSet"; foreach (ulong key in TrackedFiles[0x5F]) { STUVoiceSet voiceSet = GetInstance <STUVoiceSet>(key); string voiceMaterDir = Path.Combine(basePath, container, GetFileName(key)); foreach (STUVoiceLineInstance voiceLineInstance in voiceSet.VoiceLineInstances) { if (voiceLineInstance?.SoundDataContainer == null) { continue; } Combo.ComboInfo info = new Combo.ComboInfo(); Combo.Find(info, voiceLineInstance.SoundDataContainer.SoundbankMasterResource); foreach (ulong soundInfoNew in info.Sounds.Keys) { SaveLogic.Combo.SaveSound(flags, voiceMaterDir, info, soundInfoNew); } } } }
public void Parse(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "GamemodeImages"; string path = Path.Combine(basePath, container); foreach (ulong key in TrackedFiles[0xEE]) { var stuE3594B8E = Helper.STUHelper.GetInstance <STU_E3594B8E>(key); if (stuE3594B8E == null) { continue; } string name = $"{teResourceGUID.Index(key):X3}_{GetString(stuE3594B8E.m_name)}"; Combo.ComboInfo info = new Combo.ComboInfo(); Combo.Find(info, (ulong)stuE3594B8E.m_21EB3E73); info.SetTextureName((ulong)stuE3594B8E.m_21EB3E73, name); var context = new SaveLogic.Combo.SaveContext(info); SaveLogic.Combo.SaveLooseTextures(flags, path, context); context.Wait(); } }
public void ExtractNewEntities(ICLIFlags toolFlags) { string basePath; // sorry if this isn't useful for anyone but me. // data.json has a list under the key "added_raw" that contains all of the added files. //const string dataPath = "D:\\ow\\OverwatchDataManager\\versions\\1.18.1.2.42076\\data.json"; //const string dataPath = "D:\\ow\\OverwatchDataManager\\versions\\1.20.0.2.43435\\data.json"; //const string dataPath = "D:\\ow\\OverwatchDataManager\\versions\\1.17.0.3.41713\\data.json"; //VersionInfo versionInfo = GetVersionInfo(dataPath); //VersionInfo versionInfo = GetVersionInfoFake(@"D:\Code\Repos\overtool\OWLib-main\CASCEncDump\bin\Debug\44916.cmfhashes"); VersionInfo versionInfo = GetVersionInfoFake(@"D:\ow\resources\verdata\49154.cmfhashes"); if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "DebugNewEntities3"; Combo.ComboInfo info = new Combo.ComboInfo(); //AddNewHash(info, versionInfo, 0x7C); AddNewHash(info, versionInfo, 0x4); SaveLogic.Combo.Save(flags, Path.Combine(basePath, container), info); SaveLogic.Combo.SaveAllSoundFiles(flags, Path.Combine(basePath, container, "Sounds"), info); SaveLogic.Combo.SaveAllVoiceSoundFiles(flags, Path.Combine(basePath, container, "VoiceSounds"), info); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, container, "LooseTex"), info); SaveLogic.Combo.SaveAllStrings(flags, Path.Combine(basePath, container, "Strings"), info); }
public void SaveUnlocksForHeroes(ICLIFlags flags, IEnumerable <STUHero> heroes, string basePath, bool npc = false) { if (flags.Positionals.Length < 4) { QueryHelp(QueryTypes); return; } Dictionary <string, Dictionary <string, ParsedArg> > parsedTypes = ParseQuery(flags, QueryTypes, QueryNameOverrides); if (parsedTypes == null) { return; } foreach (STUHero hero in heroes) { if (hero == null) { continue; } string heroNameActual = GetString(hero.m_0EDCE350); if (heroNameActual == null) { continue; } Dictionary <string, ParsedArg> config = GetQuery(parsedTypes, heroNameActual.ToLowerInvariant(), "*"); heroNameActual = heroNameActual.TrimEnd(' '); string heroFileName = GetValidFilename(heroNameActual); if (config.Count == 0) { continue; } string heroPath = Path.Combine(basePath, RootDir, heroFileName); VoiceSet voiceSet = new VoiceSet(hero); ProgressionUnlocks progressionUnlocks = new ProgressionUnlocks(hero); if (progressionUnlocks.LevelUnlocks == null && !npc) { continue; } if (progressionUnlocks.LootBoxesUnlocks != null && npc) { continue; } Log($"Processing unlocks for {heroNameActual}"); { Combo.ComboInfo guiInfo = new Combo.ComboInfo(); foreach (STU_1A496D3C tex in hero.m_8203BFE1) { Combo.Find(guiInfo, tex.m_texture); guiInfo.SetTextureName(tex.m_texture, teResourceGUID.AsString(tex.m_id)); } SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(heroPath, "GUI"), guiInfo); } if (progressionUnlocks.OtherUnlocks != null) // achievements and stuff { Dictionary <string, TagExpectedValue> tags = new Dictionary <string, TagExpectedValue> { { "event", new TagExpectedValue("base") } }; SaveUnlocks(flags, progressionUnlocks.OtherUnlocks, heroPath, "Achievement", config, tags, voiceSet, hero); } if (npc) { foreach (var skin in hero.m_skinThemes) { if (!config.ContainsKey("skin") || !config["skin"].ShouldDo(GetFileName(skin.m_5E9665E3))) { continue; } SkinTheme.Save(flags, Path.Combine(heroPath, Unlock.GetTypeName(typeof(STUUnlock_SkinTheme)), string.Empty, GetFileName(skin.m_5E9665E3)), skin, hero); } continue; } if (progressionUnlocks.LevelUnlocks != null) // default unlocks { Dictionary <string, TagExpectedValue> tags = new Dictionary <string, TagExpectedValue> { { "event", new TagExpectedValue("base") } }; foreach (LevelUnlocks levelUnlocks in progressionUnlocks.LevelUnlocks) { SaveUnlocks(flags, levelUnlocks.Unlocks, heroPath, "Default", config, tags, voiceSet, hero); } } if (progressionUnlocks.LootBoxesUnlocks != null) { foreach (LootBoxUnlocks lootBoxUnlocks in progressionUnlocks.LootBoxesUnlocks) { if (lootBoxUnlocks.Unlocks == null) { continue; } string lootboxName = LootBox.GetName(lootBoxUnlocks.LootBoxType); var tags = new Dictionary <string, TagExpectedValue> { { "event", new TagExpectedValue(LootBox.GetBasicName(lootBoxUnlocks.LootBoxType)) } }; SaveUnlocks(flags, lootBoxUnlocks.Unlocks, heroPath, lootboxName, config, tags, voiceSet, hero); } } } }
public void SaveUnlocksForHeroes(ICLIFlags flags, IEnumerable <STUHero> heroes, string basePath, bool npc = false) { if (flags.Positionals.Length < 4) { QueryHelp(QueryTypes); return; } Log("Initializing..."); Dictionary <string, Dictionary <string, ParsedArg> > parsedTypes = ParseQuery(flags, QueryTypes, QueryNameOverrides); if (parsedTypes == null) { return; } foreach (STUHero hero in heroes) { string heroNameActual = GetString(hero.Name); string heroFileName = GetValidFilename(heroNameActual); if (heroFileName == null) { continue; // heroFileName = "Unknown"; // heroNameActual = "Unknown"; } heroNameActual = heroNameActual.TrimEnd(' '); heroFileName = heroFileName.TrimEnd(' '); Dictionary <string, ParsedArg> config = new Dictionary <string, ParsedArg>(); foreach (string key in new [] { heroNameActual.ToLowerInvariant(), "*" }) { if (!parsedTypes.ContainsKey(key)) { continue; } foreach (KeyValuePair <string, ParsedArg> parsedArg in parsedTypes[key]) { if (config.ContainsKey(parsedArg.Key)) { config[parsedArg.Key] = config[parsedArg.Key].Combine(parsedArg.Value); } else { config[parsedArg.Key] = parsedArg.Value.Combine(null); // clone for safety } } } if (config.Count == 0) { continue; } var unlocks = GetInstance <STUHeroUnlocks>(hero.LootboxUnlocks); if (unlocks?.Unlocks == null && !npc) { continue; } if (unlocks?.LootboxUnlocks != null && npc) { continue; } Log($"Processing data for {heroNameActual}..."); List <ItemInfo> weaponSkins = ListHeroUnlocks.GetUnlocksForHero(hero.LootboxUnlocks)?.SelectMany(x => x.Value.Where(y => y.Type == "Weapon")).ToList(); // eww? var achievementUnlocks = GatherUnlocks(unlocks?.SystemUnlocks?.Unlocks?.Select(it => (ulong)it)).ToList(); foreach (ItemInfo itemInfo in achievementUnlocks) { if (itemInfo == null) { continue; } Dictionary <string, TagExpectedValue> tags = new Dictionary <string, TagExpectedValue> { { "event", new TagExpectedValue("base") } }; SaveItemInfo(itemInfo, basePath, heroFileName, flags, hero, "Achievement", config, tags, weaponSkins); } if (npc) { foreach (STUHeroSkin skin in hero.Skins) { if (config.ContainsKey("skin") && config["skin"].ShouldDo(GetFileName(skin.SkinOverride))) { Skin.Save(flags, $"{basePath}\\{RootDir}", hero, skin, false); } } continue; } foreach (var defaultUnlocks in unlocks.Unlocks) { var dUnlocks = GatherUnlocks(defaultUnlocks.Unlocks.Select(it => (ulong)it)).ToList(); foreach (ItemInfo itemInfo in dUnlocks) { Dictionary <string, TagExpectedValue> tags = new Dictionary <string, TagExpectedValue> { { "event", new TagExpectedValue("base") } }; SaveItemInfo(itemInfo, basePath, heroFileName, flags, hero, "Standard", config, tags, weaponSkins); } } foreach (var eventUnlocks in unlocks.LootboxUnlocks) { if (eventUnlocks?.Unlocks?.Unlocks == null) { continue; } var eventKey = ItemEvents.GetInstance().EventsNormal[(uint)eventUnlocks.Event]; var eUnlocks = eventUnlocks.Unlocks.Unlocks.Select(it => GatherUnlock(it)).ToList(); foreach (ItemInfo itemInfo in eUnlocks) { if (itemInfo == null) { continue; } Dictionary <string, TagExpectedValue> tags = new Dictionary <string, TagExpectedValue> { { "event", new TagExpectedValue(eventUnlocks.Event.ToString().ToLowerInvariant()) } }; SaveItemInfo(itemInfo, basePath, heroFileName, flags, hero, eventKey, config, tags, weaponSkins); } } Combo.ComboInfo guiInfo = new Combo.ComboInfo(); Combo.Find(guiInfo, hero.ImageResource1); Combo.Find(guiInfo, hero.ImageResource2); Combo.Find(guiInfo, hero.ImageResource3); Combo.Find(guiInfo, hero.ImageResource4); guiInfo.SetTextureName(hero.ImageResource1, "Icon"); guiInfo.SetTextureName(hero.ImageResource2, "Portrait"); guiInfo.SetTextureName(hero.ImageResource4, "Avatar"); guiInfo.SetTextureName(hero.SpectatorIcon, "SpectatorIcon"); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(basePath, RootDir, heroFileName, "GUI"), guiInfo); } }
public void Parse(ICLIFlags toolFlags) { string basePath; if (toolFlags is BetterVoiceFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } foreach (var key in Program.TrackedFiles[0x75]) { var hero = GetInstance <STUHero>(key); var progression = new ProgressionUnlocks(hero); if (progression.LootBoxesUnlocks == null) { continue; // no NPCs thanks } string heroNameActual = GetValidFilename((GetString(hero.m_0EDCE350) ?? $"Unknown{teResourceGUID.Index(key)}").TrimEnd(' ')); var voiceSetComponent = GetInstance <STUVoiceSetComponent>(hero.m_gameplayEntity); if (voiceSetComponent?.m_voiceDefinition == null) { continue; } var voiceSetsCombo = new Combo.ComboInfo(); Combo.Find(voiceSetsCombo, voiceSetComponent.m_voiceDefinition); foreach (var voiceSet in voiceSetsCombo.VoiceSets) { if (voiceSet.Value.VoiceLineInstances == null) { continue; } foreach (var voicelineInstanceInfo in voiceSet.Value.VoiceLineInstances) { foreach (var voiceLineInstance in voicelineInstanceInfo.Value) { var soundFilesCombo = new Combo.ComboInfo();; var stimulus = GetInstance <STUVoiceStimulus>(voiceLineInstance.VoiceStimulus); if (stimulus == null) { continue; } var groupName = GetVoiceGroup(voiceLineInstance.VoiceStimulus, stimulus.m_category, stimulus.m_87DCD58E) ?? "Unknown"; foreach (var soundFile in voiceLineInstance.SoundFiles) { Combo.Find(soundFilesCombo, soundFile); } var path = flags.GroupByHero && flags.GroupByType ? Path.Combine(basePath, Container, heroNameActual, groupName) : Path.Combine(basePath, Container, flags.GroupByHero ? Path.Combine(groupName, heroNameActual) : groupName); foreach (var soundInfo in soundFilesCombo.VoiceSoundFiles.Values) { var filename = soundInfo.GetName(); if (!flags.GroupByHero) { filename = $"{heroNameActual}-{soundInfo.GetName()}"; } SaveLogic.Combo.SaveSoundFile(flags, path, soundFilesCombo, soundInfo.GUID, true, filename); } } } } } }
public void ExtractHeroConvos(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } if (flags.Positionals.Length < 4) { QueryHelp(QueryTypes); return; } string path = Path.Combine(basePath, Container); Dictionary <string, Dictionary <string, ParsedArg> > parsedTypes = ParseQuery(flags, QueryTypes, QueryNameOverrides); if (parsedTypes == null) { return; } Dictionary <ulong, VoiceSet> allVoiceSets = new Dictionary <ulong, VoiceSet>(); foreach (var voiceSetGUID in Program.TrackedFiles[0x5F]) { STUVoiceSet set = GetInstance <STUVoiceSet>(voiceSetGUID); if (set?.m_voiceLineInstances == null) { continue; } allVoiceSets[voiceSetGUID] = new VoiceSet(set); } // Dictionary<uint, string> mapNames = new Dictionary<uint, string>(); // foreach (ulong mapGuid in Program.TrackedFiles[0x9F]) { // STUMapHeader mapHeader = GetInstance<STUMapHeader>(mapGuid); // if (mapHeader == null) continue; // // mapNames[teResourceGUID.Index(mapGuid)] = GetValidFilename(GetString(mapHeader.m_1C706502) ?? GetString(mapHeader.m_displayName)); // } Combo.ComboInfo comboInfo = new Combo.ComboInfo(); foreach (ulong heroGuid in Program.TrackedFiles[0x75]) { STUHero hero = GetInstance <STUHero>(heroGuid); if (hero == null) { continue; } STUVoiceSetComponent voiceSetComponent = GetInstance <STUVoiceSetComponent>(hero.m_gameplayEntity); if (voiceSetComponent?.m_voiceDefinition == null || !allVoiceSets.TryGetValue(voiceSetComponent.m_voiceDefinition, out var set)) { Debugger.Log(0, "DataTool.SaveLogic.Unlock.VoiceLine", "[DataTool.SaveLogic.Unlock.VoiceLine]: VoiceSet not found\r\n"); continue; } string heroNameActual = (GetString(hero.m_0EDCE350) ?? $"Unknown{teResourceGUID.Index(heroGuid)}").TrimEnd(' '); Dictionary <string, ParsedArg> config = GetQuery(parsedTypes, heroNameActual.ToLowerInvariant(), "*"); if (config.Count == 0) { continue; } Log($"Processing data for {heroNameActual}"); heroNameActual = GetValidFilename(heroNameActual); foreach (VoiceLineInstance lineInstance in set.VoiceLines.Values) { // if (lineInstance.STU.m_voiceLineRuntime.m_4FF98D41 != null) { // var cond = lineInstance.STU.m_voiceLineRuntime.m_4FF98D41; // // HandleCondition(flags, comboInfo, lineInstance, path, heroNameActual, cond, mapNames); // } if (lineInstance.VoiceConversation == 0) { continue; } STUVoiceConversation conversation = GetInstance <STUVoiceConversation>(lineInstance.VoiceConversation); if (conversation == null) { continue; // wtf, blizz pls } string convoDir = Path.Combine(path, heroNameActual, GetFileName(lineInstance.VoiceConversation)); foreach (STUVoiceConversationLine line in conversation.m_voiceConversationLine) { string linePath = Path.Combine(convoDir, line.m_B4D405A1.ToString()); foreach (VoiceSet voiceSet in allVoiceSets.Values) { if (voiceSet.VoiceLines.ContainsKey(line.m_lineGUID)) { VoiceLine.SaveVoiceLine(flags, voiceSet.VoiceLines[line.m_lineGUID], linePath, comboInfo); } } } } } }
public void AddNewByContentHash(Combo.ComboInfo info, HashSet <CKey> contentHashes, params ushort[] types) { foreach (KeyValuePair <ulong, ProductHandler_Tank.Asset> asset in TankHandler.m_assets) { TankHandler.UnpackAsset(asset.Value, out var package, out var record); ushort fileType = teResourceGUID.Type(asset.Key); if (fileType == 0x9C) { continue; // bundle } if (fileType == 0x77) { continue; // package } if (!types.Contains(fileType)) { continue; } var cmf = TankHandler.GetContentManifestForAsset(asset.Key); if (!cmf.TryGet(record.m_GUID, out var cmfData)) { //throw new FileNotFoundException(); // todo: wtf continue; } if (contentHashes.Contains(cmfData.ContentKey)) { continue; } if (fileType == 0x4) { var locale = teResourceGUID.Locale(asset.Key); if (locale == 0xF) { continue; // ? } if (locale == 0x1F) { continue; // ? } if (locale == 0x2F) { continue; // ? } if (locale == 0x3F) { continue; // ? } if (locale == 0x4F) { continue; // ? } if (locale == 0x5F) { continue; // ? } if (teResourceGUID.Platform(asset.Key) == 0x8) { continue; // effect images } } Combo.Find(info, asset.Key); } }