public static void Save(ICLIFlags flags, string directory, STUSkinBase skin, STUHero hero) { Dictionary <ulong, ulong> replacements = GetReplacements(skin); LoudLog("\t\tFinding"); FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo(); var saveContext = new Combo.SaveContext(info); FindLogic.Combo.Find(info, hero.m_gameplayEntity, replacements); info.SetEntityName(hero.m_gameplayEntity, "Gameplay3P"); FindLogic.Combo.Find(info, hero.m_previewEmoteEntity, replacements); info.SetEntityName(hero.m_previewEmoteEntity, "PreviewEmote"); FindLogic.Combo.Find(info, hero.m_322C521A, replacements); info.SetEntityName(hero.m_322C521A, "Showcase"); FindLogic.Combo.Find(info, hero.m_26D71549, replacements); info.SetEntityName(hero.m_26D71549, "HeroGallery"); FindLogic.Combo.Find(info, hero.m_8125713E, replacements); info.SetEntityName(hero.m_8125713E, "HighlightIntro"); if (skin is STUSkinTheme skinTheme) { info.m_processExistingEntities = true; List <Dictionary <ulong, ulong> > weaponReplacementStack = new List <Dictionary <ulong, ulong> >(); for (var index = 0; index < skinTheme.m_heroWeapons.Length; index++) { var weaponOverrideGUID = skinTheme.m_heroWeapons[index]; STUHeroWeapon heroWeapon = GetInstance <STUHeroWeapon>(weaponOverrideGUID); if (heroWeapon == null) { continue; } Dictionary <ulong, ulong> weaponReplacements = GetReplacements(heroWeapon); SetPreviewWeaponNames(info, weaponReplacements, hero.m_previewWeaponEntities, index); SetPreviewWeaponNames(info, weaponReplacements, hero.m_C2FE396F, index); weaponReplacementStack.Add(weaponReplacements == null ? new Dictionary <ulong, ulong>() : weaponReplacements.Where(x => teResourceGUID.Type(x.Key) == 0x1A).ToDictionary(x => x.Key, x => x.Value)); } for (var index = 0; index < weaponReplacementStack.Count; index++) { foreach (var pair in weaponReplacementStack[index].Where(pair => pair.Key != pair.Value && info.m_modelLooks.ContainsKey(pair.Value) && info.m_modelLooks[pair.Value].m_name == null)) { info.SetModelLookName(pair.Value, $"{(STUWeaponType) index:G}-{teResourceGUID.Index(pair.Value):X}"); } } info.m_processExistingEntities = false; } foreach (STU_1A496D3C tex in hero.m_8203BFE1) // find GUI { FindLogic.Combo.Find(info, tex.m_texture, replacements); info.SetTextureName(tex.m_texture, teResourceGUID.AsString(tex.m_id)); } if (replacements != null) { string soundDirectory = Path.Combine(directory, "Sound"); FindLogic.Combo.ComboInfo diffInfoBefore = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.ComboInfo diffInfoAfter = new FindLogic.Combo.ComboInfo(); var diffInfoAfterContext = new Combo.SaveContext(diffInfoAfter); // todo: remove foreach (KeyValuePair <ulong, ulong> replacement in replacements) { uint diffReplacementType = teResourceGUID.Type(replacement.Value); if (diffReplacementType != 0x2C && diffReplacementType != 0x3F && diffReplacementType != 0xB2) { continue; // no voice sets, use extract-hero-voice } FindLogic.Combo.Find(diffInfoAfter, replacement.Value); FindLogic.Combo.Find(diffInfoBefore, replacement.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.VoiceSetAsset> voiceSet in diffInfoAfter.m_voiceSets) { if (diffInfoBefore.m_voiceSets.ContainsKey(voiceSet.Key)) { continue; } Combo.SaveVoiceSet(flags, soundDirectory, diffInfoAfterContext, voiceSet.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileAsset> soundFile in diffInfoAfter.m_soundFiles) { if (diffInfoBefore.m_soundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfterContext, soundFile.Key, false); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileAsset> soundFile in diffInfoAfter.m_voiceSoundFiles) { if (diffInfoBefore.m_voiceSoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfterContext, soundFile.Key, true); } diffInfoAfterContext.Wait(); } LoudLog("\t\tSaving"); Combo.SaveLooseTextures(flags, Path.Combine(directory, "GUI"), saveContext); Combo.Save(flags, directory, saveContext); saveContext.Wait(); LoudLog("\t\tDone"); }
public void Parse(ICLIFlags toolFlags) { SaveAbilities(toolFlags); }
protected Dictionary <string, Dictionary <string, ParsedArg> > ParseQuery(ICLIFlags flags, List <QueryType> queryTypes, Dictionary <string, string> queryNameOverrides) { string[] result = new string[flags.Positionals.Length - 3]; Array.Copy(flags.Positionals, 3, result, 0, flags.Positionals.Length - 3); Dictionary <string, Dictionary <string, ParsedArg> > parsedTypes = new Dictionary <string, Dictionary <string, ParsedArg> >(); if (result.Length == 0) { return(null); } foreach (string opt in result) { if (opt.StartsWith("--")) { continue; // ok so this is a flag } string[] split = opt.Split('|'); string hero = split[0].ToLowerInvariant(); if (queryNameOverrides != null && queryNameOverrides.ContainsKey(hero)) { hero = queryNameOverrides[hero]; } string[] afterOpts = new string[split.Length - 1]; Array.Copy(split, 1, afterOpts, 0, split.Length - 1); parsedTypes[hero] = new Dictionary <string, ParsedArg>(); if (afterOpts.Length == 0) { foreach (QueryType type in queryTypes) { parsedTypes[hero][type.Name] = new ParsedArg { Type = type.Name, Allowed = new List <string> { "*" }, Disallowed = new List <string>(), Tags = new Dictionary <string, TagValue>() }; if (type.Tags != null) { foreach (QueryTag tagObj in type.Tags.Where(x => x.Default != null)) { string tagName = tagObj.Name.ToLowerInvariant(); if (parsedTypes[hero][type.Name].Tags.ContainsKey(tagName)) { continue; } TagValue valueObject = (TagValue)Activator.CreateInstance(tagObj.ValueType); valueObject.Value = tagObj.Default; parsedTypes[hero][type.Name].Tags[tagName] = valueObject; } } } // everything for this hero } else { foreach (string afterHeroOpt in afterOpts) { string[] afterSplit = afterHeroOpt.Split('='); string type = afterSplit[0].ToLowerInvariant(); List <QueryType> types = new List <QueryType>(); if (type == "*") { types = queryTypes; } else { types.Add(queryTypes.FirstOrDefault(x => x.Name.ToLowerInvariant() == type)); } foreach (QueryType typeObj in types) { if (typeObj == null) { Log($"\r\nUnknown type: {type}\r\n"); QueryHelp(queryTypes); return(null); } parsedTypes[hero][typeObj.Name] = new ParsedArg { Type = typeObj.Name, Allowed = new List <string>(), Disallowed = new List <string>(), Tags = new Dictionary <string, TagValue>() }; string[] items = new string[afterSplit.Length - 1]; Array.Copy(afterSplit, 1, items, 0, afterSplit.Length - 1); items = string.Join("=", items).Split(','); bool isBracket = false; foreach (string item in items) { string realItem = item.ToLowerInvariant(); bool nextNotBracket = false; if (item.StartsWith("(") && item.EndsWith(")")) { realItem = item.Remove(0, 1); realItem = realItem.Remove(realItem.Length - 1); isBracket = true; nextNotBracket = true; } else if (item.StartsWith("(")) { isBracket = true; realItem = item.Remove(0, 1); } else if (item.EndsWith(")")) { nextNotBracket = true; realItem = item.Remove(item.Length - 1); } if (!isBracket) { if (!realItem.StartsWith("!")) { parsedTypes[hero][typeObj.Name].Allowed.Add(realItem); } else { parsedTypes[hero][typeObj.Name].Disallowed.Add(realItem.Remove(0, 1)); } } else { string[] kv = realItem.Split('='); string tagName = kv[0].ToLowerInvariant(); string tagValue = kv[1].ToLowerInvariant(); QueryTag tagObj = typeObj.Tags.FirstOrDefault(x => x.Name.ToLowerInvariant() == tagName); if (tagObj == null) { Log($"\r\nUnknown tag: {tagName}\r\n"); QueryHelp(queryTypes); return(null); } TagValue valueObject = (TagValue)Activator.CreateInstance(tagObj.ValueType); valueObject.Value = tagValue; parsedTypes[hero][typeObj.Name].Tags[tagName] = valueObject; } if (nextNotBracket) { isBracket = false; } } foreach (QueryTag tagObj in typeObj.Tags.Where(x => x.Default != null)) { string tagName = tagObj.Name.ToLowerInvariant(); if (parsedTypes[hero][typeObj.Name].Tags.ContainsKey(tagName)) { continue; } TagValue valueObject = (TagValue)Activator.CreateInstance(tagObj.ValueType); valueObject.Value = tagObj.Default; parsedTypes[hero][typeObj.Name].Tags[tagName] = valueObject; } if (parsedTypes[hero][typeObj.Name].Allowed.Count == 0 && parsedTypes[hero][typeObj.Name].Tags.Count > 0) { parsedTypes[hero][typeObj.Name].Allowed = new List <string> { "*" }; } } } } } return(parsedTypes); }
public static void SaveUnlock(ICLIFlags flags, Unlock unlock, string path, string eventKey, Dictionary <string, ParsedArg> config, Dictionary <string, TagExpectedValue> tags, VoiceSet voiceSet, STUHero hero) { string rarity; if (tags != null) { if (unlock.STU.m_0B1BA7C1 == null) { rarity = unlock.Rarity.ToString(); tags["leagueTeam"] = new TagExpectedValue("none"); } else { TeamDefinition teamDef = new TeamDefinition(unlock.STU.m_0B1BA7C1); tags["leagueTeam"] = new TagExpectedValue(teamDef.Abbreviation, // NY teamDef.Location, // New York teamDef.Name, // Excelsior teamDef.FullName, // New York Excelsior (teamDef.Division == Enum_5A789F71.None && teamDef.Location == null) ? "none" : "*", "*"); // all // nice file structure rarity = ""; eventKey = "League"; } tags["rarity"] = new TagExpectedValue(unlock.Rarity.ToString()); tags["special"] = new TagExpectedValue(unlock.Tag ?? "none"); } else { rarity = ""; // for general unlocks } var eventMap = GetEventConfig(); if (unlock.STU.m_BEE9BCDA != null) { var formalEventKey = unlock.STU.m_BEE9BCDA.FirstOrDefault(x => eventMap.ContainsKey(x)); if (eventMap.ContainsKey(formalEventKey)) { eventKey = eventMap[formalEventKey]; } } string thisPath = Path.Combine(path, unlock.GetTypeNameEnum(), eventKey, rarity, GetValidFilename(unlock.GetName())); if (ShouldDo(unlock, config, tags, typeof(STUUnlock_SprayPaint))) { SprayAndIcon.Save(flags, thisPath, unlock); } if (ShouldDo(unlock, config, tags, typeof(STUUnlock_AvatarPortrait))) { SprayAndIcon.Save(flags, thisPath, unlock); } if (ShouldDo(unlock, config, tags, typeof(STUUnlock_POTGAnimation))) { AnimationItem.Save(flags, thisPath, unlock); } if (ShouldDo(unlock, config, tags, typeof(STUUnlock_Emote))) { AnimationItem.Save(flags, thisPath, unlock); } if (ShouldDo(unlock, config, tags, typeof(STUUnlock_Pose))) { AnimationItem.Save(flags, thisPath, unlock); } if (ShouldDo(unlock, config, tags, typeof(STUUnlock_VoiceLine))) { VoiceLine.Save(flags, thisPath, unlock, voiceSet); } if (ShouldDo(unlock, config, tags, typeof(STUUnlock_SkinTheme))) { SkinTheme.Save(flags, thisPath, unlock, hero); } if (ShouldDo(unlock, config, tags, typeof(STUUnlock_PortraitFrame))) { thisPath = Path.Combine(path, unlock.Type); PortraitFrame.Save(flags, thisPath, unlock); } }
public void Parse(ICLIFlags toolFlags) { GetGeneralUnlocks(toolFlags); }
public static void SaveModel(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong model) { bool convertModels = true; bool doRefpose = false; if (flags is ExtractFlags extractFlags) { convertModels = extractFlags.ConvertModels && !extractFlags.Raw; doRefpose = extractFlags.ExtractRefpose; if (extractFlags.SkipModels) { return; } } FindLogic.Combo.ModelInfoNew modelInfo = info.Models[model]; string modelDirectory = Path.Combine(path, "Models", modelInfo.GetName()); string refposePath = ""; if (doRefpose) { refposePath = Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".smd"); } if (convertModels) { Model.OWModelWriter14 modelWriter = new Model.OWModelWriter14(); string modelPath = Path.Combine(modelDirectory, $"{modelInfo.GetNameIndex()}{modelWriter.Format}"); CreateDirectoryFromFile(modelPath); Stream modelStream = OpenFile(modelInfo.GUID); if (info.SaveRuntimeData.Threads) { info.SaveRuntimeData.Tasks.Add(Task.Run(() => { SaveOWModelFile(flags, modelPath, modelWriter, info, modelInfo, modelStream, doRefpose, refposePath); })); } else { SaveOWModelFile(flags, modelPath, modelWriter, info, modelInfo, modelStream, doRefpose, refposePath); } if (doRefpose) { } } 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, model); } }
public void Parse(ICLIFlags toolFlags) { Dictionary <teResourceGUID, MapHeader> maps = GetMaps(); if (toolFlags is ListFlags flags) { if (flags.JSON) { OutputJSON(maps, flags); return; } } var iD = new IndentHelper(); foreach (var map in maps) { var data = map.Value; if ((toolFlags as ListFlags).Simplify) { Log(data.GetUniqueName()); } else { Log($"{iD}{data.GetUniqueName()} ({data.MapGUID:X8})"); if (!string.IsNullOrEmpty(data.Name)) { Log($"{iD + 1}Name: {data.Name}"); } if (!string.IsNullOrEmpty(data.VariantName)) { Log($"{iD + 1}VariantName: {data.VariantName}"); } if (!string.IsNullOrEmpty(data.Description)) { Log($"{iD + 1}Desc1: {data.Description}"); } if (!string.IsNullOrEmpty(data.Description2)) { Log($"{iD + 1}Desc2: {data.Description2}"); } Log($"{iD + 1}Status: {data.State}"); Log($"{iD + 1}Type: {data.MapType}"); if (data.StateA != null || data.StateB != null) { Log($"{iD + 1}States:"); Log($"{iD + 2}{data.StateA ?? "N/A"}"); Log($"{iD + 2}{data.StateB ?? "N/A"}"); } if (data.GameModes != null) { Log($"{iD + 1}GameModes:"); foreach (var gameModeLight in data.GameModes) { Console.Out.WriteLine($"{iD + 2}{gameModeLight.Name ?? "N/A"} ({teResourceGUID.AsString(gameModeLight.GUID)})"); } } Log(); } } }
public static void Save(ICLIFlags flags, string directory, STUSkinBase skin, STUHero hero) { Dictionary <ulong, ulong> replacements = GetReplacements(skin); LoudLog("\t\tFinding"); FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.Find(info, hero.m_gameplayEntity, replacements); info.SetEntityName(hero.m_gameplayEntity, "Gameplay3P"); FindLogic.Combo.Find(info, hero.m_previewEmoteEntity, replacements); info.SetEntityName(hero.m_previewEmoteEntity, "PreviewEmote"); FindLogic.Combo.Find(info, hero.m_322C521A, replacements); info.SetEntityName(hero.m_322C521A, "Showcase"); FindLogic.Combo.Find(info, hero.m_26D71549, replacements); info.SetEntityName(hero.m_26D71549, "HeroGallery"); FindLogic.Combo.Find(info, hero.m_8125713E, replacements); info.SetEntityName(hero.m_8125713E, "HighlightIntro"); if (skin is STUSkinTheme skinTheme) { info.Config.DoExistingEntities = true; foreach (var weaponOverrideGUID in skinTheme.m_heroWeapons) { STUHeroWeapon heroWeapon = GetInstance <STUHeroWeapon>(weaponOverrideGUID); if (heroWeapon == null) { continue; } Dictionary <ulong, ulong> weaponReplacements = GetReplacements(heroWeapon); SavePreviewWeapons(info, weaponReplacements, hero.m_previewWeaponEntities); SavePreviewWeapons(info, weaponReplacements, hero.m_C2FE396F); } info.Config.DoExistingEntities = false; } foreach (STU_1A496D3C tex in hero.m_8203BFE1) { FindLogic.Combo.Find(info, tex.m_texture, replacements); info.SetTextureName(tex.m_texture, teResourceGUID.AsString(tex.m_id)); } Combo.SaveLooseTextures(flags, Path.Combine(directory, "GUI"), info); if (replacements != null) { string soundDirectory = Path.Combine(directory, "Sound"); FindLogic.Combo.ComboInfo diffInfoBefore = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.ComboInfo diffInfoAfter = new FindLogic.Combo.ComboInfo(); foreach (KeyValuePair <ulong, ulong> replacement in replacements) { uint diffReplacementType = teResourceGUID.Type(replacement.Value); if (diffReplacementType != 0x2C && diffReplacementType != 0x3F && diffReplacementType != 0xB2) { continue; // no voice sets, use extract-hero-voice } FindLogic.Combo.Find(diffInfoAfter, replacement.Value); FindLogic.Combo.Find(diffInfoBefore, replacement.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.VoiceSetInfo> voiceSet in diffInfoAfter.VoiceSets) { if (diffInfoBefore.VoiceSets.ContainsKey(voiceSet.Key)) { continue; } Combo.SaveVoiceSet(flags, soundDirectory, diffInfoAfter, voiceSet.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> soundFile in diffInfoAfter.SoundFiles) { if (diffInfoBefore.SoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfter, soundFile.Key, false); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> soundFile in diffInfoAfter.VoiceSoundFiles) { if (diffInfoBefore.VoiceSoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfter, soundFile.Key, true); } } LoudLog("\t\tSaving"); Combo.Save(flags, directory, info); LoudLog("\t\tDone"); }
private static void Main() { Console.OutputEncoding = Encoding.UTF8; Files = new Dictionary <ulong, MD5Hash>(); TrackedFiles = new Dictionary <ushort, HashSet <ulong> >(); #region Tool Detection HashSet <Type> tools = new HashSet <Type>(); { Assembly asm = typeof(ITool).Assembly; Type t = typeof(ITool); List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList(); foreach (Type tt in types) { ToolAttribute attrib = tt.GetCustomAttribute <ToolAttribute>(); if (tt.IsInterface || attrib == null) { continue; } tools.Add(tt); if (attrib.TrackTypes == null) { continue; } foreach (ushort type in attrib.TrackTypes) { if (!TrackedFiles.ContainsKey(type)) { TrackedFiles[type] = new HashSet <ulong>(); } } } } #endregion Flags = FlagParser.Parse <ToolFlags>(() => PrintHelp(tools)); if (Flags == null) { return; } Logger.EXIT = !Flags.GracefulExit; ITool targetTool = null; ICLIFlags targetToolFlags = null; #region Tool Activation foreach (Type type in tools) { ToolAttribute attrib = type.GetCustomAttribute <ToolAttribute>(); if (!string.Equals(attrib.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase)) { continue; } targetTool = Activator.CreateInstance(type) as ITool; if (attrib.CustomFlags != null) { Type flags = attrib.CustomFlags; if (typeof(ICLIFlags).IsAssignableFrom(flags)) { targetToolFlags = typeof(FlagParser).GetMethod("Parse", new Type[] { }).MakeGenericMethod(flags).Invoke(null, null) as ICLIFlags; } } break; } #endregion if (targetTool == null) { FlagParser.Help <ToolFlags>(false); PrintHelp(tools); if (Debugger.IsAttached) { Debugger.Break(); } return; } #region Initialize CASC Log("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, Util.GetVersion()); Log("Initializing CASC..."); Log("Set language to {0}", Flags.Language); CDNIndexHandler.Cache.Enabled = Flags.UseCache; CDNIndexHandler.Cache.CacheData = Flags.CacheData; CDNIndexHandler.Cache.Validate = Flags.ValidateCache; // ngdp:us:pro // http:us:pro:us.patch.battle.net:1119 if (Flags.OverwatchDirectory.ToLowerInvariant().Substring(0, 5) == "ngdp:") { string cdn = Flags.OverwatchDirectory.Substring(5, 4); string[] parts = Flags.OverwatchDirectory.Substring(5).Split(':'); string region = "us"; string product = "pro"; if (parts.Length > 1) { region = parts[1]; } if (parts.Length > 2) { product = parts[2]; } if (cdn == "bnet") { Config = CASCConfig.LoadOnlineStorageConfig(product, region); } else { if (cdn == "http") { string host = string.Join(":", parts.Skip(3)); Config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true); } } } else { Config = CASCConfig.LoadLocalStorageConfig(Flags.OverwatchDirectory, !Flags.SkipKeys, false); } Config.Languages = new HashSet <string>(new[] { Flags.Language }); #endregion foreach (Dictionary <string, string> build in Config.BuildInfo) { if (!build.ContainsKey("Tags")) { continue; } if (build["Tags"].Contains("XX?")) { IsPTR = true; } // us ptr region is known as XX, so just look for it in the tags. // this should work... untested for Asia } BuildVersion = uint.Parse(Config.BuildName.Split('.').Last()); if (Flags.SkipKeys) { Log("Disabling Key auto-detection..."); } Log("Using Overwatch Version {0}", Config.BuildName); CASC = CASCHandler.OpenStorage(Config); Root = CASC.Root as OwRootHandler; if (Root == null) { ErrorLog("Not a valid overwatch installation"); return; } // Fail when trying to extract data from a specified language with 2 or less files found. if (!Root.APMFiles.Any()) { ErrorLog("Could not find the files for language {0}. Please confirm that you have that language installed, and are using the names from the target language.", Flags.Language); if (!Flags.GracefulExit) { return; } } Log("Mapping..."); TrackedFiles[0x90] = new HashSet <ulong>(); IO.MapCMF(); IO.LoadGUIDTable(); Sound.WwiseBank.GetReady(); #region Key Detection if (!Flags.SkipKeys) { Log("Adding Encryption Keys..."); foreach (ulong key in TrackedFiles[0x90]) { if (!ValidKey(key)) { continue; } using (Stream stream = IO.OpenFile(Files[key])) { if (stream == null) { continue; } STUEncryptionKey encryptionKey = GetInstance <STUEncryptionKey>(key); if (encryptionKey != null && !KeyService.keys.ContainsKey(encryptionKey.LongRevKey)) { KeyService.keys.Add(encryptionKey.LongRevKey, encryptionKey.KeyValue); Log("Added Encryption Key {0}, Value: {1}", encryptionKey.KeyNameProper, encryptionKey.Key); } } } } #endregion Log("Tooling..."); targetTool.Parse(targetToolFlags); if (Debugger.IsAttached) { Debugger.Break(); } }
public static void Save(ICLIFlags flags, MapHeader mapInfo, STUMapHeader mapHeader, ulong key, string basePath) { var name = mapInfo.GetName(); LoudLog($"Extracting map {name}/{teResourceGUID.Index(key):X}"); // TODO: MAP11 HAS CHANGED // TODO: MAP10 TOO? name = GetValidFilename(name); 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"); var context = new Combo.SaveContext(info); Combo.Save(flags, mapPath, context); Combo.SaveLooseTextures(flags, Path.Combine(mapPath, "Textures"), context); context.Wait(); 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.m_voiceSets.Remove(announcerVoiceSet); } Combo.SaveAllVoiceSets(flags, Path.Combine(mapPath, "VoiceSets"), context); Combo.SaveAllSoundFiles(flags, Path.Combine(mapPath, "Sound"), context); context.Wait(); LoudLog("\tDone"); }
public void Parse(ICLIFlags toolFlags) { RAMTest(toolFlags); }
public void Parse(ICLIFlags toolFlags) { GetLootboxes(toolFlags); }
public void Parse(ICLIFlags toolFlags) { ExtractMOVI(toolFlags); }
public void Parse(ICLIFlags toolFlags) { SpecialHelper(toolFlags); }
public void SaveMaps(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } basePath = Path.Combine(basePath, "Environments"); if (!Directory.Exists(basePath)) { Directory.CreateDirectory(basePath); } if (!flags.SkipMapEnvironmentLUT && File.Exists(Path.Combine(basePath, "SPILUT", "config.ocio"))) { File.Delete(Path.Combine(basePath, "SPILUT", "config.ocio")); } HashSet <KeyValuePair <ulong, string> > done = new HashSet <KeyValuePair <ulong, string> >(); foreach (ulong metaKey in TrackedFiles[0x9F]) { STUMapHeader map = GetInstance <STUMapHeader>(metaKey); if (map == null) { continue; } MapHeader mapInfo = GetMap(metaKey); ulong dataKey = map.m_map; //if (teResourceGUID.Index(dataKey) != 0x7A4) continue; var mapName = GetValidFilename($"{mapInfo.GetName()}_{teResourceGUID.Index(mapInfo.MapGUID):X}"); string fname = $"ow_map_{mapName}"; var reflectionData = Map.GetPlaceableData(map, Enums.teMAP_PLACEABLE_TYPE.REFLECTIONPOINT); if (reflectionData != null) { foreach (var placeable in reflectionData.Placeables ?? Array.Empty <IMapPlaceable>()) { if (!(placeable is teMapPlaceableReflectionPoint reflectionPoint)) { continue; } if (done.Add(new KeyValuePair <ulong, string>(reflectionPoint.Header.Texture1, mapInfo.Name + "cube"))) { SaveTex(flags, basePath, Path.Combine("Cubemap", fname), reflectionPoint.Header.Texture1.ToString(), reflectionPoint.Header.Texture1); } if (done.Add(new KeyValuePair <ulong, string>(reflectionPoint.Header.Texture2, mapInfo.Name + "cube"))) { SaveTex(flags, basePath, Path.Combine("Cubemap", fname), reflectionPoint.Header.Texture2.ToString(), reflectionPoint.Header.Texture2); } } } using (Stream data = OpenFile(dataKey)) { if (data != null) { using (BinaryReader dataReader = new BinaryReader(data)) { teMap env = dataReader.Read <teMap>(); // using (Stream lightingStream = OpenFile(env.BakedLighting)) { // teLightingManifest lightingManifest = new teLightingManifest(lightingStream); //} if (!flags.SkipMapEnvironmentSound && done.Add(new KeyValuePair <ulong, string>(env.MapEnvironmentSound, mapInfo.Name))) { SaveSound(flags, basePath, Path.Combine("Sound", mapName), env.MapEnvironmentSound); } if (!flags.SkipMapEnvironmentLUT && done.Add(new KeyValuePair <ulong, string>(env.LUT, mapInfo.Name))) { SaveTex(flags, basePath, "LUT", fname + env.LUT, env.LUT); SaveLUT(flags, basePath, "SPILUT", fname + env.LUT, env.LUT, Path.Combine(basePath, "SPILUT", "config.ocio"), mapInfo); } if (!flags.SkipMapEnvironmentBlendCubemap && done.Add(new KeyValuePair <ulong, string>(env.BlendEnvironmentCubemap, mapInfo.Name))) { SaveTex(flags, basePath, "BlendCubemap", fname + env.BlendEnvironmentCubemap, env.BlendEnvironmentCubemap); } if (!flags.SkipMapEnvironmentGroundCubemap && done.Add(new KeyValuePair <ulong, string>(env.GroundEnvironmentCubemap, mapInfo.Name))) { SaveTex(flags, basePath, "GroundCubemap", fname + env.GroundEnvironmentCubemap, env.GroundEnvironmentCubemap); } if (!flags.SkipMapEnvironmentSkyCubemap && done.Add(new KeyValuePair <ulong, string>(env.SkyEnvironmentCubemap, mapInfo.Name))) { SaveTex(flags, basePath, "SkyCubemap", fname + env.SkyEnvironmentCubemap, env.SkyEnvironmentCubemap); } if (!flags.SkipMapEnvironmentSkybox && done.Add(new KeyValuePair <ulong, string>(env.SkyboxModel + env.SkyboxModelLook, mapInfo.Name))) { SaveMdl(flags, basePath, Path.Combine("Skybox", mapName), env.SkyboxModel, env.SkyboxModelLook); } if (!flags.SkipMapEnvironmentEntity && done.Add(new KeyValuePair <ulong, string>(env.EntityDefinition, mapInfo.Name))) { SaveEntity(flags, basePath, Path.Combine("Entity", mapName), env.EntityDefinition); } } } } InfoLog("Saved Environment data for {0}", mapInfo.GetUniqueName()); SaveScratchDatabase(); } }
public void GetSoundbanks(ICLIFlags toolFlags) { const string container = "ShaderCode"; //const ulong materialGUID = 0xE00000000005860; // 000000005860.008: Sombra - League - NYXL - Main //const string matName = "Sombra - League - NYXL - Main"; //const ulong materialGUID = 0xE00000000006086; //const string matName = "Orisa - Nature - Leaves"; //const ulong materialGUID = 0xE00000000002381; //const string matName = "Maps - Tall bush"; //const ulong materialGUID = 0xE000000000008B2; //const string matName = "Widow - Odette - Arm tassels"; // orisa owl //const ulong materialGUID = 0xE00000000005809; // 000000005809.008: Orisa - League - NYXL - Team Decals //const string matName = "Orisa - League - NYXL - Team Decals"; //const ulong materialGUID = 0xE00000000005840; //const string matName = "Orisa - League - NYXL - Main"; //const ulong materialGUID = 0xE000000000051CC; //const string matName = "Orisa - League - NYXL - 51CC"; string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } string path = Path.Combine(basePath, container); //TestModelLook(0x98000000000682F); // Chateau - Lake //SaveMaterial(path, 0xE00000000004F46, "Chateau - Tower - Body"); //SaveMaterial(path, 0xE00000000004F45, "Chateau - Tower - Borders"); //SaveMaterial(path, 0xE00000000004D4B, "Chateau - Tower - Windows"); //SaveMaterial(path, 0xE00000000004F44, "Chateau - Tower - Tip"); //SaveMaterial(path, 0xE000000000003A5, "Rein - Shield - Main"); //SaveMaterial(path, 0xE00000000005840, "Orisa - League - NYXL - Main"); //SaveMaterial(path, 0xE00000000005809, "Orisa - League - NYXL - Team Decals"); //SaveMaterial(path, 0xE00000000005C70, "Moira - Blackwatch - Decals"); //SaveMaterial(path, 0xE0000000000562D, "Moira - Blackwatch - Face"); //SaveCompute(path); // string allPath = Path.Combine(path, "All"); // foreach (ulong inst in TrackedFiles[0x86]) { // SaveShaderInstance(allPath, inst, teResourceGUID.AsString(inst)); // } // return; SaveMaterial(path, 0xE00000000002381, "Chateau - Tall bush"); SaveMaterial(path, 0xE00000000004D29, "Chateau - Lake"); //SaveMaterial(path, 0xE00000000004F0B, "Chateau - Background - Road"); //SaveMaterial(path, 0xE00000000004EFF, "Chateau - Background - House"); SaveMaterial(path, 0xE00000000004F46, "Chateau - Tower - Body"); SaveMaterial(path, 0xE000000000040C0, "Orisa - Classic - Main"); SaveMaterial(path, 0xE00000000000171, "Reaper - Classic - Main"); SaveMaterial(path, 0xE00000000005BBB, "Brigitte - Classic - Hair"); //SavePostFX(path); //SaveScreenQuad(path); Save088(path); }
public static void SaveAnimation(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong animation, ulong model) { bool convertAnims = false; if (flags is ExtractFlags extractFlags) { convertAnims = extractFlags.ConvertAnimations && !extractFlags.Raw; if (extractFlags.SkipAnimations) { return; } } SEAnimWriter animWriter = new SEAnimWriter(); FindLogic.Combo.AnimationInfoNew animationInfo = info.Animations[animation]; using (Stream animStream = OpenFile(animation)) { if (animStream == null) { return; } MemoryStream animMemStream = new MemoryStream(); animStream.CopyTo(animMemStream); if (info.SaveRuntimeData.Threads) { info.SaveRuntimeData.Tasks.Add(Task.Run(() => { ConvertAnimation(animMemStream, path, convertAnims, animWriter, animationInfo); })); } else { ConvertAnimation(animMemStream, path, convertAnims, animWriter, animationInfo); } } if (!info.SaveConfig.SaveAnimationEffects) { return; } FindLogic.Combo.EffectInfoCombo animationEffect; // just create a fake effect if it doesn't exist if (animationInfo.Effect == 0) { animationEffect = new FindLogic.Combo.EffectInfoCombo(0) { Effect = new EffectParser.EffectInfo() }; animationEffect.Effect.SetupEffect(); } else if (info.Effects.ContainsKey(animationInfo.Effect)) { // wot, why animationEffect = info.Effects[animationInfo.Effect]; } else { animationEffect = info.AnimationEffects[animationInfo.Effect]; } Effect.OWAnimWriter owAnimWriter = new Effect.OWAnimWriter(); string animationEffectDir = Path.Combine(path, Model.AnimationEffectDir, animationInfo.GetNameIndex()); string animationEffectFile = Path.Combine(animationEffectDir, $"{animationInfo.GetNameIndex()}{owAnimWriter.Format}"); Dictionary <ulong, HashSet <FindLogic.Combo.VoiceLineInstanceInfo> > svceLines = new Dictionary <ulong, HashSet <FindLogic.Combo.VoiceLineInstanceInfo> >(); if (animationEffect.GUID != 0) { SaveEffectExtras(flags, animationEffectDir, info, animationEffect.Effect, out svceLines); } if (info.SaveRuntimeData.Threads) { info.SaveRuntimeData.Tasks.Add(Task.Run(() => { SaveOWAnimFile(animationEffectFile, animationEffect, animationInfo, info, owAnimWriter, model, svceLines); })); } else { SaveOWAnimFile(animationEffectFile, animationEffect, animationInfo, info, owAnimWriter, model, svceLines); } }
public void Parse(ICLIFlags toolFlags) { ExtractOWL(toolFlags); }
public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong texture) { bool convertTextures = true; bool lossless = false; string convertType = "dds"; if (flags is ExtractFlags extractFlags) { convertTextures = extractFlags.ConvertTextures && !extractFlags.Raw; convertType = extractFlags.ConvertTexturesType.ToLowerInvariant(); lossless = extractFlags.ConvertTexturesLossless; if (extractFlags.SkipTextures) { return; } } path += Path.DirectorySeparatorChar; FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[texture]; string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}"); if (!convertTextures) { CreateDirectoryFromFile(path); using (Stream textureStream = OpenFile(textureInfo.GUID)) WriteFile(textureStream, $"{filePath}.{GUID.Type(textureInfo.GUID):X3}"); if (!textureInfo.UseData) { return; } using (Stream textureStream = OpenFile(textureInfo.DataGUID)) WriteFile(textureStream, $"{filePath}.04D"); } else { Stream headerStream = OpenFile(textureInfo.GUID); Stream dataStream = null; if (headerStream == null) { return; } if (textureInfo.UseData) { dataStream = OpenFile(textureInfo.DataGUID); if (dataStream == null) { return; } } if (info.SaveRuntimeData.Threads) { info.SaveRuntimeData.Tasks.Add(Task.Run(() => { ConvertTexture(convertType, lossless, filePath, path, headerStream, dataStream); })); } else { ConvertTexture(convertType, lossless, filePath, path, headerStream, dataStream); } } }
public void ExtractOWL(ICLIFlags toolFlags) { string basePath; if (toolFlags is ExtractFlags flags) { basePath = flags.OutputPath; } else { throw new Exception("no output path"); } const string container = "DebugOWL2"; string path = Path.Combine(basePath, container); // foreach (ulong key in TrackedFiles[0xB3]) { // string p = Path.Combine(path, "MatDatas"); // if (GUID.Index(key) != 0x8EE9) continue; // ImageDefinition def = new ImageDefinition(OpenFile(key)); // SaveTextureDef(flags, p, key, def); // // if (def.Layers != null) { // // foreach (ImageLayer layer in def.Layers) { // // if (GUID.Index(layer.Key) == 0x120E2) { // sf shock normal // // // Debugger.Break(); // // SaveTextureDef(flags, p, key, def); // // // found 346777171307564171 // // } // // // // if (GUID.Index(layer.Key) == 0x11C3F) { // sym normal // // // Debugger.Break(); // // SaveTextureDef(flags, p, key, def); // // // found 346777171307564777 // // // found 346777171307565869 // // } // // // // if (GUID.Index(layer.Key) == 0x11D56) { // widow sss // // // Debugger.Break(); // // SaveTextureDef(flags, p, key, def); // // //346777171307565850 / 00000000931A.0B3 // // } // // } // // } // } List <string> added = ExtractDebugNewEntities.GetAddedFiles("D:\\ow\\OverwatchDataManager\\versions\\1.20.0.2.43435\\data.json"); Combo.ComboInfo imgInfo = new Combo.ComboInfo(); // Combo.Find(imgInfo, 864691265894168957ul); //foreach (ulong key in TrackedFiles[0xA5]) { // string name = GetFileName(key); // if (!added.Contains(name)) continue; // Skin skin = GetInstance<Skin>(key); // if (skin == null) continue; //} foreach (ulong key in TrackedFiles[0x4]) { string name = GetFileName(key); if (name[3] == 'F') { continue; // :thonk: } if (!added.Contains(name)) { continue; } Combo.Find(imgInfo, key); } Console.Out.WriteLine("ok i do save"); SaveLogic.Combo.SaveLooseTextures(flags, Path.Combine(path, "Tex"), imgInfo); return; foreach (ulong key in TrackedFiles[0xA6]) { STUSkinOverride @override = GetInstance <STUSkinOverride>(key); string name = GetFileName(key); if (!added.Contains(name)) { continue; } Combo.ComboInfo info = new Combo.ComboInfo(); Combo.ComboInfo info2 = new Combo.ComboInfo(); foreach (KeyValuePair <ulong, ulong> overrideReplacement in @override.ProperReplacements) { Combo.Find(info, overrideReplacement.Key); Combo.Find(info2, overrideReplacement.Value); } string p = Path.Combine(path, "SkinOverrides", GetFileName(key)); SaveLogic.Combo.Save(flags, Path.Combine(p, "Before"), info); // SaveLogic.Combo.SaveAllMaterials(flags, Path.Combine(p, "Before"), info); SaveLogic.Combo.SaveAllModelLooks(flags, Path.Combine(p, "Before"), info); SaveLogic.Combo.Save(flags, Path.Combine(p, "After"), info2); // SaveLogic.Combo.SaveAllMaterials(flags, Path.Combine(p, "After"), info2); SaveLogic.Combo.SaveAllModelLooks(flags, Path.Combine(p, "After"), info2); } // foreach (ulong key in TrackedFiles[0x8]) { // Material material = new Material(OpenFile(key), 0); // if (GUID.Index(material.Header.ImageDefinition) == 0x931A) { // Debugger.Break(); // } // } }
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 Parse(ICLIFlags toolFlags) { GetFewParticles(); }
public void Parse(ICLIFlags toolFlags) { ExtractType(toolFlags); }
public void Parse(ICLIFlags toolFlags) { GetSoundbanks(); }
public void Parse(ICLIFlags toolFlags) { List <HighlightJSON> highlights = new List <HighlightJSON>(); DirectoryInfo overwatchAppdataFolder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Blizzard Entertainment/Overwatch")); foreach (DirectoryInfo userFolder in overwatchAppdataFolder.GetDirectories()) { DirectoryInfo highlightsFolder = new DirectoryInfo(Path.Combine(userFolder.FullName, $"{(Program.IsPTR ? "PTR\\" : "")}Highlights")); if (!highlightsFolder.Exists) { continue; } highlights.AddRange(highlightsFolder.GetFiles().Select(item => GetHighlight(item.FullName))); } if (toolFlags is ListFlags flags) { if (flags.JSON) { ParseJSON(highlights, flags); return; } } // todo: timestamp IndentHelper indent = new IndentHelper(); uint count = 0; foreach (HighlightJSON highlight in highlights) { if (count != 0) { Log($"{Environment.NewLine}"); } Log($"{indent}{highlight.UUID}:"); Log($"{indent+1}Map: {highlight.Map}"); Log($"{indent+1}Gamemode: {highlight.Gamemode}"); Log($"{indent+1}HighlightInfo:"); for (int i = 0; i < highlight.HighlightInfo.Count; i++) { Log($"{indent+2}[{i}] {{"); PrintHighlightInfoJSON(highlight.HighlightInfo[i], indent + 3); Log($"{indent+2}}}"); } Log($"{indent+1}Heroes:"); for (int i = 0; i < highlight.HeroInfo.Count; i++) { Log($"{indent+2}[{i}] {{"); Log($"{indent+3}Hero: {highlight.HeroInfo[i].Hero}"); Log($"{indent+3}Skin: {highlight.HeroInfo[i].Skin}"); Log($"{indent+3}HiglightIntro: {highlight.HeroInfo[i].HighlightIntro}"); Log($"{indent+3}Sprays:"); foreach (string spray in highlight.HeroInfo[i].Sprays) { Log($"{indent+4}{spray}"); } Log($"{indent+3}Emotes:"); foreach (string emote in highlight.HeroInfo[i].Emotes) { Log($"{indent+4}{emote}"); } Log($"{indent+3}VoiceLines:"); foreach (string voiceLine in highlight.HeroInfo[i].VoiceLines) { Log($"{indent+4}{voiceLine}"); } Log($"{indent+2}}}"); } Log($"{indent+1}Replay: {{"); Log($"{indent+2}Map: {highlight.Replay.Map}"); Log($"{indent+2}Gamemode: {highlight.Replay.Gamemode}"); Log($"{indent+2}HighlightInfo:"); PrintHighlightInfoJSON(highlight.Replay.HighlightInfo, indent + 3); Log($"{indent+1}}}"); count++; } }
private static void Main() { InitTankSettings(); HookConsole(); var tools = GetTools(); #if DEBUG FlagParser.CheckCollisions(typeof(ToolFlags), (flag, duplicate) => { Logger.Error("Flag", $"The flag \"{flag}\" from {duplicate} is a duplicate!"); }); #endif FlagParser.LoadArgs(); Logger.Info("Core", $"{Assembly.GetExecutingAssembly().GetName().Name} v{Util.GetVersion(typeof(Program).Assembly)}"); Logger.Info("Core", $"CommandLine: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]"); Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools)); if (Flags == null) { return; } Logger.Info("Core", $"CommandLineFile: {FlagParser.ArgFilePath}"); if (Flags.SaveArgs) { FlagParser.AppArgs = FlagParser.AppArgs.Where(x => !x.StartsWith("--arg")).ToArray(); FlagParser.SaveArgs(Flags.OverwatchDirectory); } else if (Flags.ResetArgs || Flags.DeleteArgs) { FlagParser.ResetArgs(); if (Flags.DeleteArgs) { FlagParser.DeleteArgs(); } Logger.Info("Core", $"CommandLineNew: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]"); Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools)); if (Flags == null) { return; } } if (string.IsNullOrWhiteSpace(Flags.OverwatchDirectory) || string.IsNullOrWhiteSpace(Flags.Mode) || Flags.Help) { PrintHelp(false, tools); return; } ITool targetTool = null; ICLIFlags targetToolFlags = null; ToolAttribute targetToolAttributes = null; #region Tool Activation foreach (var type in tools) { var attribute = type.GetCustomAttribute <ToolAttribute>(); if (!string.Equals(attribute.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase)) { continue; } targetTool = Activator.CreateInstance(type) as ITool; targetToolAttributes = attribute; if (attribute.CustomFlags != null) { var flags = attribute.CustomFlags; if (typeof(ICLIFlags).IsAssignableFrom(flags)) { targetToolFlags = typeof(FlagParser).GetMethod(nameof(FlagParser.Parse), new Type[] { }) ?.MakeGenericMethod(flags) .Invoke(null, null) as ICLIFlags; } } break; } if (targetToolFlags == null && targetTool != null) { return; } if (targetTool == null) { FlagParser.Help <ToolFlags>(false, new Dictionary <string, string>()); PrintHelp(false, tools); return; } #endregion if (!targetToolAttributes.UtilNoArchiveNeeded) { try { InitStorage(Flags.Online); } catch { Logger.Log24Bit(ConsoleSwatch.XTermColor.OrangeRed, true, Console.Error, "CASC", "=================\nError initializing CASC!\n" + "Please Scan & Repair your game, launch it for a minute, and try the tools again before reporting a bug!\n" + "========================"); throw; } //foreach (KeyValuePair<ushort, HashSet<ulong>> type in TrackedFiles.OrderBy(x => x.Key)) { // //Console.Out.WriteLine($"Found type: {type.Key:X4} ({type.Value.Count} files)"); // Console.Out.WriteLine($"Found type: {type.Key:X4}"); //} InitKeys(); InitMisc(); } var stopwatch = new Stopwatch(); Logger.Info("Core", "Tooling..."); stopwatch.Start(); targetTool.Parse(targetToolFlags); stopwatch.Stop(); Logger.Success("Core", $"Execution finished in {stopwatch.Elapsed} seconds"); ShutdownMisc(); }
public void Parse(ICLIFlags toolFlags) { ExtractVoiceSets(toolFlags); }
public void Parse(ICLIFlags toolFlags) { SaveMaps(toolFlags); }
public void Parse(ICLIFlags toolFlags) { }
public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong textureGUID) { bool convertTextures = true; string convertType = "tif"; string multiSurfaceConvertType = "tif"; bool createMultiSurfaceSheet = false; bool lossless = false; int maxMips = 1; if (flags is ExtractFlags extractFlags) { if (extractFlags.SkipTextures) { return; } createMultiSurfaceSheet = extractFlags.SheetMultiSurface; convertTextures = !extractFlags.RawTextures && !extractFlags.Raw; convertType = extractFlags.ConvertTexturesType.ToLowerInvariant(); lossless = extractFlags.ConvertTexturesLossless; multiSurfaceConvertType = convertType; if (extractFlags.ForceDDSMultiSurface) { multiSurfaceConvertType = "dds"; } if (convertType == "dds" && extractFlags.SaveMips) { maxMips = 0xF; } } path += Path.DirectorySeparatorChar; FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[textureGUID]; string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}"); if (teResourceGUID.Type(textureGUID) != 0x4) { filePath += $".{teResourceGUID.Type(textureGUID):X3}"; } if (Program.Flags.Deduplicate) { if (ScratchDBInstance.HasRecord(textureGUID)) { return; } ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}"); } CreateDirectoryFromFile(path); if (!convertTextures) { using (Stream textureStream = OpenFile(textureGUID)) { teTexture texture = new teTexture(textureStream, true); textureStream.Position = 0; WriteFile(textureStream, $"{filePath}.004"); if (!texture.PayloadRequired) { return; } for (int i = 0; i < texture.Payloads.Length; ++i) { using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i))) WriteFile(texturePayloadStream, $"{filePath}_{i}.04D"); } } } else { using (Stream textureStream = OpenFile(textureGUID)) { if (textureStream == null) { return; } teTexture texture = new teTexture(textureStream); //if (texture.Header.Flags.HasFlag(teTexture.Flags.CUBEMAP)) return; // for diffing when they add/regen loads of cubemaps if (texture.PayloadRequired) { for (int i = 0; i < texture.Payloads.Length; ++i) { texture.LoadPayload(OpenFile(texture.GetPayloadGUID(textureGUID, i)), i); if (maxMips == 1) { break; } } } uint?width = null; uint?height = null; uint?surfaces = null; if (texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces) { if (createMultiSurfaceSheet) { TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as a sheet because it has more than one surface"); height = (uint)(texture.Header.Height * texture.Header.Surfaces); surfaces = 1; texture.Header.Flags = 0; } else { TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as {multiSurfaceConvertType} because it has more than one surface"); convertType = multiSurfaceConvertType; } } using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) { convertedStream.Position = 0; if (convertType == "dds" || convertedStream.Length == 0) { WriteFile(convertedStream, $"{filePath}.dds"); return; } bool isBcffValid = teTexture.DXGI_BC4.Contains(texture.Header.Format) || teTexture.DXGI_BC5.Contains(texture.Header.Format) || teTexture.ATI2.Contains(texture.Header.GetTextureType()); ImageFormat imageFormat = null; if (convertType == "tif") { imageFormat = ImageFormat.Tiff; } if (convertType == "png") { imageFormat = ImageFormat.Png; } if (convertType == "jpg") { imageFormat = ImageFormat.Jpeg; } // if (convertType == "tga") imageFormat = Im.... oh // so there is no TGA image format. // guess the TGA users are stuck with the DirectXTex stuff for now. if (isBcffValid && imageFormat != null && !(texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces)) { BlockDecompressor decompressor = new BlockDecompressor(convertedStream); decompressor.CreateImage(); decompressor.Image.Save($"{filePath}.{convertType}", imageFormat); return; } string losslessFlag = lossless ? "-wiclossless" : string.Empty; Process pProcess = new Process { StartInfo = { FileName = "Third Party\\texconv.exe", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardInput = true, RedirectStandardError = true, CreateNoWindow = true, Arguments = $"-- \"{Path.GetFileName(filePath)}.dds\" -y -wicmulti {losslessFlag} -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{(path.EndsWith(@"/") || path.EndsWith("\\") ? path.Substring(0, path.Length - 1) : path)}" }, EnableRaisingEvents = true }; pProcess.Start(); convertedStream.Position = 0; convertedStream.CopyTo(pProcess.StandardInput.BaseStream); pProcess.StandardInput.BaseStream.Flush(); pProcess.StandardInput.BaseStream.Close(); pProcess.WaitForExit(); // when texconv writes with to the console -nologo is has done/failed conversion string line = pProcess.StandardOutput.ReadToEnd(); if (line.Contains("FAILED")) { convertedStream.Position = 0; TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as dds because texconv failed."); WriteFile(convertedStream, $"{filePath}.dds"); } } } } }