public SlotModProperties(string modPath, string charName, SmashProjectManager project) { InitializeComponent(); ModPath = modPath; CharName = charName; _SmashProjectManager = project; DB.Fighter currentFighter = project._CharacterModsPage.CurrentFighter; PathKami = ModPath + Path.DirectorySeparatorChar + "kamimod.xml"; PathVoice = ModPath + Path.DirectorySeparatorChar + "sound" + Path.DirectorySeparatorChar + "snd_vc_" + (string.IsNullOrEmpty(currentFighter.nameSoundPack) ? CharName : currentFighter.nameSoundPack) + "_cxx.nus3bank"; PathSound = ModPath + Path.DirectorySeparatorChar + "sound" + Path.DirectorySeparatorChar + "snd_se_" + (string.IsNullOrEmpty(currentFighter.nameSoundPack) ? CharName : currentFighter.nameSoundPack) + "_cxx.nus3bank"; PathChr00 = ModPath + Path.DirectorySeparatorChar + "chr" + Path.DirectorySeparatorChar + "chr_00_" + CharName + "_XX.nut"; PathChr11 = ModPath + Path.DirectorySeparatorChar + "chr" + Path.DirectorySeparatorChar + "chr_11_" + CharName + "_XX.nut"; PathChr13 = ModPath + Path.DirectorySeparatorChar + "chr" + Path.DirectorySeparatorChar + "chr_13_" + CharName + "_XX.nut"; PathStock90 = ModPath + Path.DirectorySeparatorChar + "chr" + Path.DirectorySeparatorChar + "stock_90_" + CharName + "_XX.nut"; PathChrn11 = ModPath + Path.DirectorySeparatorChar + "chr" + Path.DirectorySeparatorChar + "chrn_11_" + CharName + "_XX.nut"; XMLData = Utils.DeserializeXML <CharacterSlotModXML>(PathKami); if (XMLData == null) { return; } XMLData.isDirty = false; if (XMLData.BoxingRingText == null) { XMLData.BoxingRingText = String.Empty; } if (XMLData.CharacterName == null) { XMLData.CharacterName = String.Empty; } if (XMLData.DisplayName == null) { XMLData.DisplayName = String.Empty; } if (XMLData.Notes == null) { XMLData.Notes = String.Empty; } XMLData.chr_00 = File.Exists(PathChr00); XMLData.chr_11 = File.Exists(PathChr11); XMLData.chr_13 = File.Exists(PathChr13); XMLData.stock_90 = File.Exists(PathStock90); XMLData.chrn_11 = File.Exists(PathChrn11); XMLData.Voice = File.Exists(PathVoice); XMLData.Sound = File.Exists(PathSound); if (XMLData.chr_00) { pictureBox_chr00.BackgroundImage = FileTypes.NUT.BitmapFromPortraitNut(PathChr00); UpdatePictureBoxClickable(pictureBox_chr00); } if (XMLData.chr_11) { pictureBox_chr11.BackgroundImage = FileTypes.NUT.BitmapFromPortraitNut(PathChr11); UpdatePictureBoxClickable(pictureBox_chr11); } if (XMLData.chr_13) { pictureBox_chr13.BackgroundImage = FileTypes.NUT.BitmapFromPortraitNut(PathChr13); UpdatePictureBoxClickable(pictureBox_chr13); } if (XMLData.stock_90) { pictureBox_stock90.BackgroundImage = FileTypes.NUT.BitmapFromPortraitNut(PathStock90); UpdatePictureBoxClickable(pictureBox_stock90); } if (XMLData.chrn_11) { pictureBox_chrn11.BackgroundImage = FileTypes.NUT.BitmapFromPortraitNut(PathChrn11, true); UpdatePictureBoxClickable(pictureBox_chrn11); } textBoxDisplayName.Text = XMLData.DisplayName; checkBoxUseCustomName.Checked = XMLData.UseCustomName; textBoxCustomName.Text = XMLData.CharacterName; textBoxBoxingRing.Text = XMLData.BoxingRingText.Replace("\n", "\r\n"); textBoxCustomName.Enabled = checkBoxUseCustomName.Checked; textBoxBoxingRing.Enabled = checkBoxUseCustomName.Checked; bool hasModels = false; string[] nutFiles = new string[0]; if (Directory.Exists(ModPath + Path.DirectorySeparatorChar + "model")) { if (Directory.Exists(ModPath + Path.DirectorySeparatorChar + "model" + Path.DirectorySeparatorChar + "body")) { nutFiles = Directory.GetFiles(ModPath + Path.DirectorySeparatorChar + "model" + Path.DirectorySeparatorChar + "body", "*.nut", SearchOption.AllDirectories); } if (nutFiles.Length > 0) { hasModels = true; } else { nutFiles = Directory.GetFiles(ModPath + Path.DirectorySeparatorChar + "model", "*.nut", SearchOption.AllDirectories); if (nutFiles.Length > 0) { hasModels = true; } } } if (hasModels) { FileTypes.NUT nut = new FileTypes.NUT(); nut.Read(nutFiles[0]); if (nut.Textures.Count > 0) { XMLData.TextureID = (nut.Textures[0].HashId & 0x0000FF00) >> 8; } XMLData.Haslxx = Directory.Exists(ModPath + Path.DirectorySeparatorChar + "model" + Path.DirectorySeparatorChar + "lxx"); List <string> modelparts = currentFighter.modelParts; if (modelparts != null) { string modelsString = ""; for (int i = 0; i < modelparts.Count; ++i) { if (i != 0) { modelsString += ", "; } modelsString += modelparts[i] + " = " + (Directory.Exists(ModPath + Path.DirectorySeparatorChar + "model" + Path.DirectorySeparatorChar + modelparts[i]) ? "Yes" : "No"); } if (currentFighter.lowPolySlots != DB.Fighter.LowPolySlots.None) { modelsString += ", lxx = " + (XMLData.Haslxx ? "Yes" : "No"); } labelModels.Text = modelsString; } } else { labelModels.Text = "Mod has no models"; XMLData.TextureID = -1; XMLData.MetalModel = CharacterSlotModXML.MetalModelStatus.Works; comboBoxMetalModel.Enabled = false; textBoxTextureID.Enabled = false; buttonTextureIDChange.Enabled = false; } textBoxTextureID.Text = XMLData.TextureID.ToString(); checkBoxWifiSafe.Checked = XMLData.WifiSafe; comboBoxMetalModel.DataSource = new List <String> { "Unknown", "Works", "Errors", "Crashes" }; comboBoxMetalModel.SelectedIndex = (int)XMLData.MetalModel; labelVoicePack.Text = XMLData.Voice ? "Yes" : "No"; labelSoundPack.Text = XMLData.Sound ? "Yes" : "No"; buttonExport_chr00.Enabled = XMLData.chr_00; buttonExport_chr11.Enabled = XMLData.chr_11; buttonExport_chr13.Enabled = XMLData.chr_13; buttonExport_stock90.Enabled = XMLData.stock_90; buttonExport_chrn11.Enabled = XMLData.chrn_11; buttonVoiceRemove.Enabled = XMLData.Voice; buttonSoundRemove.Enabled = XMLData.Sound; //TODO: Portraits textBoxNotes.Text = XMLData.Notes.Replace("\n", "\r\n"); IsInitialized = true; }
public static void MassTextureIdFix() { SmashMod project = SmashProjectManager.instance.CurrentProject; foreach (DB.Fighter fighter in DB.FightersDB.Fighters) { List <ushort> ids = new List <ushort>(); foreach (CharacterSlotMod mod in project.ActiveCharacterSlotMods) { if (mod.CharacterID != fighter.id) { continue; } string ModPath = PathHelper.GetCharacterSlotModPath(fighter.name, mod.FolderName); string PathKami = ModPath + "kamimod.xml"; CharacterSlotModXML xml = Utils.DeserializeXML <CharacterSlotModXML>(PathKami); if (xml == null) { continue; } bool hasModels = false; string[] nutFiles = new string[0]; if (Directory.Exists(ModPath + Path.DirectorySeparatorChar + "model")) { if (Directory.Exists(ModPath + Path.DirectorySeparatorChar + "model" + Path.DirectorySeparatorChar + "body")) { nutFiles = Directory.GetFiles(ModPath + Path.DirectorySeparatorChar + "model" + Path.DirectorySeparatorChar + "body", "*.nut", SearchOption.AllDirectories); } if (nutFiles.Length > 0) { hasModels = true; } else { nutFiles = Directory.GetFiles(ModPath + Path.DirectorySeparatorChar + "model", "*.nut", SearchOption.AllDirectories); if (nutFiles.Length > 0) { hasModels = true; } } } if (hasModels) { FileTypes.NUT nut = new FileTypes.NUT(); nut.Read(nutFiles[0]); if (nut.Textures.Count > 0) { xml.TextureID = (nut.Textures[0].HashId & 0x0000FF00) >> 8; } else { continue; } } else { continue; } if ((xml.TextureID % 4 == 0 && xml.TextureID < 128) || ids.Contains((ushort)xml.TextureID)) { xml.TextureID = 255; while (ids.Contains((ushort)xml.TextureID)) { --xml.TextureID; if (xml.TextureID < 1) { LogHelper.Error(UIStrings.TEXTURE_ID_FIX_NO_IDS_AVAILABLE); break; } } ChangeTextureID(ModPath + "model", fighter.id, (ushort)xml.TextureID); Globals.Utils.SerializeXMLToFile(xml, PathKami); Globals.LogHelper.Info(String.Format("Changed Texture ID of {0} to {1} successfully.", mod.FolderName, xml.TextureID)); } ids.Add((ushort)xml.TextureID); } } }
private static void ChangeTextureID(Mod mod, ushort id) { ushort textureNum = 0; int baseID = 0; List <FileTypes.NUT> nuts = new List <FileTypes.NUT>(); List <FileTypes.NUD> nuds = new List <FileTypes.NUD>(); List <FileTypes.MTA> mtas = new List <FileTypes.MTA>(); for (int i = 0; i < mod.nutFiles.Length; ++i) { FileTypes.NUT n = new FileTypes.NUT(); n.Read(mod.nutFiles[i]); nuts.Add(n); foreach (FileTypes.NutTexture t in n.Textures) { if (!mod.hashChanges.ContainsKey(t.HashId)) { mod.hashChanges.Add(t.HashId, ((int)(t.HashId & 0xFFFF0000) | (id << 8) | textureNum)); ++textureNum; if (baseID == 0) { baseID = t.HashId; } } } } for (int i = 0; i < mod.nudFiles.Length; ++i) { FileTypes.NUD n = new FileTypes.NUD(); n.Read(mod.nudFiles[i]); nuds.Add(n); } for (int i = 0; i < mod.mtaFiles.Length; ++i) { FileTypes.MTA m = new FileTypes.MTA(); m.Read(mod.mtaFiles[i], (short)(baseID >> 16)); mtas.Add(m); } foreach (FileTypes.NUT n in nuts) { List <int> changedOffsets = new List <int>(); foreach (FileTypes.NutTexture t in n.Textures) { if (changedOffsets.Contains(t.HashOffset)) { continue; } changedOffsets.Add(t.HashOffset); n.SourceData.seek(t.HashOffset); n.SourceData.writeInt(mod.hashChanges[t.HashId]); } n.SaveToFile(n.SourceFile); } foreach (FileTypes.NUD n in nuds) { List <int> changedOffsets = new List <int>(); foreach (FileTypes.NUD.MatTexture t in n.allTextures) { if (!mod.hashChanges.ContainsKey(t.hash)) { continue; } if (changedOffsets.Contains(t.hashPos)) { continue; } changedOffsets.Add(t.hashPos); n.Data.seek(t.hashPos); n.Data.writeInt(mod.hashChanges[t.hash]); } n.SaveToFile(n.SourceFile); } foreach (FileTypes.MTA m in mtas) { List <int> changedOffsets = new List <int>(); foreach (FileTypes.MTA.TextureID t in m.ids) { if (!mod.hashChanges.ContainsKey(t.id)) { continue; } if (changedOffsets.Contains(t.id)) { continue; } changedOffsets.Add(t.offset); m.Data.seek(t.offset); m.Data.writeInt(mod.hashChanges[t.id]); } m.SaveToFile(m.SourceFile); } }
public static void CheckForErrors(string directoryName) { string modelPath = directoryName + "model" + Path.DirectorySeparatorChar; directoryName = directoryName.Remove(directoryName.Length - 1, 1); string modName = directoryName.Split(Path.DirectorySeparatorChar).Last(); if (!Directory.Exists(modelPath)) { LogHelper.Info(string.Format(UIStrings.INFO_ERROR_CHECKING_NO_MODELS, modName)); return; } string[] folders = Directory.GetDirectories(modelPath); foreach (string folder in folders) { string foldername = folder.Split(Path.DirectorySeparatorChar).Last(); string modelNut = folder + Path.DirectorySeparatorChar + "model.nut"; string modelNud = folder + Path.DirectorySeparatorChar + "model.nud"; string metalNud = folder + Path.DirectorySeparatorChar + "metal.nud"; if (!File.Exists(modelNut)) { LogHelper.Error(string.Format(UIStrings.ERROR_ERROR_CHECKING_MODEL_NUT_MISSING, modName, foldername)); return; } if (!File.Exists(modelNud)) { LogHelper.Error(string.Format(UIStrings.ERROR_ERROR_CHECKING_MODEL_NUD_MISSING, modName, foldername)); return; } List <int> textureIDs = new List <int>(); List <int> missingTextureIDs = new List <int>(); int[] dummyTextures = { 0x10100000, 0x10080000, 0x10101000, 0x10102000, 0x10040001, 0x10040000 }; string missingTextures = ""; FileTypes.NUT nut = new FileTypes.NUT(); nut.Read(modelNut); bool duplicateTextures = false; foreach (FileTypes.NutTexture t in nut.Textures) { if (!textureIDs.Contains(t.HashId)) { textureIDs.Add(t.HashId); } else { duplicateTextures = true; } } if (duplicateTextures) { LogHelper.Warning(string.Format(UIStrings.WARNING_ERROR_CHECKING_DUPLICATE_TEXTURES, modName, foldername)); } FileTypes.NUD nud = new FileTypes.NUD(); nud.Read(modelNud); foreach (FileTypes.NUD.MatTexture t in nud.allTextures) { if (!textureIDs.Contains(t.hash)) { if (!missingTextureIDs.Contains(t.hash) && !dummyTextures.Contains(t.hash)) { missingTextureIDs.Add(t.hash); } } } if (missingTextureIDs.Count > 0) { foreach (int i in missingTextureIDs) { if (missingTextures.Length > 0) { missingTextures += ", "; } missingTextures += "0x" + i.ToString("x8"); } LogHelper.Error(string.Format(UIStrings.WARNING_ERROR_CHECKING_MODEL_TEXTURES, modName, foldername, missingTextures)); missingTextures = ""; missingTextureIDs.Clear(); } if (!File.Exists(metalNud)) { LogHelper.Warning(string.Format(UIStrings.WARNING_ERROR_CHECKING_METAL_NUD_MISSING, modName, foldername)); return; } nud = new FileTypes.NUD(); nud.Read(metalNud); foreach (FileTypes.NUD.MatTexture t in nud.allTextures) { if (!textureIDs.Contains(t.hash)) { if (!missingTextureIDs.Contains(t.hash) && !dummyTextures.Contains(t.hash)) { missingTextureIDs.Add(t.hash); } } } if (missingTextureIDs.Count > 0) { foreach (int i in missingTextureIDs) { if (missingTextures.Length > 0) { missingTextures += ", "; } missingTextures += "0x" + i.ToString("x8"); } LogHelper.Error(string.Format(UIStrings.WARNING_ERROR_CHECKING_METAL_TEXTURES, modName, foldername, missingTextures)); } } }
private void buttonConfirm_Click(object sender, EventArgs e) { //Validate that the rows are set up correctly bool keepDefaultName = false; if (slotCount < 1) { MessageBox.Show("There are no slots to import!"); return; } for (int i = 0; i < slotCount; ++i) { string rowName = slotColumns[i].textBox_name.Text; if (rowName.Length <= 0) { MessageBox.Show("At least one row is not named! Make sure all the skins have a name before importing."); return; } if (!keepDefaultName) { if (rowName.Contains("New Mod")) { DialogResult result = MessageBox.Show("It looks like at least one row has the default name. Are you sure you want to keep that?", "Default name warning", MessageBoxButtons.YesNo); if (result == DialogResult.Yes) { keepDefaultName = true; } else { return; } } } CharacterSlotModXML xmlTest = Utils.OpenCharacterSlotKamiModFile(_CurrentFighter.name, rowName); if (xmlTest != null) { MessageBox.Show("At least one row shares a name with an already existing mod!"); return; } for (int j = 0; j < i; ++j) { if (slotColumns[j].textBox_name.Text.Equals(rowName)) { MessageBox.Show("At least 2 mods you are importing share the same name. Make sure they are all unique!"); return; } } bool pass = false; if (slotColumns[i].comboBox_body.SelectedIndex != 0) { pass = true; } if (haslxx) { if (slotColumns[i].comboBox_body_lxx.SelectedIndex != 0) { pass = true; } } if (slotColumns[i].comboBox_chr_00.SelectedIndex != 0) { pass = true; } if (slotColumns[i].comboBox_chr_11.SelectedIndex != 0) { pass = true; } if (slotColumns[i].comboBox_chr_13.SelectedIndex != 0) { pass = true; } if (slotColumns[i].comboBox_stock_90.SelectedIndex != 0) { pass = true; } if (slotColumns[i].comboBox_chrn_11.SelectedIndex != 0) { pass = true; } if (slotColumns[i].comboBox_sound.SelectedIndex != 0) { pass = true; } if (slotColumns[i].comboBox_voice.SelectedIndex != 0) { pass = true; } if (slotColumns[i].comboBox_parts != null) { for (int j = 0; j < slotColumns[i].comboBox_parts.Count(); ++j) { if (slotColumns[i].comboBox_parts[j].SelectedIndex != 0) { pass = true; break; } } } if (!pass) { MessageBox.Show("A least one row doesn't have any mod files selected! You can't have a mod with no files!"); return; } } //Import the mod string baseCharacterPath = PathHelper.FolderCharSlotsMods + (_CurrentFighter.name.ToLower()) + Path.DirectorySeparatorChar; for (int i = 0; i < slotCount; ++i) { string baseModPath = baseCharacterPath + slotColumns[i].textBox_name.Text + Path.DirectorySeparatorChar; #region XML File Creation CharacterSlotModXML xml = new CharacterSlotModXML(); xml.DisplayName = slotColumns[i].textBox_name.Text; xml.chr_00 = (slotColumns[i].comboBox_chr_00.SelectedIndex < 1) ? false : true; xml.chr_11 = (slotColumns[i].comboBox_chr_11.SelectedIndex < 1) ? false : true; xml.chr_13 = (slotColumns[i].comboBox_chr_13.SelectedIndex < 1) ? false : true; xml.stock_90 = (slotColumns[i].comboBox_stock_90.SelectedIndex < 1) ? false : true; xml.chrn_11 = (slotColumns[i].comboBox_chrn_11.SelectedIndex < 1) ? false : true; xml.Sound = (slotColumns[i].comboBox_sound.SelectedIndex < 1) ? false : true; xml.Voice = (slotColumns[i].comboBox_voice.SelectedIndex < 1) ? false : true; xml.Haslxx = (_CurrentFighter.lowPolySlots == Fighter.LowPolySlots.None) ? false : (slotColumns[i].comboBox_body_lxx.SelectedIndex < 1 ? false : true); xml.TextureID = -1; //Is recalculated lower xml.MetalModel = CharacterSlotModXML.MetalModelStatus.Works; xml.WifiSafe = true; //Assuming wifi-safe xml.UseCustomName = xml.chrn_11; xml.CharacterName = xml.UseCustomName ? slotColumns[i].textBox_name.Text : ""; #endregion #region Model Files int modelPartsCount = _CurrentFighter.modelParts.Count() - 1; string baseModelPath = baseModPath + "model" + Path.DirectorySeparatorChar; if (slotColumns[i].comboBox_body.SelectedIndex >= 1) { xml.MetalModel = CharacterSlotModXML.MetalModelStatus.Unknown; string foldername = ModelNutDirectories[slotColumns[i].comboBox_body.SelectedIndex - 1]; if (xml.TextureID == -1) { FileTypes.NUT nut = new FileTypes.NUT(); nut.Read(foldername); if (nut.Textures.Count > 0) { xml.TextureID = nut.Textures[0].HashId; } } foldername = foldername.Replace(Path.GetFileName(foldername), string.Empty); Utils.CopyAllValidFilesBetweenDirectories(foldername, baseModelPath + "body" + Path.DirectorySeparatorChar); } for (int k = 0; k < modelPartsCount; ++k) { if (slotColumns[i].comboBox_parts[k].SelectedIndex < 1) { continue; } xml.MetalModel = CharacterSlotModXML.MetalModelStatus.Unknown; string foldername = ModelNutDirectories[slotColumns[i].comboBox_parts[k].SelectedIndex - 1]; if (xml.TextureID == -1) { FileTypes.NUT nut = new FileTypes.NUT(); nut.Read(foldername); if (nut.Textures.Count > 0) { xml.TextureID = nut.Textures[0].HashId; } } foldername = foldername.Replace(Path.GetFileName(foldername), string.Empty); Utils.CopyAllValidFilesBetweenDirectories(foldername, baseModelPath + _CurrentFighter.modelParts[k + 1] + Path.DirectorySeparatorChar); } if (xml.Haslxx) { xml.MetalModel = CharacterSlotModXML.MetalModelStatus.Unknown; string foldername = ModelNutDirectories[slotColumns[i].comboBox_body_lxx.SelectedIndex - 1]; foldername = foldername.Replace(Path.GetFileName(foldername), string.Empty); Utils.CopyAllValidFilesBetweenDirectories(foldername, baseModelPath + "lxx" + Path.DirectorySeparatorChar); } #endregion #region Chr Files if (xml.chr_00 || xml.chr_11 || xml.chr_13 || xml.stock_90 || xml.chrn_11) { string baseChrPath = baseModPath + "chr" + Path.DirectorySeparatorChar; Directory.CreateDirectory(baseChrPath); if (xml.chr_00) { File.Copy(Files_chr_00[slotColumns[i].comboBox_chr_00.SelectedIndex - 1], baseChrPath + "chr_00_" + _CurrentFighter.name + "_XX.nut"); } if (xml.chr_11) { File.Copy(Files_chr_11[slotColumns[i].comboBox_chr_11.SelectedIndex - 1], baseChrPath + "chr_11_" + _CurrentFighter.name + "_XX.nut"); } if (xml.chr_13) { File.Copy(Files_chr_13[slotColumns[i].comboBox_chr_13.SelectedIndex - 1], baseChrPath + "chr_13_" + _CurrentFighter.name + "_XX.nut"); } if (xml.stock_90) { File.Copy(Files_stock_90[slotColumns[i].comboBox_stock_90.SelectedIndex - 1], baseChrPath + "stock_90_" + _CurrentFighter.name + "_XX.nut"); } if (xml.chrn_11) { File.Copy(Files_chrn_11[slotColumns[i].comboBox_chrn_11.SelectedIndex - 1], baseChrPath + "chrn_11_" + _CurrentFighter.name + "_XX.nut"); } } #endregion #region Sound Files if (xml.Sound || xml.Voice) { string baseSoundPath = baseModPath + "sound" + Path.DirectorySeparatorChar; Directory.CreateDirectory(baseSoundPath); if (xml.Sound) { File.Copy(Files_Sound_Nus3bank[slotColumns[i].comboBox_sound.SelectedIndex - 1], baseSoundPath + "snd_se_" + (string.IsNullOrEmpty(_CurrentFighter.nameSoundPack) ? _CurrentFighter.name : _CurrentFighter.nameSoundPack) + "_cxx.nus3bank"); } if (xml.Voice) { File.Copy(Files_Voice_Nus3bank[slotColumns[i].comboBox_voice.SelectedIndex - 1], baseSoundPath + "snd_vc_" + (string.IsNullOrEmpty(_CurrentFighter.nameSoundPack) ? _CurrentFighter.name : _CurrentFighter.nameSoundPack) + "_cxx.nus3bank"); } } #endregion Utils.SerializeXMLToFile <CharacterSlotModXML>(xml, baseModPath + "kamimod.xml"); LogHelper.Info(String.Format("Mod {0} imported successfully!", slotColumns[i].textBox_name.Text)); } importSuccessful = true; this.Close(); }