Exemple #1
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 = "", bool blnConditional = false)
        {
            if (nodBonus == null)
            {
                _strForcedValue = "";
                _strLimitSelection = "";
                return true;
            }

            if (blnConditional)
            {
                _objCharacter.ImprovementGroups.Add(strSourceName);
            }

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

            bool blnSuccess = true;
            _strSelectedValue = "";

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

            if (nodBonus.HasChildNodes)
            {
                // Select Text (custom entry for things like Allergy).
                if (NodeExists(nodBonus, "selecttext"))
                {
                    if (_strForcedValue != "")
                        _strLimitSelection = _strForcedValue;

                    // 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 = "";
                        return false;
                    }

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

                    // Create the Improvement.
                    CreateImprovement(frmPickText.SelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique, blnConditional);
                }
            }

            // If there is no character object, don't attempt to add any Improvements.
            if (_objCharacter == null)
                return true;

            // Check to see what bonuses the node grants.
            if (nodBonus.HasChildNodes)
            {
                // Add an Attribute.
                if (NodeExists(nodBonus, "addattribute"))
                {
                    if (nodBonus["addattribute"]["name"].InnerText == "MAG")
                    {
                        _objCharacter.MAGEnabled = true;
                        CreateImprovement("MAG", objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, "enableattribute", blnConditional, 0, 0);
                        if (nodBonus["addattribute"]["min"] != null)
                            _objCharacter.MAG.MetatypeMinimum = Convert.ToInt32(nodBonus["addattribute"]["min"].InnerText);
                        if (nodBonus["addattribute"]["max"] != null)
                            _objCharacter.MAG.MetatypeMaximum = Convert.ToInt32(nodBonus["addattribute"]["max"].InnerText);
                        if (nodBonus["addattribute"]["aug"] != null)
                            _objCharacter.MAG.MetatypeAugmentedMaximum = Convert.ToInt32(nodBonus["addattribute"]["aug"].InnerText);
                        if (nodBonus["addattribute"]["val"] != null)
                            _objCharacter.MAG.Value = Convert.ToInt32(nodBonus["addattribute"]["val"].InnerText);
                    }
                    else if (nodBonus["addattribute"]["name"].InnerText == "RES")
                    {
                        _objCharacter.RESEnabled = true;
                        CreateImprovement("RES", objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, "enableattribute", blnConditional, 0, 0);
                        if (nodBonus["addattribute"]["min"] != null)
                            _objCharacter.RES.MetatypeMinimum = Convert.ToInt32(nodBonus["addattribute"]["min"].InnerText);
                        if (nodBonus["addattribute"]["max"] != null)
                            _objCharacter.RES.MetatypeMaximum = Convert.ToInt32(nodBonus["addattribute"]["max"].InnerText);
                        if (nodBonus["addattribute"]["aug"] != null)
                            _objCharacter.RES.MetatypeAugmentedMaximum = Convert.ToInt32(nodBonus["addattribute"]["aug"].InnerText);
                        if (nodBonus["addattribute"]["val"] != null)
                            _objCharacter.RES.Value = Convert.ToInt32(nodBonus["addattribute"]["val"].InnerText);
                    }
                }

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

                // Select Restricted (select Restricted items for Fake Licenses).
                if (NodeExists(nodBonus, "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 + ")";

                    // Create the Improvement.
                    CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName, Improvement.ImprovementType.Restricted, strUnique, blnConditional);
                }

                // Select a Skill.
                if (NodeExists(nodBonus, "selectskill"))
                {
                    // 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 (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 + ")";

                    // 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["selectskill"]["val"] != null)
                                    CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, blnConditional, ValueToInt(nodBonus["selectskill"]["val"].InnerText, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);

                                if (nodBonus["selectskill"]["max"] != null)
                                    CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, blnConditional, 0, 1, 0, ValueToInt(nodBonus["selectskill"]["max"].InnerText, intRating), 0, 0, "", blnAddToRating);

                                if (nodBonus["selectskill"]["weapondv"] != null)
                                    CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.WeaponSkillDV, strUnique, blnConditional, ValueToInt(nodBonus["selectskill"]["weapondv"].InnerText, intRating));

                                if (nodBonus["selectskill"]["accuracy"] != null)
                                    CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.WeaponSkillAccuracy, strUnique, blnConditional, ValueToInt(nodBonus["selectskill"]["accuracy"].InnerText, intRating));
                            }
                        }
                        else
                        {
                            if (objSkill.Name == frmPickSkill.SelectedSkill)
                            {
                                // We've found the selected Skill.
                                if (nodBonus["selectskill"]["val"] != null)
                                    CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, blnConditional, ValueToInt(nodBonus["selectskill"]["val"].InnerText, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);

                                if (nodBonus["selectskill"]["max"] != null)
                                    CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, blnConditional, 0, 1, 0, ValueToInt(nodBonus["selectskill"]["max"].InnerText, intRating), 0, 0, "", blnAddToRating);

                                if (nodBonus["selectskill"]["weapondv"] != null)
                                    CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.WeaponSkillDV, strUnique, blnConditional, ValueToInt(nodBonus["selectskill"]["weapondv"].InnerText, intRating));

                                if (nodBonus["selectskill"]["accuracy"] != null)
                                    CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.WeaponSkillAccuracy, strUnique, blnConditional, ValueToInt(nodBonus["selectskill"]["accuracy"].InnerText, intRating));
                            }
                        }
                    }
                }

                // Select a Skill Group.
                if (NodeExists(nodBonus, "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");

                    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;

                    CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, blnConditional, ValueToInt(nodBonus["selectskillgroup"]["bonus"].InnerText, intRating), 1, 0, 0, 0, 0, strExclude, blnAddToRating);
                }

                // Select an Attribute.
                if (NodeExists(nodBonus, "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();

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

                    if (nodBonus["selectattribute"]["excludeattribute"] != null)
                    {
                        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;

                    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 + ")";

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

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

                    string strAttribute = frmPickAttribute.SelectedAttribute;

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

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

                // Select an Attribute.
                if (NodeExists(nodBonus, "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);

                    if (nodBonus["swapskillattribute"]["attribute"] != null)
                    {
                        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;

                    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 + ")";

                    CreateImprovement(frmPickAttribute.SelectedAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.SwapSkillAttribute, strUnique, blnConditional);
                }

                // Select a Spell.
                if (NodeExists(nodBonus, "selectspell"))
                {
                    // Display the Select Spell window.
                    frmSelectSpell frmPickSpell = new frmSelectSpell(_objCharacter);

                    if (nodBonus["selectspell"].Attributes["category"] != null)
                        frmPickSpell.LimitCategory = nodBonus["selectspell"].Attributes["category"].InnerText;
                    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 + ")";

                    CreateImprovement(frmPickSpell.SelectedSpell, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique, blnConditional);
                }

                // Affect a Specific Attribute.
                if (NodeExists(nodBonus, "specificattribute"))
                {
                    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["min"] != null)
                                intMin = ValueToInt(objXmlAttribute["min"].InnerXml, intRating);
                            if (objXmlAttribute["val"] != null)
                                intAug = ValueToInt(objXmlAttribute["val"].InnerXml, intRating);
                            if (objXmlAttribute["max"] != null)
                            {
                                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["aug"] != null)
                                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";

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

                // Change the maximum number of BP that can be spent on Nuyen.
                if (NodeExists(nodBonus, "nuyenmaxbp"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.NuyenMaxBP, "", blnConditional, ValueToInt(nodBonus["nuyenmaxbp"].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"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Nuyen, strUnique, blnConditional, ValueToInt(nodBonus["nuyenamt"].InnerText, intRating));
                }

                // Improve Condition Monitors.
                if (NodeExists(nodBonus, "conditionmonitor"))
                {
                    // Physical Condition.
                    if (nodBonus["conditionmonitor"]["physical"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalCM, strUnique, blnConditional, ValueToInt(nodBonus["conditionmonitor"]["physical"].InnerText, intRating));

                    // Stun Condition.
                    if (nodBonus["conditionmonitor"]["stun"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.StunCM, strUnique, blnConditional, ValueToInt(nodBonus["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;

                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThreshold, strUseUnique, blnConditional, 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;

                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThresholdOffset, strUseUnique, blnConditional, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["thresholdoffset"].InnerText, intRating));
                    }

                    // Condition Monitor Overflow.
                    if (nodBonus["conditionmonitor"]["overflow"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMOverflow, strUnique, blnConditional, ValueToInt(nodBonus["conditionmonitor"]["overflow"].InnerText, intRating));
                }

                // Improve Living Personal Attributes.
                if (NodeExists(nodBonus, "livingpersona"))
                {
                    // Response.
                    if (nodBonus["livingpersona"]["response"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaResponse, strUnique, blnConditional, ValueToInt(nodBonus["livingpersona"]["response"].InnerText, intRating));

                    // Signal.
                    if (nodBonus["livingpersona"]["signal"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSignal, strUnique, blnConditional, ValueToInt(nodBonus["livingpersona"]["signal"].InnerText, intRating));

                    // Firewall.
                    if (nodBonus["livingpersona"]["firewall"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaFirewall, strUnique, blnConditional, ValueToInt(nodBonus["livingpersona"]["firewall"].InnerText, intRating));

                    // System.
                    if (nodBonus["livingpersona"]["system"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSystem, strUnique, blnConditional, ValueToInt(nodBonus["livingpersona"]["system"].InnerText, intRating));

                    // Biofeedback Filter.
                    if (nodBonus["livingpersona"]["biofeedback"] != null)
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaBiofeedback, strUnique, blnConditional, ValueToInt(nodBonus["livingpersona"]["biofeedback"].InnerText, intRating));
                }

                // The Improvement adjusts a specific Skill.
                if (NodeExists(nodBonus, "specificskill"))
                {
                    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)
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUseUnique, blnConditional, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                        if (objXmlSkill["max"] != null)
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUseUnique, blnConditional, 0, 1, 0, ValueToInt(objXmlSkill["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                    }
                }

                // The Improvement adjusts a Skill Category.
                if (NodeExists(nodBonus, "skillcategory"))
                {
                    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["exclude"] != null)
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillCategory, strUnique, blnConditional, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                        else
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillCategory, strUnique, blnConditional, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                    }
                }

                // The Improvement adjusts a Skill Group.
                if (NodeExists(nodBonus, "skillgroup"))
                {
                    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["exclude"] != null)
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, blnConditional, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                        else
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, blnConditional, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                    }
                }

                // The Improvement adjust Skills with the given Attribute.
                if (NodeExists(nodBonus, "skillattribute"))
                {
                    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["exclude"] != null)
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillAttribute, strUseUnique, blnConditional, ValueToInt(objXmlSkill["value"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                        else
                            CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillAttribute, strUseUnique, blnConditional, ValueToInt(objXmlSkill["value"].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"))
                {
                    XmlNode objXmlSkill = nodBonus.SelectSingleNode("skillarticulation");
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EnhancedArticulation, strUnique, blnConditional, ValueToInt(objXmlSkill["bonus"].InnerText, intRating));
                }

                // Check for Armor modifiers.
                if (NodeExists(nodBonus, "armorvalue"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ArmorValue, strUnique, blnConditional, ValueToInt(nodBonus["armorvalue"].InnerText, intRating));
                }

                // Check for Reach modifiers.
                if (NodeExists(nodBonus, "reach"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Reach, strUnique, blnConditional, ValueToInt(nodBonus["reach"].InnerText, intRating));
                }

                // Check for Unarmed Damage Value modifiers.
                if (NodeExists(nodBonus, "unarmeddv"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDV, strUnique, blnConditional, ValueToInt(nodBonus["unarmeddv"].InnerText, intRating));
                }

                // Check for Unarmed Damage Value Physical.
                if (NodeExists(nodBonus, "unarmeddvphysical"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDVPhysical, "", blnConditional);
                }

                // Check for Unarmed Armor Penetration.
                if (NodeExists(nodBonus, "unarmedap"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedAP, strUnique, blnConditional, ValueToInt(nodBonus["unarmedap"].InnerText, intRating));
                }

                // Check for Initiative modifiers.
                if (NodeExists(nodBonus, "initiative"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiative, strUnique, blnConditional, ValueToInt(nodBonus["initiative"].InnerText, intRating));
                }

                // Check for Initiative Dice modifiers.
                if (NodeExists(nodBonus, "initiativedice"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.InitiativeDice, strUnique, blnConditional, ValueToInt(nodBonus["initiativedice"].InnerText, intRating));
                }

                // Check for Matrix Initiative modifiers.
                if (NodeExists(nodBonus, "matrixinitiative"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiative, strUnique, blnConditional, ValueToInt(nodBonus["matrixinitiative"].InnerText, intRating));
                }

                // Check for Matrix Initiative Pass modifiers.
                if (NodeExists(nodBonus, "matrixinitiativepass"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass, "matrixinitiativepass", blnConditional, ValueToInt(nodBonus["matrixinitiativepass"].InnerText, intRating));
                }

                // Check for Matrix Initiative Pass modifiers.
                if (NodeExists(nodBonus, "matrixinitiativepassadd"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass, strUnique, blnConditional, ValueToInt(nodBonus["matrixinitiativepassadd"].InnerText, intRating));
                }

                // Check for Lifestyle cost modifiers.
                if (NodeExists(nodBonus, "lifestylecost"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LifestyleCost, strUnique, blnConditional, ValueToInt(nodBonus["lifestylecost"].InnerText, intRating));
                }

                // Check for basic Lifestyle cost modifiers.
                if (NodeExists(nodBonus, "basiclifestylecost"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicLifestyleCost, strUnique, blnConditional, ValueToInt(nodBonus["basiclifestylecost"].InnerText, intRating));
                }

                // Check for Genetech Cost modifiers.
                if (NodeExists(nodBonus, "genetechcostmultiplier"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.GenetechCostMultiplier, strUnique, blnConditional, ValueToInt(nodBonus["genetechcostmultiplier"].InnerText, intRating));
                }

                // Check for Genetech: Transgenics Cost modifiers.
                if (NodeExists(nodBonus, "transgenicsgenetechcost"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.TransgenicsBiowareCost, strUnique, blnConditional, ValueToInt(nodBonus["transgenicsgenetechcost"].InnerText, intRating));
                }

                // Check for Basic Bioware Essence Cost modifiers.
                if (NodeExists(nodBonus, "basicbiowareessmultiplier"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicBiowareEssCost, strUnique, blnConditional, ValueToInt(nodBonus["basicbiowareessmultiplier"].InnerText, intRating));
                }

                // Check for Bioware Essence Cost modifiers.
                if (NodeExists(nodBonus, "biowareessmultiplier"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BiowareEssCost, strUnique, blnConditional, ValueToInt(nodBonus["biowareessmultiplier"].InnerText, intRating));
                }

                // Check for Cybeware Essence Cost modifiers.
                if (NodeExists(nodBonus, "cyberwareessmultiplier"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CyberwareEssCost, strUnique, blnConditional, ValueToInt(nodBonus["cyberwareessmultiplier"].InnerText, intRating));
                }

                // Check for Uneducated modifiers.
                if (NodeExists(nodBonus, "uneducated"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uneducated, strUnique, blnConditional);
                    _objCharacter.Uneducated = true;
                }

                // Check for Uncouth modifiers.
                if (NodeExists(nodBonus, "uncouth"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uncouth, strUnique, blnConditional);
                    _objCharacter.Uncouth = true;
                }

                // Check for Infirm modifiers.
                if (NodeExists(nodBonus, "infirm"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Infirm, strUnique, blnConditional);
                    _objCharacter.Infirm = true;
                }

                // Check for Adept Linguistics.
                if (NodeExists(nodBonus, "adeptlinguistics"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptLinguistics, strUnique, blnConditional, 1);
                }

                // Check for Weapon Category DV modifiers.
                if (NodeExists(nodBonus, "weaponcategorydv"))
                {
                    XmlNodeList objXmlCategoryList = nodBonus.SelectNodes("weaponcategorydv");
                    // Run through each of the Skill Groups since there may be more than one affected.
                    foreach (XmlNode objXmlCategory in objXmlCategoryList)
                        CreateImprovement(objXmlCategory["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.WeaponCategoryDV, strUnique, blnConditional, ValueToInt(objXmlCategory["bonus"].InnerXml, intRating));
                }

                // Check for Mentor Spirit bonuses.
                if (NodeExists(nodBonus, "selectmentorspirit"))
                {
                    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 + ")";

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

                    if (frmPickMentorSpirit.BonusNode2 != null)
                    {
                        blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.BonusNode2, 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 Paragon bonuses.
                if (NodeExists(nodBonus, "selectparagon"))
                {
                    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"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Smartlink, "smartlink", blnConditional);
                }

                // Check for Adapsin bonus.
                if (NodeExists(nodBonus, "adapsin"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Adapsin, "adapsin", blnConditional);
                }

                // Check for SoftWeave bonus.
                if (NodeExists(nodBonus, "softweave"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SoftWeave, "softweave", blnConditional);
                }

                // Check for Sensitive System.
                if (NodeExists(nodBonus, "sensitivesystem"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SensitiveSystem, "sensitivesystem", blnConditional);
                    _objCharacter.SensitiveSystem = true;
                }

                // Check for Movement Percent.
                if (NodeExists(nodBonus, "movementpercent"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MovementPercent, "", blnConditional, ValueToInt(nodBonus["movementpercent"].InnerText, intRating));
                }

                // Check for Swim Percent.
                if (NodeExists(nodBonus, "swimpercent"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SwimPercent, "", blnConditional, ValueToInt(nodBonus["swimpercent"].InnerText, intRating));
                }

                // Check for Fly Percent.
                if (NodeExists(nodBonus, "flypercent"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlyPercent, "", blnConditional, ValueToInt(nodBonus["flypercent"].InnerText, intRating));
                }

                // Check for Fly Speed.
                if (NodeExists(nodBonus, "flyspeed"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlySpeed, "", blnConditional, ValueToInt(nodBonus["flyspeed"].InnerText, intRating));
                }

                // Check for free Positive Qualities.
                if (NodeExists(nodBonus, "freepositivequalities"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreePositiveQualities, "", blnConditional, ValueToInt(nodBonus["freepositivequalities"].InnerText, intRating));
                }

                // Check for free Negative Qualities.
                if (NodeExists(nodBonus, "freenegativequalities"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeNegativeQualities, "", blnConditional, ValueToInt(nodBonus["freenegativequalities"].InnerText, intRating));
                }

                // Check for Select Side.
                if (NodeExists(nodBonus, "selectside"))
                {
                    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;
                }

                // Check for Free Spirit Power Points.
                if (NodeExists(nodBonus, "freespiritpowerpoints"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeSpiritPowerPoints, "", blnConditional, ValueToInt(nodBonus["freespiritpowerpoints"].InnerText, intRating));
                }

                // Check for Adept Power Points.
                if (NodeExists(nodBonus, "adeptpowerpoints"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptPowerPoints, "", blnConditional, ValueToInt(nodBonus["adeptpowerpoints"].InnerText, intRating));
                }

                // Check for Armor Encumbrance Penalty.
                if (NodeExists(nodBonus, "armorencumbrancepenalty"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ArmorEncumbrancePenalty, "", blnConditional, ValueToInt(nodBonus["armorencumbrancepenalty"].InnerText, intRating));
                }

                // Check for Initiation.
                if (NodeExists(nodBonus, "initiation"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiation, "", blnConditional, ValueToInt(nodBonus["initiation"].InnerText, intRating));
                    _objCharacter.InitiateGrade += ValueToInt(nodBonus["initiation"].InnerText, intRating);
                }

                // Check for Submersion.
                if (NodeExists(nodBonus, "submersion"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Submersion, "", blnConditional, ValueToInt(nodBonus["submersion"].InnerText, intRating));
                    _objCharacter.SubmersionGrade += ValueToInt(nodBonus["submersion"].InnerText, intRating);
                }

                // Check for Skillwires.
                if (NodeExists(nodBonus, "skillwire"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Skillwire, "", blnConditional, ValueToInt(nodBonus["skillwire"].InnerText, intRating));
                }

                // Check for Damage Resistance.
                if (NodeExists(nodBonus, "damageresistance"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DamageResistance, "damageresistance", blnConditional, ValueToInt(nodBonus["damageresistance"].InnerText, intRating));
                }

                // Check for Restricted Item Count.
                if (NodeExists(nodBonus, "restricteditemcount"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.RestrictedItemCount, "", blnConditional, ValueToInt(nodBonus["restricteditemcount"].InnerText, intRating));
                }

                // Check for Judge Intentions.
                if (NodeExists(nodBonus, "judgeintentions"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.JudgeIntentions, "", blnConditional, ValueToInt(nodBonus["judgeintentions"].InnerText, intRating));
                }

                // Check for Select Inherent Limit.
                if (NodeExists(nodBonus, "selectinherentlimit"))
                {
                    frmSelectItem frmPickItem = new frmSelectItem();
                    frmPickItem.ManualMode = "InherentLimits";
                    frmPickItem.Description = LanguageManager.Instance.GetString("String_SelectInherentLimit");
                    frmPickItem.ShowDialog();

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

                    _strSelectedValue = frmPickItem.SelectedItem;

                    Improvement.ImprovementType objImprovementType = new Improvement.ImprovementType();
                    switch (frmPickItem.SelectedItem)
                    {
                        case "mentallimit":
                            objImprovementType = Improvement.ImprovementType.MentalLimit;
                            break;
                        case "physicallimit":
                            objImprovementType = Improvement.ImprovementType.PhysicalLimit;
                            break;
                        case "sociallimit":
                            objImprovementType = Improvement.ImprovementType.SocialLimit;
                            break;
                    }
                    CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName, Improvement.ImprovementType.AddSprite, "", blnConditional);
                    CreateImprovement("", objImprovementSource, strSourceName, objImprovementType, "", blnConditional, ValueToInt(nodBonus["selectinherentlimit"]["value"].InnerText, intRating));
                }

                // Check for Mental Limit.
                if (NodeExists(nodBonus, "mentallimit"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MentalLimit, "", blnConditional, ValueToInt(nodBonus["mentallimit"].InnerText, intRating));
                }

                // Check for Physical Limit.
                if (NodeExists(nodBonus, "physicallimit"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalLimit, "", blnConditional, ValueToInt(nodBonus["physicallimit"].InnerText, intRating));
                }

                // Check for Social Limit.
                if (NodeExists(nodBonus, "sociallimit"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SocialLimit, "", blnConditional, ValueToInt(nodBonus["sociallimit"].InnerText, intRating));
                }

                // Check for Surprise.
                if (NodeExists(nodBonus, "surprise"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Surprise, "", blnConditional, ValueToInt(nodBonus["surprise"].InnerText, intRating));
                }

                // Check for Composure.
                if (NodeExists(nodBonus, "composure"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Composure, "", blnConditional, ValueToInt(nodBonus["composure"].InnerText, intRating));
                }

                // Check for Lift and Carry.
                if (NodeExists(nodBonus, "liftandcarry"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LiftAndCarry, "", blnConditional, ValueToInt(nodBonus["liftandcarry"].InnerText, intRating));
                }

                // Check for Memory.
                if (NodeExists(nodBonus, "memory"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Memory, "", blnConditional, ValueToInt(nodBonus["memory"].InnerText, intRating));
                }

                // Check for Concealability.
                if (NodeExists(nodBonus, "concealability"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Concealability, "", blnConditional, ValueToInt(nodBonus["concealability"].InnerText, intRating));
                }

                // Check for Drain Resistance.
                if (NodeExists(nodBonus, "drainresist"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DrainResistance, "", blnConditional, ValueToInt(nodBonus["drainresist"].InnerText, intRating));
                }

                // Check for Fading Resistance.
                if (NodeExists(nodBonus, "fadingresist"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FadingResistance, "", blnConditional, ValueToInt(nodBonus["fadingresist"].InnerText, intRating));
                }

                // Check for Notoriety.
                if (NodeExists(nodBonus, "notoriety"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Notoriety, "", blnConditional, ValueToInt(nodBonus["notoriety"].InnerText, intRating));
                }

                // Check for Complex Form Limit.
                if (NodeExists(nodBonus, "complexformlimit"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ComplexFormLimit, "", blnConditional, ValueToInt(nodBonus["complexformlimit"].InnerText, intRating));
                }

                // Check for Spell Limit.
                if (NodeExists(nodBonus, "spelllimit"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SpellLimit, "", blnConditional, ValueToInt(nodBonus["spelllimit"].InnerText, intRating));
                }

                // Check for Spell Category bonuses.
                if (NodeExists(nodBonus, "spellcategory"))
                {
                    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;

                        CreateImprovement(nodSpellCategory["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SpellCategory, strUseUnique, blnConditional, ValueToInt(nodSpellCategory["val"].InnerText, intRating));
                    }
                }

                // Check for Throwing Range bonuses.
                if (NodeExists(nodBonus, "throwrange"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowRange, strUnique, blnConditional, ValueToInt(nodBonus["throwrange"].InnerText, intRating));
                }

                // Check for Throwing STR bonuses.
                if (NodeExists(nodBonus, "throwstr"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowSTR, strUnique, blnConditional, ValueToInt(nodBonus["throwstr"].InnerText, intRating));
                }

                // Check for Accuracy bonuses.
                if (NodeExists(nodBonus, "accuracy"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Accuracy, strUnique, blnConditional, ValueToInt(nodBonus["accuracy"].InnerText, intRating));
                }

                // Check for Skillsoft access.
                if (NodeExists(nodBonus, "skillsoftaccess"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SkillsoftAccess, "", blnConditional);
                }

                if (NodeExists(nodBonus, "knowsoftaccess"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.KnowsoftAccess, "", blnConditional);
                }

                // Check for Quickening Metamagic.
                if (NodeExists(nodBonus, "quickeningmetamagic"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.QuickeningMetamagic, "", blnConditional);
                }

                // Check for ignore Stun CM Penalty.
                if (NodeExists(nodBonus, "ignorecmpenaltystun"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyStun, "", blnConditional);
                }

                // Check for ignore Physical CM Penalty.
                if (NodeExists(nodBonus, "ignorecmpenaltyphysical"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyPhysical, "", blnConditional);
                }

                // Check for Maximum Essence which will permanently modify the character's Maximum Essence value.
                if (NodeExists(nodBonus, "essencemax"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EssenceMax, "", blnConditional, ValueToInt(nodBonus["essencemax"].InnerText, intRating));
                }

                // Check for Select Sprite.
                if (NodeExists(nodBonus, "selectsprite"))
                {
                    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;

                    CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName, Improvement.ImprovementType.AddSprite, "", blnConditional);
                }

                // Check for Black Market Discount.
                if (NodeExists(nodBonus, "blackmarketdiscount"))
                {
                    CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BlackMarketDiscount, strUnique, blnConditional);
                    _objCharacter.BlackMarket = true;
                }

                // Select Weapon (custom entry for things like Spare Clip).
                if (NodeExists(nodBonus, "selectweapon"))
                {
                    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);

                        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;
                    }
                    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;

                        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;
                    }

                    // Create the Improvement.
                    CreateImprovement(strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique, blnConditional);
                }
            }

            // If we've made it this far, everything went OK, so commit the Improvements.
            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 = "";
            return blnSuccess;
        }
Exemple #2
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;
        }
        /// <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;
        }