/// <summary> /// Overrides the <c>FormClosing</c> handler. /// </summary> /// <param name="e"></param> protected override void OnFormClosing(FormClosingEventArgs e) { if (Scripter != null && !Scripter.IsDisposed) { Scripter.Close(); } if (e.CloseReason != CloseReason.WindowsShutDown) { if (isChanged()) { string info = "Data has changed." + Environment.NewLine + Environment.NewLine + "Okay to exit ..."; using (var ib = new infobox(" Warning", info, "yessir", "no")) e.Cancel = ib.ShowDialog(this) != DialogResult.OK; } if (!e.Cancel) { recent_write(); } } base.OnFormClosing(e); }
/// <summary> /// Handles FileMenu open file event. /// </summary> /// <param name="sender"><c><see cref="it_Open"/></c></param> /// <param name="e"></param> void Click_open(object sender, EventArgs e) { if (isChanged()) { string info = "Data has changed." + Environment.NewLine + Environment.NewLine + "Okay to exit ..."; using (var ib = new infobox(" Warning", info, "yessir", "no")) { if (ib.ShowDialog(this) != DialogResult.OK) { return; } } } using (var ofd = new OpenFileDialog()) { ofd.AutoUpgradeEnabled = false; // loL fu.net ofd.Title = "Select a Hench*.2da file"; ofd.Filter = "2da files (*.2da)|*.2da|All files (*.*)|*.*"; if (ofd.ShowDialog(this) == DialogResult.OK) { _pfe = ofd.FileName; Load_file(); } } }
// /// <summary> // /// Invokes and handles the SetCoreAiVersion inputbox via the Edit. // /// </summary> // /// <param name="sender"></param> // /// <param name="e"></param> // /// <remarks>The version is not really the version of the CoreAI. It's // /// the version of the data of each entry. Apparently it can be updated // /// IG (after info-data has already been cached to the module-object) // /// such that that stale data will be bypassed in favor of the new data. // /// But I haven't looked into it thoroughly.</remarks> // void Click_setCoreAiVersion(object sender, EventArgs e) // { // switch (Type) // { // case Type2da.Spells: // SetInfoVersion_spells(); // // it_ApplyGlobal.Enabled = SpellsChanged.Count != 0; // it_GotoChanged.Enabled = SpellsChanged.Count != 0 || SpareChange(); // break; // // case Type2da.Racial: // SetInfoVersion_racial(); // // it_ApplyGlobal.Enabled = RacesChanged.Count != 0; // it_GotoChanged.Enabled = RacesChanged.Count != 0 || SpareChange(); // break; // // case Type2da.Classes: // SetInfoVersion_classes(); // // it_ApplyGlobal.Enabled = ClassesChanged.Count != 0; // it_GotoChanged.Enabled = ClassesChanged.Count != 0 || SpareChange(); // break; // } // } /// <summary> /// IMPORTANT: This is an interim function that forcefully clears the /// InfoVersion bits. InfoVersion is obsolete in TonyAI 2.3+ - the bits /// have been repurposed. /// </summary> /// <param name="sender"><c><see cref="it_ClearCoreAI"/></c></param> /// <param name="e"></param> /// <remarks>This is implemented only to allow a user to pseudo-update /// his/her TonyAI 2.2 Hench*.2das to be compatible with 2.3+. But the /// repurposed bits would still need to be accounted for ....</remarks> void Click_clearCoreAiVersion(object sender, EventArgs e) { string info2da; switch (Type) { case Type2da.Spells: info2da = "SpellInfo"; break; default: info2da = "Flags"; break; } string info = "This clears the bits @ 0xFF000000 on the " + info2da + " page." + Environment.NewLine + Environment.NewLine + "Are you sure you know what you're doing ..."; using (var ib = new infobox(" Alert", info, "yessir", "no")) { if (ib.ShowDialog(this) == DialogResult.OK) { BypassInfoVersion = true; switch (Type) { case Type2da.Spells: SetInfoVersion_spells("0", true); it_ApplyGlobal.Enabled = SpellsChanged.Count != 0; it_GotoChanged.Enabled = SpellsChanged.Count != 0 || hasSpareChange(); break; case Type2da.Racial: SetInfoVersion_racial("0", true); it_ApplyGlobal.Enabled = RacesChanged.Count != 0; it_GotoChanged.Enabled = RacesChanged.Count != 0 || hasSpareChange(); break; case Type2da.Classes: SetInfoVersion_classes("0", true); it_ApplyGlobal.Enabled = ClassesChanged.Count != 0; it_GotoChanged.Enabled = ClassesChanged.Count != 0 || hasSpareChange(); break; } BypassInfoVersion = false; } } HenchControl.SelectResetButton(); }
/// <summary> /// Handles FileMenu close program event. /// </summary> /// <param name="sender"><c><see cref="it_Quit"/></c></param> /// <param name="e"></param> void Click_quit(object sender, EventArgs e) { if (isChanged()) { string info = "Data has changed." + Environment.NewLine + Environment.NewLine + "Okay to exit ..."; using (var ib = new infobox(" Warning", info, "yessir", "no")) { if (ib.ShowDialog(this) != DialogResult.OK) { return; } } } Close(); }
/// <summary> /// Opens a 2da-file from the Recent-files list. Removes the item from /// the list if it was not found on disk. /// </summary> /// <param name="sender">its on the Recent menu</param> /// <param name="e"></param> void Click_recent(object sender, EventArgs e) { if (isChanged()) { string info = "Data has changed." + Environment.NewLine + Environment.NewLine + "Okay to exit ..."; using (var ib = new infobox(" Warning", info, "yessir", "no")) { if (ib.ShowDialog(this) != DialogResult.OK) { return; } } } _pfe = (sender as ToolStripMenuItem).Text; Load_file(); }
/// <summary> /// Handles FileMenu save file event. /// </summary> /// <param name="sender"> /// <list type="bullet"> /// <item><c><see cref="it_Save"/></c></item> /// <item><c><see cref="it_Saveas"/></c></item> /// </list></param> /// <param name="e"></param> void Click_save(object sender, EventArgs e) { if (!hasDirtyData()) { if (sender == it_Saveas) { _pfe = _pfeT; _pfeT = String.Empty; recent_add(); } Write2daFile(); } else { const string info = "There is data that has been altered but not applied."; using (var ib = new infobox(" Attention", info, "just save", "cancel", "apply + save")) { switch (ib.ShowDialog(this)) { case DialogResult.Cancel: _pfeT = String.Empty; break; case DialogResult.Retry: Click_applyGlobal(sender, e); goto case DialogResult.OK; case DialogResult.OK: if (sender == it_Saveas) { _pfe = _pfeT; _pfeT = String.Empty; recent_add(); } Write2daFile(); break; } } } }
/// <summary> /// Checks 2da rows for double-quote <c>chars</c> and displays an error /// if any are found. /// </summary> /// <param name="rows">an array of 2da rows</param> /// <param name="he">parent for the <c><see cref="infobox"/></c></param> /// <returns><c>true</c> if a double-quote char is found</returns> /// <remarks>WARNING: This editor does *not* handle quotation marks /// around 2da fields.</remarks> static bool hasDoubleQuote(string[] rows, IWin32Window he) { foreach (string row in rows) { foreach (char character in row) { if (character == '"') { const string info = "The 2da-file contains double-quotes. Although that can be" + " valid in a 2da-file this editor is not coded to cope." + " Format the 2da-file to not use double-quotes if you want" + " to open it here."; using (var ib = new infobox(" Error", info, "drat")) ib.ShowDialog(he); return(true); } } } return(false); }
/// <summary> /// Shows the About box. /// </summary> /// <param name="sender"><c><see cref="it_About"/></c></param> /// <param name="e"></param> void Click_about(object sender, EventArgs e) { DateTime dt = Assembly.GetExecutingAssembly().GetLinkerTime(); string info = String.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:yyyy MMM d} {0:HH}:{0:mm}:{0:ss} {0:zzz}", dt); // what a f*****g pain in the ass! AssemblyName an = Assembly.GetExecutingAssembly().GetName(); string ver = "Ver " + an.Version.Major + "." + an.Version.Minor + "." + an.Version.Build + "." + an.Version.Revision; #if DEBUG ver += " - debug"; #else ver += " - release"; #endif ver += Environment.NewLine + Environment.NewLine + info; using (var ib = new infobox(" About - nwn2_ai_2da_editor", ver, "yarr")) ib.ShowDialog(this); }
/// <summary> /// Determines which file to load: /// <list type="bullet"> /// <item>HenchSpells</item> /// <item>HenchRacial</item> /// <item>HenchClasses</item> /// </list> /// </summary> /// <remarks>The fullpath of the file must already be stored in /// <c><see cref="_pfe"/></c>. /// /// /// <c>pfe</c> stands for path_file_extension.</remarks> void Load_file() { if (File.Exists(_pfe)) // safety. { // deal with recent-files first // Recents won't be written to disk unless a file "recent.cfg" // already exists in the appdir. recent_add(); // read and load the 2da second string[] rows = File.ReadAllLines(_pfe); if (!hasDoubleQuote(rows, this)) { SuspendLayout(); BypassDiffer = true; bool error = true; for (int i = 0; i != rows.Length; ++i) { rows[i] = rows[i].Trim(); } // resolve what 2da is being loaded -> // // HenchSpells.2da colheads // Label SpellInfo TargetInfo EffectWeight EffectTypes DamageInfo SaveType SaveDCType // // HenchRacial.2da colheads // Label Flags FeatSpell1 FeatSpell2 FeatSpell3 FeatSpell4 FeatSpell5 // // HenchClasses.2da colheads // Label Flags FeatSpell1 FeatSpell2 FeatSpell3 FeatSpell4 FeatSpell5 FeatSpell6 FeatSpell7 FeatSpell8 FeatSpell9 FeatSpell10 FeatSpell11 string[] fields = rows[2].Split(new char[0], StringSplitOptions.RemoveEmptyEntries); if (fields.Length > 5) { if (fields[0].ToLowerInvariant() != "label") { switch (fields.Length) { case 7: // henchspells w/out "Label" col if (fields[0].ToLowerInvariant() == "spellinfo" && fields[1].ToLowerInvariant() == "targetinfo" && fields[2].ToLowerInvariant() == "effectweight" && fields[3].ToLowerInvariant() == "effecttypes" && fields[4].ToLowerInvariant() == "damageinfo" && fields[5].ToLowerInvariant() == "savetype" && fields[6].ToLowerInvariant() == "savedctype") { hasLabels = false; Load_HenchSpells(rows); error = false; } break; case 6: // henchracial w/out "Label" col if (fields[0].ToLowerInvariant() == "flags" && fields[1].ToLowerInvariant() == "featspell1" && fields[2].ToLowerInvariant() == "featspell2" && fields[3].ToLowerInvariant() == "featspell3" && fields[4].ToLowerInvariant() == "featspell4" && fields[5].ToLowerInvariant() == "featspell5") { hasLabels = false; Load_HenchRacial(rows); error = false; } break; case 12: // henchclasses w/out "Label" col if (fields[0].ToLowerInvariant() == "flags" && fields[1].ToLowerInvariant() == "featspell1" && fields[2].ToLowerInvariant() == "featspell2" && fields[3].ToLowerInvariant() == "featspell3" && fields[4].ToLowerInvariant() == "featspell4" && fields[5].ToLowerInvariant() == "featspell5" && fields[6].ToLowerInvariant() == "featspell6" && fields[7].ToLowerInvariant() == "featspell7" && fields[8].ToLowerInvariant() == "featspell8" && fields[9].ToLowerInvariant() == "featspell9" && fields[10].ToLowerInvariant() == "featspell10" && fields[11].ToLowerInvariant() == "featspell11") { hasLabels = false; Load_HenchClasses(rows); error = false; } break; } } else // fields[0] == "label" { switch (fields.Length) { case 7: // henchracial w/ "Label" col if (fields[1].ToLowerInvariant() == "flags" && fields[2].ToLowerInvariant() == "featspell1" && fields[3].ToLowerInvariant() == "featspell2" && fields[4].ToLowerInvariant() == "featspell3" && fields[5].ToLowerInvariant() == "featspell4" && fields[6].ToLowerInvariant() == "featspell5") { hasLabels = true; Load_HenchRacial(rows); error = false; } break; case 8: // henchspells w/ "Label" col if (fields[1].ToLowerInvariant() == "spellinfo" && fields[2].ToLowerInvariant() == "targetinfo" && fields[3].ToLowerInvariant() == "effectweight" && fields[4].ToLowerInvariant() == "effecttypes" && fields[5].ToLowerInvariant() == "damageinfo" && fields[6].ToLowerInvariant() == "savetype" && fields[7].ToLowerInvariant() == "savedctype") { hasLabels = true; Load_HenchSpells(rows); error = false; } break; case 13: // henchclasses w/ "Label" col if (fields[1].ToLowerInvariant() == "flags" && fields[2].ToLowerInvariant() == "featspell1" && fields[3].ToLowerInvariant() == "featspell2" && fields[4].ToLowerInvariant() == "featspell3" && fields[5].ToLowerInvariant() == "featspell4" && fields[6].ToLowerInvariant() == "featspell5" && fields[7].ToLowerInvariant() == "featspell6" && fields[8].ToLowerInvariant() == "featspell7" && fields[9].ToLowerInvariant() == "featspell8" && fields[10].ToLowerInvariant() == "featspell9" && fields[11].ToLowerInvariant() == "featspell10" && fields[12].ToLowerInvariant() == "featspell11") { hasLabels = true; Load_HenchClasses(rows); error = false; } break; } } } if (!error) // TODO: That should be predicated on Load_Hench*() not throwing an exception. { SetTitleText(true); Tree.SelectedNode = Tree.Nodes[0]; // that should be done auto but doesn't always happen. // if (InfoVersionUpdate) // no InfoVersion in TonyAI 2.3+ // { // InfoVersionUpdate = false; // MessageBox.Show("InfoVersion(s) have been updated.", // " InfoVersion update", // MessageBoxButtons.OK, // MessageBoxIcon.Information, // MessageBoxDefaultButton.Button1); // } BypassDiffer = false; // if (HenchSpells.2da) clear bits for // - Concentration // - SpellLevel // because TonyAI 2.3+ sets those auto. if (!error && Type == Type2da.Spells) { UpdateSpellInfo(); // that needs to be done after 'BypassDiffer' ... } } else { ResumeLayout(); const string info = "That file does not appear to be HenchSpells, HenchRacial, or HenchClasses.2da"; using (var ib = new infobox(" Error", info, "err")) ib.ShowDialog(this); BypassDiffer = false; } } } }