/// <summary> /// The TonyAI 2.3+ sets bits of data by reading it directly from /// Spells.2da - such data is no longer stored in HenchSpells.2da. This /// funct clears those bits auto right after HenchSpells.2da loads. /// </summary> /// <remarks>The controls are disabled on the tabpage. /// /// /// Is based on /// <c><see cref="SetInfoVersion_spells()">SetInfoVersion_spells()</see></c>. /// This funct, however, ASSUMES that nothing in the spell-list has /// changed yet; this funct bypasses a bunch of differ-stuff that /// <c>SetInfoVersion_spells()</c> doesn't.</remarks> void UpdateSpellInfo() { Spell spell; SpellChanged spellchanged; int spellinfo0, spellinfo; int total = Spells.Count; for (int id = 0; id != total; ++id) { spell = Spells[id]; spellinfo0 = spell.spellinfo; spellinfo = spellinfo0 & ~(hc.HENCH_SPELL_INFO_CONCENTRATION_FLAG | hc.HENCH_SPELL_INFO_SPELL_LEVEL_MASK); if (spellinfo != spellinfo0) { if (id == Id) { HenchControl.SetMasterText(spellinfo.ToString()); // firing the TextChanged event takes care of it. } else { spellchanged = new SpellChanged(); spellchanged.targetinfo = spell.targetinfo; spellchanged.effectweight = spell.effectweight; spellchanged.effecttypes = spell.effecttypes; spellchanged.damageinfo = spell.damageinfo; spellchanged.savetype = spell.savetype; spellchanged.savedctype = spell.savedctype; spellchanged.spellinfo = spellinfo; SpellsChanged[id] = spellchanged; // check it spell.differ = control_Spells.SpellDiffer(spell, spellchanged); Spells[id] = spell; Tree.Nodes[id].ForeColor = Color.Crimson; } } } }
/// <summary> /// Handles the GlobalApply it. Applies all altered data to their /// <c>structs</c>. /// </summary> /// <param name="sender"> /// <list type="bullet"> /// <item><c><see cref="it_ApplyGlobal"/></c></item> /// <item><c><see cref="it_Save"/></c></item> /// <item><c><see cref="it_Saveas"/></c></item> /// </list></param> /// <param name="e"></param> /// <remarks>See <c><see cref="Click_apply()">Click_apply()</see></c> to /// apply altered data to only the selected <c>struct</c>.</remarks> void Click_applyGlobal(object sender, EventArgs e) { SetTitleText(); // TitleText will be written again (properly) by Write2daFile() if saved. it_ApplyGlobal.Enabled = false; int total; switch (Type) { case Type2da.Spells: { Spell spell; total = Spells.Count; for (int id = 0; id != total; ++id) { spell = Spells[id]; if (spell.differ != control_Spells.bit_clean) { spell.differ = control_Spells.bit_clean; spell.isChanged = true; // this flag will be cleared by Write2daFile() SpellChanged spellchanged = SpellsChanged[id]; spell.spellinfo = spellchanged.spellinfo; spell.targetinfo = spellchanged.targetinfo; spell.effectweight = spellchanged.effectweight; spell.effecttypes = spellchanged.effecttypes; spell.damageinfo = spellchanged.damageinfo; spell.savetype = spellchanged.savetype; spell.savedctype = spellchanged.savedctype; Spells[id] = spell; SpellsChanged.Remove(id); if (id == Id) // is currently selected tree-node { HenchControl.SetResetColor(DefaultForeColor); AfterSelect_node(null, null); // refresh all displayed data for the current spell jic } Tree.Nodes[id].ForeColor = Color.Blue; } } break; } case Type2da.Racial: { Race race; total = Races.Count; for (int id = 0; id != total; ++id) { race = Races[id]; if (race.differ != control_Racial.bit_clean) { race.differ = control_Racial.bit_clean; race.isChanged = true; // this flag will be cleared by Write2daFile() RaceChanged racechanged = RacesChanged[id]; race.flags = racechanged.flags; race.feat1 = racechanged.feat1; race.feat2 = racechanged.feat2; race.feat3 = racechanged.feat3; race.feat4 = racechanged.feat4; race.feat5 = racechanged.feat5; Races[id] = race; RacesChanged.Remove(id); if (id == Id) // is currently selected tree-node { HenchControl.SetResetColor(DefaultForeColor); AfterSelect_node(null, null); // refresh all displayed data for the current race jic } Tree.Nodes[id].ForeColor = Color.Blue; } } break; } case Type2da.Classes: { Class @class; total = Classes.Count; for (int id = 0; id != total; ++id) { @class = Classes[id]; if (@class.differ != control_Classes.bit_clean) { @class.differ = control_Classes.bit_clean; @class.isChanged = true; // this flag will be cleared by Write2daFile() ClassChanged classchanged = ClassesChanged[id]; @class.flags = classchanged.flags; @class.feat1 = classchanged.feat1; @class.feat2 = classchanged.feat2; @class.feat3 = classchanged.feat3; @class.feat4 = classchanged.feat4; @class.feat5 = classchanged.feat5; @class.feat6 = classchanged.feat6; @class.feat7 = classchanged.feat7; @class.feat8 = classchanged.feat8; @class.feat9 = classchanged.feat9; @class.feat10 = classchanged.feat10; @class.feat11 = classchanged.feat11; Classes[id] = @class; ClassesChanged.Remove(id); if (id == Id) // is currently selected tree-node { HenchControl.SetResetColor(DefaultForeColor); AfterSelect_node(null, null); // refresh all displayed data for the current class jic } Tree.Nodes[id].ForeColor = Color.Blue; } } break; } } }
/// <summary> /// Handles <c>TextChanged</c> event on the DamageInfo page. /// </summary> /// <param name="sender"><c><see cref="DamageInfo_text"/></c></param> /// <param name="e"></param> void TextChanged_di(object sender, EventArgs e) { // NOTE: TextChanged needs to fire when HenchSpells loads in order // to set the checkboxes and dropdown-fields. // // 'BypassDiffer' is set true since this does not need to go through // creating and deleting each SpellChanged-struct (since nothing has // changed yet OnLoad of the 2da-file). // // 'BypassDiffer' is also set true by AfterSelect_node() since the // Spell-structs already contain proper diff-data. int damageinfo; if (Int32.TryParse(DamageInfo_text.Text, out damageinfo)) { if (!he.BypassDiffer) { Spell spell = he.Spells[he.Id]; SpellChanged spellchanged; if (spell.differ != bit_clean) { spellchanged = he.SpellsChanged[he.Id]; } else { spellchanged = new SpellChanged(); spellchanged.spellinfo = spell.spellinfo; spellchanged.targetinfo = spell.targetinfo; spellchanged.effectweight = spell.effectweight; spellchanged.effecttypes = spell.effecttypes; spellchanged.savetype = spell.savetype; spellchanged.savedctype = spell.savedctype; } spellchanged.damageinfo = damageinfo; spell.differ = SpellDiffer(spell, spellchanged); he.Spells[he.Id] = spell; Color color; if (spell.differ != bit_clean) { he.SpellsChanged[he.Id] = spellchanged; color = Color.Crimson; } else { he.SpellsChanged.Remove(he.Id); if (spell.isChanged) { color = Color.Blue; } else { color = DefaultForeColor; } } _he.SetNodeColor(color); } he.PrintCurrent(damageinfo, DamageInfo_hex, DamageInfo_bin); int differ = he.Spells[he.Id].differ; if ((differ & bit_damageinfo) != 0) { DamageInfo_reset.ForeColor = Color.Crimson; } else { DamageInfo_reset.ForeColor = DefaultForeColor; } state_DamageInfo(damageinfo); if (si_IsMaster.Checked) { // the 'si_Subspell3' textchanged handler can change the value // and shoot it back here si_Subspell3.Text = DamageInfo_text.Text; } else { // else let the value pass unhindered BypassSubspell = true; si_Subspell3.Text = DamageInfo_text.Text; BypassSubspell = false; SetSpellLabelText(si_SubspellLabel3, damageinfo); } _he.EnableApplys(differ != bit_clean); } // else TODO: error dialog here. }
/// <summary> /// Handler for the "apply changed data to currently selected /// spell/race/class" button. /// </summary> /// <param name="sender">bu_Apply</param> /// <param name="e"></param> /// <remarks>See /// <c><see cref="Click_applyGlobal()">Click_applyGlobal()</see></c> to /// apply all altered data globally.</remarks> void Click_apply(object sender, EventArgs e) { SetTitleText(); switch (Type) { case Type2da.Spells: { Spell spell = Spells[Id]; if (spell.differ != control_Spells.bit_clean) { spell.differ = control_Spells.bit_clean; spell.isChanged = true; SpellChanged spellchanged = SpellsChanged[Id]; spell.spellinfo = spellchanged.spellinfo; spell.targetinfo = spellchanged.targetinfo; spell.effectweight = spellchanged.effectweight; spell.effecttypes = spellchanged.effecttypes; spell.damageinfo = spellchanged.damageinfo; spell.savetype = spellchanged.savetype; spell.savedctype = spellchanged.savedctype; Spells[Id] = spell; SpellsChanged.Remove(Id); HenchControl.SetResetColor(DefaultForeColor); AfterSelect_node(null, null); // refresh all displayed data for the current spell jic } if (Spells[Id].isChanged) // this goes outside the SpellsChanged check above because uh color goes screwy if not. { Tree.SelectedNode.ForeColor = Color.Blue; } else // I doubt this ever *needs* to run ... but safety. { Tree.SelectedNode.ForeColor = DefaultForeColor; } break; } case Type2da.Racial: { Race race = Races[Id]; if (race.differ != control_Racial.bit_clean) { race.differ = control_Racial.bit_clean; race.isChanged = true; RaceChanged racechanged = RacesChanged[Id]; race.flags = racechanged.flags; race.feat1 = racechanged.feat1; race.feat2 = racechanged.feat2; race.feat3 = racechanged.feat3; race.feat4 = racechanged.feat4; race.feat5 = racechanged.feat5; Races[Id] = race; RacesChanged.Remove(Id); HenchControl.SetResetColor(DefaultForeColor); AfterSelect_node(null, null); // refresh all displayed data for the current node jic } if (Races[Id].isChanged) // this goes outside the RacesChanged check above because uh color goes screwy if not. { Tree.SelectedNode.ForeColor = Color.Blue; } else // I doubt this ever *needs* to run ... but safety. { Tree.SelectedNode.ForeColor = DefaultForeColor; } break; } case Type2da.Classes: { Class @class = Classes[Id]; if (@class.differ != control_Classes.bit_clean) { @class.differ = control_Classes.bit_clean; @class.isChanged = true; ClassChanged classchanged = ClassesChanged[Id]; @class.flags = classchanged.flags; @class.feat1 = classchanged.feat1; @class.feat2 = classchanged.feat2; @class.feat3 = classchanged.feat3; @class.feat4 = classchanged.feat4; @class.feat5 = classchanged.feat5; @class.feat6 = classchanged.feat6; @class.feat7 = classchanged.feat7; @class.feat8 = classchanged.feat8; @class.feat9 = classchanged.feat9; @class.feat10 = classchanged.feat10; @class.feat11 = classchanged.feat11; Classes[Id] = @class; ClassesChanged.Remove(Id); HenchControl.SetResetColor(DefaultForeColor); AfterSelect_node(null, null); // refresh all displayed data for the current node jic } if (Classes[Id].isChanged) // this goes outside the ClassesChanged check above because uh color goes screwy if not. { Tree.SelectedNode.ForeColor = Color.Blue; } else // I doubt this ever *needs* to run ... but safety. { Tree.SelectedNode.ForeColor = DefaultForeColor; } break; } } }
/// <summary> /// This funct is used only for /// <c><see cref="Click_clearCoreAiVersion()">Click_clearCoreAiVersion()</see></c>. /// </summary> /// <param name="str"></param> /// <param name="all"></param> /// <remarks>Used to be a helper for <c>Click_setCoreAiVersion()</c>.</remarks> void SetInfoVersion_spells(string str, bool all) { Spell spell; SpellChanged spellchanged; int spellinfo0, spellinfo, differ; bool dirty; int ver = Int32.Parse(str) << HENCH_SPELL_INFO_VERSION_SHIFT; // the return from the dialog. int total = Spells.Count; for (int id = 0; id != total; ++id) { spell = Spells[id]; if (dirty = ((spell.differ & control_Spells.bit_spellinfo) != 0)) { spellinfo0 = SpellsChanged[id].spellinfo; } else if (all || spell.isChanged) { spellinfo0 = spell.spellinfo; } else { continue; // ignore clean spell-structs if !all } if (spellinfo0 == 0) { continue; // if spellinfo is blank leave it blank } if ((spellinfo0 & ~hc.HENCH_SPELL_INFO_VERSION_MASK) == 0) // force-clear the version if the rest of spellinfo is blank { spellinfo = 0; } else { spellinfo = ((spellinfo0 & ~hc.HENCH_SPELL_INFO_VERSION_MASK) | ver); } if (spellinfo != spellinfo0) { if (id == Id) { HenchControl.SetMasterText(spellinfo.ToString()); // firing the TextChanged event takes care of it. } else { if (dirty) { spellchanged = SpellsChanged[id]; } else { spellchanged = new SpellChanged(); spellchanged.targetinfo = spell.targetinfo; spellchanged.effectweight = spell.effectweight; spellchanged.effecttypes = spell.effecttypes; spellchanged.damageinfo = spell.damageinfo; spellchanged.savetype = spell.savetype; spellchanged.savedctype = spell.savedctype; } spellchanged.spellinfo = spellinfo; // check it differ = control_Spells.SpellDiffer(spell, spellchanged); spell.differ = differ; Spells[id] = spell; Color color; if (differ != control_Spells.bit_clean) { SpellsChanged[id] = spellchanged; color = Color.Crimson; } else { SpellsChanged.Remove(id); if (spell.isChanged) { color = Color.Blue; } else { color = DefaultForeColor; } } Tree.Nodes[id].ForeColor = color; } } } }
/// <summary> /// Handles <c>TextChanged</c> event on the SaveDCType page. /// </summary> /// <param name="sender"><c><see cref="SaveDCType_text"/></c></param> /// <param name="e"></param> void TextChanged_dc(object sender, EventArgs e) { // NOTE: TextChanged needs to fire when HenchSpells loads in order // to set the checkboxes and dropdown-fields. // // 'BypassDiffer' is set true since this does not need to go through // creating and deleting each SpellChanged-struct (since nothing has // changed yet OnLoad of the 2da-file). // // 'BypassDiffer' is also set true by AfterSelect_node() since the // Spell-structs already contain proper diff-data. int savedctype; if (Int32.TryParse(SaveDCType_text.Text, out savedctype)) { if (!he.BypassDiffer) { Spell spell = he.Spells[he.Id]; SpellChanged spellchanged; if (spell.differ != bit_clean) { spellchanged = he.SpellsChanged[he.Id]; } else { spellchanged = new SpellChanged(); spellchanged.spellinfo = spell.spellinfo; spellchanged.targetinfo = spell.targetinfo; spellchanged.effectweight = spell.effectweight; spellchanged.effecttypes = spell.effecttypes; spellchanged.damageinfo = spell.damageinfo; spellchanged.savetype = spell.savetype; } spellchanged.savedctype = savedctype; spell.differ = SpellDiffer(spell, spellchanged); he.Spells[he.Id] = spell; Color color; if (spell.differ != bit_clean) { he.SpellsChanged[he.Id] = spellchanged; color = Color.Crimson; } else { he.SpellsChanged.Remove(he.Id); if (spell.isChanged) { color = Color.Blue; } else { color = DefaultForeColor; } } _he.SetNodeColor(color); } he.PrintCurrent(savedctype, SaveDCType_hex, SaveDCType_bin); int differ = he.Spells[he.Id].differ; if ((differ & bit_savedctype) != 0) { SaveDCType_reset.ForeColor = Color.Crimson; } else { SaveDCType_reset.ForeColor = DefaultForeColor; } state_SaveDcType(savedctype); if (si_IsMaster.Checked) { // the 'si_Subspell5' textchanged handler can change the value // and shoot it back here si_Subspell5.Text = SaveDCType_text.Text; } else { // else let the value pass unhindered BypassSubspell = true; si_Subspell5.Text = SaveDCType_text.Text; BypassSubspell = false; SetSpellLabelText(si_SubspellLabel5, savedctype); } // The DC must be less than 1000 for the adjustor-buttons to appear. // 1000+ thar be AI-constants that are set using the DC-combobox. savedc_up.Enabled = (savedctype < 999); // disallow incrementing up to 1000 savedc_dn.Enabled = (savedctype < 1000); // 1000 is a CoreAI constant that shall be accessed in the dropdown // TODO: should probably disable if savedctype is negative. dc_ArmorCheckGrp.Enabled = (savedctype & ~HENCH_SAVEDCTYPE_ARMORCHECK_MASK) == 0; _he.EnableApplys(differ != bit_clean); } // else TODO: error dialog here. }
/// <summary> /// Handles <c>TextChanged</c> event on the TargetInfo page. /// </summary> /// <param name="sender"><c><see cref="TargetInfo_text"/></c></param> /// <param name="e"></param> void TextChanged_ti(object sender, EventArgs e) { // NOTE: TextChanged needs to fire when HenchSpells loads in order // to set the checkboxes and dropdown-fields. // // 'BypassDiffer' is set true since this does not need to go through // creating and deleting each SpellChanged-struct (since nothing has // changed yet OnLoad of the 2da-file). // // 'BypassDiffer' is also set true by AfterSelect_node() since the // Spell-structs already contain proper diff-data. int targetinfo; if (Int32.TryParse(TargetInfo_text.Text, out targetinfo)) { if (!he.BypassDiffer) { Spell spell = he.Spells[he.Id]; SpellChanged spellchanged; if (spell.differ != bit_clean) { spellchanged = he.SpellsChanged[he.Id]; } else { spellchanged = new SpellChanged(); spellchanged.spellinfo = spell.spellinfo; spellchanged.effectweight = spell.effectweight; spellchanged.effecttypes = spell.effecttypes; spellchanged.damageinfo = spell.damageinfo; spellchanged.savetype = spell.savetype; spellchanged.savedctype = spell.savedctype; } spellchanged.targetinfo = targetinfo; spell.differ = SpellDiffer(spell, spellchanged); he.Spells[he.Id] = spell; Color color; if (spell.differ != bit_clean) { he.SpellsChanged[he.Id] = spellchanged; color = Color.Crimson; } else { he.SpellsChanged.Remove(he.Id); if (spell.isChanged) { color = Color.Blue; } else { color = DefaultForeColor; } } _he.SetNodeColor(color); } he.PrintCurrent(targetinfo, TargetInfo_hex, TargetInfo_bin); int differ = he.Spells[he.Id].differ; if ((differ & bit_targetinfo) != 0) { TargetInfo_reset.ForeColor = Color.Crimson; } else { TargetInfo_reset.ForeColor = DefaultForeColor; } state_TargetInfo(targetinfo); if (si_IsMaster.Checked) { // the 'si_Subspell1' textchanged handler can change the value // and shoot it back here si_Subspell1.Text = TargetInfo_text.Text; } else { // else let the value pass unhindered BypassSubspell = true; si_Subspell1.Text = TargetInfo_text.Text; BypassSubspell = false; SetSpellLabelText(si_SubspellLabel1, targetinfo); } // set DamageInfo colors based on SpellInfo spelltype and TargetInfo scaledeffect switch (si_co_Spelltype.SelectedIndex) // (spellinfo & hc.HENCH_SPELL_INFO_SPELL_TYPE_MASK) { case hc.HENCH_SPELL_INFO_SPELL_TYPE_ATTACK: case hc.HENCH_SPELL_INFO_SPELL_TYPE_HEAL: case hc.HENCH_SPELL_INFO_SPELL_TYPE_HARM: case hc.HENCH_SPELL_INFO_SPELL_TYPE_ARCANE_ARCHER: case hc.HENCH_SPELL_INFO_SPELL_TYPE_DRAGON_BREATH: case hc.HENCH_SPELL_INFO_SPELL_TYPE_DOMINATE: if (ti_ScaledEffect.Checked) { GroupColor(di_BeneficialGrp, Color.LimeGreen); GroupColor(di_DetrimentalGrp, Color.Crimson); } else { GroupColor(di_BeneficialGrp, Color.Crimson); GroupColor(di_DetrimentalGrp, Color.LimeGreen); } break; } _he.EnableApplys(differ != bit_clean); } // else TODO: error dialog here. }
/// <summary> /// Handles <c>TextChanged</c> event on the EffectWeight page. /// </summary> /// <param name="sender"><c><see cref="EffectWeight_text"/></c></param> /// <param name="e"></param> void TextChanged_ew(object sender, EventArgs e) { // NOTE: TextChanged needs to fire when HenchSpells loads in order // to set the checkboxes and dropdown-fields. // // EffectWeight doesn't have checkboxes or dropdown-fields ... // // 'BypassDiffer' is set true since this does not need to go through // creating and deleting each SpellChanged-struct (since nothing has // changed yet OnLoad of the 2da-file). // // 'BypassDiffer' is also set true by AfterSelect_node() since the // Spell-structs already contain proper diff-data. float effectweight; if (Single.TryParse(EffectWeight_text.Text, out effectweight)) { if (!he.BypassDiffer) { Spell spell = he.Spells[he.Id]; SpellChanged spellchanged; if (spell.differ != bit_clean) { spellchanged = he.SpellsChanged[he.Id]; } else { spellchanged = new SpellChanged(); spellchanged.spellinfo = spell.spellinfo; spellchanged.targetinfo = spell.targetinfo; spellchanged.effecttypes = spell.effecttypes; spellchanged.damageinfo = spell.damageinfo; spellchanged.savetype = spell.savetype; spellchanged.savedctype = spell.savedctype; } spellchanged.effectweight = effectweight; spell.differ = SpellDiffer(spell, spellchanged); he.Spells[he.Id] = spell; Color color; if (spell.differ != bit_clean) { he.SpellsChanged[he.Id] = spellchanged; color = Color.Crimson; } else { he.SpellsChanged.Remove(he.Id); if (spell.isChanged) { color = Color.Blue; } else { color = DefaultForeColor; } } _he.SetNodeColor(color); } int differ = he.Spells[he.Id].differ; if ((differ & bit_effectweight) != 0) { EffectWeight_reset.ForeColor = Color.Crimson; } else { EffectWeight_reset.ForeColor = DefaultForeColor; } _he.EnableApplys(differ != bit_clean); } // else TODO: error dialog here. }
/// <summary> /// Handles <c>TextChanged</c> event on the SpellInfo page. /// </summary> /// <param name="sender"><c><see cref="SpellInfo_text"/></c></param> /// <param name="e"></param> void TextChanged_si(object sender, EventArgs e) { // NOTE: TextChanged needs to fire when HenchSpells loads in order // to set the checkboxes and dropdown-fields. // // 'BypassDiffer' is set true since this does not need to go through // creating and deleting each SpellChanged-struct (since nothing has // changed yet OnLoad of the 2da-file). // // 'BypassDiffer' is also set true by AfterSelect_node() since the // Spell-structs already contain proper diff-data. int spellinfo; if (Int32.TryParse(SpellInfo_text.Text, out spellinfo)) { if (!he.BypassDiffer) { // ensure that spellinfo has a CoreAI version // although strictly speaking I believe that GetSpellInfo() // will gracefully handle spell-data that has no version set. // if (!he.BypassInfoVersion && spellinfo != 0) // { // int ver = (spellinfo & hc.HENCH_SPELL_INFO_VERSION_MASK); // // if (ver == 0) // insert the default spell-version if a version # doesn't exist // { // spellinfo |= hc.HENCH_SPELL_INFO_VERSION; // default info-version in 'hench_i0_generic' // SpellInfo_text.Text = spellinfo.ToString(); // return; // re-fire this funct. // } // // if (ver == spellinfo) // clear the spell-version if that's the only data in spellinfo // { // // TODO: I suppose the spell-version should be stored (if not the default version #) ... // // so it can be re-inserted identically (if/after user clears all spellinfo bits). // // spellinfo = 0; // SpellInfo_text.Text = spellinfo.ToString(); // return; // re-fire this funct. // } // } Spell spell = he.Spells[he.Id]; SpellChanged spellchanged; if (spell.differ != bit_clean) { spellchanged = he.SpellsChanged[he.Id]; } else { spellchanged = new SpellChanged(); spellchanged.targetinfo = spell.targetinfo; spellchanged.effectweight = spell.effectweight; spellchanged.effecttypes = spell.effecttypes; spellchanged.damageinfo = spell.damageinfo; spellchanged.savetype = spell.savetype; spellchanged.savedctype = spell.savedctype; } spellchanged.spellinfo = spellinfo; spell.differ = SpellDiffer(spell, spellchanged); he.Spells[he.Id] = spell; Color color; if (spell.differ != bit_clean) { he.SpellsChanged[he.Id] = spellchanged; color = Color.Crimson; } else { he.SpellsChanged.Remove(he.Id); if (spell.isChanged) { color = Color.Blue; } else { color = DefaultForeColor; } } _he.SetNodeColor(color); } he.PrintCurrent(spellinfo, SpellInfo_hex, SpellInfo_bin); int differ = he.Spells[he.Id].differ; if ((differ & bit_spellinfo) != 0) { SpellInfo_reset.ForeColor = Color.Crimson; } else { SpellInfo_reset.ForeColor = DefaultForeColor; } state_SpellInfo(spellinfo); SetDetrimentalBeneficial(); si_SubspellsGrp.Enabled = si_IsMaster.Checked; // PrintInfoVersion_spell(spellinfo); _he.EnableApplys(differ != bit_clean); } // else TODO: error dialog here. }