/// <summary> /// /// </summary> /// <param name="pack"></param> /// <param name="fighter"></param> /// <param name="editor"></param> /// <returns></returns> private void ImportItemData(ZipFile pack, MEXFighterEntry fighter) { Console.WriteLine($"Importing Item Data..."); var itemEntries = pack.Where(e => Regex.IsMatch(e.FileName, @"Item/item\d\d.*.yaml")); HSD_UShort[] itemIndices = new HSD_UShort[0]; foreach (var item in itemEntries) { int val; if (int.TryParse(Regex.Match(item.FileName, @"(?<=item)\d\d").Value, out val)) { using (MemoryStream s = new MemoryStream(GetBytes(item))) using (StreamReader r = new StreamReader(s)) { // add item entry to mex items var id = editor.ItemControl.AddMEXItem(r.ReadToEnd()); // add it to itemIndices Array.Resize(ref itemIndices, val + 1); itemIndices[val] = new HSD_UShort() { Value = (ushort)id }; } } } fighter.MEXItems = itemIndices.ToArray(); }
/// <summary> /// Generates an Eff file for Fighter & Kirby /// Adds entries for effects to mexData /// Updates ids for Fighter Mex Entry /// </summary> /// <param name="pack"></param> /// <param name="fighter"></param> /// <param name="editor"></param> /// <returns>Dictionary to maps old id values to new values</returns> private void GenerateEffectFile(ZipFile pack, MEXFighterEntry fighter) { Console.WriteLine($"Generating Effect File..."); // Generate information--------------------------------------------- string charID = Regex.Match(fighter.FighterDataPath, @"(?<=Pl)..").Value; var root = Path.GetDirectoryName(MainForm.Instance.FilePath); var effectFileName = $"Ef{charID}Data.dat"; var effectOutputFilePath = Path.Combine(root, effectFileName); var symbol = $"eff{fighter.NameText}DataTable"; // Generate Effect File------------------------------------------- var models = pack.Where(e => Regex.IsMatch(e.FileName, @"Effect/effect\d\d.*.dat")).ToArray(); var ptcl = pack["Effect/effect.ptcl"]; var texg = pack["Effect/effect.texg"]; SBM_EffectTable effTable = new SBM_EffectTable(); if (ptcl != null && texg != null) { effTable._s.SetReferenceStruct(0x00, new HSDStruct(GetBytes(ptcl))); effTable._s.SetReferenceStruct(0x04, new HSDStruct(GetBytes(texg))); } SBM_EffectModel[] effModels = new SBM_EffectModel[models.Length]; for (int i = 0; i < models.Length; i++) { effModels[i] = new SBM_EffectModel(); effModels[i]._s = new HSDRawFile(GetBytes(models[i])).Roots[0].Data._s; } effTable.Models = effModels; // Save File--------------------------------------------- var effFile = new HSDRawFile(); effFile.Roots.Add(new HSDRootNode() { Name = symbol, Data = effTable }); editedFiles.Add(new Tuple <HSDRawFile, string, bool>(effFile, effectOutputFilePath, true)); // Add Effect Entries------------------------------------------- MEXEffectEntry effectFiles = new MEXEffectEntry(); effectFiles.FileName = effectFileName; effectFiles.Symbol = symbol; var effectID = editor.EffectControl.AddMEXEffectFile(effectFiles); fighter.EffectIndex = effectID; Console.WriteLine("Effect ID:" + effectID); }
/// <summary> /// /// </summary> /// <param name="pack"></param> /// <param name="fighter"></param> /// <param name="mexData"></param> private static void ExtractFiles(ZipFile pack, MEXFighterEntry fighter, MexDataEditor mexData) { Console.WriteLine($"Copying files to directory..."); var root = Path.GetDirectoryName(MainForm.Instance.FilePath); foreach (var e in pack) { var fileName = Path.GetFileName(e.FileName); if (Regex.IsMatch(fileName, @"Pl...dat") || Regex.IsMatch(fileName, @"Pl..AJ.dat") || Regex.IsMatch(fileName, @"GmRstM...dat") || Regex.IsMatch(fileName, @"Pl..DViWaitAJ.dat") || Regex.IsMatch(fileName, @"Kirby/PlKbCp...dat") || Regex.IsMatch(fileName, @"Costume/.*")) { File.WriteAllBytes(Path.Combine(root, Path.GetFileName(fileName)), GetBytes(e)); } } }
/// <summary> /// /// </summary> /// <param name="fighter"></param> /// <param name="editor"></param> /// <param name="internalID"></param> private void RemoveUI(MEXFighterEntry fighter, MexDataEditor editor, int internalID) { Console.WriteLine("Removing UI"); var root = Path.GetDirectoryName(MainForm.Instance.FilePath); int GroupID = MEXIdConverter.ToExternalID(internalID, editor.FighterControl.FighterEntries.Count + 1) - 1; int stride = editor.FighterControl.FighterEntries.Count - 3 + 1; Console.WriteLine("Removing CSP"); /*var chrSelPath = Path.Combine(root, "MnSlChr.usd"); * if (File.Exists(chrSelPath)) * { * var cssFile = new HSDRawFile(chrSelPath); * * if (cssFile.Roots[0].Data is SBM_SelectChrDataTable cssTable) * { * foreach (var n in cssTable.SingleMenuMaterialAnimation.Children[9].Children) * RemoveMatAnim(n.MaterialAnimation.TextureAnimation, GroupID, stride, FighterPackageInstaller.MAX_COSTUME_COUNT); * * foreach (var n in cssTable.MenuMaterialAnimation.Children[6].Children) * RemoveMatAnim(n.MaterialAnimation.TextureAnimation, GroupID, stride, FighterPackageInstaller.MAX_COSTUME_COUNT); * * foreach (var n in cssTable.SingleMenuMaterialAnimation.Children[6].Children) * RemoveMatAnim(n.MaterialAnimation.TextureAnimation, GroupID, stride, FighterPackageInstaller.MAX_COSTUME_COUNT); * * foreach (var n in cssTable.PortraitMaterialAnimation.Children[2].Children) * RemoveMatAnim(n.MaterialAnimation.TextureAnimation, GroupID, stride, FighterPackageInstaller.MAX_COSTUME_COUNT); * * * foreach (var n in cssTable.MenuMaterialAnimation.Children[5].Children) * RemoveMatAnim(n.MaterialAnimation.Next.TextureAnimation, GroupID, stride, 1); * * foreach (var n in cssTable.SingleMenuMaterialAnimation.Children[5].Children) * RemoveMatAnim(n.MaterialAnimation.Next.TextureAnimation, GroupID, stride, 1); * * foreach (var n in cssTable.PortraitMaterialAnimation.Children[1].Children) * RemoveMatAnim(n.MaterialAnimation.Next.TextureAnimation, GroupID, stride, 1); * * } * * editedFiles.Add(new Tuple<HSDRawFile, string, bool>(cssFile, chrSelPath, true)); * }*/ Console.WriteLine("Removing Icons"); var ifallPath = Path.Combine(root, "IfAll.usd"); if (File.Exists(ifallPath)) { var datFile = new HSDRawFile(ifallPath); var mark = datFile.Roots.Find(e => e.Name.Equals("Stc_scemdls")).Data as HSDNullPointerArrayAccessor <HSD_JOBJDesc>; for (int i = 0; i < 7; i++) // first 7 { RemoveMatAnim(mark[0].MaterialAnimations[0].Children[i].MaterialAnimation.TextureAnimation, GroupID, stride, FighterPackageInstaller.MAX_COSTUME_COUNT); } var emblemGroup = datFile.Roots.Find(e => e.Name.Equals("DmgMrk_scene_models")).Data as HSDNullPointerArrayAccessor <HSD_JOBJDesc>; RemoveMatAnim(emblemGroup[0].MaterialAnimations[0].Child.MaterialAnimation.TextureAnimation, GroupID, stride, 1); editedFiles.Add(new Tuple <HSDRawFile, string, bool>(datFile, ifallPath, true)); } Console.WriteLine("Removing Result UI"); var gmrst = Path.Combine(root, "GmRst.usd"); if (File.Exists(gmrst)) { var datFile = new HSDRawFile(gmrst); var flmsce = datFile.Roots.Find(e => e.Name.Equals("flmsce")).Data as HSD_SOBJ; var pnlsce = datFile.Roots.Find(e => e.Name.Equals("pnlsce")).Data as HSD_SOBJ; // remove stock icons for (int i = 5; i <= 8; i++) // at 5-8, 2nd mat anim { RemoveMatAnim(pnlsce.JOBJDescs[0].MaterialAnimations[0].Children[i].MaterialAnimation.Next.TextureAnimation, GroupID, stride, FighterPackageInstaller.MAX_COSTUME_COUNT); } // remove emblem entries var matgroup = pnlsce.JOBJDescs[0].MaterialAnimations[0].Children[17]; for (int i = 0; i < 4; i++) { RemoveMatAnim(matgroup.Children[i].MaterialAnimation.TextureAnimation, GroupID, stride, 1); } // check if any other fighter is using this stock icon // if not, remove it and adjust ids if (!editor.FighterControl.FighterEntries.Any(e => e.InsigniaID == fighter.InsigniaID)) { var emblemGroup = flmsce.JOBJDescs[0]; emblemGroup.JointAnimations[0].Children[4].RemoveChildAt(fighter.InsigniaID); emblemGroup.MaterialAnimations[0].Children[4].RemoveChildAt(fighter.InsigniaID); emblemGroup.RootJoint.Children[4].RemoveChildAt(fighter.InsigniaID); foreach (var f in editor.FighterControl.FighterEntries) { if (f.InsigniaID > fighter.InsigniaID) { f.InsigniaID--; } } } // name textures var largenameGroup = pnlsce.JOBJDescs[0].MaterialAnimations[0].Children[0].Children[2].MaterialAnimation.Next.TextureAnimation; RemoveMatAnim(largenameGroup, GroupID, stride, 1); var smallnameGroup = pnlsce.JOBJDescs[0].MaterialAnimations[0]; for (int i = 9; i < 13; i++) { RemoveMatAnim(smallnameGroup.Children[i].Children[1].MaterialAnimation.TextureAnimation, GroupID, stride, 1); } editedFiles.Add(new Tuple <HSDRawFile, string, bool>(datFile, gmrst, true)); } }
public FighterPackageUninstaller(int internalID, MEXFighterEntry fighter, MexDataEditor editor) { this.internalID = internalID; this.fighter = fighter; this.editor = editor; }
/// <summary> /// /// </summary> /// <param name="packagePath"></param> public override void Work(BackgroundWorker w) { var root = Path.GetDirectoryName(MainForm.Instance.FilePath); var plco = Path.Combine(root, "PlCo.dat"); var sem = Path.Combine(root, "audio\\us\\smash2.sem"); if (!File.Exists(plco)) { throw new FileNotFoundException("PlCo.dat was not found"); } if (!File.Exists(sem)) { throw new FileNotFoundException("smash2.sem was not found"); } using (ZipFile pack = new ZipFile(packagePath)) { string fighterYAMLPath = null; foreach (var e in pack) { Console.WriteLine(e.FileName); if (Path.GetFileName(e.FileName).ToLower() == "fighter.yaml") { fighterYAMLPath = e.FileName; } } if (string.IsNullOrEmpty(fighterYAMLPath)) { return; } MEXFighterEntry mexEntry = null; using (MemoryStream zos = new MemoryStream()) { pack[fighterYAMLPath].Extract(zos); zos.Position = 0; //using (StreamReader r = new StreamReader(zos)) // mexEntry = MEXFighterEntry.Deserialize(r.ReadToEnd()); } if (mexEntry == null) { return; } ProgressStatus = $"Importing {mexEntry.NameText}..."; w.ReportProgress(0); var internalID = editor.FighterControl.AddEntry(mexEntry); ProgressStatus = "Installing Item Data"; w.ReportProgress(10); ImportItemData(pack, mexEntry); ProgressStatus = "Installing Item Data"; w.ReportProgress(20); GenerateEffectFile(pack, mexEntry); ProgressStatus = "Installing Item Data"; w.ReportProgress(30); ImportSoundData(pack, mexEntry, sem); ProgressStatus = "Installing UI"; w.ReportProgress(50); InstallUI(pack, mexEntry); ProgressStatus = "Installing Item Data"; w.ReportProgress(60); InjectBoneTable(pack, plco, internalID); //... ProgressStatus = "Extracting Files"; w.ReportProgress(70); ExtractFiles(pack, mexEntry, editor); ProgressStatus = "Building new SEM"; w.ReportProgress(80); if (SemEntries.Count != 0) { SEM.SaveSEMFile(sem, SemEntries, editor._data); } ProgressStatus = "Saving Files"; w.ReportProgress(90); foreach (var d in editedFiles) { d.Item1.Save(d.Item2, d.Item3); } ProgressStatus = "Done"; w.ReportProgress(100); // done Console.WriteLine($"Done!"); } }
/// <summary> /// /// </summary> /// <param name="datPath"></param> /// <param name="pack"></param> private void InjectCharSelectImages(ZipFile pack, string datPath, HSD_TOBJ[] icons, HSD_TOBJ emblemTexture, MEXFighterEntry fighter, int stride, int groupID) { var cssFile = new HSDRawFile(datPath); if (cssFile.Roots[0].Data is SBM_SelectChrDataTable cssTable) { // get base width and height int width = 132; int height = 188; if (cssTable.PortraitMaterialAnimation.Children[2].Child.MaterialAnimation.TextureAnimation.ImageCount > 0) { width = cssTable.PortraitMaterialAnimation.Children[2].Child.MaterialAnimation.TextureAnimation.ImageBuffers[0].Data.Width; height = cssTable.PortraitMaterialAnimation.Children[2].Child.MaterialAnimation.TextureAnimation.ImageBuffers[0].Data.Height; } // LOAD CSPs var csps = pack.Where(e => Regex.IsMatch(e.FileName, "CSS/css..\\.png")).ToArray(); HSD_TOBJ[] cspTOBJs = new HSD_TOBJ[csps.Length]; foreach (var c in csps) { var index = int.Parse(Regex.Match(c.FileName, @"\d\d").Value); using (MemoryStream stream = new MemoryStream(GetBytes(c))) using (var bmp = new System.Drawing.Bitmap(stream)) { // shrink but don't grow if (bmp.Width > width || bmp.Height > height) { using (System.Drawing.Bitmap resized = new System.Drawing.Bitmap(width, height)) { using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(resized)) g.DrawImage(bmp, 0, 0, width, height); cspTOBJs[index] = TOBJConverter.BitmapToTOBJ(resized, HSDRaw.GX.GXTexFmt.CI8, HSDRaw.GX.GXTlutFmt.RGB5A3); } } else { cspTOBJs[index] = TOBJConverter.BitmapToTOBJ(bmp, HSDRaw.GX.GXTexFmt.CI8, HSDRaw.GX.GXTlutFmt.RGB5A3); } } } // Inject Icons foreach (var n in cssTable.SingleMenuMaterialAnimation.Children[9].Children) { InjectIntoMatTexAnim(n.MaterialAnimation.TextureAnimation, icons, groupID, stride, MAX_COSTUME_COUNT); } // Inject CSPs foreach (var n in cssTable.MenuMaterialAnimation.Children[6].Children) { InjectIntoMatTexAnim(n.MaterialAnimation.TextureAnimation, cspTOBJs, groupID, stride, MAX_COSTUME_COUNT); } foreach (var n in cssTable.SingleMenuMaterialAnimation.Children[6].Children) { InjectIntoMatTexAnim(n.MaterialAnimation.TextureAnimation, cspTOBJs, groupID, stride, MAX_COSTUME_COUNT); } foreach (var n in cssTable.PortraitMaterialAnimation.Children[2].Children) { InjectIntoMatTexAnim(n.MaterialAnimation.TextureAnimation, cspTOBJs, groupID, stride, MAX_COSTUME_COUNT); } // Emblem foreach (var n in cssTable.MenuMaterialAnimation.Children[5].Children) { InjectIntoMatTexAnim(n.MaterialAnimation.Next.TextureAnimation, new HSDRaw.Common.HSD_TOBJ[] { emblemTexture }, groupID, stride, 1, fighter.InsigniaID); } foreach (var n in cssTable.SingleMenuMaterialAnimation.Children[5].Children) { InjectIntoMatTexAnim(n.MaterialAnimation.Next.TextureAnimation, new HSDRaw.Common.HSD_TOBJ[] { emblemTexture }, groupID, stride, 1, fighter.InsigniaID); } foreach (var n in cssTable.PortraitMaterialAnimation.Children[1].Children) { InjectIntoMatTexAnim(n.MaterialAnimation.Next.TextureAnimation, new HSDRaw.Common.HSD_TOBJ[] { emblemTexture }, groupID, stride, 1, fighter.InsigniaID); } } editedFiles.Add(new Tuple <HSDRawFile, string, bool>(cssFile, datPath, true)); }
/// <summary> /// /// </summary> private void InstallUI(ZipFile pack, MEXFighterEntry fighter) { Console.WriteLine($"Installing UI data..."); // LOAD Stock Icons var icons = pack.Where(e => Regex.IsMatch(e.FileName, "Icon/ico..\\.png")).ToArray(); HSD_TOBJ[] iconTOBJs = new HSD_TOBJ[icons.Length]; foreach (var c in icons) { var index = int.Parse(Regex.Match(c.FileName, @"\d\d").Value); using (MemoryStream stream = new MemoryStream(GetBytes(c))) using (var bmp = new System.Drawing.Bitmap(stream)) iconTOBJs[index] = TOBJConverter.BitmapToTOBJ(bmp, HSDRaw.GX.GXTexFmt.CI4, HSDRaw.GX.GXTlutFmt.RGB5A3); } // Load Menu Icon // Load Emblem var emblemPack = pack["UI/emblem.obj"]; HSD_TOBJ emblemTexture = null; HSD_JOBJ emblemModel = null; if (emblemPack != null) { EmblemModel model; using (MemoryStream stream = new MemoryStream()) { emblemPack.Extract(stream); stream.Position = 0; model = Converters.EmblemConverter.GenerateEmblemModelFromOBJ(stream); } emblemModel = Converters.EmblemConverter.GenerateEmblemModel(model); emblemTexture = Converters.EmblemConverter.GenerateEmblemIconImage(model); } // Load Misc Name Tags and icons var largeName = pack["UI/result_victory_name.png"]; var smallName = pack["UI/result_name.png"]; HSD_TOBJ largeNameTexture = null; HSD_TOBJ smallNameTexture = null; if (largeName != null) { using (MemoryStream stream = new MemoryStream(GetBytes(largeName))) using (var bmp = new System.Drawing.Bitmap(stream)) largeNameTexture = TOBJConverter.BitmapToTOBJ(bmp, HSDRaw.GX.GXTexFmt.I4, HSDRaw.GX.GXTlutFmt.IA8); } if (smallName != null) { using (MemoryStream stream = new MemoryStream(GetBytes(smallName))) using (var bmp = new System.Drawing.Bitmap(stream)) smallNameTexture = TOBJConverter.BitmapToTOBJ(bmp, HSDRaw.GX.GXTexFmt.I4, HSDRaw.GX.GXTlutFmt.IA8); } // -------------------------------------------------------------------------- var root = Path.GetDirectoryName(MainForm.Instance.FilePath); int stride = editor.FighterControl.FighterEntries.Count - 3; int internalID = editor.FighterControl.FighterEntries.IndexOf(fighter); var externalId = MEXIdConverter.ToExternalID(internalID, editor.FighterControl.FighterEntries.Count); int GroupID = externalId - (externalId > 18 ? 1 : 0); // Inject CSPs and Stock Icons into Character Select //var chrSelPath = Path.Combine(root, "MnSlChr.usd"); //if (File.Exists(chrSelPath)) // InjectCharSelectImages(pack, chrSelPath, iconTOBJs, emblemTexture, fighter, stride, GroupID); // Inject Stock Icons into IfAll, GmRst var ifallPath = Path.Combine(root, "IfAll.usd"); if (File.Exists(ifallPath)) { var datFile = new HSDRawFile(ifallPath); var mark = datFile.Roots.Find(e => e.Name.Equals("Stc_scemdls")).Data as HSDNullPointerArrayAccessor <HSD_JOBJDesc>; for (int i = 0; i < 7; i++) // first 7 { InjectIntoMatTexAnim(mark[0].MaterialAnimations[0].Children[i].MaterialAnimation.TextureAnimation, iconTOBJs, GroupID, stride, MAX_COSTUME_COUNT); } var emblemGroup = datFile.Roots.Find(e => e.Name.Equals("DmgMrk_scene_models")).Data as HSDNullPointerArrayAccessor <HSD_JOBJDesc>; InjectIntoMatTexAnim(emblemGroup[0].MaterialAnimations[0].Child.MaterialAnimation.TextureAnimation, new HSDRaw.Common.HSD_TOBJ[] { emblemTexture }, GroupID, stride, 1, fighter.InsigniaID); editedFiles.Add(new Tuple <HSDRawFile, string, bool>(datFile, ifallPath, true)); } var gmRst = Path.Combine(root, "GmRst.usd"); if (File.Exists(gmRst)) { var datFile = new HSDRawFile(gmRst); var flmsce = datFile.Roots.Find(e => e.Name.Equals("flmsce")).Data as HSD_SOBJ; var pnlsce = datFile.Roots.Find(e => e.Name.Equals("pnlsce")).Data as HSD_SOBJ; // Stock Icons------------------------------------- for (int i = 5; i <= 8; i++) // at 5-8, 2nd mat anim { InjectIntoMatTexAnim( pnlsce.JOBJDescs[0].MaterialAnimations[0].Children[i].MaterialAnimation.Next.TextureAnimation, iconTOBJs, GroupID, stride, MAX_COSTUME_COUNT); } // Emblem Textures-------------------------------------- var matgroup = pnlsce.JOBJDescs[0].MaterialAnimations[0].Children[17]; for (int i = 0; i < 4; i++) { InjectIntoMatTexAnim(matgroup.Children[i].MaterialAnimation.TextureAnimation, new HSDRaw.Common.HSD_TOBJ[] { emblemTexture }, GroupID, stride, 1, fighter.InsigniaID); } // Emblem Model-------------------------------------- var emblemGroup = flmsce.JOBJDescs[0]; if (emblemModel != null) { var modelIndex = emblemGroup.RootJoint.Children[4].Children.Length; fighter.InsigniaID = (byte)modelIndex; var jointClone = HSDAccessor.DeepClone <HSDRaw.Common.Animation.HSD_AnimJoint>(emblemGroup.JointAnimations[0].Children[4].Child); jointClone.Next = null; var matjointClone = HSDAccessor.DeepClone <HSDRaw.Common.Animation.HSD_MatAnimJoint>(emblemGroup.MaterialAnimations[0].Children[4].Child); matjointClone.Next = null; emblemGroup.JointAnimations[0].Children[4].AddChild(jointClone); emblemGroup.MaterialAnimations[0].Children[4].AddChild(matjointClone); emblemGroup.RootJoint.Children[4].AddChild(emblemModel); } // name textures var largenameGroup = pnlsce.JOBJDescs[0].MaterialAnimations[0].Children[0].Children[2].MaterialAnimation.Next.TextureAnimation; InjectIntoMatTexAnim(largenameGroup, new HSD_TOBJ[] { largeNameTexture }, GroupID, stride, 1); var smallnameGroup = pnlsce.JOBJDescs[0].MaterialAnimations[0]; for (int i = 9; i < 13; i++) { InjectIntoMatTexAnim(smallnameGroup.Children[i].Children[1].MaterialAnimation.TextureAnimation, new HSD_TOBJ[] { smallNameTexture }, GroupID, stride, 1); } editedFiles.Add(new Tuple <HSDRawFile, string, bool>(datFile, gmRst, true)); } // Inject Emblem // Generate Emblem Models and Inject // Inject Misc Name Tags and icons }
/// <summary> /// /// </summary> /// <param name="pack"></param> /// <param name="fighter"></param> /// <param name="editor"></param> /// <returns>Dictionary to maps old sound id values to new values</returns> private void ImportSoundData(ZipFile pack, MEXFighterEntry fighter, string semFile) { Console.WriteLine($"Importing Sound Data..."); var root = Path.GetDirectoryName(MainForm.Instance.FilePath); // Load SEM File SemEntries = SEM.ReadSEMFile(semFile, true, editor._data); // narrator call----------------------------------------------- var narratorScript = @".SFXID : (id) .REVERB : 48 .PRIORITY : 15 .UNKNOWN06 : 229 .END : 0"; var narr = pack["Sound/narrator.dsp"]; var nameBank = SemEntries.Find(e => e.SoundBank?.Name == "nr_name.ssm"); if (narr != null && nameBank != null) { var narsound = new DSP(); narsound.FromFormat(GetBytes(narr), "dsp"); var index = nameBank.SoundBank.Sounds.Length; nameBank.SoundBank.AddSound(narsound); var script = new SEMScript(); SEM.CompileSEMScript(narratorScript.Replace("(id)", index.ToString()), out script.CommandData); var scriptIndex = nameBank.Scripts.Length; nameBank.AddScript(script); fighter.AnnouncerCall = scriptIndex + SemEntries.IndexOf(nameBank) * 10000; Console.WriteLine("Imported Announcer Call"); } // Create and import SSM----------------------------------------------- var semYAML = pack["Sound/sem.yaml"]; var ssmFile = pack["Sound/sound.ssm"]; if (semYAML != null) { using (MemoryStream zos = new MemoryStream()) { semYAML.Extract(zos); zos.Position = 0; using (StreamReader r = new StreamReader(zos)) { var semEntry = SEMEntry.Deserialize(r.ReadToEnd()); if (ssmFile != null) { var ssmName = fighter.NameText.ToLower() + ".ssm"; semEntry.SoundBank = new SSM(); using (MemoryStream ssmStream = new MemoryStream()) { ssmFile.Extract(ssmStream); ssmStream.Position = 0; semEntry.SoundBank.Open(ssmName, ssmStream); } var ssmFilePath = Path.Combine(root, "audio\\us\\" + ssmName); File.WriteAllBytes(ssmFilePath, GetBytes(ssmFile)); } fighter.SSMIndex = SemEntries.Count; SemEntries.Add(semEntry); } } } // Import Victory Theme var victory = pack["Sound/victory.hps"]; if (victory != null) { var ffname = $"ff_{fighter.NameText.ToLower()}.hps"; fighter.VictoryThemeID = editor.MusicControl.AddMusic(new HSD_String() { Value = ffname }); var fffilePath = Path.Combine(root, "audio\\" + ffname); File.WriteAllBytes(fffilePath, GetBytes(victory)); } }