public static void Add(this TreeView treView, MartialArt input, ContextMenuStrip strip)
        {
            if (treView == null)
            {
                return;
            }
            TreeNode objTargetNode = treView.Nodes[input.IsQuality ? 1 : 0];

            if (objTargetNode != null)
            {
                TreeNode newNode = new TreeNode();
                newNode.Text             = input.DisplayName;
                newNode.Tag              = input.InternalId;
                newNode.ContextMenuStrip = strip;
                if (!string.IsNullOrEmpty(input.Notes))
                {
                    newNode.ForeColor = Color.SaddleBrown;
                }
                newNode.ToolTipText = CommonFunctions.WordWrap(input.Notes, 100);

                foreach (MartialArtAdvantage objAdvantage in input.Advantages)
                {
                    TreeNode objAdvantageNode = new TreeNode();
                    objAdvantageNode.Text = objAdvantage.DisplayName;
                    objAdvantageNode.Tag  = objAdvantage.InternalId;
                    newNode.Nodes.Add(objAdvantageNode);
                    newNode.Expand();
                }

                objTargetNode.Nodes.Add(newNode);
                objTargetNode.Expand();
            }
        }
 public frmSelectMartialArtTechnique(Character objCharacter, MartialArt objMartialArt)
 {
     InitializeComponent();
     LanguageManager.TranslateWinForm(GlobalOptions.Language, this);
     _objCharacter  = objCharacter;
     _objMartialArt = objMartialArt;
     // Load the Martial Art information.
     _xmlBaseChummerNode = XmlManager.Load("martialarts.xml").GetFastNavigator().SelectSingleNode("/chummer");
 }
 public frmSelectMartialArtTechnique(Character objCharacter, MartialArt objMartialArt)
 {
     InitializeComponent();
     LanguageManager.TranslateWinForm(GlobalOptions.Language, this);
     _objCharacter  = objCharacter;
     _objMartialArt = objMartialArt;
     // Load the Martial Art information.
     _xmlDocument = XmlManager.Load("martialarts.xml");
 }
Example #4
0
        public SelectMartialArtTechnique(Character objCharacter, MartialArt objMartialArt)
        {
            InitializeComponent();
            this.UpdateLightDarkMode();
            this.TranslateWinForm();
            _objCharacter  = objCharacter ?? throw new ArgumentNullException(nameof(objCharacter));
            _objMartialArt = objMartialArt ?? throw new ArgumentNullException(nameof(objMartialArt));
            // Load the Martial Art information.
            _xmlBaseChummerNode = _objCharacter.LoadDataXPath("martialarts.xml").SelectSingleNodeAndCacheExpression("/chummer");
            // Populate the Martial Art Technique list.
            XPathNavigator xmlMartialArtNode = _xmlBaseChummerNode?.SelectSingleNode("martialarts/martialart[name = " + _objMartialArt.Name.CleanXPath() + ']');

            if (xmlMartialArtNode != null)
            {
                if (!xmlMartialArtNode.NodeExists("alltechniques"))
                {
                    foreach (XPathNavigator xmlTechnique in xmlMartialArtNode.SelectAndCacheExpression("techniques/technique"))
                    {
                        string strTechniqueName = xmlTechnique.Value;
                        if (_objMartialArt.Techniques.All(x => x.Name != strTechniqueName))
                        {
                            _setAllowedTechniques.Add(strTechniqueName);
                        }
                    }
                }
                else if (_objMartialArt.Techniques.Count == 0)
                {
                    //TODO: Support for allowing all techniques > 0.
                    foreach (XPathNavigator xmlTechnique in _xmlBaseChummerNode.Select("techniques/technique[(" + _objCharacter.Settings.BookXPath() + ")]"))
                    {
                        string strTechnique = xmlTechnique.Value;
                        if (_objMartialArt.Techniques.Any(x => x.Name == strTechnique))
                        {
                            continue;
                        }
                        string strTechniqueName = xmlTechnique.SelectSingleNodeAndCacheExpression("name")?.Value;
                        if (string.IsNullOrEmpty(strTechniqueName))
                        {
                            continue;
                        }
                        _setAllowedTechniques.Add(strTechniqueName);
                    }
                }
            }
        }
        public frmSelectMartialArtTechnique(Character objCharacter, MartialArt objMartialArt)
        {
            InitializeComponent();
            this.UpdateLightDarkMode();
            this.TranslateWinForm();
            _objCharacter  = objCharacter ?? throw new ArgumentNullException(nameof(objCharacter));
            _objMartialArt = objMartialArt ?? throw new ArgumentNullException(nameof(objMartialArt));
            // Load the Martial Art information.
            _xmlBaseChummerNode = _objCharacter.LoadDataXPath("martialarts.xml").CreateNavigator().SelectSingleNode("/chummer");
            // Populate the Martial Art Technique list.
            XPathNavigator xmlMartialArtNode = _xmlBaseChummerNode?.SelectSingleNode("martialarts/martialart[name = \"" + _objMartialArt.Name + "\"]");

            if (xmlMartialArtNode != null)
            {
                if (!xmlMartialArtNode.NodeExists("alltechniques"))
                {
                    foreach (XPathNavigator xmlTechnique in xmlMartialArtNode.Select("techniques/technique"))
                    {
                        string strTechniqueName = xmlTechnique.Value;
                        if (_objMartialArt.Techniques.All(x => x.Name != strTechniqueName))
                        {
                            _setAllowedTechniques.Add(strTechniqueName);
                        }
                    }
                }
                else if (_objMartialArt.Techniques.Count == 0)
                {
                    //TODO: Support for allowing all techniques  > 0.
                    string            strFilter         = '(' + _objCharacter.Options.BookXPath() + ')';
                    XPathNodeIterator objTechniquesList = _xmlBaseChummerNode.Select("techniques/technique[" + strFilter + "]");

                    foreach (XPathNavigator xmlTechnique in objTechniquesList)
                    {
                        if (_objMartialArt.Techniques.Any(x => x.Name == xmlTechnique.Value) || xmlTechnique.SelectSingleNode("name") == null)
                        {
                            continue;
                        }
                        _setAllowedTechniques.Add(xmlTechnique.SelectSingleNode("name")?.Value);
                    }
                }
            }
        }
        public frmSelectMartialArtTechnique(Character objCharacter, MartialArt objMartialArt)
        {
            InitializeComponent();
            LanguageManager.TranslateWinForm(GlobalOptions.Language, this);
            _objCharacter  = objCharacter;
            _objMartialArt = objMartialArt;
            // Load the Martial Art information.
            _xmlBaseChummerNode = XmlManager.Load("martialarts.xml").GetFastNavigator().SelectSingleNode("/chummer");
            // Populate the Martial Art Tecnnique list.
            XPathNavigator xmlMartialArtNode = _xmlBaseChummerNode?.SelectSingleNode("martialarts/martialart[name = \"" + _objMartialArt.Name + "\"]");

            if (xmlMartialArtNode != null)
            {
                if (!xmlMartialArtNode.NodeExists("alltechniques"))
                {
                    foreach (XPathNavigator xmlTechnique in xmlMartialArtNode.Select("techniques/technique"))
                    {
                        string strTechniqueName = xmlTechnique.Value;
                        if (_objMartialArt.Techniques.All(x => x.Name != strTechniqueName))
                        {
                            _setAllowedTechniques.Add(strTechniqueName);
                        }
                    }
                }
                else if (_objMartialArt.Techniques.Count == 0)
                {
                    //TODO: Support for allowing all techniques  > 0.
                    string            strFilter         = '(' + _objCharacter.Options.BookXPath() + ')';
                    XPathNodeIterator objTechniquesList = _xmlBaseChummerNode.Select("techniques/technique[" + strFilter + "]");

                    foreach (XPathNavigator xmlTechnique in objTechniquesList)
                    {
                        if (_objMartialArt.Techniques.Any(x => x.Name == xmlTechnique.Value) || xmlTechnique.SelectSingleNode("name") == null)
                        {
                            continue;
                        }
                        _setAllowedTechniques.Add(xmlTechnique.SelectSingleNode("name")?.Value);
                    }
                }
            }
        }
        public frmSelectMartialArtTechnique(Character objCharacter, MartialArt objMartialArt)
        {
            InitializeComponent();
            LanguageManager.TranslateWinForm(GlobalOptions.Language, this);
            _objCharacter  = objCharacter;
            _objMartialArt = objMartialArt;
            // Load the Martial Art information.
            _xmlBaseChummerNode = XmlManager.Load("martialarts.xml").GetFastNavigator().SelectSingleNode("/chummer");
            // Populate the Martial Art Tecnnique list.
            XPathNavigator xmlMartialArtNode = _xmlBaseChummerNode?.SelectSingleNode("martialarts/martialart[name = \"" + _objMartialArt.Name + "\"]");

            if (xmlMartialArtNode != null && !xmlMartialArtNode.NodeExists("alltechniques"))
            {
                foreach (XPathNavigator xmlTechnique in xmlMartialArtNode.Select("techniques/technique"))
                {
                    string strTechniqueName = xmlTechnique.Value;
                    if (_objMartialArt.Techniques.All(x => x.Name != strTechniqueName))
                    {
                        _setAllowedTechniques.Add(strTechniqueName);
                    }
                }
            }
        }
Example #8
0
        /// <summary>
        /// Locate a Martial Art Advantage within the character's Martial Arts.
        /// </summary>
        /// <param name="strGuid">InternalId of the Martial Art Advantage to find.</param>
        /// <param name="lstMartialArts">List of Martial Arts to search.</param>
        /// <param name="objFoundMartialArt">MartialArt the Advantage was found in.</param>
        public MartialArtAdvantage FindMartialArtAdvantage(string strGuid, List<MartialArt> lstMartialArts, out MartialArt objFoundMartialArt)
        {
            foreach (MartialArt objArt in lstMartialArts)
            {
                foreach (MartialArtAdvantage objAdvantage in objArt.Advantages)
                {
                    if (objAdvantage.InternalId == strGuid)
                    {
                        objFoundMartialArt = objArt;
                        return objAdvantage;
                    }
                }
            }

            objFoundMartialArt = null;
            return null;
        }
Example #9
0
        private void cmdDeleteMartialArt_Click(object sender, EventArgs e)
        {
            try
            {
                if (treMartialArts.SelectedNode.Level == 0)
                    return;

                if (!_objFunctions.ConfirmDelete(LanguageManager.Instance.GetString("Message_DeleteMartialArt")))
                    return;

                if (treMartialArts.SelectedNode.Level == 1)
                {
                    if (treMartialArts.SelectedNode.Parent == treMartialArts.Nodes[0])
                    {
                        // Characters may only have 2 Maneuvers per Martial Art Rating (start at -2 since we're potentially removing one).
                        int intTotalRating = -2;
                        foreach (MartialArt objCharacterMartialArt in _objCharacter.MartialArts)
                            intTotalRating += objCharacterMartialArt.Rating * 2;

                        if (treMartialArts.Nodes[1].Nodes.Count > intTotalRating && !_objCharacter.IgnoreRules)
                        {
                            MessageBox.Show(LanguageManager.Instance.GetString("Message_MartialArtManeuverLimit"), LanguageManager.Instance.GetString("MessageTitle_MartialArtManeuverLimit"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                            return;
                        }

                        // Delete the selected Martial Art.
                        MartialArt objMartialArt = _objFunctions.FindMartialArt(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts);

                        // Remove the Improvements for any Advantages for the Martial Art that is being removed.
                        foreach (MartialArtAdvantage objAdvantage in objMartialArt.Advantages)
                        {
                            _objImprovementManager.RemoveImprovements(Improvement.ImprovementSource.MartialArtAdvantage, objAdvantage.InternalId);
                        }

                        _objCharacter.MartialArts.Remove(objMartialArt);
                        treMartialArts.SelectedNode.Remove();
                    }
                    else
                    {
                        // Delete the selected Martial Art Maenuver.
                        MartialArtManeuver objManeuver = _objFunctions.FindMartialArtManeuver(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArtManeuvers);

                        _objCharacter.MartialArtManeuvers.Remove(objManeuver);
                        treMartialArts.SelectedNode.Remove();
                    }

                    CalculateBP();
                    UpdateCharacterInfo();

                    _blnIsDirty = true;
                    UpdateWindowTitle();
                }
                if (treMartialArts.SelectedNode.Level == 2)
                {
                    // Find the selected Advantage object.
                    MartialArt objSelectedMartialArt = new MartialArt(_objCharacter);
                    MartialArtAdvantage objSelectedAdvantage = _objFunctions.FindMartialArtAdvantage(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts, out objSelectedMartialArt);

                    _objImprovementManager.RemoveImprovements(Improvement.ImprovementSource.MartialArtAdvantage, objSelectedAdvantage.InternalId);
                    treMartialArts.SelectedNode.Remove();

                    objSelectedMartialArt.Advantages.Remove(objSelectedAdvantage);

                    CalculateBP();
                    UpdateCharacterInfo();

                    _blnIsDirty = true;
                    UpdateWindowTitle();
                }
            }
            catch
            {
            }
        }
Example #10
0
        private void cmdAddMartialArt_Click(object sender, EventArgs e)
        {
            // Make sure that adding a new Martial Art will not take the user over 35 BP for Positive Qualities.
            if (!_objCharacter.IgnoreRules)
            {
                // Count the BP used by Positive Qualities.
                int intBP = 0;
                foreach (Quality objQuality in _objCharacter.Qualities)
                {
                    if (objQuality.Type == QualityType.Positive && objQuality.ContributeToLimit)
                        intBP += objQuality.Cost;
                }
                // Include free Positive Quality Improvements.
                intBP -= _objImprovementManager.ValueOf(Improvement.ImprovementType.FreePositiveQualities);

                if (_objCharacter.BuildMethod == CharacterBuildMethod.Karma)
                    intBP *= _objOptions.KarmaQuality;

                // Add 5 which is the cost for a new Martial Art at Rating 1.
                if (_objCharacter.BuildMethod == CharacterBuildMethod.BP)
                    intBP += 5;
                else
                    intBP += (5 * _objOptions.KarmaQuality);

                foreach (MartialArt objCharacterMartialArt in _objCharacter.MartialArts)
                {
                    if (_objCharacter.BuildMethod == CharacterBuildMethod.BP)
                        intBP += objCharacterMartialArt.Rating * 5;
                    else
                        intBP += objCharacterMartialArt.Rating * 5 * _objOptions.KarmaQuality;
                }

                if (_objCharacter.BuildMethod == CharacterBuildMethod.BP)
                {
                    if (intBP > 35 && !_objCharacter.IgnoreRules)
                    {
                        MessageBox.Show(LanguageManager.Instance.GetString("Message_PositiveQualityLimit").Replace("{0}", "35 " + LanguageManager.Instance.GetString("String_BP")), LanguageManager.Instance.GetString("MessageTitle_PositiveQualityLimit"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
                }
                else
                {
                    if (intBP > 70 && !_objCharacter.IgnoreRules)
                    {
                        MessageBox.Show(LanguageManager.Instance.GetString("Message_PositiveQualityLimit").Replace("{0}", "70 " + LanguageManager.Instance.GetString("String_Karma")), LanguageManager.Instance.GetString("MessageTitle_PositiveQualityLimit"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
                }
            }

            frmSelectMartialArt frmPickMartialArt = new frmSelectMartialArt(_objCharacter);
            frmPickMartialArt.ShowDialog(this);

            if (frmPickMartialArt.DialogResult == DialogResult.Cancel)
                return;

            // Open the Martial Arts XML file and locate the selected piece.
            XmlDocument objXmlDocument = XmlManager.Instance.Load("martialarts.xml");

            XmlNode objXmlArt = objXmlDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + frmPickMartialArt.SelectedMartialArt + "\"]");

            TreeNode objNode = new TreeNode();
            MartialArt objMartialArt = new MartialArt(_objCharacter);
            objMartialArt.Create(objXmlArt, objNode, _objCharacter);
            _objCharacter.MartialArts.Add(objMartialArt);

            objNode.ContextMenuStrip = cmsMartialArts;

            treMartialArts.Nodes[0].Nodes.Add(objNode);
            treMartialArts.Nodes[0].Expand();

            treMartialArts.SelectedNode = objNode;

            _objFunctions.SortTree(treMartialArts);
            CalculateBP();

            _blnIsDirty = true;
            UpdateWindowTitle();
        }
Example #11
0
        private void treMartialArts_AfterSelect(object sender, TreeViewEventArgs e)
        {
            try
            {
                // The Rating NUD is only enabled if a Martial Art is currently selected.
                if (treMartialArts.SelectedNode.Level == 1 && treMartialArts.SelectedNode.Parent == treMartialArts.Nodes[0])
                {
                    MartialArt objMartialArt = _objFunctions.FindMartialArt(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts);

                    _blnSkipRefresh = true;
                    nudMartialArtsRating.Enabled = true;
                    nudMartialArtsRating.Value = objMartialArt.Rating;
                    string strBook = _objOptions.LanguageBookShort(objMartialArt.Source);
                    string strPage = objMartialArt.Page;
                    lblMartialArtSource.Text = strBook + " " + strPage;
                    tipTooltip.SetToolTip(lblMartialArtSource, _objOptions.LanguageBookLong(objMartialArt.Source) + " page " + objMartialArt.Page);
                    _blnSkipRefresh = false;
                }
                else
                    nudMartialArtsRating.Enabled = false;

                // Display the Martial Art Advantage information.
                if (treMartialArts.SelectedNode.Level == 2)
                {
                    MartialArt objMartialArt = new MartialArt(_objCharacter);
                    MartialArtAdvantage objAdvantage = _objFunctions.FindMartialArtAdvantage(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts, out objMartialArt);

                    string strBook = _objOptions.LanguageBookShort(objMartialArt.Source);
                    string strPage = objMartialArt.Page;
                    lblMartialArtSource.Text = strBook + " " + strPage;
                    tipTooltip.SetToolTip(lblMartialArtSource, _objOptions.LanguageBookLong(objMartialArt.Source) + " page " + objMartialArt.Page);
                }

                // Display the Maneuver information.
                if (treMartialArts.SelectedNode.Level == 1 && treMartialArts.SelectedNode.Parent == treMartialArts.Nodes[1])
                {
                    MartialArtManeuver objManeuver = _objFunctions.FindMartialArtManeuver(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArtManeuvers);

                    string strBook = _objOptions.LanguageBookShort(objManeuver.Source);
                    string strPage = objManeuver.Page;
                    lblMartialArtSource.Text = strBook + " " + strPage;
                    tipTooltip.SetToolTip(lblMartialArtSource, _objOptions.LanguageBookLong(objManeuver.Source) + " page " + objManeuver.Page);
                }
            }
            catch
            {
                nudMartialArtsRating.Enabled = false;
            }
        }
Example #12
0
        private void cmdAddMartialArt_Click(object sender, EventArgs e)
        {
            frmSelectMartialArt frmPickMartialArt = new frmSelectMartialArt(_objCharacter);
            frmPickMartialArt.ShowDialog(this);

            if (frmPickMartialArt.DialogResult == DialogResult.Cancel)
                return;

            // Open the Martial Arts XML file and locate the selected piece.
            XmlDocument objXmlDocument = XmlManager.Instance.Load("martialarts.xml");

            XmlNode objXmlArt = objXmlDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + frmPickMartialArt.SelectedMartialArt + "\"]");

            TreeNode objNode = new TreeNode();
            MartialArt objMartialArt = new MartialArt(_objCharacter);
            objMartialArt.Create(objXmlArt, objNode, _objCharacter);
            _objCharacter.MartialArts.Add(objMartialArt);

            objNode.ContextMenuStrip = cmsMartialArts;

            treMartialArts.Nodes[0].Nodes.Add(objNode);
            treMartialArts.Nodes[0].Expand();

            treMartialArts.SelectedNode = objNode;

            treMartialArts.SortCustom();
            CalculateBP();
            CalculateNuyen();

            _blnIsDirty = true;
            UpdateWindowTitle();
        }
Example #13
0
        /// <summary>
        /// Add a PACKS Kit to the character.
        /// </summary>
        public void AddPACKSKit()
        {
            frmSelectPACKSKit frmPickPACKSKit = new frmSelectPACKSKit(_objCharacter);
            frmPickPACKSKit.ShowDialog(this);

            bool blnCreateChildren = true;

            // If the form was canceled, don't do anything.
            if (frmPickPACKSKit.DialogResult == DialogResult.Cancel)
                return;

            XmlDocument objXmlDocument = XmlManager.Instance.Load("packs.xml");

            // Do not create child items for Gear if the chosen Kit is in the Custom category since these items will contain the exact plugins desired.
            if (frmPickPACKSKit.SelectedCategory == "Custom")
                blnCreateChildren = false;

            XmlNode objXmlKit = objXmlDocument.SelectSingleNode("/chummer/packs/pack[name = \"" + frmPickPACKSKit.SelectedKit + "\" and category = \"" + frmPickPACKSKit.SelectedCategory + "\"]");
            // Update Qualities.
            if (objXmlKit["qualities"] != null)
            {
                XmlDocument objXmlQualityDocument = XmlManager.Instance.Load("qualities.xml");

                // Positive Qualities.
                foreach (XmlNode objXmlQuality in objXmlKit.SelectNodes("qualities/positive/quality"))
                {
                    XmlNode objXmlQualityNode = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQuality.InnerText + "\"]");

                    TreeNode objNode = new TreeNode();
                    List<Weapon> objWeapons = new List<Weapon>();
                    List<TreeNode> objWeaponNodes = new List<TreeNode>();
                    Quality objQuality = new Quality(_objCharacter);
                    string strForceValue = "";

                    if (objXmlQuality.Attributes["select"] != null)
                        strForceValue = objXmlQuality.Attributes["select"].InnerText;

                    objQuality.Create(objXmlQualityNode, _objCharacter, QualitySource.Selected, objNode, objWeapons, objWeaponNodes, strForceValue);
                    _objCharacter.Qualities.Add(objQuality);

                    treQualities.Nodes[0].Nodes.Add(objNode);
                    treQualities.Nodes[0].Expand();

                    // Add any created Weapons to the character.
                    foreach (Weapon objWeapon in objWeapons)
                        _objCharacter.Weapons.Add(objWeapon);

                    // Create the Weapon Node if one exists.
                    foreach (TreeNode objWeaponNode in objWeaponNodes)
                    {
                        objWeaponNode.ContextMenuStrip = cmsWeapon;
                        treWeapons.Nodes[0].Nodes.Add(objWeaponNode);
                        treWeapons.Nodes[0].Expand();
                    }
                }

                // Negative Qualities.
                foreach (XmlNode objXmlQuality in objXmlKit.SelectNodes("qualities/negative/quality"))
                {
                    XmlNode objXmlQualityNode = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQuality.InnerText + "\"]");

                    TreeNode objNode = new TreeNode();
                    List<Weapon> objWeapons = new List<Weapon>();
                    List<TreeNode> objWeaponNodes = new List<TreeNode>();
                    Quality objQuality = new Quality(_objCharacter);
                    string strForceValue = "";

                    if (objXmlQuality.Attributes["select"] != null)
                        strForceValue = objXmlQuality.Attributes["select"].InnerText;

                    objQuality.Create(objXmlQualityNode, _objCharacter, QualitySource.Selected, objNode, objWeapons, objWeaponNodes, strForceValue);
                    _objCharacter.Qualities.Add(objQuality);

                    treQualities.Nodes[1].Nodes.Add(objNode);
                    treQualities.Nodes[1].Expand();

                    // Add any created Weapons to the character.
                    foreach (Weapon objWeapon in objWeapons)
                        _objCharacter.Weapons.Add(objWeapon);

                    // Create the Weapon Node if one exists.
                    foreach (TreeNode objWeaponNode in objWeaponNodes)
                    {
                        objWeaponNode.ContextMenuStrip = cmsWeapon;
                        treWeapons.Nodes[0].Nodes.Add(objWeaponNode);
                        treWeapons.Nodes[0].Expand();
                    }
                }
            }

            // Update Attributes.
            if (objXmlKit["attributes"] != null)
            {
                // Reset all Attributes back to 1 so we don't go over any BP limits.
                nudBOD.Value = nudBOD.Minimum;
                nudAGI.Value = nudAGI.Minimum;
                nudREA.Value = nudREA.Minimum;
                nudSTR.Value = nudSTR.Minimum;
                nudCHA.Value = nudCHA.Minimum;
                nudINT.Value = nudINT.Minimum;
                nudLOG.Value = nudLOG.Minimum;
                nudWIL.Value = nudWIL.Minimum;
                nudEDG.Value = nudEDG.Minimum;
                nudMAG.Value = nudMAG.Minimum;
                nudRES.Value = nudRES.Minimum;
                foreach (XmlNode objXmlAttribute in objXmlKit["attributes"])
                {
                    // The Attribute is calculated as given value - (6 - Metatype Maximum) so that each Metatype has the values from the file adjusted correctly.
                    switch (objXmlAttribute.Name)
                    {
                        case "bod":
                            nudBOD.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.BOD.MetatypeMaximum);
                            break;
                        case "agi":
                            nudAGI.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.AGI.MetatypeMaximum);
                            break;
                        case "rea":
                            nudREA.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.REA.MetatypeMaximum);
                            break;
                        case "str":
                            nudSTR.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.STR.MetatypeMaximum);
                            break;
                        case "cha":
                            nudCHA.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.CHA.MetatypeMaximum);
                            break;
                        case "int":
                            nudINT.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.INT.MetatypeMaximum);
                            break;
                        case "log":
                            nudLOG.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.LOG.MetatypeMaximum);
                            break;
                        case "wil":
                            nudWIL.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.WIL.MetatypeMaximum);
                            break;
                        case "mag":
                            nudMAG.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.MAG.MetatypeMaximum);
                            break;
                        case "res":
                            nudRES.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.RES.MetatypeMaximum);
                            break;
                        default:
                            nudEDG.Value = Convert.ToInt32(objXmlAttribute.InnerText) - (6 - _objCharacter.EDG.MetatypeMaximum);
                            break;
                    }
                }
            }

            // Update Skills.
            if (objXmlKit["skills"] != null)
            {
                // Active Skills.
                foreach (XmlNode objXmlSkill in objXmlKit.SelectNodes("skills/skill"))
                {
                    if (objXmlSkill["name"].InnerText.Contains("Exotic"))
                    {
                        int i = panActiveSkills.Controls.Count;
                        Skill objSkill = new Skill(_objCharacter);

                        SkillControl objSkillControl = new SkillControl(_objCharacter);
                        objSkillControl.SkillObject = objSkill;
                        objSkillControl.Width = 510;

                        // Attach an EventHandler for the RatingChanged and SpecializationChanged Events.
                        objSkillControl.RatingChanged += objActiveSkill_RatingChanged;
                        objSkillControl.SpecializationChanged += objSkill_SpecializationChanged;
                        objSkillControl.SkillName = objXmlSkill["name"].InnerText;

                        switch (objXmlSkill["name"].InnerText)
                        {
                            case "Exotic Ranged Weapon":
                            case "Exotic Melee Weapon":
                                objSkill.Attribute = "AGI";
                                objSkillControl.SkillCategory = "Combat Active";
                                objSkill.Default = true;
                                break;
                            default:
                                objSkill.Attribute = "REA";
                                objSkillControl.SkillCategory = "Vehicle Active";
                                objSkill.Default = false;
                                break;
                        }
                        objSkill.ExoticSkill = true;
                        _objCharacter.Skills.Add(objSkill);


						if (_objCharacter.IgnoreRules)
						{
							objSkillControl.SkillRatingMaximum = 12;
						}
						else
						{
							objSkillControl.SkillRatingMaximum = 6;
						}

						// Make sure it's not going above the maximum number.
						if (Convert.ToInt32(objXmlSkill["rating"].InnerText) > objSkillControl.SkillRatingMaximum)
                            objSkillControl.SkillRating = objSkillControl.SkillRatingMaximum;
                        else
                            objSkillControl.SkillRating = Convert.ToInt32(objXmlSkill["rating"].InnerText);

                        if (objXmlSkill["spec"] != null)
                            objSkillControl.SkillSpec = objXmlSkill["spec"].InnerText;
                        else
                            objSkillControl.SkillSpec = "";

                        // Set the SkillControl's Location since scrolling the Panel causes it to actually change the child Controls' Locations.
                        objSkillControl.Location = new Point(0, objSkillControl.Height * i + panActiveSkills.AutoScrollPosition.Y);
                        panActiveSkills.Controls.Add(objSkillControl);
                    }
                    else
                    {
                        // Find the correct Skill Control.
                        SkillControl objSkillControl = new SkillControl(_objCharacter);
                        foreach (SkillControl objControl in panActiveSkills.Controls)
                        {
                            if (objControl.SkillName == objXmlSkill["name"].InnerText)
                            {
                                objSkillControl = objControl;
                                break;
                            }
                        }

                        // Make sure it's not going above the maximum number.
                        if (Convert.ToInt32(objXmlSkill["rating"].InnerText) > objSkillControl.SkillRatingMaximum)
                            objSkillControl.SkillRating = objSkillControl.SkillRatingMaximum;
                        else
                            objSkillControl.SkillRating = Convert.ToInt32(objXmlSkill["rating"].InnerText);

                        if (objXmlSkill["spec"] != null)
                            objSkillControl.SkillSpec = objXmlSkill["spec"].InnerText;
                        else
                            objSkillControl.SkillSpec = "";
                    }
                }

                // Skill Groups.
                foreach (XmlNode objXmlGroup in objXmlKit.SelectNodes("skills/skillgroup"))
                {
                    // Find the correct SkillGroupControl.
                    SkillGroupControl objSkillGroupControl = new SkillGroupControl(_objCharacter.Options, _objCharacter);
                    foreach (SkillGroupControl objControl in panSkillGroups.Controls)
                    {
                        if (objControl.GroupName == objXmlGroup["name"].InnerText)
                        {
                            objSkillGroupControl = objControl;
                            break;
                        }
                    }

                    // Make sure it's not going above the maximum number.
                    if (Convert.ToInt32(objXmlGroup["base"].InnerText) > objSkillGroupControl.GroupRatingMaximum)
                    {
                        objSkillGroupControl.BaseRating = objSkillGroupControl.GroupRatingMaximum;
                        objSkillGroupControl.KarmaRating = 0;
                    }
                    else if (Convert.ToInt32(objXmlGroup["base"].InnerText) + Convert.ToInt32(objXmlGroup["karma"].InnerText) > objSkillGroupControl.GroupRatingMaximum)
                    {
                        objSkillGroupControl.BaseRating = Convert.ToInt32(objXmlGroup["base"].InnerText);
                        objSkillGroupControl.KarmaRating = objSkillGroupControl.GroupRatingMaximum - objSkillGroupControl.BaseRating;
                    }
                    else
                    {
                        objSkillGroupControl.BaseRating = Convert.ToInt32(objXmlGroup["base"].InnerText);
                        objSkillGroupControl.KarmaRating = Convert.ToInt32(objXmlGroup["karma"].InnerText);
                    }
                }
            }

            // Update Knowledge Skills.
            if (objXmlKit["knowledgeskills"] != null)
            {
                foreach (XmlNode objXmlSkill in objXmlKit.SelectNodes("knowledgeskills/skill"))
                {
                    int i = panKnowledgeSkills.Controls.Count;
                    Skill objSkill = new Skill(_objCharacter);
                    objSkill.Name = objXmlSkill["name"].InnerText;

                    SkillControl objSkillControl = new SkillControl(_objCharacter);
                    objSkillControl.SkillObject = objSkill;

                    // Attach an EventHandler for the RatingChanged and SpecializationChanged Events.
                    objSkillControl.RatingChanged += objKnowledgeSkill_RatingChanged;
                    objSkillControl.SpecializationChanged += objSkill_SpecializationChanged;
                    objSkillControl.DeleteSkill += objKnowledgeSkill_DeleteSkill;

                    objSkillControl.KnowledgeSkill = true;
                    objSkillControl.AllowDelete = true;

					if (_objCharacter.IgnoreRules)
					{
						objSkillControl.SkillRatingMaximum = 12;
					}
					else
					{
						objSkillControl.SkillRatingMaximum = 6;
					}
					// Set the SkillControl's Location since scrolling the Panel causes it to actually change the child Controls' Locations.
					objSkillControl.Location = new Point(0, objSkillControl.Height * i + panKnowledgeSkills.AutoScrollPosition.Y);
                    panKnowledgeSkills.Controls.Add(objSkillControl);

                    objSkillControl.SkillName = objXmlSkill["name"].InnerText;

                    // Make sure it's not going above the maximum number.
                    if (Convert.ToInt32(objXmlSkill["rating"].InnerText) > objSkillControl.SkillRatingMaximum)
                        objSkillControl.SkillRating = objSkillControl.SkillRatingMaximum;
                    else
                        objSkillControl.SkillRating = Convert.ToInt32(objXmlSkill["rating"].InnerText);

                    if (objXmlSkill["spec"] != null)
                        objSkillControl.SkillSpec = objXmlSkill["spec"].InnerText;
                    else
                        objSkillControl.SkillSpec = "";

                    if (objXmlSkill["category"] != null)
                        objSkillControl.SkillCategory = objXmlSkill["category"].InnerText;

                    _objCharacter.Skills.Add(objSkill);
                }
            }

            // Select a Martial Art.
            if (objXmlKit["selectmartialart"] != null)
            {
                string strForcedValue = "";
                int intRating = 1;
                if (objXmlKit["selectmartialart"].Attributes["select"] != null)
                    strForcedValue = objXmlKit["selectmartialart"].Attributes["select"].InnerText;
                if (objXmlKit["selectmartialart"].Attributes["rating"] != null)
                    intRating = Convert.ToInt32(objXmlKit["selectmartialart"].Attributes["rating"].InnerText);

                frmSelectMartialArt frmPickMartialArt = new frmSelectMartialArt(_objCharacter);
                frmPickMartialArt.ForcedValue = strForcedValue;
                frmPickMartialArt.ShowDialog(this);

                if (frmPickMartialArt.DialogResult != DialogResult.Cancel)
                {
                    // Open the Martial Arts XML file and locate the selected piece.
                    XmlDocument objXmlMartialArtDocument = XmlManager.Instance.Load("martialarts.xml");

                    XmlNode objXmlArt = objXmlMartialArtDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + frmPickMartialArt.SelectedMartialArt + "\"]");

                    TreeNode objNode = new TreeNode();
                    MartialArt objMartialArt = new MartialArt(_objCharacter);
                    objMartialArt.Create(objXmlArt, objNode, _objCharacter);
                    objMartialArt.Rating = intRating;
                    _objCharacter.MartialArts.Add(objMartialArt);

                    objNode.ContextMenuStrip = cmsMartialArts;

                    treMartialArts.Nodes[0].Nodes.Add(objNode);
                    treMartialArts.Nodes[0].Expand();

                    treMartialArts.SelectedNode = objNode;
                }
            }

            // Update Martial Arts.
            if (objXmlKit["martialarts"] != null)
            {
                // Open the Martial Arts XML file and locate the selected art.
                XmlDocument objXmlMartialArtDocument = XmlManager.Instance.Load("martialarts.xml");

                foreach (XmlNode objXmlArt in objXmlKit.SelectNodes("martialarts/martialart"))
                {
                    TreeNode objNode = new TreeNode();
                    MartialArt objArt = new MartialArt(_objCharacter);
                    XmlNode objXmlArtNode = objXmlMartialArtDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + objXmlArt["name"].InnerText + "\"]");
                    objArt.Create(objXmlArtNode, objNode, _objCharacter);
                    objArt.Rating = Convert.ToInt32(objXmlArt["rating"].InnerText);
                    _objCharacter.MartialArts.Add(objArt);

                    // Check for Advantages.
                    foreach (XmlNode objXmlAdvantage in objXmlArt.SelectNodes("techniques/technique"))
                    {
                        TreeNode objChildNode = new TreeNode();
                        MartialArtAdvantage objAdvantage = new MartialArtAdvantage(_objCharacter);
                        XmlNode objXmlAdvantageNode = objXmlMartialArtDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + objXmlArt["name"].InnerText + "\"]/techniques/technique[. = \"" + objXmlAdvantage.InnerText + "\"]");
                        objAdvantage.Create(objXmlAdvantageNode, _objCharacter, objChildNode);
                        objArt.Advantages.Add(objAdvantage);

                        objNode.Nodes.Add(objChildNode);
                        objNode.Expand();
                    }

                    treMartialArts.Nodes[0].Nodes.Add(objNode);
                    treMartialArts.Nodes[0].Expand();
                }
            }

            // Update Adept Powers.
            if (objXmlKit["powers"] != null)
            {
                // Open the Powers XML file and locate the selected power.
                XmlDocument objXmlPowerDocument = XmlManager.Instance.Load("powers.xml");

                foreach (XmlNode objXmlPower in objXmlKit.SelectNodes("powers/power"))
                {
                    XmlNode objXmlPowerNode = objXmlPowerDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower["name"].InnerText + "\"]");

                    int i = panPowers.Controls.Count;

                    Power objPower = new Power(_objCharacter);
                    _objCharacter.Powers.Add(objPower);

                    PowerControl objPowerControl = new PowerControl();
                    objPowerControl.PowerObject = objPower;

                    // Attach an EventHandler for the PowerRatingChanged Event.
                    objPowerControl.PowerRatingChanged += objPower_PowerRatingChanged;
                    objPowerControl.DeletePower += objPower_DeletePower;

                    objPowerControl.PowerName = objXmlPowerNode["name"].InnerText;
                    objPowerControl.PointsPerLevel = Convert.ToDecimal(objXmlPowerNode["points"].InnerText, GlobalOptions.Instance.CultureInfo);
                    objPowerControl.AdeptWayDiscount = Convert.ToDecimal(objXmlPowerNode["adeptway"].InnerText, GlobalOptions.Instance.CultureInfo);
                    if (objXmlPowerNode["levels"].InnerText == "no")
                    {
                        objPowerControl.LevelEnabled = false;
                    }
                    else
                    {
                        objPowerControl.LevelEnabled = true;
                        if (objXmlPowerNode["levels"].InnerText != "yes")
                            objPower.MaxLevels = Convert.ToInt32(objXmlPowerNode["levels"].InnerText);
                    }

                    objPower.Source = objXmlPowerNode["source"].InnerText;
                    objPower.Page = objXmlPowerNode["page"].InnerText;
                    if (objXmlPowerNode["doublecost"] != null)
                        objPower.DoubleCost = false;

                    if (objXmlPowerNode.InnerXml.Contains("bonus"))
                    {
                        objPower.Bonus = objXmlPowerNode["bonus"];

                        if (objXmlPower["name"].Attributes["select"] != null)
                            _objImprovementManager.ForcedValue = objXmlPower["name"].Attributes["select"].InnerText;

                        _objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Power, objPower.InternalId, objPower.Bonus, false, Convert.ToInt32(objPower.Rating), objPower.DisplayNameShort);
                        objPowerControl.Extra = _objImprovementManager.SelectedValue;
                    }

                    objPowerControl.Top = i * objPowerControl.Height;
                    panPowers.Controls.Add(objPowerControl);

                    // Set the Rating of the Power if applicable.
                    if (objXmlPower["rating"] != null)
                        objPowerControl.PowerLevel = Convert.ToInt32(objXmlPower["rating"].InnerText);
                }
            }

            // Update Complex Forms.
            if (objXmlKit["programs"] != null)
            {
                // Open the Programs XML file and locate the selected program.
                XmlDocument objXmlProgramDocument = XmlManager.Instance.Load("complexforms.xml");

                foreach (XmlNode objXmlProgram in objXmlKit.SelectNodes("complexforms/complexform"))
                {
                    XmlNode objXmlProgramNode = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlProgram["name"].InnerText + "\"]");

                    string strForceValue = "";
                    if (objXmlProgram.Attributes["select"] != null)
                        strForceValue = objXmlProgram.Attributes["select"].InnerText;

                    TreeNode objNode = new TreeNode();
                    ComplexForm objProgram = new ComplexForm(_objCharacter);
                    objProgram.Create(objXmlProgramNode, _objCharacter, objNode, strForceValue);

                    treComplexForms.Nodes[0].Nodes.Add(objNode);
                    treComplexForms.Nodes[0].Expand();

                    _objCharacter.ComplexForms.Add(objProgram);

                    treComplexForms.SortCustom();
                }
            }

            // Update Spells.
            if (objXmlKit["spells"] != null)
            {
                XmlDocument objXmlSpellDocument = XmlManager.Instance.Load("spells.xml");

                foreach (XmlNode objXmlSpell in objXmlKit.SelectNodes("spells/spell"))
                {
                    // Make sure the Spell has not already been added to the character.
                    bool blnFound = false;
                    foreach (TreeNode nodSpell in treSpells.Nodes[0].Nodes)
                    {
                        if (nodSpell.Text == objXmlSpell.InnerText)
                        {
                            blnFound = true;
                            break;
                        }
                    }

                    // The Spell is not in the list, so add it.
                    if (!blnFound)
                    {
                        string strForceValue = "";
                        if (objXmlSpell.Attributes["select"] != null)
                            strForceValue = objXmlSpell.Attributes["select"].InnerText;

                        XmlNode objXmlSpellNode = objXmlSpellDocument.SelectSingleNode("/chummer/spells/spell[name = \"" + objXmlSpell.InnerText + "\"]");

                        Spell objSpell = new Spell(_objCharacter);
                        TreeNode objNode = new TreeNode();
                        objSpell.Create(objXmlSpellNode, _objCharacter, objNode, strForceValue);
                        objNode.ContextMenuStrip = cmsSpell;
                        _objCharacter.Spells.Add(objSpell);

                        switch (objSpell.Category)
                        {
                            case "Combat":
                                treSpells.Nodes[0].Nodes.Add(objNode);
                                treSpells.Nodes[0].Expand();
                                break;
                            case "Detection":
                                treSpells.Nodes[1].Nodes.Add(objNode);
                                treSpells.Nodes[1].Expand();
                                break;
                            case "Health":
                                treSpells.Nodes[2].Nodes.Add(objNode);
                                treSpells.Nodes[2].Expand();
                                break;
                            case "Illusion":
                                treSpells.Nodes[3].Nodes.Add(objNode);
                                treSpells.Nodes[3].Expand();
                                break;
                            case "Manipulation":
                                treSpells.Nodes[4].Nodes.Add(objNode);
                                treSpells.Nodes[4].Expand();
                                break;
                            case "Rituals":
                                int intNode = 5;
                                if (_objCharacter.AdeptEnabled && !_objCharacter.MagicianEnabled)
                                    intNode = 0;
                                treSpells.Nodes[intNode].Nodes.Add(objNode);
                                treSpells.Nodes[intNode].Expand();
                                break;
                        }

                        treSpells.SortCustom();
                    }
                }
            }

            // Update Spirits.
            if (objXmlKit["spirits"] != null)
            {
                foreach (XmlNode objXmlSpirit in objXmlKit.SelectNodes("spirits/spirit"))
                {
                    int i = panSpirits.Controls.Count;

                    Spirit objSpirit = new Spirit(_objCharacter);
                    _objCharacter.Spirits.Add(objSpirit);

                    SpiritControl objSpiritControl = new SpiritControl();
                    objSpiritControl.SpiritObject = objSpirit;
                    objSpiritControl.EntityType = SpiritType.Spirit;

                    // Attach an EventHandler for the ServicesOwedChanged Event.
                    objSpiritControl.ServicesOwedChanged += objSpirit_ServicesOwedChanged;
                    objSpiritControl.ForceChanged += objSpirit_ForceChanged;
                    objSpiritControl.BoundChanged += objSpirit_BoundChanged;
                    objSpiritControl.DeleteSpirit += objSpirit_DeleteSpirit;

                    objSpiritControl.Name = objXmlSpirit["name"].InnerText;
                    objSpiritControl.Force = Convert.ToInt32(objXmlSpirit["force"].InnerText);
                    objSpiritControl.ServicesOwed = Convert.ToInt32(objXmlSpirit["services"].InnerText);

                    objSpiritControl.Top = i * objSpiritControl.Height;
                    panSpirits.Controls.Add(objSpiritControl);
                }
            }

            // Update Lifestyles.
            if (objXmlKit["lifestyles"] != null)
            {
                XmlDocument objXmlLifestyleDocument = XmlManager.Instance.Load("lifestyles.xml");

                foreach (XmlNode objXmlLifestyle in objXmlKit.SelectNodes("lifestyles/lifestyle"))
                {
                    string strName = objXmlLifestyle["name"].InnerText;
                    int intMonths = Convert.ToInt32(objXmlLifestyle["months"].InnerText);

                    // Create the Lifestyle.
                    TreeNode objNode = new TreeNode();
                    Lifestyle objLifestyle = new Lifestyle(_objCharacter);

                    XmlNode objXmlLifestyleNode = objXmlLifestyleDocument.SelectSingleNode("/chummer/lifestyles/lifestyle[name = \"" + strName + "\"]");
                    if (objXmlLifestyleNode != null)
                    {
                        // This is a standard Lifestyle, so just use the Create method.
                        objLifestyle.Create(objXmlLifestyleNode, objNode);
                        objLifestyle.Months = intMonths;
                    }
                    else
                    {
                        // This is an Advanced Lifestyle, so build it manually.
                        objLifestyle.Name = strName;
                        objLifestyle.Months = intMonths;
                        objLifestyle.Cost = Convert.ToInt32(objXmlLifestyle["cost"].InnerText);
                        objLifestyle.Dice = Convert.ToInt32(objXmlLifestyle["dice"].InnerText);
                        objLifestyle.Multiplier = Convert.ToInt32(objXmlLifestyle["multiplier"].InnerText);
                        objLifestyle.BaseLifestyle = objXmlLifestyle["baselifestyle"].InnerText;
                        objLifestyle.Source = "SR5";
                        objLifestyle.Page = "373";
                        objLifestyle.Comforts = Convert.ToInt32(objXmlLifestyle["comforts"].InnerText);
                        objLifestyle.ComfortsEntertainment = Convert.ToInt32(objXmlLifestyle["comfortsentertainment"].InnerText);
                        objLifestyle.Security = Convert.ToInt32(objXmlLifestyle["security"].InnerText);
                        objLifestyle.SecurityEntertainment = Convert.ToInt32(objXmlLifestyle["securityentertainment"].InnerText);
                        objLifestyle.Area = Convert.ToInt32(objXmlLifestyle["area"].InnerText);
                        objLifestyle.AreaEntertainment = Convert.ToInt32(objXmlLifestyle["areaentertainment"].InnerText);

                        foreach (LifestyleQuality objXmlQuality in objXmlLifestyle.SelectNodes("lifestylequalities/lifestylequality"))
                            objLifestyle.LifestyleQualities.Add(objXmlQuality);

                        objNode.Text = strName;
                    }

                    // Add the Lifestyle to the character and Lifestyle Tree.
                    if (objLifestyle.BaseLifestyle != "")
                        objNode.ContextMenuStrip = cmsAdvancedLifestyle;
                    else
                        objNode.ContextMenuStrip = cmsLifestyleNotes;
                    _objCharacter.Lifestyles.Add(objLifestyle);
                    treLifestyles.Nodes[0].Nodes.Add(objNode);
                    treLifestyles.Nodes[0].Expand();
                }
            }

            // Update NuyenBP.
            if (objXmlKit["nuyenbp"] != null)
            {
                int intAmount = Convert.ToInt32(objXmlKit["nuyenbp"].InnerText);
                //if (_objCharacter.BuildMethod == CharacterBuildMethod.Karma)
                //intAmount *= 2;

                // Make sure we don't go over the field's maximum which would throw an Exception.
                if (nudNuyen.Value + intAmount > nudNuyen.Maximum)
                    nudNuyen.Value = nudNuyen.Maximum;
                else
                    nudNuyen.Value += intAmount;
            }

            // Update Armor.
            if (objXmlKit["armors"] != null)
            {
                XmlDocument objXmlArmorDocument = XmlManager.Instance.Load("armor.xml");

                foreach (XmlNode objXmlArmor in objXmlKit.SelectNodes("armors/armor"))
                {
                    XmlNode objXmlArmorNode = objXmlArmorDocument.SelectSingleNode("/chummer/armors/armor[name = \"" + objXmlArmor["name"].InnerText + "\"]");

                    Armor objArmor = new Armor(_objCharacter);
                    TreeNode objNode = new TreeNode();
                    objArmor.Create(objXmlArmorNode, objNode, cmsArmorMod, Convert.ToInt32(objXmlArmor["rating"].InnerText), false, blnCreateChildren);
                    _objCharacter.Armor.Add(objArmor);

                    // Look for Armor Mods.
                    if (objXmlArmor["mods"] != null)
                    {
                        foreach (XmlNode objXmlMod in objXmlArmor.SelectNodes("mods/mod"))
                        {
                            List<Weapon> lstWeapons = new List<Weapon>();
                            List<TreeNode> lstWeaponNodes = new List<TreeNode>();
                            XmlNode objXmlModNode = objXmlArmorDocument.SelectSingleNode("/chummer/mods/mod[name = \"" + objXmlMod["name"].InnerText + "\"]");
                            ArmorMod objMod = new ArmorMod(_objCharacter);
                            TreeNode objModNode = new TreeNode();
                            int intRating = 0;
                            if (objXmlMod["rating"] != null)
                                intRating = Convert.ToInt32(objXmlMod["rating"].InnerText);
                            objMod.Create(objXmlModNode, objModNode, intRating, lstWeapons, lstWeaponNodes);
                            objModNode.ContextMenuStrip = cmsArmorMod;
                            objMod.Parent = objArmor;

                            objArmor.ArmorMods.Add(objMod);

                            objNode.Nodes.Add(objModNode);
                            objNode.Expand();

                            // Add any Weapons created by the Mod.
                            foreach (Weapon objWeapon in lstWeapons)
                                _objCharacter.Weapons.Add(objWeapon);

                            foreach (TreeNode objWeaponNode in lstWeaponNodes)
                            {
                                objWeaponNode.ContextMenuStrip = cmsWeapon;
                                treWeapons.Nodes[0].Nodes.Add(objWeaponNode);
                                treWeapons.Nodes[0].Expand();
                            }
                        }
                    }

                    XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");
                    foreach (XmlNode objXmlGear in objXmlArmor.SelectNodes("gears/gear"))
                        AddPACKSGear(objXmlGearDocument, objXmlGear, objNode, objArmor, cmsArmorGear, blnCreateChildren);

                    objNode.ContextMenuStrip = cmsArmor;
                    treArmor.Nodes[0].Nodes.Add(objNode);
                    treArmor.Nodes[0].Expand();
                }
            }

            // Update Weapons.
            if (objXmlKit["weapons"] != null)
            {
                XmlDocument objXmlWeaponDocument = XmlManager.Instance.Load("weapons.xml");

                pgbProgress.Visible = true;
                pgbProgress.Value = 0;
                pgbProgress.Maximum = objXmlKit.SelectNodes("weapons/weapon").Count;
                int i = 0;
                foreach (XmlNode objXmlWeapon in objXmlKit.SelectNodes("weapons/weapon"))
                {
                    i++;
                    pgbProgress.Value = i;
                    Application.DoEvents();

                    XmlNode objXmlWeaponNode = objXmlWeaponDocument.SelectSingleNode("/chummer/weapons/weapon[name = \"" + objXmlWeapon["name"].InnerText + "\"]");

                    Weapon objWeapon = new Weapon(_objCharacter);
                    TreeNode objNode = new TreeNode();
                    objWeapon.Create(objXmlWeaponNode, _objCharacter, objNode, cmsWeapon, cmsWeaponAccessory, cmsWeaponMod, blnCreateChildren);
                    _objCharacter.Weapons.Add(objWeapon);

                    // Look for Weapon Accessories.
                    if (objXmlWeapon["accessories"] != null)
                    {
                        foreach (XmlNode objXmlAccessory in objXmlWeapon.SelectNodes("accessories/accessory"))
                        {
                            XmlNode objXmlAccessoryNode = objXmlWeaponDocument.SelectSingleNode("/chummer/accessories/accessory[name = \"" + objXmlAccessory["name"].InnerText + "\"]");
                            WeaponAccessory objMod = new WeaponAccessory(_objCharacter);
                            TreeNode objModNode = new TreeNode();
                            string strMount = "";
							int intRating = 0;
                            if (objXmlAccessory["mount"] != null)
                                strMount = objXmlAccessory["mount"].InnerText;
                            objMod.Create(objXmlAccessoryNode, objModNode, strMount, intRating);
                            objModNode.ContextMenuStrip = cmsWeaponAccessory;
                            objMod.Parent = objWeapon;

                            objWeapon.WeaponAccessories.Add(objMod);

                            XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");
                            foreach (XmlNode objXmlGear in objXmlAccessory.SelectNodes("gears/gear"))
                                AddPACKSGear(objXmlGearDocument, objXmlGear, objModNode, objMod, cmsWeaponAccessoryGear, blnCreateChildren);

                            objNode.Nodes.Add(objModNode);
                            objNode.Expand();
                        }
                    }

                    // Look for Weapon Mods.
                    if (objXmlWeapon["mods"] != null)
                    {
                        foreach (XmlNode objXmlMod in objXmlWeapon.SelectNodes("mods/mod"))
                        {
                            XmlNode objXmlModNode = objXmlWeaponDocument.SelectSingleNode("/chummer/mods/mod[name = \"" + objXmlMod["name"].InnerText + "\"]");
                            WeaponMod objMod = new WeaponMod(_objCharacter);
                            TreeNode objModNode = new TreeNode();
                            objMod.Create(objXmlModNode, objModNode);
                            objModNode.ContextMenuStrip = cmsWeaponMod;
                            objMod.Parent = objWeapon;

                            objWeapon.WeaponMods.Add(objMod);

                            objNode.Nodes.Add(objModNode);
                            objNode.Expand();
                        }
                    }

                    // Look for an Underbarrel Weapon.
                    if (objXmlWeapon["underbarrel"] != null)
                    {
                        XmlNode objXmlUnderbarrelNode = objXmlWeaponDocument.SelectSingleNode("/chummer/weapons/weapon[name = \"" + objXmlWeapon["underbarrel"].InnerText + "\"]");

                        Weapon objUnderbarrelWeapon = new Weapon(_objCharacter);
                        TreeNode objUnderbarrelNode = new TreeNode();
                        objUnderbarrelWeapon.Create(objXmlUnderbarrelNode, _objCharacter, objUnderbarrelNode, cmsWeapon, cmsWeaponAccessory, cmsWeaponMod, blnCreateChildren);
                        objWeapon.UnderbarrelWeapons.Add(objUnderbarrelWeapon);
                        objNode.Nodes.Add(objUnderbarrelNode);
                        objNode.Expand();
                    }

                    objNode.ContextMenuStrip = cmsWeapon;
                    treWeapons.Nodes[0].Nodes.Add(objNode);
                    treWeapons.Nodes[0].Expand();

                    Application.DoEvents();
                }
            }

            // Update Cyberware.
            if (objXmlKit["cyberwares"] != null)
            {
                XmlDocument objXmlCyberwareDocument = XmlManager.Instance.Load("cyberware.xml");
                XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");

                pgbProgress.Visible = true;
                pgbProgress.Value = 0;
                pgbProgress.Maximum = objXmlKit.SelectNodes("cyberwares/cyberware").Count;
                int i = 0;
                foreach (XmlNode objXmlCyberware in objXmlKit.SelectNodes("cyberwares/cyberware"))
                {
                    i++;
                    pgbProgress.Value = i;
                    Application.DoEvents();

                    List<Weapon> objWeapons = new List<Weapon>();
                    List<TreeNode> objWeaponNodes = new List<TreeNode>();
                    TreeNode objNode = new TreeNode();
                    Cyberware objCyberware = new Cyberware(_objCharacter);
                    Grade objGrade = objCyberware.ConvertToCyberwareGrade(objXmlCyberware["grade"].InnerText, Improvement.ImprovementSource.Cyberware);

                    int intRating = 0;
                    if (objXmlCyberware["rating"] != null)
                        intRating = Convert.ToInt32(objXmlCyberware["rating"].InnerText);

                    XmlNode objXmlCyberwareNode = objXmlCyberwareDocument.SelectSingleNode("/chummer/cyberwares/cyberware[name = \"" + objXmlCyberware["name"].InnerText + "\"]");
                    objCyberware.Create(objXmlCyberwareNode, _objCharacter, objGrade, Improvement.ImprovementSource.Cyberware, intRating, objNode, objWeapons, objWeaponNodes, true, blnCreateChildren);
                    _objCharacter.Cyberware.Add(objCyberware);

                    // Add any children.
                    if (objXmlCyberware["cyberwares"] != null)
                    {
                        foreach (XmlNode objXmlChild in objXmlCyberware.SelectNodes("cyberwares/cyberware"))
                        {
                            TreeNode objChildNode = new TreeNode();
                            Cyberware objChildCyberware = new Cyberware(_objCharacter);

                            int intChildRating = 0;
                            if (objXmlChild["rating"] != null)
                                intChildRating = Convert.ToInt32(objXmlChild["rating"].InnerText);

                            XmlNode objXmlChildNode = objXmlCyberwareDocument.SelectSingleNode("/chummer/cyberwares/cyberware[name = \"" + objXmlChild["name"].InnerText + "\"]");
                            objChildCyberware.Create(objXmlChildNode, _objCharacter, objGrade, Improvement.ImprovementSource.Cyberware, intChildRating, objChildNode, objWeapons, objWeaponNodes, true, blnCreateChildren);
                            objCyberware.Children.Add(objChildCyberware);
                            objChildNode.ContextMenuStrip = cmsCyberware;

                            foreach (XmlNode objXmlGear in objXmlChild.SelectNodes("gears/gear"))
                                AddPACKSGear(objXmlGearDocument, objXmlGear, objChildNode, objChildCyberware, cmsCyberwareGear, blnCreateChildren);

                            objNode.Nodes.Add(objChildNode);
                            objNode.Expand();
                        }
                    }

                    foreach (XmlNode objXmlGear in objXmlCyberware.SelectNodes("gears/gear"))
                        AddPACKSGear(objXmlGearDocument, objXmlGear, objNode, objCyberware, cmsCyberwareGear, blnCreateChildren);

                    objNode.ContextMenuStrip = cmsCyberware;
                    treCyberware.Nodes[0].Nodes.Add(objNode);
                    treCyberware.Nodes[0].Expand();

                    // Add any Weapons created by the Gear.
                    foreach (Weapon objWeapon in objWeapons)
                        _objCharacter.Weapons.Add(objWeapon);

                    foreach (TreeNode objWeaponNode in objWeaponNodes)
                    {
                        objWeaponNode.ContextMenuStrip = cmsWeapon;
                        treWeapons.Nodes[0].Nodes.Add(objWeaponNode);
                        treWeapons.Nodes[0].Expand();
                    }

                    Application.DoEvents();
                }

                treCyberware.SortCustom();
            }

            // Update Bioware.
            if (objXmlKit["biowares"] != null)
            {
                XmlDocument objXmlBiowareDocument = XmlManager.Instance.Load("bioware.xml");

                pgbProgress.Visible = true;
                pgbProgress.Value = 0;
                pgbProgress.Maximum = objXmlKit.SelectNodes("biowares/bioware").Count;
                int i = 0;

                foreach (XmlNode objXmlBioware in objXmlKit.SelectNodes("biowares/bioware"))
                {
                    i++;
                    pgbProgress.Value = i;
                    Application.DoEvents();

                    List<Weapon> objWeapons = new List<Weapon>();
                    List<TreeNode> objWeaponNodes = new List<TreeNode>();
                    TreeNode objNode = new TreeNode();
                    Cyberware objCyberware = new Cyberware(_objCharacter);
                    Grade objGrade = objCyberware.ConvertToCyberwareGrade(objXmlBioware["grade"].InnerText, Improvement.ImprovementSource.Bioware);

                    int intRating = 0;
                    if (objXmlBioware["rating"] != null)
                        intRating = Convert.ToInt32(objXmlBioware["rating"].InnerText);

                    XmlNode objXmlBiowareNode = objXmlBiowareDocument.SelectSingleNode("/chummer/biowares/bioware[name = \"" + objXmlBioware["name"].InnerText + "\"]");
                    objCyberware.Create(objXmlBiowareNode, _objCharacter, objGrade, Improvement.ImprovementSource.Bioware, intRating, objNode, objWeapons, objWeaponNodes, true, blnCreateChildren);
                    _objCharacter.Cyberware.Add(objCyberware);

                    objNode.ContextMenuStrip = cmsBioware;
                    treCyberware.Nodes[1].Nodes.Add(objNode);
                    treCyberware.Nodes[1].Expand();

                    // Add any Weapons created by the Gear.
                    foreach (Weapon objWeapon in objWeapons)
                        _objCharacter.Weapons.Add(objWeapon);

                    foreach (TreeNode objWeaponNode in objWeaponNodes)
                    {
                        objWeaponNode.ContextMenuStrip = cmsWeapon;
                        treWeapons.Nodes[0].Nodes.Add(objWeaponNode);
                        treWeapons.Nodes[0].Expand();
                    }

                    Application.DoEvents();
                }

                treCyberware.SortCustom();
            }

            // Update Gear.
            if (objXmlKit["gears"] != null)
            {
                XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");

                pgbProgress.Visible = true;
                pgbProgress.Value = 0;
                pgbProgress.Maximum = objXmlKit.SelectNodes("gears/gear").Count;
                int i = 0;

                foreach (XmlNode objXmlGear in objXmlKit.SelectNodes("gears/gear"))
                {
                    i++;
                    pgbProgress.Value = i;
                    Application.DoEvents();

                    AddPACKSGear(objXmlGearDocument, objXmlGear, treGear.Nodes[0], _objCharacter, cmsGear, blnCreateChildren);

                    Application.DoEvents();
                }
            }

            // Update Vehicles.
            if (objXmlKit["vehicles"] != null)
            {
                XmlDocument objXmlVehicleDocument = XmlManager.Instance.Load("vehicles.xml");

                pgbProgress.Visible = true;
                pgbProgress.Value = 0;
                pgbProgress.Maximum = objXmlKit.SelectNodes("vehicles/vehicle").Count;
                int i = 0;

                foreach (XmlNode objXmlVehicle in objXmlKit.SelectNodes("vehicles/vehicle"))
                {
                    i++;
                    pgbProgress.Value = i;
                    Application.DoEvents();

                    Gear objDefaultSensor = new Gear(_objCharacter);

                    TreeNode objNode = new TreeNode();
                    Vehicle objVehicle = new Vehicle(_objCharacter);

                    XmlNode objXmlVehicleNode = objXmlVehicleDocument.SelectSingleNode("/chummer/vehicles/vehicle[name = \"" + objXmlVehicle["name"].InnerText + "\"]");
                    objVehicle.Create(objXmlVehicleNode, objNode, cmsVehicle, cmsVehicleGear, cmsVehicleWeapon, cmsVehicleWeaponAccessory, cmsVehicleWeaponMod, blnCreateChildren);
                    _objCharacter.Vehicles.Add(objVehicle);

                    // Grab the default Sensor that comes with the Vehicle.
                    foreach (Gear objSensorGear in objVehicle.Gear)
                    {
                        if (objSensorGear.Category == "Sensors" && objSensorGear.Cost == "0" && objSensorGear.Rating == 0)
                        {
                            objDefaultSensor = objSensorGear;
                            break;
                        }
                    }

                    // Add any Vehicle Mods.
                    if (objXmlVehicle["mods"] != null)
                    {
                        foreach (XmlNode objXmlMod in objXmlVehicle.SelectNodes("mods/mod"))
                        {
                            TreeNode objModNode = new TreeNode();
                            VehicleMod objMod = new VehicleMod(_objCharacter);

                            int intRating = 0;
                            if (objXmlMod["rating"] != null)
                                intRating = Convert.ToInt32(objXmlMod["rating"].InnerText);

                            XmlNode objXmlModNode = objXmlVehicleDocument.SelectSingleNode("/chummer/mods/mod[name = \"" + objXmlMod["name"].InnerText + "\"]");
                            objMod.Create(objXmlModNode, objModNode, intRating);
                            objVehicle.Mods.Add(objMod);

                            objNode.Nodes.Add(objModNode);
                            objNode.Expand();
                        }
                    }

                    // Add any Vehicle Gear.
                    if (objXmlVehicle["gears"] != null)
                    {
                        XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");

                        foreach (XmlNode objXmlGear in objXmlVehicle.SelectNodes("gears/gear"))
                        {
                            List<Weapon> objWeapons = new List<Weapon>();
                            List<TreeNode> objWeaponNodes = new List<TreeNode>();
                            TreeNode objGearNode = new TreeNode();
                            Gear objGear = new Gear(_objCharacter);
                            int intQty = 1;

                            int intRating = 0;
                            if (objXmlGear["rating"] != null)
                                intRating = Convert.ToInt32(objXmlGear["rating"].InnerText);
                            string strForceValue = "";
                            if (objXmlGear["name"].Attributes["select"] != null)
                                strForceValue = objXmlGear["name"].Attributes["select"].InnerText;
                            if (objXmlGear["qty"] != null)
                                intQty = Convert.ToInt32(objXmlGear["qty"].InnerText);

                            XmlNode objXmlGearNode = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear["name"].InnerText + "\"]");
                            objGear.Create(objXmlGearNode, _objCharacter, objGearNode, intRating, objWeapons, objWeaponNodes, strForceValue, false, false, false, blnCreateChildren, false);
                            objGear.Quantity = intQty;
                            objGearNode.Text = objGear.DisplayName;
                            objVehicle.Gear.Add(objGear);

                            // Look for child components.
                            if (objXmlGear["gears"] != null)
                            {
                                foreach (XmlNode objXmlChild in objXmlGear.SelectNodes("gears/gear"))
                                {
                                    AddPACKSGear(objXmlGearDocument, objXmlChild, objGearNode, objGear, cmsVehicleGear, blnCreateChildren);
                                }
                            }

                            objGearNode.Expand();
                            objGearNode.ContextMenuStrip = cmsVehicleGear;
                            objNode.Nodes.Add(objGearNode);
                            objNode.Expand();

                            // If this is a Sensor, it will replace the Vehicle's base sensor, so remove it.
                            if (objGear.Category == "Sensors" && objGear.Cost == "0" && objGear.Rating == 0)
                            {
                                objVehicle.Gear.Remove(objDefaultSensor);
                                foreach (TreeNode objSensorNode in objNode.Nodes)
                                {
                                    if (objSensorNode.Tag.ToString() == objDefaultSensor.InternalId)
                                    {
                                        objSensorNode.Remove();
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    // Add any Vehicle Weapons.
                    if (objXmlVehicle["weapons"] != null)
                    {
                        XmlDocument objXmlWeaponDocument = XmlManager.Instance.Load("weapons.xml");

                        foreach (XmlNode objXmlWeapon in objXmlVehicle.SelectNodes("weapons/weapon"))
                        {
                            TreeNode objWeaponNode = new TreeNode();
                            Weapon objWeapon = new Weapon(_objCharacter);

                            XmlNode objXmlWeaponNode = objXmlWeaponDocument.SelectSingleNode("/chummer/weapons/weapon[name = \"" + objXmlWeapon["name"].InnerText + "\"]");
                            objWeapon.Create(objXmlWeaponNode, _objCharacter, objWeaponNode, cmsVehicleWeapon, cmsVehicleWeaponAccessory, cmsVehicleWeaponMod, blnCreateChildren);
                            objWeapon.VehicleMounted = true;

                            // Find the first Weapon Mount in the Vehicle.
                            foreach (VehicleMod objMod in objVehicle.Mods)
                            {
                                if (objMod.Name.StartsWith("Weapon Mount") || objMod.Name.StartsWith("Heavy Weapon Mount"))
                                {
                                    objMod.Weapons.Add(objWeapon);
                                    foreach (TreeNode objModNode in objNode.Nodes)
                                    {
                                        if (objModNode.Tag.ToString() == objMod.InternalId)
                                        {
                                            objWeaponNode.ContextMenuStrip = cmsVehicleWeapon;
                                            objModNode.Nodes.Add(objWeaponNode);
                                            objModNode.Expand();
                                            break;
                                        }
                                    }
                                    break;
                                }
                            }

                            // Look for Weapon Accessories.
                            if (objXmlWeapon["accessories"] != null)
                            {
                                foreach (XmlNode objXmlAccessory in objXmlWeapon.SelectNodes("accessories/accessory"))
                                {
                                    XmlNode objXmlAccessoryNode = objXmlWeaponDocument.SelectSingleNode("/chummer/accessories/accessory[name = \"" + objXmlAccessory["name"].InnerText + "\"]");
                                    WeaponAccessory objMod = new WeaponAccessory(_objCharacter);
                                    TreeNode objModNode = new TreeNode();
                                    string strMount = "";
									int intRating = 0;
									if (objXmlAccessory["mount"] != null)
                                        strMount = objXmlAccessory["mount"].InnerText;
                                    objMod.Create(objXmlAccessoryNode, objModNode, strMount,intRating);
                                    objModNode.ContextMenuStrip = cmsWeaponAccessory;
                                    objMod.Parent = objWeapon;

                                    objWeapon.WeaponAccessories.Add(objMod);

                                    objWeaponNode.Nodes.Add(objModNode);
                                    objWeaponNode.Expand();
                                }
                            }

                            // Look for Weapon Mods.
                            if (objXmlWeapon["mods"] != null)
                            {
                                foreach (XmlNode objXmlMod in objXmlWeapon.SelectNodes("mods/mod"))
                                {
                                    XmlNode objXmlModNode = objXmlWeaponDocument.SelectSingleNode("/chummer/mods/mod[name = \"" + objXmlMod["name"].InnerText + "\"]");
                                    WeaponMod objMod = new WeaponMod(_objCharacter);
                                    TreeNode objModNode = new TreeNode();
                                    objMod.Create(objXmlModNode, objModNode);
                                    objModNode.ContextMenuStrip = cmsVehicleWeaponMod;
                                    objMod.Parent = objWeapon;

                                    objWeapon.WeaponMods.Add(objMod);

                                    objWeaponNode.Nodes.Add(objModNode);
                                    objWeaponNode.Expand();
                                }
                            }
                        }
                    }

                    objNode.ContextMenuStrip = cmsVehicle;
                    treVehicles.Nodes[0].Nodes.Add(objNode);
                    treVehicles.Nodes[0].Expand();

                    Application.DoEvents();
                }
            }

            pgbProgress.Visible = false;

            if (frmPickPACKSKit.AddAgain)
                AddPACKSKit();

            PopulateGearList();
            UpdateCharacterInfo();
        }
Example #14
0
        /// <summary>
        /// Load the Character from an XML file.
        /// </summary>
        public bool Load()
        {
            XmlDocument objXmlDocument = new XmlDocument();
            objXmlDocument.Load(_strFileName);

            XmlNode objXmlCharacter = objXmlDocument.SelectSingleNode("/character");
            XmlNodeList objXmlNodeList;

            try
            {
                _blnIgnoreRules = Convert.ToBoolean(objXmlCharacter["ignorerules"].InnerText);
            }
            catch
            {
                _blnIgnoreRules = false;
            }
            try
            {
                _blnCreated = Convert.ToBoolean(objXmlCharacter["created"].InnerText);
            }
            catch
            {
            }

            ResetCharacter();

            // Get the game edition of the file if possible and make sure it's intended to be used with this version of the application.
            try
            {
                if (objXmlCharacter["gameedition"].InnerText != string.Empty && objXmlCharacter["gameedition"].InnerText != "SR4")
                {
                    MessageBox.Show(LanguageManager.Instance.GetString("Message_IncorrectGameVersion_SR5"), LanguageManager.Instance.GetString("MessageTitle_IncorrectGameVersion"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
            }
            catch
            {
            }

            // Get the name of the settings file in use if possible.
            try
            {
                _strSettingsFileName = objXmlCharacter["settings"].InnerText;
            }
            catch
            {
            }

            // Load the character's settings file.
            if (!_objOptions.Load(_strSettingsFileName))
                return false;

            try
            {
                _decEssenceAtSpecialStart = Convert.ToDecimal(objXmlCharacter["essenceatspecialstart"].InnerText, GlobalOptions.Instance.CultureInfo);
                // fix to work around a mistake made when saving decimal values in previous versions.
                if (_decEssenceAtSpecialStart > EssenceMaximum)
                    _decEssenceAtSpecialStart /= 10;
            }
            catch
            {
            }

            // Metatype information.
            _strMetatype = objXmlCharacter["metatype"].InnerText;
            try
            {
                _strMovement = objXmlCharacter["movement"].InnerText;
            }
            catch
            {
            }
            _intMetatypeBP = Convert.ToInt32(objXmlCharacter["metatypebp"].InnerText);
            _strMetavariant = objXmlCharacter["metavariant"].InnerText;
            try
            {
                _strMetatypeCategory = objXmlCharacter["metatypecategory"].InnerText;
            }
            catch
            {
            }
            try
            {
                _intMutantCritterBaseSkills = Convert.ToInt32(objXmlCharacter["mutantcritterbaseskills"].InnerText);
            }
            catch
            {
            }

            // General character information.
            _strName = objXmlCharacter["name"].InnerText;
            try
            {
                _strMugshot = objXmlCharacter["mugshot"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strSex = objXmlCharacter["sex"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strAge = objXmlCharacter["age"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strEyes = objXmlCharacter["eyes"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strHeight = objXmlCharacter["height"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strWeight = objXmlCharacter["weight"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strSkin = objXmlCharacter["skin"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strHair = objXmlCharacter["hair"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strDescription = objXmlCharacter["description"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strBackground = objXmlCharacter["background"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strConcept = objXmlCharacter["concept"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strNotes = objXmlCharacter["notes"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strAlias = objXmlCharacter["alias"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strPlayerName = objXmlCharacter["playername"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strGameNotes = objXmlCharacter["gamenotes"].InnerText;
            }
            catch
            {
            }

            try
            {
                _blnIsCritter = Convert.ToBoolean(objXmlCharacter["iscritter"].InnerText);
            }
            catch
            {
            }

            try
            {
                _blnPossessed = Convert.ToBoolean(objXmlCharacter["possessed"].InnerText);
            }
            catch
            {
            }

            try
            {
                _blnOverrideSpecialAttributeESSLoss = Convert.ToBoolean(objXmlCharacter["overridespecialattributeessloss"].InnerText);
            }
            catch
            {
            }

            try
            {
                _intKarma = Convert.ToInt32(objXmlCharacter["karma"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intTotalKarma = Convert.ToInt32(objXmlCharacter["totalkarma"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intStreetCred = Convert.ToInt32(objXmlCharacter["streetcred"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intNotoriety = Convert.ToInt32(objXmlCharacter["notoriety"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intPublicAwareness = Convert.ToInt32(objXmlCharacter["publicawareness"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intBurntStreetCred = Convert.ToInt32(objXmlCharacter["burntstreetcred"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intMaxAvail = Convert.ToInt32(objXmlCharacter["maxavail"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intNuyen = Convert.ToInt32(objXmlCharacter["nuyen"].InnerText);
            }
            catch
            {
            }

            // Build Points/Karma.
            _intBuildPoints = Convert.ToInt32(objXmlCharacter["bp"].InnerText);
            try
            {
                _intBuildKarma = Convert.ToInt32(objXmlCharacter["buildkarma"].InnerText);
            }
            catch
            {
            }
            try
            {
                _objBuildMethod = ConvertToCharacterBuildMethod(objXmlCharacter["buildmethod"].InnerText);
            }
            catch
            {
            }
            _intKnowledgeSkillPoints = Convert.ToInt32(objXmlCharacter["knowpts"].InnerText);
            _decNuyenBP = Convert.ToDecimal(objXmlCharacter["nuyenbp"].InnerText, GlobalOptions.Instance.CultureInfo);
            _decNuyenMaximumBP = Convert.ToDecimal(objXmlCharacter["nuyenmaxbp"].InnerText, GlobalOptions.Instance.CultureInfo);
            _blnAdeptEnabled = Convert.ToBoolean(objXmlCharacter["adept"].InnerText);
            _blnMagicianEnabled = Convert.ToBoolean(objXmlCharacter["magician"].InnerText);
            _blnTechnomancerEnabled = Convert.ToBoolean(objXmlCharacter["technomancer"].InnerText);
            try
            {
                _blnInitiationEnabled = Convert.ToBoolean(objXmlCharacter["initiationoverride"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnCritterEnabled = Convert.ToBoolean(objXmlCharacter["critter"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnUneducated = Convert.ToBoolean(objXmlCharacter["uneducated"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnUncouth = Convert.ToBoolean(objXmlCharacter["uncouth"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnInfirm = Convert.ToBoolean(objXmlCharacter["infirm"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnBlackMarket = Convert.ToBoolean(objXmlCharacter["blackmarket"].InnerText);
            }
            catch
            {
            }
            _blnMAGEnabled = Convert.ToBoolean(objXmlCharacter["magenabled"].InnerText);
            try
            {
                _intInitiateGrade = Convert.ToInt32(objXmlCharacter["initiategrade"].InnerText);
            }
            catch
            {
            }
            _blnRESEnabled = Convert.ToBoolean(objXmlCharacter["resenabled"].InnerText);
            try
            {
                _intSubmersionGrade = Convert.ToInt32(objXmlCharacter["submersiongrade"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnGroupMember = Convert.ToBoolean(objXmlCharacter["groupmember"].InnerText);
            }
            catch
            {
            }
            try
            {
                _strGroupName = objXmlCharacter["groupname"].InnerText;
                _strGroupNotes = objXmlCharacter["groupnotes"].InnerText;
            }
            catch
            {
            }

            // Improvements.
            XmlNodeList objXmlImprovementList = objXmlDocument.SelectNodes("/character/improvements/improvement");
            foreach (XmlNode objXmlImprovement in objXmlImprovementList)
            {
                Improvement objImprovement = new Improvement();
                objImprovement.Load(objXmlImprovement);
                _lstImprovements.Add(objImprovement);
            }

            // Qualities
            objXmlNodeList = objXmlDocument.SelectNodes("/character/qualities/quality");
            bool blnHasOldQualities = false;
            foreach (XmlNode objXmlQuality in objXmlNodeList)
            {
                if (objXmlQuality["name"] != null)
                {
                    Quality objQuality = new Quality(this);
                    objQuality.Load(objXmlQuality);
                    _lstQualities.Add(objQuality);
                }
                else
                {
                    // If the Quality does not have a name tag, it is in the old format. Set the flag to show that old Qualities are in use.
                    blnHasOldQualities = true;
                }
            }
            // If old Qualities are in use, they need to be converted before we can continue.
            if (blnHasOldQualities)
                ConvertOldQualities(objXmlNodeList);

            // Attributes.
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"BOD\"]");
            _attBOD.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"AGI\"]");
            _attAGI.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"REA\"]");
            _attREA.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"STR\"]");
            _attSTR.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"CHA\"]");
            _attCHA.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"INT\"]");
            _attINT.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"LOG\"]");
            _attLOG.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"WIL\"]");
            _attWIL.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"INI\"]");
            _attINI.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"EDG\"]");
            _attEDG.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"MAG\"]");
            _attMAG.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"RES\"]");
            _attRES.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"ESS\"]");
            _attESS.Load(objXmlCharacter);

            // A.I. Attributes.
            try
            {
                _intSignal = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/attributes/signal").InnerText);
                _intResponse = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/attributes/response").InnerText);
            }
            catch
            {
            }

            // Force.
            try
            {
                _intMaxSkillRating = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/attributes/maxskillrating").InnerText);
            }
            catch
            {
            }

            // Attempt to load the split MAG Attribute information for Mystic Adepts.
            if (_blnAdeptEnabled && _blnMagicianEnabled)
            {
                try
                {
                    _intMAGAdept = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/magsplitadept").InnerText);
                    _intMAGMagician = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/magsplitmagician").InnerText);
                }
                catch
                {
                }
            }

            // Attempt to load the Magic Tradition.
            try
            {
                _strMagicTradition = objXmlDocument.SelectSingleNode("/character/tradition").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Technomancer Stream.
            try
            {
                _strTechnomancerStream = objXmlDocument.SelectSingleNode("/character/stream").InnerText;
            }
            catch
            {
            }

            // Attempt to load Condition Monitor Progress.
            try
            {
                _intPhysicalCMFilled = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/physicalcmfilled").InnerText);
                _intStunCMFilled = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/stuncmfilled").InnerText);
            }
            catch
            {
            }

            // Skills.
            foreach (Skill objSkill in _lstSkills)
            {
                XmlNode objXmlSkill = objXmlDocument.SelectSingleNode("/character/skills/skill[name = \"" + objSkill.Name + "\"]");
                if (objXmlSkill != null)
                {
                    objSkill.Load(objXmlSkill);
                }
            }

            // Exotic Skills.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/skills/skill[exotic = \"True\"]");
            foreach (XmlNode objXmlSkill in objXmlNodeList)
            {
                Skill objSkill = new Skill(this);
                objSkill.Load(objXmlSkill);
                _lstSkills.Add(objSkill);
            }

            // SkillGroups.
            foreach (SkillGroup objGroup in _lstSkillGroups)
            {
                XmlNode objXmlSkill = objXmlDocument.SelectSingleNode("/character/skillgroups/skillgroup[name = \"" + objGroup.Name + "\"]");
                if (objXmlSkill != null)
                {
                    objGroup.Load(objXmlSkill);
                    // If the character is set to ignore rules or is in Career Mode, Skill Groups should have a maximum Rating of 6 unless they have been given a higher maximum Rating already.
                    if ((_blnIgnoreRules || _blnCreated) && objGroup.RatingMaximum < 6)
                        objGroup.RatingMaximum = 6;
                }
            }

            // Knowledge Skills.
            List<ListItem> lstKnowledgeSkillOrder = new List<ListItem>();
            objXmlNodeList = objXmlDocument.SelectNodes("/character/skills/skill[knowledge = \"True\"]");
            // Sort the Knowledge Skills in alphabetical order.
            foreach (XmlNode objXmlSkill in objXmlNodeList)
            {
                ListItem objGroup = new ListItem();
                objGroup.Value = objXmlSkill["name"].InnerText;
                objGroup.Name = objXmlSkill["name"].InnerText;
                lstKnowledgeSkillOrder.Add(objGroup);
            }
            SortListItem objSort = new SortListItem();
            lstKnowledgeSkillOrder.Sort(objSort.Compare);

            foreach (ListItem objItem in lstKnowledgeSkillOrder)
            {
                Skill objSkill = new Skill(this);
                XmlNode objNode = objXmlDocument.SelectSingleNode("/character/skills/skill[knowledge = \"True\" and name = " + CleanXPath(objItem.Value) + "]");
                objSkill.Load(objNode);
                _lstSkills.Add(objSkill);
            }

            // Contacts.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/contacts/contact");
            foreach (XmlNode objXmlContact in objXmlNodeList)
            {
                Contact objContact = new Contact(this);
                objContact.Load(objXmlContact);
                _lstContacts.Add(objContact);
            }

            // Armor.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/armors/armor");
            foreach (XmlNode objXmlArmor in objXmlNodeList)
            {
                Armor objArmor = new Armor(this);
                objArmor.Load(objXmlArmor);
                _lstArmor.Add(objArmor);
            }

            // Weapons.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/weapons/weapon");
            foreach (XmlNode objXmlWeapon in objXmlNodeList)
            {
                Weapon objWeapon = new Weapon(this);
                objWeapon.Load(objXmlWeapon);
                _lstWeapons.Add(objWeapon);
            }

            // Cyberware/Bioware.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/cyberwares/cyberware");
            foreach (XmlNode objXmlCyberware in objXmlNodeList)
            {
                Cyberware objCyberware = new Cyberware(this);
                objCyberware.Load(objXmlCyberware);
                _lstCyberware.Add(objCyberware);
            }

            // Spells.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/spells/spell");
            foreach (XmlNode objXmlSpell in objXmlNodeList)
            {
                Spell objSpell = new Spell(this);
                objSpell.Load(objXmlSpell);
                _lstSpells.Add(objSpell);
            }

            // Foci.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/foci/focus");
            foreach (XmlNode objXmlFocus in objXmlNodeList)
            {
                Focus objFocus = new Focus();
                objFocus.Load(objXmlFocus);
                _lstFoci.Add(objFocus);
            }

            // Stacked Foci.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/stackedfoci/stackedfocus");
            foreach (XmlNode objXmlStack in objXmlNodeList)
            {
                StackedFocus objStack = new StackedFocus(this);
                objStack.Load(objXmlStack);
                _lstStackedFoci.Add(objStack);
            }

            // Powers.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/powers/power");
            foreach (XmlNode objXmlPower in objXmlNodeList)
            {
                Power objPower = new Power(this);
                objPower.Load(objXmlPower);
                _lstPowers.Add(objPower);
            }

            // Spirits/Sprites.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/spirits/spirit");
            foreach (XmlNode objXmlSpirit in objXmlNodeList)
            {
                Spirit objSpirit = new Spirit(this);
                objSpirit.Load(objXmlSpirit);
                _lstSpirits.Add(objSpirit);
            }

            // Compex Forms/Technomancer Programs.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/techprograms/techprogram");
            foreach (XmlNode objXmlProgram in objXmlNodeList)
            {
                TechProgram objProgram = new TechProgram(this);
                objProgram.Load(objXmlProgram);
                _lstTechPrograms.Add(objProgram);
            }

            // Martial Arts.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/martialarts/martialart");
            foreach (XmlNode objXmlArt in objXmlNodeList)
            {
                MartialArt objMartialArt = new MartialArt(this);
                objMartialArt.Load(objXmlArt);
                _lstMartialArts.Add(objMartialArt);
            }

            // Martial Art Maneuvers.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/martialartmaneuvers/martialartmaneuver");
            foreach (XmlNode objXmlManeuver in objXmlNodeList)
            {
                MartialArtManeuver objManeuver = new MartialArtManeuver(this);
                objManeuver.Load(objXmlManeuver);
                _lstMartialArtManeuvers.Add(objManeuver);
            }

            // Lifestyles.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/lifestyles/lifestyle");
            foreach (XmlNode objXmlLifestyle in objXmlNodeList)
            {
                Lifestyle objLifestyle = new Lifestyle(this);
                objLifestyle.Load(objXmlLifestyle);
                _lstLifestyles.Add(objLifestyle);
            }

            // <gears>
            objXmlNodeList = objXmlDocument.SelectNodes("/character/gears/gear");
            foreach (XmlNode objXmlGear in objXmlNodeList)
            {
                switch (objXmlGear["category"].InnerText)
                {
                    case "Commlink":
                    case "Commlink Upgrade":
                        Commlink objCommlink = new Commlink(this);
                        objCommlink.Load(objXmlGear);
                        _lstGear.Add(objCommlink);
                        break;
                    case "Commlink Operating System":
                    case "Commlink Operating System Upgrade":
                        OperatingSystem objOperatingSystem = new OperatingSystem(this);
                        objOperatingSystem.Load(objXmlGear);
                        _lstGear.Add(objOperatingSystem);
                        break;
                    default:
                        Gear objGear = new Gear(this);
                        objGear.Load(objXmlGear);
                        _lstGear.Add(objGear);
                        break;
                }
            }

            // Vehicles.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/vehicles/vehicle");
            foreach (XmlNode objXmlVehicle in objXmlNodeList)
            {
                Vehicle objVehicle = new Vehicle(this);
                objVehicle.Load(objXmlVehicle);
                _lstVehicles.Add(objVehicle);
            }

            // Metamagics/Echoes.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/metamagics/metamagic");
            foreach (XmlNode objXmlMetamagic in objXmlNodeList)
            {
                Metamagic objMetamagic = new Metamagic(this);
                objMetamagic.Load(objXmlMetamagic);
                _lstMetamagics.Add(objMetamagic);
            }

            // Critter Powers.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/critterpowers/critterpower");
            foreach (XmlNode objXmlPower in objXmlNodeList)
            {
                CritterPower objPower = new CritterPower(this);
                objPower.Load(objXmlPower);
                _lstCritterPowers.Add(objPower);
            }

            // Initiation Grades.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/initiationgrades/initiationgrade");
            foreach (XmlNode objXmlGrade in objXmlNodeList)
            {
                InitiationGrade objGrade = new InitiationGrade(this);
                objGrade.Load(objXmlGrade);
                _lstInitiationGrades.Add(objGrade);
            }

            // Expense Log Entries.
            XmlNodeList objXmlExpenseList = objXmlDocument.SelectNodes("/character/expenses/expense");
            foreach (XmlNode objXmlExpense in objXmlExpenseList)
            {
                ExpenseLogEntry objExpenseLogEntry = new ExpenseLogEntry();
                objExpenseLogEntry.Load(objXmlExpense);
                _lstExpenseLog.Add(objExpenseLogEntry);
            }

            // Locations.
            XmlNodeList objXmlLocationList = objXmlDocument.SelectNodes("/character/locations/location");
            foreach (XmlNode objXmlLocation in objXmlLocationList)
            {
                _lstLocations.Add(objXmlLocation.InnerText);
            }

            // Armor Bundles.
            XmlNodeList objXmlBundleList = objXmlDocument.SelectNodes("/character/armorbundles/armorbundle");
            foreach (XmlNode objXmlBundle in objXmlBundleList)
            {
                _lstArmorBundles.Add(objXmlBundle.InnerText);
            }

            // Weapon Locations.
            XmlNodeList objXmlWeaponLocationList = objXmlDocument.SelectNodes("/character/weaponlocations/weaponlocation");
            foreach (XmlNode objXmlLocation in objXmlWeaponLocationList)
            {
                _lstWeaponLocations.Add(objXmlLocation.InnerText);
            }

            // Improvement Groups.
            XmlNodeList objXmlGroupList = objXmlDocument.SelectNodes("/character/improvementgroups/improvementgroup");
            foreach (XmlNode objXmlGroup in objXmlGroupList)
            {
                _lstImprovementGroups.Add(objXmlGroup.InnerText);
            }

            // Calendar.
            XmlNodeList objXmlWeekList = objXmlDocument.SelectNodes("/character/calendar/week");
            foreach (XmlNode objXmlWeek in objXmlWeekList)
            {
                CalendarWeek objWeek = new CalendarWeek();
                objWeek.Load(objXmlWeek);
                _lstCalendar.Add(objWeek);
            }

            // If the character had old Qualities that were converted, immediately save the file so they are in the new format.
            if (blnHasOldQualities)
                Save();

            return true;
        }
        /// <summary>
        /// Locate a Martial Art Technique within the character's Martial Arts.
        /// </summary>
        /// <param name="strGuid">InternalId of the Martial Art Advantage to find.</param>
        /// <param name="lstMartialArts">List of Martial Arts to search.</param>
        /// <param name="objFoundMartialArt">MartialArt the Technique was found in.</param>
        public static MartialArtTechnique FindMartialArtTechnique(this IEnumerable <MartialArt> lstMartialArts, string strGuid, out MartialArt objFoundMartialArt)
        {
            if (!string.IsNullOrWhiteSpace(strGuid) && !strGuid.IsEmptyGuid())
            {
                foreach (MartialArt objArt in lstMartialArts)
                {
                    foreach (MartialArtTechnique objTechnique in objArt.Techniques)
                    {
                        if (objTechnique.InternalId == strGuid)
                        {
                            objFoundMartialArt = objArt;
                            return(objTechnique);
                        }
                    }
                }
            }

            objFoundMartialArt = null;
            return(null);
        }
Example #16
0
        private bool ProcessBonus(Improvement.ImprovementSource objImprovementSource, ref string strSourceName,
			bool blnConcatSelectedValue,
			int intRating, string strFriendlyName, XmlNode bonusNode, string strUnique)
        {
            Log.Info("Has Child Nodes");
            // Add an Attribute.
            if (bonusNode.LocalName == ("addattribute"))
            {
                Log.Info("addattribute");
                if (bonusNode["name"].InnerText == "MAG")
                {
                    _objCharacter.MAGEnabled = true;
                    Log.Info("Calling CreateImprovement for MAG");
                    CreateImprovement("MAG", objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute,
                        "enableattribute", 0, 0);
                }
                else if (bonusNode["name"].InnerText == "RES")
                {
                    _objCharacter.RESEnabled = true;
                    Log.Info("Calling CreateImprovement for RES");
                    CreateImprovement("RES", objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute,
                        "enableattribute", 0, 0);
                }
            }

            // Enable a special tab.
            if (bonusNode.LocalName == ("enabletab"))
            {
                Log.Info("enabletab");
                foreach (XmlNode objXmlEnable in bonusNode.ChildNodes)
                {
                    switch (objXmlEnable.InnerText)
                    {
                        case "magician":
                            _objCharacter.MagicianEnabled = true;
                            Log.Info("magician");
                            CreateImprovement("Magician", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab,
                                "enabletab", 0, 0);
                            break;
                        case "adept":
                            _objCharacter.AdeptEnabled = true;
                            Log.Info("adept");
                            CreateImprovement("Adept", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab,
                                "enabletab",
                                0, 0);
                            break;
                        case "technomancer":
                            _objCharacter.TechnomancerEnabled = true;
                            Log.Info("technomancer");
                            CreateImprovement("Technomancer", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab,
                                "enabletab", 0, 0);
                            break;
                        case "critter":
                            _objCharacter.CritterEnabled = true;
                            Log.Info("critter");
                            CreateImprovement("Critter", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab,
                                "enabletab", 0, 0);
                            break;
                        case "initiation":
                            _objCharacter.InitiationEnabled = true;
                            Log.Info("initiation");
                            CreateImprovement("Initiation", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab,
                                "enabletab", 0, 0);
                            break;
                    }
                }
            }

            // Select Restricted (select Restricted items for Fake Licenses).
            if (bonusNode.LocalName == ("selectrestricted"))
            {
                Log.Info("selectrestricted");
                frmSelectItem frmPickItem = new frmSelectItem();
                frmPickItem.Character = _objCharacter;
                if (_strForcedValue != string.Empty)
                    frmPickItem.ForceItem = _strForcedValue;
                frmPickItem.AllowAutoSelect = false;
                frmPickItem.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickItem.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickItem.SelectedItem;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                // Create the Improvement.
                Log.Info("Calling CreateImprovement");
                CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName,
                    Improvement.ImprovementType.Restricted, strUnique);
            }

            if (bonusNode.LocalName == "cyberseeker")
            {
                //Check if valid attrib
                if (new string[] {"BOD", "AGI", "STR", "REA", "LOG", "CHA", "INT", "WIL", "BOX"}.Any(x => x == bonusNode.InnerText))
                {
                    CreateImprovement(bonusNode.InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.Seeker, strUnique,0,0,0,0,0,0);

                }
                else
                {
                    Utils.BreakIfDebug();
                }

            }

            // Select a Skill.
            if (bonusNode.LocalName == ("selectskill"))
            {
                //TODO this don't work
                Log.Info("selectskill");
                if (_strForcedValue == "+2 to a Combat Skill")
                    _strForcedValue = "";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("_strForcedValue = " + _strForcedValue);

                // Display the Select Skill window and record which Skill was selected.
                frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                if (strFriendlyName != "")
                    frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed")
                        .Replace("{0}", strFriendlyName);
                else
                    frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

                Log.Info("selectskill = " + bonusNode.OuterXml.ToString());
                if (bonusNode.OuterXml.Contains("skillgroup"))
                    frmPickSkill.OnlySkillGroup = bonusNode.Attributes["skillgroup"].InnerText;
                else if (bonusNode.OuterXml.Contains("skillcategory"))
                    frmPickSkill.OnlyCategory = bonusNode.Attributes["skillcategory"].InnerText;
                else if (bonusNode.OuterXml.Contains("excludecategory"))
                    frmPickSkill.ExcludeCategory = bonusNode.Attributes["excludecategory"].InnerText;
                else if (bonusNode.OuterXml.Contains("limittoskill"))
                    frmPickSkill.LimitToSkill = bonusNode.Attributes["limittoskill"].InnerText;
                else if (bonusNode.OuterXml.Contains("limittoattribute"))
                    frmPickSkill.LinkedAttribute = bonusNode.Attributes["limittoattribute"].InnerText;

                if (_strForcedValue != "")
                {
                    frmPickSkill.OnlySkill = _strForcedValue;
                    frmPickSkill.Opacity = 0;
                }
                frmPickSkill.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickSkill.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                bool blnAddToRating = false;
                if (bonusNode["applytorating"] != null)
                {
                    if (bonusNode["applytorating"].InnerText == "yes")
                        blnAddToRating = true;
                }

                _strSelectedValue = frmPickSkill.SelectedSkill;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                // Find the selected Skill.
                foreach (Skill objSkill in _objCharacter.SkillsSection.Skills)
                {
                    if (frmPickSkill.SelectedSkill.Contains("Exotic Melee Weapon") ||
                        frmPickSkill.SelectedSkill.Contains("Exotic Ranged Weapon") ||
                        frmPickSkill.SelectedSkill.Contains("Pilot Exotic Vehicle"))
                    {
                        if (objSkill.Name + " (" + objSkill.Specialization + ")" == frmPickSkill.SelectedSkill)
                        {
                            // We've found the selected Skill.
                            if (bonusNode.InnerXml.Contains("val"))
                            {
                                Log.Info("Calling CreateImprovement");
                                CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName,
                                    Improvement.ImprovementType.Skill, strUnique, ValueToInt(bonusNode["val"].InnerText, intRating), 1,
                                    0, 0, 0, 0, "", blnAddToRating);
                            }

                            if (bonusNode.InnerXml.Contains("max"))
                            {
                                Log.Info("Calling CreateImprovement");
                                CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName,
                                    Improvement.ImprovementType.Skill, strUnique, 0, 1, 0,
                                    ValueToInt(bonusNode["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                            }
                        }
                    }
                    else
                    {
                        if (objSkill.Name == frmPickSkill.SelectedSkill)
                        {
                            // We've found the selected Skill.
                            if (bonusNode.InnerXml.Contains("val"))
                            {
                                Log.Info("Calling CreateImprovement");
                                CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill,
                                    strUnique,
                                    ValueToInt(bonusNode["val"].InnerText, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }

                            if (bonusNode.InnerXml.Contains("max"))
                            {
                                Log.Info("Calling CreateImprovement");
                                CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill,
                                    strUnique,
                                    0, 1, 0, ValueToInt(bonusNode["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                            }
                        }
                    }
                }
            }

            // Select a Skill Group.
            if (bonusNode.LocalName == ("selectskillgroup"))
            {
                Log.Info("selectskillgroup");
                string strExclude = "";
                if (bonusNode.Attributes["excludecategory"] != null)
                    strExclude = bonusNode.Attributes["excludecategory"].InnerText;

                frmSelectSkillGroup frmPickSkillGroup = new frmSelectSkillGroup();
                if (strFriendlyName != "")
                    frmPickSkillGroup.Description =
                        LanguageManager.Instance.GetString("String_Improvement_SelectSkillGroupName").Replace("{0}", strFriendlyName);
                else
                    frmPickSkillGroup.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillGroup");

                Log.Info("_strForcedValue = " + _strForcedValue);
                Log.Info("_strLimitSelection = " + _strLimitSelection);

                if (_strForcedValue != "")
                {
                    frmPickSkillGroup.OnlyGroup = _strForcedValue;
                    frmPickSkillGroup.Opacity = 0;
                }

                if (strExclude != string.Empty)
                    frmPickSkillGroup.ExcludeCategory = strExclude;

                frmPickSkillGroup.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickSkillGroup.DialogResult == DialogResult.Cancel)
                {
                    Rollback();

                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                bool blnAddToRating = false;
                if (bonusNode["applytorating"] != null)
                {
                    if (bonusNode["applytorating"].InnerText == "yes")
                        blnAddToRating = true;
                }

                _strSelectedValue = frmPickSkillGroup.SelectedSkillGroup;

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                if (bonusNode.SelectSingleNode("bonus") != null)
                {
                    Log.Info("Calling CreateImprovement");
                    CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup,
                        strUnique, ValueToInt(bonusNode["bonus"].InnerText, intRating), 1, 0, 0, 0, 0, strExclude,
                        blnAddToRating);
                }
                else
                {
                    Log.Info("Calling CreateImprovement");
                    CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup,
                        strUnique, 0, 0, 0, 1, 0, 0, strExclude,
                        blnAddToRating);
                }
            }

            if (bonusNode.LocalName == ("selectattributes"))
            {
                foreach (XmlNode objXmlAttribute in bonusNode.SelectNodes("selectattribute"))
                {
                    Log.Info("selectattribute");
                    // Display the Select Attribute window and record which Skill was selected.
                    frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                    if (strFriendlyName != "")
                        frmPickAttribute.Description =
                            LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                    else
                        frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                    // Add MAG and/or RES to the list of Attributes if they are enabled on the form.
                    if (_objCharacter.MAGEnabled)
                        frmPickAttribute.AddMAG();
                    if (_objCharacter.RESEnabled)
                        frmPickAttribute.AddRES();

                    Log.Info("selectattribute = " + bonusNode.OuterXml.ToString());

                    if (objXmlAttribute.InnerXml.Contains("<attribute>"))
                    {
                        List<string> strValue = new List<string>();
                        foreach (XmlNode objSubNode in objXmlAttribute.SelectNodes("attribute"))
                            strValue.Add(objSubNode.InnerText);
                        frmPickAttribute.LimitToList(strValue);
                    }

                    if (bonusNode.InnerXml.Contains("<excludeattribute>"))
                    {
                        List<string> strValue = new List<string>();
                        foreach (XmlNode objSubNode in objXmlAttribute.SelectNodes("excludeattribute"))
                            strValue.Add(objSubNode.InnerText);
                        frmPickAttribute.RemoveFromList(strValue);
                    }

                    // Check to see if there is only one possible selection because of _strLimitSelection.
                    if (_strForcedValue != "")
                        _strLimitSelection = _strForcedValue;

                    Log.Info("_strForcedValue = " + _strForcedValue);
                    Log.Info("_strLimitSelection = " + _strLimitSelection);

                    if (_strLimitSelection != "")
                    {
                        frmPickAttribute.SingleAttribute(_strLimitSelection);
                        frmPickAttribute.Opacity = 0;
                    }

                    frmPickAttribute.ShowDialog();

                    // Make sure the dialogue window was not canceled.
                    if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                    {
                        Rollback();
                        _strForcedValue = "";
                        return false;
                    }

                    _strSelectedValue = frmPickAttribute.SelectedAttribute;
                    if (blnConcatSelectedValue)
                        strSourceName += " (" + _strSelectedValue + ")";

                    Log.Info("_strSelectedValue = " + _strSelectedValue);
                    Log.Info("strSourceName = " + strSourceName);

                    // Record the improvement.
                    int intMin = 0;
                    int intAug = 0;
                    int intMax = 0;
                    int intAugMax = 0;

                    // Extract the modifiers.
                    if (objXmlAttribute.InnerXml.Contains("min"))
                        intMin = Convert.ToInt32(objXmlAttribute["min"].InnerText);
                    if (objXmlAttribute.InnerXml.Contains("val"))
                        intAug = Convert.ToInt32(objXmlAttribute["val"].InnerText);
                    if (objXmlAttribute.InnerXml.Contains("max"))
                        intMax = Convert.ToInt32(objXmlAttribute["max"].InnerText);
                    if (objXmlAttribute.InnerXml.Contains("aug"))
                        intAugMax = Convert.ToInt32(objXmlAttribute["aug"].InnerText);

                    string strAttribute = frmPickAttribute.SelectedAttribute;

                    if (objXmlAttribute["affectbase"] != null)
                        strAttribute += "Base";

                    Log.Info("Calling CreateImprovement");
                    CreateImprovement(strAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute,
                        strUnique,
                        0, 1, intMin, intMax, intAug, intAugMax);
                }
            }

            // Select an CharacterAttribute.
            if (bonusNode.LocalName == ("selectattribute"))
            {
                Log.Info("selectattribute");
                // Display the Select Attribute window and record which Skill was selected.
                frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                if (strFriendlyName != "")
                    frmPickAttribute.Description =
                        LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                else
                    frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                // Add MAG and/or RES to the list of Attributes if they are enabled on the form.
                if (_objCharacter.MAGEnabled)
                    frmPickAttribute.AddMAG();
                if (_objCharacter.RESEnabled)
                    frmPickAttribute.AddRES();

                Log.Info("selectattribute = " + bonusNode.OuterXml.ToString());

                if (bonusNode.InnerXml.Contains("<attribute>"))
                {
                    List<string> strValue = new List<string>();
                    foreach (XmlNode objXmlAttribute in bonusNode.SelectNodes("attribute"))
                        strValue.Add(objXmlAttribute.InnerText);
                    frmPickAttribute.LimitToList(strValue);
                }

                if (bonusNode.InnerXml.Contains("<excludeattribute>"))
                {
                    List<string> strValue = new List<string>();
                    foreach (XmlNode objXmlAttribute in bonusNode.SelectNodes("excludeattribute"))
                        strValue.Add(objXmlAttribute.InnerText);
                    frmPickAttribute.RemoveFromList(strValue);
                }

                // Check to see if there is only one possible selection because of _strLimitSelection.
                if (_strForcedValue != "")
                    _strLimitSelection = _strForcedValue;

                Log.Info("_strForcedValue = " + _strForcedValue);
                Log.Info("_strLimitSelection = " + _strLimitSelection);

                if (_strLimitSelection != "")
                {
                    frmPickAttribute.SingleAttribute(_strLimitSelection);
                    frmPickAttribute.Opacity = 0;
                }

                frmPickAttribute.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    return false;
                }

                _strSelectedValue = frmPickAttribute.SelectedAttribute;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                // Record the improvement.
                int intMin = 0;
                int intAug = 0;
                int intMax = 0;
                int intAugMax = 0;

                // Extract the modifiers.
                if (bonusNode.InnerXml.Contains("min"))
                    intMin = ValueToInt(bonusNode["min"].InnerXml, intRating);
                if (bonusNode.InnerXml.Contains("val"))
                    intAug = ValueToInt(bonusNode["val"].InnerXml, intRating);
                if (bonusNode.InnerXml.Contains("max"))
                    intMax = ValueToInt(bonusNode["max"].InnerXml, intRating);
                if (bonusNode.InnerXml.Contains("aug"))
                    intAugMax = ValueToInt(bonusNode["aug"].InnerXml, intRating);

                string strAttribute = frmPickAttribute.SelectedAttribute;

                if (bonusNode["affectbase"] != null)
                    strAttribute += "Base";

                Log.Info("Calling CreateImprovement");
                CreateImprovement(strAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute,
                    strUnique,
                    0, 1, intMin, intMax, intAug, intAugMax);
            }

            // Select a Limit.
            if (bonusNode.LocalName == ("selectlimit"))
            {
                Log.Info("selectlimit");
                // Display the Select Limit window and record which Limit was selected.
                frmSelectLimit frmPickLimit = new frmSelectLimit();
                if (strFriendlyName != "")
                    frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimitNamed")
                        .Replace("{0}", strFriendlyName);
                else
                    frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimit");

                Log.Info("selectlimit = " + bonusNode.OuterXml.ToString());

                if (bonusNode.InnerXml.Contains("<limit>"))
                {
                    List<string> strValue = new List<string>();
                    foreach (XmlNode objXmlAttribute in bonusNode.SelectNodes("limit"))
                        strValue.Add(objXmlAttribute.InnerText);
                    frmPickLimit.LimitToList(strValue);
                }

                if (bonusNode.InnerXml.Contains("<excludelimit>"))
                {
                    List<string> strValue = new List<string>();
                    foreach (XmlNode objXmlAttribute in bonusNode.SelectNodes("excludelimit"))
                        strValue.Add(objXmlAttribute.InnerText);
                    frmPickLimit.RemoveFromList(strValue);
                }

                // Check to see if there is only one possible selection because of _strLimitSelection.
                if (_strForcedValue != "")
                    _strLimitSelection = _strForcedValue;

                Log.Info("_strForcedValue = " + _strForcedValue);
                Log.Info("_strLimitSelection = " + _strLimitSelection);

                if (_strLimitSelection != "")
                {
                    frmPickLimit.SingleLimit(_strLimitSelection);
                    frmPickLimit.Opacity = 0;
                }

                frmPickLimit.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickLimit.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    return false;
                }

                _strSelectedValue = frmPickLimit.SelectedLimit;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                // Record the improvement.
                int intMin = 0;
                int intAug = 0;
                int intMax = 0;
                int intAugMax = 0;

                // Extract the modifiers.
                if (bonusNode.InnerXml.Contains("min"))
                    intMin = ValueToInt(bonusNode["min"].InnerXml, intRating);
                if (bonusNode.InnerXml.Contains("val"))
                    intAug = ValueToInt(bonusNode["val"].InnerXml, intRating);
                if (bonusNode.InnerXml.Contains("max"))
                    intMax = ValueToInt(bonusNode["max"].InnerXml, intRating);
                if (bonusNode.InnerXml.Contains("aug"))
                    intAugMax = ValueToInt(bonusNode["aug"].InnerXml, intRating);

                string strLimit = frmPickLimit.SelectedLimit;

                if (bonusNode["affectbase"] != null)
                    strLimit += "Base";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                LimitModifier objLimitMod = new LimitModifier(_objCharacter);
                // string strBonus = bonusNode["value"].InnerText;
                int intBonus = intAug;
                string strName = strFriendlyName;
                TreeNode nodTemp = new TreeNode();
                Improvement.ImprovementType objType = Improvement.ImprovementType.PhysicalLimit;

                switch (strLimit)
                {
                    case "Mental":
                        {
                            objType = Improvement.ImprovementType.MentalLimit;
                            break;
                        }
                    case "Social":
                        {
                            objType = Improvement.ImprovementType.SocialLimit;
                            break;
                        }
                    default:
                        {
                            objType = Improvement.ImprovementType.PhysicalLimit;
                            break;
                        }
                }

                Log.Info("Calling CreateImprovement");
                CreateImprovement(strLimit, objImprovementSource, strSourceName, objType, strFriendlyName, intBonus, 0, intMin,
                    intMax,
                    intAug, intAugMax);
            }

            // Select an CharacterAttribute to use instead of the default on a skill.
            if (bonusNode.LocalName == ("swapskillattribute"))
            {
                Log.Info("swapskillattribute");
                // Display the Select Attribute window and record which Skill was selected.
                frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                if (strFriendlyName != "")
                    frmPickAttribute.Description =
                        LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                else
                    frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                List<string> strValue = new List<string>();
                strValue.Add("LOG");
                strValue.Add("WIL");
                strValue.Add("INT");
                strValue.Add("CHA");
                strValue.Add("EDG");
                strValue.Add("MAG");
                strValue.Add("RES");
                frmPickAttribute.RemoveFromList(strValue);

                Log.Info("swapskillattribute = " + bonusNode.OuterXml.ToString());

                if (bonusNode.InnerXml.Contains("<attribute>"))
                {
                    List<string> strLimitValue = new List<string>();
                    foreach (XmlNode objXmlAttribute in bonusNode.SelectNodes("attribute"))
                        strLimitValue.Add(objXmlAttribute.InnerText);
                    frmPickAttribute.LimitToList(strLimitValue);
                }

                // Check to see if there is only one possible selection because of _strLimitSelection.
                if (_strForcedValue != "")
                    _strLimitSelection = _strForcedValue;

                Log.Info("_strForcedValue = " + _strForcedValue);
                Log.Info("_strLimitSelection = " + _strLimitSelection);

                if (_strLimitSelection != "")
                {
                    frmPickAttribute.SingleAttribute(_strLimitSelection);
                    frmPickAttribute.Opacity = 0;
                }

                frmPickAttribute.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickAttribute.SelectedAttribute;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                Log.Info("Calling CreateImprovement");
                CreateImprovement(frmPickAttribute.SelectedAttribute, objImprovementSource, strSourceName,
                    Improvement.ImprovementType.SwapSkillAttribute, strUnique);
            }

            // Select a Spell.
            if (bonusNode.LocalName == ("selectspell"))
            {
                Log.Info("selectspell");
                // Display the Select Spell window.
                frmSelectSpell frmPickSpell = new frmSelectSpell(_objCharacter);

                if (bonusNode.Attributes["category"] != null)
                    frmPickSpell.LimitCategory = bonusNode.Attributes["category"].InnerText;

                Log.Info("selectspell = " + bonusNode.OuterXml.ToString());
                Log.Info("_strForcedValue = " + _strForcedValue);
                Log.Info("_strLimitSelection = " + _strLimitSelection);

                if (_strForcedValue != "")
                {
                    frmPickSpell.ForceSpellName = _strForcedValue;
                    frmPickSpell.Opacity = 0;
                }

                frmPickSpell.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickSpell.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickSpell.SelectedSpell;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                Log.Info("Calling CreateImprovement");
                CreateImprovement(frmPickSpell.SelectedSpell, objImprovementSource, strSourceName, Improvement.ImprovementType.Text,
                    strUnique);
            }

            // Select a Contact
            if (bonusNode.LocalName == ("selectcontact"))
            {
                Log.Info("selectcontact");
                XmlNode nodSelect = bonusNode;

                frmSelectItem frmSelect = new frmSelectItem();

                String strMode = NodeExists(nodSelect, "type")
                    ? nodSelect["type"].InnerText
                    : "all";

                List<Contact> selectedContactsList;
                if (strMode == "all")
                {
                    selectedContactsList = new List<Contact>(_objCharacter.Contacts);
                }
                else if (strMode == "group" || strMode == "nongroup")
                {
                    bool blnGroup = strMode == "group";

                    //Select any contact where IsGroup equals blnGroup
                    //and add to a list
                    selectedContactsList =
                        new List<Contact>(from contact in _objCharacter.Contacts
                            where contact.IsGroup == blnGroup
                            select contact);
                }
                else
                {
                    Rollback();
                    return false;
                }

                if (selectedContactsList.Count == 0)
                {
                    MessageBox.Show(LanguageManager.Instance.GetString("Message_NoContactFound"),
                        LanguageManager.Instance.GetString("MessageTitle_NoContactFound"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Rollback();
                    return false;
                }

                int count = 0;
                //Black magic LINQ to cast content of list to another type
                List<ListItem> contacts = new List<ListItem>(from x in selectedContactsList
                    select new ListItem() {Name = x.Name, Value = (count++).ToString()});

                String strPrice = NodeExists(nodSelect, "cost")
                    ? nodSelect["cost"].InnerText
                    : "";

                frmSelect.GeneralItems = contacts;
                frmSelect.ShowDialog();

                int index = int.Parse(frmSelect.SelectedItem);
                if (frmSelect.DialogResult != DialogResult.Cancel)
                {
                    Contact selectedContact = selectedContactsList[index];

                    if (nodSelect["mademan"] != null)
                    {
                        selectedContact.MadeMan = true;
                        CreateImprovement(selectedContact.GUID, Improvement.ImprovementSource.Quality, strSourceName,
                            Improvement.ImprovementType.ContactMadeMan, selectedContact.GUID);
                    }

                    if (String.IsNullOrWhiteSpace(_strSelectedValue))
                    {
                        _strSelectedValue = selectedContact.Name;
                    }
                    else
                    {
                        _strSelectedValue += (", " + selectedContact.Name);
                    }
                }
                else
                {
                    Rollback();
                    return false;
                }
            }

            if (bonusNode.LocalName == "addcontact")
            {
                Log.Info("addcontact");

                int loyalty, connection;

                bonusNode.TryGetField("loyalty", out loyalty, 1);
                bonusNode.TryGetField("connection", out connection, 1);
                bool group = bonusNode["group"] != null;
                bool free = bonusNode["free"] != null;

                Contact contact = new Contact(_objCharacter);
                contact.Free = free;
                contact.IsGroup = group;
                contact.Loyalty = loyalty;
                contact.Connection = connection;
                contact.ReadOnly = true;
                _objCharacter.Contacts.Add(contact);

                CreateImprovement(contact.GUID, Improvement.ImprovementSource.Quality, strSourceName,
                            Improvement.ImprovementType.AddContact, contact.GUID);
            }

            // Affect a Specific CharacterAttribute.
            if (bonusNode.LocalName == ("specificattribute"))
            {
                Log.Info("specificattribute");

                if (bonusNode["name"].InnerText != "ESS")
                {
                    // Display the Select CharacterAttribute window and record which CharacterAttribute was selected.
                    // Record the improvement.
                    int intMin = 0;
                    int intAug = 0;
                    int intMax = 0;
                    int intAugMax = 0;

                    // Extract the modifiers.
                    if (bonusNode.InnerXml.Contains("min"))
                        intMin = ValueToInt(bonusNode["min"].InnerXml, intRating);
                    if (bonusNode.InnerXml.Contains("val"))
                        intAug = ValueToInt(bonusNode["val"].InnerXml, intRating);
                    if (bonusNode.InnerXml.Contains("max"))
                    {
                        if (bonusNode["max"].InnerText.Contains("-natural"))
                        {
                            intMax = Convert.ToInt32(bonusNode["max"].InnerText.Replace("-natural", string.Empty)) -
                                     _objCharacter.GetAttribute(bonusNode["name"].InnerText).MetatypeMaximum;
                        }
                        else
                            intMax = ValueToInt(bonusNode["max"].InnerXml, intRating);
                    }
                    if (bonusNode.InnerXml.Contains("aug"))
                        intAugMax = ValueToInt(bonusNode["aug"].InnerXml, intRating);

                    string strUseUnique = strUnique;
                    if (bonusNode["name"].Attributes["precedence"] != null)
                        strUseUnique = "precedence" + bonusNode["name"].Attributes["precedence"].InnerText;

                    string strAttribute = bonusNode["name"].InnerText;

                    if (bonusNode["affectbase"] != null)
                        strAttribute += "Base";

                    CreateImprovement(strAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute,
                        strUseUnique, 0, 1, intMin, intMax, intAug, intAugMax);
                }
                else
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Essence, "",
                        Convert.ToInt32(bonusNode["val"].InnerText));
                }
            }

            // Add a paid increase to an attribute
            if (bonusNode.LocalName == ("attributelevel"))
            {
                Log.Info(new object[] {"attributelevel", bonusNode.OuterXml});
                String strAttrib;
                int value;
                bonusNode.TryGetField("val", out value, 1);

                if (bonusNode.TryGetField("name", out strAttrib))
                {
                    CreateImprovement(strAttrib, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.Attributelevel, "", value);
                }
                else
                {
                    Log.Error(new object[] {"attributelevel", bonusNode.OuterXml});
                }
            }

            if (bonusNode.LocalName == ("skilllevel"))
            {
                Log.Info(new object[] {"skilllevel", bonusNode.OuterXml});
                String strSkill;
                int value;
                bonusNode.TryGetField("val", out value, 1);
                if (bonusNode.TryGetField("name", out strSkill))
                {
                    CreateImprovement(strSkill, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillLevel, "", value);

                }
                else
                {
                    Log.Error(new object[] {"skilllevel", bonusNode.OuterXml});
                }
            }

            if (bonusNode.LocalName == "pushtext")
            {

                String push = bonusNode.InnerText;
                if (!String.IsNullOrWhiteSpace(push))
                {
                    _objCharacter.Pushtext.Push(push);
                }
            }

            if (bonusNode.LocalName == "knowsoft")
            {
                int val = bonusNode["val"] != null ? ValueToInt(bonusNode["val"].InnerText, intRating) : 1;

                string name;
                if (!string.IsNullOrWhiteSpace(_strForcedValue))
                {
                    name = _strForcedValue;
                }
                else if (bonusNode["pick"] != null)
                {
                    List<ListItem> types;
                    if (bonusNode["group"] != null)
                    {
                        var v = bonusNode.SelectNodes($"./group");
                        types =
                            KnowledgeSkill.KnowledgeTypes.Where(x => bonusNode.SelectNodes($"group[. = '{x.Value}']").Count > 0).ToList();

                    }
                    else if (bonusNode["notgroup"] != null)
                    {
                        types =
                            KnowledgeSkill.KnowledgeTypes.Where(x => bonusNode.SelectNodes($"notgroup[. = '{x.Value}']").Count == 0).ToList();
                    }
                    else
                    {
                        types = KnowledgeSkill.KnowledgeTypes;
                    }

                    frmSelectItem select = new frmSelectItem();
                    select.DropdownItems = KnowledgeSkill.KnowledgeSkillsWithCategory(types.Select(x => x.Value).ToArray());

                    select.ShowDialog();
                    if (select.DialogResult == DialogResult.Cancel)
                    {
                        return false;
                    }

                    name = select.SelectedItem;
                }
                else if (bonusNode["name"] != null)
                {
                    name = bonusNode["name"].InnerText;
                }
                else
                {
                    //TODO some kind of error handling
                    Log.Error(new[] {bonusNode.OuterXml, "Missing pick or name"});
                    return false;
                }
                _strSelectedValue = name;

                KnowledgeSkill skill = new KnowledgeSkill(_objCharacter, name);

                bool knowsoft = bonusNode.TryCheckValue("require", "skilljack");

                if (knowsoft)
                {
                    _objCharacter.SkillsSection.KnowsoftSkills.Add(skill);
                    if (_objCharacter.SkillsoftAccess)
                    {
                        _objCharacter.SkillsSection.KnowledgeSkills.Add(skill);
                    }
                }
                else
                {
                    _objCharacter.SkillsSection.KnowledgeSkills.Add(skill);
                }

                CreateImprovement(name, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillBase, strUnique, val);
                CreateImprovement(skill.Id.ToString(), objImprovementSource, strSourceName,
                    Improvement.ImprovementType.SkillKnowledgeForced, strUnique);

            }

            if (bonusNode.LocalName == "knowledgeskilllevel")
            {
                //Theoretically life modules, right now we just give out free points and let people sort it out themselves.
                //Going to be fun to do the real way, from a computer science perspective, but i don't feel like using 2 weeks on that now

                int val = bonusNode["val"] != null ? ValueToInt(bonusNode["val"].InnerText, intRating) : 1;
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeKnowledgeSkills, "", val);
            }

            if (bonusNode.LocalName == "knowledgeskillpoints")
            {
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeKnowledgeSkills, "", ValueToInt(bonusNode.InnerText,Convert.ToInt32(bonusNode.Value)));
            }

            if (bonusNode.LocalName == ("skillgrouplevel"))
            {
                Log.Info(new object[] {"skillgrouplevel", bonusNode.OuterXml});
                String strSkillGroup;
                int value;
                if (bonusNode.TryGetField("name", out strSkillGroup) &&
                    bonusNode.TryGetField("val", out value))
                {
                    CreateImprovement(strSkillGroup, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillGroupLevel, "", value);
                }
                else
                {
                    Log.Error(new object[] {"skillgrouplevel", bonusNode.OuterXml});
                }
            }

            // Change the maximum number of BP that can be spent on Nuyen.
            if (bonusNode.LocalName == ("nuyenmaxbp"))
            {
                Log.Info("nuyenmaxbp");
                Log.Info("nuyenmaxbp = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.NuyenMaxBP, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Apply a bonus/penalty to physical limit.
            if (bonusNode.LocalName == ("physicallimit"))
            {
                Log.Info("physicallimit");
                Log.Info("physicallimit = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("Physical", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalLimit, strFriendlyName,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Apply a bonus/penalty to mental limit.
            if (bonusNode.LocalName == ("mentallimit"))
            {
                Log.Info("mentallimit");
                Log.Info("mentallimit = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("Mental", objImprovementSource, strSourceName, Improvement.ImprovementType.MentalLimit, strFriendlyName,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Apply a bonus/penalty to social limit.
            if (bonusNode.LocalName == ("sociallimit"))
            {
                Log.Info("sociallimit");
                Log.Info("sociallimit = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("Social", objImprovementSource, strSourceName, Improvement.ImprovementType.SocialLimit, strFriendlyName,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Change the amount of Nuyen the character has at creation time (this can put the character over the amount they're normally allowed).
            if (bonusNode.LocalName == ("nuyenamt"))
            {
                Log.Info("nuyenamt");
                Log.Info("nuyenamt = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Nuyen, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Improve Condition Monitors.
            if (bonusNode.LocalName == ("conditionmonitor"))
            {
                Log.Info("conditionmonitor");
                Log.Info("conditionmonitor = " + bonusNode.OuterXml.ToString());
                // Physical Condition.
                if (bonusNode.InnerXml.Contains("physical"))
                {
                    Log.Info("Calling CreateImprovement for Physical");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalCM, strUnique,
                        ValueToInt(bonusNode["physical"].InnerText, intRating));
                }

                // Stun Condition.
                if (bonusNode.InnerXml.Contains("stun"))
                {
                    Log.Info("Calling CreateImprovement for Stun");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.StunCM, strUnique,
                        ValueToInt(bonusNode["stun"].InnerText, intRating));
                }

                // Condition Monitor Threshold.
                if (NodeExists(bonusNode, "threshold"))
                {
                    string strUseUnique = strUnique;
                    if (bonusNode["threshold"].Attributes["precedence"] != null)
                        strUseUnique = "precedence" + bonusNode["threshold"].Attributes["precedence"].InnerText;

                    Log.Info("Calling CreateImprovement for Threshold");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThreshold, strUseUnique,
                        ValueToInt(bonusNode["threshold"].InnerText, intRating));
                }

                // Condition Monitor Threshold Offset. (Additioal boxes appear before the FIRST Condition Monitor penalty)
                if (NodeExists(bonusNode, "thresholdoffset"))
                {
                    string strUseUnique = strUnique;
                    if (bonusNode["thresholdoffset"].Attributes["precedence"] != null)
                        strUseUnique = "precedence" + bonusNode["thresholdoffset"].Attributes["precedence"].InnerText;

                    Log.Info("Calling CreateImprovement for Threshold Offset");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThresholdOffset,
                        strUseUnique, ValueToInt(bonusNode["thresholdoffset"].InnerText, intRating));
                }

                // Condition Monitor Overflow.
                if (bonusNode.InnerXml.Contains("overflow"))
                {
                    Log.Info("Calling CreateImprovement for Overflow");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMOverflow, strUnique,
                        ValueToInt(bonusNode["overflow"].InnerText, intRating));
                }
            }

            // Improve Living Personal Attributes.
            if (bonusNode.LocalName == ("livingpersona"))
            {
                Log.Info("livingpersona");
                Log.Info("livingpersona = " + bonusNode.OuterXml.ToString());
                // Response.
                if (bonusNode.InnerXml.Contains("response"))
                {
                    Log.Info("Calling CreateImprovement for response");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaResponse,
                        strUnique, ValueToInt(bonusNode["response"].InnerText, intRating));
                }

                // Signal.
                if (bonusNode.InnerXml.Contains("signal"))
                {
                    Log.Info("Calling CreateImprovement for signal");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSignal,
                        strUnique,
                        ValueToInt(bonusNode["signal"].InnerText, intRating));
                }

                // Firewall.
                if (bonusNode.InnerXml.Contains("firewall"))
                {
                    Log.Info("Calling CreateImprovement for firewall");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaFirewall,
                        strUnique, ValueToInt(bonusNode["firewall"].InnerText, intRating));
                }

                // System.
                if (bonusNode.InnerXml.Contains("system"))
                {
                    Log.Info("Calling CreateImprovement for system");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSystem,
                        strUnique,
                        ValueToInt(bonusNode["system"].InnerText, intRating));
                }

                // Biofeedback Filter.
                if (bonusNode.InnerXml.Contains("biofeedback"))
                {
                    Log.Info("Calling CreateImprovement for biofeedback");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaBiofeedback,
                        strUnique, ValueToInt(bonusNode["biofeedback"].InnerText, intRating));
                }
            }

            // The Improvement adjusts a specific Skill.
            if (bonusNode.LocalName == ("specificskill"))
            {
                Log.Info("specificskill");
                Log.Info("specificskill = " + bonusNode.OuterXml.ToString());
                bool blnAddToRating = false;
                if (bonusNode["applytorating"] != null)
                {
                    if (bonusNode["applytorating"].InnerText == "yes")
                        blnAddToRating = true;
                }

                string strUseUnique = strUnique;
                if (bonusNode.Attributes["precedence"] != null)
                    strUseUnique = "precedence" + bonusNode.Attributes["precedence"].InnerText;

                // Record the improvement.
                if (bonusNode["bonus"] != null)
                {
                    Log.Info("Calling CreateImprovement for bonus");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.Skill, strUseUnique, ValueToInt(bonusNode["bonus"].InnerXml, intRating), 1, 0, 0, 0,
                        0, "", blnAddToRating);
                }
                if (bonusNode["max"] != null)
                {
                    Log.Info("Calling CreateImprovement for max");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.Skill, strUseUnique, 0, 1, 0, ValueToInt(bonusNode["max"].InnerText, intRating), 0,
                        0,
                        "", blnAddToRating);
                }
            }

            if (bonusNode.LocalName == "reflexrecorderoptimization")
            {
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ReflexRecorderOptimization, strUnique);
            }

            // The Improvement adds a martial art
            if (bonusNode.LocalName == ("martialart"))
            {
                Log.Info("martialart");
                Log.Info("martialart = " + bonusNode.OuterXml.ToString());
                XmlDocument _objXmlDocument = XmlManager.Instance.Load("martialarts.xml");
                XmlNode objXmlArt =
                    _objXmlDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + bonusNode.InnerText +
                                                     "\"]");

                TreeNode objNode = new TreeNode();
                MartialArt objMartialArt = new MartialArt(_objCharacter);
                objMartialArt.Create(objXmlArt, objNode, _objCharacter);
                objMartialArt.IsQuality = true;
                _objCharacter.MartialArts.Add(objMartialArt);
            }

            // The Improvement adds a limit modifier
            if (bonusNode.LocalName == ("limitmodifier"))
            {
                Log.Info("limitmodifier");
                Log.Info("limitmodifier = " + bonusNode.OuterXml.ToString());
                LimitModifier objLimitMod = new LimitModifier(_objCharacter);
                string strLimit = bonusNode["limit"].InnerText;
                string strBonus = bonusNode["value"].InnerText;
                if (strBonus == "Rating")
                {
                    strBonus = intRating.ToString();
                }
                string strCondition = "";
                try
                {
                    strCondition = bonusNode["condition"].InnerText;
                }
                catch
                {
                }
                int intBonus = 0;
                if (strBonus == "Rating")
                    intBonus = intRating;
                else
                    intBonus = Convert.ToInt32(strBonus);
                string strName = strFriendlyName;
                TreeNode nodTemp = new TreeNode();
                Log.Info("Calling CreateImprovement");
                CreateImprovement(strLimit, objImprovementSource, strSourceName, Improvement.ImprovementType.LimitModifier,
                    strFriendlyName, intBonus, 0, 0, 0, 0, 0, strCondition);
            }

            // The Improvement adjusts a Skill Category.
            if (bonusNode.LocalName == ("skillcategory"))
            {
                Log.Info("skillcategory");
                Log.Info("skillcategory = " + bonusNode.OuterXml.ToString());

                bool blnAddToRating = false;
                if (bonusNode["applytorating"] != null)
                {
                    if (bonusNode["applytorating"].InnerText == "yes")
                        blnAddToRating = true;
                }
                if (bonusNode.InnerXml.Contains("exclude"))
                {
                    Log.Info("Calling CreateImprovement - exclude");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillCategory, strUnique, ValueToInt(bonusNode["bonus"].InnerXml, intRating), 1, 0,
                        0,
                        0, 0, bonusNode["exclude"].InnerText, blnAddToRating);
                }
                else
                {
                    Log.Info("Calling CreateImprovement");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillCategory, strUnique, ValueToInt(bonusNode["bonus"].InnerXml, intRating), 1, 0,
                        0,
                        0, 0, "", blnAddToRating);
                }
            }

            // The Improvement adjusts a Skill Group.
            if (bonusNode.LocalName == ("skillgroup"))
            {
                Log.Info("skillgroup");
                Log.Info("skillgroup = " + bonusNode.OuterXml.ToString());

                bool blnAddToRating = false;
                if (bonusNode["applytorating"] != null)
                {
                    if (bonusNode["applytorating"].InnerText == "yes")
                        blnAddToRating = true;
                }
                if (bonusNode.InnerXml.Contains("exclude"))
                {
                    Log.Info("Calling CreateImprovement - exclude");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(bonusNode["bonus"].InnerXml, intRating), 1, 0, 0, 0,
                        0, bonusNode["exclude"].InnerText, blnAddToRating);
                }
                else
                {
                    Log.Info("Calling CreateImprovement");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(bonusNode["bonus"].InnerXml, intRating), 1, 0, 0, 0,
                        0, "", blnAddToRating);
                }
            }

            // The Improvement adjust Skills with the given CharacterAttribute.
            if (bonusNode.LocalName == ("skillattribute"))
            {
                Log.Info("skillattribute");
                Log.Info("skillattribute = " + bonusNode.OuterXml.ToString());

                string strUseUnique = strUnique;
                if (bonusNode["name"].Attributes["precedence"] != null)
                    strUseUnique = "precedence" + bonusNode["name"].Attributes["precedence"].InnerText;

                bool blnAddToRating = false;
                if (bonusNode["applytorating"] != null)
                {
                    if (bonusNode["applytorating"].InnerText == "yes")
                        blnAddToRating = true;
                }
                if (bonusNode.InnerXml.Contains("exclude"))
                {
                    Log.Info("Calling CreateImprovement - exclude");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillAttribute, strUseUnique, ValueToInt(bonusNode["bonus"].InnerXml, intRating), 1,
                        0, 0, 0, 0, bonusNode["exclude"].InnerText, blnAddToRating);
                }
                else
                {
                    Log.Info("Calling CreateImprovement");
                    CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.SkillAttribute, strUseUnique, ValueToInt(bonusNode["bonus"].InnerXml, intRating), 1,
                        0, 0, 0, 0, "", blnAddToRating);
                }
            }

            // The Improvement comes from Enhanced Articulation (improves Physical Active Skills linked to a Physical CharacterAttribute).
            if (bonusNode.LocalName == ("skillarticulation"))
            {
                Log.Info("skillarticulation");
                Log.Info("skillarticulation = " + bonusNode.OuterXml.ToString());

                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EnhancedArticulation,
                    strUnique,
                    ValueToInt(bonusNode["bonus"].InnerText, intRating));
            }

            // Check for Armor modifiers.
            if (bonusNode.LocalName == ("armor"))
            {
                Log.Info("armor");
                Log.Info("armor = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                string strUseUnique = strUnique;
                if (bonusNode.Attributes["precedence"] != null)
                {
                    strUseUnique = "precedence" + bonusNode.Attributes["precedence"].InnerText;
                }
                else if (bonusNode.Attributes["group"] != null)
                {
                    strUseUnique = "group" + bonusNode.Attributes["group"].InnerText;
                }
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Armor, strUseUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Reach modifiers.
            if (bonusNode.LocalName == ("reach"))
            {
                Log.Info("reach");
                Log.Info("reach = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Reach, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Unarmed Damage Value modifiers.
            if (bonusNode.LocalName == ("unarmeddv"))
            {
                Log.Info("unarmeddv");
                Log.Info("unarmeddv = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDV, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Unarmed Damage Value Physical.
            if (bonusNode.LocalName == ("unarmeddvphysical"))
            {
                Log.Info("unarmeddvphysical");
                Log.Info("unarmeddvphysical = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDVPhysical, "");
            }

            // Check for Unarmed Armor Penetration.
            if (bonusNode.LocalName == ("unarmedap"))
            {
                Log.Info("unarmedap");
                Log.Info("unarmedap = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedAP, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Initiative modifiers.
            if (bonusNode.LocalName == ("initiative"))
            {
                Log.Info("initiative");
                Log.Info("initiative = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiative, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Initiative Pass modifiers. Only the highest one ever applies.
            if (bonusNode.LocalName == ("initiativepass"))
            {
                Log.Info("initiativepass");
                Log.Info("initiativepass = "******"Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.InitiativePass,
                    "initiativepass", ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Initiative Pass modifiers. Only the highest one ever applies.
            if (bonusNode.LocalName == ("initiativepassadd"))
            {
                Log.Info("initiativepassadd");
                Log.Info("initiativepassadd = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.InitiativePassAdd, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Matrix Initiative modifiers.
            if (bonusNode.LocalName == ("matrixinitiative"))
            {
                Log.Info("matrixinitiative");
                Log.Info("matrixinitiative = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiative, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Matrix Initiative Pass modifiers.
            if (bonusNode.LocalName == ("matrixinitiativepass"))
            {
                Log.Info("matrixinitiativepass");
                Log.Info("matrixinitiativepass = "******"Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass,
                    "matrixinitiativepass", ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Matrix Initiative Pass modifiers.
            if (bonusNode.LocalName == ("matrixinitiativepassadd"))
            {
                Log.Info("matrixinitiativepassadd");
                Log.Info("matrixinitiativepassadd = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass,
                    strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Lifestyle cost modifiers.
            if (bonusNode.LocalName == ("lifestylecost"))
            {
                Log.Info("lifestylecost");
                Log.Info("lifestylecost = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LifestyleCost, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for basic Lifestyle cost modifiers.
            if (bonusNode.LocalName == ("basiclifestylecost"))
            {
                Log.Info("basiclifestylecost");
                Log.Info("basiclifestylecost = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicLifestyleCost, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Genetech Cost modifiers.
            if (bonusNode.LocalName == ("genetechcostmultiplier"))
            {
                Log.Info("genetechcostmultiplier");
                Log.Info("genetechcostmultiplier = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.GenetechCostMultiplier,
                    strUnique, ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Genetech: Transgenics Cost modifiers.
            if (bonusNode.LocalName == ("transgenicsgenetechcost"))
            {
                Log.Info("transgenicsgenetechcost");
                Log.Info("transgenicsgenetechcost = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.TransgenicsBiowareCost,
                    strUnique, ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Basic Bioware Essence Cost modifiers.
            if (bonusNode.LocalName == ("basicbiowareessmultiplier"))
            {
                Log.Info("basicbiowareessmultiplier");
                Log.Info("basicbiowareessmultiplier = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicBiowareEssCost,
                    strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Bioware Essence Cost modifiers.
            if (bonusNode.LocalName == ("biowareessmultiplier"))
            {
                Log.Info("biowareessmultiplier");
                Log.Info("biowareessmultiplier = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BiowareEssCost, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Cybeware Essence Cost modifiers.
            if (bonusNode.LocalName == ("cyberwareessmultiplier"))
            {
                Log.Info("cyberwareessmultiplier");
                Log.Info("cyberwareessmultiplier = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CyberwareEssCost, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Uneducated modifiers.
            if (bonusNode.LocalName == ("uneducated"))
            {
                Log.Info("uneducated");
                Log.Info("uneducated = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uneducated, strUnique);
                _objCharacter.SkillsSection.Uneducated = true;
            }

            // Check for College Education modifiers.
            if (bonusNode.LocalName == ("collegeeducation"))
            {
                Log.Info("collegeeducation");
                Log.Info("collegeeducation = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CollegeEducation, strUnique);
                _objCharacter.SkillsSection.CollegeEducation = true;
            }

            // Check for Jack Of All Trades modifiers.
            if (bonusNode.LocalName == ("jackofalltrades"))
            {
                Log.Info("jackofalltrades");
                Log.Info("jackofalltrades = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.JackOfAllTrades, strUnique);
                _objCharacter.SkillsSection.JackOfAllTrades = true;
            }

            // Check for Prototype Transhuman modifiers.
            if (bonusNode.LocalName == ("prototypetranshuman"))
            {
                Log.Info("prototypetranshuman");
                Log.Info("prototypetranshuman = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");

                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PrototypeTranshuman, strUnique);
                _objCharacter.PrototypeTranshuman = Convert.ToDecimal(bonusNode.InnerText);

            }
            // Check for Uncouth modifiers.
            if (bonusNode.LocalName == ("uncouth"))
            {
                Log.Info("uncouth");
                Log.Info("uncouth = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uncouth, strUnique);
                _objCharacter.SkillsSection.Uncouth = true;
            }

            // Check for Friends In High Places modifiers.
            if (bonusNode.LocalName == ("friendsinhighplaces"))
            {
                Log.Info("friendsinhighplaces");
                Log.Info("friendsinhighplaces = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FriendsInHighPlaces,
                    strUnique);
                _objCharacter.FriendsInHighPlaces = true;
            }
            // Check for School of Hard Knocks modifiers.
            if (bonusNode.LocalName == ("schoolofhardknocks"))
            {
                Log.Info("schoolofhardknocks");
                Log.Info("schoolofhardknocks = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SchoolOfHardKnocks, strUnique);
                _objCharacter.SkillsSection.SchoolOfHardKnocks = true;
            }
            // Check for ExCon modifiers.
            if (bonusNode.LocalName == ("excon"))
            {
                Log.Info("ExCon");
                Log.Info("ExCon = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ExCon, strUnique);
                _objCharacter.ExCon = true;
            }

            // Check for TrustFund modifiers.
            if (bonusNode.LocalName == ("trustfund"))
            {
                Log.Info("TrustFund");
                Log.Info("TrustFund = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.TrustFund,
                    strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
                _objCharacter.TrustFund = ValueToInt(bonusNode.InnerText, intRating);
            }

            // Check for Tech School modifiers.
            if (bonusNode.LocalName == ("techschool"))
            {
                Log.Info("techschool");
                Log.Info("techschool = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.TechSchool, strUnique);
                _objCharacter.SkillsSection.TechSchool = true;
            }
            // Check for MadeMan modifiers.
            if (bonusNode.LocalName == ("mademan"))
            {
                Log.Info("MadeMan");
                Log.Info("MadeMan = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MadeMan, strUnique);
                _objCharacter.MadeMan = true;
            }

            // Check for Linguist modifiers.
            if (bonusNode.LocalName == ("linguist"))
            {
                Log.Info("Linguist");
                Log.Info("Linguist = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Linguist, strUnique);
                _objCharacter.SkillsSection.Linguist = true;
            }

            // Check for LightningReflexes modifiers.
            if (bonusNode.LocalName == ("lightningreflexes"))
            {
                Log.Info("LightningReflexes");
                Log.Info("LightningReflexes = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LightningReflexes, strUnique);
                _objCharacter.LightningReflexes = true;
            }

            // Check for Fame modifiers.
            if (bonusNode.LocalName == ("fame"))
            {
                Log.Info("Fame");
                Log.Info("Fame = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Fame, strUnique);
                _objCharacter.Fame = true;
            }
            // Check for BornRich modifiers.
            if (bonusNode.LocalName == ("bornrich"))
            {
                Log.Info("BornRich");
                Log.Info("BornRich = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BornRich, strUnique);
                _objCharacter.BornRich = true;
            }
            // Check for Erased modifiers.
            if (bonusNode.LocalName == ("erased"))
            {
                Log.Info("Erased");
                Log.Info("Erased = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Erased, strUnique);
                _objCharacter.Erased = true;
            }
            // Check for Erased modifiers.
            if (bonusNode.LocalName == ("overclocker"))
            {
                Log.Info("OverClocker");
                Log.Info("Overclocker = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Overclocker, strUnique);
                _objCharacter.Overclocker = true;
            }

            // Check for Restricted Gear modifiers.
            if (bonusNode.LocalName == ("restrictedgear"))
            {
                Log.Info("restrictedgear");
                Log.Info("restrictedgear = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.RestrictedGear, strUnique);
                _objCharacter.RestrictedGear = true;
            }

            // Check for Adept Linguistics.
            if (bonusNode.LocalName == ("adeptlinguistics"))
            {
                Log.Info("adeptlinguistics");
                Log.Info("adeptlinguistics = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptLinguistics, strUnique,
                    1);
            }

            // Check for Weapon Category DV modifiers.
            if (bonusNode.LocalName == ("weaponcategorydv"))
            {
                //TODO: FIX THIS
                /*
                 * I feel like talking a little bit about improvementmanager at
                 * this point. It is an intresting class. First of all, it
                 * manages to throw out everything we ever learned about OOP
                 * and create a class based on functional programming.
                 *
                 * That is true, it is a class, based on manipulating a single
                 * list on another class.
                 *
                 * But atleast there is a reference to it somewhere right?
                 *
                 * No, you create one wherever you need it, meaning there are
                 * tens of instances of this class, all operating on the same
                 * list
                 *
                 * After that, it is just plain stupid.
                 * If you have an list of xmlNodes and some might be the same
                 * it checks if a specific node exists (sometimes even by text
                 * comparison on .OuterXml) and then runs specific code for
                 * each. If it is there multiple times either of those 2 things
                 * happen.
                 *
                 * 1. Sad, nothing we can do, guess you have to survive
                 * 2. Lets create a foreach in that specific part of the code
                 *
                 * F**k ImprovementManager, kill it with fire, burn the ashes
                 * and feed what remains to a dragon that eats unholy
                 * abominations
                 */

                Log.Info("weaponcategorydv");
                Log.Info("weaponcategorydv = " + bonusNode.OuterXml.ToString());
                XmlNodeList objXmlCategoryList = bonusNode.SelectNodes("weaponcategorydv");
                XmlNode nodWeapon = bonusNode;

                if (NodeExists(nodWeapon, "selectskill"))
                {
                    // Display the Select Skill window and record which Skill was selected.
                    frmSelectItem frmPickCategory = new frmSelectItem();
                    List<ListItem> lstGeneralItems = new List<ListItem>();

                    ListItem liBlades = new ListItem();
                    liBlades.Name = "Blades";
                    liBlades.Value = "Blades";

                    ListItem liClubs = new ListItem();
                    liClubs.Name = "Clubs";
                    liClubs.Value = "Clubs";

                    ListItem liUnarmed = new ListItem();
                    liUnarmed.Name = "Unarmed";
                    liUnarmed.Value = "Unarmed";

                    ListItem liAstral = new ListItem();
                    liAstral.Name = "Astral Combat";
                    liAstral.Value = "Astral Combat";

                    ListItem liExotic = new ListItem();
                    liExotic.Name = "Exotic Melee Weapons";
                    liExotic.Value = "Exotic Melee Weapons";

                    lstGeneralItems.Add(liAstral);
                    lstGeneralItems.Add(liBlades);
                    lstGeneralItems.Add(liClubs);
                    lstGeneralItems.Add(liExotic);
                    lstGeneralItems.Add(liUnarmed);
                    frmPickCategory.GeneralItems = lstGeneralItems;

                    if (strFriendlyName != "")
                        frmPickCategory.Description =
                            LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed").Replace("{0}", strFriendlyName);
                    else
                        frmPickCategory.Description = LanguageManager.Instance.GetString("Title_SelectWeaponCategory");

                    Log.Info("_strForcedValue = " + _strForcedValue);

                    if (_strForcedValue.StartsWith("Adept:") || _strForcedValue.StartsWith("Magician:"))
                        _strForcedValue = "";

                    if (_strForcedValue != "")
                    {
                        frmPickCategory.Opacity = 0;
                    }
                    frmPickCategory.ShowDialog();

                    // Make sure the dialogue window was not canceled.
                    if (frmPickCategory.DialogResult == DialogResult.Cancel)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }

                    _strSelectedValue = frmPickCategory.SelectedItem;

                    Log.Info("strSelected = " + _strSelectedValue);

                    foreach (Power objPower in _objCharacter.Powers)
                    {
                        if (objPower.InternalId == strSourceName)
                        {
                            objPower.Extra = _strSelectedValue;
                        }
                    }

                    Log.Info("Calling CreateImprovement");
                    CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName,
                        Improvement.ImprovementType.WeaponCategoryDV, strUnique, ValueToInt(nodWeapon["bonus"].InnerXml, intRating));
                }
                else
                {
                    // Run through each of the Skill Groups since there may be more than one affected.
                    foreach (XmlNode objXmlCategory in objXmlCategoryList)
                    {
                        Log.Info("Calling CreateImprovement");
                        CreateImprovement(objXmlCategory["name"].InnerText, objImprovementSource, strSourceName,
                            Improvement.ImprovementType.WeaponCategoryDV, strUnique, ValueToInt(objXmlCategory["bonus"].InnerXml, intRating));
                    }
                }
            }

            // Check for Mentor Spirit bonuses.
            if (bonusNode.LocalName == ("selectmentorspirit"))
            {
                Log.Info("selectmentorspirit");
                Log.Info("selectmentorspirit = " + bonusNode.OuterXml.ToString());
                frmSelectMentorSpirit frmPickMentorSpirit = new frmSelectMentorSpirit(_objCharacter);
                frmPickMentorSpirit.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickMentorSpirit.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickMentorSpirit.SelectedMentor;

                string strHoldValue = _strSelectedValue;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                if (frmPickMentorSpirit.BonusNode != null)
                {
                    if (!CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.BonusNode,
                        blnConcatSelectedValue, intRating, strFriendlyName))
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }
                }

                if (frmPickMentorSpirit.Choice1BonusNode != null)
                {
                    Log.Info("frmPickMentorSpirit.Choice1BonusNode = " + frmPickMentorSpirit.Choice1BonusNode.OuterXml.ToString());
                    string strForce = _strForcedValue;
                    if (!frmPickMentorSpirit.Choice1.StartsWith("Adept:") && !frmPickMentorSpirit.Choice1.StartsWith("Magician:"))
                        _strForcedValue = frmPickMentorSpirit.Choice1;
                    else
                        _strForcedValue = "";
                    Log.Info("Calling CreateImprovement");
                    bool blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice1BonusNode,
                        blnConcatSelectedValue, intRating, strFriendlyName);
                    if (!blnSuccess)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }
                    _strForcedValue = strForce;
                    _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice1;
                }

                if (frmPickMentorSpirit.Choice2BonusNode != null)
                {
                    Log.Info("frmPickMentorSpirit.Choice2BonusNode = " + frmPickMentorSpirit.Choice2BonusNode.OuterXml.ToString());
                    string strForce = _strForcedValue;
                    if (!frmPickMentorSpirit.Choice2.StartsWith("Adept:") && !frmPickMentorSpirit.Choice2.StartsWith("Magician:"))
                        _strForcedValue = frmPickMentorSpirit.Choice2;
                    else
                        _strForcedValue = "";
                    Log.Info("Calling CreateImprovement");
                    bool blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice2BonusNode,
                        blnConcatSelectedValue, intRating, strFriendlyName);
                    if (!blnSuccess)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }
                    _strForcedValue = strForce;
                    _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice2;
                }

                _strSelectedValue = strHoldValue;
                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("_strForcedValue = " + _strForcedValue);
            }

            // Check for Paragon bonuses.
            if (bonusNode.LocalName == ("selectparagon"))
            {
                Log.Info("selectparagon");
                Log.Info("selectparagon = " + bonusNode.OuterXml.ToString());
                frmSelectMentorSpirit frmPickMentorSpirit = new frmSelectMentorSpirit(_objCharacter);
                frmPickMentorSpirit.XmlFile = "paragons.xml";
                frmPickMentorSpirit.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickMentorSpirit.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickMentorSpirit.SelectedMentor;
                string strHoldValue = _strSelectedValue;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                if (frmPickMentorSpirit.BonusNode != null)
                {
                    bool blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.BonusNode,
                        blnConcatSelectedValue, intRating, strFriendlyName);
                    if (!blnSuccess)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }
                }

                if (frmPickMentorSpirit.Choice1BonusNode != null)
                {
                    string strForce = _strForcedValue;
                    _strForcedValue = frmPickMentorSpirit.Choice1;
                    bool blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice1BonusNode,
                        blnConcatSelectedValue, intRating, strFriendlyName);
                    if (!blnSuccess)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }
                    _strForcedValue = strForce;
                    _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice1;
                }

                if (frmPickMentorSpirit.Choice2BonusNode != null)
                {
                    string strForce = _strForcedValue;
                    _strForcedValue = frmPickMentorSpirit.Choice2;
                    bool blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice2BonusNode,
                        blnConcatSelectedValue, intRating, strFriendlyName);
                    if (!blnSuccess)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }
                    _strForcedValue = strForce;
                    _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice2;
                }

                _strSelectedValue = strHoldValue;
            }

            // Check for Smartlink bonus.
            if (bonusNode.LocalName == ("smartlink"))
            {
                Log.Info("smartlink");
                Log.Info("smartlink = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Smartlink, "smartlink");
            }

            // Check for Adapsin bonus.
            if (bonusNode.LocalName == ("adapsin"))
            {
                Log.Info("adapsin");
                Log.Info("adapsin = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Adapsin, "adapsin");
            }

            // Check for SoftWeave bonus.
            if (bonusNode.LocalName == ("softweave"))
            {
                Log.Info("softweave");
                Log.Info("softweave = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SoftWeave, "softweave");
            }

            // Check for Sensitive System.
            if (bonusNode.LocalName == ("sensitivesystem"))
            {
                Log.Info("sensitivesystem");
                Log.Info("sensitivesystem = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SensitiveSystem,
                    "sensitivesystem");
            }

            // Check for Movement Percent.
            if (bonusNode.LocalName == ("movementpercent"))
            {
                Log.Info("movementpercent");
                Log.Info("movementpercent = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MovementPercent, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Swim Percent.
            if (bonusNode.LocalName == ("swimpercent"))
            {
                Log.Info("swimpercent");
                Log.Info("swimpercent = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SwimPercent, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Fly Percent.
            if (bonusNode.LocalName == ("flypercent"))
            {
                Log.Info("flypercent");
                Log.Info("flypercent = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlyPercent, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Fly Speed.
            if (bonusNode.LocalName == ("flyspeed"))
            {
                Log.Info("flyspeed");
                Log.Info("flyspeed = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlySpeed, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for free Positive Qualities.
            if (bonusNode.LocalName == ("freepositivequalities"))
            {
                Log.Info("freepositivequalities");
                Log.Info("freepositivequalities = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreePositiveQualities, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for free Negative Qualities.
            if (bonusNode.LocalName == ("freenegativequalities"))
            {
                Log.Info("freenegativequalities");
                Log.Info("freenegativequalities = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeNegativeQualities, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Select Side.
            if (bonusNode.LocalName == ("selectside"))
            {
                Log.Info("selectside");
                Log.Info("selectside = " + bonusNode.OuterXml.ToString());
                frmSelectSide frmPickSide = new frmSelectSide();
                frmPickSide.Description = LanguageManager.Instance.GetString("Label_SelectSide").Replace("{0}", strFriendlyName);
                if (_strForcedValue != "")
                    frmPickSide.ForceValue(_strForcedValue);
                else
                    frmPickSide.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickSide.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickSide.SelectedSide;
                Log.Info("_strSelectedValue = " + _strSelectedValue);
            }

            // Check for Free Spirit Power Points.
            if (bonusNode.LocalName == ("freespiritpowerpoints"))
            {
                Log.Info("freespiritpowerpoints");
                Log.Info("freespiritpowerpoints = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeSpiritPowerPoints, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Adept Power Points.
            if (bonusNode.LocalName == ("adeptpowerpoints"))
            {
                Log.Info("adeptpowerpoints");
                Log.Info("adeptpowerpoints = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptPowerPoints, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Adept Powers
            if (bonusNode.LocalName == ("specificpower"))
            {
                //TODO: Probably broken
                Log.Info("specificpower");
                Log.Info("specificpower = " + bonusNode.OuterXml.ToString());
                // If the character isn't an adept or mystic adept, skip the rest of this.
                if (_objCharacter.AdeptEnabled)
                {
                    string strSelection = "";
                    _strForcedValue = "";

                    Log.Info("objXmlSpecificPower = " + bonusNode.OuterXml.ToString());

                    string strPowerName = bonusNode["name"].InnerText;
                    int intLevels = 0;
                    if (bonusNode["val"] != null)
                        intLevels = Convert.ToInt32(bonusNode["val"].InnerText);
                    bool blnFree = false;
                    if (bonusNode["free"] != null)
                        blnFree = (bonusNode["free"].InnerText == "yes");

                    string strPowerNameLimit = strPowerName;
                    if (bonusNode["selectlimit"] != null)
                    {
                        Log.Info("selectlimit = " + bonusNode["selectlimit"].OuterXml.ToString());
                        _strForcedValue = "";
                        // Display the Select Limit window and record which Limit was selected.
                        frmSelectLimit frmPickLimit = new frmSelectLimit();
                        if (strFriendlyName != "")
                            frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimitNamed")
                                .Replace("{0}", strFriendlyName);
                        else
                            frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimit");

                        if (bonusNode["selectlimit"].InnerXml.Contains("<limit>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in bonusNode["selectlimit"].SelectNodes("limit"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickLimit.LimitToList(strValue);
                        }

                        if (bonusNode["selectlimit"].InnerXml.Contains("<excludelimit>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in bonusNode["selectlimit"].SelectNodes("excludelimit"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickLimit.RemoveFromList(strValue);
                        }

                        // Check to see if there is only one possible selection because of _strLimitSelection.
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

                        Log.Info("_strForcedValue = " + _strForcedValue);
                        Log.Info("_strLimitSelection = " + _strLimitSelection);

                        if (_strLimitSelection != "")
                        {
                            frmPickLimit.SingleLimit(_strLimitSelection);
                            frmPickLimit.Opacity = 0;
                        }

                        frmPickLimit.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickLimit.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickLimit.SelectedLimit;
                        strSelection = _strSelectedValue;
                        _strForcedValue = _strSelectedValue;

                        Log.Info("_strForcedValue = " + _strForcedValue);
                        Log.Info("_strLimitSelection = " + _strLimitSelection);
                    }

                    if (bonusNode["selectskill"] != null)
                    {
                        Log.Info("selectskill = " + bonusNode["selectskill"].OuterXml.ToString());
                        XmlNode nodSkill = bonusNode;
                        // Display the Select Skill window and record which Skill was selected.
                        frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                        if (strFriendlyName != "")
                            frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed")
                                .Replace("{0}", strFriendlyName);
                        else
                            frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

                        if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillgroup"))
                            frmPickSkill.OnlySkillGroup = nodSkill.SelectSingleNode("selectskill").Attributes["skillgroup"].InnerText;
                        else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillcategory"))
                            frmPickSkill.OnlyCategory = nodSkill.SelectSingleNode("selectskill").Attributes["skillcategory"].InnerText;
                        else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("excludecategory"))
                            frmPickSkill.ExcludeCategory = nodSkill.SelectSingleNode("selectskill").Attributes["excludecategory"].InnerText;
                        else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("limittoskill"))
                            frmPickSkill.LimitToSkill = nodSkill.SelectSingleNode("selectskill").Attributes["limittoskill"].InnerText;

                        if (_strForcedValue.StartsWith("Adept:") || _strForcedValue.StartsWith("Magician:"))
                            _strForcedValue = "";

                        Log.Info("_strForcedValue = " + _strForcedValue);
                        Log.Info("_strLimitSelection = " + _strLimitSelection);

                        if (_strForcedValue != "")
                        {
                            frmPickSkill.OnlySkill = _strForcedValue;
                            frmPickSkill.Opacity = 0;
                        }
                        frmPickSkill.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickSkill.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickSkill.SelectedSkill;
                        _strForcedValue = _strSelectedValue;
                        strSelection = _strSelectedValue;

                        Log.Info("_strForcedValue = " + _strForcedValue);
                        Log.Info("_strSelectedValue = " + _strSelectedValue);
                        Log.Info("strSelection = " + strSelection);
                    }

                    if (bonusNode["selecttext"] != null)
                    {
                        Log.Info("selecttext = " + bonusNode["selecttext"].OuterXml.ToString());
                        frmSelectText frmPickText = new frmSelectText();

                        if (_objCharacter.Pushtext.Count > 0)
                        {
                            strSelection = _objCharacter.Pushtext.Pop();
                        }
                        else
                        {
                            frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText")
                                .Replace("{0}", strFriendlyName);

                            Log.Info("_strForcedValue = " + _strForcedValue);
                            Log.Info("_strLimitSelection = " + _strLimitSelection);

                            if (_strLimitSelection != "")
                            {
                                frmPickText.SelectedValue = _strLimitSelection;
                                frmPickText.Opacity = 0;
                            }

                            frmPickText.ShowDialog();

                            // Make sure the dialogue window was not canceled.
                            if (frmPickText.DialogResult == DialogResult.Cancel)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return false;
                            }

                            strSelection = frmPickText.SelectedValue;
                            _strLimitSelection = strSelection;
                        }
                        Log.Info("_strLimitSelection = " + _strLimitSelection);
                        Log.Info("strSelection = " + strSelection);
                    }

                    if (bonusNode["specificattribute"] != null)
                    {
                        Log.Info("specificattribute = " + bonusNode["specificattribute"].OuterXml.ToString());
                        strSelection = bonusNode["specificattribute"]["name"].InnerText.ToString();
                        Log.Info(
                            "strSelection = " + strSelection);
                    }

                    if (bonusNode["selectattribute"] != null)
                    {
                        Log.Info("selectattribute = " + bonusNode["selectattribute"].OuterXml.ToString());
                        XmlNode nodSkill = bonusNode;
                        if (_strForcedValue.StartsWith("Adept"))
                            _strForcedValue = "";

                        // Display the Select CharacterAttribute window and record which CharacterAttribute was selected.
                        frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                        if (strFriendlyName != "")
                            frmPickAttribute.Description =
                                LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                        // Add MAG and/or RES to the list of Attributes if they are enabled on the form.
                        if (_objCharacter.MAGEnabled)
                            frmPickAttribute.AddMAG();
                        if (_objCharacter.RESEnabled)
                            frmPickAttribute.AddRES();

                        if (nodSkill["selectattribute"].InnerXml.Contains("<attribute>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("attribute"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickAttribute.LimitToList(strValue);
                        }

                        if (nodSkill["selectattribute"].InnerXml.Contains("<excludeattribute>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("excludeattribute"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickAttribute.RemoveFromList(strValue);
                        }

                        // Check to see if there is only one possible selection because of _strLimitSelection.
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

                        Log.Info("_strForcedValue = " + _strForcedValue);
                        Log.Info("_strLimitSelection = " + _strLimitSelection);

                        if (_strLimitSelection != "")
                        {
                            frmPickAttribute.SingleAttribute(_strLimitSelection);
                            frmPickAttribute.Opacity = 0;
                        }

                        frmPickAttribute.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickAttribute.SelectedAttribute;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";
                        strSelection = _strSelectedValue;
                        _strForcedValue = _strSelectedValue;

                        Log.Info("_strSelectedValue = " + _strSelectedValue);
                        Log.Info("strSourceName = " + strSourceName);
                        Log.Info("_strForcedValue = " + _strForcedValue);
                    }

                    // Check if the character already has this power
                    Log.Info("strSelection = " + strSelection);
                    bool blnHasPower = false;
                    Power objPower = new Power(_objCharacter);
                    foreach (Power power in _objCharacter.Powers)
                    {
                        if (power.Name == strPowerNameLimit)
                        {
                            if (power.Extra != "" && power.Extra == strSelection)
                            {
                                blnHasPower = true;
                                objPower = power;
                            }
                            else if (power.Extra == "")
                            {
                                blnHasPower = true;
                                objPower = power;
                            }
                        }
                    }

                    Log.Info("blnHasPower = " + blnHasPower);

                    if (blnHasPower)
                    {
                        // If yes, mark it free or give it free levels
                        if (blnFree)
                        {
                            objPower.Free = true;
                        }
                        else
                        {
                            objPower.FreeLevels += intLevels;
                            if (objPower.Rating < objPower.FreeLevels)
                                objPower.Rating = objPower.FreeLevels;
                        }
                    }
                    else
                    {
                        Log.Info("Adding Power " + strPowerName);
                        // If no, add the power and mark it free or give it free levels
                        objPower = new Power(_objCharacter);
                        _objCharacter.Powers.Add(objPower);

                        // Get the Power information
                        XmlDocument objXmlDocument = new XmlDocument();
                        objXmlDocument = XmlManager.Instance.Load("powers.xml");
                        XmlNode objXmlPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + strPowerName + "\"]");
                        Log.Info("objXmlPower = " + objXmlPower.OuterXml.ToString());

                        bool blnLevels = false;
                        if (objXmlPower["levels"] != null)
                            blnLevels = (objXmlPower["levels"].InnerText == "yes");
                        objPower.LevelsEnabled = blnLevels;
                        objPower.Name = strPowerNameLimit;
                        objPower.PointsPerLevel = Convert.ToDecimal(objXmlPower["points"].InnerText, GlobalOptions.Instance.CultureInfo);
                        objPower.Source = objXmlPower["source"].InnerText;
                        objPower.Page = objXmlPower["page"].InnerText;
                        if (strSelection != string.Empty)
                            objPower.Extra = strSelection;
                        if (objXmlPower["doublecost"] != null)
                            objPower.DoubleCost = false;

                        if (blnFree)
                        {
                            objPower.Free = true;
                        }
                        else
                        {
                            objPower.FreeLevels += intLevels;
                            if (objPower.Rating < intLevels)
                                objPower.Rating = objPower.FreeLevels;
                        }

                        if (objXmlPower.InnerXml.Contains("bonus"))
                        {
                            objPower.Bonus = objXmlPower["bonus"];
                            Log.Info("Calling CreateImprovements");
                            if (
                                !CreateImprovements(Improvement.ImprovementSource.Power, objPower.InternalId, objPower.Bonus, false,
                                    Convert.ToInt32(objPower.Rating), objPower.DisplayNameShort))
                            {
                                _objCharacter.Powers.Remove(objPower);
                            }
                        }
                    }
                    _strSelectedValue = "";
                    _strForcedValue = "";
                    strSelection = "";
                }
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptPower, "");
            }

            // Select a Power.
            if (bonusNode.LocalName == ("selectpowers"))
            {
                XmlNodeList objXmlPowerList = bonusNode.SelectNodes("selectpower");
                foreach (XmlNode objNode in objXmlPowerList)
                {
                    Log.Info("selectpower");
                    Log.Info("_strSelectedValue = " + _strSelectedValue);
                    Log.Info("_strForcedValue = " + _strForcedValue);

                    //Gerry: These unfortunately did not work in any case of multiple bonuses
                    // Switched the setting of powerpoints and levels to ADDING them
                    // Remove resetting powerpoints.
                    bool blnExistingPower = false;
                    foreach (Power objExistingPower in _objCharacter.Powers)
                    {
                        if (objExistingPower.Name.StartsWith("Improved Reflexes"))
                        {
                            if (objExistingPower.Name.EndsWith("1"))
                            {
                                if (objExistingPower.Name.EndsWith("1"))
                                {
                                    if (intRating >= 6)
                                        objExistingPower.FreePoints += 1.5M;
                                    //else
                                    //	objExistingPower.FreePoints = 0;
                                }
                                else if (objExistingPower.Name.EndsWith("2"))
                                {
                                    if (intRating >= 10)
                                        objExistingPower.FreePoints += 2.5M;
                                    else if (intRating >= 4)
                                        objExistingPower.FreePoints += 1.0M;
                                    //else
                                    //	objExistingPower.FreePoints = 0;
                                }
                                else
                                {
                                    if (intRating >= 14)
                                        objExistingPower.FreePoints += 3.5M;
                                    else if (intRating >= 8)
                                        objExistingPower.FreePoints += 2.0M;
                                    else if (intRating >= 4)
                                        objExistingPower.FreePoints += 1.0M;
                                    //else
                                    //	objExistingPower.FreePoints = 0;
                                }
                            }
                            else
                            {
                                // we have to adjust the number of free levels.
                                decimal decLevels = Convert.ToDecimal(intRating)/4;
                                decLevels = Math.Floor(decLevels/objExistingPower.PointsPerLevel);
                                objExistingPower.FreeLevels += Convert.ToInt32(decLevels);
                                if (objExistingPower.Rating < intRating)
                                    objExistingPower.Rating = objExistingPower.FreeLevels;
                                break;
                            }
                        }
                        else
                        {
                            // we have to adjust the number of free levels.
                            decimal decLevels = Convert.ToDecimal(intRating)/4;
                            decLevels = Math.Floor(decLevels/objExistingPower.PointsPerLevel);
                            objExistingPower.FreeLevels = Convert.ToInt32(decLevels);
                            if (objExistingPower.Rating < intRating)
                                objExistingPower.Rating = objExistingPower.FreeLevels;
                            break;
                        }
                        //}
                    }

                    if (!blnExistingPower)
                    {
                        // Display the Select Skill window and record which Skill was selected.
                        frmSelectPower frmPickPower = new frmSelectPower(_objCharacter);
                        Log.Info("selectpower = " + objNode.OuterXml.ToString());

                        if (objNode.OuterXml.Contains("limittopowers"))
                            frmPickPower.LimitToPowers = objNode.Attributes["limittopowers"].InnerText;
                        frmPickPower.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickPower.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickPower.SelectedPower;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        XmlDocument objXmlDocument = XmlManager.Instance.Load("powers.xml");
                        XmlNode objXmlPower =
                            objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + _strSelectedValue + "\"]");
                        string strSelection = "";

                        Log.Info("_strSelectedValue = " + _strSelectedValue);
                        Log.Info("strSourceName = " + strSourceName);

                        XmlNode objBonus = objXmlPower["bonus"];

                        string strPowerNameLimit = _strSelectedValue;
                        if (objBonus != null)
                        {
                            if (objBonus["selectlimit"] != null)
                            {
                                Log.Info("selectlimit = " + objBonus["selectlimit"].OuterXml.ToString());
                                _strForcedValue = "";
                                // Display the Select Limit window and record which Limit was selected.
                                frmSelectLimit frmPickLimit = new frmSelectLimit();
                                if (strFriendlyName != "")
                                    frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimitNamed")
                                        .Replace("{0}", strFriendlyName);
                                else
                                    frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimit");

                                if (objBonus["selectlimit"].InnerXml.Contains("<limit>"))
                                {
                                    List<string> strValue = new List<string>();
                                    foreach (XmlNode objXmlAttribute in objBonus["selectlimit"].SelectNodes("limit"))
                                        strValue.Add(objXmlAttribute.InnerText);
                                    frmPickLimit.LimitToList(strValue);
                                }

                                if (objBonus["selectlimit"].InnerXml.Contains("<excludelimit>"))
                                {
                                    List<string> strValue = new List<string>();
                                    foreach (XmlNode objXmlAttribute in objBonus["selectlimit"].SelectNodes("excludelimit"))
                                        strValue.Add(objXmlAttribute.InnerText);
                                    frmPickLimit.RemoveFromList(strValue);
                                }

                                // Check to see if there is only one possible selection because of _strLimitSelection.
                                if (_strForcedValue != "")
                                    _strLimitSelection = _strForcedValue;

                                Log.Info("_strForcedValue = " + _strForcedValue);
                                Log.Info("_strLimitSelection = " + _strLimitSelection);

                                if (_strLimitSelection != "")
                                {
                                    frmPickLimit.SingleLimit(_strLimitSelection);
                                    frmPickLimit.Opacity = 0;
                                }

                                frmPickLimit.ShowDialog();

                                // Make sure the dialogue window was not canceled.
                                if (frmPickLimit.DialogResult == DialogResult.Cancel)
                                {
                                    Rollback();
                                    _strForcedValue = "";
                                    _strLimitSelection = "";
                                    return false;
                                }

                                _strSelectedValue = frmPickLimit.SelectedLimit;
                                strSelection = _strSelectedValue;
                                _strForcedValue = _strSelectedValue;

                                Log.Info("_strForcedValue = " + _strForcedValue);
                                Log.Info("_strLimitSelection = " + _strLimitSelection);
                            }

                            if (objBonus["selectskill"] != null)
                            {
                                Log.Info("selectskill = " + objBonus["selectskill"].OuterXml.ToString());
                                XmlNode nodSkill = objBonus;
                                // Display the Select Skill window and record which Skill was selected.
                                frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                                if (strFriendlyName != "")
                                    frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed")
                                        .Replace("{0}", strFriendlyName);
                                else
                                    frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

                                if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillgroup"))
                                    frmPickSkill.OnlySkillGroup = nodSkill.SelectSingleNode("selectskill").Attributes["skillgroup"].InnerText;
                                else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillcategory"))
                                    frmPickSkill.OnlyCategory = nodSkill.SelectSingleNode("selectskill").Attributes["skillcategory"].InnerText;
                                else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("excludecategory"))
                                    frmPickSkill.ExcludeCategory = nodSkill.SelectSingleNode("selectskill").Attributes["excludecategory"].InnerText;
                                else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("limittoskill"))
                                    frmPickSkill.LimitToSkill = nodSkill.SelectSingleNode("selectskill").Attributes["limittoskill"].InnerText;

                                if (_strForcedValue.StartsWith("Adept:") || _strForcedValue.StartsWith("Magician:"))
                                    _strForcedValue = "";

                                Log.Info("_strForcedValue = " + _strForcedValue);
                                Log.Info("_strLimitSelection = " + _strLimitSelection);

                                if (_strForcedValue != "")
                                {
                                    frmPickSkill.OnlySkill = _strForcedValue;
                                    frmPickSkill.Opacity = 0;
                                }
                                frmPickSkill.ShowDialog();

                                // Make sure the dialogue window was not canceled.
                                if (frmPickSkill.DialogResult == DialogResult.Cancel)
                                {
                                    Rollback();
                                    _strForcedValue = "";
                                    _strLimitSelection = "";
                                    return false;
                                }

                                _strSelectedValue = frmPickSkill.SelectedSkill;
                                _strForcedValue = _strSelectedValue;
                                strSelection = _strSelectedValue;

                                Log.Info("_strForcedValue = " + _strForcedValue);
                                Log.Info("_strSelectedValue = " + _strSelectedValue);
                                Log.Info("strSelection = " + strSelection);
                            }

                            if (objBonus["selecttext"] != null)
                            {
                                Log.Info("selecttext = " + objBonus["selecttext"].OuterXml.ToString());
                                frmSelectText frmPickText = new frmSelectText();
                                frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText")
                                    .Replace("{0}", strFriendlyName);

                                Log.Info("_strForcedValue = " + _strForcedValue);
                                Log.Info("_strLimitSelection = " + _strLimitSelection);

                                if (_strLimitSelection != "")
                                {
                                    frmPickText.SelectedValue = _strLimitSelection;
                                    frmPickText.Opacity = 0;
                                }

                                frmPickText.ShowDialog();

                                // Make sure the dialogue window was not canceled.
                                if (frmPickText.DialogResult == DialogResult.Cancel)
                                {
                                    Rollback();
                                    _strForcedValue = "";
                                    _strLimitSelection = "";
                                    return false;
                                }

                                strSelection = frmPickText.SelectedValue;
                                _strLimitSelection = strSelection;

                                Log.Info("_strLimitSelection = " + _strLimitSelection);
                                Log.Info("strSelection = " + strSelection);
                            }

                            if (objBonus["specificattribute"] != null)
                            {
                                Log.Info("specificattribute = " + objBonus["specificattribute"].OuterXml.ToString());
                                strSelection = objBonus["specificattribute"]["name"].InnerText.ToString();
                                Log.Info("strSelection = " + strSelection);
                            }

                            if (objBonus["selectattribute"] != null)
                            {
                                Log.Info("selectattribute = " + objBonus["selectattribute"].OuterXml.ToString());
                                XmlNode nodSkill = objBonus;
                                if (_strForcedValue.StartsWith("Adept"))
                                    _strForcedValue = "";

                                // Display the Select CharacterAttribute window and record which CharacterAttribute was selected.
                                frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                                if (strFriendlyName != "")
                                    frmPickAttribute.Description =
                                        LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                                else
                                    frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                                // Add MAG and/or RES to the list of Attributes if they are enabled on the form.
                                if (_objCharacter.MAGEnabled)
                                    frmPickAttribute.AddMAG();
                                if (_objCharacter.RESEnabled)
                                    frmPickAttribute.AddRES();

                                if (nodSkill["selectattribute"].InnerXml.Contains("<attribute>"))
                                {
                                    List<string> strValue = new List<string>();
                                    foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("attribute"))
                                        strValue.Add(objXmlAttribute.InnerText);
                                    frmPickAttribute.LimitToList(strValue);
                                }

                                if (nodSkill["selectattribute"].InnerXml.Contains("<excludeattribute>"))
                                {
                                    List<string> strValue = new List<string>();
                                    foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("excludeattribute"))
                                        strValue.Add(objXmlAttribute.InnerText);
                                    frmPickAttribute.RemoveFromList(strValue);
                                }

                                // Check to see if there is only one possible selection because of _strLimitSelection.
                                if (_strForcedValue != "")
                                    _strLimitSelection = _strForcedValue;

                                Log.Info("_strForcedValue = " + _strForcedValue);
                                Log.Info("_strLimitSelection = " + _strLimitSelection);

                                if (_strLimitSelection != "")
                                {
                                    frmPickAttribute.SingleAttribute(_strLimitSelection);
                                    frmPickAttribute.Opacity = 0;
                                }

                                frmPickAttribute.ShowDialog();

                                // Make sure the dialogue window was not canceled.
                                if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                                {
                                    Rollback();
                                    _strForcedValue = "";
                                    _strLimitSelection = "";
                                    return false;
                                }

                                _strSelectedValue = frmPickAttribute.SelectedAttribute;
                                if (blnConcatSelectedValue)
                                    strSourceName += " (" + _strSelectedValue + ")";
                                strSelection = _strSelectedValue;
                                _strForcedValue = _strSelectedValue;

                                Log.Info("_strSelectedValue = " + _strSelectedValue);
                                Log.Info("strSourceName = " + strSourceName);
                                Log.Info("_strForcedValue = " + _strForcedValue);
                            }
                        }

                        // If no, add the power and mark it free or give it free levels
                        Power objPower = new Power(_objCharacter);
                        bool blnHasPower = false;

                        foreach (Power power in _objCharacter.Powers)
                        {
                            if (power.Name == objXmlPower["name"].InnerText)
                            {
                                if (power.Extra != "" && power.Extra == strSelection)
                                {
                                    blnHasPower = true;
                                    objPower = power;
                                }
                                else if (power.Extra == "")
                                {
                                    blnHasPower = true;
                                    objPower = power;
                                }
                            }
                        }

                        Log.Info("blnHasPower = " + blnHasPower);

                        if (blnHasPower)
                        {
                            // If yes, mark it free or give it free levels
                            if (objXmlPower["levels"].InnerText == "no")
                            {
                                if (objPower.Name.StartsWith("Improved Reflexes"))
                                {
                                    if (objPower.Name.EndsWith("1"))
                                    {
                                        if (intRating >= 6)
                                            objPower.FreePoints = 1.5M;
                                        else
                                            objPower.FreePoints = 0;
                                    }
                                    else if (objPower.Name.EndsWith("2"))
                                    {
                                        if (intRating >= 10)
                                            objPower.FreePoints = 2.5M;
                                        else if (intRating >= 4)
                                            objPower.FreePoints = 1.0M;
                                        else
                                            objPower.FreePoints = 0;
                                    }
                                    else
                                    {
                                        if (intRating >= 14)
                                            objPower.FreePoints = 3.5M;
                                        else if (intRating >= 8)
                                            objPower.FreePoints = 2.0M;
                                        else if (intRating >= 4)
                                            objPower.FreePoints = 1.0M;
                                        else
                                            objPower.FreePoints = 0;
                                    }
                                }
                                else
                                {
                                    objPower.Free = true;
                                }
                            }
                            else
                            {
                                decimal decLevels = Convert.ToDecimal(intRating)/4;
                                decLevels = Math.Floor(decLevels/objPower.PointsPerLevel);
                                objPower.FreeLevels += Convert.ToInt32(decLevels);
                                objPower.Rating += Convert.ToInt32(decLevels);
                            }
                            objPower.BonusSource = strSourceName;
                        }
                        else
                        {
                            Log.Info("Adding Power " + _strSelectedValue);
                            // Get the Power information
                            _objCharacter.Powers.Add(objPower);
                            Log.Info("objXmlPower = " + objXmlPower.OuterXml.ToString());

                            bool blnLevels = false;
                            if (objXmlPower["levels"] != null)
                                blnLevels = (objXmlPower["levels"].InnerText == "yes");
                            objPower.LevelsEnabled = blnLevels;
                            objPower.Name = objXmlPower["name"].InnerText;
                            objPower.PointsPerLevel = Convert.ToDecimal(objXmlPower["points"].InnerText, GlobalOptions.Instance.CultureInfo);
                            objPower.Source = objXmlPower["source"].InnerText;
                            objPower.Page = objXmlPower["page"].InnerText;
                            objPower.BonusSource = strSourceName;
                            if (strSelection != string.Empty)
                                objPower.Extra = strSelection;
                            if (objXmlPower["doublecost"] != null)
                                objPower.DoubleCost = false;

                            if (objXmlPower["levels"].InnerText == "no")
                            {
                                if (objPower.Name.StartsWith("Improved Reflexes"))
                                {
                                    if (objPower.Name.EndsWith("1"))
                                    {
                                        if (intRating >= 6)
                                            objPower.FreePoints = 1.5M;
                                        else
                                            objPower.FreePoints = 0;
                                    }
                                    else if (objPower.Name.EndsWith("2"))
                                    {
                                        if (intRating >= 10)
                                            objPower.FreePoints = 2.5M;
                                        else if (intRating >= 4)
                                            objPower.FreePoints = 1.0M;
                                        else
                                            objPower.FreePoints = 0;
                                    }
                                    else
                                    {
                                        if (intRating >= 14)
                                            objPower.FreePoints = 3.5M;
                                        else if (intRating >= 8)
                                            objPower.FreePoints = 2.0M;
                                        else if (intRating >= 4)
                                            objPower.FreePoints = 1.0M;
                                        else
                                            objPower.FreePoints = 0;
                                    }
                                }
                                else
                                {
                                    objPower.Free = true;
                                }
                            }
                            else
                            {
                                decimal decLevels = Convert.ToDecimal(intRating)/4;
                                decLevels = Math.Floor(decLevels/objPower.PointsPerLevel);
                                objPower.FreeLevels += Convert.ToInt32(decLevels);
                                if (objPower.Rating < intRating)
                                    objPower.Rating = objPower.FreeLevels;
                            }

                            if (objXmlPower.InnerXml.Contains("bonus"))
                            {
                                objPower.Bonus = objXmlPower["bonus"];
                                Log.Info("Calling CreateImprovements");
                                if (
                                    !CreateImprovements(Improvement.ImprovementSource.Power, objPower.InternalId, objPower.Bonus, false,
                                        Convert.ToInt32(objPower.Rating), objPower.DisplayNameShort))
                                {
                                    _objCharacter.Powers.Remove(objPower);
                                }
                            }
                        }
                    }
                }
            }

            // Check for Armor Encumbrance Penalty.
            if (bonusNode.LocalName == ("armorencumbrancepenalty"))
            {
                Log.Info("armorencumbrancepenalty");
                Log.Info("armorencumbrancepenalty = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ArmorEncumbrancePenalty, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Initiation.
            if (bonusNode.LocalName == ("initiation"))
            {
                Log.Info("initiation");
                Log.Info("initiation = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiation, "",
                    ValueToInt(bonusNode.InnerText, intRating));
                _objCharacter.InitiateGrade += ValueToInt(bonusNode.InnerText, intRating);
            }

            // Check for Submersion.
            if (bonusNode.LocalName == ("submersion"))
            {
                Log.Info("submersion");
                Log.Info("submersion = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Submersion, "",
                    ValueToInt(bonusNode.InnerText, intRating));
                _objCharacter.SubmersionGrade += ValueToInt(bonusNode.InnerText, intRating);
            }

            // Check for Skillwires.
            if (bonusNode.LocalName == ("skillwire"))
            {
                Log.Info("skillwire");
                Log.Info("skillwire = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Skillwire, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Hardwires.
            if (bonusNode.LocalName == ("hardwires"))
            {
                Log.Info("hardwire");
                Log.Info("hardwire = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                Cyberware objCyberware = new Cyberware(_objCharacter);
                CommonFunctions _objFunctions = new CommonFunctions();
                objCyberware = _objFunctions.FindCyberware(strSourceName, _objCharacter.Cyberware);
                if (objCyberware == null)
                {
                    Log.Info("_strSelectedValue = " + _strSelectedValue);
                    Log.Info("_strForcedValue = " + _strForcedValue);

                    // Display the Select Skill window and record which Skill was selected.
                    frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                    if (strFriendlyName != "")
                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed")
                            .Replace("{0}", strFriendlyName);
                    else
                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

                    Log.Info("selectskill = " + bonusNode.OuterXml.ToString());
                    if (bonusNode.OuterXml.Contains("skillgroup"))
                        frmPickSkill.OnlySkillGroup = bonusNode.Attributes["skillgroup"].InnerText;
                    else if (bonusNode.OuterXml.Contains("skillcategory"))
                        frmPickSkill.OnlyCategory = bonusNode.Attributes["skillcategory"].InnerText;
                    else if (bonusNode.OuterXml.Contains("excludecategory"))
                        frmPickSkill.ExcludeCategory = bonusNode.Attributes["excludecategory"].InnerText;
                    else if (bonusNode.OuterXml.Contains("limittoskill"))
                        frmPickSkill.LimitToSkill = bonusNode.Attributes["limittoskill"].InnerText;
                    else if (bonusNode.OuterXml.Contains("limittoattribute"))
                        frmPickSkill.LinkedAttribute = bonusNode.Attributes["limittoattribute"].InnerText;

                    if (_strForcedValue != "")
                    {
                        frmPickSkill.OnlySkill = _strForcedValue;
                        frmPickSkill.Opacity = 0;
                    }
                    frmPickSkill.ShowDialog();

                    // Make sure the dialogue window was not canceled.
                    if (frmPickSkill.DialogResult == DialogResult.Cancel)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }

                    _strSelectedValue = frmPickSkill.SelectedSkill;
                }
                else
                {
                    _strSelectedValue = objCyberware.Location;
                }
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);
                CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.Hardwire, _strSelectedValue,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Damage Resistance.
            if (bonusNode.LocalName == ("damageresistance"))
            {
                Log.Info("damageresistance");
                Log.Info("damageresistance = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DamageResistance,"",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Restricted Item Count.
            if (bonusNode.LocalName == ("restricteditemcount"))
            {
                Log.Info("restricteditemcount");
                Log.Info("restricteditemcount = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.RestrictedItemCount, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Judge Intentions.
            if (bonusNode.LocalName == ("judgeintentions"))
            {
                Log.Info("judgeintentions");
                Log.Info("judgeintentions = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.JudgeIntentions, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Composure.
            if (bonusNode.LocalName == ("composure"))
            {
                Log.Info("composure");
                Log.Info("composure = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Composure, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Lift and Carry.
            if (bonusNode.LocalName == ("liftandcarry"))
            {
                Log.Info("liftandcarry");
                Log.Info("liftandcarry = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LiftAndCarry, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Memory.
            if (bonusNode.LocalName == ("memory"))
            {
                Log.Info("memory");
                Log.Info("memory = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Memory, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Concealability.
            if (bonusNode.LocalName == ("concealability"))
            {
                Log.Info("concealability");
                Log.Info("concealability = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Concealability, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Drain Resistance.
            if (bonusNode.LocalName == ("drainresist"))
            {
                Log.Info("drainresist");
                Log.Info("drainresist = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DrainResistance, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Fading Resistance.
            if (bonusNode.LocalName == ("fadingresist"))
            {
                Log.Info("fadingresist");
                Log.Info("fadingresist = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FadingResistance, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Notoriety.
            if (bonusNode.LocalName == ("notoriety"))
            {
                Log.Info("notoriety");
                Log.Info("notoriety = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Notoriety, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Complex Form Limit.
            if (bonusNode.LocalName == ("complexformlimit"))
            {
                Log.Info("complexformlimit");
                Log.Info("complexformlimit = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ComplexFormLimit, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Spell Limit.
            if (bonusNode.LocalName == ("spelllimit"))
            {
                Log.Info("spelllimit");
                Log.Info("spelllimit = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SpellLimit, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Spell Category bonuses.
            if (bonusNode.LocalName == ("spellcategory"))
            {
                Log.Info("spellcategory");
                Log.Info("spellcategory = " + bonusNode.OuterXml.ToString());

                string strUseUnique = strUnique;
                if (bonusNode["name"].Attributes["precedence"] != null)
                    strUseUnique = "precedence" + bonusNode["name"].Attributes["precedence"].InnerText;

                Log.Info("Calling CreateImprovement");
                CreateImprovement(bonusNode["name"].InnerText, objImprovementSource, strSourceName,
                    Improvement.ImprovementType.SpellCategory, strUseUnique, ValueToInt(bonusNode["val"].InnerText, intRating));
            }

            // Check for Throwing Range bonuses.
            if (bonusNode.LocalName == ("throwrange"))
            {
                Log.Info("throwrange");
                Log.Info("throwrange = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowRange, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Throwing STR bonuses.
            if (bonusNode.LocalName == ("throwstr"))
            {
                Log.Info("throwstr");
                Log.Info("throwstr = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowSTR, strUnique,
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Skillsoft access.
            if (bonusNode.LocalName == ("skillsoftaccess"))
            {
                Log.Info("skillsoftaccess");
                Log.Info("skillsoftaccess = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SkillsoftAccess, "");
                _objCharacter.SkillsSection.KnowledgeSkills.AddRange(_objCharacter.SkillsSection.KnowsoftSkills);
            }

            // Check for Quickening Metamagic.
            if (bonusNode.LocalName == ("quickeningmetamagic"))
            {
                Log.Info("quickeningmetamagic");
                Log.Info("quickeningmetamagic = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.QuickeningMetamagic, "");
            }

            // Check for ignore Stun CM Penalty.
            if (bonusNode.LocalName == ("ignorecmpenaltystun"))
            {
                Log.Info("ignorecmpenaltystun");
                Log.Info("ignorecmpenaltystun = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyStun, "");
            }

            // Check for ignore Physical CM Penalty.
            if (bonusNode.LocalName == ("ignorecmpenaltyphysical"))
            {
                Log.Info("ignorecmpenaltyphysical");
                Log.Info("ignorecmpenaltyphysical = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyPhysical, "");
            }

            // Check for a Cyborg Essence which will permanently set the character's ESS to 0.1.
            if (bonusNode.LocalName == ("cyborgessence"))
            {
                Log.Info("cyborgessence");
                Log.Info("cyborgessence = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CyborgEssence, "");
            }

            // Check for Maximum Essence which will permanently modify the character's Maximum Essence value.
            if (bonusNode.LocalName == ("essencemax"))
            {
                Log.Info("essencemax");
                Log.Info("essencemax = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EssenceMax, "",
                    ValueToInt(bonusNode.InnerText, intRating));
            }

            // Check for Select Sprite.
            if (bonusNode.LocalName == ("selectsprite"))
            {
                Log.Info("selectsprite");
                Log.Info("selectsprite = " + bonusNode.OuterXml.ToString());
                XmlDocument objXmlDocument = XmlManager.Instance.Load("critters.xml");
                XmlNodeList objXmlNodeList =
                    objXmlDocument.SelectNodes("/chummer/metatypes/metatype[contains(category, \"Sprites\")]");
                List<ListItem> lstCritters = new List<ListItem>();
                foreach (XmlNode objXmlNode in objXmlNodeList)
                {
                    ListItem objItem = new ListItem();
                    if (objXmlNode["translate"] != null)
                        objItem.Name = objXmlNode["translate"].InnerText;
                    else
                        objItem.Name = objXmlNode["name"].InnerText;
                    objItem.Value = objItem.Name;
                    lstCritters.Add(objItem);
                }

                frmSelectItem frmPickItem = new frmSelectItem();
                frmPickItem.GeneralItems = lstCritters;
                frmPickItem.ShowDialog();

                if (frmPickItem.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickItem.SelectedItem;

                Log.Info("Calling CreateImprovement");
                CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName,
                    Improvement.ImprovementType.AddSprite,
                    "");
            }

            // Check for Black Market Discount.
            if (bonusNode.LocalName == ("blackmarketdiscount"))
            {
                Log.Info("blackmarketdiscount");
                Log.Info("blackmarketdiscount = " + bonusNode.OuterXml.ToString());
                Log.Info("Calling CreateImprovement");
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BlackMarketDiscount,
                    strUnique);
                _objCharacter.BlackMarketDiscount = true;
            }
            // Select Armor (Mostly used for Custom Fit (Stack)).
            if (bonusNode.LocalName == ("selectarmor"))
            {
                Log.Info("selectarmor");
                Log.Info("selectarmor = " + bonusNode.OuterXml.ToString());
                string strSelectedValue = "";
                if (_strForcedValue != "")
                    _strLimitSelection = _strForcedValue;

                // Display the Select Item window and record the value that was entered.

                List<ListItem> lstArmors = new List<ListItem>();
                foreach (Armor objArmor in _objCharacter.Armor)
                {
                    foreach (ArmorMod objMod in objArmor.ArmorMods)
                    {
                        if (objMod.Name.StartsWith("Custom Fit"))
                        {
                            ListItem objItem = new ListItem();
                            objItem.Value = objArmor.Name;
                            objItem.Name = objArmor.DisplayName;
                            lstArmors.Add(objItem);
                        }
                    }
                }

                if (lstArmors.Count > 0)
                {

                    frmSelectItem frmPickItem = new frmSelectItem();
                    frmPickItem.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);
                    frmPickItem.GeneralItems = lstArmors;

                    Log.Info( "_strLimitSelection = " + _strLimitSelection);
                    Log.Info( "_strForcedValue = " + _strForcedValue);

                    if (_strLimitSelection != "")
                    {
                        frmPickItem.ForceItem = _strLimitSelection;
                        frmPickItem.Opacity = 0;
                    }

                    frmPickItem.ShowDialog();

                    // Make sure the dialogue window was not canceled.
                    if (frmPickItem.DialogResult == DialogResult.Cancel)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }

                    _strSelectedValue = frmPickItem.SelectedItem;
                    if (blnConcatSelectedValue)
                        strSourceName += " (" + _strSelectedValue + ")";

                    strSelectedValue = frmPickItem.SelectedItem;
                    Log.Info( "_strSelectedValue = " + _strSelectedValue);
                    Log.Info( "strSelectedValue = " + strSelectedValue);
                }

            }

            // Select Weapon (custom entry for things like Spare Clip).
            if (bonusNode.LocalName == ("selectweapon"))
            {
                Log.Info("selectweapon");
                Log.Info("selectweapon = " + bonusNode.OuterXml.ToString());
                string strSelectedValue = "";
                if (_strForcedValue != "")
                    _strLimitSelection = _strForcedValue;

                if (_objCharacter == null)
                {
                    // If the character is null (this is a Vehicle), the user must enter their own string.
                    // Display the Select Item window and record the value that was entered.
                    frmSelectText frmPickText = new frmSelectText();
                    frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText")
                        .Replace("{0}", strFriendlyName);

                    Log.Info("_strLimitSelection = " + _strLimitSelection);
                    Log.Info("_strForcedValue = " + _strForcedValue);

                    if (_strLimitSelection != "")
                    {
                        frmPickText.SelectedValue = _strLimitSelection;
                        frmPickText.Opacity = 0;
                    }

                    frmPickText.ShowDialog();

                    // Make sure the dialogue window was not canceled.
                    if (frmPickText.DialogResult == DialogResult.Cancel)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }

                    _strSelectedValue = frmPickText.SelectedValue;
                    if (blnConcatSelectedValue)
                        strSourceName += " (" + _strSelectedValue + ")";

                    strSelectedValue = frmPickText.SelectedValue;
                    Log.Info("_strSelectedValue = " + _strSelectedValue);
                    Log.Info("strSelectedValue = " + strSelectedValue);
                }
                else
                {
                    List<ListItem> lstWeapons = new List<ListItem>();
                    foreach (Weapon objWeapon in _objCharacter.Weapons)
                    {
                        ListItem objItem = new ListItem();
                        objItem.Value = objWeapon.Name;
                        objItem.Name = objWeapon.DisplayName;
                        lstWeapons.Add(objItem);
                    }

                    frmSelectItem frmPickItem = new frmSelectItem();
                    frmPickItem.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText")
                        .Replace("{0}", strFriendlyName);
                    frmPickItem.GeneralItems = lstWeapons;

                    Log.Info("_strLimitSelection = " + _strLimitSelection);
                    Log.Info("_strForcedValue = " + _strForcedValue);

                    if (_strLimitSelection != "")
                    {
                        frmPickItem.ForceItem = _strLimitSelection;
                        frmPickItem.Opacity = 0;
                    }

                    frmPickItem.ShowDialog();

                    // Make sure the dialogue window was not canceled.
                    if (frmPickItem.DialogResult == DialogResult.Cancel)
                    {
                        Rollback();
                        _strForcedValue = "";
                        _strLimitSelection = "";
                        return false;
                    }

                    _strSelectedValue = frmPickItem.SelectedItem;
                    if (blnConcatSelectedValue)
                        strSourceName += " (" + _strSelectedValue + ")";

                    strSelectedValue = frmPickItem.SelectedItem;
                    Log.Info("_strSelectedValue = " + _strSelectedValue);
                    Log.Info("strSelectedValue = " + strSelectedValue);
                }

                // Create the Improvement.
                Log.Info("Calling CreateImprovement");
                CreateImprovement(strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique);
            }

            // Select an Optional Power.
            if (bonusNode.LocalName == ("optionalpowers"))
            {
                XmlNodeList objXmlPowerList = bonusNode.SelectNodes("optionalpower");
                //Log.Info("selectoptionalpower");
                // Display the Select Attribute window and record which Skill was selected.
                frmSelectOptionalPower frmPickPower = new frmSelectOptionalPower();
                frmPickPower.Description = LanguageManager.Instance.GetString("String_Improvement_SelectOptionalPower");
                string strForcedValue = "";

                List<KeyValuePair<string, string>> lstValue = new List<KeyValuePair<string,string>>();
                foreach (XmlNode objXmlOptionalPower in objXmlPowerList)
                {
                    string strQuality = objXmlOptionalPower.InnerText;
                    if (objXmlOptionalPower.Attributes["select"] != null)
                    {
                        strForcedValue = objXmlOptionalPower.Attributes["select"].InnerText;
                    }
                    lstValue.Add(new KeyValuePair<string, string>(strQuality,strForcedValue));
                }
                frmPickPower.LimitToList(lstValue);

                // Check to see if there is only one possible selection because of _strLimitSelection.
                if (_strForcedValue != "")
                    _strLimitSelection = _strForcedValue;

                Log.Info( "_strForcedValue = " + _strForcedValue);
                Log.Info( "_strLimitSelection = " + _strLimitSelection);

                if (_strLimitSelection != "")
                {
                    frmPickPower.SinglePower(_strLimitSelection);
                    frmPickPower.Opacity = 0;
                }

                frmPickPower.ShowDialog();

                // Make sure the dialogue window was not canceled.
                if (frmPickPower.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickPower.SelectedPower;
                // Record the improvement.
                XmlDocument objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
                XmlNode objXmlPowerNode = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + _strSelectedValue + "\"]");
                TreeNode objPowerNode = new TreeNode();
                CritterPower objPower = new CritterPower(_objCharacter);

                objPower.Create(objXmlPowerNode, _objCharacter, objPowerNode, 0, strForcedValue);
                _objCharacter.CritterPowers.Add(objPower);
            }

            if (bonusNode.LocalName == "publicawareness")
            {
                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PublicAwareness, strUnique, ValueToInt(bonusNode.InnerText,1));
            }

            if (bonusNode.LocalName == "dealerconnection")
            {
                Log.Info("dealerconnection");
                frmSelectItem frmPickItem = new frmSelectItem();
                List<ListItem> lstItems = new List<ListItem>();
                XmlNodeList objXmlList = bonusNode.SelectNodes("category");
                foreach (XmlNode objNode in objXmlList)
                {
                    ListItem objItem = new ListItem();
                    objItem.Value = objNode.InnerText;
                    objItem.Name = objNode.InnerText;
                    lstItems.Add(objItem);
                }
                frmPickItem.GeneralItems = lstItems;
                frmPickItem.AllowAutoSelect = false;
                frmPickItem.ShowDialog();
                // Make sure the dialogue window was not canceled.
                if (frmPickItem.DialogResult == DialogResult.Cancel)
                {
                    Rollback();
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    return false;
                }

                _strSelectedValue = frmPickItem.SelectedItem;
                if (blnConcatSelectedValue)
                    strSourceName += " (" + _strSelectedValue + ")";

                Log.Info("_strSelectedValue = " + _strSelectedValue);
                Log.Info("strSourceName = " + strSourceName);

                // Create the Improvement.
                Log.Info("Calling CreateImprovement");
                CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName,
                    Improvement.ImprovementType.DealerConnection, strUnique);
            }

            if (bonusNode.LocalName == "unlockskills")
            {
                List<string> options = bonusNode.InnerText.Split(',').Select(x => x.Trim()).ToList();
                string final;
                if (options.Count == 0)
                {
                    Utils.BreakIfDebug();
                    return false;
                }
                else if (options.Count == 1)
                {
                    final = options[0];
                }
                else
                {
                    frmSelectItem frmSelect = new frmSelectItem
                    {
                        AllowAutoSelect = true,
                        GeneralItems = options.Select(x => new ListItem(x, x)).ToList()
                    };

                    if (_objCharacter.Pushtext.Count > 0)
                    {
                        frmSelect.ForceItem = _objCharacter.Pushtext.Pop();
                    }

                    if (frmSelect.ShowDialog() == DialogResult.Cancel)
                    {
                        return false;
                    }

                    final = frmSelect.SelectedItem;
                }

                SkillsSection.FilterOptions skills;
                if (Enum.TryParse(final, out skills))
                {
                    _objCharacter.SkillsSection.AddSkills(skills);
                    CreateImprovement(skills.ToString(), Improvement.ImprovementSource.Quality, strSourceName,
                        Improvement.ImprovementType.SpecialSkills, strUnique);
                }
                else
                {
                    Utils.BreakIfDebug();
                    Log.Info(new[] {"Failed to parse", "specialskills", bonusNode.OuterXml});
                }
            }

            //nothing went wrong, so return true
            return true;
        }
Example #17
0
        /// <summary>
        /// Load the Character from an XML file.
        /// </summary>
        public bool Load()
        {
            XmlDocument objXmlDocument = new XmlDocument();
            objXmlDocument.Load(_strFileName);

            XmlNode objXmlCharacter = objXmlDocument.SelectSingleNode("/character");
            XmlNodeList objXmlNodeList;

            try
            {
                _blnIgnoreRules = Convert.ToBoolean(objXmlCharacter["ignorerules"].InnerText);
            }
            catch
            {
                _blnIgnoreRules = false;
            }
            try
            {
                _blnCreated = Convert.ToBoolean(objXmlCharacter["created"].InnerText);
            }
            catch
            {
            }

            ResetCharacter();

            // Get the game edition of the file if possible and make sure it's intended to be used with this version of the application.
            try
            {
                if (objXmlCharacter["gameedition"].InnerText != string.Empty && objXmlCharacter["gameedition"].InnerText != "SR5")
                {
                    MessageBox.Show(LanguageManager.Instance.GetString("Message_IncorrectGameVersion_SR4"), LanguageManager.Instance.GetString("MessageTitle_IncorrectGameVersion"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
            }
            catch
            {
            }

            // Get the name of the settings file in use if possible.
            try
            {
                _strSettingsFileName = objXmlCharacter["settings"].InnerText;
            }
            catch
            {
            }

            // Load the character's settings file.
            if (!_objOptions.Load(_strSettingsFileName))
                return false;

            try
            {
                _decEssenceAtSpecialStart = Convert.ToDecimal(objXmlCharacter["essenceatspecialstart"].InnerText, GlobalOptions.Instance.CultureInfo);
                // fix to work around a mistake made when saving decimal values in previous versions.
                if (_decEssenceAtSpecialStart > EssenceMaximum)
                    _decEssenceAtSpecialStart /= 10;
            }
            catch
            {
            }

            try
            {
                _strVersionCreated = objXmlCharacter["createdversion"].InnerText;
            }
            catch
            {
            }

            // Metatype information.
            _strMetatype = objXmlCharacter["metatype"].InnerText;
            try
            {
                _strWalk = objXmlCharacter["walk"].InnerText;
                _strRun = objXmlCharacter["run"].InnerText;
                _strSprint = objXmlCharacter["sprint"].InnerText;
            }
            catch
            {
            }
            _intMetatypeBP = Convert.ToInt32(objXmlCharacter["metatypebp"].InnerText);
            _strMetavariant = objXmlCharacter["metavariant"].InnerText;
            try
            {
                _strMetatypeCategory = objXmlCharacter["metatypecategory"].InnerText;
            }
            catch
            {
            }
            try
            {
                _intMutantCritterBaseSkills = Convert.ToInt32(objXmlCharacter["mutantcritterbaseskills"].InnerText);
            }
            catch
            {
            }

            // General character information.
            _strName = objXmlCharacter["name"].InnerText;
            try
            {
                _strMugshot = objXmlCharacter["mugshot"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strSex = objXmlCharacter["sex"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strAge = objXmlCharacter["age"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strEyes = objXmlCharacter["eyes"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strHeight = objXmlCharacter["height"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strWeight = objXmlCharacter["weight"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strSkin = objXmlCharacter["skin"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strHair = objXmlCharacter["hair"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strDescription = objXmlCharacter["description"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strBackground = objXmlCharacter["background"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strConcept = objXmlCharacter["concept"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strNotes = objXmlCharacter["notes"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strAlias = objXmlCharacter["alias"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strPlayerName = objXmlCharacter["playername"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strGameNotes = objXmlCharacter["gamenotes"].InnerText;
            }
            catch
            {
            }

            try
            {
                _strGameplayOption = objXmlCharacter["gameplayoption"].InnerText;
            }
            catch
            {
            }
            try
            {
                _intMaxNuyen = Convert.ToInt32(objXmlCharacter["maxnuyen"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intContactMultiplier = Convert.ToInt32(objXmlCharacter["contactmultiplier"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intMaxKarma = Convert.ToInt32(objXmlCharacter["maxkarma"].InnerText);
            }
            catch
            {
            }
            try
            {
                _strPriorityMetatype = objXmlCharacter["prioritymetatype"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strPriorityAttributes = objXmlCharacter["priorityattributes"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strPrioritySpecial = objXmlCharacter["priorityspecial"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strPrioritySkills = objXmlCharacter["priorityskills"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strPriorityResources = objXmlCharacter["priorityresources"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strSkill1 = objXmlCharacter["priorityskill1"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strSkill2 = objXmlCharacter["priorityskill2"].InnerText;
            }
            catch
            {
            }
            try
            {
                _strSkillGroup = objXmlCharacter["priorityskillgroup"].InnerText;
            }
            catch
            {
            }

            try
            {
                _blnIsCritter = Convert.ToBoolean(objXmlCharacter["iscritter"].InnerText);
            }
            catch
            {
            }

            try
            {
                _blnPossessed = Convert.ToBoolean(objXmlCharacter["possessed"].InnerText);
            }
            catch
            {
            }

            try
            {
                _blnOverrideSpecialAttributeESSLoss = Convert.ToBoolean(objXmlCharacter["overridespecialattributeessloss"].InnerText);
            }
            catch
            {
            }

            try
            {
                _intContactPoints = Convert.ToInt32(objXmlCharacter["contactpoints"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intContactPointsUsed = Convert.ToInt32(objXmlCharacter["contactpointsused"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intCFPLimit = Convert.ToInt32(objXmlCharacter["cfplimit"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intSpellLimit = Convert.ToInt32(objXmlCharacter["spelllimit"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intKarma = Convert.ToInt32(objXmlCharacter["karma"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intTotalKarma = Convert.ToInt32(objXmlCharacter["totalkarma"].InnerText);
            }
            catch
            {
            }

            try
            {
                _intSpecial = Convert.ToInt32(objXmlCharacter["special"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intTotalSpecial = Convert.ToInt32(objXmlCharacter["totalspecial"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intAttributes = Convert.ToInt32(objXmlCharacter["attributes"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intTotalAttributes = Convert.ToInt32(objXmlCharacter["totalattributes"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intContactPoints = Convert.ToInt32(objXmlCharacter["contactpoints"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intContactPointsUsed = Convert.ToInt32(objXmlCharacter["contactpointsused"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intStreetCred = Convert.ToInt32(objXmlCharacter["streetcred"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intNotoriety = Convert.ToInt32(objXmlCharacter["notoriety"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intPublicAwareness = Convert.ToInt32(objXmlCharacter["publicawareness"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intBurntStreetCred = Convert.ToInt32(objXmlCharacter["burntstreetcred"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intMaxAvail = Convert.ToInt32(objXmlCharacter["maxavail"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intNuyen = Convert.ToInt32(objXmlCharacter["nuyen"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intStartingNuyen = Convert.ToInt32(objXmlCharacter["startingnuyen"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intAdeptWayDiscount = Convert.ToInt32(objXmlCharacter["adeptwaydiscount"].InnerText);
            }
            catch
            {
            }

            // Sum to X point value.
            try
            {
                _intSumtoTen = Convert.ToInt32(objXmlCharacter["sumtoten"].InnerText);
            }
            catch
            {
            }
            // Build Points/Karma.
            _intBuildPoints = Convert.ToInt32(objXmlCharacter["bp"].InnerText);
            try
            {
                _intBuildKarma = Convert.ToInt32(objXmlCharacter["buildkarma"].InnerText);
                if (_intMaxKarma == 0)
                    _intMaxKarma = _intBuildKarma;
                if (_intBuildKarma == 35 && _strGameplayOption == "")
                {
                    _strGameplayOption = "Prime Runner";
                }
                if (_intBuildKarma == 35 && _intMaxNuyen == 0)
                {
                    _intMaxNuyen = 25;
                }
            }
            catch
            {
            }
            //Maximum number of Karma that can be spent/gained on Qualities.
            try
            {
                _intGameplayOptionQualityLimit = Convert.ToInt32(objXmlCharacter["gameplayoptionqualitylimit"].InnerText);
            }
            catch
            {
            }
            try
            {
                _objBuildMethod = ConvertToCharacterBuildMethod(objXmlCharacter["buildmethod"].InnerText);
            }
            catch
            {
            }
            try
            {
                _intKnowledgeSkills = Convert.ToInt32(objXmlCharacter["knowskillpts"].InnerText);

            }
            catch { }
            _intKnowledgeSkillPoints = Convert.ToInt32(objXmlCharacter["knowpts"].InnerText);
            _intSkillPoints = Convert.ToInt32(objXmlCharacter["skillpts"].InnerText);
            _intSkillPointsMaximum = Convert.ToInt32(objXmlCharacter["skillptsmax"].InnerText);
            _intSkillGroups = Convert.ToInt32(objXmlCharacter["skillgrps"].InnerText);
            _intSkillGroupsMaximum = Convert.ToInt32(objXmlCharacter["skillgrpsmax"].InnerText);
            _decNuyenBP = Convert.ToDecimal(objXmlCharacter["nuyenbp"].InnerText, GlobalOptions.Instance.CultureInfo);
            _decNuyenMaximumBP = Convert.ToDecimal(objXmlCharacter["nuyenmaxbp"].InnerText, GlobalOptions.Instance.CultureInfo);
            _blnAdeptEnabled = Convert.ToBoolean(objXmlCharacter["adept"].InnerText);
            _blnMagicianEnabled = Convert.ToBoolean(objXmlCharacter["magician"].InnerText);
            _blnTechnomancerEnabled = Convert.ToBoolean(objXmlCharacter["technomancer"].InnerText);
            try
            {
                _blnInitiationEnabled = Convert.ToBoolean(objXmlCharacter["initiationoverride"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnCritterEnabled = Convert.ToBoolean(objXmlCharacter["critter"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnUneducated = Convert.ToBoolean(objXmlCharacter["uneducated"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnUncouth = Convert.ToBoolean(objXmlCharacter["uncouth"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnSchoolOfHardKnocks = Convert.ToBoolean(objXmlCharacter["schoolofhardknocks"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnFriendsInHighPlaces = Convert.ToBoolean(objXmlCharacter["friendsinhighplaces"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnCollegeEducation = Convert.ToBoolean(objXmlCharacter["collegeeducation"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnJackOfAllTrades = Convert.ToBoolean(objXmlCharacter["jackofalltrades"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnInfirm = Convert.ToBoolean(objXmlCharacter["infirm"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnBlackMarket = Convert.ToBoolean(objXmlCharacter["blackmarket"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnExCon = Convert.ToBoolean(objXmlCharacter["excon"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnTrustFund = Convert.ToBoolean(objXmlCharacter["trustfund"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnTechSchool = Convert.ToBoolean(objXmlCharacter["techschool"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnRestrictedGear = Convert.ToBoolean(objXmlCharacter["restrictedgear"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnOverclocker = Convert.ToBoolean(objXmlCharacter["overclocker"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnMadeMan = Convert.ToBoolean(objXmlCharacter["mademan"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnLinguist = Convert.ToBoolean(objXmlCharacter["linguist"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnLightningReflexes = Convert.ToBoolean(objXmlCharacter["lightningreflexes"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnFame = Convert.ToBoolean(objXmlCharacter["fame"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnBornRich = Convert.ToBoolean(objXmlCharacter["bornrich"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnErased = Convert.ToBoolean(objXmlCharacter["erased"].InnerText);
            }
            catch
            {
            }
            _blnMAGEnabled = Convert.ToBoolean(objXmlCharacter["magenabled"].InnerText);
            try
            {
                _intInitiateGrade = Convert.ToInt32(objXmlCharacter["initiategrade"].InnerText);
            }
            catch
            {
            }
            _blnRESEnabled = Convert.ToBoolean(objXmlCharacter["resenabled"].InnerText);
            try
            {
                _intSubmersionGrade = Convert.ToInt32(objXmlCharacter["submersiongrade"].InnerText);
            }
            catch
            {
            }
            try
            {
                _blnGroupMember = Convert.ToBoolean(objXmlCharacter["groupmember"].InnerText);
            }
            catch
            {
            }
            try
            {
                _strGroupName = objXmlCharacter["groupname"].InnerText;
                _strGroupNotes = objXmlCharacter["groupnotes"].InnerText;
            }
            catch
            {
            }

            // Improvements.
            XmlNodeList objXmlImprovementList = objXmlDocument.SelectNodes("/character/improvements/improvement");
            foreach (XmlNode objXmlImprovement in objXmlImprovementList)
            {
                Improvement objImprovement = new Improvement();
                objImprovement.Load(objXmlImprovement);
                _lstImprovements.Add(objImprovement);
            }

            // Qualities
            objXmlNodeList = objXmlDocument.SelectNodes("/character/qualities/quality");
            bool blnHasOldQualities = false;
            foreach (XmlNode objXmlQuality in objXmlNodeList)
            {
                if (objXmlQuality["name"] != null)
                {
                    Quality objQuality = new Quality(this);
                    objQuality.Load(objXmlQuality);
                    _lstQualities.Add(objQuality);
                }
                else
                {
                    // If the Quality does not have a name tag, it is in the old format. Set the flag to show that old Qualities are in use.
                    blnHasOldQualities = true;
                }
            }
            // If old Qualities are in use, they need to be converted before we can continue.
            if (blnHasOldQualities)
                ConvertOldQualities(objXmlNodeList);

            // Attributes.
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"BOD\"]");
            _attBOD.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"AGI\"]");
            _attAGI.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"REA\"]");
            _attREA.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"STR\"]");
            _attSTR.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"CHA\"]");
            _attCHA.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"INT\"]");
            _attINT.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"LOG\"]");
            _attLOG.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"WIL\"]");
            _attWIL.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"INI\"]");
            _attINI.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"EDG\"]");
            _attEDG.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"MAG\"]");
            _attMAG.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"RES\"]");
            _attRES.Load(objXmlCharacter);
            objXmlCharacter = objXmlDocument.SelectSingleNode("/character/attributes/attribute[name = \"ESS\"]");
            _attESS.Load(objXmlCharacter);

            // A.I. Attributes.
            try
            {
                _intSignal = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/attributes/signal").InnerText);
                _intResponse = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/attributes/response").InnerText);
            }
            catch
            {
            }

            // Force.
            try
            {
                _intMaxSkillRating = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/attributes/maxskillrating").InnerText);
            }
            catch
            {
            }

            // Attempt to load the split MAG Attribute information for Mystic Adepts.
            if (_blnAdeptEnabled && _blnMagicianEnabled)
            {
                try
                {
                    _intMAGAdept = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/magsplitadept").InnerText);
                    _intMAGMagician = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/magsplitmagician").InnerText);
                }
                catch
                {
                }
            }

            // Attempt to load the Magic Tradition.
            try
            {
                _strMagicTradition = objXmlDocument.SelectSingleNode("/character/tradition").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Magic Tradition Drain Attributes.
            try
            {
                _strTraditionDrain = objXmlDocument.SelectSingleNode("/character/traditiondrain").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Magic Tradition Name.
            try
            {
                _strTraditionName = objXmlDocument.SelectSingleNode("/character/traditionname").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Spirit Combat Name.
            try
            {
                _strSpiritCombat = objXmlDocument.SelectSingleNode("/character/spiritcombat").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Spirit Detection Name.
            try
            {
                _strSpiritDetection = objXmlDocument.SelectSingleNode("/character/spiritdetection").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Spirit Health Name.
            try
            {
                _strSpiritHealth = objXmlDocument.SelectSingleNode("/character/spirithealth").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Spirit Illusion Name.
            try
            {
                _strSpiritIllusion = objXmlDocument.SelectSingleNode("/character/spiritillusion").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Spirit Manipulation Name.
            try
            {
                _strSpiritManipulation = objXmlDocument.SelectSingleNode("/character/spiritmanipulation").InnerText;
            }
            catch
            {
            }
            // Attempt to load the Technomancer Stream.
            try
            {
                _strTechnomancerStream = objXmlDocument.SelectSingleNode("/character/stream").InnerText;
            }
            catch
            {
            }

            // Attempt to load Condition Monitor Progress.
            try
            {
                _intPhysicalCMFilled = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/physicalcmfilled").InnerText);
                _intStunCMFilled = Convert.ToInt32(objXmlDocument.SelectSingleNode("/character/stuncmfilled").InnerText);
            }
            catch
            {
            }

            // Skills.
            foreach (Skill objSkill in _lstSkills)
            {
                XmlNode objXmlSkill = objXmlDocument.SelectSingleNode("/character/skills/skill[name = \"" + objSkill.Name + "\"]");
                if (objXmlSkill != null)
                {
                    objSkill.Load(objXmlSkill);
                }
            }

            // Exotic Skills.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/skills/skill[exotic = \"True\"]");
            foreach (XmlNode objXmlSkill in objXmlNodeList)
            {
                Skill objSkill = new Skill(this);
                objSkill.Load(objXmlSkill);
                _lstSkills.Add(objSkill);
            }

            // SkillGroups.
            foreach (SkillGroup objGroup in _lstSkillGroups)
            {
                XmlNode objXmlSkill = objXmlDocument.SelectSingleNode("/character/skillgroups/skillgroup[name = \"" + objGroup.Name + "\"]");
                if (objXmlSkill != null)
                {
                    objGroup.Load(objXmlSkill);
                    // If the character is set to ignore rules or is in Career Mode, Skill Groups should have a maximum Rating of 6 unless they have been given a higher maximum Rating already.
                    if ((_blnIgnoreRules || _blnCreated) && objGroup.RatingMaximum < 12)
                        objGroup.RatingMaximum = 12;
                }
            }

            // Apply the broken skill group fix
            foreach (Skill objSkill in _lstSkills)
            {
                foreach (SkillGroup objGroup in _lstSkillGroups)
                {
                    if (objGroup.Broken && objGroup.Name == objSkill.SkillGroup)
                    {
                        objSkill.FreeLevels = objGroup.Rating;
                        objSkill.Base = objGroup.Rating;
                        objSkill.Karma = objSkill.Rating - objSkill.Base;
                    }
                }
            }

            foreach (SkillGroup objGroup in _lstSkillGroups)
            {
                if (objGroup.Base == 0 && objGroup.Karma == 0 && objGroup.Rating > 0)
                    objGroup.Base = objGroup.Rating;
            }

            // Knowledge Skills.
            List<ListItem> lstKnowledgeSkillOrder = new List<ListItem>();
            objXmlNodeList = objXmlDocument.SelectNodes("/character/skills/skill[knowledge = \"True\"]");
            // Sort the Knowledge Skills in alphabetical order.
            foreach (XmlNode objXmlSkill in objXmlNodeList)
            {
                ListItem objGroup = new ListItem();
                objGroup.Value = objXmlSkill["name"].InnerText;
                objGroup.Name = objXmlSkill["name"].InnerText;
                lstKnowledgeSkillOrder.Add(objGroup);
            }
            SortListItem objSort = new SortListItem();
            lstKnowledgeSkillOrder.Sort(objSort.Compare);

            foreach (ListItem objItem in lstKnowledgeSkillOrder)
            {
                Skill objSkill = new Skill(this);
                XmlNode objNode = objXmlDocument.SelectSingleNode("/character/skills/skill[knowledge = \"True\" and name = " + CleanXPath(objItem.Value) + "]");
                objSkill.Load(objNode);
                _lstSkills.Add(objSkill);
            }

            // Contacts.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/contacts/contact");
            foreach (XmlNode objXmlContact in objXmlNodeList)
            {
                Contact objContact = new Contact(this);
                objContact.Load(objXmlContact);
                _lstContacts.Add(objContact);
            }

            // Armor.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/armors/armor");
            foreach (XmlNode objXmlArmor in objXmlNodeList)
            {
                Armor objArmor = new Armor(this);
                objArmor.Load(objXmlArmor);
                _lstArmor.Add(objArmor);
            }

            // Weapons.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/weapons/weapon");
            foreach (XmlNode objXmlWeapon in objXmlNodeList)
            {
                Weapon objWeapon = new Weapon(this);
                objWeapon.Load(objXmlWeapon);
                _lstWeapons.Add(objWeapon);
            }

            // Cyberware/Bioware.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/cyberwares/cyberware");
            foreach (XmlNode objXmlCyberware in objXmlNodeList)
            {
                Cyberware objCyberware = new Cyberware(this);
                objCyberware.Load(objXmlCyberware);
                _lstCyberware.Add(objCyberware);
            }

            // Spells.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/spells/spell");
            foreach (XmlNode objXmlSpell in objXmlNodeList)
            {
                Spell objSpell = new Spell(this);
                objSpell.Load(objXmlSpell);
                _lstSpells.Add(objSpell);
            }

            // Foci.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/foci/focus");
            foreach (XmlNode objXmlFocus in objXmlNodeList)
            {
                Focus objFocus = new Focus();
                objFocus.Load(objXmlFocus);
                _lstFoci.Add(objFocus);
            }

            // Stacked Foci.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/stackedfoci/stackedfocus");
            foreach (XmlNode objXmlStack in objXmlNodeList)
            {
                StackedFocus objStack = new StackedFocus(this);
                objStack.Load(objXmlStack);
                _lstStackedFoci.Add(objStack);
            }

            // Powers.
            List<ListItem> lstPowerOrder = new List<ListItem>();
            objXmlNodeList = objXmlDocument.SelectNodes("/character/powers/power");
            // Sort the Powers in alphabetical order.
            foreach (XmlNode objXmlPower in objXmlNodeList)
            {
                ListItem objGroup = new ListItem();
                objGroup.Value = objXmlPower["extra"].InnerText;
                objGroup.Name = objXmlPower["name"].InnerText;

                lstPowerOrder.Add(objGroup);
            }
            objSort = new SortListItem();
            lstPowerOrder.Sort(objSort.Compare);

            foreach (ListItem objItem in lstPowerOrder)
            {
                Power objPower = new Power(this);
                XmlNode objNode = objXmlDocument.SelectSingleNode("/character/powers/power[name = " + CleanXPath(objItem.Name) + " and extra = " + CleanXPath(objItem.Value) + "]");
                objPower.Load(objNode);
                _lstPowers.Add(objPower);
            }

            // Spirits/Sprites.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/spirits/spirit");
            foreach (XmlNode objXmlSpirit in objXmlNodeList)
            {
                Spirit objSpirit = new Spirit(this);
                objSpirit.Load(objXmlSpirit);
                _lstSpirits.Add(objSpirit);
            }

            // Compex Forms/Technomancer Programs.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/complexforms/complexform");
            foreach (XmlNode objXmlProgram in objXmlNodeList)
            {
                ComplexForm objProgram = new ComplexForm(this);
                objProgram.Load(objXmlProgram);
                _lstComplexForms.Add(objProgram);
            }

            // Martial Arts.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/martialarts/martialart");
            foreach (XmlNode objXmlArt in objXmlNodeList)
            {
                MartialArt objMartialArt = new MartialArt(this);
                objMartialArt.Load(objXmlArt);
                _lstMartialArts.Add(objMartialArt);
            }

            // Martial Art Maneuvers.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/martialartmaneuvers/martialartmaneuver");
            foreach (XmlNode objXmlManeuver in objXmlNodeList)
            {
                MartialArtManeuver objManeuver = new MartialArtManeuver(this);
                objManeuver.Load(objXmlManeuver);
                _lstMartialArtManeuvers.Add(objManeuver);
            }

            // Limit Modifiers.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/limitmodifiers/limitmodifier");
            foreach (XmlNode objXmlLimit in objXmlNodeList)
            {
                LimitModifier obLimitModifier = new LimitModifier(this);
                obLimitModifier.Load(objXmlLimit);
                _lstLimitModifiers.Add(obLimitModifier);
            }

            // Lifestyles.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/lifestyles/lifestyle");
            foreach (XmlNode objXmlLifestyle in objXmlNodeList)
            {
                Lifestyle objLifestyle = new Lifestyle(this);
                objLifestyle.Load(objXmlLifestyle);
                _lstLifestyles.Add(objLifestyle);
            }

            // <gears>
            objXmlNodeList = objXmlDocument.SelectNodes("/character/gears/gear");
            foreach (XmlNode objXmlGear in objXmlNodeList)
            {
                switch (objXmlGear["category"].InnerText)
                {
                    case "Commlinks":
                    case "Cyberdecks":
                    case "Rigger Command Consoles":
                        Commlink objCommlink = new Commlink(this);
                        objCommlink.Load(objXmlGear);
                        _lstGear.Add(objCommlink);
                        break;
                    default:
                        Gear objGear = new Gear(this);
                        objGear.Load(objXmlGear);
                        _lstGear.Add(objGear);
                        break;
                }
            }

            // Vehicles.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/vehicles/vehicle");
            foreach (XmlNode objXmlVehicle in objXmlNodeList)
            {
                Vehicle objVehicle = new Vehicle(this);
                objVehicle.Load(objXmlVehicle);
                _lstVehicles.Add(objVehicle);
            }

            // Metamagics/Echoes.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/metamagics/metamagic");
            foreach (XmlNode objXmlMetamagic in objXmlNodeList)
            {
                Metamagic objMetamagic = new Metamagic(this);
                objMetamagic.Load(objXmlMetamagic);
                _lstMetamagics.Add(objMetamagic);
            }

            // Arts
            objXmlNodeList = objXmlDocument.SelectNodes("/character/arts/art");
            foreach (XmlNode objXmlArt in objXmlNodeList)
            {
                Art objArt = new Art(this);
                objArt.Load(objXmlArt);
                _lstArts.Add(objArt);
            }

            // Enhancements
            objXmlNodeList = objXmlDocument.SelectNodes("/character/enhancements/enhancement");
            foreach (XmlNode objXmlEnhancement in objXmlNodeList)
            {
                Enhancement objEnhancement = new Enhancement(this);
                objEnhancement.Load(objXmlEnhancement);
                _lstEnhancements.Add(objEnhancement);
            }

            // Critter Powers.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/critterpowers/critterpower");
            foreach (XmlNode objXmlPower in objXmlNodeList)
            {
                CritterPower objPower = new CritterPower(this);
                objPower.Load(objXmlPower);
                _lstCritterPowers.Add(objPower);
            }

            // Initiation Grades.
            objXmlNodeList = objXmlDocument.SelectNodes("/character/initiationgrades/initiationgrade");
            foreach (XmlNode objXmlGrade in objXmlNodeList)
            {
                InitiationGrade objGrade = new InitiationGrade(this);
                objGrade.Load(objXmlGrade);
                _lstInitiationGrades.Add(objGrade);
            }

            // Expense Log Entries.
            XmlNodeList objXmlExpenseList = objXmlDocument.SelectNodes("/character/expenses/expense");
            foreach (XmlNode objXmlExpense in objXmlExpenseList)
            {
                ExpenseLogEntry objExpenseLogEntry = new ExpenseLogEntry();
                objExpenseLogEntry.Load(objXmlExpense);
                _lstExpenseLog.Add(objExpenseLogEntry);
            }

            // Locations.
            XmlNodeList objXmlLocationList = objXmlDocument.SelectNodes("/character/locations/location");
            foreach (XmlNode objXmlLocation in objXmlLocationList)
            {
                _lstLocations.Add(objXmlLocation.InnerText);
            }

            // Armor Bundles.
            XmlNodeList objXmlBundleList = objXmlDocument.SelectNodes("/character/armorbundles/armorbundle");
            foreach (XmlNode objXmlBundle in objXmlBundleList)
            {
                _lstArmorBundles.Add(objXmlBundle.InnerText);
            }

            // Weapon Locations.
            XmlNodeList objXmlWeaponLocationList = objXmlDocument.SelectNodes("/character/weaponlocations/weaponlocation");
            foreach (XmlNode objXmlLocation in objXmlWeaponLocationList)
            {
                _lstWeaponLocations.Add(objXmlLocation.InnerText);
            }

            // Improvement Groups.
            XmlNodeList objXmlGroupList = objXmlDocument.SelectNodes("/character/improvementgroups/improvementgroup");
            foreach (XmlNode objXmlGroup in objXmlGroupList)
            {
                _lstImprovementGroups.Add(objXmlGroup.InnerText);
            }

            // Calendar.
            XmlNodeList objXmlWeekList = objXmlDocument.SelectNodes("/character/calendar/week");
            foreach (XmlNode objXmlWeek in objXmlWeekList)
            {
                CalendarWeek objWeek = new CalendarWeek();
                objWeek.Load(objXmlWeek);
                _lstCalendar.Add(objWeek);
            }

            // Look for the unarmed attack
            bool blnFoundUnarmed = false;
            foreach (Weapon objWeapon in _lstWeapons)
            {
                if (objWeapon.Name == "Unarmed Attack")
                    blnFoundUnarmed = true;
            }

            if (!blnFoundUnarmed)
            {
                // Add the Unarmed Attack Weapon to the character.
                try
                {
                    XmlDocument objXmlWeaponDoc = XmlManager.Instance.Load("weapons.xml");
                    XmlNode objXmlWeapon = objXmlWeaponDoc.SelectSingleNode("/chummer/weapons/weapon[name = \"Unarmed Attack\"]");
                    TreeNode objGearWeaponNode = new TreeNode();
                    Weapon objWeapon = new Weapon(this);
                    objWeapon.Create(objXmlWeapon, this, objGearWeaponNode, null, null, null);
                    objGearWeaponNode.ForeColor = SystemColors.GrayText;
                    _lstWeapons.Add(objWeapon);
                }
                catch
                {
                }
            }

            // converting from old dwarven resistance to new dwarven resistance
            if (this.Metatype.ToLower().Equals("dwarf")
                && this.Qualities.Where(x => x.Name.Equals("Dwarf Resistance")).FirstOrDefault() == null
                && this.Qualities.Where(x => x.Name.Equals("Resistance to Pathogens and Toxins")).FirstOrDefault() != null)
            {
                this.Qualities.Remove(this.Qualities.Where(x => x.Name.Equals("Resistance to Pathogens and Toxins")).First());
                XmlNode objXmlDwarfQuality = XmlManager.Instance.Load("qualities.xml").SelectSingleNode("/chummer/qualities/quality[name = \"Dwarf Resistance\"]");

                TreeNode objNode = new TreeNode();
                List<Weapon> objWeapons = new List<Weapon>();
                List<TreeNode> objWeaponNodes = new List<TreeNode>();
                Quality objQuality = new Quality(this);

                objQuality.Create(objXmlDwarfQuality, this, QualitySource.Metatype, objNode, objWeapons, objWeaponNodes);
                this._lstQualities.Add(objQuality);
                blnHasOldQualities = true;
            }

            // load issue where the contact multiplier was set to 0
            if (_intContactMultiplier == 0 && _strGameplayOption != string.Empty)
            {
                XmlDocument objXmlDocumentPriority = XmlManager.Instance.Load("gameplayoptions.xml");
                XmlNode objXmlGameplayOption = objXmlDocumentPriority.SelectSingleNode("/chummer/gameplayoptions/gameplayoption[name = \"" + _strGameplayOption + "\"]");
                string strKarma = objXmlGameplayOption["karma"].InnerText;
                string strNuyen = objXmlGameplayOption["maxnuyen"].InnerText;
                string strContactMultiplier = "0";
                if (!_objOptions.FreeContactsMultiplierEnabled)
                {

                    strContactMultiplier = objXmlGameplayOption["contactmultiplier"].InnerText;
                }
                else
                {
                    strContactMultiplier = _objOptions.FreeContactsMultiplier.ToString();
                }
                _intMaxKarma = Convert.ToInt32(strKarma);
                _intMaxNuyen = Convert.ToInt32(strNuyen);
                _intContactMultiplier = Convert.ToInt32(strContactMultiplier);
                _intContactPoints = (CHA.Base + CHA.Karma) * _intContactMultiplier;
            }

            // If the character had old Qualities that were converted, immediately save the file so they are in the new format.
            if (blnHasOldQualities)
                Save();

            return true;
        }
Example #18
0
        private void treMartialArts_AfterSelect(object sender, TreeViewEventArgs e)
        {
            try
            {
                // The Rating NUD is only enabled if a Martial Art is currently selected.
                if (treMartialArts.SelectedNode.Level == 1 && treMartialArts.SelectedNode.Parent == treMartialArts.Nodes[0])
                {
                    MartialArt objMartialArt = _objFunctions.FindMartialArt(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts);

                    _blnSkipRefresh = true;
                    if (objMartialArt.Rating < 4)
                    {
                        string strTip = LanguageManager.Instance.GetString("Tip_ImproveItem").Replace("{0}", (objMartialArt.Rating + 1).ToString()).Replace("{1}", (((objMartialArt.Rating + 1) * 5 * _objOptions.KarmaQuality) - ((objMartialArt.Rating) * 5 * _objOptions.KarmaQuality)).ToString());
                        tipTooltip.SetToolTip(cmdImproveMartialArtsRating, strTip);
                        cmdImproveMartialArtsRating.Enabled = true;
                    }
                    else
                        cmdImproveMartialArtsRating.Enabled = false;
                    lblMartialArtsRating.Text = objMartialArt.Rating.ToString();
                    string strBook = _objOptions.LanguageBookShort(objMartialArt.Source);
                    string strPage = objMartialArt.Page;
                    lblMartialArtSource.Text = strBook + " " + strPage;
                    tipTooltip.SetToolTip(lblMartialArtSource, _objOptions.LanguageBookLong(objMartialArt.Source) + " " + LanguageManager.Instance.GetString("String_Page") + " " + objMartialArt.Page);
                    _blnSkipRefresh = false;
                }
                else
                    cmdImproveMartialArtsRating.Enabled = false;

                // Display the Martial Art Advantage information.
                if (treMartialArts.SelectedNode.Level == 2)
                {
                    MartialArt objMartialArt = new MartialArt(_objCharacter);
                    MartialArtAdvantage objAdvantage = _objFunctions.FindMartialArtAdvantage(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts, out objMartialArt);

                    string strBook = _objOptions.LanguageBookShort(objMartialArt.Source);
                    string strPage = objMartialArt.Page;
                    lblMartialArtSource.Text = strBook + " " + strPage;
                    tipTooltip.SetToolTip(lblMartialArtSource, _objOptions.LanguageBookLong(objMartialArt.Source) + " page " + objMartialArt.Page);
                }

                // Display the Maneuver information.
                if (treMartialArts.SelectedNode.Level == 1 && treMartialArts.SelectedNode.Parent == treMartialArts.Nodes[1])
                {
                    MartialArtManeuver objManeuver = _objFunctions.FindMartialArtManeuver(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArtManeuvers);

                    string strBook = _objOptions.LanguageBookShort(objManeuver.Source);
                    string strPage = objManeuver.Page;
                    lblMartialArtSource.Text = strBook + " " + strPage;
                    tipTooltip.SetToolTip(lblMartialArtSource, _objOptions.LanguageBookLong(objManeuver.Source) + " page " + objManeuver.Page);
                }
            }
            catch
            {
                cmdImproveMartialArtsRating.Enabled = false;
            }
        }
Example #19
0
        private void tsAddTechniqueNotes_Click(object sender, EventArgs e)
        {
            try
            {
                bool blnFound = false;
                MartialArt objMartialArt = new MartialArt(_objCharacter);
                MartialArtAdvantage objTechnique = _objFunctions.FindMartialArtAdvantage(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts, out objMartialArt);
                if (objTechnique != null)
                    blnFound = true;

                if (blnFound)
                {
                    frmNotes frmItemNotes = new frmNotes();
                    frmItemNotes.Notes = objTechnique.Notes;
                    string strOldValue = objTechnique.Notes;
                    frmItemNotes.ShowDialog(this);

                    if (frmItemNotes.DialogResult == DialogResult.OK)
                    {
                        objTechnique.Notes = frmItemNotes.Notes;
                        if (objTechnique.Notes != strOldValue)
                        {
                            _blnIsDirty = true;
                            UpdateWindowTitle();
                        }
                    }

                    if (objTechnique.Notes != string.Empty)
                        treMartialArts.SelectedNode.ForeColor = Color.SaddleBrown;
                    else
                        treMartialArts.SelectedNode.ForeColor = SystemColors.WindowText;
                    treMartialArts.SelectedNode.ToolTipText = CommonFunctions.WordWrap(objTechnique.Notes, 100);
                }
            }
            catch
            {
            }
        }
Example #20
0
        private void cmdAddMartialArt_Click(object sender, EventArgs e)
        {
            int intKarmaCost = 7 * _objOptions.KarmaQuality;
            if (intKarmaCost > _objCharacter.Karma)
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_NotEnoughKarma"), LanguageManager.Instance.GetString("MessageTitle_NotEnoughKarma"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            frmSelectMartialArt frmPickMartialArt = new frmSelectMartialArt(_objCharacter);
            frmPickMartialArt.ShowDialog(this);

            if (frmPickMartialArt.DialogResult == DialogResult.Cancel)
                return;

            // Open the Martial Arts XML file and locate the selected piece.
            XmlDocument objXmlDocument = XmlManager.Instance.Load("martialarts.xml");

            XmlNode objXmlArt = objXmlDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + frmPickMartialArt.SelectedMartialArt + "\"]");

            TreeNode objNode = new TreeNode();
            MartialArt objMartialArt = new MartialArt(_objCharacter);
            objMartialArt.Create(objXmlArt, objNode, _objCharacter);
            _objCharacter.MartialArts.Add(objMartialArt);

            objNode.ContextMenuStrip = cmsMartialArts;

            // Create the Expense Log Entry.
            ExpenseLogEntry objExpense = new ExpenseLogEntry();
            objExpense.Create(intKarmaCost * -1, LanguageManager.Instance.GetString("String_ExpenseLearnMartialArt") + " " + frmPickMartialArt.SelectedMartialArt, ExpenseType.Karma, DateTime.Now);
            _objCharacter.ExpenseEntries.Add(objExpense);
            _objCharacter.Karma -= intKarmaCost;

            ExpenseUndo objUndo = new ExpenseUndo();
            objUndo.CreateKarma(KarmaExpenseType.AddMartialArt, objMartialArt.Name);
            objExpense.Undo = objUndo;

            treMartialArts.Nodes[0].Nodes.Add(objNode);
            treMartialArts.Nodes[0].Expand();

            treMartialArts.SelectedNode = objNode;

            _objFunctions.SortTree(treMartialArts);
            UpdateCharacterInfo();

            _blnIsDirty = true;
            UpdateWindowTitle();
        }
Example #21
0
        private void cmdDeleteMartialArt_Click(object sender, EventArgs e)
        {
            try
            {
                if (treMartialArts.SelectedNode.Level == 0)
                    return;

                if (!_objFunctions.ConfirmDelete(LanguageManager.Instance.GetString("Message_DeleteMartialArt")))
                    return;

                if (treMartialArts.SelectedNode.Level == 1)
                {
                    // Delete the selected Martial Art.
                    MartialArt objMartialArt = _objFunctions.FindMartialArt(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts);

                    if (objMartialArt.Name == "One Trick Pony")
                    {
                        foreach (Quality objQuality in _objCharacter.Qualities)
                        {
                            if (objQuality.Name == "One Trick Pony")
                            {
                                _objCharacter.Qualities.Remove(objQuality);
                                foreach (TreeNode nodQuality in treQualities.Nodes[0].Nodes)
                                {
                                    if (nodQuality.Text.ToString() == "One Trick Pony")
                                        nodQuality.Remove();
                                }
                                break;
                            }
                        }
                    }

                    // Remove the Improvements for any Advantages for the Martial Art that is being removed.
                    foreach (MartialArtAdvantage objAdvantage in objMartialArt.Advantages)
                    {
                        _objImprovementManager.RemoveImprovements(Improvement.ImprovementSource.MartialArtAdvantage, objAdvantage.InternalId);
                    }

                    _objCharacter.MartialArts.Remove(objMartialArt);
                    treMartialArts.SelectedNode.Remove();

                    CalculateBP();
                    UpdateCharacterInfo();

                    _blnIsDirty = true;
                    UpdateWindowTitle();
                }
                if (treMartialArts.SelectedNode.Level == 2)
                {
                    // Find the selected Advantage object.
                    MartialArt objSelectedMartialArt = new MartialArt(_objCharacter);
                    MartialArtAdvantage objSelectedAdvantage = _objFunctions.FindMartialArtAdvantage(treMartialArts.SelectedNode.Tag.ToString(), _objCharacter.MartialArts, out objSelectedMartialArt);

                    _objImprovementManager.RemoveImprovements(Improvement.ImprovementSource.MartialArtAdvantage, objSelectedAdvantage.InternalId);
                    treMartialArts.SelectedNode.Remove();

                    objSelectedMartialArt.Advantages.Remove(objSelectedAdvantage);

                    CalculateBP();
                    UpdateCharacterInfo();

                    _blnIsDirty = true;
                    UpdateWindowTitle();
                }
            }
            catch
            {
            }
        }
Example #22
0
        /// <summary>
        /// Create all of the Improvements for an XML Node.
        /// </summary>
        /// <param name="objImprovementSource">Type of object that grants these Improvements.</param>
        /// <param name="strSourceName">Name of the item that grants these Improvements.</param>
        /// <param name="nodBonus">bonus XMLXode from the source data file.</param>
        /// <param name="blnConcatSelectedValue">Whether or not any selected values should be concatinated with the SourceName string when storing.</param>
        /// <param name="intRating">Selected Rating value that is used to replace the Rating string in an Improvement.</param>
        /// <param name="strFriendlyName">Friendly name to show in any dialogue windows that ask for a value.</param>
        public bool CreateImprovements(Improvement.ImprovementSource objImprovementSource, string strSourceName, XmlNode nodBonus, bool blnConcatSelectedValue = false, int intRating = 1, string strFriendlyName = "", object fCreate = null)
        {
            objFunctions.LogWrite(CommonFunctions.LogType.Entering, "Chummer.ImprovementManager", "CreateImprovements");
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "objImprovementSource = " + objImprovementSource.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "nodBonus = " + nodBonus.OuterXml.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "blnConcatSelectedValue = " + blnConcatSelectedValue.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "intRating = " + intRating.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strFriendlyName = " + strFriendlyName);
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "intRating = " + intRating.ToString());

            bool blnSuccess = true;

            try
            {
                if (nodBonus == null)
                {
                    _strForcedValue = "";
                    _strLimitSelection = "";
                    objFunctions.LogWrite(CommonFunctions.LogType.Exiting, "Chummer.ImprovementManager", "CreateImprovements");
                    return true;
                }

                string strUnique = "";
                if (nodBonus.Attributes["unique"] != null)
                    strUnique = nodBonus.Attributes["unique"].InnerText;

                _strSelectedValue = "";

                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                // If no friendly name was provided, use the one from SourceName.
                if (strFriendlyName == "")
                    strFriendlyName = strSourceName;

                if (nodBonus.HasChildNodes)
                {
                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Has Child Nodes");

                    // Select Text (custom entry for things like Allergy).
                    if (NodeExists(nodBonus, "selecttext"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selecttext");
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                        // Display the Select Text window and record the value that was entered.
                        frmSelectText frmPickText = new frmSelectText();
                        frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);

                        if (_strLimitSelection != "")
                        {
                            frmPickText.SelectedValue = _strLimitSelection;
                            frmPickText.Opacity = 0;
                        }

                        frmPickText.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickText.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            objFunctions.LogWrite(CommonFunctions.LogType.Exiting, "Chummer.ImprovementManager", "CreateImprovements");
                            return false;
                        }

                        _strSelectedValue = frmPickText.SelectedValue;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        // Create the Improvement.
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickText.SelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique);
                    }
                }

                // If there is no character object, don't attempt to add any Improvements.
                if (_objCharacter == null)
                {
                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_objCharacter = Null");
                    objFunctions.LogWrite(CommonFunctions.LogType.Exiting, "Chummer.ImprovementManager", "CreateImprovements");
                    return true;
                }

                // Check to see what bonuses the node grants.
                if (nodBonus.HasChildNodes)
                {
                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Has Child Nodes");
                    // Add an Attribute.
                    if (NodeExists(nodBonus, "addattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "addattribute");
                        if (nodBonus["addattribute"]["name"].InnerText == "MAG")
                        {
                            _objCharacter.MAGEnabled = true;
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for MAG");
                            CreateImprovement("MAG", objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, "enableattribute", 0, 0);
                        }
                        else if (nodBonus["addattribute"]["name"].InnerText == "RES")
                        {
                            _objCharacter.RESEnabled = true;
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for RES");
                            CreateImprovement("RES", objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, "enableattribute", 0, 0);
                        }
                    }

                    // Enable a special tab.
                    if (NodeExists(nodBonus, "enabletab"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "enabletab");
                        foreach (XmlNode objXmlEnable in nodBonus["enabletab"].ChildNodes)
                        {
                            switch (objXmlEnable.InnerText)
                            {
                                case "magician":
                                    _objCharacter.MagicianEnabled = true;
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "magician");
                                    CreateImprovement("Magician", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab, "enabletab", 0, 0);
                                    break;
                                case "adept":
                                    _objCharacter.AdeptEnabled = true;
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "adept");
                                    CreateImprovement("Adept", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab, "enabletab", 0, 0);
                                    break;
                                case "technomancer":
                                    _objCharacter.TechnomancerEnabled = true;
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "technomancer");
                                    CreateImprovement("Technomancer", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab, "enabletab", 0, 0);
                                    break;
                                case "critter":
                                    _objCharacter.CritterEnabled = true;
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "critter");
                                    CreateImprovement("Critter", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab, "enabletab", 0, 0);
                                    break;
                                case "initiation":
                                    _objCharacter.InitiationEnabled = true;
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiation");
                                    CreateImprovement("Initiation", objImprovementSource, strSourceName, Improvement.ImprovementType.SpecialTab, "enabletab", 0, 0);
                                    break;
                            }
                        }
                    }

                    // Select Restricted (select Restricted items for Fake Licenses).
                    if (NodeExists(nodBonus, "selectrestricted"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectrestricted");
                        frmSelectItem frmPickItem = new frmSelectItem();
                        frmPickItem.Character = _objCharacter;
                        if (_strForcedValue != string.Empty)
                            frmPickItem.ForceItem = _strForcedValue;
                        frmPickItem.AllowAutoSelect = false;
                        frmPickItem.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickItem.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickItem.SelectedItem;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        // Create the Improvement.
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName, Improvement.ImprovementType.Restricted, strUnique);
                    }

                    // Select a Skill.
                    if (NodeExists(nodBonus, "selectskill"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectrestricted");
                        if (_strForcedValue == "+2 to a Combat Skill")
                            _strForcedValue = "";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);

                        // Display the Select Skill window and record which Skill was selected.
                        frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                        if (strFriendlyName != "")
                            frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectskill = " + nodBonus.SelectSingleNode("selectskill").OuterXml.ToString());
                        if (nodBonus.SelectSingleNode("selectskill").OuterXml.Contains("skillgroup"))
                            frmPickSkill.OnlySkillGroup = nodBonus.SelectSingleNode("selectskill").Attributes["skillgroup"].InnerText;
                        else if (nodBonus.SelectSingleNode("selectskill").OuterXml.Contains("skillcategory"))
                            frmPickSkill.OnlyCategory = nodBonus.SelectSingleNode("selectskill").Attributes["skillcategory"].InnerText;
                        else if (nodBonus.SelectSingleNode("selectskill").OuterXml.Contains("excludecategory"))
                            frmPickSkill.ExcludeCategory = nodBonus.SelectSingleNode("selectskill").Attributes["excludecategory"].InnerText;
                        else if (nodBonus.SelectSingleNode("selectskill").OuterXml.Contains("limittoskill"))
                            frmPickSkill.LimitToSkill = nodBonus.SelectSingleNode("selectskill").Attributes["limittoskill"].InnerText;
                        if (_strForcedValue != "")
                        {
                            frmPickSkill.OnlySkill = _strForcedValue;
                            frmPickSkill.Opacity = 0;
                        }
                        frmPickSkill.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickSkill.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        bool blnAddToRating = false;
                        if (nodBonus["selectskill"]["applytorating"] != null)
                        {
                            if (nodBonus["selectskill"]["applytorating"].InnerText == "yes")
                                blnAddToRating = true;
                        }

                        _strSelectedValue = frmPickSkill.SelectedSkill;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        // Find the selected Skill.
                        foreach (Skill objSkill in _objCharacter.Skills)
                        {
                            if (frmPickSkill.SelectedSkill.Contains("Exotic Melee Weapon") || frmPickSkill.SelectedSkill.Contains("Exotic Ranged Weapon") || frmPickSkill.SelectedSkill.Contains("Pilot Exotic Vehicle"))
                            {
                                if (objSkill.Name + " (" + objSkill.Specialization + ")" == frmPickSkill.SelectedSkill)
                                {
                                    // We've found the selected Skill.
                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("val"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, ValueToInt(nodBonus["selectskill"]["val"].InnerText, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                                    }

                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("max"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, 0, 1, 0, ValueToInt(nodBonus["selectskill"]["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                                    }
                                }
                            }
                            else
                            {
                                if (objSkill.Name == frmPickSkill.SelectedSkill)
                                {
                                    // We've found the selected Skill.
                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("val"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, ValueToInt(nodBonus["selectskill"]["val"].InnerText, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                                    }

                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("max"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, 0, 1, 0, ValueToInt(nodBonus["selectskill"]["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                                    }
                                }
                            }
                        }
                    }

                    // Select a Skill Group.
                    if (NodeExists(nodBonus, "selectskillgroup"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectskillgroup");
                        string strExclude = "";
                        if (nodBonus["selectskillgroup"].Attributes["excludecategory"] != null)
                            strExclude = nodBonus["selectskillgroup"].Attributes["excludecategory"].InnerText;

                        frmSelectSkillGroup frmPickSkillGroup = new frmSelectSkillGroup();
                        if (strFriendlyName != "")
                            frmPickSkillGroup.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillGroupName").Replace("{0}", strFriendlyName);
                        else
                            frmPickSkillGroup.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillGroup");

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                        if (_strForcedValue != "")
                        {
                            frmPickSkillGroup.OnlyGroup = _strForcedValue;
                            frmPickSkillGroup.Opacity = 0;
                        }

                        if (strExclude != string.Empty)
                            frmPickSkillGroup.ExcludeCategory = strExclude;

                        frmPickSkillGroup.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickSkillGroup.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        bool blnAddToRating = false;
                        if (nodBonus["selectskillgroup"]["applytorating"] != null)
                        {
                            if (nodBonus["selectskillgroup"]["applytorating"].InnerText == "yes")
                                blnAddToRating = true;
                        }

                        _strSelectedValue = frmPickSkillGroup.SelectedSkillGroup;

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        if (nodBonus["selectskillgroup"].SelectSingleNode("bonus") != null)
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(nodBonus["selectskillgroup"]["bonus"].InnerText, intRating), 1, 0, 0, 0, 0, strExclude, blnAddToRating);
                        }
                        else
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(nodBonus["selectskillgroup"]["max"].InnerText, intRating), 0, 0, 1, 0, 0, strExclude, blnAddToRating);
                        }
                    }

                    // Select an Attribute.
                    if (NodeExists(nodBonus, "selectattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectattribute");
                        // Display the Select Attribute window and record which Skill was selected.
                        frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                        if (strFriendlyName != "")
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                        // Add MAG and/or RES to the list of Attributes if they are enabled on the form.
                        if (_objCharacter.MAGEnabled)
                            frmPickAttribute.AddMAG();
                        if (_objCharacter.RESEnabled)
                            frmPickAttribute.AddRES();

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectattribute = " + nodBonus["selectattribute"].OuterXml.ToString());

                        if (nodBonus["selectattribute"].InnerXml.Contains("<attribute>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in nodBonus["selectattribute"].SelectNodes("attribute"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickAttribute.LimitToList(strValue);
                        }

                        if (nodBonus["selectattribute"].InnerXml.Contains("<excludeattribute>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in nodBonus["selectattribute"].SelectNodes("excludeattribute"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickAttribute.RemoveFromList(strValue);
                        }

                        // Check to see if there is only one possible selection because of _strLimitSelection.
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                        if (_strLimitSelection != "")
                        {
                            frmPickAttribute.SingleAttribute(_strLimitSelection);
                            frmPickAttribute.Opacity = 0;
                        }

                        frmPickAttribute.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickAttribute.SelectedAttribute;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        // Record the improvement.
                        int intMin = 0;
                        int intAug = 0;
                        int intMax = 0;
                        int intAugMax = 0;

                        // Extract the modifiers.
                        if (nodBonus["selectattribute"].InnerXml.Contains("min"))
                            intMin = ValueToInt(nodBonus["selectattribute"]["min"].InnerXml, intRating);
                        if (nodBonus["selectattribute"].InnerXml.Contains("val"))
                            intAug = ValueToInt(nodBonus["selectattribute"]["val"].InnerXml, intRating);
                        if (nodBonus["selectattribute"].InnerXml.Contains("max"))
                            intMax = ValueToInt(nodBonus["selectattribute"]["max"].InnerXml, intRating);
                        if (nodBonus["selectattribute"].InnerXml.Contains("aug"))
                            intAugMax = ValueToInt(nodBonus["selectattribute"]["aug"].InnerXml, intRating);

                        string strAttribute = frmPickAttribute.SelectedAttribute;

                        if (nodBonus["selectattribute"]["affectbase"] != null)
                            strAttribute += "Base";

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(strAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, strUnique, 0, 1, intMin, intMax, intAug, intAugMax);
                    }

                    // Select a Limit.
                    if (NodeExists(nodBonus, "selectlimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectlimit");
                        // Display the Select Limit window and record which Limit was selected.
                        frmSelectLimit frmPickLimit = new frmSelectLimit();
                        if (strFriendlyName != "")
                            frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimitNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimit");

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectlimit = " + nodBonus["selectlimit"].OuterXml.ToString());

                        if (nodBonus["selectlimit"].InnerXml.Contains("<limit>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in nodBonus["selectlimit"].SelectNodes("limit"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickLimit.LimitToList(strValue);
                        }

                        if (nodBonus["selectlimit"].InnerXml.Contains("<excludelimit>"))
                        {
                            List<string> strValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in nodBonus["selectlimit"].SelectNodes("excludelimit"))
                                strValue.Add(objXmlAttribute.InnerText);
                            frmPickLimit.RemoveFromList(strValue);
                        }

                        // Check to see if there is only one possible selection because of _strLimitSelection.
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                        if (_strLimitSelection != "")
                        {
                            frmPickLimit.SingleLimit(_strLimitSelection);
                            frmPickLimit.Opacity = 0;
                        }

                        frmPickLimit.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickLimit.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickLimit.SelectedLimit;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        // Record the improvement.
                        int intMin = 0;
                        int intAug = 0;
                        int intMax = 0;
                        int intAugMax = 0;

                        // Extract the modifiers.
                        if (nodBonus["selectlimit"].InnerXml.Contains("min"))
                            intMin = ValueToInt(nodBonus["selectlimit"]["min"].InnerXml, intRating);
                        if (nodBonus["selectlimit"].InnerXml.Contains("val"))
                            intAug = ValueToInt(nodBonus["selectlimit"]["val"].InnerXml, intRating);
                        if (nodBonus["selectlimit"].InnerXml.Contains("max"))
                            intMax = ValueToInt(nodBonus["selectlimit"]["max"].InnerXml, intRating);
                        if (nodBonus["selectlimit"].InnerXml.Contains("aug"))
                            intAugMax = ValueToInt(nodBonus["selectlimit"]["aug"].InnerXml, intRating);

                        string strLimit = frmPickLimit.SelectedLimit;

                        if (nodBonus["selectlimit"]["affectbase"] != null)
                            strLimit += "Base";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        LimitModifier objLimitMod = new LimitModifier(_objCharacter);
                        // string strBonus = nodBonus["limitmodifier"]["value"].InnerText;
                        int intBonus = intAug;
                        string strName = strFriendlyName;
                        TreeNode nodTemp = new TreeNode();

                        Improvement.ImprovementType objType = Improvement.ImprovementType.PhysicalLimit;
                        if (strLimit == "Mental")
                            objType = Improvement.ImprovementType.MentalLimit;
                        else if (strLimit == "Social")
                            objType = Improvement.ImprovementType.SocialLimit;

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(strLimit, objImprovementSource, strSourceName, objType, strFriendlyName, intBonus, 0, intMin, intMax, intAug, intAugMax);
                    }

                    // Select an Attribute.
                    if (NodeExists(nodBonus, "swapskillattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "swapskillattribute");
                        // Display the Select Attribute window and record which Skill was selected.
                        frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                        if (strFriendlyName != "")
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                        List<string> strValue = new List<string>();
                        strValue.Add("LOG");
                        strValue.Add("WIL");
                        strValue.Add("INT");
                        strValue.Add("CHA");
                        strValue.Add("EDG");
                        strValue.Add("MAG");
                        strValue.Add("RES");
                        frmPickAttribute.RemoveFromList(strValue);

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "swapskillattribute = " + nodBonus["swapskillattribute"].OuterXml.ToString());

                        if (nodBonus["swapskillattribute"].InnerXml.Contains("<attribute>"))
                        {
                            List<string> strLimitValue = new List<string>();
                            foreach (XmlNode objXmlAttribute in nodBonus["swapskillattribute"].SelectNodes("attribute"))
                                strLimitValue.Add(objXmlAttribute.InnerText);
                            frmPickAttribute.LimitToList(strLimitValue);
                        }

                        // Check to see if there is only one possible selection because of _strLimitSelection.
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                        if (_strLimitSelection != "")
                        {
                            frmPickAttribute.SingleAttribute(_strLimitSelection);
                            frmPickAttribute.Opacity = 0;
                        }

                        frmPickAttribute.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickAttribute.SelectedAttribute;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickAttribute.SelectedAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.SwapSkillAttribute, strUnique);
                    }

                    // Select a Spell.
                    if (NodeExists(nodBonus, "selectspell"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectspell");
                        // Display the Select Spell window.
                        frmSelectSpell frmPickSpell = new frmSelectSpell(_objCharacter);

                        if (nodBonus["selectspell"].Attributes["category"] != null)
                            frmPickSpell.LimitCategory = nodBonus["selectspell"].Attributes["category"].InnerText;

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectspell = " + nodBonus["selectspell"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                        if (_strForcedValue != "")
                        {
                            frmPickSpell.ForceSpellName = _strForcedValue;
                            frmPickSpell.Opacity = 0;
                        }

                        frmPickSpell.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickSpell.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return false;
                        }

                        _strSelectedValue = frmPickSpell.SelectedSpell;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickSpell.SelectedSpell, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique);
                    }

                    // Affect a Specific Attribute.
                    if (NodeExists(nodBonus, "specificattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "specificattribute");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificattribute = " + nodBonus["specificattribute"].OuterXml.ToString());
                        XmlNodeList objXmlAttributeList = nodBonus.SelectNodes("specificattribute");
                        foreach (XmlNode objXmlAttribute in objXmlAttributeList)
                        {
                            if (objXmlAttribute["name"].InnerText != "ESS")
                            {
                                // Display the Select Attribute window and record which Attribute was selected.
                                // Record the improvement.
                                int intMin = 0;
                                int intAug = 0;
                                int intMax = 0;
                                int intAugMax = 0;

                                // Extract the modifiers.
                                if (objXmlAttribute.InnerXml.Contains("min"))
                                    intMin = ValueToInt(objXmlAttribute["min"].InnerXml, intRating);
                                if (objXmlAttribute.InnerXml.Contains("val"))
                                    intAug = ValueToInt(objXmlAttribute["val"].InnerXml, intRating);
                                if (objXmlAttribute.InnerXml.Contains("max"))
                                {
                                    if (objXmlAttribute["max"].InnerText.Contains("-natural"))
                                    {
                                        intMax = Convert.ToInt32(objXmlAttribute["max"].InnerText.Replace("-natural", string.Empty)) - _objCharacter.GetAttribute(objXmlAttribute["name"].InnerText).MetatypeMaximum;
                                    }
                                    else
                                        intMax = ValueToInt(objXmlAttribute["max"].InnerXml, intRating);
                                }
                                if (objXmlAttribute.InnerXml.Contains("aug"))
                                    intAugMax = ValueToInt(objXmlAttribute["aug"].InnerXml, intRating);

                                string strUseUnique = strUnique;
                                if (objXmlAttribute["name"].Attributes["precedence"] != null)
                                    strUseUnique = "precedence" + objXmlAttribute["name"].Attributes["precedence"].InnerText;

                                string strAttribute = objXmlAttribute["name"].InnerText;

                                if (objXmlAttribute["affectbase"] != null)
                                    strAttribute += "Base";

                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(strAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, strUseUnique, 0, 1, intMin, intMax, intAug, intAugMax);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Essence, "", Convert.ToInt32(objXmlAttribute["val"].InnerText));
                            }
                        }
                    }

                    // Change the maximum number of BP that can be spent on Nuyen.
                    if (NodeExists(nodBonus, "nuyenmaxbp"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "nuyenmaxbp");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "nuyenmaxbp = " + nodBonus["nuyenmaxbp"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.NuyenMaxBP, "", ValueToInt(nodBonus["nuyenmaxbp"].InnerText, intRating));
                    }

                    // Apply a bonus/penalty to physical limit.
                    if (NodeExists(nodBonus, "physicallimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "physicallimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "physicallimit = " + nodBonus["physicallimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalLimit, "", ValueToInt(nodBonus["physicallimit"].InnerText, intRating));
                    }

                    // Apply a bonus/penalty to mental limit.
                    if (NodeExists(nodBonus, "mentallimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "mentallimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "mentallimit = " + nodBonus["mentallimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MentalLimit, "", ValueToInt(nodBonus["mentallimit"].InnerText, intRating));
                    }

                    // Apply a bonus/penalty to social limit.
                    if (NodeExists(nodBonus, "sociallimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "sociallimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "sociallimit = " + nodBonus["sociallimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SocialLimit, "", ValueToInt(nodBonus["sociallimit"].InnerText, intRating));
                    }

                    // Change the amount of Nuyen the character has at creation time (this can put the character over the amount they're normally allowed).
                    if (NodeExists(nodBonus, "nuyenamt"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "nuyenamt");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "nuyenamt = " + nodBonus["nuyenamt"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Nuyen, strUnique, ValueToInt(nodBonus["nuyenamt"].InnerText, intRating));
                    }

                    // Improve Condition Monitors.
                    if (NodeExists(nodBonus, "conditionmonitor"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "conditionmonitor");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "conditionmonitor = " + nodBonus["conditionmonitor"].OuterXml.ToString());
                        // Physical Condition.
                        if (nodBonus.SelectSingleNode("conditionmonitor").InnerXml.Contains("physical"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Physical");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalCM, strUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["physical"].InnerText, intRating));
                        }

                        // Stun Condition.
                        if (nodBonus.SelectSingleNode("conditionmonitor").InnerXml.Contains("stun"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Stun");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.StunCM, strUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["stun"].InnerText, intRating));
                        }

                        // Condition Monitor Threshold.
                        if (NodeExists(nodBonus.SelectSingleNode("conditionmonitor"), "threshold"))
                        {
                            string strUseUnique = strUnique;
                            if (nodBonus["conditionmonitor"]["threshold"].Attributes["precedence"] != null)
                                strUseUnique = "precedence" + nodBonus["conditionmonitor"]["threshold"].Attributes["precedence"].InnerText;

                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Threshold");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThreshold, strUseUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["threshold"].InnerText, intRating));
                        }

                        // Condition Monitor Threshold Offset. (Additioal boxes appear before the FIRST Condition Monitor penalty)
                        if (NodeExists(nodBonus.SelectSingleNode("conditionmonitor"), "thresholdoffset"))
                        {
                            string strUseUnique = strUnique;
                            if (nodBonus["conditionmonitor"]["thresholdoffset"].Attributes["precedence"] != null)
                                strUseUnique = "precedence" + nodBonus["conditionmonitor"]["thresholdoffset"].Attributes["precedence"].InnerText;

                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Threshold Offset");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThresholdOffset, strUseUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["thresholdoffset"].InnerText, intRating));
                        }

                        // Condition Monitor Overflow.
                        if (nodBonus.SelectSingleNode("conditionmonitor").InnerXml.Contains("overflow"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Overflow");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMOverflow, strUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["overflow"].InnerText, intRating));
                        }
                    }

                    // Improve Living Personal Attributes.
                    if (NodeExists(nodBonus, "livingpersona"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "livingpersona");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "livingpersona = " + nodBonus["livingpersona"].OuterXml.ToString());
                        // Response.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("response"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for response");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaResponse, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["response"].InnerText, intRating));
                        }

                        // Signal.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("signal"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for signal");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSignal, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["signal"].InnerText, intRating));
                        }

                        // Firewall.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("firewall"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for firewall");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaFirewall, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["firewall"].InnerText, intRating));
                        }

                        // System.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("system"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for system");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSystem, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["system"].InnerText, intRating));
                        }

                        // Biofeedback Filter.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("biofeedback"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for biofeedback");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaBiofeedback, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["biofeedback"].InnerText, intRating));
                        }
                    }

                    // The Improvement adjusts a specific Skill.
                    if (NodeExists(nodBonus, "specificskill"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "specificskill");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificskill = " + nodBonus["specificskill"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("specificskill");
                        // Run through each specific Skill since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }

                            string strUseUnique = strUnique;
                            if (nodBonus["specificskill"].Attributes["precedence"] != null)
                                strUseUnique = "precedence" + nodBonus["specificskill"].Attributes["precedence"].InnerText;

                            // Record the improvement.
                            if (objXmlSkill["bonus"] != null)
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for bonus");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUseUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                            if (objXmlSkill["max"] != null)
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for max");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUseUnique, 0, 1, 0, ValueToInt(objXmlSkill["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement adds a martial art
                    if (NodeExists(nodBonus, "martialart"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "martialart");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "martialart = " + nodBonus["martialart"].OuterXml.ToString());
                        XmlDocument _objXmlDocument = XmlManager.Instance.Load("martialarts.xml");
                        XmlNode objXmlArt = _objXmlDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + nodBonus["martialart"].InnerText + "\"]");

                        TreeNode objNode = new TreeNode();
                        MartialArt objMartialArt = new MartialArt(_objCharacter);
                        objMartialArt.Create(objXmlArt, objNode, _objCharacter);
                        objMartialArt.IsQuality = true;
                        _objCharacter.MartialArts.Add(objMartialArt);
                    }

                    // The Improvement adds a limit modifier
                    if (NodeExists(nodBonus, "limitmodifier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "limitmodifier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "limitmodifier = " + nodBonus["limitmodifier"].OuterXml.ToString());
                        LimitModifier objLimitMod = new LimitModifier(_objCharacter);
                        string strLimit = nodBonus["limitmodifier"]["limit"].InnerText;
                        string strBonus = nodBonus["limitmodifier"]["value"].InnerText;
                        string strCondition = "";
                        try
                        {
                            strCondition = nodBonus["limitmodifier"]["condition"].InnerText;
                        }
                        catch { }
                        int intBonus = 0;
                        if (strBonus == "Rating")
                            intBonus = intRating;
                        else
                            intBonus = Convert.ToInt32(strBonus);
                        string strName = strFriendlyName;
                        TreeNode nodTemp = new TreeNode();
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(strLimit, objImprovementSource, strSourceName, Improvement.ImprovementType.LimitModifier, strFriendlyName, intBonus, 0, 0, 0, 0, 0, strCondition);

                    }

                    // The Improvement adjusts a Skill Category.
                    if (NodeExists(nodBonus, "skillcategory"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillcategory");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillcategory = " + nodBonus["skillcategory"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("skillcategory");
                        // Run through each of the Skill Categories since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }
                            if (objXmlSkill.InnerXml.Contains("exclude"))
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement - exclude");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillCategory, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillCategory, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement adjusts a Skill Group.
                    if (NodeExists(nodBonus, "skillgroup"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillgroup");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillgroup = " + nodBonus["skillgroup"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("skillgroup");
                        // Run through each of the Skill Groups since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }
                            if (objXmlSkill.InnerXml.Contains("exclude"))
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement - exclude");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement adjust Skills with the given Attribute.
                    if (NodeExists(nodBonus, "skillattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillattribute");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillattribute = " + nodBonus["skillattribute"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("skillattribute");
                        // Run through each of the Skill Attributes since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            string strUseUnique = strUnique;
                            if (objXmlSkill["name"].Attributes["precedence"] != null)
                                strUseUnique = "precedence" + objXmlSkill["name"].Attributes["precedence"].InnerText;

                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }
                            if (objXmlSkill.InnerXml.Contains("exclude"))
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement - exclude");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillAttribute, strUseUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillAttribute, strUseUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement comes from Enhanced Articulation (improves Physical Active Skills linked to a Physical Attribute).
                    if (NodeExists(nodBonus, "skillarticulation"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillarticulation");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillarticulation = " + nodBonus["skillarticulation"].OuterXml.ToString());
                        XmlNode objXmlSkill = nodBonus.SelectSingleNode("skillarticulation");
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EnhancedArticulation, strUnique, ValueToInt(objXmlSkill["bonus"].InnerText, intRating));
                    }

                    // Check for Armor modifiers.
                    if (NodeExists(nodBonus, "armor"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "armor");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "armor = " + nodBonus["armor"].OuterXml.ToString());
                        XmlNode objXmlArmor = nodBonus.SelectSingleNode("armor");
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Armor, strUnique, ValueToInt(objXmlArmor.InnerText, intRating));
                    }

                    // Check for Reach modifiers.
                    if (NodeExists(nodBonus, "reach"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "reach");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "reach = " + nodBonus["reach"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Reach, strUnique, ValueToInt(nodBonus["reach"].InnerText, intRating));
                    }

                    // Check for Unarmed Damage Value modifiers.
                    if (NodeExists(nodBonus, "unarmeddv"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "unarmeddv");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "unarmeddv = " + nodBonus["unarmeddv"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDV, strUnique, ValueToInt(nodBonus["unarmeddv"].InnerText, intRating));
                    }

                    // Check for Unarmed Damage Value Physical.
                    if (NodeExists(nodBonus, "unarmeddvphysical"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "unarmeddvphysical");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "unarmeddvphysical = " + nodBonus["unarmeddvphysical"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDVPhysical, "");
                    }

                    // Check for Unarmed Armor Penetration.
                    if (NodeExists(nodBonus, "unarmedap"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "unarmedap");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "unarmedap = " + nodBonus["unarmedap"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedAP, strUnique, ValueToInt(nodBonus["unarmedap"].InnerText, intRating));
                    }

                    // Check for Initiative modifiers.
                    if (NodeExists(nodBonus, "initiative"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiative");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiative = " + nodBonus["initiative"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiative, strUnique, ValueToInt(nodBonus["initiative"].InnerText, intRating));
                    }

                    // Check for Initiative Pass modifiers. Only the highest one ever applies.
                    if (NodeExists(nodBonus, "initiativepass"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiativepass");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiativepass = "******"initiativepass"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.InitiativePass, "initiativepass", ValueToInt(nodBonus["initiativepass"].InnerText, intRating));
                    }

                    // Check for Initiative Pass modifiers. Only the highest one ever applies.
                    if (NodeExists(nodBonus, "initiativepassadd"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiativepassadd");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiativepassadd = " + nodBonus["initiativepassadd"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.InitiativePassAdd, strUnique, ValueToInt(nodBonus["initiativepassadd"].InnerText, intRating));
                    }

                    // Check for Matrix Initiative modifiers.
                    if (NodeExists(nodBonus, "matrixinitiative"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "matrixinitiative");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "matrixinitiative = " + nodBonus["matrixinitiative"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiative, strUnique, ValueToInt(nodBonus["matrixinitiative"].InnerText, intRating));
                    }

                    // Check for Matrix Initiative Pass modifiers.
                    if (NodeExists(nodBonus, "matrixinitiativepass"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "matrixinitiativepass");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "matrixinitiativepass = "******"matrixinitiativepass"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass, "matrixinitiativepass", ValueToInt(nodBonus["matrixinitiativepass"].InnerText, intRating));
                    }

                    // Check for Matrix Initiative Pass modifiers.
                    if (NodeExists(nodBonus, "matrixinitiativepassadd"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "matrixinitiativepassadd");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "matrixinitiativepassadd = " + nodBonus["matrixinitiativepassadd"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass, strUnique, ValueToInt(nodBonus["matrixinitiativepassadd"].InnerText, intRating));
                    }

                    // Check for Lifestyle cost modifiers.
                    if (NodeExists(nodBonus, "lifestylecost"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "lifestylecost");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "lifestylecost = " + nodBonus["lifestylecost"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LifestyleCost, strUnique, ValueToInt(nodBonus["lifestylecost"].InnerText, intRating));
                    }

                    // Check for basic Lifestyle cost modifiers.
                    if (NodeExists(nodBonus, "basiclifestylecost"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "basiclifestylecost");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "basiclifestylecost = " + nodBonus["basiclifestylecost"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicLifestyleCost, strUnique, ValueToInt(nodBonus["basiclifestylecost"].InnerText, intRating));
                    }

                    // Check for Genetech Cost modifiers.
                    if (NodeExists(nodBonus, "genetechcostmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "genetechcostmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "genetechcostmultiplier = " + nodBonus["genetechcostmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.GenetechCostMultiplier, strUnique, ValueToInt(nodBonus["genetechcostmultiplier"].InnerText, intRating));
                    }

                    // Check for Genetech: Transgenics Cost modifiers.
                    if (NodeExists(nodBonus, "transgenicsgenetechcost"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "transgenicsgenetechcost");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "transgenicsgenetechcost = " + nodBonus["transgenicsgenetechcost"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.TransgenicsBiowareCost, strUnique, ValueToInt(nodBonus["transgenicsgenetechcost"].InnerText, intRating));
                    }

                    // Check for Basic Bioware Essence Cost modifiers.
                    if (NodeExists(nodBonus, "basicbiowareessmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "basicbiowareessmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "basicbiowareessmultiplier = " + nodBonus["basicbiowareessmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicBiowareEssCost, strUnique, ValueToInt(nodBonus["basicbiowareessmultiplier"].InnerText, intRating));
                    }

                    // Check for Bioware Essence Cost modifiers.
                    if (NodeExists(nodBonus, "biowareessmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "biowareessmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "biowareessmultiplier = " + nodBonus["biowareessmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BiowareEssCost, strUnique, ValueToInt(nodBonus["biowareessmultiplier"].InnerText, intRating));
                    }

                    // Check for Cybeware Essence Cost modifiers.
                    if (NodeExists(nodBonus, "cyberwareessmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "cyberwareessmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "cyberwareessmultiplier = " + nodBonus["cyberwareessmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CyberwareEssCost, strUnique, ValueToInt(nodBonus["cyberwareessmultiplier"].InnerText, intRating));
                    }

                    // Check for Uneducated modifiers.
                    if (NodeExists(nodBonus, "uneducated"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "uneducated");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "uneducated = " + nodBonus["uneducated"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uneducated, strUnique);
                        _objCharacter.Uneducated = true;
                    }

                    // Check for Uncouth modifiers.
                    if (NodeExists(nodBonus, "uncouth"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "uncouth");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "uncouth = " + nodBonus["uncouth"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uncouth, strUnique);
                        _objCharacter.Uncouth = true;
                    }

                    // Check for Infirm modifiers.
                    if (NodeExists(nodBonus, "infirm"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "infirm");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "infirm = " + nodBonus["infirm"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Infirm, strUnique);
                        _objCharacter.Infirm = true;
                    }

                    // Check for Adept Linguistics.
                    if (NodeExists(nodBonus, "adeptlinguistics"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "adeptlinguistics");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "adeptlinguistics = " + nodBonus["adeptlinguistics"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptLinguistics, strUnique, 1);
                    }

                    // Check for Weapon Category DV modifiers.
                    if (NodeExists(nodBonus, "weaponcategorydv"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "weaponcategorydv");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "weaponcategorydv = " + nodBonus["weaponcategorydv"].OuterXml.ToString());
                        XmlNodeList objXmlCategoryList = nodBonus.SelectNodes("weaponcategorydv");
                        XmlNode nodWeapon = nodBonus["weaponcategorydv"];

                        if (NodeExists(nodWeapon, "selectskill"))
                        {
                            // Display the Select Skill window and record which Skill was selected.
                            frmSelectItem frmPickCategory = new frmSelectItem();
                            List<ListItem> lstGeneralItems = new List<ListItem>();

                            ListItem liBlades = new ListItem();
                            liBlades.Name = "Blades";
                            liBlades.Value = "Blades";

                            ListItem liClubs = new ListItem();
                            liClubs.Name = "Clubs";
                            liClubs.Value = "Clubs";

                            ListItem liUnarmed = new ListItem();
                            liUnarmed.Name = "Unarmed";
                            liUnarmed.Value = "Unarmed";

                            ListItem liAstral = new ListItem();
                            liAstral.Name = "Astral Combat";
                            liAstral.Value = "Astral Combat";

                            ListItem liExotic = new ListItem();
                            liExotic.Name = "Exotic Melee Weapons";
                            liExotic.Value = "Exotic Melee Weapons";

                            lstGeneralItems.Add(liAstral);
                            lstGeneralItems.Add(liBlades);
                            lstGeneralItems.Add(liClubs);
                            lstGeneralItems.Add(liExotic);
                            lstGeneralItems.Add(liUnarmed);
                            frmPickCategory.GeneralItems = lstGeneralItems;

                            if (strFriendlyName != "")
                                frmPickCategory.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed").Replace("{0}", strFriendlyName);
                            else
                                frmPickCategory.Description = LanguageManager.Instance.GetString("Title_SelectWeaponCategory");

                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);

                            if (_strForcedValue.StartsWith("Adept:") || _strForcedValue.StartsWith("Magician:"))
                                _strForcedValue = "";

                            if (_strForcedValue != "")
                            {
                                frmPickCategory.Opacity = 0;
                            }
                            frmPickCategory.ShowDialog();

                            // Make sure the dialogue window was not canceled.
                            if (frmPickCategory.DialogResult == DialogResult.Cancel)
                            {
                                Rollback();
                                blnSuccess = false;
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return false;
                            }

                            string strSelected = frmPickCategory.SelectedItem;

                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelected = " + strSelected);

                            foreach (Power objPower in _objCharacter.Powers)
                            {
                                if (objPower.InternalId == strSourceName)
                                {
                                    objPower.Name = objPower.Name + " (" + strSelected + ")";
                                }
                            }

                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement(strSelected, objImprovementSource, strSourceName, Improvement.ImprovementType.WeaponCategoryDV, strUnique, ValueToInt(nodWeapon["bonus"].InnerXml, intRating));
                        }
                        else
                        {
                            // Run through each of the Skill Groups since there may be more than one affected.
                            foreach (XmlNode objXmlCategory in objXmlCategoryList)
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(objXmlCategory["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.WeaponCategoryDV, strUnique, ValueToInt(objXmlCategory["bonus"].InnerXml, intRating));
                            }
                        }
                    }

                    // Check for Mentor Spirit bonuses.
                    if (NodeExists(nodBonus, "selectmentorspirit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectmentorspirit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectmentorspirit = " + nodBonus["selectmentorspirit"].OuterXml.ToString());
                        frmSelectMentorSpirit frmPickMentorSpirit = new frmSelectMentorSpirit(_objCharacter);
                        frmPickMentorSpirit.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickMentorSpirit.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return blnSuccess;
                        }

                        _strSelectedValue = frmPickMentorSpirit.SelectedMentor;

                        string strHoldValue = _strSelectedValue;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                        if (frmPickMentorSpirit.BonusNode != null)
                        {
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                        }

                        if (frmPickMentorSpirit.Choice1BonusNode != null)
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "frmPickMentorSpirit.Choice1BonusNode = " + frmPickMentorSpirit.Choice1BonusNode.OuterXml.ToString());
                            string strForce = _strForcedValue;
                            if (!frmPickMentorSpirit.Choice1.StartsWith("Adept:") && !frmPickMentorSpirit.Choice1.StartsWith("Magician:"))
                                _strForcedValue = frmPickMentorSpirit.Choice1;
                            else
                                _strForcedValue = "";
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice1BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                            _strForcedValue = strForce;
                            _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice1;
                        }

                        if (frmPickMentorSpirit.Choice2BonusNode != null)
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "frmPickMentorSpirit.Choice2BonusNode = " + frmPickMentorSpirit.Choice2BonusNode.OuterXml.ToString());
                            string strForce = _strForcedValue;
                            if (!frmPickMentorSpirit.Choice2.StartsWith("Adept:") && !frmPickMentorSpirit.Choice2.StartsWith("Magician:"))
                                _strForcedValue = frmPickMentorSpirit.Choice2;
                            else
                                _strForcedValue = "";
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice2BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                            _strForcedValue = strForce;
                            _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice2;
                        }

                        _strSelectedValue = strHoldValue;
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                    }

                    // Check for Paragon bonuses.
                    if (NodeExists(nodBonus, "selectparagon"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectparagon");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectparagon = " + nodBonus["selectparagon"].OuterXml.ToString());
                        frmSelectMentorSpirit frmPickMentorSpirit = new frmSelectMentorSpirit(_objCharacter);
                        frmPickMentorSpirit.XmlFile = "paragons.xml";
                        frmPickMentorSpirit.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickMentorSpirit.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return blnSuccess;
                        }

                        _strSelectedValue = frmPickMentorSpirit.SelectedMentor;
                        string strHoldValue = _strSelectedValue;
                        if (blnConcatSelectedValue)
                            strSourceName += " (" + _strSelectedValue + ")";

                        if (frmPickMentorSpirit.BonusNode != null)
                        {
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                        }

                        if (frmPickMentorSpirit.Choice1BonusNode != null)
                        {
                            string strForce = _strForcedValue;
                            _strForcedValue = frmPickMentorSpirit.Choice1;
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice1BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                            _strForcedValue = strForce;
                            _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice1;
                        }

                        if (frmPickMentorSpirit.Choice2BonusNode != null)
                        {
                            string strForce = _strForcedValue;
                            _strForcedValue = frmPickMentorSpirit.Choice2;
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice2BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                            _strForcedValue = strForce;
                            _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice2;
                        }

                        _strSelectedValue = strHoldValue;
                    }

                    // Check for Smartlink bonus.
                    if (NodeExists(nodBonus, "smartlink"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "smartlink");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "smartlink = " + nodBonus["smartlink"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Smartlink, "smartlink");
                    }

                    // Check for Adapsin bonus.
                    if (NodeExists(nodBonus, "adapsin"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "adapsin");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "adapsin = " + nodBonus["adapsin"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Adapsin, "adapsin");
                    }

                    // Check for SoftWeave bonus.
                    if (NodeExists(nodBonus, "softweave"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "softweave");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "softweave = " + nodBonus["softweave"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SoftWeave, "softweave");
                    }

                    // Check for Sensitive System.
                    if (NodeExists(nodBonus, "sensitivesystem"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "sensitivesystem");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "sensitivesystem = " + nodBonus["sensitivesystem"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SensitiveSystem, "sensitivesystem");
                    }

                    // Check for Movement Percent.
                    if (NodeExists(nodBonus, "movementpercent"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "movementpercent");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "movementpercent = " + nodBonus["movementpercent"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MovementPercent, "", ValueToInt(nodBonus["movementpercent"].InnerText, intRating));
                    }

                    // Check for Swim Percent.
                    if (NodeExists(nodBonus, "swimpercent"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "swimpercent");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "swimpercent = " + nodBonus["swimpercent"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SwimPercent, "", ValueToInt(nodBonus["swimpercent"].InnerText, intRating));
                    }

                    // Check for Fly Percent.
                    if (NodeExists(nodBonus, "flypercent"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "flypercent");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "flypercent = " + nodBonus["flypercent"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlyPercent, "", ValueToInt(nodBonus["flypercent"].InnerText, intRating));
                    }

                    // Check for Fly Speed.
                    if (NodeExists(nodBonus, "flyspeed"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "flyspeed");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "flyspeed = " + nodBonus["flyspeed"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlySpeed, "", ValueToInt(nodBonus["flyspeed"].InnerText, intRating));
                    }

                    // Check for free Positive Qualities.
                    if (NodeExists(nodBonus, "freepositivequalities"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "freepositivequalities");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "freepositivequalities = " + nodBonus["freepositivequalities"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreePositiveQualities, "", ValueToInt(nodBonus["freepositivequalities"].InnerText, intRating));
                    }

                    // Check for free Negative Qualities.
                    if (NodeExists(nodBonus, "freenegativequalities"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "freenegativequalities");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "freenegativequalities = " + nodBonus["freenegativequalities"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeNegativeQualities, "", ValueToInt(nodBonus["freenegativequalities"].InnerText, intRating));
                    }

                    // Check for Select Side.
                    if (NodeExists(nodBonus, "selectside"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectside");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectside = " + nodBonus["selectside"].OuterXml.ToString());
                        frmSelectSide frmPickSide = new frmSelectSide();
                        frmPickSide.Description = LanguageManager.Instance.GetString("Label_SelectSide").Replace("{0}", strFriendlyName);
                        if (_strForcedValue != "")
                            frmPickSide.ForceValue(_strForcedValue);
                        else
                            frmPickSide.ShowDialog();

                        // Make sure the dialogue window was not canceled.
                        if (frmPickSide.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return blnSuccess;
                        }

                        _strSelectedValue = frmPickSide.SelectedSide;
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                    }

                    // Check for Free Spirit Power Points.
                    if (NodeExists(nodBonus, "freespiritpowerpoints"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "freespiritpowerpoints");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "freespiritpowerpoints = " + nodBonus["freespiritpowerpoints"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeSpiritPowerPoints, "", ValueToInt(nodBonus["freespiritpowerpoints"].InnerText, intRating));
                    }

                    // Check for Adept Power Points.
                    if (NodeExists(nodBonus, "adeptpowerpoints"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "adeptpowerpoints");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "adeptpowerpoints = " + nodBonus["adeptpowerpoints"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptPowerPoints, "", ValueToInt(nodBonus["adeptpowerpoints"].InnerText, intRating));
                    }

                    // Check for Adept Powers
                    if (NodeExists(nodBonus, "specificpower"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "specificpower");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificpower = " + nodBonus["specificpower"].OuterXml.ToString());
                        // If the character isn't an adept or mystic adept, skip the rest of this.
                        if (_objCharacter.AdeptEnabled)
                        {
                            string strSelection = "";
                            _strForcedValue = "";

                            XmlNodeList objXmlPowerList = nodBonus.SelectNodes("specificpower");
                            foreach (XmlNode objXmlSpecificPower in objXmlPowerList)
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "objXmlSpecificPower = " + objXmlSpecificPower.OuterXml.ToString());

                                string strPowerName = objXmlSpecificPower["name"].InnerText;
                                int intLevels = 0;
                                if (objXmlSpecificPower["val"] != null)
                                    intLevels = Convert.ToInt32(objXmlSpecificPower["val"].InnerText);
                                bool blnFree = false;
                                if (objXmlSpecificPower["free"] != null)
                                    blnFree = (objXmlSpecificPower["free"].InnerText == "yes");

                                string strPowerNameLimit = strPowerName;
                                if (objXmlSpecificPower["selectlimit"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectlimit = " + objXmlSpecificPower["selectlimit"].OuterXml.ToString());
                                    _strForcedValue = "";
                                    // Display the Select Limit window and record which Limit was selected.
                                    frmSelectLimit frmPickLimit = new frmSelectLimit();
                                    if (strFriendlyName != "")
                                        frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimitNamed").Replace("{0}", strFriendlyName);
                                    else
                                        frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimit");

                                    if (nodBonus["specificpower"]["selectlimit"].InnerXml.Contains("<limit>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in nodBonus["specificpower"]["selectlimit"].SelectNodes("limit"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickLimit.LimitToList(strValue);
                                    }

                                    if (nodBonus["specificpower"]["selectlimit"].InnerXml.Contains("<excludelimit>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in nodBonus["specificpower"]["selectlimit"].SelectNodes("excludelimit"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickLimit.RemoveFromList(strValue);
                                    }

                                    // Check to see if there is only one possible selection because of _strLimitSelection.
                                    if (_strForcedValue != "")
                                        _strLimitSelection = _strForcedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strLimitSelection != "")
                                    {
                                        frmPickLimit.SingleLimit(_strLimitSelection);
                                        frmPickLimit.Opacity = 0;
                                    }

                                    frmPickLimit.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickLimit.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    _strSelectedValue = frmPickLimit.SelectedLimit;
                                    strSelection = _strSelectedValue;
                                    _strForcedValue = _strSelectedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objXmlSpecificPower["selectskill"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectskill = " + objXmlSpecificPower["selectskill"].OuterXml.ToString());
                                    XmlNode nodSkill = nodBonus["specificpower"];
                                    // Display the Select Skill window and record which Skill was selected.
                                    frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                                    if (strFriendlyName != "")
                                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed").Replace("{0}", strFriendlyName);
                                    else
                                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

                                    if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillgroup"))
                                        frmPickSkill.OnlySkillGroup = nodSkill.SelectSingleNode("selectskill").Attributes["skillgroup"].InnerText;
                                    else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillcategory"))
                                        frmPickSkill.OnlyCategory = nodSkill.SelectSingleNode("selectskill").Attributes["skillcategory"].InnerText;
                                    else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("excludecategory"))
                                        frmPickSkill.ExcludeCategory = nodSkill.SelectSingleNode("selectskill").Attributes["excludecategory"].InnerText;
                                    else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("limittoskill"))
                                        frmPickSkill.LimitToSkill = nodSkill.SelectSingleNode("selectskill").Attributes["limittoskill"].InnerText;

                                    if (_strForcedValue.StartsWith("Adept:") || _strForcedValue.StartsWith("Magician:"))
                                        _strForcedValue = "";

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strForcedValue != "")
                                    {
                                        frmPickSkill.OnlySkill = _strForcedValue;
                                        frmPickSkill.Opacity = 0;
                                    }
                                    frmPickSkill.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickSkill.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    _strSelectedValue = frmPickSkill.SelectedSkill;
                                    _strForcedValue = _strSelectedValue;
                                    strSelection = _strSelectedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objXmlSpecificPower["selecttext"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selecttext = " + objXmlSpecificPower["selecttext"].OuterXml.ToString());
                                    frmSelectText frmPickText = new frmSelectText();
                                    frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strLimitSelection != "")
                                    {
                                        frmPickText.SelectedValue = _strLimitSelection;
                                        frmPickText.Opacity = 0;
                                    }

                                    frmPickText.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickText.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    strSelection = frmPickText.SelectedValue;
                                    _strLimitSelection = strSelection;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objXmlSpecificPower["specificattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificattribute = " + objXmlSpecificPower["specificattribute"].OuterXml.ToString());
                                    strSelection = objXmlSpecificPower["specificattribute"]["name"].InnerText.ToString();
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objXmlSpecificPower["selectattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectattribute = " + objXmlSpecificPower["selectattribute"].OuterXml.ToString());
                                    XmlNode nodSkill = objXmlSpecificPower;
                                    if (_strForcedValue.StartsWith("Adept"))
                                        _strForcedValue = "";

                                    // Display the Select Attribute window and record which Attribute was selected.
                                    frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                                    if (strFriendlyName != "")
                                        frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                                    else
                                        frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                                    // Add MAG and/or RES to the list of Attributes if they are enabled on the form.
                                    if (_objCharacter.MAGEnabled)
                                        frmPickAttribute.AddMAG();
                                    if (_objCharacter.RESEnabled)
                                        frmPickAttribute.AddRES();

                                    if (nodSkill["selectattribute"].InnerXml.Contains("<attribute>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("attribute"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickAttribute.LimitToList(strValue);
                                    }

                                    if (nodSkill["selectattribute"].InnerXml.Contains("<excludeattribute>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("excludeattribute"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickAttribute.RemoveFromList(strValue);
                                    }

                                    // Check to see if there is only one possible selection because of _strLimitSelection.
                                    if (_strForcedValue != "")
                                        _strLimitSelection = _strForcedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strLimitSelection != "")
                                    {
                                        frmPickAttribute.SingleAttribute(_strLimitSelection);
                                        frmPickAttribute.Opacity = 0;
                                    }

                                    frmPickAttribute.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    _strSelectedValue = frmPickAttribute.SelectedAttribute;
                                    if (blnConcatSelectedValue)
                                        strSourceName += " (" + _strSelectedValue + ")";
                                    strSelection = _strSelectedValue;
                                    _strForcedValue = _strSelectedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                }

                                // Check if the character already has this power
                                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                bool blnHasPower = false;
                                Power objPower = new Power(_objCharacter);
                                foreach (Power power in _objCharacter.Powers)
                                {
                                    if (power.Name == strPowerNameLimit)
                                    {
                                        if (power.Extra != "" && power.Extra == strSelection)
                                        {
                                            blnHasPower = true;
                                            objPower = power;
                                        }
                                        else if (power.Extra == "")
                                        {
                                            blnHasPower = true;
                                            objPower = power;
                                        }
                                    }
                                }

                                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "blnHasPower = " + blnHasPower);

                                if (blnHasPower)
                                {
                                    // If yes, mark it free or give it free levels
                                    if (blnFree)
                                    {
                                        objPower.Free = true;
                                    }
                                    else
                                    {
                                        objPower.FreeLevels += intLevels;
                                        if (objPower.Rating < objPower.FreeLevels)
                                            objPower.Rating = objPower.FreeLevels;
                                    }
                                }
                                else
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Adding Power " + strPowerName);
                                    // If no, add the power and mark it free or give it free levels
                                    objPower = new Power(_objCharacter);
                                    _objCharacter.Powers.Add(objPower);

                                    // Get the Power information
                                    XmlDocument objXmlDocument = new XmlDocument();
                                    objXmlDocument = XmlManager.Instance.Load("powers.xml");
                                    XmlNode objXmlPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + strPowerName + "\"]");
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "objXmlPower = " + objXmlPower.OuterXml.ToString());

                                    bool blnLevels = false;
                                    if (objXmlPower["levels"] != null)
                                        blnLevels = (objXmlPower["levels"].InnerText == "yes");
                                    objPower.LevelsEnabled = blnLevels;
                                    objPower.Name = strPowerNameLimit;
                                    objPower.PointsPerLevel = Convert.ToDecimal(objXmlPower["points"].InnerText, GlobalOptions.Instance.CultureInfo);
                                    objPower.Source = objXmlPower["source"].InnerText;
                                    objPower.Page = objXmlPower["page"].InnerText;
                                    if (strSelection != string.Empty)
                                        objPower.Extra = strSelection;
                                    if (objXmlPower["doublecost"] != null)
                                        objPower.DoubleCost = false;

                                    if (blnFree)
                                    {
                                        objPower.Free = true;
                                    }
                                    else
                                    {
                                        objPower.FreeLevels += intLevels;
                                        if (objPower.Rating < intLevels)
                                            objPower.Rating = objPower.FreeLevels;
                                    }

                                    if (objXmlPower.InnerXml.Contains("bonus"))
                                    {
                                        objPower.Bonus = objXmlPower["bonus"];
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovements");
                                        if (!CreateImprovements(Improvement.ImprovementSource.Power, objPower.InternalId, objPower.Bonus, false, Convert.ToInt32(objPower.Rating), objPower.DisplayNameShort))
                                        {
                                            _objCharacter.Powers.Remove(objPower);
                                        }
                                    }
                                }
                                _strSelectedValue = "";
                                _strForcedValue = "";
                                strSelection = "";
                            }
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptPower, "");
                        }
                    }

                    // Select a Power.
                    if (NodeExists(nodBonus, "selectpower"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectpower");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);

                        bool blnExistingPower = false;
                        foreach (Power objExistingPower in _objCharacter.Powers)
                        {
                            if (objExistingPower.BonusSource == strSourceName)
                            {
                                blnExistingPower = true;
                                if (!objExistingPower.Free)
                                {
                                    if (objExistingPower.Name.StartsWith("Improved Reflexes"))
                                    {
                                        if (objExistingPower.Name.EndsWith("1"))
                                        {
                                            if (intRating >= 6)
                                                objExistingPower.FreePoints = 1.5M;
                                            else
                                                objExistingPower.FreePoints = 0;
                                        }
                                        else if (objExistingPower.Name.EndsWith("2"))
                                        {
                                            if (intRating >= 10)
                                                objExistingPower.FreePoints = 2.5M;
                                            else if (intRating >= 4)
                                                objExistingPower.FreePoints = 1.0M;
                                            else
                                                objExistingPower.FreePoints = 0;
                                        }
                                        else
                                        {
                                            if (intRating >= 14)
                                                objExistingPower.FreePoints = 3.5M;
                                            else if (intRating >= 8)
                                                objExistingPower.FreePoints = 2.0M;
                                            else if (intRating >= 4)
                                                objExistingPower.FreePoints = 1.0M;
                                            else
                                                objExistingPower.FreePoints = 0;
                                        }
                                    }
                                    else
                                    {
                                        // we have to adjust the number of free levels.
                                        decimal decLevels = Convert.ToDecimal(intRating) / 4;
                                        decLevels = Math.Floor(decLevels / objExistingPower.PointsPerLevel);
                                        objExistingPower.FreeLevels = Convert.ToInt32(decLevels);
                                        if (objExistingPower.Rating < intRating)
                                            objExistingPower.Rating = objExistingPower.FreeLevels;
                                        break;
                                    }
                                }
                            }
                        }

                        if (!blnExistingPower)
                        {
                            // Display the Select Skill window and record which Skill was selected.
                            frmSelectPower frmPickPower = new frmSelectPower(_objCharacter);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectpower = " + nodBonus.SelectSingleNode("selectpower").OuterXml.ToString());
                            frmPickPower.ShowDialog();

                            // Make sure the dialogue window was not canceled.
                            if (frmPickPower.DialogResult == DialogResult.Cancel)
                            {
                                Rollback();
                                blnSuccess = false;
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return false;
                            }

                            _strSelectedValue = frmPickPower.SelectedPower;
                            if (blnConcatSelectedValue)
                                strSourceName += " (" + _strSelectedValue + ")";

                            XmlDocument objXmlDocument = XmlManager.Instance.Load("powers.xml");
                            XmlNode objXmlPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + _strSelectedValue + "\"]");
                            string strSelection = "";

                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);

                            XmlNode objBonus = objXmlPower["bonus"];

                            string strPowerNameLimit = _strSelectedValue;
                            if (objBonus != null)
                            {
                                if (objBonus["selectlimit"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectlimit = " + objBonus["selectlimit"].OuterXml.ToString());
                                    _strForcedValue = "";
                                    // Display the Select Limit window and record which Limit was selected.
                                    frmSelectLimit frmPickLimit = new frmSelectLimit();
                                    if (strFriendlyName != "")
                                        frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimitNamed").Replace("{0}", strFriendlyName);
                                    else
                                        frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimit");

                                    if (objBonus["selectlimit"].InnerXml.Contains("<limit>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in objBonus["selectlimit"].SelectNodes("limit"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickLimit.LimitToList(strValue);
                                    }

                                    if (objBonus["selectlimit"].InnerXml.Contains("<excludelimit>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in objBonus["selectlimit"].SelectNodes("excludelimit"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickLimit.RemoveFromList(strValue);
                                    }

                                    // Check to see if there is only one possible selection because of _strLimitSelection.
                                    if (_strForcedValue != "")
                                        _strLimitSelection = _strForcedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strLimitSelection != "")
                                    {
                                        frmPickLimit.SingleLimit(_strLimitSelection);
                                        frmPickLimit.Opacity = 0;
                                    }

                                    frmPickLimit.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickLimit.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    _strSelectedValue = frmPickLimit.SelectedLimit;
                                    strSelection = _strSelectedValue;
                                    _strForcedValue = _strSelectedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objBonus["selectskill"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectskill = " + objBonus["selectskill"].OuterXml.ToString());
                                    XmlNode nodSkill = objBonus;
                                    // Display the Select Skill window and record which Skill was selected.
                                    frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                                    if (strFriendlyName != "")
                                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed").Replace("{0}", strFriendlyName);
                                    else
                                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

                                    if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillgroup"))
                                        frmPickSkill.OnlySkillGroup = nodSkill.SelectSingleNode("selectskill").Attributes["skillgroup"].InnerText;
                                    else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("skillcategory"))
                                        frmPickSkill.OnlyCategory = nodSkill.SelectSingleNode("selectskill").Attributes["skillcategory"].InnerText;
                                    else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("excludecategory"))
                                        frmPickSkill.ExcludeCategory = nodSkill.SelectSingleNode("selectskill").Attributes["excludecategory"].InnerText;
                                    else if (nodSkill.SelectSingleNode("selectskill").OuterXml.Contains("limittoskill"))
                                        frmPickSkill.LimitToSkill = nodSkill.SelectSingleNode("selectskill").Attributes["limittoskill"].InnerText;

                                    if (_strForcedValue.StartsWith("Adept:") || _strForcedValue.StartsWith("Magician:"))
                                        _strForcedValue = "";

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strForcedValue != "")
                                    {
                                        frmPickSkill.OnlySkill = _strForcedValue;
                                        frmPickSkill.Opacity = 0;
                                    }
                                    frmPickSkill.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickSkill.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    _strSelectedValue = frmPickSkill.SelectedSkill;
                                    _strForcedValue = _strSelectedValue;
                                    strSelection = _strSelectedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objBonus["selecttext"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selecttext = " + objBonus["selecttext"].OuterXml.ToString());
                                    frmSelectText frmPickText = new frmSelectText();
                                    frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strLimitSelection != "")
                                    {
                                        frmPickText.SelectedValue = _strLimitSelection;
                                        frmPickText.Opacity = 0;
                                    }

                                    frmPickText.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickText.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    strSelection = frmPickText.SelectedValue;
                                    _strLimitSelection = strSelection;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objBonus["specificattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificattribute = " + objBonus["specificattribute"].OuterXml.ToString());
                                    strSelection = objBonus["specificattribute"]["name"].InnerText.ToString();
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objBonus["selectattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectattribute = " + objBonus["selectattribute"].OuterXml.ToString());
                                    XmlNode nodSkill = objBonus;
                                    if (_strForcedValue.StartsWith("Adept"))
                                        _strForcedValue = "";

                                    // Display the Select Attribute window and record which Attribute was selected.
                                    frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                                    if (strFriendlyName != "")
                                        frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                                    else
                                        frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

                                    // Add MAG and/or RES to the list of Attributes if they are enabled on the form.
                                    if (_objCharacter.MAGEnabled)
                                        frmPickAttribute.AddMAG();
                                    if (_objCharacter.RESEnabled)
                                        frmPickAttribute.AddRES();

                                    if (nodSkill["selectattribute"].InnerXml.Contains("<attribute>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("attribute"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickAttribute.LimitToList(strValue);
                                    }

                                    if (nodSkill["selectattribute"].InnerXml.Contains("<excludeattribute>"))
                                    {
                                        List<string> strValue = new List<string>();
                                        foreach (XmlNode objXmlAttribute in nodSkill["selectattribute"].SelectNodes("excludeattribute"))
                                            strValue.Add(objXmlAttribute.InnerText);
                                        frmPickAttribute.RemoveFromList(strValue);
                                    }

                                    // Check to see if there is only one possible selection because of _strLimitSelection.
                                    if (_strForcedValue != "")
                                        _strLimitSelection = _strForcedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

                                    if (_strLimitSelection != "")
                                    {
                                        frmPickAttribute.SingleAttribute(_strLimitSelection);
                                        frmPickAttribute.Opacity = 0;
                                    }

                                    frmPickAttribute.ShowDialog();

                                    // Make sure the dialogue window was not canceled.
                                    if (frmPickAttribute.DialogResult == DialogResult.Cancel)
                                    {
                                        Rollback();
                                        blnSuccess = false;
                                        _strForcedValue = "";
                                        _strLimitSelection = "";
                                        return false;
                                    }

                                    _strSelectedValue = frmPickAttribute.SelectedAttribute;
                                    if (blnConcatSelectedValue)
                                        strSourceName += " (" + _strSelectedValue + ")";
                                    strSelection = _strSelectedValue;
                                    _strForcedValue = _strSelectedValue;

                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                                }
                            }

                            // If no, add the power and mark it free or give it free levels
                            Power objPower = new Power(_objCharacter);
                            bool blnHasPower = false;

                            foreach (Power power in _objCharacter.Powers)
                            {
                                if (power.Name == objXmlPower["name"].InnerText)
                                {
                                    if (power.Extra != "" && power.Extra == strSelection)
                                    {
                                        blnHasPower = true;
                                        objPower = power;
                                    }
                                    else if (power.Extra == "")
                                    {
                                        blnHasPower = true;
                                        objPower = power;
                                    }
                                }
                            }

                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "blnHasPower = " + blnHasPower);

                            if (blnHasPower)
                            {
                                // If yes, mark it free or give it free levels
                                if (objXmlPower["levels"].InnerText == "no")
                                {
                                    if (objPower.Name.StartsWith("Improved Reflexes"))
                                    {
                                        if (objPower.Name.EndsWith("1"))
                                        {
                                            if (intRating >= 6)
                                                objPower.FreePoints = 1.5M;
                                            else
                                                objPower.FreePoints = 0;
                                        }
                                        else if (objPower.Name.EndsWith("2"))
                                        {
                                            if (intRating >= 10)
                                                objPower.FreePoints = 2.5M;
                                            else if (intRating >= 4)
                                                objPower.FreePoints = 1.0M;
                                            else
                                                objPower.FreePoints = 0;
                                        }
                                        else
                                        {
                                            if (intRating >= 14)
                                                objPower.FreePoints = 3.5M;
                                            else if (intRating >= 8)
                                                objPower.FreePoints = 2.0M;
                                            else if (intRating >= 4)
                                                objPower.FreePoints = 1.0M;
                                            else
                                                objPower.FreePoints = 0;
                                        }
                                    }
                                    else
                                    {
                                        objPower.Free = true;
                                    }
                                }
                                else
                                {
                                    decimal decLevels = Convert.ToDecimal(intRating) / 4;
                                    decLevels = Math.Floor(decLevels / objPower.PointsPerLevel);
                                    objPower.FreeLevels += Convert.ToInt32(decLevels);
                                    objPower.Rating += Convert.ToInt32(decLevels);
                                }
                                objPower.BonusSource = strSourceName;
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Adding Power " + _strSelectedValue);
                                // Get the Power information
                                _objCharacter.Powers.Add(objPower);
                                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "objXmlPower = " + objXmlPower.OuterXml.ToString());

                                bool blnLevels = false;
                                if (objXmlPower["levels"] != null)
                                    blnLevels = (objXmlPower["levels"].InnerText == "yes");
                                objPower.LevelsEnabled = blnLevels;
                                objPower.Name = objXmlPower["name"].InnerText;
                                objPower.PointsPerLevel = Convert.ToDecimal(objXmlPower["points"].InnerText, GlobalOptions.Instance.CultureInfo);
                                objPower.Source = objXmlPower["source"].InnerText;
                                objPower.Page = objXmlPower["page"].InnerText;
                                objPower.BonusSource = strSourceName;
                                if (strSelection != string.Empty)
                                    objPower.Extra = strSelection;
                                if (objXmlPower["doublecost"] != null)
                                    objPower.DoubleCost = false;

                                if (objXmlPower["levels"].InnerText == "no")
                                {
                                    if (objPower.Name.StartsWith("Improved Reflexes"))
                                    {
                                        if (objPower.Name.EndsWith("1"))
                                        {
                                            if (intRating >= 6)
                                                objPower.FreePoints = 1.5M;
                                            else
                                                objPower.FreePoints = 0;
                                        }
                                        else if (objPower.Name.EndsWith("2"))
                                        {
                                            if (intRating >= 10)
                                                objPower.FreePoints = 2.5M;
                                            else if (intRating >= 4)
                                                objPower.FreePoints = 1.0M;
                                            else
                                                objPower.FreePoints = 0;
                                        }
                                        else
                                        {
                                            if (intRating >= 14)
                                                objPower.FreePoints = 3.5M;
                                            else if (intRating >= 8)
                                                objPower.FreePoints = 2.0M;
                                            else if (intRating >= 4)
                                                objPower.FreePoints = 1.0M;
                                            else
                                                objPower.FreePoints = 0;
                                        }
                                    }
                                    else
                                    {
                                    objPower.Free = true;
                                    }
                                }
                                else
                                {
                                    decimal decLevels = Convert.ToDecimal(intRating) / 4;
                                    decLevels = Math.Floor(decLevels / objPower.PointsPerLevel);
                                    objPower.FreeLevels += Convert.ToInt32(decLevels);
                                    if (objPower.Rating < intRating)
                                        objPower.Rating = objPower.FreeLevels;
                                }

                                if (objXmlPower.InnerXml.Contains("bonus"))
                                {
                                    objPower.Bonus = objXmlPower["bonus"];
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovements");
                                    if (!CreateImprovements(Improvement.ImprovementSource.Power, objPower.InternalId, objPower.Bonus, false, Convert.ToInt32(objPower.Rating), objPower.DisplayNameShort))
                                    {
                                        _objCharacter.Powers.Remove(objPower);
                                    }
                                }
                            }
                        }
                    }

                    // Check for Armor Encumbrance Penalty.
                    if (NodeExists(nodBonus, "armorencumbrancepenalty"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "armorencumbrancepenalty");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "armorencumbrancepenalty = " + nodBonus["armorencumbrancepenalty"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ArmorEncumbrancePenalty, "", ValueToInt(nodBonus["armorencumbrancepenalty"].InnerText, intRating));
                    }

                    // Check for Initiation.
                    if (NodeExists(nodBonus, "initiation"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiation");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiation = " + nodBonus["initiation"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiation, "", ValueToInt(nodBonus["initiation"].InnerText, intRating));
                        _objCharacter.InitiateGrade += ValueToInt(nodBonus["initiation"].InnerText, intRating);
                    }

                    // Check for Submersion.
                    if (NodeExists(nodBonus, "submersion"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "submersion");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "submersion = " + nodBonus["submersion"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Submersion, "", ValueToInt(nodBonus["submersion"].InnerText, intRating));
                        _objCharacter.SubmersionGrade += ValueToInt(nodBonus["submersion"].InnerText, intRating);
                    }

                    // Check for Skillwires.
                    if (NodeExists(nodBonus, "skillwire"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillwire");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillwire = " + nodBonus["skillwire"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Skillwire, "", ValueToInt(nodBonus["skillwire"].InnerText, intRating));
                    }

                    // Check for Damage Resistance.
                    if (NodeExists(nodBonus, "damageresistance"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "damageresistance");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "damageresistance = " + nodBonus["damageresistance"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DamageResistance, "damageresistance", ValueToInt(nodBonus["damageresistance"].InnerText, intRating));
                    }

                    // Check for Restricted Item Count.
                    if (NodeExists(nodBonus, "restricteditemcount"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "restricteditemcount");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "restricteditemcount = " + nodBonus["restricteditemcount"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.RestrictedItemCount, "", ValueToInt(nodBonus["restricteditemcount"].InnerText, intRating));
                    }

                    // Check for Judge Intentions.
                    if (NodeExists(nodBonus, "judgeintentions"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "judgeintentions");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "judgeintentions = " + nodBonus["judgeintentions"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.JudgeIntentions, "", ValueToInt(nodBonus["judgeintentions"].InnerText, intRating));
                    }

                    // Check for Composure.
                    if (NodeExists(nodBonus, "composure"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "composure");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "composure = " + nodBonus["composure"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Composure, "", ValueToInt(nodBonus["composure"].InnerText, intRating));
                    }

                    // Check for Lift and Carry.
                    if (NodeExists(nodBonus, "liftandcarry"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "liftandcarry");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "liftandcarry = " + nodBonus["liftandcarry"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LiftAndCarry, "", ValueToInt(nodBonus["liftandcarry"].InnerText, intRating));
                    }

                    // Check for Memory.
                    if (NodeExists(nodBonus, "memory"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "memory");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "memory = " + nodBonus["memory"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Memory, "", ValueToInt(nodBonus["memory"].InnerText, intRating));
                    }

                    // Check for Concealability.
                    if (NodeExists(nodBonus, "concealability"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "concealability");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "concealability = " + nodBonus["concealability"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Concealability, "", ValueToInt(nodBonus["concealability"].InnerText, intRating));
                    }

                    // Check for Drain Resistance.
                    if (NodeExists(nodBonus, "drainresist"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "drainresist");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "drainresist = " + nodBonus["drainresist"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DrainResistance, "", ValueToInt(nodBonus["drainresist"].InnerText, intRating));
                    }

                    // Check for Fading Resistance.
                    if (NodeExists(nodBonus, "fadingresist"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "fadingresist");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "fadingresist = " + nodBonus["fadingresist"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FadingResistance, "", ValueToInt(nodBonus["fadingresist"].InnerText, intRating));
                    }

                    // Check for Notoriety.
                    if (NodeExists(nodBonus, "notoriety"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "notoriety");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "notoriety = " + nodBonus["notoriety"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Notoriety, "", ValueToInt(nodBonus["notoriety"].InnerText, intRating));
                    }

                    // Check for Complex Form Limit.
                    if (NodeExists(nodBonus, "complexformlimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "complexformlimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "complexformlimit = " + nodBonus["complexformlimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ComplexFormLimit, "", ValueToInt(nodBonus["complexformlimit"].InnerText, intRating));
                    }

                    // Check for Spell Limit.
                    if (NodeExists(nodBonus, "spelllimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "spelllimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "spelllimit = " + nodBonus["spelllimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SpellLimit, "", ValueToInt(nodBonus["spelllimit"].InnerText, intRating));
                    }

                    // Check for Spell Category bonuses.
                    if (NodeExists(nodBonus, "spellcategory"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "spellcategory");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "spellcategory = " + nodBonus["spellcategory"].OuterXml.ToString());
                        XmlNodeList objXmlCategoryList = nodBonus.SelectNodes("spellcategory");

                        // Run through each of the Spell Categories since there may be more than one affected.
                        foreach (XmlNode nodSpellCategory in objXmlCategoryList)
                        {
                            string strUseUnique = strUnique;
                            if (nodSpellCategory["name"].Attributes["precedence"] != null)
                                strUseUnique = "precedence" + nodSpellCategory["name"].Attributes["precedence"].InnerText;

                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement(nodSpellCategory["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SpellCategory, strUseUnique, ValueToInt(nodSpellCategory["val"].InnerText, intRating));
                        }
                    }

                    // Check for Throwing Range bonuses.
                    if (NodeExists(nodBonus, "throwrange"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "throwrange");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "throwrange = " + nodBonus["throwrange"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowRange, strUnique, ValueToInt(nodBonus["throwrange"].InnerText, intRating));
                    }

                    // Check for Throwing STR bonuses.
                    if (NodeExists(nodBonus, "throwstr"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "throwstr");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "throwstr = " + nodBonus["throwstr"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowSTR, strUnique, ValueToInt(nodBonus["throwstr"].InnerText, intRating));
                    }

                    // Check for Skillsoft access.
                    if (NodeExists(nodBonus, "skillsoftaccess"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillsoftaccess");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillsoftaccess = " + nodBonus["skillsoftaccess"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SkillsoftAccess, "");
                    }

                    // Check for Quickening Metamagic.
                    if (NodeExists(nodBonus, "quickeningmetamagic"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "quickeningmetamagic");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "quickeningmetamagic = " + nodBonus["quickeningmetamagic"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.QuickeningMetamagic, "");
                    }

                    // Check for ignore Stun CM Penalty.
                    if (NodeExists(nodBonus, "ignorecmpenaltystun"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "ignorecmpenaltystun");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "ignorecmpenaltystun = " + nodBonus["ignorecmpenaltystun"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyStun, "");
                    }

                    // Check for ignore Physical CM Penalty.
                    if (NodeExists(nodBonus, "ignorecmpenaltyphysical"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "ignorecmpenaltyphysical");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "ignorecmpenaltyphysical = " + nodBonus["ignorecmpenaltyphysical"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyPhysical, "");
                    }

                    // Check for a Cyborg Essence which will permanently set the character's ESS to 0.1.
                    if (NodeExists(nodBonus, "cyborgessence"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "cyborgessence");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "cyborgessence = " + nodBonus["cyborgessence"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CyborgEssence, "");
                    }

                    // Check for Maximum Essence which will permanently modify the character's Maximum Essence value.
                    if (NodeExists(nodBonus, "essencemax"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "essencemax");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "essencemax = " + nodBonus["essencemax"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EssenceMax, "", ValueToInt(nodBonus["essencemax"].InnerText, intRating));
                    }

                    // Check for Select Sprite.
                    if (NodeExists(nodBonus, "selectsprite"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectsprite");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectsprite = " + nodBonus["selectsprite"].OuterXml.ToString());
                        XmlDocument objXmlDocument = XmlManager.Instance.Load("critters.xml");
                        XmlNodeList objXmlNodeList = objXmlDocument.SelectNodes("/chummer/metatypes/metatype[contains(category, \"Sprites\")]");
                        List<ListItem> lstCritters = new List<ListItem>();
                        foreach (XmlNode objXmlNode in objXmlNodeList)
                        {
                            ListItem objItem = new ListItem();
                            if (objXmlNode["translate"] != null)
                                objItem.Name = objXmlNode["translate"].InnerText;
                            else
                                objItem.Name = objXmlNode["name"].InnerText;
                            objItem.Value = objItem.Name;
                            lstCritters.Add(objItem);
                        }

                        frmSelectItem frmPickItem = new frmSelectItem();
                        frmPickItem.GeneralItems = lstCritters;
                        frmPickItem.ShowDialog();

                        if (frmPickItem.DialogResult == DialogResult.Cancel)
                        {
                            Rollback();
                            blnSuccess = false;
                            _strForcedValue = "";
                            _strLimitSelection = "";
                            return blnSuccess;
                        }

                        _strSelectedValue = frmPickItem.SelectedItem;

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName, Improvement.ImprovementType.AddSprite, "");
                    }

                    // Check for Black Market Discount.
                    if (NodeExists(nodBonus, "blackmarketdiscount"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "blackmarketdiscount");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "blackmarketdiscount = " + nodBonus["blackmarketdiscount"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BlackMarketDiscount, strUnique);
                        _objCharacter.BlackMarket = true;
                    }

                    // Select Weapon (custom entry for things like Spare Clip).
                    if (NodeExists(nodBonus, "selectweapon"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectweapon");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectweapon = " + nodBonus["selectweapon"].OuterXml.ToString());
                        string strSelectedValue = "";
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

                        if (_objCharacter == null)
                        {
                            // If the character is null (this is a Vehicle), the user must enter their own string.
                            // Display the Select Item window and record the value that was entered.
                            frmSelectText frmPickText = new frmSelectText();
                            frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);

                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);

                            if (_strLimitSelection != "")
                            {
                                frmPickText.SelectedValue = _strLimitSelection;
                                frmPickText.Opacity = 0;
                            }

                            frmPickText.ShowDialog();

                            // Make sure the dialogue window was not canceled.
                            if (frmPickText.DialogResult == DialogResult.Cancel)
                            {
                                Rollback();
                                blnSuccess = false;
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return false;
                            }

                            _strSelectedValue = frmPickText.SelectedValue;
                            if (blnConcatSelectedValue)
                                strSourceName += " (" + _strSelectedValue + ")";

                            strSelectedValue = frmPickText.SelectedValue;
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelectedValue = " + strSelectedValue);
                        }
                        else
                        {
                            List<ListItem> lstWeapons = new List<ListItem>();
                            foreach (Weapon objWeapon in _objCharacter.Weapons)
                            {
                                ListItem objItem = new ListItem();
                                objItem.Value = objWeapon.Name;
                                objItem.Name = objWeapon.DisplayName;
                                lstWeapons.Add(objItem);
                            }

                            frmSelectItem frmPickItem = new frmSelectItem();
                            frmPickItem.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);
                            frmPickItem.GeneralItems = lstWeapons;

                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);

                            if (_strLimitSelection != "")
                            {
                                frmPickItem.ForceItem = _strLimitSelection;
                                frmPickItem.Opacity = 0;
                            }

                            frmPickItem.ShowDialog();

                            // Make sure the dialogue window was not canceled.
                            if (frmPickItem.DialogResult == DialogResult.Cancel)
                            {
                                Rollback();
                                blnSuccess = false;
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return false;
                            }

                            _strSelectedValue = frmPickItem.SelectedItem;
                            if (blnConcatSelectedValue)
                                strSourceName += " (" + _strSelectedValue + ")";

                            strSelectedValue = frmPickItem.SelectedItem;
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelectedValue = " + strSelectedValue);
                        }

                        // Create the Improvement.
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique);
                    }
                }

                // If we've made it this far, everything went OK, so commit the Improvements.
                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling Commit");
                Commit();
                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Returned from Commit");
                // Clear the Forced Value and Limit Selection strings once we're done to prevent these from forcing their values on other Improvements.
                _strForcedValue = "";
                _strLimitSelection = "";
            }
            catch (Exception ex)
            {
                objFunctions.LogWrite(CommonFunctions.LogType.Error, "Chummer.ImprovementManager", "ERROR Message = " + ex.Message);
                objFunctions.LogWrite(CommonFunctions.LogType.Error, "Chummer.ImprovementManager", "ERROR Source  = " + ex.Source);
                objFunctions.LogWrite(CommonFunctions.LogType.Error, "Chummer.ImprovementManager", "ERROR Trace   = " + ex.StackTrace.ToString());
                MessageBox.Show("If you're seeing this, an error just occurred that couldn't be handled. If you have the debug log turned on, please email chummerlog.txt (zipped please) to [email protected]. If you don't have the debug log turned on, please turn it on in the Options dialog and try to repeat what you did so the error can be captured. Thank you.");
                Rollback();
                blnSuccess = false;
            }
            objFunctions.LogWrite(CommonFunctions.LogType.Exiting, "Chummer.ImprovementManager", "CreateImprovements");
            return blnSuccess;
        }