public static void Iterate(List <ulong> files, Dictionary <ulong, Record> map, CASCHandler handler) { foreach (ulong key in files) { if (!map.ContainsKey(key)) { continue; } using (Stream stream = Util.OpenFile(map[key], handler)) { if (stream == null) { continue; } try { OWString str = new OWString(stream); if (str.Value == null || str.Value.Length == 0) { continue; } Console.Out.WriteLine("{0:X12}.{1:X3}: {2}", GUID.LongKey(key), GUID.Type(key), str.Value); } catch { Console.Out.WriteLine("Error with file {0:X12}.{1:X3}", GUID.LongKey(key), GUID.Type(key)); } } } }
private static void ExtractImage(ulong imageKey, string dpath, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, string name = null) { ulong imageDataKey = (imageKey & 0xFFFFFFFFUL) | 0x100000000UL | 0x0320000000000000UL; if (string.IsNullOrWhiteSpace(name)) { name = $"{GUID.LongKey(imageKey):X12}"; } string path = $"{dpath}{name}.dds"; if (!Directory.Exists(Path.GetDirectoryName(path))) { Directory.CreateDirectory(Path.GetDirectoryName(path)); } using (Stream outp = File.Open(path, FileMode.Create, FileAccess.Write)) { if (map.ContainsKey(imageDataKey)) { Texture tex = new Texture(Util.OpenFile(map[imageKey], handler), Util.OpenFile(map[imageDataKey], handler)); tex.Save(outp); } else { TextureLinear tex = new TextureLinear(Util.OpenFile(map[imageKey], handler)); tex.Save(outp); } } if (!quiet) { Console.Out.WriteLine("Wrote image {0}", path); } }
internal static STUInstance[] GetInstances(ulong guid, CASCHandler handler, Dictionary <ulong, Record> map) { Stream str = Util.OpenFile(map[guid], handler); ISTU stu = ISTU.NewInstance(str, uint.MaxValue); return(stu.Instances.ToArray()); }
public static Tuple <string, STUD, IInventorySTUDInstance> GetInventoryName(ulong key, Dictionary <ulong, Record> map, CASCHandler handler) { if (!map.ContainsKey(key)) { return(null); } STUD stud = new STUD(Util.OpenFile(map[key], handler)); if (stud.Instances == null) { return(null); } if (stud.Instances[0] == null) { return(null); } IInventorySTUDInstance instance = stud.Instances[0] as IInventorySTUDInstance; if (instance == null) { return(null); } return(new Tuple <string, STUD, IInventorySTUDInstance>(Util.GetString(instance.Header.name.key, map, handler), stud, instance)); }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { List <ulong> masters = track[0x75]; List <ulong> blank = new List <ulong>(); Dictionary <ulong, ulong> blankdict = new Dictionary <ulong, ulong>(); List <string> extract = new List <string>(); for (int i = 3; i < flags.Positionals.Length; ++i) { extract.Add(flags.Positionals[i].ToLowerInvariant()); } foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } if (extract.Count > 0 && !extract.Contains(heroName.ToLowerInvariant())) { continue; } if (master.Header.itemMaster.key != 0) // AI { InventoryMaster inventory = Extract.OpenInventoryMaster(master, map, handler); if (inventory.ItemGroups.Length > 0 || inventory.DefaultGroups.Length > 0) { continue; } } Console.Out.WriteLine("{0} {1:X}", heroName, GUID.Index(masterKey)); string path = string.Format("{0}{1}{2}{1}{3:X}{1}", flags.Positionals[2], Path.DirectorySeparatorChar, Util.Strip(Util.SanitizePath(heroName)), GUID.LongKey(masterKey)); HashSet <ulong> models = new HashSet <ulong>(); Dictionary <ulong, ulong> animList = new Dictionary <ulong, ulong>(); HashSet <ulong> parsed = new HashSet <ulong>(); Dictionary <ulong, List <ImageLayer> > layers = new Dictionary <ulong, List <ImageLayer> >(); Dictionary <ulong, List <ulong> > sound = new Dictionary <ulong, List <ulong> >(); ExtractLogic.Skin.FindModels(master.Header.binding, blank, models, animList, layers, blankdict, parsed, map, handler, sound); ExtractLogic.Skin.Save(master, path, heroName, $"{GUID.LongKey(masterKey):X}", blankdict, parsed, models, layers, animList, flags, track, map, handler, masterKey, false, quiet, sound, 0); } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { Console.Out.WriteLine("key_name key"); foreach (ulong key in track[0x90]) { if (!map.ContainsKey(key)) { continue; } using (Stream stream = Util.OpenFile(map[key], handler)) { if (stream == null) { continue; } STUD stud = new STUD(stream); if (stud.Instances[0].Name != stud.Manager.GetName(typeof(EncryptionKey))) { continue; } EncryptionKey ek = (EncryptionKey)stud.Instances[0]; Console.Out.WriteLine("{0} {1}", ek.KeyNameText, ek.KeyValueText); } } if (System.Diagnostics.Debugger.IsAttached) { using (Stream output = File.Open("ow_dump.keys", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) { using (TextWriter writer = new StreamWriter(output)) { foreach (KeyValuePair <ulong, byte[]> key in KeyService.keys) { writer.WriteLine("{0:X16} {1}", key.Key, ByteArrayToString(key.Value)); } } } if (handler.Config.KeyRing != null) { using (Stream output = File.Open("ow_keyring.keys", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) { using (TextWriter writer = new StreamWriter(output)) { foreach (KeyValuePair <string, List <string> > pair in handler.Config.KeyRing.KeyValue) { if (pair.Key.StartsWith("key-")) { string reverseKey = pair.Key.Substring(pair.Key.Length - 16); string key = ""; for (int i = 0; i < 8; ++i) { key = reverseKey.Substring(i * 2, 2) + key; } ulong keyL = ulong.Parse(key, System.Globalization.NumberStyles.HexNumber); writer.WriteLine("{0:X16} {1}", keyL, pair.Value[0].ToByteArray()); } } } } } } }
internal static string GetOWString(ulong guid, CASCHandler handler, Dictionary <ulong, Record> map) { if (guid == 0 || !map.ContainsKey(guid)) { return(null); } Stream str = Util.OpenFile(map[guid], handler); OWString ows = new OWString(str); return(ows); }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; List <ulong> masters = track[0x9D]; Dictionary <ulong, ulong> replace = new Dictionary <ulong, ulong>(); foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null || masterStud.Instances[0] == null) { continue; } AnnouncerVoiceList master = (AnnouncerVoiceList)masterStud.Instances[0]; if (master == null) { continue; } string path = string.Format("{0}{1}{2:X}{1}Announcer{1}", output, Path.DirectorySeparatorChar, GUID.Index(masterKey)); HashSet <ulong> done = new HashSet <ulong>(); Console.Out.WriteLine("Dumping voice lines for announcer {0:X}", GUID.Index(masterKey)); Dictionary <ulong, List <ulong> > soundData = new Dictionary <ulong, List <ulong> >(); for (int i = 0; i < master.Entries.Length; ++i) { AnnouncerVoiceList.AnnouncerFXEntry entry = master.Entries[i]; OWRecord[] primary = master.Primary[i]; OWRecord[] secondary = master.Secondary[i]; Sound.FindSoundsEx(entry.master, done, soundData, map, handler, replace, masterKey); foreach (OWRecord record in primary) { Sound.FindSoundsEx(record, done, soundData, map, handler, replace, masterKey); } foreach (OWRecord record in secondary) { Sound.FindSoundsEx(record, done, soundData, map, handler, replace, masterKey); } } DumpVoice.Save(path, soundData, map, handler, quiet); } }
public static InventoryMaster OpenInventoryMaster(HeroMaster master, Dictionary <ulong, Record> map, CASCHandler handler) { if (!map.ContainsKey(master.Header.itemMaster.key)) { return(null); } STUD inventoryStud = new STUD(Util.OpenFile(map[master.Header.itemMaster.key], handler)); InventoryMaster inventory = (InventoryMaster)inventoryStud.Instances[0]; if (inventory == null) { return(null); } return(inventory); }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { List <ulong> ids = new List <ulong>(); foreach (string arg in flags.Positionals.Skip(2)) { ids.Add(ulong.Parse(arg.Split('.')[0], System.Globalization.NumberStyles.HexNumber)); } Console.Out.WriteLine("Scanning for textures..."); foreach (ulong f003 in track[0x3]) { STUD record = new STUD(Util.OpenFile(map[f003], handler), true, STUDManager.Instance, false, true); if (record.Instances == null) { continue; } foreach (ISTUDInstance instance in record.Instances) { if (instance == null) { continue; } if (instance.Name == record.Manager.GetName(typeof(ComplexModelRecord))) { ComplexModelRecord r = (ComplexModelRecord)instance; if (ids.Contains(GUID.LongKey(r.Data.model.key))) { Dictionary <ulong, List <ImageLayer> > layers = new Dictionary <ulong, List <ImageLayer> >(); ExtractLogic.Skin.FindTextures(r.Data.material.key, layers, new Dictionary <ulong, ulong>(), new HashSet <ulong>(), map, handler); Console.Out.WriteLine("Model ID {0:X12}", GUID.LongKey(r.Data.model.key)); foreach (KeyValuePair <ulong, List <ImageLayer> > pair in layers) { Console.Out.WriteLine("Material ID {0:X16}", pair.Key); HashSet <ulong> dedup = new HashSet <ulong>(); foreach (ImageLayer layer in pair.Value) { if (dedup.Add(layer.Key)) { Console.Out.WriteLine("Texture ID {0:X12}", GUID.LongKey(layer.Key)); } } } ids.Remove(GUID.LongKey(r.Data.model.key)); } } } } }
public static void Save(string path, Dictionary <ulong, List <ulong> > sounds, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, Dictionary <ulong, ulong> replace = null, HashSet <ulong> done = null) { if (done == null) { done = new HashSet <ulong>(); } foreach (KeyValuePair <ulong, List <ulong> > pair in sounds) { string rootOutput = $"{path}{GUID.LongKey(pair.Key):X12}{Path.DirectorySeparatorChar}"; foreach (ulong key in pair.Value) { if (!done.Add(key)) { continue; } ulong typ = GUID.Type(key); string ext = "wem"; if (typ == 0x043) { ext = "bnk"; } if (!Directory.Exists(rootOutput)) { Directory.CreateDirectory(rootOutput); } string outputPath = $"{rootOutput}{GUID.LongKey(key):X12}.{ext}"; using (Stream soundStream = Util.OpenFile(map[key], handler)) { if (soundStream == null) { //Console.Out.WriteLine("Failed to dump {0}, probably missing key", ooutputPath); continue; } using (Stream outputStream = File.Open(outputPath, FileMode.Create)) { Util.CopyBytes(soundStream, outputStream, (int)soundStream.Length); if (!quiet) { Console.Out.WriteLine("Wrote file {0}", outputPath); } } } } } }
public static string GetDescription(IInventorySTUDInstance instance, Dictionary <ulong, Record> map, CASCHandler handler) { if (instance.Header.description != 0) { using (Stream descStream = Util.OpenFile(map[instance.Header.description], handler)) { STUD description = new STUD(descStream); if (description.Instances == null) { return(null); } InventoryDescription desc = description.Instances[0] as InventoryDescription; if (desc == null) { return(null); } return(Util.GetString(desc.Header.str, map, handler)); } } return(null); }
public void Save(string path, Record record, CASCHandler handler, string mode, bool quiet) { string output = Path.Combine(path, mode, $"{GUID.Type(record.record.Key):X3}", $"{GUID.LongKey(record.record.Key):X12}.{GUID.Type(record.record.Key):X3}"); using (Stream acp = Util.OpenFile(record, handler)) { if (acp == null) { return; } if (!Directory.Exists(Path.GetDirectoryName(output))) { Directory.CreateDirectory(Path.GetDirectoryName(output)); } using (Stream file = File.Open(output, FileMode.Create)) { Util.CopyBytes(acp, file, (int)acp.Length); if (!quiet) { Console.Out.WriteLine("Wrote file {0}", output); } } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { List <ulong> masters = track[0x75]; foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } if (master.Header.itemMaster.key != 0) // AI { InventoryMaster inventory = Extract.OpenInventoryMaster(master, map, handler); if (inventory.ItemGroups.Length > 0 || inventory.DefaultGroups.Length > 0) { continue; } } Console.Out.WriteLine("{0} {1:X}", heroName, GUID.LongKey(masterKey)); } }
static void Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; List <IOvertool> tools = new List <IOvertool>(); { Assembly asm = typeof(IOvertool).Assembly; Type t = typeof(IOvertool); List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList(); foreach (Type tt in types) { if (tt.IsInterface) { continue; } IOvertool toolinst = (IOvertool)Activator.CreateInstance(tt); if (toolinst.Display) { tools.Add(toolinst); } } } OverToolFlags flags = FlagParser.Parse <OverToolFlags>(() => PrintHelp(tools)); if (flags == null) { return; } Logger.EXIT = !flags.GracefulExit; bool quiet = flags.Quiet; string root = flags.OverwatchDirectory; string opt = flags.Mode; IOvertool tool = null; Dictionary <ushort, List <ulong> > track = new Dictionary <ushort, List <ulong> > { [0x90] = new List <ulong>() // internal requirements }; toolsMap = new Dictionary <string, IOvertool>(); foreach (IOvertool t in tools) { if (t.FullOpt == opt || (opt.Length == 1 && t.Opt != (char)0 && t.Opt == opt[0])) { tool = t; } if (t.Track != null) { foreach (ushort tr in t.Track) { if (!track.ContainsKey(tr)) { track[tr] = new List <ulong>(); } } } if (toolsMap.ContainsKey(t.FullOpt)) { Console.Out.WriteLine("Duplicate opt! {0} conflicts with {1}", t.Title, toolsMap[t.FullOpt].Title); } if (t.FullOpt.Length == 1) { Console.Out.WriteLine("FullOpt should not be length 1 for {0}", t.Title); } toolsMap[t.FullOpt] = t; } if (tool == null || flags.Positionals.Length - 2 < tool.MinimumArgs) { PrintHelp(tools); return; } Dictionary <ulong, Record> map = new Dictionary <ulong, Record>(); Console.Out.WriteLine("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, OWLib.Util.GetVersion()); Console.Out.WriteLine("Initializing CASC..."); Console.Out.WriteLine("Set language to {0}", flags.Language); CDNIndexHandler.Cache.Enabled = flags.UseCache; CDNIndexHandler.Cache.CacheData = flags.CacheData; CDNIndexHandler.Cache.Validate = flags.ValidateCache; CASCConfig config = null; // ngdp:us:pro // http:us:pro:us.patch.battle.net:1119 if (root.ToLowerInvariant().Substring(0, 5) == "ngdp:") { string cdn = root.Substring(5, 4); string[] parts = root.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(root, !flags.SkipKeys, false); } config.Languages = new HashSet <string>(new string[1] { flags.Language }); if (flags.SkipKeys) { Console.Out.WriteLine("Disabling Key auto-detection..."); } Regex versionRegex = new Regex(@"\d+\.\d+"); Match versionMatch = versionRegex.Match(config.BuildName); if (versionMatch.Success) { float version = float.Parse(versionMatch.Value); if (version > 1.13) { Console.ForegroundColor = ConsoleColor.Red; Console.Out.WriteLine("==========\nWARNING: Overtool only works with Overwatch version 1.13 and below! You are using {0}!", config.BuildName); Console.Out.WriteLine("You must use DataTool for Overwatch 1.14 and above!\n=========="); Console.ResetColor(); } } Console.Out.WriteLine("Using Overwatch Version {0}", config.BuildName); CASCHandler handler = CASCHandler.OpenStorage(config); OwRootHandler ow = handler.Root as OwRootHandler; if (ow == null) { Console.Error.WriteLine("Not a valid overwatch installation"); return; } // Fail when trying to extract data from a specified language with 2 or less files found. if (ow.APMFiles.Count() == 0) { Console.Error.WriteLine("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; } } Console.Out.WriteLine("Mapping..."); Util.MapCMF(ow, handler, map, track, flags.Language); if (!flags.SkipKeys) { Console.Out.WriteLine("Adding Encryption Keys..."); foreach (ulong key in track[0x90]) { if (!map.ContainsKey(key)) { continue; } using (Stream stream = Util.OpenFile(map[key], handler)) { if (stream == null) { continue; } ISTU stu = ISTU.NewInstance(stream, UInt32.Parse(config.BuildName.Split('.').Last())); if (!(stu.Instances.FirstOrDefault() is STUEncryptionKey)) { continue; } STUEncryptionKey ek = stu.Instances.FirstOrDefault() as STUEncryptionKey; if (ek != null && !KeyService.keys.ContainsKey(ek.LongRevKey)) { KeyService.keys.Add(ek.LongRevKey, ek.KeyValue); Console.Out.WriteLine("Added Encryption Key {0}, Value: {1}", ek.KeyNameProper, ek.Key); } } } } Console.Out.WriteLine("Tooling..."); tool.Parse(track, map, handler, quiet, flags); if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Break(); } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { List <ulong> masters = track[0x75]; foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } string goodhero = heroName; foreach (var c in Path.GetInvalidFileNameChars()) { goodhero = goodhero.Replace(c, '_'); } if (master.Header.itemMaster.key == 0) // AI { continue; } bool ex = System.Diagnostics.Debugger.IsAttached || flags.Expert; if (ex) { Console.Out.WriteLine("Cosmetics for {0} ({1:X16})", heroName, GUID.LongKey(masterKey)); } else { Console.Out.WriteLine("Cosmetics for {0}", heroName); } if (!map.ContainsKey(master.Header.itemMaster.key)) { Console.Out.WriteLine("Error loading inventory master file..."); continue; } STUD inventoryStud = new STUD(Util.OpenFile(map[master.Header.itemMaster.key], handler)); #if OUTPUT_STUDINVENTORYMASTER Stream studStream = Util.OpenFile(map[master.Header.itemMaster.key], handler); string outFilename = string.Format("./STUDs/ListInventoryMaster/{0}.stud", goodhero); string putPathname = outFilename.Substring(0, outFilename.LastIndexOf('/')); Directory.CreateDirectory(putPathname); Stream OutWriter = File.Create(outFilename); studStream.CopyTo(OutWriter); OutWriter.Close(); studStream.Close(); #endif InventoryMaster inventory = (InventoryMaster)inventoryStud.Instances[0]; if (inventory == null) { Console.Out.WriteLine("Error loading inventory master file..."); continue; } Console.Out.WriteLine("\tACHIEVEMENT ({0} items)", inventory.Achievables.Length); foreach (OWRecord record in inventory.Achievables) { GetInventoryName(record.key, ex, map, handler, goodhero); } for (int i = 0; i < inventory.DefaultGroups.Length; ++i) { if (inventory.Defaults[i].Length == 0) { continue; } OWRecord[] records = inventory.Defaults[i]; Console.Out.WriteLine("\tSTANDARD_{0} ({1} items)", ItemEvents.GetInstance().GetEvent(inventory.DefaultGroups[i].@event), records.Length); foreach (OWRecord record in records) { GetInventoryName(record.key, ex, map, handler, goodhero); } } for (int i = 0; i < inventory.ItemGroups.Length; ++i) { if (inventory.Items[i].Length == 0) { continue; } OWRecord[] records = inventory.Items[i]; Console.Out.WriteLine("\t{0} ({1} items)", ItemEvents.GetInstance().GetEvent(inventory.ItemGroups[i].@event), records.Length); foreach (OWRecord record in records) { GetInventoryName(record.key, ex, map, handler, goodhero); } } Console.Out.WriteLine(""); } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; List <string> maps = flags.Positionals.Skip(3).ToList(); bool skipCmodel = !flags.ExportCollision; for (int i = 0; i < maps.Count; ++i) { maps[i] = maps[i].ToUpperInvariant().TrimStart('0'); } bool mapWildcard = maps.Count == 0; if (maps.Count > 0 && maps.Contains("*")) { mapWildcard = true; } char animEncoding = flags.AnimFormat; if (flags.Raw) { animEncoding = '+'; } bool suppressAnimations = flags.SkipAnimations; if (animEncoding == '+' && !flags.RawAnimation) { suppressAnimations = true; } char modelEncoding = flags.ModelFormat; if (flags.Raw) { modelEncoding = '+'; } bool suppressModels = flags.SkipModels; if (modelEncoding == '+' && !flags.RawModel) { suppressModels = true; } IDataWriter animWriter = null; if (animEncoding != 0 && animEncoding != '+') { Assembly asm = typeof(IDataWriter).Assembly; Type t = typeof(IDataWriter); List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList(); foreach (Type tt in types) { if (animWriter != null) { break; } if (tt.IsInterface) { continue; } IDataWriter tmp = (IDataWriter)Activator.CreateInstance(tt); for (int i = 0; i < tmp.Identifier.Length; ++i) { if (tmp.Identifier[i] == animEncoding) { animWriter = tmp; break; } } } } IDataWriter modelWriter = null; if (modelEncoding != 0 && modelEncoding != '+') { Assembly asm = typeof(IDataWriter).Assembly; Type t = typeof(IDataWriter); List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList(); foreach (Type tt in types) { if (modelWriter != null) { break; } if (tt.IsInterface) { continue; } IDataWriter tmp = (IDataWriter)Activator.CreateInstance(tt); for (int i = 0; i < tmp.Identifier.Length; ++i) { if (tmp.Identifier[i] == modelEncoding) { modelWriter = tmp; break; } } } } List <ulong> masters = track[0x9F]; List <byte> LODs = new List <byte>(new byte[5] { 0, 1, 128, 254, 255 }); Dictionary <ulong, ulong> replace = new Dictionary <ulong, ulong>(); foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null) { continue; } MapMaster master = (MapMaster)masterStud.Instances[0]; if (master == null) { continue; } string name = Util.GetString(master.Header.name.key, map, handler); if (string.IsNullOrWhiteSpace(name)) { name = $"Unknown{GUID.Index(master.Header.data.key):X}"; } if (!mapWildcard && !(maps.Contains(name.ToUpperInvariant()) || maps.Contains($"{GUID.Index(masterKey):X}"))) { continue; } string outputPath = string.Format("{0}{1}{2}{1}{3:X}{1}", output, Path.DirectorySeparatorChar, Util.SanitizePath(name), GUID.Index(master.Header.data.key)); if (!map.ContainsKey(master.Header.data.key)) { continue; } HashSet <ulong> parsed = new HashSet <ulong>(); Dictionary <ulong, ulong> animList = new Dictionary <ulong, ulong>(); Dictionary <ulong, List <ulong> > soundData = new Dictionary <ulong, List <ulong> >(); if (!map.ContainsKey(master.DataKey(1))) { continue; } if (!map.ContainsKey(master.DataKey(2))) { continue; } if (!map.ContainsKey(master.DataKey(8))) { continue; } if (!map.ContainsKey(master.DataKey(0xB))) { continue; } if (!map.ContainsKey(master.DataKey(0x11))) { continue; } if (!map.ContainsKey(master.DataKey(0x10))) { continue; } using (Stream mapStream = Util.OpenFile(map[master.DataKey(1)], handler)) { Console.Out.WriteLine("Extracting map {0} with ID {1:X8}", name, GUID.Index(master.Header.data.key)); Map mapData = new Map(mapStream); IDataWriter owmap = new OWMAPWriter(); Dictionary <ulong, List <string> >[] used = null; if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } HashSet <ulong> soundDone = new HashSet <ulong>(); Sound.FindSoundsEx(master.Header.audio.key, soundDone, soundData, map, handler, replace, master.Header.data.key); using (Stream map2Stream = Util.OpenFile(map[master.DataKey(2)], handler)) { if (map2Stream != null) { Map map2Data = new Map(map2Stream); using (Stream map8Stream = Util.OpenFile(map[master.DataKey(8)], handler)) { if (map8Stream != null) { Map map8Data = new Map(map8Stream); using (Stream mapBStream = Util.OpenFile(map[master.DataKey(0xB)], handler)) { if (mapBStream != null) { Map mapBData = new Map(mapBStream, true); using (Stream map11Stream = Util.OpenFile(map[master.DataKey(0x11)], handler)) { if (map11Stream != null) { Map11 map11 = new Map11(map11Stream); Sound.FindSoundsSTUD(map11.main, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11)); Sound.FindSoundsSTUD(map11.secondary, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11)); } } mapBStream.Position = (long)(Math.Ceiling((float)mapBStream.Position / 16.0f) * 16); // Future proofing for (int i = 0; i < mapBData.STUDs.Count; ++i) { STUD stud = mapBData.STUDs[i]; Sound.FindSoundsSTUD(stud, soundDone, soundData, map, handler, replace, master.DataKey(0xB), master.DataKey(0xB)); } for (int i = 0; i < mapBData.Records.Length; ++i) { if (mapBData.Records[i] != null && mapBData.Records[i].GetType() != typeof(MapEntity)) { continue; } MapEntity mapprop = (MapEntity)mapBData.Records[i]; if (!map.ContainsKey(mapprop.Header.Entity)) { continue; } Sound.FindSoundsEx(mapprop.Header.Entity, soundDone, soundData, map, handler, replace, master.DataKey(0xB)); HashSet <ulong> bindingModels = new HashSet <ulong>(); Dictionary <ulong, List <ImageLayer> > bindingTextures = new Dictionary <ulong, List <ImageLayer> >(); using (Stream bindingFile = Util.OpenFile(map[mapprop.Header.Entity], handler)) { STUD binding = new STUD(bindingFile, true, STUDManager.Instance, false, true); foreach (ISTUDInstance instance in binding.Instances) { if (instance == null) { continue; } if (instance.Name != binding.Manager.GetName(typeof(ComplexModelRecord))) { continue; } ComplexModelRecord cmr = (ComplexModelRecord)instance; mapprop.ModelLook = cmr.Data.material.key; mapprop.Model = cmr.Data.model.key; Skin.FindAnimations(cmr.Data.animationList.key, soundData, animList, replace, parsed, map, handler, bindingModels, bindingTextures, mapprop.Model); Skin.FindAnimations(cmr.Data.secondaryAnimationList.key, soundData, animList, replace, parsed, map, handler, bindingModels, bindingTextures, mapprop.Model); break; } } mapBData.Records[i] = mapprop; } using (Stream mapLStream = Util.OpenFile(map[master.DataKey(9)], handler)) { Map mapLData = new Map(mapLStream); using (Stream outputStream = File.Open($"{outputPath}{Util.SanitizePath(name)}{owmap.Format}", FileMode.Create, FileAccess.Write)) { used = owmap.Write(outputStream, mapData, map2Data, map8Data, mapBData, mapLData, name, modelWriter); } } } } } } } } IDataWriter owmat = new OWMATWriter(); using (Stream map10Stream = Util.OpenFile(map[master.DataKey(0x10)], handler)) { Map10 physics = new Map10(map10Stream); using (Stream outputStream = File.Open($"{outputPath}physics{modelWriter.Format}", FileMode.Create, FileAccess.Write)) { modelWriter.Write(physics, outputStream, new object[0]); } } if (used != null) { Dictionary <ulong, List <string> > models = used[0]; Dictionary <ulong, List <string> > materials = used[1]; Dictionary <ulong, Dictionary <ulong, List <ImageLayer> > > cache = new Dictionary <ulong, Dictionary <ulong, List <ImageLayer> > >(); if (!suppressModels) { foreach (KeyValuePair <ulong, List <string> > modelpair in models) { if (!map.ContainsKey(modelpair.Key)) { continue; } if (!parsed.Add(modelpair.Key)) { continue; } HashSet <string> extracted = new HashSet <string>(); using (Stream modelStream = Util.OpenFile(map[modelpair.Key], handler)) { Chunked mdl = new Chunked(modelStream, true); modelStream.Position = 0; if (modelEncoding != '+' && modelWriter != null) { foreach (string modelOutput in modelpair.Value) { if (!extracted.Add(modelOutput)) { continue; } using (Stream outputStream = File.Open($"{outputPath}{modelOutput}", FileMode.Create, FileAccess.Write)) { if (modelWriter.Write(mdl, outputStream, LODs, new Dictionary <ulong, List <ImageLayer> >(), new object[5] { null, null, null, null, skipCmodel })) { if (!quiet) { Console.Out.WriteLine("Wrote model {0}", modelOutput); } } else { if (!quiet) { Console.Out.WriteLine("Failed to write model"); } } } } } if (flags.RawModel) { using (Stream outputStream = File.Open($"{outputPath}{GUID.LongKey(modelpair.Key):X12}.{GUID.Type(modelpair.Key):X3}", FileMode.Create, FileAccess.Write)) { if (modelWriter.Write(mdl, outputStream, LODs, new Dictionary <ulong, List <ImageLayer> >(), new object[5] { null, null, null, null, skipCmodel })) { if (!quiet) { Console.Out.WriteLine("Wrote raw model {0:X12}.{1:X3}", GUID.LongKey(modelpair.Key), GUID.Type(modelpair.Key)); } } else { if (!quiet) { Console.Out.WriteLine("Failed to write model"); } } } } } } } if (!suppressAnimations) { foreach (KeyValuePair <ulong, ulong> kv in animList) { ulong parent = kv.Value; ulong key = kv.Key; Stream animStream = Util.OpenFile(map[key], handler); if (animStream == null) { continue; } Animation anim = new Animation(animStream); animStream.Position = 0; string outpath = string.Format("{0}Animations{1}{2:X12}{1}{5}{1}{3:X12}.{4:X3}", outputPath, Path.DirectorySeparatorChar, GUID.Index(parent), GUID.LongKey(key), GUID.Type(key), anim.Header.priority); if (!Directory.Exists(Path.GetDirectoryName(outpath))) { Directory.CreateDirectory(Path.GetDirectoryName(outpath)); } if (flags.RawAnimation) { using (Stream outp = File.Open(outpath, FileMode.Create, FileAccess.Write)) { animStream.CopyTo(outp); if (!quiet) { Console.Out.WriteLine("Wrote raw animation {0}", outpath); } } } if (animEncoding != '+' && animWriter != null) { outpath = string.Format("{0}Animations{1}{2:X12}{1}{5}{1}{3:X12}.{4}", outputPath, Path.DirectorySeparatorChar, GUID.Index(parent), GUID.LongKey(key), animWriter.Format, anim.Header.priority); using (Stream outp = File.Open(outpath, FileMode.Create, FileAccess.Write)) { animWriter.Write(anim, outp); if (!quiet) { Console.Out.WriteLine("Wrote animation {0}", outpath); } } } } } if (!flags.SkipSound) { Console.Out.WriteLine("Dumping sounds..."); string soundPath = $"{outputPath}Sounds{Path.DirectorySeparatorChar}"; if (!Directory.Exists(soundPath)) { Directory.CreateDirectory(soundPath); } DumpVoice.Save(soundPath, soundData, map, handler, quiet); } if (!flags.SkipTextures) { foreach (KeyValuePair <ulong, List <string> > matpair in materials) { Dictionary <ulong, List <ImageLayer> > tmp = new Dictionary <ulong, List <ImageLayer> >(); if (cache.ContainsKey(matpair.Key)) { tmp = cache[matpair.Key]; } else { Skin.FindTextures(matpair.Key, tmp, new Dictionary <ulong, ulong>(), new HashSet <ulong>(), map, handler); cache.Add(matpair.Key, tmp); } Dictionary <string, TextureType> types = new Dictionary <string, TextureType>(); foreach (KeyValuePair <ulong, List <ImageLayer> > kv in tmp) { ulong materialId = kv.Key; List <ImageLayer> sublayers = kv.Value; HashSet <ulong> materialParsed = new HashSet <ulong>(); foreach (ImageLayer layer in sublayers) { if (!materialParsed.Add(layer.Key)) { continue; } KeyValuePair <string, TextureType> pair = Skin.SaveTexture(layer.Key, materialId, map, handler, outputPath, quiet, $"Textures/{GUID.Index(matpair.Key):X8}"); if (pair.Key == null) { continue; } types.Add(pair.Key, pair.Value); } } foreach (string matOutput in matpair.Value) { if (File.Exists($"{outputPath}{matOutput}")) { continue; } using (Stream outputStream = File.Open($"{outputPath}{matOutput}", FileMode.Create, FileAccess.Write)) { if (owmat.Write(null, outputStream, null, tmp, new object[1] { types })) { if (!quiet) { Console.Out.WriteLine("Wrote material {0}", matOutput); } } else { if (!quiet) { Console.Out.WriteLine("Failed to write material"); } } } } } } } } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { foreach (ulong key in track[0x54]) { if (!map.ContainsKey(key)) { continue; } Dictionary <OWRecord, string> items = new Dictionary <OWRecord, string>(); using (Stream input = Util.OpenFile(map[key], handler)) { if (input == null) { continue; } STUD stud = new STUD(input); if (stud.Instances == null || stud.Instances[0] == null) { continue; } GlobalInventoryMaster master = stud.Instances[0] as GlobalInventoryMaster; if (master == null) { continue; } Console.Out.WriteLine("\tACHIEVEMENT"); foreach (OWRecord record in master.StandardItems) { ListInventory.GetInventoryName(record.key, false, map, handler, "General"); } Dictionary <string, List <OWRecord> > aggreg = new Dictionary <string, List <OWRecord> >(); for (int i = 0; i < master.Generic.Length; ++i) { if (master.GenericItems[i].Length == 0) { continue; } string s = $"\tSTANDARD_{ItemEvents.GetInstance().GetEvent(master.Generic[i].@event)}"; if (!aggreg.ContainsKey(s)) { aggreg[s] = new List <OWRecord>(); } for (int j = 0; j < master.GenericItems[i].Length; ++j) { aggreg[s].Add(master.GenericItems[i][j]); } } foreach (KeyValuePair <string, List <OWRecord> > pair in aggreg) { Console.Out.WriteLine(pair.Key); foreach (OWRecord record in pair.Value) { ListInventory.GetInventoryName(record, false, map, handler, "General"); } } aggreg.Clear(); for (int i = 0; i < master.Categories.Length; ++i) { if (master.CategoryItems[i].Length == 0) { continue; } Console.Out.WriteLine($"\t{ItemEvents.GetInstance().GetEvent(master.Categories[i].@event)}"); for (int j = 0; j < master.CategoryItems[i].Length; ++j) { ListInventory.GetInventoryName(master.CategoryItems[i][j], false, map, handler, "General"); } } for (int i = 0; i < master.ExclusiveOffsets.Length; ++i) { if (master.LootboxExclusive[i].Length == 0) { continue; } Console.Out.WriteLine($"\tLOOTBOX_EXCLUSIVE_{ItemEvents.GetInstance().GetEvent((ulong)i)}"); for (int j = 0; j < master.LootboxExclusive[i].Length; ++j) { ListInventory.GetInventoryName(master.LootboxExclusive[i][j].item, false, map, handler, "General"); } } } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; foreach (ulong key in track[0x54]) { if (!map.ContainsKey(key)) { continue; } Dictionary <OWRecord, string> items = new Dictionary <OWRecord, string>(); using (Stream input = Util.OpenFile(map[key], handler)) { if (input == null) { continue; } STUD stud = new STUD(input); if (stud.Instances == null || stud.Instances[0] == null) { continue; } GlobalInventoryMaster master = stud.Instances[0] as GlobalInventoryMaster; if (master == null) { continue; } foreach (OWRecord record in master.StandardItems) { items[record] = "ACHIEVEMENT"; } for (int i = 0; i < master.Generic.Length; ++i) { string name = $"STANDARD_{ItemEvents.GetInstance().GetEvent(master.Generic[i].@event)}"; for (int j = 0; j < master.GenericItems[i].Length; ++j) { items[master.GenericItems[i][j]] = name; } } for (int i = 0; i < master.Categories.Length; ++i) { string name = ItemEvents.GetInstance().GetEvent(master.Categories[i].@event); for (int j = 0; j < master.CategoryItems[i].Length; ++j) { items[master.CategoryItems[i][j]] = name; } } for (int i = 0; i < master.ExclusiveOffsets.Length; ++i) { string name = $"LOOTBOX_EXCLUSIVE_{i:X}"; for (int j = 0; j < master.LootboxExclusive[i].Length; ++j) { items[master.LootboxExclusive[i][j].item] = name; } } } foreach (KeyValuePair <OWRecord, string> recordname in items) { OWRecord record = recordname.Key; string itemGroup = recordname.Value; if (!map.ContainsKey(record.key)) { continue; } STUD stud = new STUD(Util.OpenFile(map[record.key], handler)); if (stud.Instances == null) { continue; } IInventorySTUDInstance instance = (IInventorySTUDInstance)stud.Instances[0]; string name = Util.GetString(instance.Header.name.key, map, handler); if (name == null) { name = $"{GUID.LongKey(key):X12}"; } switch (instance.Name) { case "Spray": Console.Out.WriteLine("Extracting spray {0}...", name); ExtractLogic.Spray.Extract(stud, output, "Generic", name, itemGroup, track, map, handler, quiet, flags); break; case "Icon": Console.Out.WriteLine("Extracting icon {0}...", name); ExtractLogic.Icon.Extract(stud, output, "Generic", name, itemGroup, track, map, handler, quiet, flags); break; case "Portrait": PortraitItem portrait = instance as PortraitItem; ExtractLogic.Portrait.Extract(stud, output, "Generic", $"Tier {portrait.Data.tier}", itemGroup, track, map, handler, quiet, flags); break; default: continue; } } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { List <ulong> masters = track[0x9F]; foreach (ulong key in masters) { if (!map.ContainsKey(key)) { continue; } ISTU stu = ISTU.NewInstance(Util.OpenFile(map[key], handler), uint.MaxValue); if (stu.Instances == null) { continue; } STUMap mapSTU = stu.Instances.First() as STUMap; if (map == null) { continue; } // Console.Out.WriteLine($"{key}"); // // if (mapSTU.StringDescriptionA != null) { // Console.Out.WriteLine($"\tStringDescriptionA: {Util.GetString(mapSTU.StringDescriptionA, map, handler)}"); // } // if (mapSTU.StringStateA != null) { // Console.Out.WriteLine($"\tStringStateA: {Util.GetString(mapSTU.StringStateA, map, handler)}"); // } // if (mapSTU.StringName != null) { // Console.Out.WriteLine($"\tStringName: {Util.GetString(mapSTU.StringName, map, handler)}"); // } // if (mapSTU.StringStateB != null) { // Console.Out.WriteLine($"StringStateB: {Util.GetString(mapSTU.StringStateB, map, handler)}"); // } // if (mapSTU.StringDescriptionB != null) { // Console.Out.WriteLine($"\tStringDescriptionB: {Util.GetString(mapSTU.StringDescriptionB, map, handler)}"); // } // if (mapSTU.StringSubline != null) { // Console.Out.WriteLine($"\tStringSubline: {Util.GetString(mapSTU.StringSubline, map, handler)}"); // } // if (mapSTU.StringNameB != null) { // Console.Out.WriteLine($"\tStringNameB: {Util.GetString(mapSTU.StringNameB, map, handler)}"); // } //string name = Util.GetString(map.Header.name.key, map, handler); //if (string.IsNullOrWhiteSpace(name)) { // name = $"Unknown{GUID.Index(masterKey):X}"; //} //Console.Out.WriteLine(name); //Console.Out.WriteLine("\tID: {0:X8}", GUID.Index(masterKey)); //string subline = Util.GetString(map.Header.subline.key, map, handler); //if (subline == null) { // subline = ""; //} //if (map.Header.subline.key != map.Header.subline2.key && map.Header.subline2.key != 0) { // subline += " " + Util.GetString(map.Header.subline2.key, map, handler); //} //subline = subline.Trim(); //if (subline.Length > 0) { // Console.Out.WriteLine("\tSubline: {0}", subline); //} //TryString("State", Util.GetString(map.Header.stateA.key, map, handler)); //TryString("State", Util.GetString(map.Header.stateB.key, map, handler)); //string description = Util.GetString(map.Header.description1.key, map, handler); //if (description == null) { // description = ""; //} //if (map.Header.description1.key != map.Header.description2.key && map.Header.description2.key != 0) { // description += " " + Util.GetString(map.Header.description2.key, map, handler); //} //description = description.Trim(); //if (description.Length > 0) { // Console.Out.WriteLine("\tDescription: {0}", description); //} } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; List <string> heroes = new List <string>(); if (flags.Positionals.Length > 3) { heroes.AddRange(flags.Positionals[3].ToLowerInvariant().Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries)); } bool heroAllWildcard = heroes.Count == 0 || heroes.Contains("*"); List <ulong> masters = track[0x75]; foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null || masterStud.Instances[0] == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } if (!heroes.Contains(heroName.ToLowerInvariant())) { if (!heroAllWildcard) { continue; } } if (master.Header.itemMaster.key != 0) // AI { InventoryMaster inventory = Extract.OpenInventoryMaster(master, map, handler); if (inventory.ItemGroups.Length > 0 || inventory.DefaultGroups.Length > 0) { continue; } } Console.Out.WriteLine("Dumping voice bites for NPC {0}", heroName); Dictionary <ulong, List <ulong> > soundData = ExtractLogic.Sound.FindSounds(master, track, map, handler, null, masterKey); string path = string.Format("{0}{1}{2}{1}{3}{1}", output, Path.DirectorySeparatorChar, Util.Strip(Util.SanitizePath(heroName)), "Sound Dump"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } Save(path, soundData, map, handler, quiet); } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; HashSet <string> heroes = new HashSet <string>(); HashSet <string> heroBlank = new HashSet <string>(); Dictionary <string, HashSet <string> > heroSkin = new Dictionary <string, HashSet <string> >(); bool heroAllWildcard = false; if (flags.Positionals.Length > 3 && flags.Positionals[1] != "*") { foreach (string name in flags.Positionals[3].ToLowerInvariant().Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries)) { string[] data = name.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); string realname = data[0]; heroes.Add(realname); data = data.Skip(1).ToArray(); if (data.Length == 0) { heroBlank.Add(realname); continue; } heroSkin[realname] = new HashSet <string>(); foreach (string skin in data) { heroSkin[realname].Add(skin); } } } else { heroAllWildcard = true; } List <ulong> masters = track[0x75]; foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } if (master.Header.itemMaster.key == 0) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } if (heroAllWildcard) { heroes.Add(heroName.ToLowerInvariant()); heroBlank.Add(heroName.ToLowerInvariant()); } if (!heroes.Contains(heroName.ToLowerInvariant())) { continue; } InventoryMaster inventory = OpenInventoryMaster(master, map, handler); if (inventory == null) { continue; } Dictionary <OWRecord, string> items = new Dictionary <OWRecord, string>(); foreach (OWRecord record in inventory.Achievables) { items[record] = "ACHIEVEMENT"; } for (int i = 0; i < inventory.DefaultGroups.Length; ++i) { string name = $"STANDARD_{ItemEvents.GetInstance().GetEvent(inventory.DefaultGroups[i].@event)}"; for (int j = 0; j < inventory.Defaults[i].Length; ++j) { items[inventory.Defaults[i][j]] = name; } } for (int i = 0; i < inventory.ItemGroups.Length; ++i) { string name = ItemEvents.GetInstance().GetEvent(inventory.ItemGroups[i].@event); for (int j = 0; j < inventory.Items[i].Length; ++j) { items[inventory.Items[i][j]] = name; } } Dictionary <string, WeaponSkinItem> weaponskins = new Dictionary <string, WeaponSkinItem>(); Console.Out.WriteLine("Finding weapon skins for {0}", heroName); foreach (KeyValuePair <OWRecord, string> recordname in items) { OWRecord record = recordname.Key; string itemGroup = recordname.Value; if (!map.ContainsKey(record.key)) { continue; } STUD stud = new STUD(Util.OpenFile(map[record.key], handler)); if (stud.Instances == null) { continue; } IInventorySTUDInstance instance = (IInventorySTUDInstance)stud.Instances[0]; WeaponSkinItem weapon = instance as WeaponSkinItem; if (weapon == null) { continue; } if (weapon.Data.index == 0) { continue; } string name = Util.GetString(instance.Header.name.key, map, handler); if (name == null) { name = $"Untitled-{GUID.LongKey(instance.Header.name.key):X12}"; continue; } weaponskins[name] = weapon; Console.Out.WriteLine("Found data for weapon skin {0}", name); } foreach (KeyValuePair <OWRecord, string> recordname in items) { OWRecord record = recordname.Key; string itemGroup = recordname.Value; if (!map.ContainsKey(record.key)) { continue; } STUD stud = new STUD(Util.OpenFile(map[record.key], handler)); if (stud.Instances == null) { continue; } IInventorySTUDInstance instance = (IInventorySTUDInstance)stud.Instances[0]; SkinItem skin = instance as SkinItem; if (skin == null) { continue; } string name = Util.GetString(instance.Header.name.key, map, handler); if (name == null) { name = $"Untitled-{GUID.LongKey(instance.Header.name.key):X12}"; continue; } if (heroBlank.Contains(heroName.ToLowerInvariant()) || heroSkin[heroName.ToLowerInvariant()].Contains(name.ToLowerInvariant())) { Console.Out.WriteLine("Saving textures for skin {0}", name); foreach (KeyValuePair <string, WeaponSkinItem> pair in weaponskins) { string output_real = string.Format("{0}{1}{4}{1}Weapon Skin{1}{2}{1}{3}{1}", output, System.IO.Path.DirectorySeparatorChar, Util.SanitizePath(pair.Key), Util.SanitizePath(name), Util.SanitizePath(heroName)); Dictionary <ulong, ulong> replace = new Dictionary <ulong, ulong>(); ExtractLogic.Skin.FindReplacements(skin.Data.skin.key, (int)pair.Value.Data.index, replace, new HashSet <ulong>(), map, handler, master, skin, true); Dictionary <ulong, ulong> replace_blank = new Dictionary <ulong, ulong>(); ExtractLogic.Skin.FindReplacements(skin.Data.skin.key, -1, replace_blank, new HashSet <ulong>(), map, handler, master, skin, false); if (replace.Values.Count == 0) { continue; } Dictionary <ulong, List <ImageLayer> > layers = new Dictionary <ulong, List <ImageLayer> >(); Dictionary <ulong, List <ImageLayer> > layers_orig = new Dictionary <ulong, List <ImageLayer> >(); foreach (KeyValuePair <ulong, ulong> texture_pair in replace) { ushort type = GUID.Type(texture_pair.Key); switch (type) { case 0x1A: ExtractLogic.Skin.FindTextures(texture_pair.Value, layers, replace, new HashSet <ulong>(), map, handler); if (replace_blank.ContainsKey(texture_pair.Key)) { ExtractLogic.Skin.FindTextures(replace_blank[texture_pair.Key], layers_orig, replace_blank, new HashSet <ulong>(), map, handler); } else { ExtractLogic.Skin.FindTextures(texture_pair.Key, layers_orig, replace_blank, new HashSet <ulong>(), map, handler); } break; } } Dictionary <ulong, HashSet <ulong> > origTextures = new Dictionary <ulong, HashSet <ulong> >(); foreach (KeyValuePair <ulong, List <ImageLayer> > kv in layers_orig) { ulong materialId = kv.Key; List <ImageLayer> sublayers = kv.Value; HashSet <ulong> materialParsed = new HashSet <ulong>(); if (!origTextures.ContainsKey(materialId)) { origTextures[materialId] = new HashSet <ulong>(); } foreach (ImageLayer layer in sublayers) { origTextures[materialId].Add(layer.key); } } foreach (KeyValuePair <ulong, List <ImageLayer> > kv in layers) { ulong materialId = kv.Key; List <ImageLayer> sublayers = kv.Value; HashSet <ulong> materialParsed = new HashSet <ulong>(); foreach (ImageLayer layer in sublayers) { if (!materialParsed.Add(layer.key)) { continue; } if (origTextures.ContainsKey(materialId) && origTextures[materialId].Contains(layer.key)) { continue; } ExtractLogic.Skin.SaveTexture(layer.key, materialId, map, handler, output_real, quiet, ""); } } } } } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; string[] validCommands = new string[] { "skin", "spray", "icon", "victory pose", "emote", "heroic intro" }; bool typeWildcard = true; List <string> types = new List <string>(); if (flags.Positionals.Length > 3) { types.AddRange(flags.Positionals[3].ToLowerInvariant().Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries)); typeWildcard = types.Contains("*"); types = types.FindAll((string it) => validCommands.Contains(it)).ToList(); } if (!typeWildcard && types.Count == 0) { string cmdlist = ""; for (int i = 0; i < validCommands.Length; i++) { if (i != 0) { cmdlist += ", "; if (i == validCommands.Length - 1) { cmdlist += "or "; } } cmdlist += validCommands[i].ToString().ToLower(); } Console.Out.WriteLine("The output type was not a valid option. ({0})", cmdlist); return; } Dictionary <string, List <string> > heroTypes = new Dictionary <string, List <string> >(); Dictionary <string, bool> heroWildcard = new Dictionary <string, bool>(); Dictionary <string, Dictionary <string, List <ulong> > > heroIgnore = new Dictionary <string, Dictionary <string, List <ulong> > >(); bool heroAllWildcard = false; if (flags.Positionals.Length > 4 && flags.Positionals[4] != "*") { foreach (string pair in flags.Positionals[4].ToLowerInvariant().Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries)) { List <string> data = new List <string>(pair.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)); string name = data[0]; data.RemoveAt(0); if (!heroTypes.ContainsKey(name)) { heroTypes[name] = new List <string>(); heroIgnore[name] = new Dictionary <string, List <ulong> >(); heroWildcard[name] = false; } if (data.Count > 0) { foreach (string d in data) { List <string> subdata = new List <string>(d.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)); string subn = subdata[0]; subdata.RemoveAt(0); heroTypes[name].Add(subn); heroIgnore[name][subn] = new List <ulong>(); if (subdata.Count > 0) { foreach (string sd in subdata) { try { heroIgnore[name][subn].Add(ulong.Parse(sd, System.Globalization.NumberStyles.HexNumber)); } catch { } } } } } if (data.Count == 0 || data.Contains("*")) { heroWildcard[name] = true; } } } else { heroAllWildcard = true; } int replacementIndex = flags.WeaponSkinIndex; List <ulong> masters = track[0x75]; foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } if (master.Header.itemMaster.key == 0) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } if (heroAllWildcard) { if (!heroTypes.ContainsKey(heroName.ToLowerInvariant())) { heroTypes.Add(heroName.ToLowerInvariant(), new List <string>()); } if (!heroWildcard.ContainsKey(heroName.ToLowerInvariant())) { heroWildcard.Add(heroName.ToLowerInvariant(), true); } } if (!heroTypes.ContainsKey(heroName.ToLowerInvariant())) { continue; } InventoryMaster inventory = OpenInventoryMaster(master, map, handler); if (inventory == null) { continue; } Dictionary <OWRecord, string> items = new Dictionary <OWRecord, string>(); foreach (OWRecord record in inventory.Achievables) { items[record] = "ACHIEVEMENT"; } for (int i = 0; i < inventory.DefaultGroups.Length; ++i) { string name = $"STANDARD_{ItemEvents.GetInstance().GetEvent(inventory.DefaultGroups[i].@event)}"; for (int j = 0; j < inventory.Defaults[i].Length; ++j) { items[inventory.Defaults[i][j]] = name; } } for (int i = 0; i < inventory.ItemGroups.Length; ++i) { string name = ItemEvents.GetInstance().GetEvent(inventory.ItemGroups[i].@event); for (int j = 0; j < inventory.Items[i].Length; ++j) { items[inventory.Items[i][j]] = name; } } foreach (KeyValuePair <OWRecord, string> recordname in items) { OWRecord record = recordname.Key; string itemGroup = recordname.Value; if (!map.ContainsKey(record.key)) { continue; } STUD stud = new STUD(Util.OpenFile(map[record.key], handler)); if (stud.Instances == null) { continue; } IInventorySTUDInstance instance = (IInventorySTUDInstance)stud.Instances[0]; if (!typeWildcard && !types.Contains(instance.Name.ToLowerInvariant())) { continue; } string name = Util.GetString(instance.Header.name.key, map, handler); if (name == null) { name = $"Untitled-{GUID.LongKey(instance.Header.name.key):X12}"; continue; } if (!heroWildcard[heroName.ToLowerInvariant()] && !heroTypes[heroName.ToLowerInvariant()].Contains(name.ToLowerInvariant())) { continue; } switch (instance.Name) { case "Spray": Console.Out.WriteLine("Extracting spray {0} for {1}...", name, heroName); ExtractLogic.Spray.Extract(stud, output, heroName, name, itemGroup, track, map, handler, quiet, flags); break; case "Skin": List <ulong> ignoreList = new List <ulong>(); try { ignoreList = heroIgnore[heroName.ToLowerInvariant()][name.ToLowerInvariant()]; } catch { } Console.Out.WriteLine("Extracting {0} models and textures for {1}", name, heroName); ExtractLogic.Skin.Extract(master, stud, output, heroName, name, itemGroup, ignoreList, track, map, handler, quiet, flags, masterKey, replacementIndex); break; case "Icon": Console.Out.WriteLine("Extracting icon {0} for {1}...", name, heroName); ExtractLogic.Icon.Extract(stud, output, heroName, name, itemGroup, track, map, handler, quiet, flags); break; case "Emote": case "Victory Pose": case "Heroic Intro": Console.Out.WriteLine("Extracting {2} {0} for {1}...", name, heroName, instance.Name); ExtractLogic.ItemAnimation.Extract(record.key, stud, output, heroName, name, itemGroup, track, map, handler, quiet, flags); break; case "Voice Line": //Console.Out.WriteLine("Extracting voice line {0} for {1}...", name, heroName); //ExtractLogic.VoiceLine.Extract(master, stud, output, heroName, name, track, map, handler); break; } } } }
static void Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; List <IOvertool> tools = new List <IOvertool>(); { Assembly asm = typeof(IOvertool).Assembly; Type t = typeof(IOvertool); List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList(); foreach (Type tt in types) { if (tt.IsInterface) { continue; } IOvertool toolinst = (IOvertool)Activator.CreateInstance(tt); if (toolinst.Display) { tools.Add(toolinst); } } } OverToolFlags flags = FlagParser.Parse <OverToolFlags>(() => PrintHelp(tools)); if (flags == null) { return; } bool quiet = flags.Quiet; string root = flags.OverwatchDirectory; char opt = flags.Mode[0]; IOvertool tool = null; Dictionary <ushort, List <ulong> > track = new Dictionary <ushort, List <ulong> >(); track[0x90] = new List <ulong>(); // internal requirements toolsMap = new Dictionary <char, IOvertool>(); foreach (IOvertool t in tools) { if (t.Opt == opt) { tool = t; } foreach (ushort tr in t.Track) { if (!track.ContainsKey(tr)) { track[tr] = new List <ulong>(); } } if (toolsMap.ContainsKey(t.Opt)) { Console.Out.WriteLine("Duplicate opt! {0} conflicts with {1}", t.Title, toolsMap[t.Opt].Title); } toolsMap[t.Opt] = t; } if (tool == null || flags.Positionals.Length - 2 < tool.MinimumArgs) { PrintHelp(tools); return; } Dictionary <ulong, Record> map = new Dictionary <ulong, Record>(); Console.Out.WriteLine("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, OWLib.Util.GetVersion()); Console.Out.WriteLine("Initializing CASC..."); Console.Out.WriteLine("Set language to {0}", flags.Language); CDNIndexHandler.Cache.Enabled = flags.UseCache; CDNIndexHandler.Cache.CacheData = flags.CacheData; CDNIndexHandler.Cache.Validate = flags.ValidateCache; CASCConfig config = null; // ngdp:us:pro // http:us:pro:us.patch.battle.net:1119 if (root.ToLowerInvariant().Substring(0, 5) == "ngdp:") { string cdn = root.Substring(5, 4); string[] parts = root.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(root, !flags.SkipKeys, false); } config.Languages = new HashSet <string>(new string[1] { flags.Language }); if (flags.SkipKeys) { Console.Out.WriteLine("Disabling Key auto-detection..."); } Console.Out.WriteLine("Using Overwatch Version {0}", config.BuildName); CASCHandler handler = CASCHandler.OpenStorage(config); OwRootHandler ow = handler.Root as OwRootHandler; if (ow == null) { Console.Error.WriteLine("Not a valid overwatch installation"); return; } // Fail when trying to extract data from a specified language with 2 or less files found. if (ow.APMFiles.Count() == 0) { Console.Error.WriteLine("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); return; } Console.Out.WriteLine("Mapping..."); Util.MapCMF(ow, handler, map, track, flags); if (!flags.SkipKeys) { Console.Out.WriteLine("Adding Encryption Keys..."); foreach (ulong key in track[0x90]) { if (!map.ContainsKey(key)) { continue; } using (Stream stream = Util.OpenFile(map[key], handler)) { if (stream == null) { continue; } STUD stud = new STUD(stream); if (stud.Instances[0].Name != stud.Manager.GetName(typeof(EncryptionKey))) { continue; } EncryptionKey ek = (EncryptionKey)stud.Instances[0]; if (!KeyService.keys.ContainsKey(ek.KeyNameLong)) { KeyService.keys.Add(ek.KeyNameLong, ek.KeyValueText.ToByteArray()); Console.Out.WriteLine("Added Encryption Key {0}, Value: {1}", ek.KeyNameText, ek.KeyValueText); } } } } Console.Out.WriteLine("Tooling..."); tool.Parse(track, map, handler, quiet, flags); if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Break(); } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; List <string> maps = new List <string>(); if (flags.Positionals.Length > 3) { maps.AddRange(flags.Positionals.Skip(2).Select((it) => it.ToLower())); } bool wildcard = maps.Count == 0 || maps.Contains("*"); List <ulong> masters = track[0x9F]; Dictionary <ulong, ulong> replace = new Dictionary <ulong, ulong>(); foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null || masterStud.Instances[0] == null) { continue; } MapMaster master = (MapMaster)masterStud.Instances[0]; if (master == null) { continue; } string name = Util.GetString(master.Header.name.key, map, handler); if (string.IsNullOrWhiteSpace(name)) { name = $"Unknown{GUID.Index(master.Header.data.key):X}"; } if (!maps.Contains(name.ToLowerInvariant()) && !wildcard) { continue; } if (!map.ContainsKey(master.DataKey(0xB))) { continue; } if (!map.ContainsKey(master.DataKey(0x11))) { continue; } Console.Out.WriteLine("Dumping audio for map {0}", name); Dictionary <ulong, List <ulong> > soundData = new Dictionary <ulong, List <ulong> >(); string path = string.Format("{0}{1}{2}{1}{3}{1}{4}{1}", output, Path.DirectorySeparatorChar, Util.Strip(Util.SanitizePath(name)), "Audio", GUID.Index(master.Header.data.key)); HashSet <ulong> soundDone = new HashSet <ulong>(); using (Stream mapBStream = Util.OpenFile(map[master.DataKey(0xB)], handler)) { if (mapBStream != null) { Map mapB = new Map(mapBStream); foreach (STUD stud in mapB.STUDs) { Sound.FindSoundsSTUD(stud, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0xB)); } for (int i = 0; i < mapB.Records.Length; ++i) { if (mapB.Records[i] != null && mapB.Records[i].GetType() != typeof(Map0B)) { continue; } Map0B mapprop = (Map0B)mapB.Records[i]; if (!map.ContainsKey(mapprop.Header.binding)) { continue; } Sound.FindSoundsEx(mapprop.Header.binding, soundDone, soundData, map, handler, replace, master.DataKey(0xB)); } } } using (Stream map11Stream = Util.OpenFile(map[master.DataKey(0x11)], handler)) { if (map11Stream != null) { Map11 map11 = new Map11(map11Stream); Sound.FindSoundsSTUD(map11.main, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11)); Sound.FindSoundsSTUD(map11.secondary, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11)); } } if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } DumpVoice.Save(path, soundData, map, handler, quiet); } }
public static void GetInventoryName(ulong key, bool ex, Dictionary <ulong, Record> map, CASCHandler handler, string heroName) { Tuple <string, STUD, IInventorySTUDInstance> data = GetInventoryName(key, map, handler); if (data == null) { return; } string name = data.Item1; STUD stud = data.Item2; IInventorySTUDInstance instance = data.Item3; if (name == null && instance.Name != stud.Manager.GetName(typeof(CreditItem))) { Console.Out.WriteLine("\t\t(Untitled-{0:X12}) ({1} {2})", GUID.LongKey(key), instance.Header.rarity, stud.Instances[0].Name); return; } #if OUTPUT_STUDINVENTORY Stream studStream = Util.OpenFile(map[key], handler); string filename = string.Format("{0}_{1}", instance.Name, name); foreach (var c in Path.GetInvalidFileNameChars()) { filename = filename.Replace(c, '_'); } string outFilename = string.Format("./STUDs/Inventory/{0}/{1}.stud", heroName, filename); string putPathname = outFilename.Substring(0, outFilename.LastIndexOf('/')); Directory.CreateDirectory(putPathname); Stream OutWriter = File.Create(outFilename); studStream.CopyTo(OutWriter); OutWriter.Close(); studStream.Close(); #endif string addt = string.Empty; if (instance.Name == stud.Manager.GetName(typeof(CreditItem))) { CreditItem credits = (CreditItem)instance; name = $"{credits.Data.value} Credits"; } if (instance.Name == stud.Manager.GetName(typeof(WeaponSkinItem))) { WeaponSkinItem weapon = (WeaponSkinItem)instance; addt = $" Index {weapon.Data.index}"; } if (ex) { Console.Out.WriteLine("\t\t{0} ({1} {2} in file {3:X16}){4}", name, instance.Header.rarity, stud.Instances[0].Name, GUID.LongKey(key), addt); } else { Console.Out.WriteLine("\t\t{0} ({1} {2}){3}", name, instance.Header.rarity, stud.Instances[0].Name, addt); } if (instance.Header.description != 0) { using (Stream descStream = Util.OpenFile(map[instance.Header.description], handler)) { STUD description = new STUD(descStream); if (description.Instances == null) { return; } InventoryDescription desc = description.Instances[0] as InventoryDescription; if (desc == null) { return; } string descriptionStr = Util.GetString(desc.Header.str, map, handler); if (!string.IsNullOrEmpty(descriptionStr)) { Console.Out.WriteLine("\t\t\t{0}", descriptionStr); } } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { string output = flags.Positionals[2]; List <string> heroes = new List <string>(); if (flags.Positionals.Length > 3) { heroes.AddRange(flags.Positionals[3].ToLowerInvariant().Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries)); } bool heroAllWildcard = heroes.Count == 0 || heroes.Contains("*"); List <ulong> masters = track[0x75]; foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null || masterStud.Instances[0] == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } if (!heroes.Contains(heroName.ToLowerInvariant())) { if (!heroAllWildcard) { continue; } } HashSet <ulong> items = new HashSet <ulong>(); InventoryMaster inventory = Extract.OpenInventoryMaster(master, map, handler); if (inventory == null) { continue; } foreach (OWRecord record in inventory.Achievables) { items.Add(record); } for (int i = 0; i < inventory.DefaultGroups.Length; ++i) { for (int j = 0; j < inventory.Defaults[i].Length; ++j) { items.Add(inventory.Defaults[i][j]); } } for (int i = 0; i < inventory.ItemGroups.Length; ++i) { for (int j = 0; j < inventory.Items[i].Length; ++j) { items.Add(inventory.Items[i][j]); } } HashSet <ulong> done = new HashSet <ulong>(); string path = string.Format("{0}{1}{2}{1}{3}{1}", output, Path.DirectorySeparatorChar, Util.Strip(Util.SanitizePath(heroName)), "Sound Dump Full"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } bool haveBase = false; foreach (ulong itemKey in items) { if (!map.ContainsKey(itemKey)) { continue; } using (Stream itemStream = Util.OpenFile(map[itemKey], handler)) { STUD itemStud = new STUD(itemStream); if (itemStud.Instances == null) { continue; } SkinItem item = itemStud.Instances[0] as SkinItem; if (item == null) { continue; } Dictionary <ulong, List <ulong> > sound = new Dictionary <ulong, List <ulong> >(); if (!haveBase) { sound.Clear(); Console.Out.WriteLine("Processing base sounds for hero {0}", heroName); Skin.ExtractData(item, master, false, new HashSet <ulong>(), new Dictionary <ulong, ulong>(), new HashSet <ulong>(), new Dictionary <ulong, List <ImageLayer> >(), new Dictionary <ulong, ulong>(), sound, new List <ulong>(), -1, map, handler); Sound.FindSounds(master, track, map, handler, null, masterKey, sound); DumpVoice.Save($"{path}_Base{Path.DirectorySeparatorChar}", sound, map, handler, quiet, null, done); haveBase = true; } sound.Clear(); string itemName = Util.GetString(item.Header.name, map, handler); if (string.IsNullOrWhiteSpace(itemName)) { itemName = $"Item-{itemKey:X16}"; } Console.Out.WriteLine("Processing new sounds for skin {0}", itemName); Dictionary <ulong, ulong> replace = new Dictionary <ulong, ulong>(); Skin.ExtractData(item, master, true, new HashSet <ulong>(), new Dictionary <ulong, ulong>(), new HashSet <ulong>(), new Dictionary <ulong, List <ImageLayer> >(), replace, sound, new List <ulong>(), -1, map, handler); Sound.FindSounds(master, track, map, handler, replace, masterKey, sound); DumpVoice.Save($"{path}{Util.Strip(Util.SanitizePath(itemName))}{Path.DirectorySeparatorChar}", sound, map, handler, quiet, replace, done); } } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { List <ulong> masters = track[0x75]; foreach (ulong masterKey in masters) { if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler)); if (masterStud.Instances == null) { continue; } HeroMaster master = (HeroMaster)masterStud.Instances[0]; if (master == null) { continue; } string heroName = Util.GetString(master.Header.name.key, map, handler); if (heroName == null) { continue; } string goodhero = heroName; foreach (var c in Path.GetInvalidFileNameChars()) { goodhero = goodhero.Replace(c, '_'); } if (master.Header.itemMaster.key == 0) // AI { continue; } bool ex = System.Diagnostics.Debugger.IsAttached || flags.Expert; bool hasName = false; if (!map.ContainsKey(master.Header.itemMaster.key)) { Console.Out.WriteLine("Error loading inventory master file..."); continue; } STUD inventoryStud = new STUD(Util.OpenFile(map[master.Header.itemMaster.key], handler)); #if OUTPUT_STUDINVENTORYMASTER Stream studStream = Util.OpenFile(map[master.Header.itemMaster.key], handler); string outFilename = string.Format("./STUDs/ListInventoryMaster/{0}.stud", goodhero); string putPathname = outFilename.Substring(0, outFilename.LastIndexOf('/')); Directory.CreateDirectory(putPathname); Stream OutWriter = File.Create(outFilename); studStream.CopyTo(OutWriter); OutWriter.Close(); studStream.Close(); #endif InventoryMaster inventory = (InventoryMaster)inventoryStud.Instances[0]; if (inventory == null) { Console.Out.WriteLine("Error loading inventory master file..."); continue; } Dictionary <int, string> indexMap = new Dictionary <int, string>(); List <OWRecord> items = new List <OWRecord>(); items.AddRange(inventory.Achievables.ToList()); for (int i = 0; i < inventory.DefaultGroups.Length; ++i) { string name = $"STANDARD_{ItemEvents.GetInstance().GetEvent(inventory.DefaultGroups[i].@event)}"; items.AddRange(inventory.Defaults[i].ToList()); } for (int i = 0; i < inventory.ItemGroups.Length; ++i) { string name = ItemEvents.GetInstance().GetEvent(inventory.ItemGroups[i].@event); items.AddRange(inventory.Items[i].ToList()); } foreach (OWRecord record in items) { STUD item = new STUD(Util.OpenFile(map[record], handler)); if (item.Instances == null) { continue; } WeaponSkinItem skin = item.Instances[0] as WeaponSkinItem; if (skin == null) { continue; } if (!hasName) { if (ex) { Console.Out.WriteLine("Weapons for {0} ({2:X16}) in package {1:X16}", heroName, map[masterKey].package.packageKey, masterKey); } else { Console.Out.WriteLine("Weapons for {0}", heroName); } hasName = true; } Console.Out.WriteLine("\tIndex {0} - {1}", skin.Data.index, Util.GetString(skin.Header.name, map, handler)); } if (hasName) { Console.Out.WriteLine(""); } } }
public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags) { List <ulong> masters = track[0x9F]; foreach (ulong masterKey in masters) { Console.Out.WriteLine(""); if (!map.ContainsKey(masterKey)) { continue; } STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler), true, STUDManager.Instance, false, true); if (masterStud.Instances == null) { continue; } MapMaster master = (MapMaster)masterStud.Instances[0]; if (master == null) { continue; } string name = Util.GetString(master.Header.name.key, map, handler); if (string.IsNullOrWhiteSpace(name)) { name = $"Unknown{GUID.Index(masterKey):X}"; } Console.Out.WriteLine(name); Console.Out.WriteLine("\tID: {0:X8}", GUID.Index(masterKey)); string subline = Util.GetString(master.Header.subline.key, map, handler); if (subline == null) { subline = ""; } if (master.Header.subline.key != master.Header.subline2.key && master.Header.subline2.key != 0) { subline += " " + Util.GetString(master.Header.subline2.key, map, handler); } subline = subline.Trim(); if (subline.Length > 0) { Console.Out.WriteLine("\tSubline: {0}", subline); } TryString("State", Util.GetString(master.Header.stateA.key, map, handler)); TryString("State", Util.GetString(master.Header.stateB.key, map, handler)); string description = Util.GetString(master.Header.description1.key, map, handler); if (description == null) { description = ""; } if (master.Header.description1.key != master.Header.description2.key && master.Header.description2.key != 0) { description += " " + Util.GetString(master.Header.description2.key, map, handler); } description = description.Trim(); if (description.Length > 0) { Console.Out.WriteLine("\tDescription: {0}", description); } } }