Beispiel #1
0
        /// <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;
                    }
                }
            }
        }
Beispiel #2
0
        /// <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.
        }
Beispiel #4
0
        /// <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;
                    }
                }
            }
        }
Beispiel #6
0
        /// <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.
        }