public frmSelectLimitModifier(LimitModifier objLimitModifier = null, params string[] lstLimits)
        {
            InitializeComponent();
            this.TranslateWinForm();

            // Build the list of Limits.
            List <ListItem> lstLimitItems = new List <ListItem>();

            foreach (string strLimit in lstLimits)
            {
                lstLimitItems.Add(new ListItem(strLimit, LanguageManager.GetString("String_Limit" + strLimit + "Short")));
            }

            cboLimit.BeginUpdate();
            cboLimit.ValueMember   = nameof(ListItem.Value);
            cboLimit.DisplayMember = nameof(ListItem.Name);
            cboLimit.DataSource    = lstLimitItems;
            if (lstLimitItems.Count >= 1)
            {
                cboLimit.SelectedIndex = 0;
            }
            else
            {
                cmdOK.Enabled = false;
            }
            cboLimit.EndUpdate();

            if (objLimitModifier != null)
            {
                cboLimit.SelectedValue = objLimitModifier.Limit;
                txtName.Text           = objLimitModifier.Name;
                _intBonus         = objLimitModifier.Bonus;
                txtCondition.Text = objLimitModifier.Condition;
            }
        }
Esempio n. 2
0
 public SelectLimitModifier(LimitModifier objLimitModifier = null, params string[] lstLimits)
 {
     _objLimitModifier = objLimitModifier;
     _lstLimits        = lstLimits;
     InitializeComponent();
     this.UpdateLightDarkMode();
     this.TranslateWinForm();
 }
 public frmSelectLimitModifier(LimitModifier objLimitModifier = null)
 {
     InitializeComponent();
     LanguageManager.TranslateWinForm(GlobalOptions.Language, this);
     if (objLimitModifier != null)
     {
         txtName.Text      = objLimitModifier.Name;
         _intBonus         = objLimitModifier.Bonus;
         txtCondition.Text = objLimitModifier.Condition;
     }
 }
 public frmSelectLimitModifier(LimitModifier objLimitModifier = null)
 {
     InitializeComponent();
     LanguageManager.Instance.Load(GlobalOptions.Instance.Language, this);
     if (objLimitModifier != null)
     {
         txtName.Text = objLimitModifier.Name;
         _intBonus = objLimitModifier.Bonus;
         txtCondition.Text = objLimitModifier.Condition;
     }
 }
        public static void Add(this TreeView treView, LimitModifier input, ContextMenuStrip strip)
        {
            if (treView == null)
            {
                return;
            }
            TreeNode nodeToAddTo = treView.Nodes[(int)Enum.Parse(typeof(LimitType), input.Limit)];

            if (!nodeToAddTo.Nodes.ContainsKey(input.DisplayName))
            {
                nodeToAddTo.Nodes.Add(input.CreateTreeNode(strip));
                nodeToAddTo.Expand();
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Edit and update a Limit Modifier.
        /// </summary>
        /// <param name="treLimit"></param>
        /// <param name="cmsLimitModifier"></param>
        protected void UpdateLimitModifier(TreeView treLimit, ContextMenuStrip cmsLimitModifier)
        {
            TreeNode      objSelectedNode  = treLimit.SelectedNode;
            LimitModifier objLimitModifier = CommonFunctions.FindByIdWithNameCheck(treLimit.SelectedNode.Tag.ToString(),
                                                                                   _objCharacter.LimitModifiers);

            //If the LimitModifier couldn't be found (Ie it comes from an Improvement or the user hasn't properly selected a treenode, fail out early.
            if (objLimitModifier == null)
            {
                MessageBox.Show(LanguageManager.GetString("Warning_NoLimitFound"));
                return;
            }
            frmSelectLimitModifier frmPickLimitModifier = new frmSelectLimitModifier(objLimitModifier);

            frmPickLimitModifier.ShowDialog(this);

            if (frmPickLimitModifier.DialogResult == DialogResult.Cancel)
            {
                return;
            }

            //Remove the old LimitModifier to ensure we don't double up.
            _objCharacter.LimitModifiers.Remove(objLimitModifier);
            // Create the new limit modifier.
            TreeNode objNode = new TreeNode();

            objLimitModifier = new LimitModifier(_objCharacter);
            string strLimit     = treLimit.SelectedNode.Parent.Text;
            string strCondition = frmPickLimitModifier.SelectedCondition;

            objLimitModifier.Create(frmPickLimitModifier.SelectedName, frmPickLimitModifier.SelectedBonus, strLimit,
                                    strCondition, objNode);
            objLimitModifier.Guid = new Guid(objSelectedNode.Tag.ToString());
            if (objLimitModifier.InternalId == Guid.Empty.ToString())
            {
                return;
            }

            _objCharacter.LimitModifiers.Add(objLimitModifier);

            //Add the new treeview node for the LimitModifier.
            objNode.ContextMenuStrip = cmsLimitModifier;
            objNode.Text             = objLimitModifier.DisplayName;
            objNode.Tag = objLimitModifier.InternalId;
            objSelectedNode.Parent.Nodes.Add(objNode);
            objSelectedNode.Remove();
        }
Esempio n. 7
0
        public static void Add(this TreeView treView, LimitModifier input, ContextMenuStrip strip)
        {
            if (treView == null)
            {
                return;
            }
            TreeNode nodeToAddTo = treView.Nodes[(int)Enum.Parse(typeof(LimitType), input.Limit)];

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

                nodeToAddTo.Nodes.Add(newNode);
                nodeToAddTo.Expand();
            }
        }
Esempio n. 8
0
        public SelectLimitModifier(LimitModifier objLimitModifier = null, params string[] lstLimits)
        {
            InitializeComponent();
            this.UpdateLightDarkMode();
            this.TranslateWinForm();

            // Build the list of Limits.
            using (new FetchSafelyFromPool <List <ListItem> >(Utils.ListItemListPool, out List <ListItem> lstLimitItems))
            {
                foreach (string strLimit in lstLimits)
                {
                    lstLimitItems.Add(
                        new ListItem(strLimit, LanguageManager.GetString("String_Limit" + strLimit + "Short")));
                }

                cboLimit.BeginUpdate();
                cboLimit.PopulateWithListItems(lstLimitItems);
                if (lstLimitItems.Count >= 1)
                {
                    cboLimit.SelectedIndex = 0;
                }
                else
                {
                    cmdOK.Enabled = false;
                }
                cboLimit.EndUpdate();
            }

            if (objLimitModifier != null)
            {
                cboLimit.SelectedValue = objLimitModifier.Limit;
                txtName.Text           = objLimitModifier.Name;
                _intBonus         = objLimitModifier.Bonus;
                txtCondition.Text = objLimitModifier.Condition;
            }
        }
Esempio n. 9
0
        private void cmdAddLimitModifier_Click(object sender, EventArgs e)
        {
            try
            {
                // Select the Limit node if we're currently on a child.
                if (treLimit.SelectedNode.Level > 1)
                    treLimit.SelectedNode = treLimit.SelectedNode.Parent;

                frmSelectLimitModifier frmPickLimitModifier = new frmSelectLimitModifier();
                frmPickLimitModifier.ShowDialog(this);

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

                // Create the new limit modifier.
                TreeNode objNode = new TreeNode();
                LimitModifier objLimitModifier = new LimitModifier(_objCharacter);
                string strLimit = treLimit.SelectedNode.Text;
                string strCondition = frmPickLimitModifier.SelectedCondition;
                objLimitModifier.Create(frmPickLimitModifier.SelectedName, frmPickLimitModifier.SelectedBonus, strLimit, strCondition, _objCharacter, objNode);
                if (objLimitModifier.InternalId == Guid.Empty.ToString())
                    return;

                objNode.ContextMenuStrip = cmsLimitModifier;
                _objCharacter.LimitModifiers.Add(objLimitModifier);

                treLimit.SelectedNode.Nodes.Add(objNode);
                treLimit.SelectedNode.Expand();

                _blnIsDirty = true;
                UpdateWindowTitle();
            }
            catch
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_SelectLimitModifier"), LanguageManager.Instance.GetString("MessageTitle_SelectLimitModifier"), MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Load the Character from an XML file.
        /// </summary>
        public bool Load()
        {
            XmlDocument objXmlDocument = new XmlDocument();
            objXmlDocument.Load(_strFileName);

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

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

            ResetCharacter();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return true;
        }
Esempio n. 11
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;
        }
Esempio n. 12
0
        /// <summary>
        /// Edit and update a Limit Modifier.
        /// </summary>
        /// <param name="treLimit"></param>
        /// <param name="cmsLimitModifier"></param>
        protected void UpdateLimitModifier(TreeView treLimit, ContextMenuStrip cmsLimitModifier)
        {
            TreeNode objSelectedNode = treLimit.SelectedNode;
            LimitModifier objLimitModifier = _objFunctions.FindLimitModifier(treLimit.SelectedNode.Tag.ToString(),
                _objCharacter.LimitModifiers);
            //If the LimitModifier couldn't be found (Ie it comes from an Improvement or the user hasn't properly selected a treenode, fail out early.
            if (objLimitModifier == null)
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Warning_NoLimitFound"));
                return;
            }
            frmSelectLimitModifier frmPickLimitModifier = new frmSelectLimitModifier(objLimitModifier);
            frmPickLimitModifier.ShowDialog(this);

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

            //Remove the old LimitModifier to ensure we don't double up.
            _objCharacter.LimitModifiers.Remove(objLimitModifier);
            // Create the new limit modifier.
            TreeNode objNode = new TreeNode();
            objLimitModifier = new LimitModifier(_objCharacter);
            string strLimit = treLimit.SelectedNode.Parent.Text;
            string strCondition = frmPickLimitModifier.SelectedCondition;
            objLimitModifier.Create(frmPickLimitModifier.SelectedName, frmPickLimitModifier.SelectedBonus, strLimit,
                strCondition, _objCharacter, objNode);
            objLimitModifier.Guid = new Guid(objSelectedNode.Tag.ToString());
            if (objLimitModifier.InternalId == Guid.Empty.ToString())
                return;

            _objCharacter.LimitModifiers.Add(objLimitModifier);

            //Add the new treeview node for the LimitModifier.
            objNode.ContextMenuStrip = cmsLimitModifier;
            objNode.Text = objLimitModifier.DisplayName;
            objNode.Tag = objLimitModifier.InternalId;
            objSelectedNode.Parent.Nodes.Add(objNode);
            objSelectedNode.Remove();
        }
Esempio n. 13
0
        /// <summary>
        /// Create all of the Improvements for an XML Node.
        /// </summary>
        /// <param name="objImprovementSource">Type of object that grants these Improvements.</param>
        /// <param name="strSourceName">Name of the item that grants these Improvements.</param>
        /// <param name="nodBonus">bonus XMLXode from the source data file.</param>
        /// <param name="blnConcatSelectedValue">Whether or not any selected values should be concatinated with the SourceName string when storing.</param>
        /// <param name="intRating">Selected Rating value that is used to replace the Rating string in an Improvement.</param>
        /// <param name="strFriendlyName">Friendly name to show in any dialogue windows that ask for a value.</param>
        public bool CreateImprovements(Improvement.ImprovementSource objImprovementSource, string strSourceName, XmlNode nodBonus, bool blnConcatSelectedValue = false, int intRating = 1, string strFriendlyName = "", object fCreate = null)
        {
            objFunctions.LogWrite(CommonFunctions.LogType.Entering, "Chummer.ImprovementManager", "CreateImprovements");
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "objImprovementSource = " + objImprovementSource.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSourceName = " + strSourceName);
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "nodBonus = " + nodBonus.OuterXml.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "blnConcatSelectedValue = " + blnConcatSelectedValue.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "intRating = " + intRating.ToString());
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strFriendlyName = " + strFriendlyName);
            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "intRating = " + intRating.ToString());

            bool blnSuccess = true;

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

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

                _strSelectedValue = "";

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

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

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

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

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

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

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

                        frmPickText.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        // Find the selected Skill.
                        foreach (Skill objSkill in _objCharacter.Skills)
                        {
                            if (frmPickSkill.SelectedSkill.Contains("Exotic Melee Weapon") || frmPickSkill.SelectedSkill.Contains("Exotic Ranged Weapon") || frmPickSkill.SelectedSkill.Contains("Pilot Exotic Vehicle"))
                            {
                                if (objSkill.Name + " (" + objSkill.Specialization + ")" == frmPickSkill.SelectedSkill)
                                {
                                    // We've found the selected Skill.
                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("val"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, ValueToInt(nodBonus["selectskill"]["val"].InnerText, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                                    }

                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("max"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name + " (" + objSkill.Specialization + ")", objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, 0, 1, 0, ValueToInt(nodBonus["selectskill"]["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                                    }
                                }
                            }
                            else
                            {
                                if (objSkill.Name == frmPickSkill.SelectedSkill)
                                {
                                    // We've found the selected Skill.
                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("val"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, ValueToInt(nodBonus["selectskill"]["val"].InnerText, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                                    }

                                    if (nodBonus.SelectSingleNode("selectskill").InnerXml.Contains("max"))
                                    {
                                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                        CreateImprovement(objSkill.Name, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUnique, 0, 1, 0, ValueToInt(nodBonus["selectskill"]["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                                    }
                                }
                            }
                        }
                    }

                    // Select a Skill Group.
                    if (NodeExists(nodBonus, "selectskillgroup"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectskillgroup");
                        string strExclude = "";
                        if (nodBonus["selectskillgroup"].Attributes["excludecategory"] != null)
                            strExclude = nodBonus["selectskillgroup"].Attributes["excludecategory"].InnerText;

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

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

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

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

                        frmPickSkillGroup.ShowDialog();

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

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

                        _strSelectedValue = frmPickSkillGroup.SelectedSkillGroup;

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

                        if (nodBonus["selectskillgroup"].SelectSingleNode("bonus") != null)
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(nodBonus["selectskillgroup"]["bonus"].InnerText, intRating), 1, 0, 0, 0, 0, strExclude, blnAddToRating);
                        }
                        else
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement(_strSelectedValue, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(nodBonus["selectskillgroup"]["max"].InnerText, intRating), 0, 0, 1, 0, 0, strExclude, blnAddToRating);
                        }
                    }

                    // Select an Attribute.
                    if (NodeExists(nodBonus, "selectattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectattribute");
                        // Display the Select Attribute window and record which Skill was selected.
                        frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                        if (strFriendlyName != "")
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

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

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectattribute = " + nodBonus["selectattribute"].OuterXml.ToString());

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

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

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

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

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

                        frmPickAttribute.ShowDialog();

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

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

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

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

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

                        string strAttribute = frmPickAttribute.SelectedAttribute;

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

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(strAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, strUnique, 0, 1, intMin, intMax, intAug, intAugMax);
                    }

                    // Select a Limit.
                    if (NodeExists(nodBonus, "selectlimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectlimit");
                        // Display the Select Limit window and record which Limit was selected.
                        frmSelectLimit frmPickLimit = new frmSelectLimit();
                        if (strFriendlyName != "")
                            frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimitNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickLimit.Description = LanguageManager.Instance.GetString("String_Improvement_SelectLimit");

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectlimit = " + nodBonus["selectlimit"].OuterXml.ToString());

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

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

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

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

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

                        frmPickLimit.ShowDialog();

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

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

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

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

                        string strLimit = frmPickLimit.SelectedLimit;

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

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

                        LimitModifier objLimitMod = new LimitModifier(_objCharacter);
                        // string strBonus = nodBonus["limitmodifier"]["value"].InnerText;
                        int intBonus = intAug;
                        string strName = strFriendlyName;
                        TreeNode nodTemp = new TreeNode();

                        Improvement.ImprovementType objType = Improvement.ImprovementType.PhysicalLimit;
                        if (strLimit == "Mental")
                            objType = Improvement.ImprovementType.MentalLimit;
                        else if (strLimit == "Social")
                            objType = Improvement.ImprovementType.SocialLimit;

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(strLimit, objImprovementSource, strSourceName, objType, strFriendlyName, intBonus, 0, intMin, intMax, intAug, intAugMax);
                    }

                    // Select an Attribute.
                    if (NodeExists(nodBonus, "swapskillattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "swapskillattribute");
                        // Display the Select Attribute window and record which Skill was selected.
                        frmSelectAttribute frmPickAttribute = new frmSelectAttribute();
                        if (strFriendlyName != "")
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttributeNamed").Replace("{0}", strFriendlyName);
                        else
                            frmPickAttribute.Description = LanguageManager.Instance.GetString("String_Improvement_SelectAttribute");

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

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "swapskillattribute = " + nodBonus["swapskillattribute"].OuterXml.ToString());

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

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

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

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

                        frmPickAttribute.ShowDialog();

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

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

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

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickAttribute.SelectedAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.SwapSkillAttribute, strUnique);
                    }

                    // Select a Spell.
                    if (NodeExists(nodBonus, "selectspell"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectspell");
                        // Display the Select Spell window.
                        frmSelectSpell frmPickSpell = new frmSelectSpell(_objCharacter);

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

                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectspell = " + nodBonus["selectspell"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strLimitSelection = " + _strLimitSelection);

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

                        frmPickSpell.ShowDialog();

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

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

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

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickSpell.SelectedSpell, objImprovementSource, strSourceName, Improvement.ImprovementType.Text, strUnique);
                    }

                    // Affect a Specific Attribute.
                    if (NodeExists(nodBonus, "specificattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "specificattribute");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificattribute = " + nodBonus["specificattribute"].OuterXml.ToString());
                        XmlNodeList objXmlAttributeList = nodBonus.SelectNodes("specificattribute");
                        foreach (XmlNode objXmlAttribute in objXmlAttributeList)
                        {
                            if (objXmlAttribute["name"].InnerText != "ESS")
                            {
                                // Display the Select Attribute window and record which Attribute was selected.
                                // Record the improvement.
                                int intMin = 0;
                                int intAug = 0;
                                int intMax = 0;
                                int intAugMax = 0;

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

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

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

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

                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(strAttribute, objImprovementSource, strSourceName, Improvement.ImprovementType.Attribute, strUseUnique, 0, 1, intMin, intMax, intAug, intAugMax);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Essence, "", Convert.ToInt32(objXmlAttribute["val"].InnerText));
                            }
                        }
                    }

                    // Change the maximum number of BP that can be spent on Nuyen.
                    if (NodeExists(nodBonus, "nuyenmaxbp"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "nuyenmaxbp");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "nuyenmaxbp = " + nodBonus["nuyenmaxbp"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.NuyenMaxBP, "", ValueToInt(nodBonus["nuyenmaxbp"].InnerText, intRating));
                    }

                    // Apply a bonus/penalty to physical limit.
                    if (NodeExists(nodBonus, "physicallimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "physicallimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "physicallimit = " + nodBonus["physicallimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalLimit, "", ValueToInt(nodBonus["physicallimit"].InnerText, intRating));
                    }

                    // Apply a bonus/penalty to mental limit.
                    if (NodeExists(nodBonus, "mentallimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "mentallimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "mentallimit = " + nodBonus["mentallimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MentalLimit, "", ValueToInt(nodBonus["mentallimit"].InnerText, intRating));
                    }

                    // Apply a bonus/penalty to social limit.
                    if (NodeExists(nodBonus, "sociallimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "sociallimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "sociallimit = " + nodBonus["sociallimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SocialLimit, "", ValueToInt(nodBonus["sociallimit"].InnerText, intRating));
                    }

                    // Change the amount of Nuyen the character has at creation time (this can put the character over the amount they're normally allowed).
                    if (NodeExists(nodBonus, "nuyenamt"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "nuyenamt");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "nuyenamt = " + nodBonus["nuyenamt"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Nuyen, strUnique, ValueToInt(nodBonus["nuyenamt"].InnerText, intRating));
                    }

                    // Improve Condition Monitors.
                    if (NodeExists(nodBonus, "conditionmonitor"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "conditionmonitor");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "conditionmonitor = " + nodBonus["conditionmonitor"].OuterXml.ToString());
                        // Physical Condition.
                        if (nodBonus.SelectSingleNode("conditionmonitor").InnerXml.Contains("physical"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Physical");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.PhysicalCM, strUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["physical"].InnerText, intRating));
                        }

                        // Stun Condition.
                        if (nodBonus.SelectSingleNode("conditionmonitor").InnerXml.Contains("stun"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Stun");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.StunCM, strUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["stun"].InnerText, intRating));
                        }

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

                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Threshold");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThreshold, strUseUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["threshold"].InnerText, intRating));
                        }

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

                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Threshold Offset");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMThresholdOffset, strUseUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["thresholdoffset"].InnerText, intRating));
                        }

                        // Condition Monitor Overflow.
                        if (nodBonus.SelectSingleNode("conditionmonitor").InnerXml.Contains("overflow"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for Overflow");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CMOverflow, strUnique, ValueToInt(nodBonus.SelectSingleNode("conditionmonitor")["overflow"].InnerText, intRating));
                        }
                    }

                    // Improve Living Personal Attributes.
                    if (NodeExists(nodBonus, "livingpersona"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "livingpersona");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "livingpersona = " + nodBonus["livingpersona"].OuterXml.ToString());
                        // Response.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("response"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for response");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaResponse, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["response"].InnerText, intRating));
                        }

                        // Signal.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("signal"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for signal");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSignal, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["signal"].InnerText, intRating));
                        }

                        // Firewall.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("firewall"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for firewall");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaFirewall, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["firewall"].InnerText, intRating));
                        }

                        // System.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("system"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for system");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaSystem, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["system"].InnerText, intRating));
                        }

                        // Biofeedback Filter.
                        if (nodBonus.SelectSingleNode("livingpersona").InnerXml.Contains("biofeedback"))
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for biofeedback");
                            CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LivingPersonaBiofeedback, strUnique, ValueToInt(nodBonus.SelectSingleNode("livingpersona")["biofeedback"].InnerText, intRating));
                        }
                    }

                    // The Improvement adjusts a specific Skill.
                    if (NodeExists(nodBonus, "specificskill"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "specificskill");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificskill = " + nodBonus["specificskill"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("specificskill");
                        // Run through each specific Skill since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }

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

                            // Record the improvement.
                            if (objXmlSkill["bonus"] != null)
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for bonus");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUseUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                            if (objXmlSkill["max"] != null)
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement for max");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.Skill, strUseUnique, 0, 1, 0, ValueToInt(objXmlSkill["max"].InnerText, intRating), 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement adds a martial art
                    if (NodeExists(nodBonus, "martialart"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "martialart");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "martialart = " + nodBonus["martialart"].OuterXml.ToString());
                        XmlDocument _objXmlDocument = XmlManager.Instance.Load("martialarts.xml");
                        XmlNode objXmlArt = _objXmlDocument.SelectSingleNode("/chummer/martialarts/martialart[name = \"" + nodBonus["martialart"].InnerText + "\"]");

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

                    // The Improvement adds a limit modifier
                    if (NodeExists(nodBonus, "limitmodifier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "limitmodifier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "limitmodifier = " + nodBonus["limitmodifier"].OuterXml.ToString());
                        LimitModifier objLimitMod = new LimitModifier(_objCharacter);
                        string strLimit = nodBonus["limitmodifier"]["limit"].InnerText;
                        string strBonus = nodBonus["limitmodifier"]["value"].InnerText;
                        string strCondition = "";
                        try
                        {
                            strCondition = nodBonus["limitmodifier"]["condition"].InnerText;
                        }
                        catch { }
                        int intBonus = 0;
                        if (strBonus == "Rating")
                            intBonus = intRating;
                        else
                            intBonus = Convert.ToInt32(strBonus);
                        string strName = strFriendlyName;
                        TreeNode nodTemp = new TreeNode();
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(strLimit, objImprovementSource, strSourceName, Improvement.ImprovementType.LimitModifier, strFriendlyName, intBonus, 0, 0, 0, 0, 0, strCondition);

                    }

                    // The Improvement adjusts a Skill Category.
                    if (NodeExists(nodBonus, "skillcategory"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillcategory");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillcategory = " + nodBonus["skillcategory"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("skillcategory");
                        // Run through each of the Skill Categories since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }
                            if (objXmlSkill.InnerXml.Contains("exclude"))
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement - exclude");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillCategory, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillCategory, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement adjusts a Skill Group.
                    if (NodeExists(nodBonus, "skillgroup"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillgroup");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillgroup = " + nodBonus["skillgroup"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("skillgroup");
                        // Run through each of the Skill Groups since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }
                            if (objXmlSkill.InnerXml.Contains("exclude"))
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement - exclude");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillGroup, strUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement adjust Skills with the given Attribute.
                    if (NodeExists(nodBonus, "skillattribute"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillattribute");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillattribute = " + nodBonus["skillattribute"].OuterXml.ToString());
                        XmlNodeList objXmlSkillList = nodBonus.SelectNodes("skillattribute");
                        // Run through each of the Skill Attributes since there may be more than one affected.
                        foreach (XmlNode objXmlSkill in objXmlSkillList)
                        {
                            string strUseUnique = strUnique;
                            if (objXmlSkill["name"].Attributes["precedence"] != null)
                                strUseUnique = "precedence" + objXmlSkill["name"].Attributes["precedence"].InnerText;

                            bool blnAddToRating = false;
                            if (objXmlSkill["applytorating"] != null)
                            {
                                if (objXmlSkill["applytorating"].InnerText == "yes")
                                    blnAddToRating = true;
                            }
                            if (objXmlSkill.InnerXml.Contains("exclude"))
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement - exclude");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillAttribute, strUseUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, objXmlSkill["exclude"].InnerText, blnAddToRating);
                            }
                            else
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                                CreateImprovement(objXmlSkill["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SkillAttribute, strUseUnique, ValueToInt(objXmlSkill["bonus"].InnerXml, intRating), 1, 0, 0, 0, 0, "", blnAddToRating);
                            }
                        }
                    }

                    // The Improvement comes from Enhanced Articulation (improves Physical Active Skills linked to a Physical Attribute).
                    if (NodeExists(nodBonus, "skillarticulation"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillarticulation");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillarticulation = " + nodBonus["skillarticulation"].OuterXml.ToString());
                        XmlNode objXmlSkill = nodBonus.SelectSingleNode("skillarticulation");
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EnhancedArticulation, strUnique, ValueToInt(objXmlSkill["bonus"].InnerText, intRating));
                    }

                    // Check for Armor modifiers.
                    if (NodeExists(nodBonus, "armor"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "armor");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "armor = " + nodBonus["armor"].OuterXml.ToString());
                        XmlNode objXmlArmor = nodBonus.SelectSingleNode("armor");
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Armor, strUnique, ValueToInt(objXmlArmor.InnerText, intRating));
                    }

                    // Check for Reach modifiers.
                    if (NodeExists(nodBonus, "reach"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "reach");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "reach = " + nodBonus["reach"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Reach, strUnique, ValueToInt(nodBonus["reach"].InnerText, intRating));
                    }

                    // Check for Unarmed Damage Value modifiers.
                    if (NodeExists(nodBonus, "unarmeddv"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "unarmeddv");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "unarmeddv = " + nodBonus["unarmeddv"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDV, strUnique, ValueToInt(nodBonus["unarmeddv"].InnerText, intRating));
                    }

                    // Check for Unarmed Damage Value Physical.
                    if (NodeExists(nodBonus, "unarmeddvphysical"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "unarmeddvphysical");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "unarmeddvphysical = " + nodBonus["unarmeddvphysical"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedDVPhysical, "");
                    }

                    // Check for Unarmed Armor Penetration.
                    if (NodeExists(nodBonus, "unarmedap"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "unarmedap");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "unarmedap = " + nodBonus["unarmedap"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.UnarmedAP, strUnique, ValueToInt(nodBonus["unarmedap"].InnerText, intRating));
                    }

                    // Check for Initiative modifiers.
                    if (NodeExists(nodBonus, "initiative"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiative");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiative = " + nodBonus["initiative"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiative, strUnique, ValueToInt(nodBonus["initiative"].InnerText, intRating));
                    }

                    // Check for Initiative Pass modifiers. Only the highest one ever applies.
                    if (NodeExists(nodBonus, "initiativepass"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiativepass");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiativepass = "******"initiativepass"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.InitiativePass, "initiativepass", ValueToInt(nodBonus["initiativepass"].InnerText, intRating));
                    }

                    // Check for Initiative Pass modifiers. Only the highest one ever applies.
                    if (NodeExists(nodBonus, "initiativepassadd"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiativepassadd");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiativepassadd = " + nodBonus["initiativepassadd"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.InitiativePassAdd, strUnique, ValueToInt(nodBonus["initiativepassadd"].InnerText, intRating));
                    }

                    // Check for Matrix Initiative modifiers.
                    if (NodeExists(nodBonus, "matrixinitiative"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "matrixinitiative");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "matrixinitiative = " + nodBonus["matrixinitiative"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiative, strUnique, ValueToInt(nodBonus["matrixinitiative"].InnerText, intRating));
                    }

                    // Check for Matrix Initiative Pass modifiers.
                    if (NodeExists(nodBonus, "matrixinitiativepass"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "matrixinitiativepass");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "matrixinitiativepass = "******"matrixinitiativepass"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass, "matrixinitiativepass", ValueToInt(nodBonus["matrixinitiativepass"].InnerText, intRating));
                    }

                    // Check for Matrix Initiative Pass modifiers.
                    if (NodeExists(nodBonus, "matrixinitiativepassadd"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "matrixinitiativepassadd");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "matrixinitiativepassadd = " + nodBonus["matrixinitiativepassadd"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MatrixInitiativePass, strUnique, ValueToInt(nodBonus["matrixinitiativepassadd"].InnerText, intRating));
                    }

                    // Check for Lifestyle cost modifiers.
                    if (NodeExists(nodBonus, "lifestylecost"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "lifestylecost");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "lifestylecost = " + nodBonus["lifestylecost"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LifestyleCost, strUnique, ValueToInt(nodBonus["lifestylecost"].InnerText, intRating));
                    }

                    // Check for basic Lifestyle cost modifiers.
                    if (NodeExists(nodBonus, "basiclifestylecost"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "basiclifestylecost");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "basiclifestylecost = " + nodBonus["basiclifestylecost"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicLifestyleCost, strUnique, ValueToInt(nodBonus["basiclifestylecost"].InnerText, intRating));
                    }

                    // Check for Genetech Cost modifiers.
                    if (NodeExists(nodBonus, "genetechcostmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "genetechcostmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "genetechcostmultiplier = " + nodBonus["genetechcostmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.GenetechCostMultiplier, strUnique, ValueToInt(nodBonus["genetechcostmultiplier"].InnerText, intRating));
                    }

                    // Check for Genetech: Transgenics Cost modifiers.
                    if (NodeExists(nodBonus, "transgenicsgenetechcost"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "transgenicsgenetechcost");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "transgenicsgenetechcost = " + nodBonus["transgenicsgenetechcost"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.TransgenicsBiowareCost, strUnique, ValueToInt(nodBonus["transgenicsgenetechcost"].InnerText, intRating));
                    }

                    // Check for Basic Bioware Essence Cost modifiers.
                    if (NodeExists(nodBonus, "basicbiowareessmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "basicbiowareessmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "basicbiowareessmultiplier = " + nodBonus["basicbiowareessmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BasicBiowareEssCost, strUnique, ValueToInt(nodBonus["basicbiowareessmultiplier"].InnerText, intRating));
                    }

                    // Check for Bioware Essence Cost modifiers.
                    if (NodeExists(nodBonus, "biowareessmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "biowareessmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "biowareessmultiplier = " + nodBonus["biowareessmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BiowareEssCost, strUnique, ValueToInt(nodBonus["biowareessmultiplier"].InnerText, intRating));
                    }

                    // Check for Cybeware Essence Cost modifiers.
                    if (NodeExists(nodBonus, "cyberwareessmultiplier"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "cyberwareessmultiplier");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "cyberwareessmultiplier = " + nodBonus["cyberwareessmultiplier"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CyberwareEssCost, strUnique, ValueToInt(nodBonus["cyberwareessmultiplier"].InnerText, intRating));
                    }

                    // Check for Uneducated modifiers.
                    if (NodeExists(nodBonus, "uneducated"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "uneducated");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "uneducated = " + nodBonus["uneducated"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uneducated, strUnique);
                        _objCharacter.Uneducated = true;
                    }

                    // Check for Uncouth modifiers.
                    if (NodeExists(nodBonus, "uncouth"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "uncouth");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "uncouth = " + nodBonus["uncouth"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Uncouth, strUnique);
                        _objCharacter.Uncouth = true;
                    }

                    // Check for Infirm modifiers.
                    if (NodeExists(nodBonus, "infirm"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "infirm");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "infirm = " + nodBonus["infirm"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Infirm, strUnique);
                        _objCharacter.Infirm = true;
                    }

                    // Check for Adept Linguistics.
                    if (NodeExists(nodBonus, "adeptlinguistics"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "adeptlinguistics");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "adeptlinguistics = " + nodBonus["adeptlinguistics"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptLinguistics, strUnique, 1);
                    }

                    // Check for Weapon Category DV modifiers.
                    if (NodeExists(nodBonus, "weaponcategorydv"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "weaponcategorydv");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "weaponcategorydv = " + nodBonus["weaponcategorydv"].OuterXml.ToString());
                        XmlNodeList objXmlCategoryList = nodBonus.SelectNodes("weaponcategorydv");
                        XmlNode nodWeapon = nodBonus["weaponcategorydv"];

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

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

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

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

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

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

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

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

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

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

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

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

                            string strSelected = frmPickCategory.SelectedItem;

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

                            foreach (Power objPower in _objCharacter.Powers)
                            {
                                if (objPower.InternalId == strSourceName)
                                {
                                    objPower.Name = objPower.Name + " (" + strSelected + ")";
                                }
                            }

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

                    // Check for Mentor Spirit bonuses.
                    if (NodeExists(nodBonus, "selectmentorspirit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectmentorspirit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectmentorspirit = " + nodBonus["selectmentorspirit"].OuterXml.ToString());
                        frmSelectMentorSpirit frmPickMentorSpirit = new frmSelectMentorSpirit(_objCharacter);
                        frmPickMentorSpirit.ShowDialog();

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

                        _strSelectedValue = frmPickMentorSpirit.SelectedMentor;

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

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

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

                        if (frmPickMentorSpirit.Choice1BonusNode != null)
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "frmPickMentorSpirit.Choice1BonusNode = " + frmPickMentorSpirit.Choice1BonusNode.OuterXml.ToString());
                            string strForce = _strForcedValue;
                            if (!frmPickMentorSpirit.Choice1.StartsWith("Adept:") && !frmPickMentorSpirit.Choice1.StartsWith("Magician:"))
                                _strForcedValue = frmPickMentorSpirit.Choice1;
                            else
                                _strForcedValue = "";
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice1BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                            _strForcedValue = strForce;
                            _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice1;
                        }

                        if (frmPickMentorSpirit.Choice2BonusNode != null)
                        {
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "frmPickMentorSpirit.Choice2BonusNode = " + frmPickMentorSpirit.Choice2BonusNode.OuterXml.ToString());
                            string strForce = _strForcedValue;
                            if (!frmPickMentorSpirit.Choice2.StartsWith("Adept:") && !frmPickMentorSpirit.Choice2.StartsWith("Magician:"))
                                _strForcedValue = frmPickMentorSpirit.Choice2;
                            else
                                _strForcedValue = "";
                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            blnSuccess = CreateImprovements(objImprovementSource, strSourceName, frmPickMentorSpirit.Choice2BonusNode, blnConcatSelectedValue, intRating, strFriendlyName);
                            if (!blnSuccess)
                            {
                                Rollback();
                                _strForcedValue = "";
                                _strLimitSelection = "";
                                return blnSuccess;
                            }
                            _strForcedValue = strForce;
                            _objCharacter.Improvements.Last().Notes = frmPickMentorSpirit.Choice2;
                        }

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

                    // Check for Paragon bonuses.
                    if (NodeExists(nodBonus, "selectparagon"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectparagon");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectparagon = " + nodBonus["selectparagon"].OuterXml.ToString());
                        frmSelectMentorSpirit frmPickMentorSpirit = new frmSelectMentorSpirit(_objCharacter);
                        frmPickMentorSpirit.XmlFile = "paragons.xml";
                        frmPickMentorSpirit.ShowDialog();

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

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

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

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

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

                        _strSelectedValue = strHoldValue;
                    }

                    // Check for Smartlink bonus.
                    if (NodeExists(nodBonus, "smartlink"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "smartlink");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "smartlink = " + nodBonus["smartlink"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Smartlink, "smartlink");
                    }

                    // Check for Adapsin bonus.
                    if (NodeExists(nodBonus, "adapsin"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "adapsin");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "adapsin = " + nodBonus["adapsin"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Adapsin, "adapsin");
                    }

                    // Check for SoftWeave bonus.
                    if (NodeExists(nodBonus, "softweave"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "softweave");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "softweave = " + nodBonus["softweave"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SoftWeave, "softweave");
                    }

                    // Check for Sensitive System.
                    if (NodeExists(nodBonus, "sensitivesystem"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "sensitivesystem");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "sensitivesystem = " + nodBonus["sensitivesystem"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SensitiveSystem, "sensitivesystem");
                    }

                    // Check for Movement Percent.
                    if (NodeExists(nodBonus, "movementpercent"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "movementpercent");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "movementpercent = " + nodBonus["movementpercent"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.MovementPercent, "", ValueToInt(nodBonus["movementpercent"].InnerText, intRating));
                    }

                    // Check for Swim Percent.
                    if (NodeExists(nodBonus, "swimpercent"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "swimpercent");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "swimpercent = " + nodBonus["swimpercent"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SwimPercent, "", ValueToInt(nodBonus["swimpercent"].InnerText, intRating));
                    }

                    // Check for Fly Percent.
                    if (NodeExists(nodBonus, "flypercent"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "flypercent");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "flypercent = " + nodBonus["flypercent"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlyPercent, "", ValueToInt(nodBonus["flypercent"].InnerText, intRating));
                    }

                    // Check for Fly Speed.
                    if (NodeExists(nodBonus, "flyspeed"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "flyspeed");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "flyspeed = " + nodBonus["flyspeed"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FlySpeed, "", ValueToInt(nodBonus["flyspeed"].InnerText, intRating));
                    }

                    // Check for free Positive Qualities.
                    if (NodeExists(nodBonus, "freepositivequalities"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "freepositivequalities");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "freepositivequalities = " + nodBonus["freepositivequalities"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreePositiveQualities, "", ValueToInt(nodBonus["freepositivequalities"].InnerText, intRating));
                    }

                    // Check for free Negative Qualities.
                    if (NodeExists(nodBonus, "freenegativequalities"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "freenegativequalities");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "freenegativequalities = " + nodBonus["freenegativequalities"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeNegativeQualities, "", ValueToInt(nodBonus["freenegativequalities"].InnerText, intRating));
                    }

                    // Check for Select Side.
                    if (NodeExists(nodBonus, "selectside"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectside");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectside = " + nodBonus["selectside"].OuterXml.ToString());
                        frmSelectSide frmPickSide = new frmSelectSide();
                        frmPickSide.Description = LanguageManager.Instance.GetString("Label_SelectSide").Replace("{0}", strFriendlyName);
                        if (_strForcedValue != "")
                            frmPickSide.ForceValue(_strForcedValue);
                        else
                            frmPickSide.ShowDialog();

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

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

                    // Check for Free Spirit Power Points.
                    if (NodeExists(nodBonus, "freespiritpowerpoints"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "freespiritpowerpoints");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "freespiritpowerpoints = " + nodBonus["freespiritpowerpoints"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FreeSpiritPowerPoints, "", ValueToInt(nodBonus["freespiritpowerpoints"].InnerText, intRating));
                    }

                    // Check for Adept Power Points.
                    if (NodeExists(nodBonus, "adeptpowerpoints"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "adeptpowerpoints");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "adeptpowerpoints = " + nodBonus["adeptpowerpoints"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.AdeptPowerPoints, "", ValueToInt(nodBonus["adeptpowerpoints"].InnerText, intRating));
                    }

                    // Check for Adept Powers
                    if (NodeExists(nodBonus, "specificpower"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "specificpower");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificpower = " + nodBonus["specificpower"].OuterXml.ToString());
                        // If the character isn't an adept or mystic adept, skip the rest of this.
                        if (_objCharacter.AdeptEnabled)
                        {
                            string strSelection = "";
                            _strForcedValue = "";

                            XmlNodeList objXmlPowerList = nodBonus.SelectNodes("specificpower");
                            foreach (XmlNode objXmlSpecificPower in objXmlPowerList)
                            {
                                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "objXmlSpecificPower = " + objXmlSpecificPower.OuterXml.ToString());

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

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

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

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

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

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

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

                                    frmPickLimit.ShowDialog();

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

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

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

                                if (objXmlSpecificPower["selectskill"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectskill = " + objXmlSpecificPower["selectskill"].OuterXml.ToString());
                                    XmlNode nodSkill = nodBonus["specificpower"];
                                    // Display the Select Skill window and record which Skill was selected.
                                    frmSelectSkill frmPickSkill = new frmSelectSkill(_objCharacter);
                                    if (strFriendlyName != "")
                                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkillNamed").Replace("{0}", strFriendlyName);
                                    else
                                        frmPickSkill.Description = LanguageManager.Instance.GetString("String_Improvement_SelectSkill");

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

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

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

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

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

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

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

                                if (objXmlSpecificPower["selecttext"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selecttext = " + objXmlSpecificPower["selecttext"].OuterXml.ToString());
                                    frmSelectText frmPickText = new frmSelectText();
                                    frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);

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

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

                                    frmPickText.ShowDialog();

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

                                    strSelection = frmPickText.SelectedValue;
                                    _strLimitSelection = strSelection;

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

                                if (objXmlSpecificPower["specificattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificattribute = " + objXmlSpecificPower["specificattribute"].OuterXml.ToString());
                                    strSelection = objXmlSpecificPower["specificattribute"]["name"].InnerText.ToString();
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objXmlSpecificPower["selectattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectattribute = " + objXmlSpecificPower["selectattribute"].OuterXml.ToString());
                                    XmlNode nodSkill = objXmlSpecificPower;
                                    if (_strForcedValue.StartsWith("Adept"))
                                        _strForcedValue = "";

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

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

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

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

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

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

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

                                    frmPickAttribute.ShowDialog();

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

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

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

                                // Check if the character already has this power
                                objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                bool blnHasPower = false;
                                Power objPower = new Power(_objCharacter);
                                foreach (Power power in _objCharacter.Powers)
                                {
                                    if (power.Name == strPowerNameLimit)
                                    {
                                        if (power.Extra != "" && power.Extra == strSelection)
                                        {
                                            blnHasPower = true;
                                            objPower = power;
                                        }
                                        else if (power.Extra == "")
                                        {
                                            blnHasPower = true;
                                            objPower = power;
                                        }
                                    }
                                }

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

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

                                    // Get the Power information
                                    XmlDocument objXmlDocument = new XmlDocument();
                                    objXmlDocument = XmlManager.Instance.Load("powers.xml");
                                    XmlNode objXmlPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + strPowerName + "\"]");
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "objXmlPower = " + objXmlPower.OuterXml.ToString());

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

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

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

                    // Select a Power.
                    if (NodeExists(nodBonus, "selectpower"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectpower");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strForcedValue = " + _strForcedValue);

                        bool blnExistingPower = false;
                        foreach (Power objExistingPower in _objCharacter.Powers)
                        {
                            if (objExistingPower.BonusSource == strSourceName)
                            {
                                blnExistingPower = true;
                                if (!objExistingPower.Free)
                                {
                                    if (objExistingPower.Name.StartsWith("Improved Reflexes"))
                                    {
                                        if (objExistingPower.Name.EndsWith("1"))
                                        {
                                            if (intRating >= 6)
                                                objExistingPower.FreePoints = 1.5M;
                                            else
                                                objExistingPower.FreePoints = 0;
                                        }
                                        else if (objExistingPower.Name.EndsWith("2"))
                                        {
                                            if (intRating >= 10)
                                                objExistingPower.FreePoints = 2.5M;
                                            else if (intRating >= 4)
                                                objExistingPower.FreePoints = 1.0M;
                                            else
                                                objExistingPower.FreePoints = 0;
                                        }
                                        else
                                        {
                                            if (intRating >= 14)
                                                objExistingPower.FreePoints = 3.5M;
                                            else if (intRating >= 8)
                                                objExistingPower.FreePoints = 2.0M;
                                            else if (intRating >= 4)
                                                objExistingPower.FreePoints = 1.0M;
                                            else
                                                objExistingPower.FreePoints = 0;
                                        }
                                    }
                                    else
                                    {
                                        // we have to adjust the number of free levels.
                                        decimal decLevels = Convert.ToDecimal(intRating) / 4;
                                        decLevels = Math.Floor(decLevels / objExistingPower.PointsPerLevel);
                                        objExistingPower.FreeLevels = Convert.ToInt32(decLevels);
                                        if (objExistingPower.Rating < intRating)
                                            objExistingPower.Rating = objExistingPower.FreeLevels;
                                        break;
                                    }
                                }
                            }
                        }

                        if (!blnExistingPower)
                        {
                            // Display the Select Skill window and record which Skill was selected.
                            frmSelectPower frmPickPower = new frmSelectPower(_objCharacter);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectpower = " + nodBonus.SelectSingleNode("selectpower").OuterXml.ToString());
                            frmPickPower.ShowDialog();

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

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

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

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

                            XmlNode objBonus = objXmlPower["bonus"];

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

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

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

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

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

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

                                    frmPickLimit.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

                                if (objBonus["selecttext"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selecttext = " + objBonus["selecttext"].OuterXml.ToString());
                                    frmSelectText frmPickText = new frmSelectText();
                                    frmPickText.Description = LanguageManager.Instance.GetString("String_Improvement_SelectText").Replace("{0}", strFriendlyName);

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

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

                                    frmPickText.ShowDialog();

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

                                    strSelection = frmPickText.SelectedValue;
                                    _strLimitSelection = strSelection;

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

                                if (objBonus["specificattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "specificattribute = " + objBonus["specificattribute"].OuterXml.ToString());
                                    strSelection = objBonus["specificattribute"]["name"].InnerText.ToString();
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelection = " + strSelection);
                                }

                                if (objBonus["selectattribute"] != null)
                                {
                                    objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectattribute = " + objBonus["selectattribute"].OuterXml.ToString());
                                    XmlNode nodSkill = objBonus;
                                    if (_strForcedValue.StartsWith("Adept"))
                                        _strForcedValue = "";

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

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

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

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

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

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

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

                                    frmPickAttribute.ShowDialog();

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

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

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

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

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

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

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

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

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

                                if (objXmlPower.InnerXml.Contains("bonus"))
                                {
                                    objPower.Bonus = objXmlPower["bonus"];
                                    objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovements");
                                    if (!CreateImprovements(Improvement.ImprovementSource.Power, objPower.InternalId, objPower.Bonus, false, Convert.ToInt32(objPower.Rating), objPower.DisplayNameShort))
                                    {
                                        _objCharacter.Powers.Remove(objPower);
                                    }
                                }
                            }
                        }
                    }

                    // Check for Armor Encumbrance Penalty.
                    if (NodeExists(nodBonus, "armorencumbrancepenalty"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "armorencumbrancepenalty");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "armorencumbrancepenalty = " + nodBonus["armorencumbrancepenalty"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ArmorEncumbrancePenalty, "", ValueToInt(nodBonus["armorencumbrancepenalty"].InnerText, intRating));
                    }

                    // Check for Initiation.
                    if (NodeExists(nodBonus, "initiation"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "initiation");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "initiation = " + nodBonus["initiation"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Initiation, "", ValueToInt(nodBonus["initiation"].InnerText, intRating));
                        _objCharacter.InitiateGrade += ValueToInt(nodBonus["initiation"].InnerText, intRating);
                    }

                    // Check for Submersion.
                    if (NodeExists(nodBonus, "submersion"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "submersion");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "submersion = " + nodBonus["submersion"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Submersion, "", ValueToInt(nodBonus["submersion"].InnerText, intRating));
                        _objCharacter.SubmersionGrade += ValueToInt(nodBonus["submersion"].InnerText, intRating);
                    }

                    // Check for Skillwires.
                    if (NodeExists(nodBonus, "skillwire"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillwire");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillwire = " + nodBonus["skillwire"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Skillwire, "", ValueToInt(nodBonus["skillwire"].InnerText, intRating));
                    }

                    // Check for Damage Resistance.
                    if (NodeExists(nodBonus, "damageresistance"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "damageresistance");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "damageresistance = " + nodBonus["damageresistance"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DamageResistance, "damageresistance", ValueToInt(nodBonus["damageresistance"].InnerText, intRating));
                    }

                    // Check for Restricted Item Count.
                    if (NodeExists(nodBonus, "restricteditemcount"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "restricteditemcount");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "restricteditemcount = " + nodBonus["restricteditemcount"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.RestrictedItemCount, "", ValueToInt(nodBonus["restricteditemcount"].InnerText, intRating));
                    }

                    // Check for Judge Intentions.
                    if (NodeExists(nodBonus, "judgeintentions"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "judgeintentions");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "judgeintentions = " + nodBonus["judgeintentions"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.JudgeIntentions, "", ValueToInt(nodBonus["judgeintentions"].InnerText, intRating));
                    }

                    // Check for Composure.
                    if (NodeExists(nodBonus, "composure"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "composure");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "composure = " + nodBonus["composure"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Composure, "", ValueToInt(nodBonus["composure"].InnerText, intRating));
                    }

                    // Check for Lift and Carry.
                    if (NodeExists(nodBonus, "liftandcarry"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "liftandcarry");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "liftandcarry = " + nodBonus["liftandcarry"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.LiftAndCarry, "", ValueToInt(nodBonus["liftandcarry"].InnerText, intRating));
                    }

                    // Check for Memory.
                    if (NodeExists(nodBonus, "memory"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "memory");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "memory = " + nodBonus["memory"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Memory, "", ValueToInt(nodBonus["memory"].InnerText, intRating));
                    }

                    // Check for Concealability.
                    if (NodeExists(nodBonus, "concealability"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "concealability");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "concealability = " + nodBonus["concealability"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Concealability, "", ValueToInt(nodBonus["concealability"].InnerText, intRating));
                    }

                    // Check for Drain Resistance.
                    if (NodeExists(nodBonus, "drainresist"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "drainresist");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "drainresist = " + nodBonus["drainresist"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.DrainResistance, "", ValueToInt(nodBonus["drainresist"].InnerText, intRating));
                    }

                    // Check for Fading Resistance.
                    if (NodeExists(nodBonus, "fadingresist"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "fadingresist");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "fadingresist = " + nodBonus["fadingresist"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.FadingResistance, "", ValueToInt(nodBonus["fadingresist"].InnerText, intRating));
                    }

                    // Check for Notoriety.
                    if (NodeExists(nodBonus, "notoriety"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "notoriety");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "notoriety = " + nodBonus["notoriety"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.Notoriety, "", ValueToInt(nodBonus["notoriety"].InnerText, intRating));
                    }

                    // Check for Complex Form Limit.
                    if (NodeExists(nodBonus, "complexformlimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "complexformlimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "complexformlimit = " + nodBonus["complexformlimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ComplexFormLimit, "", ValueToInt(nodBonus["complexformlimit"].InnerText, intRating));
                    }

                    // Check for Spell Limit.
                    if (NodeExists(nodBonus, "spelllimit"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "spelllimit");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "spelllimit = " + nodBonus["spelllimit"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SpellLimit, "", ValueToInt(nodBonus["spelllimit"].InnerText, intRating));
                    }

                    // Check for Spell Category bonuses.
                    if (NodeExists(nodBonus, "spellcategory"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "spellcategory");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "spellcategory = " + nodBonus["spellcategory"].OuterXml.ToString());
                        XmlNodeList objXmlCategoryList = nodBonus.SelectNodes("spellcategory");

                        // Run through each of the Spell Categories since there may be more than one affected.
                        foreach (XmlNode nodSpellCategory in objXmlCategoryList)
                        {
                            string strUseUnique = strUnique;
                            if (nodSpellCategory["name"].Attributes["precedence"] != null)
                                strUseUnique = "precedence" + nodSpellCategory["name"].Attributes["precedence"].InnerText;

                            objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                            CreateImprovement(nodSpellCategory["name"].InnerText, objImprovementSource, strSourceName, Improvement.ImprovementType.SpellCategory, strUseUnique, ValueToInt(nodSpellCategory["val"].InnerText, intRating));
                        }
                    }

                    // Check for Throwing Range bonuses.
                    if (NodeExists(nodBonus, "throwrange"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "throwrange");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "throwrange = " + nodBonus["throwrange"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowRange, strUnique, ValueToInt(nodBonus["throwrange"].InnerText, intRating));
                    }

                    // Check for Throwing STR bonuses.
                    if (NodeExists(nodBonus, "throwstr"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "throwstr");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "throwstr = " + nodBonus["throwstr"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.ThrowSTR, strUnique, ValueToInt(nodBonus["throwstr"].InnerText, intRating));
                    }

                    // Check for Skillsoft access.
                    if (NodeExists(nodBonus, "skillsoftaccess"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "skillsoftaccess");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "skillsoftaccess = " + nodBonus["skillsoftaccess"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.SkillsoftAccess, "");
                    }

                    // Check for Quickening Metamagic.
                    if (NodeExists(nodBonus, "quickeningmetamagic"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "quickeningmetamagic");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "quickeningmetamagic = " + nodBonus["quickeningmetamagic"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.QuickeningMetamagic, "");
                    }

                    // Check for ignore Stun CM Penalty.
                    if (NodeExists(nodBonus, "ignorecmpenaltystun"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "ignorecmpenaltystun");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "ignorecmpenaltystun = " + nodBonus["ignorecmpenaltystun"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyStun, "");
                    }

                    // Check for ignore Physical CM Penalty.
                    if (NodeExists(nodBonus, "ignorecmpenaltyphysical"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "ignorecmpenaltyphysical");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "ignorecmpenaltyphysical = " + nodBonus["ignorecmpenaltyphysical"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.IgnoreCMPenaltyPhysical, "");
                    }

                    // Check for a Cyborg Essence which will permanently set the character's ESS to 0.1.
                    if (NodeExists(nodBonus, "cyborgessence"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "cyborgessence");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "cyborgessence = " + nodBonus["cyborgessence"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.CyborgEssence, "");
                    }

                    // Check for Maximum Essence which will permanently modify the character's Maximum Essence value.
                    if (NodeExists(nodBonus, "essencemax"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "essencemax");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "essencemax = " + nodBonus["essencemax"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.EssenceMax, "", ValueToInt(nodBonus["essencemax"].InnerText, intRating));
                    }

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

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

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

                        _strSelectedValue = frmPickItem.SelectedItem;

                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement(frmPickItem.SelectedItem, objImprovementSource, strSourceName, Improvement.ImprovementType.AddSprite, "");
                    }

                    // Check for Black Market Discount.
                    if (NodeExists(nodBonus, "blackmarketdiscount"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "blackmarketdiscount");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "blackmarketdiscount = " + nodBonus["blackmarketdiscount"].OuterXml.ToString());
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling CreateImprovement");
                        CreateImprovement("", objImprovementSource, strSourceName, Improvement.ImprovementType.BlackMarketDiscount, strUnique);
                        _objCharacter.BlackMarket = true;
                    }

                    // Select Weapon (custom entry for things like Spare Clip).
                    if (NodeExists(nodBonus, "selectweapon"))
                    {
                        objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "selectweapon");
                        objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "selectweapon = " + nodBonus["selectweapon"].OuterXml.ToString());
                        string strSelectedValue = "";
                        if (_strForcedValue != "")
                            _strLimitSelection = _strForcedValue;

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

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

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

                            frmPickText.ShowDialog();

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

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

                            strSelectedValue = frmPickText.SelectedValue;
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelectedValue = " + strSelectedValue);
                        }
                        else
                        {
                            List<ListItem> lstWeapons = new List<ListItem>();
                            foreach (Weapon objWeapon in _objCharacter.Weapons)
                            {
                                ListItem objItem = new ListItem();
                                objItem.Value = objWeapon.Name;
                                objItem.Name = objWeapon.DisplayName;
                                lstWeapons.Add(objItem);
                            }

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

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

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

                            frmPickItem.ShowDialog();

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

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

                            strSelectedValue = frmPickItem.SelectedItem;
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "_strSelectedValue = " + _strSelectedValue);
                            objFunctions.LogWrite(CommonFunctions.LogType.Content, "Chummer.ImprovementManager", "strSelectedValue = " + strSelectedValue);
                        }

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

                // If we've made it this far, everything went OK, so commit the Improvements.
                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Calling Commit");
                Commit();
                objFunctions.LogWrite(CommonFunctions.LogType.Message, "Chummer.ImprovementManager", "Returned from Commit");
                // Clear the Forced Value and Limit Selection strings once we're done to prevent these from forcing their values on other Improvements.
                _strForcedValue = "";
                _strLimitSelection = "";
            }
            catch (Exception ex)
            {
                objFunctions.LogWrite(CommonFunctions.LogType.Error, "Chummer.ImprovementManager", "ERROR Message = " + ex.Message);
                objFunctions.LogWrite(CommonFunctions.LogType.Error, "Chummer.ImprovementManager", "ERROR Source  = " + ex.Source);
                objFunctions.LogWrite(CommonFunctions.LogType.Error, "Chummer.ImprovementManager", "ERROR Trace   = " + ex.StackTrace.ToString());
                MessageBox.Show("If you're seeing this, an error just occurred that couldn't be handled. If you have the debug log turned on, please email chummerlog.txt (zipped please) to [email protected]. If you don't have the debug log turned on, please turn it on in the Options dialog and try to repeat what you did so the error can be captured. Thank you.");
                Rollback();
                blnSuccess = false;
            }
            objFunctions.LogWrite(CommonFunctions.LogType.Exiting, "Chummer.ImprovementManager", "CreateImprovements");
            return blnSuccess;
        }