Example #1
0
        public void CreateAllCritterPowersTest()
        {
            // Create a new Human character.
            Character objCharacter = new Character();
            objCharacter.LoadMetatype(Guid.Parse("e28e7075-f635-4c02-937c-e4fc61c51602"));

            TreeNode objNode = new TreeNode();

            XmlDocument objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
            foreach (XmlNode objXmlNode in objXmlDocument.SelectNodes("/chummer/powers/power"))
            {
                CritterPower objPower = new CritterPower(objCharacter);
                objPower.Create(objXmlNode, objCharacter, objNode, 0, "", false);
            }
        }
Example #2
0
        /// <summary>
        /// Create a Critter, put them into Career Mode, link them, and open the newly-created Critter.
        /// </summary>
        /// <param name="strCritterName">Name of the Critter's Metatype.</param>
        /// <param name="intForce">Critter's Force.</param>
        private async void CreateCritter(string strCritterName, int intForce)
        {
            // Code from frmMetatype.
            XmlDocument objXmlDocument = XmlManager.Load("critters.xml");

            XmlNode objXmlMetatype = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + strCritterName + "\"]");

            // If the Critter could not be found, show an error and get out of here.
            if (objXmlMetatype == null)
            {
                Program.MainForm.ShowMessageBox(string.Format(GlobalOptions.CultureInfo, LanguageManager.GetString("Message_UnknownCritterType"), strCritterName), LanguageManager.GetString("MessageTitle_SelectCritterType"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // The Critter should use the same settings file as the character.
            using (Character objCharacter = new Character
            {
                SettingsFile = _objSpirit.CharacterObject.SettingsFile,

                // Override the defaults for the setting.
                IgnoreRules = true,
                IsCritter = true,
                BuildMethod = CharacterBuildMethod.Karma
            })
            {
                if (!string.IsNullOrEmpty(txtCritterName.Text))
                {
                    objCharacter.Name = txtCritterName.Text;
                }

                string strSpace = LanguageManager.GetString("String_Space");
                using (SaveFileDialog saveFileDialog = new SaveFileDialog
                {
                    Filter = LanguageManager.GetString("DialogFilter_Chum5") + '|' + LanguageManager.GetString("DialogFilter_All"),
                    FileName = strCritterName + strSpace + '(' + LanguageManager.GetString(_objSpirit.RatingLabel) + strSpace + _objSpirit.Force.ToString(GlobalOptions.InvariantCultureInfo) + ").chum5"
                })
                {
                    if (saveFileDialog.ShowDialog(this) != DialogResult.OK)
                    {
                        return;
                    }
                    string strFileName = saveFileDialog.FileName;
                    objCharacter.FileName = strFileName;
                }

                Cursor = Cursors.WaitCursor;

                // Set Metatype information.
                if (strCritterName == "Ally Spirit")
                {
                    objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["bodaug"]?.InnerText, intForce, 0));
                    objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["agiaug"]?.InnerText, intForce, 0));
                    objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["reaaug"]?.InnerText, intForce, 0));
                    objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["straug"]?.InnerText, intForce, 0));
                    objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["chaaug"]?.InnerText, intForce, 0));
                    objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["intaug"]?.InnerText, intForce, 0));
                    objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["logaug"]?.InnerText, intForce, 0));
                    objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["wilaug"]?.InnerText, intForce, 0));
                    objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["magaug"]?.InnerText, intForce, 0));
                    objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["resaug"]?.InnerText, intForce, 0));
                    objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["edgaug"]?.InnerText, intForce, 0));
                    objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["essaug"]?.InnerText, intForce, 0));
                }
                else
                {
                    int intMinModifier = -3;
                    objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["bodmin"]?.InnerText, intForce, 3));
                    objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["agimin"]?.InnerText, intForce, 3));
                    objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["reamin"]?.InnerText, intForce, 3));
                    objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["strmin"]?.InnerText, intForce, 3));
                    objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["chamin"]?.InnerText, intForce, 3));
                    objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["intmin"]?.InnerText, intForce, 3));
                    objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["logmin"]?.InnerText, intForce, 3));
                    objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["wilmin"]?.InnerText, intForce, 3));
                    objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["magmin"]?.InnerText, intForce, 3));
                    objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["resmin"]?.InnerText, intForce, 3));
                    objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"]?.InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"]?.InnerText, intForce, 3),
                                                  ExpressionToString(objXmlMetatype["edgmin"]?.InnerText, intForce, 3));
                    objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"]?.InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"]?.InnerText, intForce, 0),
                                                  ExpressionToString(objXmlMetatype["essaug"]?.InnerText, intForce, 0));
                }

                // If we're working with a Critter, set the Attributes to their default values.
                objCharacter.BOD.MetatypeMinimum = ExpressionToInt(objXmlMetatype["bodmin"]?.InnerText, intForce, 0);
                objCharacter.AGI.MetatypeMinimum = ExpressionToInt(objXmlMetatype["agimin"]?.InnerText, intForce, 0);
                objCharacter.REA.MetatypeMinimum = ExpressionToInt(objXmlMetatype["reamin"]?.InnerText, intForce, 0);
                objCharacter.STR.MetatypeMinimum = ExpressionToInt(objXmlMetatype["strmin"]?.InnerText, intForce, 0);
                objCharacter.CHA.MetatypeMinimum = ExpressionToInt(objXmlMetatype["chamin"]?.InnerText, intForce, 0);
                objCharacter.INT.MetatypeMinimum = ExpressionToInt(objXmlMetatype["intmin"]?.InnerText, intForce, 0);
                objCharacter.LOG.MetatypeMinimum = ExpressionToInt(objXmlMetatype["logmin"]?.InnerText, intForce, 0);
                objCharacter.WIL.MetatypeMinimum = ExpressionToInt(objXmlMetatype["wilmin"]?.InnerText, intForce, 0);
                objCharacter.MAG.MetatypeMinimum = ExpressionToInt(objXmlMetatype["magmin"]?.InnerText, intForce, 0);
                objCharacter.RES.MetatypeMinimum = ExpressionToInt(objXmlMetatype["resmin"]?.InnerText, intForce, 0);
                objCharacter.EDG.MetatypeMinimum = ExpressionToInt(objXmlMetatype["edgmin"]?.InnerText, intForce, 0);
                objCharacter.ESS.MetatypeMinimum = ExpressionToInt(objXmlMetatype["essmax"]?.InnerText, intForce, 0);

                // Sprites can never have Physical Attributes.
                if (objXmlMetatype["category"].InnerText.EndsWith("Sprite", StringComparison.Ordinal))
                {
                    objCharacter.BOD.AssignLimits("0", "0", "0");
                    objCharacter.AGI.AssignLimits("0", "0", "0");
                    objCharacter.REA.AssignLimits("0", "0", "0");
                    objCharacter.STR.AssignLimits("0", "0", "0");
                }

                objCharacter.Metatype         = strCritterName;
                objCharacter.MetatypeCategory = objXmlMetatype["category"].InnerText;
                objCharacter.Metavariant      = string.Empty;
                objCharacter.MetatypeBP       = 0;

                if (objXmlMetatype["movement"] != null)
                {
                    objCharacter.Movement = objXmlMetatype["movement"].InnerText;
                }
                // Load the Qualities file.
                XmlDocument objXmlQualityDocument = XmlManager.Load("qualities.xml");

                // Determine if the Metatype has any bonuses.
                if (objXmlMetatype.InnerXml.Contains("bonus"))
                {
                    ImprovementManager.CreateImprovements(objCharacter, Improvement.ImprovementSource.Metatype, strCritterName, objXmlMetatype.SelectSingleNode("bonus"), 1, strCritterName);
                }

                // Create the Qualities that come with the Metatype.
                foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/*/quality"))
                {
                    XmlNode       objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                    List <Weapon> lstWeapons    = new List <Weapon>();
                    Quality       objQuality    = new Quality(objCharacter);
                    string        strForceValue = objXmlQualityItem.Attributes?["select"]?.InnerText ?? string.Empty;
                    QualitySource objSource     = objXmlQualityItem.Attributes["removable"]?.InnerText == bool.TrueString ? QualitySource.MetatypeRemovable : QualitySource.Metatype;
                    objQuality.Create(objXmlQuality, objSource, lstWeapons, strForceValue);
                    objCharacter.Qualities.Add(objQuality);

                    // Add any created Weapons to the character.
                    foreach (Weapon objWeapon in lstWeapons)
                    {
                        objCharacter.Weapons.Add(objWeapon);
                    }
                }

                // Add any Critter Powers the Metatype/Critter should have.
                XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + objCharacter.Metatype + "\"]");

                objXmlDocument = XmlManager.Load("critterpowers.xml");
                foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
                {
                    XmlNode      objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                    CritterPower objPower           = new CritterPower(objCharacter);
                    string       strForcedValue     = objXmlPower.Attributes?["select"]?.InnerText ?? string.Empty;
                    int          intRating          = Convert.ToInt32(objXmlPower.Attributes?["rating"]?.InnerText, GlobalOptions.InvariantCultureInfo);

                    objPower.Create(objXmlCritterPower, intRating, strForcedValue);
                    objCharacter.CritterPowers.Add(objPower);
                }

                if (objXmlCritter["optionalpowers"] != null)
                {
                    //For every 3 full points of Force a spirit has, it may gain one Optional Power.
                    for (int i = intForce - 3; i >= 0; i -= 3)
                    {
                        XmlDocument objDummyDocument = new XmlDocument
                        {
                            XmlResolver = null
                        };
                        XmlNode bonusNode = objDummyDocument.CreateNode(XmlNodeType.Element, "bonus", null);
                        objDummyDocument.AppendChild(bonusNode);
                        XmlNode powerNode = objDummyDocument.ImportNode(objXmlMetatype["optionalpowers"].CloneNode(true), true);
                        objDummyDocument.ImportNode(powerNode, true);
                        bonusNode.AppendChild(powerNode);
                        ImprovementManager.CreateImprovements(objCharacter, Improvement.ImprovementSource.Metatype, objCharacter.Metatype, bonusNode, 1, objCharacter.Metatype);
                    }
                }

                // Add any Complex Forms the Critter comes with (typically Sprites)
                XmlDocument objXmlProgramDocument = XmlManager.Load("complexforms.xml");
                foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
                {
                    string      strForceValue         = objXmlComplexForm.Attributes?["select"]?.InnerText ?? string.Empty;
                    XmlNode     objXmlComplexFormData = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlComplexForm.InnerText + "\"]");
                    ComplexForm objComplexForm        = new ComplexForm(objCharacter);
                    objComplexForm.Create(objXmlComplexFormData, strForceValue);
                    objCharacter.ComplexForms.Add(objComplexForm);
                }

                // Add any Gear the Critter comes with (typically Programs for A.I.s)
                XmlDocument objXmlGearDocument = XmlManager.Load("gear.xml");
                foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
                {
                    int intRating = 0;
                    if (objXmlGear.Attributes["rating"] != null)
                    {
                        intRating = ExpressionToInt(objXmlGear.Attributes["rating"].InnerText, decimal.ToInt32(nudForce.Value), 0);
                    }
                    string        strForceValue  = objXmlGear.Attributes?["select"]?.InnerText ?? string.Empty;
                    XmlNode       objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = " + objXmlGear.InnerText.CleanXPath() + "]");
                    Gear          objGear        = new Gear(objCharacter);
                    List <Weapon> lstWeapons     = new List <Weapon>();
                    objGear.Create(objXmlGearItem, intRating, lstWeapons, strForceValue);
                    objGear.Cost = "0";
                    objCharacter.Gear.Add(objGear);
                }

                // Add the Unarmed Attack Weapon to the character.
                objXmlDocument = XmlManager.Load("weapons.xml");
                XmlNode objXmlWeapon = objXmlDocument.SelectSingleNode("/chummer/weapons/weapon[name = \"Unarmed Attack\"]");
                if (objXmlWeapon != null)
                {
                    List <Weapon> lstWeapons = new List <Weapon>();
                    Weapon        objWeapon  = new Weapon(objCharacter);
                    objWeapon.Create(objXmlWeapon, lstWeapons);
                    objWeapon.ParentID = Guid.NewGuid().ToString("D", GlobalOptions.InvariantCultureInfo); // Unarmed Attack can never be removed
                    objCharacter.Weapons.Add(objWeapon);
                    foreach (Weapon objLoopWeapon in lstWeapons)
                    {
                        objCharacter.Weapons.Add(objLoopWeapon);
                    }
                }

                objCharacter.Alias   = strCritterName;
                objCharacter.Created = true;
                if (!objCharacter.Save())
                {
                    Cursor = Cursors.Default;
                    return;
                }

                _objSpirit.FileName = objCharacter.FileName;
            }

            // Link the newly-created Critter to the Spirit.
            imgLink.SetToolTip(LanguageManager.GetString(_objSpirit.EntityType == SpiritType.Spirit ? "Tip_Spirit_OpenFile" : "Tip_Sprite_OpenFile"));
            ContactDetailChanged?.Invoke(this, null);

            Character objOpenCharacter = await Program.MainForm.LoadCharacter(_objSpirit.FileName).ConfigureAwait(true);

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

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

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

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

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

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

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

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

                }
                else
                {
                    Utils.BreakIfDebug();
                }

            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                frmPickSkillGroup.ShowDialog();

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

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

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

                _strSelectedValue = frmPickSkillGroup.SelectedSkillGroup;

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

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

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

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

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

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

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

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

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

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

                    frmPickAttribute.ShowDialog();

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

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

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

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

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

                    string strAttribute = frmPickAttribute.SelectedAttribute;

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

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

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

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

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

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

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

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

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

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

                frmPickAttribute.ShowDialog();

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

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

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

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

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

                string strAttribute = frmPickAttribute.SelectedAttribute;

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

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

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

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

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

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

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

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

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

                frmPickLimit.ShowDialog();

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

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

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

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

                string strLimit = frmPickLimit.SelectedLimit;

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

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

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

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

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

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

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

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

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

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

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

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

                frmPickAttribute.ShowDialog();

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

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

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

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

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

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

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

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

                frmPickSpell.ShowDialog();

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

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

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

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

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

                frmSelectItem frmSelect = new frmSelectItem();

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

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

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

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

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

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

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

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

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

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

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

                int loyalty, connection;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                KnowledgeSkill skill = new KnowledgeSkill(_objCharacter, name);

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

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

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

            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    _strSelectedValue = frmPickCategory.SelectedItem;

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

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

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

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

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

                _strSelectedValue = frmPickMentorSpirit.SelectedMentor;

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

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

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

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

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

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

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

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

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

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

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

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

                _strSelectedValue = strHoldValue;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        frmPickLimit.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                            frmPickText.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

                        frmPickAttribute.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        XmlNode objBonus = objXmlPower["bonus"];

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

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

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

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

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

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

                                frmPickLimit.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                frmPickText.ShowDialog();

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

                                strSelection = frmPickText.SelectedValue;
                                _strLimitSelection = strSelection;

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

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

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

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

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

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

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

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

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

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

                                frmPickAttribute.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                _strSelectedValue = frmPickItem.SelectedItem;

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

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

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

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

                if (lstArmors.Count > 0)
                {

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

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

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

                    frmPickItem.ShowDialog();

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

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

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

            }

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

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

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

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

                    frmPickText.ShowDialog();

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

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

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

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

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

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

                    frmPickItem.ShowDialog();

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

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

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

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

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

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

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

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

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

                frmPickPower.ShowDialog();

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

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

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

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

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

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

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

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

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

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

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

                    final = frmSelect.SelectedItem;
                }

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

            //nothing went wrong, so return true
            return true;
        }
Example #4
0
        private void cmdAddQuality_Click(object sender, EventArgs e)
        {
            frmSelectQuality frmPickQuality = new frmSelectQuality(_objCharacter);
            frmPickQuality.ShowDialog(this);

            // Don't do anything else if the form was canceled.
            if (frmPickQuality.DialogResult == DialogResult.Cancel)
                return;

            XmlDocument objXmlDocument = XmlManager.Instance.Load("qualities.xml");
            XmlNode objXmlQuality = objXmlDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + frmPickQuality.SelectedQuality + "\"]");

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

            objQuality.Create(objXmlQuality, _objCharacter, QualitySource.Selected, objNode, objWeapons, objWeaponNodes);
            objNode.ContextMenuStrip = cmsQuality;
            if (objQuality.InternalId == Guid.Empty.ToString())
                return;

            if (frmPickQuality.FreeCost)
                objQuality.BP = 0;

            bool blnAddItem = true;
            int intKarmaCost = objQuality.BP * _objOptions.KarmaQuality;
            if (!_objCharacter.Options.DontDoubleQualities)
                intKarmaCost *= 2;

            // Make sure the character has enough Karma to pay for the Quality.
            if (objQuality.Type == QualityType.Positive)
            {
                if (intKarmaCost > _objCharacter.Karma)
                {
                    MessageBox.Show(LanguageManager.Instance.GetString("Message_NotEnoughKarma"), LanguageManager.Instance.GetString("MessageTitle_NotEnoughKarma"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                    blnAddItem = false;
                }

                if (blnAddItem && !frmPickQuality.FreeCost && objQuality.ContributeToBP)
                {
                    if (!ConfirmKarmaExpense(LanguageManager.Instance.GetString("Message_ConfirmKarmaExpenseSpend").Replace("{0}", objQuality.DisplayNameShort).Replace("{1}", intKarmaCost.ToString())))
                        blnAddItem = false;
                }

                if (blnAddItem && objQuality.ContributeToBP)
                {
                    // Create the Karma expense.
                    ExpenseLogEntry objExpense = new ExpenseLogEntry();
                    objExpense.Create(intKarmaCost * -1, LanguageManager.Instance.GetString("String_ExpenseAddPositiveQuality") + " " + objQuality.DisplayNameShort, ExpenseType.Karma, DateTime.Now);
                    _objCharacter.ExpenseEntries.Add(objExpense);
                    _objCharacter.Karma -= intKarmaCost;

                    ExpenseUndo objUndo = new ExpenseUndo();
                    objUndo.CreateKarma(KarmaExpenseType.AddQuality, objQuality.InternalId);
                    objExpense.Undo = objUndo;
                }
            }
            else
            {
                if (MessageBox.Show(LanguageManager.Instance.GetString("Message_AddNegativeQuality"), LanguageManager.Instance.GetString("MessageTitle_AddNegativeQuality"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                    blnAddItem = false;

                if (blnAddItem)
                {
                    // Create a Karma Expense for the Negative Quality.
                    ExpenseLogEntry objExpense = new ExpenseLogEntry();
                    objExpense.Create(0, LanguageManager.Instance.GetString("String_ExpenseAddNegativeQuality") + " " + objQuality.DisplayNameShort, ExpenseType.Karma, DateTime.Now);
                    _objCharacter.ExpenseEntries.Add(objExpense);

                    ExpenseUndo objUndo = new ExpenseUndo();
                    objUndo.CreateKarma(KarmaExpenseType.AddQuality, objQuality.InternalId);
                    objExpense.Undo = objUndo;
                }
            }

            if (blnAddItem)
            {
                // Add the Quality to the appropriate parent node.
                if (objQuality.Type == QualityType.Positive)
                {
                    treQualities.Nodes[0].Nodes.Add(objNode);
                    treQualities.Nodes[0].Expand();
                }
                else
                {
                    treQualities.Nodes[1].Nodes.Add(objNode);
                    treQualities.Nodes[1].Expand();
                }
                _objCharacter.Qualities.Add(objQuality);

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

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

                // Add any additional Qualities that are forced on the character.
                if (objXmlQuality.SelectNodes("addqualities/addquality").Count > 0)
                {
                    foreach (XmlNode objXmlAddQuality in objXmlQuality.SelectNodes("addqualities/addquality"))
                    {
                        XmlNode objXmlSelectedQuality = objXmlDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlAddQuality.InnerText + "\"]");
                        string strForceValue = "";
                        if (objXmlAddQuality.Attributes["select"] != null)
                            strForceValue = objXmlAddQuality.Attributes["select"].InnerText;
                        bool blnAddQuality = true;

                        // Make sure the character does not yet have this Quality.
                        foreach (Quality objCharacterQuality in _objCharacter.Qualities)
                        {
                            if (objCharacterQuality.Name == objXmlAddQuality.InnerText && objCharacterQuality.Extra == strForceValue)
                            {
                                blnAddQuality = false;
                                break;
                            }
                        }

                        if (blnAddQuality)
                        {
                            TreeNode objAddQualityNode = new TreeNode();
                            List<Weapon> objAddWeapons = new List<Weapon>();
                            List<TreeNode> objAddWeaponNodes = new List<TreeNode>();
                            Quality objAddQuality = new Quality(_objCharacter);
                            objAddQuality.Create(objXmlSelectedQuality, _objCharacter, QualitySource.Selected, objAddQualityNode, objAddWeapons, objAddWeaponNodes, strForceValue);
                            objNode.Nodes.Add(objAddQualityNode);
                            objNode.Expand();
                            _objCharacter.Qualities.Add(objAddQuality);

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

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

                // Add any Critter Powers that are gained through the Quality (Infected).
                if (objXmlQuality.SelectNodes("powers/power").Count > 0)
                {
                    objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
                    foreach (XmlNode objXmlPower in objXmlQuality.SelectNodes("powers/power"))
                    {
                        XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                        TreeNode objPowerNode = new TreeNode();
                        CritterPower objPower = new CritterPower(_objCharacter);
                        string strForcedValue = "";
                        int intRating = 0;

                        if (objXmlPower.Attributes["rating"] != null)
                            intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                        if (objXmlPower.Attributes["select"] != null)
                            strForcedValue = objXmlPower.Attributes["select"].InnerText;

                        objPower.Create(objXmlCritterPower, _objCharacter, objPowerNode, intRating, strForcedValue);
                        _objCharacter.CritterPowers.Add(objPower);

                        if (objPower.Category != "Weakness")
                        {
                            treCritterPowers.Nodes[0].Nodes.Add(objPowerNode);
                            treCritterPowers.Nodes[0].Expand();
                        }
                        else
                        {
                            treCritterPowers.Nodes[1].Nodes.Add(objPowerNode);
                            treCritterPowers.Nodes[1].Expand();
                        }
                    }
                }
            }
            else
            {
                // Remove the Improvements created by the Create method.
                _objImprovementManager.RemoveImprovements(Improvement.ImprovementSource.Quality, objQuality.InternalId);
            }

            // If the Quality is a mentor spirit, add any qualities particular to the mentor spirit.
            if (objQuality.Name == "Mentor Spirit")
            {
                XmlDocument objXmlMentors = XmlManager.Instance.Load("mentors.xml");
                XmlNode objXmlMentor = objXmlMentors.SelectSingleNode("/chummer/mentors/mentor[name = \"" + objQuality.Extra + "\"]");
                XmlNode objXmlAddQualities = objXmlMentor["addqualities"];

                // If there are additional qualities
                if (objXmlAddQualities != null)
                {
                    foreach (XmlNode objXmlAddQuality in objXmlAddQualities.ChildNodes)
                    {
                        XmlNode objXmlMentorQuality = objXmlDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlAddQuality.InnerText + "\"]");

                        TreeNode objMentorNode = new TreeNode();
                        List<Weapon> objMentorWeapons = new List<Weapon>();
                        List<TreeNode> objMentorWeaponNodes = new List<TreeNode>();
                        Quality objSpiritQuality = new Quality(_objCharacter);
                        string strExtra = "";
                        if (objXmlAddQuality.Attributes["select"].InnerText.ToString().Length > 0)
                        {
                            strExtra = objXmlAddQuality.Attributes["select"].InnerText.ToString();
                            objSpiritQuality.Create(objXmlMentorQuality, _objCharacter, QualitySource.Selected, objMentorNode, objMentorWeapons, objMentorWeaponNodes, strExtra);
                        }
                        else
                            objSpiritQuality.Create(objXmlMentorQuality, _objCharacter, QualitySource.Selected, objMentorNode, objMentorWeapons, objMentorWeaponNodes);

                        objSpiritQuality.BP = 0;

                        // Add the quality to the character
                        if (objSpiritQuality.Type == QualityType.Positive)
                        {
                            treQualities.Nodes[0].Nodes.Add(objMentorNode);
                            treQualities.Nodes[0].Expand();
                        }
                        else
                        {
                            treQualities.Nodes[1].Nodes.Add(objMentorNode);
                            treQualities.Nodes[1].Expand();
                        }
                        _objCharacter.Qualities.Add(objSpiritQuality);
                    }
                }
            }

            _objFunctions.SortTree(treQualities);
            UpdateMentorSpirits();
            UpdateCharacterInfo();
            RefreshPowers();
            RefreshContacts();

            _blnIsDirty = true;
            UpdateWindowTitle();

            if (frmPickQuality.AddAgain)
                cmdAddQuality_Click(sender, e);
        }
Example #5
0
        private void cmdAddCritterPower_Click(object sender, EventArgs e)
        {
            // Make sure the Critter is allowed to have Optional Powers.
            XmlDocument objXmlDocument = XmlManager.Instance.Load("critters.xml");
            XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");

            if (objXmlCritter == null)
            {
                objXmlDocument = XmlManager.Instance.Load("metatypes.xml");
                objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");
            }

            frmSelectCritterPower frmPickCritterPower = new frmSelectCritterPower(_objCharacter);
            frmPickCritterPower.ShowDialog(this);

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

            objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
            XmlNode objXmlPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + frmPickCritterPower.SelectedPower + "\"]");
            TreeNode objNode = new TreeNode();
            CritterPower objPower = new CritterPower(_objCharacter);
            objPower.Create(objXmlPower, _objCharacter, objNode, frmPickCritterPower.SelectedRating);
            objPower.PowerPoints = frmPickCritterPower.PowerPoints;
            objNode.ContextMenuStrip = cmsCritterPowers;
            if (objPower.InternalId == Guid.Empty.ToString())
                return;

            _objCharacter.CritterPowers.Add(objPower);

            if (objPower.Category != "Weakness")
            {
                treCritterPowers.Nodes[0].Nodes.Add(objNode);
                treCritterPowers.Nodes[0].Expand();
            }
            else
            {
                treCritterPowers.Nodes[1].Nodes.Add(objNode);
                treCritterPowers.Nodes[1].Expand();
            }

            // Determine if the Critter should have access to the Possession menu item.
            bool blnAllowPossession = false;
            foreach (CritterPower objCritterPower in _objCharacter.CritterPowers)
            {
                if (objCritterPower.Name == "Inhabitation" || objCritterPower.Name == "Possession")
                {
                    blnAllowPossession = true;
                    break;
                }
            }
            mnuSpecialPossess.Visible = blnAllowPossession;

            _objFunctions.SortTree(treCritterPowers);
            UpdateCharacterInfo();

            _blnIsDirty = true;
            UpdateWindowTitle();

            if (frmPickCritterPower.AddAgain)
                cmdAddCritterPower_Click(sender, e);
        }
Example #6
0
        /// <summary>
        /// Load the Character from an XML file.
        /// </summary>
        public bool Load()
        {
            XmlDocument objXmlDocument = new XmlDocument();
            objXmlDocument.Load(_strFileName);

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

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

            ResetCharacter();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return true;
        }
Example #7
0
        private void cmdAddCritterPower_Click(object sender, EventArgs e)
        {
            // Make sure the Critter is allowed to have Optional Powers.
            XmlDocument objXmlDocument = XmlManager.Instance.Load("critters.xml");
            XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");

            if (objXmlCritter == null)
            {
                objXmlDocument = XmlManager.Instance.Load("metatypes.xml");
                objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");
            }

            frmSelectCritterPower frmPickCritterPower = new frmSelectCritterPower(_objCharacter);
            frmPickCritterPower.ShowDialog(this);

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

            objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
            XmlNode objXmlPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + frmPickCritterPower.SelectedPower + "\"]");
            TreeNode objNode = new TreeNode();
            CritterPower objPower = new CritterPower(_objCharacter);
            objPower.Create(objXmlPower, _objCharacter, objNode, frmPickCritterPower.SelectedRating);
            objPower.PowerPoints = frmPickCritterPower.PowerPoints;
            objNode.ContextMenuStrip = cmsCritterPowers;
            if (objPower.InternalId == Guid.Empty.ToString())
                return;

            _objCharacter.CritterPowers.Add(objPower);

            if (objPower.Category != "Weakness")
            {
                treCritterPowers.Nodes[0].Nodes.Add(objNode);
                treCritterPowers.Nodes[0].Expand();
            }
            else
            {
                treCritterPowers.Nodes[1].Nodes.Add(objNode);
                treCritterPowers.Nodes[1].Expand();
            }

            treCritterPowers.SortCustom();
            UpdateCharacterInfo();

            _blnIsDirty = true;
            UpdateWindowTitle();

            if (frmPickCritterPower.AddAgain)
                cmdAddCritterPower_Click(sender, e);
        }
Example #8
0
        private void mnuSpecialCyberzombie_Click(object sender, EventArgs e)
        {
            bool blnEssence = true;
            bool blnCyberware = false;
            string strMessage = LanguageManager.Instance.GetString("Message_CyberzombieRequirements");

            // Make sure the character has an Essence lower than 0.
            if (_objCharacter.Essence >= 0)
            {
                strMessage += "\n\t" + LanguageManager.Instance.GetString("Message_CyberzombieRequirementsEssence");
                blnEssence = false;
            }

            // Make sure the character has an Invoked Memory Stimulator.
            foreach (Cyberware objCyberware in _objCharacter.Cyberware)
            {
                if (objCyberware.Name == "Invoked Memory Stimulator")
                    blnCyberware = true;
            }

            if (!blnCyberware)
                strMessage += "\n\t" + LanguageManager.Instance.GetString("Message_CyberzombieRequirementsStimulator");

            if (!blnEssence || !blnCyberware)
            {
                MessageBox.Show(strMessage, LanguageManager.Instance.GetString("MessageTitle_CyberzombieRequirements"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (MessageBox.Show(LanguageManager.Instance.GetString("Message_CyberzombieConfirm"), LanguageManager.Instance.GetString("MessageTitle_CyberzombieConfirm"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                return;

            // Get the player to roll Dice to make a WIL Test and record the result.
            frmDiceHits frmWILHits = new frmDiceHits();
            frmWILHits.Text = LanguageManager.Instance.GetString("String_CyberzombieWILText");
            frmWILHits.Description = LanguageManager.Instance.GetString("String_CyberzombieWILDescription");
            int intDice = _objCharacter.WIL.TotalValue;
            int intThreshold = 3 + (Convert.ToInt32(_objCharacter.EssencePenalty - Convert.ToInt32(_objCharacter.EssenceMaximum)));
            frmWILHits.Dice = intDice;
            frmWILHits.ShowDialog(this);

            if (frmWILHits.DialogResult != DialogResult.OK)
                return;

            int intWILResult = frmWILHits.Result;

            // The character gains 10 + ((Threshold - Hits) * 10)BP worth of Negative Qualities.
            int intResult = 10;
            if (intWILResult < intThreshold)
            {
                intResult = (intThreshold - intWILResult) * 10;
            }
            _objImprovementManager.CreateImprovement("", Improvement.ImprovementSource.Cyberzombie, "Cyberzombie Qualities", Improvement.ImprovementType.FreeNegativeQualities, "", intResult * -1);

            // Convert the character.
            // Characters lose access to Resonance.
            _objCharacter.RESEnabled = false;

            // Gain MAG that is permanently set to 1.
            _objCharacter.MAGEnabled = true;
            _objCharacter.MAG.MetatypeMinimum = 1;
            _objCharacter.MAG.MetatypeMaximum = 1;
            _objCharacter.MAG.Value = 1;

            // Add the Cyberzombie Lifestyle if it is not already taken.
            bool blnHasLifestyle = false;
            foreach (Lifestyle objLifestyle in _objCharacter.Lifestyles)
            {
                if (objLifestyle.Name == "Cyberzombie Lifestyle Addition")
                    blnHasLifestyle = true;
            }
            if (!blnHasLifestyle)
            {
                XmlDocument objXmlLifestyleDocument = XmlManager.Instance.Load("lifestyles.xml");
                XmlNode objXmlLifestyle = objXmlLifestyleDocument.SelectSingleNode("/chummer/lifestyles/lifestyle[name = \"Cyberzombie Lifestyle Addition\"]");

                TreeNode objLifestyleNode = new TreeNode();
                Lifestyle objLifestyle = new Lifestyle(_objCharacter);
                objLifestyle.Create(objXmlLifestyle, objLifestyleNode);
                _objCharacter.Lifestyles.Add(objLifestyle);

                treLifestyles.Nodes[0].Nodes.Add(objLifestyleNode);
                treLifestyles.Nodes[0].Expand();
            }

            // Change the MetatypeCategory to Cyberzombie.
            _objCharacter.MetatypeCategory = "Cyberzombie";

            // Gain access to Critter Powers.
            _objCharacter.CritterEnabled = true;

            // Gain the Dual Natured Critter Power if it does not yet exist.
            bool blnHasPower = false;
            foreach (CritterPower objPower in _objCharacter.CritterPowers)
            {
                if (objPower.Name == "Dual Natured")
                    blnHasPower = true;
            }
            if (!blnHasPower)
            {
                XmlDocument objXmlPowerDocument = XmlManager.Instance.Load("critterpowers.xml");
                XmlNode objXmlPowerNode = objXmlPowerDocument.SelectSingleNode("/chummer/powers/power[name = \"Dual Natured\"]");

                TreeNode objNode = new TreeNode();
                CritterPower objCritterPower = new CritterPower(_objCharacter);
                objCritterPower.Create(objXmlPowerNode, _objCharacter, objNode);
                _objCharacter.CritterPowers.Add(objCritterPower);

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

            // Gain the Immunity (Normal Weapons) Critter Power if it does not yet exist.
            blnHasPower = false;
            foreach (CritterPower objPower in _objCharacter.CritterPowers)
            {
                if (objPower.Name == "Immunity" && objPower.Extra == "Normal Weapons")
                    blnHasPower = true;
            }
            if (!blnHasPower)
            {
                XmlDocument objXmlPowerDocument = XmlManager.Instance.Load("critterpowers.xml");
                XmlNode objXmlPowerNode = objXmlPowerDocument.SelectSingleNode("/chummer/powers/power[name = \"Immunity\"]");

                TreeNode objNode = new TreeNode();
                CritterPower objCritterPower = new CritterPower(_objCharacter);
                objCritterPower.Create(objXmlPowerNode, _objCharacter, objNode, 0, "Normal Weapons");
                _objCharacter.CritterPowers.Add(objCritterPower);

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

            mnuSpecialCyberzombie.Visible = false;

            _blnIsDirty = true;
            UpdateWindowTitle();

            UpdateCharacterInfo();
        }
Example #9
0
        /// <summary>
        /// Create a Critter, put them into Career Mode, link them, and open the newly-created Critter.
        /// </summary>
        /// <param name="strCritterName">Name of the Critter's Metatype.</param>
        /// <param name="intForce">Critter's Force.</param>
        private void CreateCritter(string strCritterName, int intForce)
        {
            // The Critter should use the same settings file as the character.
            Character objCharacter = new Character();
            objCharacter.SettingsFile = _objSpirit.CharacterObject.SettingsFile;

            // Override the defaults for the setting.
            objCharacter.IgnoreRules = true;
            objCharacter.IsCritter = true;
            objCharacter.BuildMethod = CharacterBuildMethod.Karma;
            objCharacter.BuildPoints = 0;

            if (txtCritterName.Text != string.Empty)
                objCharacter.Name = txtCritterName.Text;

            // Make sure that Running Wild is one of the allowed source books since most of the Critter Powers come from this book.
            bool blnRunningWild = false;
            blnRunningWild = (objCharacter.Options.Books.Contains("RW"));

            if (!blnRunningWild)
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_Main_RunningWild"), LanguageManager.Instance.GetString("MessageTitle_Main_RunningWild"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // Ask the user to select a filename for the new character.
            string strForce = LanguageManager.Instance.GetString("String_Force");
            if (_objSpirit.EntityType == SpiritType.Sprite)
                strForce = LanguageManager.Instance.GetString("String_Rating");
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*";
            saveFileDialog.FileName = strCritterName + " (" + strForce + " " + _objSpirit.Force.ToString() + ").chum5";
            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                string strFileName = saveFileDialog.FileName;
                objCharacter.FileName = strFileName;
            }
            else
                return;

            // Code from frmMetatype.
            ImprovementManager objImprovementManager = new ImprovementManager(objCharacter);
            XmlDocument objXmlDocument = XmlManager.Instance.Load("critters.xml");

            XmlNode objXmlMetatype = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + strCritterName + "\"]");

            // If the Critter could not be found, show an error and get out of here.
            if (objXmlMetatype == null)
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_UnknownCritterType").Replace("{0}", strCritterName), LanguageManager.Instance.GetString("MessageTitle_SelectCritterType"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Set Metatype information.
            if (strCritterName == "Ally Spirit")
            {
                objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }
            else
            {
                int intMinModifier = -3;
                if (objXmlMetatype["category"].InnerText == "Mutant Critters")
                    intMinModifier = 0;
                objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }

            // If we're working with a Critter, set the Attributes to their default values.
            objCharacter.BOD.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
            objCharacter.AGI.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
            objCharacter.REA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
            objCharacter.STR.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
            objCharacter.CHA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
            objCharacter.INT.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
            objCharacter.LOG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
            objCharacter.WIL.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
            objCharacter.MAG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
            objCharacter.RES.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
            objCharacter.EDG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
            objCharacter.ESS.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));

            // Sprites can never have Physical Attributes or WIL.
            if (objXmlMetatype["category"].InnerText.EndsWith("Sprite"))
            {
                objCharacter.BOD.AssignLimits("0", "0", "0");
                objCharacter.AGI.AssignLimits("0", "0", "0");
                objCharacter.REA.AssignLimits("0", "0", "0");
                objCharacter.STR.AssignLimits("0", "0", "0");
                objCharacter.WIL.AssignLimits("0", "0", "0");
                objCharacter.INI.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                objCharacter.INI.MetatypeMaximum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
            }

            objCharacter.Metatype = strCritterName;
            objCharacter.MetatypeCategory = objXmlMetatype["category"].InnerText;
            objCharacter.Metavariant = "";
            objCharacter.MetatypeBP = 0;

            if (objXmlMetatype["movement"] != null)
                objCharacter.Movement = objXmlMetatype["movement"].InnerText;
            // Load the Qualities file.
            XmlDocument objXmlQualityDocument = XmlManager.Instance.Load("qualities.xml");

            // Determine if the Metatype has any bonuses.
            if (objXmlMetatype.InnerXml.Contains("bonus"))
                objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metatype, strCritterName, objXmlMetatype.SelectSingleNode("bonus"), false, 1, strCritterName);

            // Create the Qualities that come with the Metatype.
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
            {
                XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                List<Weapon> objWeapons = new List<Weapon>();
                List<TreeNode> objWeaponNodes = new List<TreeNode>();
                Quality objQuality = new Quality(objCharacter);
                string strForceValue = "";
                if (objXmlQualityItem.Attributes["select"] != null)
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                QualitySource objSource = new QualitySource();
                objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"] != null)
                    objSource = QualitySource.MetatypeRemovable;
                objQuality.Create(objXmlQuality, objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                objCharacter.Qualities.Add(objQuality);

                // Add any created Weapons to the character.
                foreach (Weapon objWeapon in objWeapons)
                    objCharacter.Weapons.Add(objWeapon);
            }
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
            {
                XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                List<Weapon> objWeapons = new List<Weapon>();
                List<TreeNode> objWeaponNodes = new List<TreeNode>();
                Quality objQuality = new Quality(objCharacter);
                string strForceValue = "";
                if (objXmlQualityItem.Attributes["select"] != null)
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                QualitySource objSource = new QualitySource();
                objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"] != null)
                    objSource = QualitySource.MetatypeRemovable;
                objQuality.Create(objXmlQuality, objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                objCharacter.Qualities.Add(objQuality);

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

            // Add any Critter Powers the Metatype/Critter should have.
            XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + objCharacter.Metatype + "\"]");

            objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
            foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
            {
                XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                CritterPower objPower = new CritterPower(objCharacter);
                string strForcedValue = "";
                int intRating = 0;

                if (objXmlPower.Attributes["rating"] != null)
                    intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                if (objXmlPower.Attributes["select"] != null)
                    strForcedValue = objXmlPower.Attributes["select"].InnerText;

                objPower.Create(objXmlCritterPower, objCharacter, objNode, intRating, strForcedValue);
                objCharacter.CritterPowers.Add(objPower);
            }

            // Set the Skill Ratings for the Critter.
            foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/skill"))
            {
                if (objXmlSkill.InnerText.Contains("Exotic"))
                {
                    Skill objExotic = new Skill(objCharacter);
                    objExotic.ExoticSkill = true;
                    objExotic.Attribute = "AGI";
                    if (objXmlSkill.Attributes["spec"] != null)
                    {
                        SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                        objExotic.Specializations.Add(objSpec);
                    }
                    if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
                        objExotic.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                    objExotic.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                    objExotic.Name = objXmlSkill.InnerText;
                    objCharacter.Skills.Add(objExotic);
                }
                else
                {
                    foreach (Skill objSkill in objCharacter.Skills)
                    {
                        if (objSkill.Name == objXmlSkill.InnerText)
                        {
                            if (objXmlSkill.Attributes["spec"] != null)
                            {
                                SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                                objSkill.Specializations.Add(objSpec);
                            }
                            if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
                                objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                            objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                            break;
                        }
                    }
                }
            }

            // Set the Skill Group Ratings for the Critter.
            foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/group"))
            {
                foreach (SkillGroup objSkill in objCharacter.SkillGroups)
                {
                    if (objSkill.Name == objXmlSkill.InnerText)
                    {
                        objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                        objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                        break;
                    }
                }
            }

            // Set the Knowledge Skill Ratings for the Critter.
            foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/knowledge"))
            {
                Skill objKnowledge = new Skill(objCharacter);
                objKnowledge.Name = objXmlSkill.InnerText;
                objKnowledge.KnowledgeSkill = true;
                if (objXmlSkill.Attributes["spec"] != null)
                {
                    SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                    objKnowledge.Specializations.Add(objSpec);
                }
                objKnowledge.SkillCategory = objXmlSkill.Attributes["category"].InnerText;
                if (Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText) > 6)
                    objKnowledge.RatingMaximum = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                objKnowledge.Rating = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                objCharacter.Skills.Add(objKnowledge);
            }

            // If this is a Critter with a Force (which dictates their Skill Rating/Maximum Skill Rating), set their Skill Rating Maximums.
            if (intForce > 0)
            {
                int intMaxRating = intForce;
                // Determine the highest Skill Rating the Critter has.
                foreach (Skill objSkill in objCharacter.Skills)
                {
                    if (objSkill.RatingMaximum > intMaxRating)
                        intMaxRating = objSkill.RatingMaximum;
                }

                // Now that we know the upper limit, set all of the Skill Rating Maximums to match.
                foreach (Skill objSkill in objCharacter.Skills)
                    objSkill.RatingMaximum = intMaxRating;
                foreach (SkillGroup objGroup in objCharacter.SkillGroups)
                    objGroup.RatingMaximum = intMaxRating;

                // Set the MaxSkillRating for the character so it can be used later when they add new Knowledge Skills or Exotic Skills.
                objCharacter.MaxSkillRating = intMaxRating;
            }

            // Add any Complex Forms the Critter comes with (typically Sprites)
            XmlDocument objXmlProgramDocument = XmlManager.Instance.Load("complexforms.xml");
            foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
            {
                string strForceValue = "";
                if (objXmlComplexForm.Attributes["select"] != null)
                    strForceValue = objXmlComplexForm.Attributes["select"].InnerText;
                XmlNode objXmlProgram = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlComplexForm.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                ComplexForm objProgram = new ComplexForm(objCharacter);
                objProgram.Create(objXmlProgram, objCharacter, objNode, strForceValue);
                objCharacter.ComplexForms.Add(objProgram);
            }

            // Add any Gear the Critter comes with (typically Programs for A.I.s)
            XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");
            foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
            {
                int intRating = 0;
                if (objXmlGear.Attributes["rating"] != null)
                    intRating = Convert.ToInt32(ExpressionToString(objXmlGear.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                string strForceValue = "";
                if (objXmlGear.Attributes["select"] != null)
                    strForceValue = objXmlGear.Attributes["select"].InnerText;
                XmlNode objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                Gear objGear = new Gear(objCharacter);
                List<Weapon> lstWeapons = new List<Weapon>();
                List<TreeNode> lstWeaponNodes = new List<TreeNode>();
                objGear.Create(objXmlGearItem, objCharacter, objNode, intRating, lstWeapons, lstWeaponNodes, strForceValue);
                objGear.Cost = "0";
                objGear.Cost3 = "0";
                objGear.Cost6 = "0";
                objGear.Cost10 = "0";
                objCharacter.Gear.Add(objGear);
            }

            // If this is a Mutant Critter, count up the number of Skill points they start with.
            if (objCharacter.MetatypeCategory == "Mutant Critters")
            {
                foreach (Skill objSkill in objCharacter.Skills)
                    objCharacter.MutantCritterBaseSkills += objSkill.Rating;
            }

            // Add the Unarmed Attack Weapon to the character.
            try
            {
                objXmlDocument = XmlManager.Instance.Load("weapons.xml");
                XmlNode objXmlWeapon = objXmlDocument.SelectSingleNode("/chummer/weapons/weapon[name = \"Unarmed Attack\"]");
                TreeNode objDummy = new TreeNode();
                Weapon objWeapon = new Weapon(objCharacter);
                objWeapon.Create(objXmlWeapon, objCharacter, objDummy, null, null, null);
                objCharacter.Weapons.Add(objWeapon);
            }
            catch
            {
            }

            objCharacter.Alias = strCritterName;
            objCharacter.Created = true;
            objCharacter.Save();

            string strOpenFile = objCharacter.FileName;
            objCharacter = null;

            // Link the newly-created Critter to the Spirit.
            _objSpirit.FileName = strOpenFile;
            if (_objSpirit.EntityType == SpiritType.Spirit)
                tipTooltip.SetToolTip(imgLink, LanguageManager.Instance.GetString("Tip_Spirit_OpenFile"));
            else
                tipTooltip.SetToolTip(imgLink, LanguageManager.Instance.GetString("Tip_Sprite_OpenFile"));
            FileNameChanged(this);

            GlobalOptions.Instance.MainForm.LoadCharacter(strOpenFile, true);
        }
Example #10
0
        void TestMetatype(string strFile)
        {
            XmlDocument objXmlDocument = XmlManager.Load(strFile);

            pgbProgress.Minimum = 0;
            pgbProgress.Value   = 0;
            pgbProgress.Maximum = objXmlDocument.SelectNodes("/chummer/metatypes/metatype").Count;

            foreach (XmlNode objXmlMetatype in objXmlDocument.SelectNodes("/chummer/metatypes/metatype"))
            {
                pgbProgress.Value++;
                Application.DoEvents();

                objXmlDocument = XmlManager.Load(strFile);
                Character objCharacter = new Character();

                try
                {
                    int intForce = 0;
                    if (objXmlMetatype["forcecreature"] != null)
                    {
                        intForce = 1;
                    }

                    // Set Metatype information.
                    if (strFile != "critters.xml" || objXmlMetatype["name"].InnerText == "Ally Spirit")
                    {
                        objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                        objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                        objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                        objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                        objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                        objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                        objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                        objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                        objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                        objCharacter.MAGAdept.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                        objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                        objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                        objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                        objCharacter.DEP.AssignLimits(ExpressionToString(objXmlMetatype["depmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["depmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["depaug"].InnerText, intForce, 0));
                    }
                    else
                    {
                        int intMinModifier = -3;
                        objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                        objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                        objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                        objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                        objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                        objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                        objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                        objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                        objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                        objCharacter.MAGAdept.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                        objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                        objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                        objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                        objCharacter.DEP.AssignLimits(ExpressionToString(objXmlMetatype["depmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["depmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["depmin"].InnerText, intForce, 3));
                    }

                    /* If we're working with a Critter, set the Attributes to their default values.
                     * if (strFile == "critters.xml")
                     * {
                     *  _objCharacter.BOD.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
                     *  _objCharacter.AGI.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
                     *  _objCharacter.REA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
                     *  _objCharacter.STR.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
                     *  _objCharacter.CHA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
                     *  _objCharacter.INT.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
                     *  _objCharacter.LOG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
                     *  _objCharacter.WIL.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
                     *  _objCharacter.MAG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
                     *  _objCharacter.RES.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
                     *  _objCharacter.EDG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
                     *  _objCharacter.ESS.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));
                     *  _objCharacter.DEP.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["depmin"].InnerText, intForce, 0));
                     * }
                     *
                     * // Sprites can never have Physical Attributes or WIL.
                     * if (objXmlMetatype["name"].InnerText.EndsWith("Sprite"))
                     * {
                     *  _objCharacter.BOD.AssignLimits("0", "0", "0");
                     *  _objCharacter.AGI.AssignLimits("0", "0", "0");
                     *  _objCharacter.REA.AssignLimits("0", "0", "0");
                     *  _objCharacter.STR.AssignLimits("0", "0", "0");
                     * }
                     *
                     * _objCharacter.Metatype = objXmlMetatype["name"].InnerText;
                     * _objCharacter.MetatypeCategory = objXmlMetatype["category"].InnerText;
                     * _objCharacter.Metavariant = string.Empty;
                     * _objCharacter.MetatypeBP = 400;
                     *
                     * if (objXmlMetatype["movement"] != null)
                     *  _objCharacter.Movement = objXmlMetatype["movement"].InnerText;
                     * // Load the Qualities file.
                     * XmlDocument objXmlQualityDocument = XmlManager.Load("qualities.xml");
                     *
                     * // Determine if the Metatype has any bonuses.
                     * if (objXmlMetatype.InnerXml.Contains("bonus"))
                     *  objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metatype, objXmlMetatype["name"].InnerText, objXmlMetatype.SelectSingleNode("bonus"), false, 1, objXmlMetatype["name"].InnerText);
                     *
                     * // Create the Qualities that come with the Metatype.
                     * foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
                     * {
                     *  XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                     *  List<Weapon> lstWeapons = new List<Weapon>();
                     *  Quality objQuality = new Quality(_objCharacter);
                     *  string strForceValue = string.Empty;
                     *  if (objXmlQualityItem.Attributes["select"] != null)
                     *      strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                     *  QualitySource objSource = new QualitySource();
                     *  objSource = QualitySource.Metatype;
                     *  if (objXmlQualityItem.Attributes["removable"] != null)
                     *      objSource = QualitySource.MetatypeRemovable;
                     *  objQuality.Create(objXmlQuality, _objCharacter, objSource, lstWeapons, strForceValue);
                     *  _objCharacter.Qualities.Add(objQuality);
                     * }
                     * foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
                     * {
                     *  XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                     *  List<Weapon> lstWeapons = new List<Weapon>();
                     *  Quality objQuality = new Quality(_objCharacter);
                     *  string strForceValue = string.Empty;
                     *  if (objXmlQualityItem.Attributes["select"] != null)
                     *      strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                     *  QualitySource objSource = new QualitySource();
                     *  objSource = QualitySource.Metatype;
                     *  if (objXmlQualityItem.Attributes["removable"] != null)
                     *      objSource = QualitySource.MetatypeRemovable;
                     *  objQuality.Create(objXmlQuality, _objCharacter, objSource, lstWeapons, strForceValue);
                     *  _objCharacter.Qualities.Add(objQuality);
                     * }
                     *
                     * /* Run through the character's Attributes one more time and make sure their value matches their minimum value.
                     * if (strFile == "metatypes.xml")
                     * {
                     *  _objCharacter.BOD.Value = _objCharacter.BOD.TotalMinimum;
                     *  _objCharacter.AGI.Value = _objCharacter.AGI.TotalMinimum;
                     *  _objCharacter.REA.Value = _objCharacter.REA.TotalMinimum;
                     *  _objCharacter.STR.Value = _objCharacter.STR.TotalMinimum;
                     *  _objCharacter.CHA.Value = _objCharacter.CHA.TotalMinimum;
                     *  _objCharacter.INT.Value = _objCharacter.INT.TotalMinimum;
                     *  _objCharacter.LOG.Value = _objCharacter.LOG.TotalMinimum;
                     *  _objCharacter.WIL.Value = _objCharacter.WIL.TotalMinimum;
                     * }*/

                    // Add any Critter Powers the Metatype/Critter should have.
                    XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + objCharacter.Metatype + "\"]");

                    objXmlDocument = XmlManager.Load("critterpowers.xml");
                    foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
                    {
                        XmlNode      objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                        CritterPower objPower           = new CritterPower(objCharacter);
                        string       strForcedValue     = objXmlPower.Attributes?["select"]?.InnerText ?? string.Empty;
                        int          intRating          = 0;

                        if (objXmlPower.Attributes["rating"] != null)
                        {
                            intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                        }

                        objPower.Create(objXmlCritterPower, intRating, strForcedValue);
                        objCharacter.CritterPowers.Add(objPower);
                    }

                    // Set the Skill Ratings for the Critter.
                    foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/skill"))
                    {
                        if (objXmlSkill.InnerText.Contains("Exotic"))
                        {
                            //Skill objExotic = new Skill(_objCharacter);
                            //objExotic.ExoticSkill = true;
                            //objExotic.Attribute = "AGI";
                            //if (objXmlSkill.Attributes["spec"] != null)
                            //{
                            //SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                            //objExotic.Specializations.Add(objSpec);
                            //}
                            //if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0)) > 6)
                            //    objExotic.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                            //objExotic.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                            //objExotic.Name = objXmlSkill.InnerText;
                            //_objCharacter.Skills.Add(objExotic);
                        }
                        else
                        {
                            foreach (Skill objSkill in objCharacter.SkillsSection.Skills)
                            {
                                if (objSkill.Name == objXmlSkill.InnerText)
                                {
                                    if (objXmlSkill.Attributes["spec"] != null)
                                    {
                                        //SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                                        //objSkill.Specializations.Add(objSpec);
                                    }
                                    //if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0)) > 6)
                                    //    objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                                    //objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                                    break;
                                }
                            }
                        }
                    }

                    //TODO: Sorry, whenever we get critter book...
                    // Set the Skill Group Ratings for the Critter.
                    //foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/group"))
                    //{
                    //    foreach (SkillGroup objSkill in _objCharacter.SkillGroups)
                    //    {
                    //        if (objSkill.Name == objXmlSkill.InnerText)
                    //        {
                    //            objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                    //            objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                    //            break;
                    //        }
                    //    }
                    //}

                    // Set the Knowledge Skill Ratings for the Critter.
                    //foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/knowledge"))
                    //{
                    //    Skill objKnowledge = new Skill(_objCharacter);
                    //    objKnowledge.Name = objXmlSkill.InnerText;
                    //    objKnowledge.KnowledgeSkill = true;
                    //    if (objXmlSkill.Attributes["spec"] != null)
                    //                   {
                    //                       //SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                    //                       //objKnowledge.Specializations.Add(objSpec);
                    //                   }
                    //    objKnowledge.SkillCategory = objXmlSkill.Attributes["category"].InnerText;
                    //    //if (Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText) > 6)
                    //    //    objKnowledge.RatingMaximum = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                    //    //objKnowledge.Rating = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                    //    _objCharacter.Skills.Add(objKnowledge);
                    //}

                    // If this is a Critter with a Force (which dictates their Skill Rating/Maximum Skill Rating), set their Skill Rating Maximums.
                    if (intForce > 0)
                    {
                        int intMaxRating = intForce;
                        // Determine the highest Skill Rating the Critter has.
                        foreach (Skill objSkill in objCharacter.SkillsSection.Skills)
                        {
                            if (objSkill.RatingMaximum > intMaxRating)
                            {
                                intMaxRating = objSkill.RatingMaximum;
                            }
                        }

                        // Now that we know the upper limit, set all of the Skill Rating Maximums to match.
                        //foreach (Skill objSkill in _objCharacter.Skills)
                        //    objSkill.RatingMaximum = intMaxRating;
                        //foreach (SkillGroup objGroup in _objCharacter.SkillGroups)
                        //    objGroup.RatingMaximum = intMaxRating;

                        // Set the MaxSkillRating for the character so it can be used later when they add new Knowledge Skills or Exotic Skills.
                    }

                    // Add any Complex Forms the Critter comes with (typically Sprites)
                    XmlDocument objXmlProgramDocument = XmlManager.Load("complexforms.xml");
                    foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
                    {
                        int intRating = 0;
                        if (objXmlComplexForm.Attributes["rating"] != null)
                        {
                            intRating = ExpressionToInt(objXmlComplexForm.Attributes["rating"].InnerText, intForce, 0);
                        }
                        string      strForceValue         = objXmlComplexForm.Attributes?["select"]?.InnerText ?? string.Empty;
                        XmlNode     objXmlComplexFormData = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlComplexForm.InnerText + "\"]");
                        ComplexForm objComplexForm        = new ComplexForm(objCharacter);
                        objComplexForm.Create(objXmlComplexFormData, strForceValue);
                        objCharacter.ComplexForms.Add(objComplexForm);
                    }

                    // Add any Gear the Critter comes with (typically Programs for A.I.s)
                    XmlDocument objXmlGearDocument = XmlManager.Load("gear.xml");
                    foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
                    {
                        int intRating = 0;
                        if (objXmlGear.Attributes["rating"] != null)
                        {
                            intRating = ExpressionToInt(objXmlGear.Attributes["rating"].InnerText, intForce, 0);
                        }
                        string        strForceValue  = objXmlGear.Attributes?["select"]?.InnerText ?? string.Empty;
                        XmlNode       objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear.InnerText + "\"]");
                        Gear          objGear        = new Gear(objCharacter);
                        List <Weapon> lstWeapons     = new List <Weapon>();
                        objGear.Create(objXmlGearItem, intRating, lstWeapons, strForceValue);
                        objGear.Cost = "0";
                        objCharacter.Gear.Add(objGear);
                    }
                }
                catch
                {
                    txtOutput.Text += objCharacter.Metatype + " general failure\r\n";
                }

                objCharacter.DeleteCharacter();
            }
        }
Example #11
0
        /// <summary>
        /// A Metatype has been selected, so fill in all of the necessary Character information.
        /// </summary>
        void MetatypeSelected()
        {
            if (lstMetatypes.Text != "")
            {
                ImprovementManager objImprovementManager = new ImprovementManager(_objCharacter);
                XmlDocument objXmlDocument = XmlManager.Instance.Load(_strXmlFile);
                XmlNode objXmlMetatype = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + lstMetatypes.SelectedValue + "\"]");
                XmlNode objXmlMetavariant = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + lstMetatypes.SelectedValue + "\"]/metavariants/metavariant[name = \"" + cboMetavariant.SelectedValue + "\"]");
                int intForce = 0;
                if (nudForce.Visible)
                    intForce = Convert.ToInt32(nudForce.Value);

                // Set Metatype information.

                if (cboMetavariant.SelectedValue.ToString() != "None")
                {
                    _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetavariant["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["bodaug"].InnerText, intForce, 0));
                    _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetavariant["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["agiaug"].InnerText, intForce, 0));
                    _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetavariant["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["reaaug"].InnerText, intForce, 0));
                    _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetavariant["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["straug"].InnerText, intForce, 0));
                    _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetavariant["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["chaaug"].InnerText, intForce, 0));
                    _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetavariant["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["intaug"].InnerText, intForce, 0));
                    _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetavariant["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["logaug"].InnerText, intForce, 0));
                    _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetavariant["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["wilaug"].InnerText, intForce, 0));
                    _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetavariant["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["iniaug"].InnerText, intForce, 0));
                    _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetavariant["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["magaug"].InnerText, intForce, 0));
                    _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetavariant["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["resaug"].InnerText, intForce, 0));
                    _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetavariant["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["edgaug"].InnerText, intForce, 0));
                    _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetavariant["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["essaug"].InnerText, intForce, 0));
                }
                else if (_strXmlFile != "critters.xml" || lstMetatypes.SelectedValue.ToString() == "Ally Spirit")
                {
                    _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                    _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                    _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                    _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                    _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                    _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                    _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                    _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                    _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                    _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                    _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                    _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                    _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                }
                else
                {
                    int intMinModifier = -3;
                    if (cboCategory.SelectedValue.ToString() == "Mutant Critters")
                        intMinModifier = 0;
                    _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                    _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                    _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                    _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                    _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                    _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                    _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                    _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                    _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                    _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                    _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                    _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                    _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                }

                // If we're working with a Critter, set the Attributes to their default values.
                if (_strXmlFile == "critters.xml")
                {
                    _objCharacter.BOD.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
                    _objCharacter.AGI.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
                    _objCharacter.REA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
                    _objCharacter.STR.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
                    _objCharacter.CHA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
                    _objCharacter.INT.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
                    _objCharacter.LOG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
                    _objCharacter.WIL.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
                    _objCharacter.MAG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
                    _objCharacter.RES.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
                    _objCharacter.EDG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
                    _objCharacter.ESS.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));
                }

                // Sprites can never have Physical Attributes or WIL.
                if (lstMetatypes.SelectedValue.ToString().EndsWith("Sprite"))
                {
                    _objCharacter.BOD.AssignLimits("0", "0", "0");
                    _objCharacter.AGI.AssignLimits("0", "0", "0");
                    _objCharacter.REA.AssignLimits("0", "0", "0");
                    _objCharacter.STR.AssignLimits("0", "0", "0");
                    _objCharacter.WIL.AssignLimits("0", "0", "0");
                    _objCharacter.INI.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                    _objCharacter.INI.MetatypeMaximum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                }

                // If this is a Shapeshifter, a Metavariant must be selected. Default to Human if None is selected.
                if (cboCategory.SelectedValue.ToString() == "Shapeshifter" && cboMetavariant.SelectedValue.ToString() == "None")
                    cboMetavariant.SelectedValue = "Human";

                _objCharacter.Metatype = lstMetatypes.SelectedValue.ToString();
                _objCharacter.MetatypeCategory = cboCategory.SelectedValue.ToString();
                if (cboMetavariant.SelectedValue.ToString() == "None")
                {
                    _objCharacter.Metavariant = "";
                    _objCharacter.MetatypeBP = Convert.ToInt32(lblBP.Text);
                }
                else
                {
                    _objCharacter.Metavariant = cboMetavariant.SelectedValue.ToString();
                    _objCharacter.MetatypeBP = Convert.ToInt32(lblMetavariantBP.Text);
                }

                if (objXmlMetatype["movement"] != null)
                    _objCharacter.Movement = objXmlMetatype["movement"].InnerText;
                // Load the Qualities file.
                XmlDocument objXmlQualityDocument = XmlManager.Instance.Load("qualities.xml");

                if (cboMetavariant.SelectedValue.ToString() == "None")
                {
                    // Determine if the Metatype has any bonuses.
                    if (objXmlMetatype.InnerXml.Contains("bonus"))
                        objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metatype, lstMetatypes.SelectedValue.ToString(), objXmlMetatype.SelectSingleNode("bonus"), false, 1, lstMetatypes.SelectedValue.ToString());

                    // Create the Qualities that come with the Metatype.
                    foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

                        // Add any created Weapons to the character.
                        foreach (Weapon objWeapon in objWeapons)
                            _objCharacter.Weapons.Add(objWeapon);
                    }
                    foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

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

                // If a Metavariant has been selected, locate it in the file.
                if (cboMetavariant.SelectedValue.ToString() != "None")
                {
                    // Determine if the Metavariant has any bonuses.
                    if (objXmlMetavariant.InnerXml.Contains("bonus"))
                    {
                        objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metavariant, cboMetavariant.SelectedValue.ToString(), objXmlMetavariant.SelectSingleNode("bonus"), false, 1, cboMetavariant.SelectedValue.ToString());
                    }

                    // Create the Qualities that come with the Metatype.
                    foreach (XmlNode objXmlQualityItem in objXmlMetavariant.SelectNodes("qualities/positive/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

                        // Add any created Weapons to the character.
                        foreach (Weapon objWeapon in objWeapons)
                            _objCharacter.Weapons.Add(objWeapon);
                    }
                    foreach (XmlNode objXmlQualityItem in objXmlMetavariant.SelectNodes("qualities/negative/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

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

                // Run through the character's Attributes one more time and make sure their value matches their minimum value.
                if (_strXmlFile == "metatypes.xml")
                {
                    _objCharacter.BOD.Value = _objCharacter.BOD.TotalMinimum;
                    _objCharacter.AGI.Value = _objCharacter.AGI.TotalMinimum;
                    _objCharacter.REA.Value = _objCharacter.REA.TotalMinimum;
                    _objCharacter.STR.Value = _objCharacter.STR.TotalMinimum;
                    _objCharacter.CHA.Value = _objCharacter.CHA.TotalMinimum;
                    _objCharacter.INT.Value = _objCharacter.INT.TotalMinimum;
                    _objCharacter.LOG.Value = _objCharacter.LOG.TotalMinimum;
                    _objCharacter.WIL.Value = _objCharacter.WIL.TotalMinimum;
                }

                // Add any Critter Powers the Metatype/Critter should have.
                XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");

                objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
                foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
                {
                    XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                    TreeNode objNode = new TreeNode();
                    CritterPower objPower = new CritterPower(_objCharacter);
                    string strForcedValue = "";
                    int intRating = 0;

                    if (objXmlPower.Attributes["rating"] != null)
                        intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                    if (objXmlPower.Attributes["select"] != null)
                        strForcedValue = objXmlPower.Attributes["select"].InnerText;

                    objPower.Create(objXmlCritterPower, _objCharacter, objNode, intRating, strForcedValue);
                    objPower.CountTowardsLimit = false;
                    _objCharacter.CritterPowers.Add(objPower);
                }

                // Add any Critter Powers the Metavariant should have.
                if (cboMetavariant.SelectedValue.ToString() != "None")
                {
                    foreach (XmlNode objXmlPower in objXmlMetavariant.SelectNodes("powers/power"))
                    {
                        XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        CritterPower objPower = new CritterPower(_objCharacter);
                        string strForcedValue = "";
                        int intRating = 0;

                        if (objXmlPower.Attributes["rating"] != null)
                            intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                        if (objXmlPower.Attributes["select"] != null)
                            strForcedValue = objXmlPower.Attributes["select"].InnerText;

                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, intRating, strForcedValue);
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }
                }

                // If this is a Blood Spirit, add their free Critter Powers.
                if (chkBloodSpirit.Checked)
                {
                    XmlNode objXmlCritterPower;
                    TreeNode objNode;
                    CritterPower objPower;
                    bool blnAddPower = true;

                    // Energy Drain.
                    foreach (CritterPower objFindPower in _objCharacter.CritterPowers)
                    {
                        if (objFindPower.Name == "Energy Drain")
                        {
                            blnAddPower = false;
                            break;
                        }
                    }
                    if (blnAddPower)
                    {
                        objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Energy Drain\"]");
                        objNode = new TreeNode();
                        objPower = new CritterPower(_objCharacter);
                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }

                    // Fear.
                    blnAddPower = true;
                    foreach (CritterPower objFindPower in _objCharacter.CritterPowers)
                    {
                        if (objFindPower.Name == "Fear")
                        {
                            blnAddPower = false;
                            break;
                        }
                    }
                    if (blnAddPower)
                    {
                        objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Fear\"]");
                        objNode = new TreeNode();
                        objPower = new CritterPower(_objCharacter);
                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }

                    // Natural Weapon.
                    objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Natural Weapon\"]");
                    objNode = new TreeNode();
                    objPower = new CritterPower(_objCharacter);
                    objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "DV " + intForce.ToString() + "P, AP 0");
                    objPower.CountTowardsLimit = false;
                    _objCharacter.CritterPowers.Add(objPower);

                    // Evanescence.
                    blnAddPower = true;
                    foreach (CritterPower objFindPower in _objCharacter.CritterPowers)
                    {
                        if (objFindPower.Name == "Evanescence")
                        {
                            blnAddPower = false;
                            break;
                        }
                    }
                    if (blnAddPower)
                    {
                        objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Evanescence\"]");
                        objNode = new TreeNode();
                        objPower = new CritterPower(_objCharacter);
                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }
                }

                // Remove the Critter's Materialization Power if they have it. Add the Possession or Inhabitation Power if the Possession-based Tradition checkbox is checked.
                if (chkPossessionBased.Checked)
                {
                    foreach (CritterPower objCritterPower in _objCharacter.CritterPowers)
                    {
                        if (objCritterPower.Name == "Materialization")
                        {
                            _objCharacter.CritterPowers.Remove(objCritterPower);
                            break;
                        }
                    }

                    // Add the selected Power.
                    XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + cboPossessionMethod.SelectedValue.ToString() + "\"]");
                    TreeNode objNode = new TreeNode();
                    CritterPower objPower = new CritterPower(_objCharacter);
                    objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                    objPower.CountTowardsLimit = false;
                    _objCharacter.CritterPowers.Add(objPower);
                }

                // Set the Skill Ratings for the Critter.
                foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/skill"))
                {
                    if (objXmlSkill.InnerText.Contains("Exotic"))
                    {
                        Skill objExotic = new Skill(_objCharacter);
                        objExotic.ExoticSkill = true;
                        objExotic.Attribute = "AGI";
                        if (objXmlSkill.Attributes["spec"] != null)
                        {
                            SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                            objExotic.Specializations.Add(objSpec);
                        }
                        if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
                            objExotic.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                        objExotic.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                        objExotic.Name = objXmlSkill.InnerText;
                        _objCharacter.Skills.Add(objExotic);
                    }
                    else
                    {
                        foreach (Skill objSkill in _objCharacter.Skills)
                        {
                            if (objSkill.Name == objXmlSkill.InnerText)
                            {
                                if (objXmlSkill.Attributes["spec"] != null)
                                {
                                    SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                                    objSkill.Specializations.Add(objSpec);
                                }
                                if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
                                    objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                                objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                                break;
                            }
                        }
                    }
                }

                // Set the Skill Group Ratings for the Critter.
                foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/group"))
                {
                    foreach (SkillGroup objSkill in _objCharacter.SkillGroups)
                    {
                        if (objSkill.Name == objXmlSkill.InnerText)
                        {
                            objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                            objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                            break;
                        }
                    }
                }

                // Set the Knowledge Skill Ratings for the Critter.
                foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/knowledge"))
                {
                    Skill objKnowledge = new Skill(_objCharacter);
                    objKnowledge.Name = objXmlSkill.InnerText;
                    objKnowledge.KnowledgeSkill = true;
                    if (objXmlSkill.Attributes["spec"] != null)
                    {
                        SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                        objKnowledge.Specializations.Add(objSpec);
                    }
                    objKnowledge.SkillCategory = objXmlSkill.Attributes["category"].InnerText;
             					if (Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText) > 6)
                        objKnowledge.RatingMaximum = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                    objKnowledge.Rating = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                    _objCharacter.Skills.Add(objKnowledge);
                }

                // If this is a Critter with a Force (which dictates their Skill Rating/Maximum Skill Rating), set their Skill Rating Maximums.
                if (intForce > 0)
                {
                    int intMaxRating = intForce;
                    // Determine the highest Skill Rating the Critter has.
                    foreach (Skill objSkill in _objCharacter.Skills)
                    {
                        if (objSkill.RatingMaximum > intMaxRating)
                            intMaxRating = objSkill.RatingMaximum;
                    }

                    // Now that we know the upper limit, set all of the Skill Rating Maximums to match.
                    foreach (Skill objSkill in _objCharacter.Skills)
                        objSkill.RatingMaximum = intMaxRating;
                    foreach (SkillGroup objGroup in _objCharacter.SkillGroups)
                        objGroup.RatingMaximum = intMaxRating;

                    // Set the MaxSkillRating for the character so it can be used later when they add new Knowledge Skills or Exotic Skills.
                    _objCharacter.MaxSkillRating = intMaxRating;
                }

                // Add any Complex Forms the Critter comes with (typically Sprites)
                XmlDocument objXmlProgramDocument = XmlManager.Instance.Load("complexforms.xml");
                foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
                {
                    string strForceValue = "";
                    if (objXmlComplexForm.Attributes["select"] != null)
                        strForceValue = objXmlComplexForm.Attributes["select"].InnerText;
                    XmlNode objXmlProgram = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlComplexForm.InnerText + "\"]");
                    TreeNode objNode = new TreeNode();
                    ComplexForm objProgram = new ComplexForm(_objCharacter);
                    objProgram.Create(objXmlProgram, _objCharacter, objNode, strForceValue);
                    _objCharacter.ComplexForms.Add(objProgram);
                }

                // Add any Gear the Critter comes with (typically Programs for A.I.s)
                XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");
                foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
                {
                    int intRating = 0;
                    if (objXmlGear.Attributes["rating"] != null)
                        intRating = Convert.ToInt32(ExpressionToString(objXmlGear.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                    string strForceValue = "";
                    if (objXmlGear.Attributes["select"] != null)
                        strForceValue = objXmlGear.Attributes["select"].InnerText;
                    XmlNode objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear.InnerText + "\"]");
                    TreeNode objNode = new TreeNode();
                    Gear objGear = new Gear(_objCharacter);
                    List<Weapon> lstWeapons = new List<Weapon>();
                    List<TreeNode> lstWeaponNodes = new List<TreeNode>();
                    objGear.Create(objXmlGearItem, _objCharacter, objNode, intRating, lstWeapons, lstWeaponNodes, strForceValue);
                    objGear.Cost = "0";
                    objGear.Cost3 = "0";
                    objGear.Cost6 = "0";
                    objGear.Cost10 = "0";
                    _objCharacter.Gear.Add(objGear);
                }

                // If this is a Mutant Critter, count up the number of Skill points they start with.
                if (_objCharacter.MetatypeCategory == "Mutant Critters")
                {
                    foreach (Skill objSkill in _objCharacter.Skills)
                        _objCharacter.MutantCritterBaseSkills += objSkill.Rating;
                }

                if (cboMetavariant.Text != "None")
                {
                    int x = 0;
                       int.TryParse(lblMetavariantBP.Text, out x);
                    //_objCharacter.BuildKarma = _objCharacter.BuildKarma - x;
                }
                else
                {
                    int x = 0;
                       int.TryParse(lblBP.Text, out x);
                    //_objCharacter.BuildKarma = _objCharacter.BuildKarma - x;
                }
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            else
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_Metatype_SelectMetatype"), LanguageManager.Instance.GetString("MessageTitle_Metatype_SelectMetatype"), MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            _objCharacter.Movement = (_objCharacter.AGI.TotalValue * 2).ToString() + "/" + (_objCharacter.AGI.TotalValue * 4).ToString();
        }
Example #12
0
        /// <summary>
        /// Create a Critter, put them into Career Mode, link them, and open the newly-created Critter.
        /// </summary>
        /// <param name="strCritterName">Name of the Critter's Metatype.</param>
        /// <param name="intForce">Critter's Force.</param>
        private void CreateCritter(string strCritterName, int intForce)
        {
            // The Critter should use the same settings file as the character.
            Character objCharacter = new Character();

            objCharacter.SettingsFile = _objSpirit.CharacterObject.SettingsFile;

            // Override the defaults for the setting.
            objCharacter.IgnoreRules = true;
            objCharacter.IsCritter   = true;
            objCharacter.BuildMethod = CharacterBuildMethod.Karma;
            objCharacter.BuildPoints = 0;

            if (txtCritterName.Text != string.Empty)
            {
                objCharacter.Name = txtCritterName.Text;
            }

            // Make sure that Running Wild is one of the allowed source books since most of the Critter Powers come from this book.
            bool blnRunningWild = false;

            blnRunningWild = (objCharacter.Options.Books.Contains("RW"));

            if (!blnRunningWild)
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_Main_RunningWild"), LanguageManager.Instance.GetString("MessageTitle_Main_RunningWild"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // Ask the user to select a filename for the new character.
            string strForce = LanguageManager.Instance.GetString("String_Force");

            if (_objSpirit.EntityType == SpiritType.Sprite)
            {
                strForce = LanguageManager.Instance.GetString("String_Rating");
            }
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Filter   = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*";
            saveFileDialog.FileName = strCritterName + " (" + strForce + " " + _objSpirit.Force.ToString() + ").chum5";
            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                string strFileName = saveFileDialog.FileName;
                objCharacter.FileName = strFileName;
            }
            else
            {
                return;
            }

            // Code from frmMetatype.
            ImprovementManager objImprovementManager = new ImprovementManager(objCharacter);
            XmlDocument        objXmlDocument        = XmlManager.Instance.Load("critters.xml");

            XmlNode objXmlMetatype = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + strCritterName + "\"]");

            // If the Critter could not be found, show an error and get out of here.
            if (objXmlMetatype == null)
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_UnknownCritterType").Replace("{0}", strCritterName), LanguageManager.Instance.GetString("MessageTitle_SelectCritterType"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Set Metatype information.
            if (strCritterName == "Ally Spirit")
            {
                objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }
            else
            {
                int intMinModifier = -3;
                if (objXmlMetatype["category"].InnerText == "Mutant Critters")
                {
                    intMinModifier = 0;
                }
                objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }

            // If we're working with a Critter, set the Attributes to their default values.
            objCharacter.BOD.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
            objCharacter.AGI.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
            objCharacter.REA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
            objCharacter.STR.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
            objCharacter.CHA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
            objCharacter.INT.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
            objCharacter.LOG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
            objCharacter.WIL.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
            objCharacter.MAG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
            objCharacter.RES.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
            objCharacter.EDG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
            objCharacter.ESS.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));

            // Sprites can never have Physical Attributes or WIL.
            if (objXmlMetatype["category"].InnerText.EndsWith("Sprite"))
            {
                objCharacter.BOD.AssignLimits("0", "0", "0");
                objCharacter.AGI.AssignLimits("0", "0", "0");
                objCharacter.REA.AssignLimits("0", "0", "0");
                objCharacter.STR.AssignLimits("0", "0", "0");
                objCharacter.WIL.AssignLimits("0", "0", "0");
                objCharacter.INI.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                objCharacter.INI.MetatypeMaximum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
            }

            objCharacter.Metatype         = strCritterName;
            objCharacter.MetatypeCategory = objXmlMetatype["category"].InnerText;
            objCharacter.Metavariant      = "";
            objCharacter.MetatypeBP       = 0;

            if (objXmlMetatype["movement"] != null)
            {
                objCharacter.Movement = objXmlMetatype["movement"].InnerText;
            }
            // Load the Qualities file.
            XmlDocument objXmlQualityDocument = XmlManager.Instance.Load("qualities.xml");

            // Determine if the Metatype has any bonuses.
            if (objXmlMetatype.InnerXml.Contains("bonus"))
            {
                objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metatype, strCritterName, objXmlMetatype.SelectSingleNode("bonus"), false, 1, strCritterName);
            }

            // Create the Qualities that come with the Metatype.
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
            {
                XmlNode         objXmlQuality  = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode        objNode        = new TreeNode();
                List <Weapon>   objWeapons     = new List <Weapon>();
                List <TreeNode> objWeaponNodes = new List <TreeNode>();
                Quality         objQuality     = new Quality(objCharacter);
                string          strForceValue  = "";
                if (objXmlQualityItem.Attributes["select"] != null)
                {
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                }
                QualitySource objSource = new QualitySource();
                objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"] != null)
                {
                    objSource = QualitySource.MetatypeRemovable;
                }
                objQuality.Create(objXmlQuality, objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                objCharacter.Qualities.Add(objQuality);

                // Add any created Weapons to the character.
                foreach (Weapon objWeapon in objWeapons)
                {
                    objCharacter.Weapons.Add(objWeapon);
                }
            }
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
            {
                XmlNode         objXmlQuality  = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode        objNode        = new TreeNode();
                List <Weapon>   objWeapons     = new List <Weapon>();
                List <TreeNode> objWeaponNodes = new List <TreeNode>();
                Quality         objQuality     = new Quality(objCharacter);
                string          strForceValue  = "";
                if (objXmlQualityItem.Attributes["select"] != null)
                {
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                }
                QualitySource objSource = new QualitySource();
                objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"] != null)
                {
                    objSource = QualitySource.MetatypeRemovable;
                }
                objQuality.Create(objXmlQuality, objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                objCharacter.Qualities.Add(objQuality);

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

            // Add any Critter Powers the Metatype/Critter should have.
            XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + objCharacter.Metatype + "\"]");

            objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
            foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
            {
                XmlNode      objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                TreeNode     objNode            = new TreeNode();
                CritterPower objPower           = new CritterPower(objCharacter);
                string       strForcedValue     = "";
                int          intRating          = 0;

                if (objXmlPower.Attributes["rating"] != null)
                {
                    intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                }
                if (objXmlPower.Attributes["select"] != null)
                {
                    strForcedValue = objXmlPower.Attributes["select"].InnerText;
                }

                objPower.Create(objXmlCritterPower, objCharacter, objNode, intRating, strForcedValue);
                objCharacter.CritterPowers.Add(objPower);
            }

            //TODO, when is this shit required, 4e holdover or need?
            // Set the Skill Ratings for the Critter.
            //foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/skill"))
            //{
            //	if (objXmlSkill.InnerText.Contains("Exotic"))
            //	{
            //		Skill objExotic = new Skill(objCharacter);
            //		objExotic.ExoticSkill = true;
            //		objExotic.Attribute = "AGI";
            //		if (objXmlSkill.Attributes["spec"] != null)
            //                 {
            //                     SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
            //                     objExotic.Specializations.Add(objSpec);
            //                 }
            //		if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
            //			objExotic.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
            //		objExotic.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
            //		objExotic.Name = objXmlSkill.InnerText;
            //		objCharacter.Skills.Add(objExotic);
            //	}
            //	else
            //	{
            //		foreach (Skill objSkill in objCharacter.Skills)
            //		{
            //			if (objSkill.Name == objXmlSkill.InnerText)
            //			{
            //				if (objXmlSkill.Attributes["spec"] != null)
            //                         {
            //                             SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
            //                             objSkill.Specializations.Add(objSpec);
            //                         }
            //				if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
            //					objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
            //				objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
            //				break;
            //			}
            //		}
            //	}
            //}

            // Set the Skill Group Ratings for the Critter.
            //foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/group"))
            //{
            //	foreach (SkillGroup objSkill in objCharacter.SkillGroups)
            //	{
            //		if (objSkill.Name == objXmlSkill.InnerText)
            //		{
            //			objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
            //			objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
            //			break;
            //		}
            //	}
            //}

            //TODO: WHEN IS THIS NEEDED, 4e holdover?
            //// Set the Knowledge Skill Ratings for the Critter.
            //foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/knowledge"))
            //{
            //	Skill objKnowledge = new Skill(objCharacter);
            //	objKnowledge.Name = objXmlSkill.InnerText;
            //	objKnowledge.KnowledgeSkill = true;
            //	if (objXmlSkill.Attributes["spec"] != null)
            //             {
            //                 SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
            //                 objKnowledge.Specializations.Add(objSpec);
            //             }
            //	objKnowledge.SkillCategory = objXmlSkill.Attributes["category"].InnerText;
            //	if (Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText) > 6)
            //		objKnowledge.RatingMaximum = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
            //	objKnowledge.Rating = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
            //	objCharacter.Skills.Add(objKnowledge);
            //}

            //// If this is a Critter with a Force (which dictates their Skill Rating/Maximum Skill Rating), set their Skill Rating Maximums.
            //if (intForce > 0)
            //{
            //	int intMaxRating = intForce;
            //	// Determine the highest Skill Rating the Critter has.
            //	foreach (Skill objSkill in objCharacter.Skills)
            //	{
            //		if (objSkill.RatingMaximum > intMaxRating)
            //			intMaxRating = objSkill.RatingMaximum;
            //	}

            //	// Now that we know the upper limit, set all of the Skill Rating Maximums to match.
            //	foreach (Skill objSkill in objCharacter.Skills)
            //		objSkill.RatingMaximum = intMaxRating;
            //	foreach (SkillGroup objGroup in objCharacter.SkillGroups)
            //		objGroup.RatingMaximum = intMaxRating;

            //	// Set the MaxSkillRating for the character so it can be used later when they add new Knowledge Skills or Exotic Skills.
            //	objCharacter.MaxSkillRating = intMaxRating;
            //}

            // Add any Complex Forms the Critter comes with (typically Sprites)
            XmlDocument objXmlProgramDocument = XmlManager.Instance.Load("complexforms.xml");

            foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
            {
                string strForceValue = "";
                if (objXmlComplexForm.Attributes["select"] != null)
                {
                    strForceValue = objXmlComplexForm.Attributes["select"].InnerText;
                }
                XmlNode     objXmlProgram = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlComplexForm.InnerText + "\"]");
                TreeNode    objNode       = new TreeNode();
                ComplexForm objProgram    = new ComplexForm(objCharacter);
                objProgram.Create(objXmlProgram, objCharacter, objNode, strForceValue);
                objCharacter.ComplexForms.Add(objProgram);
            }

            // Add any Gear the Critter comes with (typically Programs for A.I.s)
            XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");

            foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
            {
                int intRating = 0;
                if (objXmlGear.Attributes["rating"] != null)
                {
                    intRating = Convert.ToInt32(ExpressionToString(objXmlGear.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                }
                string strForceValue = "";
                if (objXmlGear.Attributes["select"] != null)
                {
                    strForceValue = objXmlGear.Attributes["select"].InnerText;
                }
                XmlNode         objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear.InnerText + "\"]");
                TreeNode        objNode        = new TreeNode();
                Gear            objGear        = new Gear(objCharacter);
                List <Weapon>   lstWeapons     = new List <Weapon>();
                List <TreeNode> lstWeaponNodes = new List <TreeNode>();
                objGear.Create(objXmlGearItem, objCharacter, objNode, intRating, lstWeapons, lstWeaponNodes, strForceValue);
                objGear.Cost   = "0";
                objGear.Cost3  = "0";
                objGear.Cost6  = "0";
                objGear.Cost10 = "0";
                objCharacter.Gear.Add(objGear);
            }

            // If this is a Mutant Critter, count up the number of Skill points they start with.
            if (objCharacter.MetatypeCategory == "Mutant Critters")
            {
                foreach (Skill objSkill in objCharacter.SkillsSection.Skills)
                {
                    objCharacter.MutantCritterBaseSkills += objSkill.Rating;
                }
            }

            // Add the Unarmed Attack Weapon to the character.
            try
            {
                objXmlDocument = XmlManager.Instance.Load("weapons.xml");
                XmlNode  objXmlWeapon = objXmlDocument.SelectSingleNode("/chummer/weapons/weapon[name = \"Unarmed Attack\"]");
                TreeNode objDummy     = new TreeNode();
                Weapon   objWeapon    = new Weapon(objCharacter);
                objWeapon.Create(objXmlWeapon, objCharacter, objDummy, null, null);
                objCharacter.Weapons.Add(objWeapon);
            }
            catch
            {
            }

            objCharacter.Alias   = strCritterName;
            objCharacter.Created = true;
            objCharacter.Save();

            string strOpenFile = objCharacter.FileName;

            objCharacter = null;

            // Link the newly-created Critter to the Spirit.
            _objSpirit.FileName = strOpenFile;
            if (_objSpirit.EntityType == SpiritType.Spirit)
            {
                tipTooltip.SetToolTip(imgLink, LanguageManager.Instance.GetString("Tip_Spirit_OpenFile"));
            }
            else
            {
                tipTooltip.SetToolTip(imgLink, LanguageManager.Instance.GetString("Tip_Sprite_OpenFile"));
            }
            FileNameChanged(this);

            GlobalOptions.Instance.MainForm.LoadCharacter(strOpenFile, true);
        }
Example #13
0
        void TestMetatype(string strFile)
        {
            XmlDocument objXmlDocument = XmlManager.Instance.Load(strFile);

            pgbProgress.Minimum = 0;
            pgbProgress.Value = 0;
            pgbProgress.Maximum = objXmlDocument.SelectNodes("/chummer/metatypes/metatype").Count;

            foreach (XmlNode objXmlMetatype in objXmlDocument.SelectNodes("/chummer/metatypes/metatype"))
            {
                pgbProgress.Value++;
                Application.DoEvents();

                objXmlDocument = XmlManager.Instance.Load(strFile);
                Character _objCharacter = new Character();
                ImprovementManager objImprovementManager = new ImprovementManager(_objCharacter);

                try
                {
                    int intForce = 0;
                    if (objXmlMetatype["forcecreature"] != null)
                        intForce = 1;

                    // Set Metatype information.
                    if (strFile != "critters.xml" || objXmlMetatype["name"].InnerText == "Ally Spirit")
                    {
                        _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                        _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                        _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                        _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                        _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                        _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                        _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                        _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                        _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                        _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                        _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                        _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                        _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                    }
                    else
                    {
                        int intMinModifier = -3;
                        if (objXmlMetatype["category"].InnerText == "Mutant Critters")
                            intMinModifier = 0;
                        _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                        _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                        _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                        _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                        _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                        _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                        _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                        _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                        _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                        _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                        _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                        _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                        _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                    }

                    // If we're working with a Critter, set the Attributes to their default values.
                    if (strFile == "critters.xml")
                    {
                        _objCharacter.BOD.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
                        _objCharacter.AGI.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
                        _objCharacter.REA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
                        _objCharacter.STR.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
                        _objCharacter.CHA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
                        _objCharacter.INT.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
                        _objCharacter.LOG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
                        _objCharacter.WIL.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
                        _objCharacter.MAG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
                        _objCharacter.RES.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
                        _objCharacter.EDG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
                        _objCharacter.ESS.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));
                    }

                    // Sprites can never have Physical Attributes or WIL.
                    if (objXmlMetatype["name"].InnerText.EndsWith("Sprite"))
                    {
                        _objCharacter.BOD.AssignLimits("0", "0", "0");
                        _objCharacter.AGI.AssignLimits("0", "0", "0");
                        _objCharacter.REA.AssignLimits("0", "0", "0");
                        _objCharacter.STR.AssignLimits("0", "0", "0");
                        _objCharacter.WIL.AssignLimits("0", "0", "0");
                        _objCharacter.INI.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                        _objCharacter.INI.MetatypeMaximum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                    }

                    _objCharacter.Metatype = objXmlMetatype["name"].InnerText;
                    _objCharacter.MetatypeCategory = objXmlMetatype["category"].InnerText;
                    _objCharacter.Metavariant = "";
                    _objCharacter.MetatypeBP = 400;

                    if (objXmlMetatype["movement"] != null)
                        _objCharacter.Movement = objXmlMetatype["movement"].InnerText;
                    // Load the Qualities file.
                    XmlDocument objXmlQualityDocument = XmlManager.Instance.Load("qualities.xml");

                    // Determine if the Metatype has any bonuses.
                    if (objXmlMetatype.InnerXml.Contains("bonus"))
                        objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metatype, objXmlMetatype["name"].InnerText, objXmlMetatype.SelectSingleNode("bonus"), false, 1, objXmlMetatype["name"].InnerText);

                    // Create the Qualities that come with the Metatype.
                    foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        _objCharacter.Qualities.Add(objQuality);
                    }
                    foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        _objCharacter.Qualities.Add(objQuality);
                    }

                    // Run through the character's Attributes one more time and make sure their value matches their minimum value.
                    if (strFile == "metatypes.xml")
                    {
                        _objCharacter.BOD.Value = _objCharacter.BOD.TotalMinimum;
                        _objCharacter.AGI.Value = _objCharacter.AGI.TotalMinimum;
                        _objCharacter.REA.Value = _objCharacter.REA.TotalMinimum;
                        _objCharacter.STR.Value = _objCharacter.STR.TotalMinimum;
                        _objCharacter.CHA.Value = _objCharacter.CHA.TotalMinimum;
                        _objCharacter.INT.Value = _objCharacter.INT.TotalMinimum;
                        _objCharacter.LOG.Value = _objCharacter.LOG.TotalMinimum;
                        _objCharacter.WIL.Value = _objCharacter.WIL.TotalMinimum;
                    }

                    // Add any Critter Powers the Metatype/Critter should have.
                    XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");

                    objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
                    foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
                    {
                        XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        CritterPower objPower = new CritterPower(_objCharacter);
                        string strForcedValue = "";
                        int intRating = 0;

                        if (objXmlPower.Attributes["rating"] != null)
                            intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                        if (objXmlPower.Attributes["select"] != null)
                            strForcedValue = objXmlPower.Attributes["select"].InnerText;

                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, intRating, strForcedValue);
                        _objCharacter.CritterPowers.Add(objPower);
                    }

                    // Set the Skill Ratings for the Critter.
                    foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/skill"))
                    {
                        if (objXmlSkill.InnerText.Contains("Exotic"))
                        {
                            Skill objExotic = new Skill(_objCharacter);
                            objExotic.ExoticSkill = true;
                            objExotic.Attribute = "AGI";
                            if (objXmlSkill.Attributes["spec"] != null)
                                objExotic.Specialization = objXmlSkill.Attributes["spec"].InnerText;
                            if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0)) > 6)
                                objExotic.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                            objExotic.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                            objExotic.Name = objXmlSkill.InnerText;
                            _objCharacter.Skills.Add(objExotic);
                        }
                        else
                        {
                            foreach (Skill objSkill in _objCharacter.Skills)
                            {
                                if (objSkill.Name == objXmlSkill.InnerText)
                                {
                                    if (objXmlSkill.Attributes["spec"] != null)
                                        objSkill.Specialization = objXmlSkill.Attributes["spec"].InnerText;
                                    if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0)) > 6)
                                        objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                                    objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                                    break;
                                }
                            }
                        }
                    }

                    // Set the Skill Group Ratings for the Critter.
                    foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/group"))
                    {
                        foreach (SkillGroup objSkill in _objCharacter.SkillGroups)
                        {
                            if (objSkill.Name == objXmlSkill.InnerText)
                            {
                                objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                                objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                                break;
                            }
                        }
                    }

                    // Set the Knowledge Skill Ratings for the Critter.
                    foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/knowledge"))
                    {
                        Skill objKnowledge = new Skill(_objCharacter);
                        objKnowledge.Name = objXmlSkill.InnerText;
                        objKnowledge.KnowledgeSkill = true;
                        if (objXmlSkill.Attributes["spec"] != null)
                            objKnowledge.Specialization = objXmlSkill.Attributes["spec"].InnerText;
                        objKnowledge.SkillCategory = objXmlSkill.Attributes["category"].InnerText;
                        if (Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText) > 6)
                            objKnowledge.RatingMaximum = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                        objKnowledge.Rating = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                        _objCharacter.Skills.Add(objKnowledge);
                    }

                    // If this is a Critter with a Force (which dictates their Skill Rating/Maximum Skill Rating), set their Skill Rating Maximums.
                    if (intForce > 0)
                    {
                        int intMaxRating = intForce;
                        // Determine the highest Skill Rating the Critter has.
                        foreach (Skill objSkill in _objCharacter.Skills)
                        {
                            if (objSkill.RatingMaximum > intMaxRating)
                                intMaxRating = objSkill.RatingMaximum;
                        }

                        // Now that we know the upper limit, set all of the Skill Rating Maximums to match.
                        foreach (Skill objSkill in _objCharacter.Skills)
                            objSkill.RatingMaximum = intMaxRating;
                        foreach (SkillGroup objGroup in _objCharacter.SkillGroups)
                            objGroup.RatingMaximum = intMaxRating;

                        // Set the MaxSkillRating for the character so it can be used later when they add new Knowledge Skills or Exotic Skills.
                        _objCharacter.MaxSkillRating = intMaxRating;
                    }

                    // Add any Complex Forms the Critter comes with (typically Sprites)
                    XmlDocument objXmlProgramDocument = XmlManager.Instance.Load("programs.xml");
                    foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
                    {
                        int intRating = 0;
                        if (objXmlComplexForm.Attributes["rating"] != null)
                            intRating = Convert.ToInt32(ExpressionToString(objXmlComplexForm.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                        string strForceValue = "";
                        if (objXmlComplexForm.Attributes["select"] != null)
                            strForceValue = objXmlComplexForm.Attributes["select"].InnerText;
                        XmlNode objXmlProgram = objXmlProgramDocument.SelectSingleNode("/chummer/programs/program[name = \"" + objXmlComplexForm.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        TechProgram objProgram = new TechProgram(_objCharacter);
                        objProgram.Create(objXmlProgram, _objCharacter, objNode, strForceValue);
                        objProgram.Rating = intRating;
                        _objCharacter.TechPrograms.Add(objProgram);

                        // Add the Program Option if applicable.
                        if (objXmlComplexForm.Attributes["option"] != null)
                        {
                            int intOptRating = 0;
                            if (objXmlComplexForm.Attributes["optionrating"] != null)
                                intOptRating = Convert.ToInt32(ExpressionToString(objXmlComplexForm.Attributes["optionrating"].InnerText, Convert.ToInt32(intForce), 0));
                            string strOptForceValue = "";
                            if (objXmlComplexForm.Attributes["optionselect"] != null)
                                strOptForceValue = objXmlComplexForm.Attributes["optionselect"].InnerText;
                            XmlNode objXmlOption = objXmlProgramDocument.SelectSingleNode("/chummer/options/option[name = \"" + objXmlComplexForm.Attributes["option"].InnerText + "\"]");
                            TreeNode objNodeOpt = new TreeNode();
                            TechProgramOption objOption = new TechProgramOption(_objCharacter);
                            objOption.Create(objXmlOption, _objCharacter, objNodeOpt, strOptForceValue);
                            objOption.Rating = intOptRating;
                            objProgram.Options.Add(objOption);
                        }
                    }

                    // Add any Gear the Critter comes with (typically Programs for A.I.s)
                    XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");
                    foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
                    {
                        int intRating = 0;
                        if (objXmlGear.Attributes["rating"] != null)
                            intRating = Convert.ToInt32(ExpressionToString(objXmlGear.Attributes["rating"].InnerText, Convert.ToInt32(intForce), 0));
                        string strForceValue = "";
                        if (objXmlGear.Attributes["select"] != null)
                            strForceValue = objXmlGear.Attributes["select"].InnerText;
                        XmlNode objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        Gear objGear = new Gear(_objCharacter);
                        List<Weapon> lstWeapons = new List<Weapon>();
                        List<TreeNode> lstWeaponNodes = new List<TreeNode>();
                        objGear.Create(objXmlGearItem, _objCharacter, objNode, intRating, lstWeapons, lstWeaponNodes, strForceValue);
                        objGear.Cost = "0";
                        objGear.Cost3 = "0";
                        objGear.Cost6 = "0";
                        objGear.Cost10 = "0";
                        _objCharacter.Gear.Add(objGear);
                    }

                    // If this is a Mutant Critter, count up the number of Skill points they start with.
                    if (_objCharacter.MetatypeCategory == "Mutant Critters")
                    {
                        foreach (Skill objSkill in _objCharacter.Skills)
                            _objCharacter.MutantCritterBaseSkills += objSkill.Rating;
                    }
                }
                catch
                {
                    txtOutput.Text += _objCharacter.Metatype + " general failure\n";
                }
            }
        }
        /// <summary>
        /// A Metatype has been selected, so fill in all of the necessary Character information.
        /// </summary>
        void MetatypeSelected()
        {
            if (cboTalents.SelectedIndex == -1)
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_Metatype_SelectTalent"), LanguageManager.Instance.GetString("MessageTitle_Metatype_SelectTalent"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if ((cboSkill1.SelectedIndex == -1 && cboSkill1.Visible) || (cboSkill2.SelectedIndex == -1 && cboSkill2.Visible))
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_Metatype_SelectSkill"), LanguageManager.Instance.GetString("MessageTitle_Metatype_SelectSkill"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (cboSkill1.Visible && cboSkill2.Visible && cboSkill1.SelectedValue.ToString() == cboSkill2.SelectedValue.ToString())
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_Metatype_Duplicate"), LanguageManager.Instance.GetString("MessageTitle_Metatype_Duplicate"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (lstMetatypes.Text != "")
            {
                ImprovementManager objImprovementManager = new ImprovementManager(_objCharacter);
                XmlDocument objXmlDocument = XmlManager.Instance.Load(_strXmlFile);

                XmlNode objXmlMetatype = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + lstMetatypes.SelectedValue + "\"]");
                XmlNode objXmlMetavariant = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + lstMetatypes.SelectedValue + "\"]/metavariants/metavariant[name = \"" + cboMetavariant.SelectedValue + "\"]");

                int intForce = 0;
                if (nudForce.Visible)
                    intForce = Convert.ToInt32(nudForce.Value);

                // Set Metatype information.
                if (cboMetavariant.SelectedValue.ToString() != "None")
                {
                    _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetavariant["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["bodaug"].InnerText, intForce, 0));
                    _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetavariant["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["agiaug"].InnerText, intForce, 0));
                    _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetavariant["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["reaaug"].InnerText, intForce, 0));
                    _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetavariant["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["straug"].InnerText, intForce, 0));
                    _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetavariant["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["chaaug"].InnerText, intForce, 0));
                    _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetavariant["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["intaug"].InnerText, intForce, 0));
                    _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetavariant["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["logaug"].InnerText, intForce, 0));
                    _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetavariant["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["wilaug"].InnerText, intForce, 0));
                    _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetavariant["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["iniaug"].InnerText, intForce, 0));
                    _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetavariant["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["magaug"].InnerText, intForce, 0));
                    _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetavariant["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["resaug"].InnerText, intForce, 0));
                    _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetavariant["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["edgaug"].InnerText, intForce, 0));
                    _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetavariant["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetavariant["essaug"].InnerText, intForce, 0));
                    _objCharacter.MetatypeBP = Convert.ToInt32(lblMetavariantBP.Text);
                }
                else if (_strXmlFile != "critters.xml" || lstMetatypes.SelectedValue.ToString() == "Ally Spirit")
                {
                    _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                    _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                    _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                    _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                    _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                    _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                    _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                    _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                    _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                    _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                    _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                    _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                    _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                }
                else
                {
                    int intMinModifier = -3;
                    if (cboCategory.SelectedValue.ToString() == "Mutant Critters")
                        intMinModifier = 0;
                    _objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                    _objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                    _objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                    _objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                    _objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                    _objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                    _objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                    _objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                    _objCharacter.INI.AssignLimits(ExpressionToString(objXmlMetatype["inimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["iniaug"].InnerText, intForce, 0));
                    _objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                    _objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                    _objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                    _objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
                }

                // If we're working with a Critter, set the Attributes to their default values.
                if (_strXmlFile == "critters.xml")
                {
                    _objCharacter.BOD.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
                    _objCharacter.AGI.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
                    _objCharacter.REA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
                    _objCharacter.STR.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
                    _objCharacter.CHA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
                    _objCharacter.INT.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
                    _objCharacter.LOG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
                    _objCharacter.WIL.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
                    _objCharacter.MAG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
                    _objCharacter.RES.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
                    _objCharacter.EDG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
                    _objCharacter.ESS.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));
                }

                // Sprites can never have Physical Attributes or WIL.
                if (lstMetatypes.SelectedValue.ToString().EndsWith("Sprite"))
                {
                    _objCharacter.BOD.AssignLimits("0", "0", "0");
                    _objCharacter.AGI.AssignLimits("0", "0", "0");
                    _objCharacter.REA.AssignLimits("0", "0", "0");
                    _objCharacter.STR.AssignLimits("0", "0", "0");
                    _objCharacter.WIL.AssignLimits("0", "0", "0");
                    _objCharacter.INI.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                    _objCharacter.INI.MetatypeMaximum = Convert.ToInt32(ExpressionToString(objXmlMetatype["inimax"].InnerText, intForce, 0));
                }

                // If this is a Shapeshifter, a Metavariant must be selected. Default to Human if None is selected.
                if (cboCategory.SelectedValue.ToString() == "Shapeshifter" && cboMetavariant.SelectedValue.ToString() == "None")
                    cboMetavariant.SelectedValue = "Human";

                _objCharacter.Metatype = lstMetatypes.SelectedValue.ToString();
                _objCharacter.MetatypeCategory = cboCategory.SelectedValue.ToString();
                if (cboMetavariant.SelectedValue.ToString() == "None")
                {
                    _objCharacter.Metavariant = "";
                }
                else
                {
                    _objCharacter.Metavariant = cboMetavariant.SelectedValue.ToString();
                }

                if (objXmlMetatype["movement"] != null) // TODO: Replace with Walk/Run
                    _objCharacter.Movement = objXmlMetatype["movement"].InnerText;

                // Load the Qualities file.
                XmlDocument objXmlQualityDocument = XmlManager.Instance.Load("qualities.xml");

                if (cboMetavariant.SelectedValue.ToString() == "None")
                {
                    // Determine if the Metatype has any bonuses.
                    if (objXmlMetatype.InnerXml.Contains("bonus"))
                        objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metatype, lstMetatypes.SelectedValue.ToString(), objXmlMetatype.SelectSingleNode("bonus"), false, 1, lstMetatypes.SelectedValue.ToString());

                    // Create the Qualities that come with the Metatype.
                    foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

                        // Add any created Weapons to the character.
                        foreach (Weapon objWeapon in objWeapons)
                            _objCharacter.Weapons.Add(objWeapon);
                    }
                    foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

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

                // If a Metavariant has been selected, locate it in the file.
                if (cboMetavariant.SelectedValue.ToString() != "None")
                {
                    // Determine if the Metavariant has any bonuses.
                    if (objXmlMetavariant.InnerXml.Contains("bonus"))
                        objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metavariant, cboMetavariant.SelectedValue.ToString(), objXmlMetavariant.SelectSingleNode("bonus"), false, 1, cboMetavariant.SelectedValue.ToString());

                    // Create the Qualities that come with the Metatype.
                    foreach (XmlNode objXmlQualityItem in objXmlMetavariant.SelectNodes("qualities/positive/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        objQuality.ContributeToLimit = false;
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

                        // Add any created Weapons to the character.
                        foreach (Weapon objWeapon in objWeapons)
                            _objCharacter.Weapons.Add(objWeapon);
                    }
                    foreach (XmlNode objXmlQualityItem in objXmlMetavariant.SelectNodes("qualities/negative/quality"))
                    {
                        XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        List<Weapon> objWeapons = new List<Weapon>();
                        List<TreeNode> objWeaponNodes = new List<TreeNode>();
                        Quality objQuality = new Quality(_objCharacter);
                        string strForceValue = "";
                        if (objXmlQualityItem.Attributes["select"] != null)
                            strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                        QualitySource objSource = new QualitySource();
                        objSource = QualitySource.Metatype;
                        if (objXmlQualityItem.Attributes["removable"] != null)
                            objSource = QualitySource.MetatypeRemovable;
                        objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                        objQuality.ContributeToLimit = false;
                        _objCharacter.Qualities.Add(objQuality);

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

                // Run through the character's Attributes one more time and make sure their value matches their minimum value.
                if (_strXmlFile == "metatypes.xml")
                {
                    _objCharacter.BOD.Value = _objCharacter.BOD.TotalMinimum;
                    _objCharacter.AGI.Value = _objCharacter.AGI.TotalMinimum;
                    _objCharacter.REA.Value = _objCharacter.REA.TotalMinimum;
                    _objCharacter.STR.Value = _objCharacter.STR.TotalMinimum;
                    _objCharacter.CHA.Value = _objCharacter.CHA.TotalMinimum;
                    _objCharacter.INT.Value = _objCharacter.INT.TotalMinimum;
                    _objCharacter.LOG.Value = _objCharacter.LOG.TotalMinimum;
                    _objCharacter.WIL.Value = _objCharacter.WIL.TotalMinimum;

                    _objCharacter.BOD.Base = _objCharacter.BOD.TotalMinimum;
                    _objCharacter.AGI.Base = _objCharacter.AGI.TotalMinimum;
                    _objCharacter.REA.Base = _objCharacter.REA.TotalMinimum;
                    _objCharacter.STR.Base = _objCharacter.STR.TotalMinimum;
                    _objCharacter.CHA.Base = _objCharacter.CHA.TotalMinimum;
                    _objCharacter.INT.Base = _objCharacter.INT.TotalMinimum;
                    _objCharacter.LOG.Base = _objCharacter.LOG.TotalMinimum;
                    _objCharacter.WIL.Base = _objCharacter.WIL.TotalMinimum;

                    _objCharacter.BOD.Karma = 0;
                    _objCharacter.AGI.Karma = 0;
                    _objCharacter.REA.Karma = 0;
                    _objCharacter.STR.Karma = 0;
                    _objCharacter.CHA.Karma = 0;
                    _objCharacter.INT.Karma = 0;
                    _objCharacter.LOG.Karma = 0;
                    _objCharacter.WIL.Karma = 0;
                    _objCharacter.EDG.Karma = 0;
                    _objCharacter.MAG.Karma = 0;
                    _objCharacter.RES.Karma = 0;
                }

                // Add any Critter Powers the Metatype/Critter should have.
                XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");

                objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
                foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
                {
                    XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                    TreeNode objNode = new TreeNode();
                    CritterPower objPower = new CritterPower(_objCharacter);
                    string strForcedValue = "";
                    int intRating = 0;

                    if (objXmlPower.Attributes["rating"] != null)
                        intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                    if (objXmlPower.Attributes["select"] != null)
                        strForcedValue = objXmlPower.Attributes["select"].InnerText;

                    objPower.Create(objXmlCritterPower, _objCharacter, objNode, intRating, strForcedValue);
                    objPower.CountTowardsLimit = false;
                    _objCharacter.CritterPowers.Add(objPower);
                }

                // Add any Critter Powers the Metavariant should have.
                if (cboMetavariant.SelectedValue.ToString() != "None")
                {
                    foreach (XmlNode objXmlPower in objXmlMetavariant.SelectNodes("powers/power"))
                    {
                        XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                        TreeNode objNode = new TreeNode();
                        CritterPower objPower = new CritterPower(_objCharacter);
                        string strForcedValue = "";
                        int intRating = 0;

                        if (objXmlPower.Attributes["rating"] != null)
                            intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                        if (objXmlPower.Attributes["select"] != null)
                            strForcedValue = objXmlPower.Attributes["select"].InnerText;

                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, intRating, strForcedValue);
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }
                }

                // If this is a Blood Spirit, add their free Critter Powers.
                if (chkBloodSpirit.Checked)
                {
                    XmlNode objXmlCritterPower;
                    TreeNode objNode;
                    CritterPower objPower;
                    bool blnAddPower = true;

                    // Energy Drain.
                    foreach (CritterPower objFindPower in _objCharacter.CritterPowers)
                    {
                        if (objFindPower.Name == "Energy Drain")
                        {
                            blnAddPower = false;
                            break;
                        }
                    }
                    if (blnAddPower)
                    {
                        objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Energy Drain\"]");
                        objNode = new TreeNode();
                        objPower = new CritterPower(_objCharacter);
                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }

                    // Fear.
                    blnAddPower = true;
                    foreach (CritterPower objFindPower in _objCharacter.CritterPowers)
                    {
                        if (objFindPower.Name == "Fear")
                        {
                            blnAddPower = false;
                            break;
                        }
                    }
                    if (blnAddPower)
                    {
                        objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Fear\"]");
                        objNode = new TreeNode();
                        objPower = new CritterPower(_objCharacter);
                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }

                    // Natural Weapon.
                    objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Natural Weapon\"]");
                    objNode = new TreeNode();
                    objPower = new CritterPower(_objCharacter);
                    objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "DV " + intForce.ToString() + "P, AP 0");
                    objPower.CountTowardsLimit = false;
                    _objCharacter.CritterPowers.Add(objPower);

                    // Evanescence.
                    blnAddPower = true;
                    foreach (CritterPower objFindPower in _objCharacter.CritterPowers)
                    {
                        if (objFindPower.Name == "Evanescence")
                        {
                            blnAddPower = false;
                            break;
                        }
                    }
                    if (blnAddPower)
                    {
                        objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Evanescence\"]");
                        objNode = new TreeNode();
                        objPower = new CritterPower(_objCharacter);
                        objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                        objPower.CountTowardsLimit = false;
                        _objCharacter.CritterPowers.Add(objPower);
                    }
                }

                // Remove the Critter's Materialization Power if they have it. Add the Possession or Inhabitation Power if the Possession-based Tradition checkbox is checked.
                if (chkPossessionBased.Checked)
                {
                    foreach (CritterPower objCritterPower in _objCharacter.CritterPowers)
                    {
                        if (objCritterPower.Name == "Materialization")
                        {
                            _objCharacter.CritterPowers.Remove(objCritterPower);
                            break;
                        }
                    }

                    // Add the selected Power.
                    XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + cboPossessionMethod.SelectedValue.ToString() + "\"]");
                    TreeNode objNode = new TreeNode();
                    CritterPower objPower = new CritterPower(_objCharacter);
                    objPower.Create(objXmlCritterPower, _objCharacter, objNode, 0, "");
                    objPower.CountTowardsLimit = false;
                    _objCharacter.CritterPowers.Add(objPower);
                }

                // Set the Skill Ratings for the Critter.
                foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/skill"))
                {
                    if (objXmlSkill.InnerText.Contains("Exotic"))
                    {
                        Skill objExotic = new Skill(_objCharacter);
                        objExotic.ExoticSkill = true;
                        objExotic.Attribute = "AGI";
                        if (objXmlSkill.Attributes["spec"] != null)
                        {
                            SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                            objExotic.Specializations.Add(objSpec);
                        }
                        if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
                            objExotic.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                        objExotic.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                        objExotic.Name = objXmlSkill.InnerText;
                        _objCharacter.Skills.Add(objExotic);
                    }
                    else
                    {
                        foreach (Skill objSkill in _objCharacter.Skills)
                        {
                            if (objSkill.Name == objXmlSkill.InnerText)
                            {
                                if (objXmlSkill.Attributes["spec"] != null)
                                {
                                    SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                                    objSkill.Specializations.Add(objSpec);
                                }
                                if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0)) > 6)
                                    objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                                objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                                break;
                            }
                        }
                    }
                }

                // Set the Skill Group Ratings for the Critter.
                foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/group"))
                {
                    foreach (SkillGroup objSkill in _objCharacter.SkillGroups)
                    {
                        if (objSkill.Name == objXmlSkill.InnerText)
                        {
                            objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                            objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                            break;
                        }
                    }
                }

                // Set the Knowledge Skill Ratings for the Critter.
                foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/knowledge"))
                {
                    Skill objKnowledge = new Skill(_objCharacter);
                    objKnowledge.Name = objXmlSkill.InnerText;
                    objKnowledge.KnowledgeSkill = true;
                    if (objXmlSkill.Attributes["spec"] != null)
                    {
                        SkillSpecialization objSpec = new SkillSpecialization(objXmlSkill.Attributes["spec"].InnerText);
                        objKnowledge.Specializations.Add(objSpec);
                    }
                    objKnowledge.SkillCategory = objXmlSkill.Attributes["category"].InnerText;
                    if (Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText) > 6)
                        objKnowledge.RatingMaximum = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                    objKnowledge.Rating = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                    _objCharacter.Skills.Add(objKnowledge);
                }

                // If this is a Critter with a Force (which dictates their Skill Rating/Maximum Skill Rating), set their Skill Rating Maximums.
                if (intForce > 0)
                {
                    int intMaxRating = intForce;
                    // Determine the highest Skill Rating the Critter has.
                    foreach (Skill objSkill in _objCharacter.Skills)
                    {
                        if (objSkill.RatingMaximum > intMaxRating)
                            intMaxRating = objSkill.RatingMaximum;
                    }

                    // Now that we know the upper limit, set all of the Skill Rating Maximums to match.
                    foreach (Skill objSkill in _objCharacter.Skills)
                        objSkill.RatingMaximum = intMaxRating;
                    foreach (SkillGroup objGroup in _objCharacter.SkillGroups)
                        objGroup.RatingMaximum = intMaxRating;

                    // Set the MaxSkillRating for the character so it can be used later when they add new Knowledge Skills or Exotic Skills.
                    _objCharacter.MaxSkillRating = intMaxRating;
                }

                // Add any Complex Forms the Critter comes with (typically Sprites)
                XmlDocument objXmlProgramDocument = XmlManager.Instance.Load("complexforms.xml");
                foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
                {
                    string strForceValue = "";
                    if (objXmlComplexForm.Attributes["select"] != null)
                        strForceValue = objXmlComplexForm.Attributes["select"].InnerText;
                    XmlNode objXmlProgram = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlComplexForm.InnerText + "\"]");
                    TreeNode objNode = new TreeNode();
                    ComplexForm objProgram = new ComplexForm(_objCharacter);
                    objProgram.Create(objXmlProgram, _objCharacter, objNode, strForceValue);
                    _objCharacter.ComplexForms.Add(objProgram);
                }

                // Add any Gear the Critter comes with (typically Programs for A.I.s)
                XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");
                foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
                {
                    int intRating = 0;
                    if (objXmlGear.Attributes["rating"] != null)
                        intRating = Convert.ToInt32(ExpressionToString(objXmlGear.Attributes["rating"].InnerText, Convert.ToInt32(nudForce.Value), 0));
                    string strForceValue = "";
                    if (objXmlGear.Attributes["select"] != null)
                        strForceValue = objXmlGear.Attributes["select"].InnerText;
                    XmlNode objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear.InnerText + "\"]");
                    TreeNode objNode = new TreeNode();
                    Gear objGear = new Gear(_objCharacter);
                    List<Weapon> lstWeapons = new List<Weapon>();
                    List<TreeNode> lstWeaponNodes = new List<TreeNode>();
                    objGear.Create(objXmlGearItem, _objCharacter, objNode, intRating, lstWeapons, lstWeaponNodes, strForceValue);
                    objGear.Cost = "0";
                    objGear.Cost3 = "0";
                    objGear.Cost6 = "0";
                    objGear.Cost10 = "0";
                    _objCharacter.Gear.Add(objGear);
                }

                // If this is a Mutant Critter, count up the number of Skill points they start with.
                if (_objCharacter.MetatypeCategory == "Mutant Critters")
                {
                    foreach (Skill objSkill in _objCharacter.Skills)
                        _objCharacter.MutantCritterBaseSkills += objSkill.Rating;
                }

                // begin priority based character settings
                // Load the Priority information.
                XmlDocument objXmlDocumentPriority = XmlManager.Instance.Load(_strPrioritiesXmlFile);

                // Set the character priority selections
                _objCharacter.MetatypePriority = cboHeritage.Text.ToString();
                _objCharacter.AttributesPriority = cboAttributes.Text.ToString();
                _objCharacter.SpecialPriority = cboTalent.Text.ToString();
                _objCharacter.SkillsPriority = cboSkills.Text.ToString();
                _objCharacter.ResourcesPriority = cboResources.Text.ToString();

                // Set starting nuyen
                XmlNodeList objXmResourceList = objXmlDocumentPriority.SelectNodes("/chummer/priorities/priority[category = \"Resources\" and gameplayoption = \"" + _objCharacter.GameplayOption + "\" and value = \"" + cboResources.SelectedValue + "\"]");
                if (objXmResourceList.Count > 0)
                {
                    _objCharacter.Nuyen = Convert.ToInt32(objXmResourceList[0]["resources"].InnerText.ToString());
                    _objCharacter.StartingNuyen = _objCharacter.Nuyen;
                }

                // Set starting positive qualities
                foreach (XmlNode objXmlQualityItem in objXmlDocumentPriority.SelectNodes("/chummer/priorities/priority[category = \"Talent\" and value = \"" + cboTalent.SelectedValue + "\"]/talents/talent[value = \"" + cboTalents.SelectedValue + "\"]/qualities/quality"))
                {
                    XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                    TreeNode objNode = new TreeNode();
                    List<Weapon> objWeapons = new List<Weapon>();
                    List<TreeNode> objWeaponNodes = new List<TreeNode>();
                    Quality objQuality = new Quality(_objCharacter);
                    string strForceValue = "";
                    if (objXmlQualityItem.Attributes["select"] != null)
                        strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                    QualitySource objSource = new QualitySource();
                    objSource = QualitySource.Metatype;
                    if (objXmlQualityItem.Attributes["removable"] != null)
                        objSource = QualitySource.MetatypeRemovable;
                    objQuality.Create(objXmlQuality, _objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                    _objCharacter.Qualities.Add(objQuality);

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

                // Set starting magic
                XmlNodeList objXmlTalentList = objXmlDocumentPriority.SelectNodes("/chummer/priorities/priority[category = \"Talent\" and value = \"" + cboTalent.SelectedValue + "\"]/talents/talent[value = \"" + cboTalents.SelectedValue + "\"]");
                if (objXmlTalentList[0]["magic"] != null)
                {
                    _objCharacter.MAG.Value = Convert.ToInt32(objXmlTalentList[0]["magic"].InnerText);
                    _objCharacter.MAG.MetatypeMinimum = Convert.ToInt32(objXmlTalentList[0]["magic"].InnerText);
                    if (_objCharacter.MAG.Value > 0)
                        _objCharacter.MAGEnabled = true;
                    if (objXmlTalentList[0]["spells"] != null)
                    {
                        _objCharacter.SpellLimit = Convert.ToInt32(objXmlTalentList[0]["spells"].InnerText);
                    }
                    else
                    {
                        _objCharacter.SpellLimit = 0;
                    }
                }

                if (objXmlTalentList[0]["maxmagic"] != null)
                    _objCharacter.MAG.MetatypeMaximum = Convert.ToInt32(objXmlTalentList[0]["magic"].InnerText);

                // Set starting resonance
                objXmlTalentList = objXmlDocumentPriority.SelectNodes("/chummer/priorities/priority[category = \"Talent\" and value = \"" + cboTalent.SelectedValue + "\"]/talents/talent[value = \"" + cboTalents.SelectedValue + "\"]");
                if (objXmlTalentList[0]["resonance"] != null)
                {
                    _objCharacter.RES.Value = Convert.ToInt32(objXmlTalentList[0]["resonance"].InnerText);
                    _objCharacter.RES.MetatypeMinimum = Convert.ToInt32(objXmlTalentList[0]["resonance"].InnerText);
                    _objCharacter.RESEnabled = true;
                    _objCharacter.CFPLimit = Convert.ToInt32(objXmlTalentList[0]["cfp"].InnerText);
                }

                if (objXmlTalentList[0]["maxresonance"] != null)
                    _objCharacter.RES.MetatypeMaximum = Convert.ToInt32(objXmlTalentList[0]["resonance"].InnerText);

                // Set starting talent tabs
                switch (cboTalents.SelectedValue.ToString())
                {
                    case "Magician":
                        _objCharacter.MagicianEnabled = true;
                        break;
                    case "Aspected Magician":
                        _objCharacter.MagicianEnabled = true;
                        break;
                    case "Adept":
                        _objCharacter.AdeptEnabled = true;
                        break;
                    case "Mystic Adept":
                        _objCharacter.MagicianEnabled = true;
                        _objCharacter.AdeptEnabled = true;
                        break;
                    case "Technomancer":
                        _objCharacter.TechnomancerEnabled = true;
                        break;
                    default:
                        break;
                }

                // Set Free Skills/Skill Groups
                int intFreeLevels = 0;
                bool blnGroup = (cboTalents.SelectedValue.ToString() == "Aspected Magician");
                if (cboTalent.SelectedValue.ToString() == "A")
                    intFreeLevels = 5;
                else if (cboTalent.SelectedValue.ToString() == "B")
                    intFreeLevels = 4;
                else if (cboTalent.SelectedValue.ToString() == "C")
                    intFreeLevels = 2;
                foreach (Skill objSkill in _objCharacter.Skills)
                {
                    if (cboSkill1.Visible && objSkill.Name == cboSkill1.Text && !blnGroup)
                    {
                        objSkill.FreeLevels = intFreeLevels;
                        if (objSkill.Rating < intFreeLevels)
                            objSkill.Rating = intFreeLevels;
                        _objCharacter.PriorityBonusSkill1 = cboSkill1.Text.ToString();
                    }
                    else if (cboSkill2.Visible && objSkill.Name == cboSkill2.Text && !blnGroup)
                    {
                        objSkill.FreeLevels = intFreeLevels;
                        if (objSkill.Rating < intFreeLevels)
                            objSkill.Rating = intFreeLevels;
                        _objCharacter.PriorityBonusSkill2 = cboSkill2.Text.ToString();
                    }
                    else
                    {
                        objSkill.FreeLevels = 0;
                        if (blnGroup)
                        {
                            // if this skill is a magical skill not belonging to the selected group, reduce the skill maximum to 0
                            if (objSkill.SkillGroup == "Conjuring" || objSkill.SkillGroup == "Enchanting" || objSkill.SkillGroup == "Sorcery")
                            {
                                if (objSkill.SkillGroup != cboSkill1.SelectedValue.ToString())
                                    objSkill.RatingMaximum = 0;
                                else
                                {
                                    if (_objCharacter.IgnoreRules)
                                        objSkill.RatingMaximum = 12;
                                    else
                                        objSkill.RatingMaximum = 6;
                                }
                                _objCharacter.PriorityBonusSkillGroup = cboSkill1.Text.ToString();
                            }
                        }
                    }
                }
                foreach (SkillGroup objSkillGroup in _objCharacter.SkillGroups)
                {
                    if (cboSkill1.Visible && objSkillGroup.Name == cboSkill1.Text && blnGroup)
                    {
                        objSkillGroup.FreeLevels = intFreeLevels;
                        if (objSkillGroup.Base < intFreeLevels)
                            objSkillGroup.Base = intFreeLevels;
                        _objCharacter.PriorityBonusSkillGroup = cboSkill1.Text.ToString();
                    }
                    else
                        objSkillGroup.FreeLevels = 0;

                    if (blnGroup)
                    {
                        // if this skill is a magical skill not belonging to the selected group, reduce the skill maximum to 0
                        if (objSkillGroup.Name == "Conjuring" || objSkillGroup.Name == "Enchanting" || objSkillGroup.Name == "Sorcery")
                        {
                            if (objSkillGroup.Name != cboSkill1.SelectedValue.ToString())
                                objSkillGroup.RatingMaximum = 0;
                            else
                            {
                                if (_objCharacter.IgnoreRules)
                                    objSkillGroup.RatingMaximum = 12;
                                else
                                    objSkillGroup.RatingMaximum = 6;
                            }
                        }
                    }
                }

                // Ignore Rules
                if (_objCharacter.IgnoreRules)
                {
                    foreach (Skill objSkill in _objCharacter.Skills)
                    {
                        objSkill.RatingMaximum = 99;
                    }
                    foreach (SkillGroup objSkillGroup in _objCharacter.SkillGroups)
                    {
                        objSkillGroup.RatingMaximum = 99;
                    }
                }

                // Set Special Attributes
                _objCharacter.Special = Convert.ToInt32(lblSpecial.Text);
                _objCharacter.TotalSpecial = Convert.ToInt32(lblSpecial.Text);

                // Set Attributes
                XmlNodeList objXmlPriorityList = objXmlDocumentPriority.SelectNodes("/chummer/priorities/priority[category = \"Attributes\" and value = \"" + cboAttributes.SelectedValue + "\"]");
                if (objXmlPriorityList[0]["attributes"] != null)
                {
                    _objCharacter.Attributes = Convert.ToInt32(objXmlPriorityList[0]["attributes"].InnerText);
                    _objCharacter.TotalAttributes = _objCharacter.Attributes;
                }

                // Set Skills and Skill Groups
                objXmlPriorityList = objXmlDocumentPriority.SelectNodes("/chummer/priorities/priority[category = \"Skills\" and value = \"" + cboSkills.SelectedValue + "\"]");
                if (objXmlPriorityList[0]["skills"] != null)
                {
                    _objCharacter.SkillPoints = Convert.ToInt32(objXmlPriorityList[0]["skills"].InnerText);
                    _objCharacter.SkillPointsMaximum = _objCharacter.SkillPoints;
                    _objCharacter.SkillGroupPoints = Convert.ToInt32(objXmlPriorityList[0]["skillgroups"].InnerText);
                    _objCharacter.SkillGroupPointsMaximum = _objCharacter.SkillGroupPoints;
                }

                // Load the Priority information.
                XmlNode objXmlGameplayOption = objXmlDocumentPriority.SelectSingleNode("/chummer/gameplayoptions/gameplayoption[name = \"" + _objCharacter.GameplayOption + "\"]");
                string strKarma = objXmlGameplayOption["karma"].InnerText;
                string strNuyen = objXmlGameplayOption["maxnuyen"].InnerText;
                string strContactMultiplier = objXmlGameplayOption["contactmultiplier"].InnerText;
                _objCharacter.MaxKarma = Convert.ToInt32(strKarma);
                _objCharacter.MaxNuyen = Convert.ToInt32(strNuyen);
                _objCharacter.ContactMultiplier = Convert.ToInt32(strContactMultiplier);

                // Set free contact points
                _objCharacter.ContactPoints = _objCharacter.CHA.Value * _objCharacter.ContactMultiplier;

                // Set starting karma
                _objCharacter.BuildKarma = _objCharacter.MaxKarma;

                // Set starting movement rate
                _objCharacter.Movement = (_objCharacter.AGI.TotalValue * 2).ToString() + "/" + (_objCharacter.AGI.TotalValue * 4).ToString();

                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            else
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_Metatype_SelectMetatype"), LanguageManager.Instance.GetString("MessageTitle_Metatype_SelectMetatype"), MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Example #15
0
        /// <summary>
        /// Create a Critter, put them into Career Mode, link them, and open the newly-created Critter.
        /// </summary>
        /// <param name="strCritterName">Name of the Critter's Metatype.</param>
        /// <param name="intForce">Critter's Force.</param>
        private void CreateCritter(string strCritterName, int intForce)
        {
            // The Critter should use the same settings file as the character.
            Character objCharacter = new Character
            {
                SettingsFile = _objSpirit.CharacterObject.SettingsFile,

                // Override the defaults for the setting.
                IgnoreRules = true,
                IsCritter   = true,
                BuildMethod = CharacterBuildMethod.Karma,
                BuildPoints = 0
            };

            if (!string.IsNullOrEmpty(txtCritterName.Text))
            {
                objCharacter.Name = txtCritterName.Text;
            }

            // Ask the user to select a filename for the new character.
            string strForce = LanguageManager.GetString("String_Force");

            if (_objSpirit.EntityType == SpiritType.Sprite)
            {
                strForce = LanguageManager.GetString("String_Rating");
            }
            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter   = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*",
                FileName = strCritterName + " (" + strForce + " " + _objSpirit.Force.ToString() + ").chum5"
            };

            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                string strFileName = saveFileDialog.FileName;
                objCharacter.FileName = strFileName;
            }
            else
            {
                objCharacter.Dispose();
                return;
            }

            Cursor = Cursors.WaitCursor;

            // Code from frmMetatype.
            XmlDocument objXmlDocument = XmlManager.Load("critters.xml");

            XmlNode objXmlMetatype = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + strCritterName + "\"]");

            // If the Critter could not be found, show an error and get out of here.
            if (objXmlMetatype == null)
            {
                MessageBox.Show(LanguageManager.GetString("Message_UnknownCritterType").Replace("{0}", strCritterName), LanguageManager.GetString("MessageTitle_SelectCritterType"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Set Metatype information.
            if (strCritterName == "Ally Spirit")
            {
                objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }
            else
            {
                int intMinModifier = -3;
                objCharacter.BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                objCharacter.AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                objCharacter.REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                objCharacter.STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                objCharacter.CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                objCharacter.INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                objCharacter.LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                objCharacter.WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                objCharacter.MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                objCharacter.RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                objCharacter.EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                objCharacter.ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }

            // If we're working with a Critter, set the Attributes to their default values.
            objCharacter.BOD.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
            objCharacter.AGI.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
            objCharacter.REA.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
            objCharacter.STR.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
            objCharacter.CHA.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
            objCharacter.INT.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
            objCharacter.LOG.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
            objCharacter.WIL.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
            objCharacter.MAG.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
            objCharacter.RES.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
            objCharacter.EDG.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
            objCharacter.ESS.MetatypeMinimum = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));

            // Sprites can never have Physical Attributes or WIL.
            if (objXmlMetatype["category"].InnerText.EndsWith("Sprite"))
            {
                objCharacter.BOD.AssignLimits("0", "0", "0");
                objCharacter.AGI.AssignLimits("0", "0", "0");
                objCharacter.REA.AssignLimits("0", "0", "0");
                objCharacter.STR.AssignLimits("0", "0", "0");
                objCharacter.WIL.AssignLimits("0", "0", "0");
            }

            objCharacter.Metatype         = strCritterName;
            objCharacter.MetatypeCategory = objXmlMetatype["category"].InnerText;
            objCharacter.Metavariant      = string.Empty;
            objCharacter.MetatypeBP       = 0;

            if (objXmlMetatype["movement"] != null)
            {
                objCharacter.Movement = objXmlMetatype["movement"].InnerText;
            }
            // Load the Qualities file.
            XmlDocument objXmlQualityDocument = XmlManager.Load("qualities.xml");

            // Determine if the Metatype has any bonuses.
            if (objXmlMetatype.InnerXml.Contains("bonus"))
            {
                ImprovementManager.CreateImprovements(objCharacter, Improvement.ImprovementSource.Metatype, strCritterName, objXmlMetatype.SelectSingleNode("bonus"), false, 1, strCritterName);
            }

            // Create the Qualities that come with the Metatype.
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
            {
                XmlNode         objXmlQuality  = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode        objNode        = new TreeNode();
                List <Weapon>   objWeapons     = new List <Weapon>();
                List <TreeNode> objWeaponNodes = new List <TreeNode>();
                Quality         objQuality     = new Quality(objCharacter);
                string          strForceValue  = string.Empty;
                if (objXmlQualityItem.Attributes["select"] != null)
                {
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                }
                QualitySource objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"]?.InnerText == bool.TrueString)
                {
                    objSource = QualitySource.MetatypeRemovable;
                }
                objQuality.Create(objXmlQuality, objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                objCharacter.Qualities.Add(objQuality);

                // Add any created Weapons to the character.
                foreach (Weapon objWeapon in objWeapons)
                {
                    objCharacter.Weapons.Add(objWeapon);
                }
            }
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
            {
                XmlNode         objXmlQuality  = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode        objNode        = new TreeNode();
                List <Weapon>   objWeapons     = new List <Weapon>();
                List <TreeNode> objWeaponNodes = new List <TreeNode>();
                Quality         objQuality     = new Quality(objCharacter);
                string          strForceValue  = string.Empty;
                if (objXmlQualityItem.Attributes["select"] != null)
                {
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                }
                QualitySource objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"]?.InnerText == bool.TrueString)
                {
                    objSource = QualitySource.MetatypeRemovable;
                }
                objQuality.Create(objXmlQuality, objCharacter, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                objCharacter.Qualities.Add(objQuality);

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

            // Add any Critter Powers the Metatype/Critter should have.
            XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + objCharacter.Metatype + "\"]");

            objXmlDocument = XmlManager.Load("critterpowers.xml");
            foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
            {
                XmlNode      objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                TreeNode     objNode            = new TreeNode();
                CritterPower objPower           = new CritterPower(objCharacter);
                string       strForcedValue     = string.Empty;
                int          intRating          = 0;

                if (objXmlPower.Attributes["rating"] != null)
                {
                    intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                }
                if (objXmlPower.Attributes["select"] != null)
                {
                    strForcedValue = objXmlPower.Attributes["select"].InnerText;
                }

                objPower.Create(objXmlCritterPower, objNode, intRating, strForcedValue);
                objCharacter.CritterPowers.Add(objPower);
            }

            if (objXmlCritter["optionalpowers"] != null)
            {
                //For every 3 full points of Force a spirit has, it may gain one Optional Power.
                for (int i = intForce - 3; i >= 0; i -= 3)
                {
                    XmlDocument objDummyDocument = new XmlDocument();
                    XmlNode     bonusNode        = objDummyDocument.CreateNode(XmlNodeType.Element, "bonus", null);
                    objDummyDocument.AppendChild(bonusNode);
                    XmlNode powerNode = objDummyDocument.ImportNode(objXmlMetatype["optionalpowers"].CloneNode(true), true);
                    objDummyDocument.ImportNode(powerNode, true);
                    bonusNode.AppendChild(powerNode);
                    ImprovementManager.CreateImprovements(objCharacter, Improvement.ImprovementSource.Metatype, objCharacter.Metatype, bonusNode, false, 1, objCharacter.Metatype);
                }
            }
            // Add any Complex Forms the Critter comes with (typically Sprites)
            XmlDocument objXmlProgramDocument = XmlManager.Load("complexforms.xml");

            foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
            {
                string strForceValue = string.Empty;
                if (objXmlComplexForm.Attributes["select"] != null)
                {
                    strForceValue = objXmlComplexForm.Attributes["select"].InnerText;
                }
                XmlNode     objXmlProgram = objXmlProgramDocument.SelectSingleNode("/chummer/complexforms/complexform[name = \"" + objXmlComplexForm.InnerText + "\"]");
                TreeNode    objNode       = new TreeNode();
                ComplexForm objProgram    = new ComplexForm(objCharacter);
                objProgram.Create(objXmlProgram, objNode, null, strForceValue);
                objCharacter.ComplexForms.Add(objProgram);
            }

            // Add any Gear the Critter comes with (typically Programs for A.I.s)
            XmlDocument objXmlGearDocument = XmlManager.Load("gear.xml");

            foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
            {
                int intRating = 0;
                if (objXmlGear.Attributes["rating"] != null)
                {
                    intRating = Convert.ToInt32(ExpressionToString(objXmlGear.Attributes["rating"].InnerText, decimal.ToInt32(nudForce.Value), 0));
                }
                string strForceValue = string.Empty;
                if (objXmlGear.Attributes["select"] != null)
                {
                    strForceValue = objXmlGear.Attributes["select"].InnerText;
                }
                XmlNode         objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[name = \"" + objXmlGear.InnerText + "\"]");
                TreeNode        objNode        = new TreeNode();
                Gear            objGear        = new Gear(objCharacter);
                List <Weapon>   lstWeapons     = new List <Weapon>();
                List <TreeNode> lstWeaponNodes = new List <TreeNode>();
                objGear.Create(objXmlGearItem, objNode, intRating, lstWeapons, lstWeaponNodes, strForceValue);
                objGear.Cost = "0";
                objCharacter.Gear.Add(objGear);
            }

            // Add the Unarmed Attack Weapon to the character.
            objXmlDocument = XmlManager.Load("weapons.xml");
            XmlNode objXmlWeapon = objXmlDocument.SelectSingleNode("/chummer/weapons/weapon[name = \"Unarmed Attack\"]");

            if (objXmlWeapon != null)
            {
                Weapon objWeapon = new Weapon(objCharacter);
                objWeapon.Create(objXmlWeapon, null, null, null, objCharacter.Weapons);
                objWeapon.ParentID = Guid.NewGuid().ToString(); // Unarmed Attack can never be removed
                objCharacter.Weapons.Add(objWeapon);
            }

            objCharacter.Alias   = strCritterName;
            objCharacter.Created = true;
            if (!objCharacter.Save())
            {
                Cursor = Cursors.Default;
                objCharacter.Dispose();
                return;
            }

            string strOpenFile = objCharacter.FileName;

            objCharacter.Dispose();
            objCharacter = null;

            // Link the newly-created Critter to the Spirit.
            _objSpirit.FileName = strOpenFile;
            if (_objSpirit.EntityType == SpiritType.Spirit)
            {
                tipTooltip.SetToolTip(imgLink, LanguageManager.GetString("Tip_Spirit_OpenFile"));
            }
            else
            {
                tipTooltip.SetToolTip(imgLink, LanguageManager.GetString("Tip_Sprite_OpenFile"));
            }
            FileNameChanged(this);

            Character objOpenCharacter = Program.MainForm.LoadCharacter(strOpenFile);

            Cursor = Cursors.Default;
            Program.MainForm.OpenCharacter(objOpenCharacter);
        }
Example #16
0
        private void mnuSpecialCyberzombie_Click(object sender, EventArgs e)
        {
            bool blnEssence = true;
            bool blnCyberware = false;
            string strMessage = LanguageManager.Instance.GetString("Message_CyberzombieRequirements");

            // Make sure the character has an Essence lower than 0.
            if (_objCharacter.Essence >= 0)
            {
                strMessage += "\n\t" + LanguageManager.Instance.GetString("Message_CyberzombieRequirementsEssence");
                blnEssence = false;
            }

            // Make sure the character has an Invoked Memory Stimulator.
            foreach (Cyberware objCyberware in _objCharacter.Cyberware)
            {
                if (objCyberware.Name == "Invoked Memory Stimulator")
                    blnCyberware = true;
            }

            if (!blnCyberware)
                strMessage += "\n\t" + LanguageManager.Instance.GetString("Message_CyberzombieRequirementsStimulator");

            if (!blnEssence || !blnCyberware)
            {
                MessageBox.Show(strMessage, LanguageManager.Instance.GetString("MessageTitle_CyberzombieRequirements"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (MessageBox.Show(LanguageManager.Instance.GetString("Message_CyberzombieConfirm"), LanguageManager.Instance.GetString("MessageTitle_CyberzombieConfirm"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                return;

            // Convert the character.
            // Characters lose access to Resonance.
            _objCharacter.RESEnabled = false;

            // Gain MAG that is permanently set to 1.
            _objCharacter.MAGEnabled = true;
            _objCharacter.MAG.MetatypeMinimum = 1;
            _objCharacter.MAG.MetatypeMaximum = 1;
            _objCharacter.MAG.Value = 1;

            // Add the Cyberzombie Lifestyle if it is not already taken.
            bool blnHasLifestyle = false;
            foreach (Lifestyle objLifestyle in _objCharacter.Lifestyles)
            {
                if (objLifestyle.Name == "Cyberzombie Lifestyle Addition")
                    blnHasLifestyle = true;
            }
            if (!blnHasLifestyle)
            {
                XmlDocument objXmlLifestyleDocument = XmlManager.Instance.Load("lifestyles.xml");
                XmlNode objXmlLifestyle = objXmlLifestyleDocument.SelectSingleNode("/chummer/lifestyles/lifestyle[name = \"Cyberzombie Lifestyle Addition\"]");

                TreeNode objLifestyleNode = new TreeNode();
                Lifestyle objLifestyle = new Lifestyle(_objCharacter);
                objLifestyle.Create(objXmlLifestyle, objLifestyleNode);
                _objCharacter.Lifestyles.Add(objLifestyle);

                treLifestyles.Nodes[0].Nodes.Add(objLifestyleNode);
                treLifestyles.Nodes[0].Expand();
            }

            // Change the MetatypeCategory to Cyberzombie.
            _objCharacter.MetatypeCategory = "Cyberzombie";

            // Gain access to Critter Powers.
            _objCharacter.CritterEnabled = true;

            // Gain the Dual Natured Critter Power if it does not yet exist.
            bool blnHasPower = false;
            foreach (CritterPower objPower in _objCharacter.CritterPowers)
            {
                if (objPower.Name == "Dual Natured")
                    blnHasPower = true;
            }
            if (!blnHasPower)
            {
                XmlDocument objXmlPowerDocument = XmlManager.Instance.Load("critterpowers.xml");
                XmlNode objXmlPowerNode = objXmlPowerDocument.SelectSingleNode("/chummer/powers/power[name = \"Dual Natured\"]");

                TreeNode objNode = new TreeNode();
                CritterPower objCritterPower = new CritterPower(_objCharacter);
                objCritterPower.Create(objXmlPowerNode, _objCharacter, objNode);
                _objCharacter.CritterPowers.Add(objCritterPower);

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

            // Gain the Immunity (Normal Weapons) Critter Power if it does not yet exist.
            blnHasPower = false;
            foreach (CritterPower objPower in _objCharacter.CritterPowers)
            {
                if (objPower.Name == "Immunity" && objPower.Extra == "Normal Weapons")
                    blnHasPower = true;
            }
            if (!blnHasPower)
            {
                XmlDocument objXmlPowerDocument = XmlManager.Instance.Load("critterpowers.xml");
                XmlNode objXmlPowerNode = objXmlPowerDocument.SelectSingleNode("/chummer/powers/power[name = \"Immunity\"]");

                TreeNode objNode = new TreeNode();
                CritterPower objCritterPower = new CritterPower(_objCharacter);
                objCritterPower.Create(objXmlPowerNode, _objCharacter, objNode, 0, "Normal Weapons");
                _objCharacter.CritterPowers.Add(objCritterPower);

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

            mnuSpecialCyberzombie.Visible = false;

            _blnIsDirty = true;
            UpdateWindowTitle();

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

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

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

            ResetCharacter();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return true;
        }
Example #18
0
        private void mnuSpecialPossessInanimate_Click(object sender, EventArgs e)
        {
            // Make sure the Spirit has been saved first.
            if (_blnIsDirty)
            {
                if (MessageBox.Show(LanguageManager.Instance.GetString("Message_PossessionSave"), LanguageManager.Instance.GetString("MessageTitle_Possession"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
                    return;
            }

            // Prompt the user to select an inanimate Vessel.
            XmlDocument objVesselDoc = XmlManager.Instance.Load("vessels.xml");
            XmlNodeList objXmlMetatypeList = objVesselDoc.SelectNodes("/chummer/metatypes/metatype");
            List<ListItem> lstMetatype = new List<ListItem>();
            foreach (XmlNode objXmlMetatype in objXmlMetatypeList)
            {
                ListItem objItem = new ListItem();
                objItem.Value = objXmlMetatype["name"].InnerText;
                if (objXmlMetatype["translate"] != null)
                    objItem.Name = objXmlMetatype["translate"].InnerText;
                else
                    objItem.Name = objXmlMetatype["name"].InnerText;
                lstMetatype.Add(objItem);
            }

            frmSelectItem frmSelectVessel = new frmSelectItem();
            frmSelectVessel.GeneralItems = lstMetatype;
            frmSelectVessel.ShowDialog(this);

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

            // Load the Spirit's save file into a new Merge character.
            Character objMerge = new Character();
            objMerge.FileName = _objCharacter.FileName;
            objMerge.Load();
            objMerge.Possessed = true;
            objMerge.Alias = frmSelectVessel.SelectedItem + " (" + LanguageManager.Instance.GetString("String_Possessed") + ")";

            // Get the Node for the selected Vessel.
            XmlNode objSelected = objVesselDoc.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + frmSelectVessel.SelectedItem + "\"]");

            // Get the Attribute Modifiers for the Vessel.
            int intBOD = Convert.ToInt32(objSelected["bodmin"].InnerText);
            int intAGI = Convert.ToInt32(objSelected["agimin"].InnerText);
            int intREA = Convert.ToInt32(objSelected["reamin"].InnerText);
            int intSTR = Convert.ToInt32(objSelected["strmin"].InnerText);

            // Add the Attribute modifiers, making sure that none of them go below 1.
            int intSetBOD = objMerge.MAG.TotalValue + intBOD;
            int intSetAGI = objMerge.MAG.TotalValue + intAGI;
            int intSetREA = objMerge.MAG.TotalValue + intREA;
            int intSetSTR = objMerge.MAG.TotalValue + intSTR;

            objMerge.BOD.MetatypeMinimum += intBOD;
            if (objMerge.BOD.MetatypeMinimum < 1)
                objMerge.BOD.MetatypeMinimum = 1;
            objMerge.BOD.MetatypeMaximum += intBOD;
            if (objMerge.BOD.MetatypeMaximum < 1)
                objMerge.BOD.MetatypeMaximum = 1;
            objMerge.BOD.Value = intSetBOD;
            if (objMerge.BOD.Value < 1)
                objMerge.BOD.Value = 1;

            objMerge.AGI.MetatypeMinimum += intAGI;
            if (objMerge.AGI.MetatypeMinimum < 1)
                objMerge.AGI.MetatypeMinimum = 1;
            objMerge.AGI.MetatypeMaximum += intAGI;
            if (objMerge.AGI.MetatypeMaximum < 1)
                objMerge.AGI.MetatypeMaximum = 1;
            objMerge.AGI.Value = intSetAGI;
            if (objMerge.AGI.Value < 1)
                objMerge.AGI.Value = 1;

            objMerge.REA.MetatypeMinimum += intREA;
            if (objMerge.REA.MetatypeMinimum < 1)
                objMerge.REA.MetatypeMinimum = 1;
            objMerge.REA.MetatypeMaximum += intREA;
            if (objMerge.REA.MetatypeMaximum < 1)
                objMerge.REA.MetatypeMaximum = 1;
            objMerge.REA.Value = intSetREA;
            if (objMerge.REA.Value < 1)
                objMerge.REA.Value = 1;

            objMerge.STR.MetatypeMinimum += intSTR;
            if (objMerge.STR.MetatypeMinimum < 1)
                objMerge.STR.MetatypeMinimum = 1;
            objMerge.STR.MetatypeMaximum += intSTR;
            if (objMerge.STR.MetatypeMaximum < 1)
                objMerge.STR.MetatypeMaximum = 1;
            objMerge.STR.Value = intSetSTR;
            if (objMerge.STR.Value < 1)
                objMerge.STR.Value = 1;

            // Update the Movement if the Vessel has one.
            if (objSelected["movement"] != null)
                objMerge.Movement = objSelected["movement"].InnerText;

            // Add any additional Critter Powers the Vessel grants.
            if (objSelected["powers"] != null)
            {
                XmlDocument objXmlPowerDoc = XmlManager.Instance.Load("critterpowers.xml");
                foreach (XmlNode objXmlPower in objSelected.SelectNodes("powers/power"))
                {
                    XmlNode objXmlCritterPower = objXmlPowerDoc.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                    CritterPower objPower = new CritterPower(objMerge);
                    string strSelect = "";
                    int intRating = 0;
                    if (objXmlPower.Attributes["select"] != null)
                        strSelect = objXmlPower.Attributes["select"].InnerText;
                    if (objXmlPower.Attributes["rating"] != null)
                        intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);

                    TreeNode objDummy = new TreeNode();
                    objPower.Create(objXmlCritterPower, objMerge, objDummy, intRating, strSelect);

                    objMerge.CritterPowers.Add(objPower);
                }
            }

            // Give the Critter the Immunity to Normal Weapons Power if they don't already have it.
            bool blnHasImmunity = false;
            foreach (CritterPower objCritterPower in objMerge.CritterPowers)
            {
                if (objCritterPower.Name == "Immunity" && objCritterPower.Extra == "Normal Weapons")
                {
                    blnHasImmunity = true;
                    break;
                }
            }
            if (!blnHasImmunity)
            {
                XmlDocument objPowerDoc = new XmlDocument();
                objPowerDoc = XmlManager.Instance.Load("critterpowers.xml");
                XmlNode objPower = objPowerDoc.SelectSingleNode("/chummer/powers/power[name = \"Immunity\"]");

                CritterPower objCritterPower = new CritterPower(objMerge);
                TreeNode objDummy = new TreeNode();
                objCritterPower.Create(objPower, objMerge, objDummy, 0, "Normal Weapons");
                objMerge.CritterPowers.Add(objCritterPower);
            }

            // Add any Improvements the Vessel grants.
            if (objSelected["bonus"] != null)
            {
                ImprovementManager objMergeManager = new ImprovementManager(objMerge);
                objMergeManager.CreateImprovements(Improvement.ImprovementSource.Metatype, frmSelectVessel.SelectedItem, objSelected["bonus"], false, 1, frmSelectVessel.SelectedItem);
            }

            // Now that everything is done, save the merged character and open them.
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*";

            string strShowFileName = "";
            string[] strFile = _objCharacter.FileName.Split(Path.DirectorySeparatorChar);
            strShowFileName = strFile[strFile.Length - 1];

            if (strShowFileName == "")
                strShowFileName = _objCharacter.Alias;
            strShowFileName = strShowFileName.Replace(".chum5", string.Empty);

            strShowFileName += " (" + LanguageManager.Instance.GetString("String_Possessed") + ")";

            saveFileDialog.FileName = strShowFileName;

            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                objMerge.FileName = saveFileDialog.FileName;
                objMerge.Save();

                // Get the name of the file and destroy the references to the Vessel and the merged character.
                string strOpenFile = objMerge.FileName;
                objMerge = null;

                GlobalOptions.Instance.MainForm.LoadCharacter(strOpenFile);
            }
            else
            {
                // The save process was canceled, so drop everything.
                objMerge = null;
            }
        }
Example #19
0
        private void mnuSpecialConvertToFreeSprite_Click(object sender, EventArgs e)
        {
            XmlDocument objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
            XmlNode objXmlPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Denial\"]");
            TreeNode objNode = new TreeNode();
            CritterPower objPower = new CritterPower(_objCharacter);
            objPower.Create(objXmlPower, _objCharacter, objNode);
            objPower.CountTowardsLimit = false;
            objNode.ContextMenuStrip = cmsCritterPowers;
            if (objPower.InternalId == Guid.Empty.ToString())
                return;

            _objCharacter.CritterPowers.Add(objPower);

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

            _objCharacter.MetatypeCategory = "Free Sprite";
            mnuSpecialConvertToFreeSprite.Visible = false;

            treCritterPowers.SortCustom();
            UpdateCharacterInfo();

            _blnIsDirty = true;
            UpdateWindowTitle();
        }
Example #20
0
        private void mnuSpecialPossess_Click(object sender, EventArgs e)
        {
            // Make sure the Spirit has been saved first.
            if (_blnIsDirty)
            {
                if (MessageBox.Show(LanguageManager.Instance.GetString("Message_PossessionSave"), LanguageManager.Instance.GetString("MessageTitle_Possession"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
                    return;
            }

            // Prompt the user to select a save file to possess.
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*";

            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                Character objVessel = new Character();
                objVessel.FileName = openFileDialog.FileName;
                objVessel.Load();
                // Make sure the Vessel is in Career Mode.
                if (!objVessel.Created)
                {
                    MessageBox.Show(LanguageManager.Instance.GetString("Message_VesselInCareerMode"), LanguageManager.Instance.GetString("MessageTitle_Possession"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                    objVessel = null;
                    return;
                }

                // Load the Spirit's save file into a new Merge character.
                Character objMerge = new Character();
                objMerge.FileName = _objCharacter.FileName;
                objMerge.Load();
                objMerge.Possessed = true;
                objMerge.Alias = objVessel.Alias + " (" + LanguageManager.Instance.GetString("String_Possessed") + ")";

                // Give the Critter the Immunity to Normal Weapons Power if they don't already have it.
                bool blnHasImmunity = false;
                foreach (CritterPower objCritterPower in objMerge.CritterPowers)
                {
                    if (objCritterPower.Name == "Immunity" && objCritterPower.Extra == "Normal Weapons")
                    {
                        blnHasImmunity = true;
                        break;
                    }
                }
                if (!blnHasImmunity)
                {
                    XmlDocument objPowerDoc = new XmlDocument();
                    objPowerDoc = XmlManager.Instance.Load("critterpowers.xml");
                    XmlNode objPower = objPowerDoc.SelectSingleNode("/chummer/powers/power[name = \"Immunity\"]");

                    CritterPower objCritterPower = new CritterPower(objMerge);
                    TreeNode objDummy = new TreeNode();
                    objCritterPower.Create(objPower, objMerge, objDummy, 0, "Normal Weapons");
                    objMerge.CritterPowers.Add(objCritterPower);
                }

                // Add the Vessel's Physical Attributes to the Spirit's Force.
                objMerge.BOD.MetatypeMaximum = objVessel.BOD.Value + objMerge.MAG.TotalValue;
                objMerge.BOD.Value = objVessel.BOD.Value + objMerge.MAG.TotalValue;
                objMerge.AGI.MetatypeMaximum = objVessel.AGI.Value + objMerge.MAG.TotalValue;
                objMerge.AGI.Value = objVessel.AGI.Value + objMerge.MAG.TotalValue;
                objMerge.REA.MetatypeMaximum = objVessel.REA.Value + objMerge.MAG.TotalValue;
                objMerge.REA.Value = objVessel.REA.Value + objMerge.MAG.TotalValue;
                objMerge.STR.MetatypeMaximum = objVessel.STR.Value + objMerge.MAG.TotalValue;
                objMerge.STR.Value = objVessel.STR.Value + objMerge.MAG.TotalValue;

                // Copy any Lifestyles the Vessel has.
                foreach (Lifestyle objLifestyle in objVessel.Lifestyles)
                    objMerge.Lifestyles.Add(objLifestyle);

                // Copy any Armor the Vessel has.
                foreach (Armor objArmor in objVessel.Armor)
                {
                    objMerge.Armor.Add(objArmor);
                    CopyArmorImprovements(objVessel, objMerge, objArmor);
                }

                // Copy any Gear the Vessel has.
                foreach (Gear objGear in objVessel.Gear)
                {
                    objMerge.Gear.Add(objGear);
                    CopyGearImprovements(objVessel, objMerge, objGear);
                }

                // Copy any Cyberware/Bioware the Vessel has.
                foreach (Cyberware objCyberware in objVessel.Cyberware)
                {
                    objMerge.Cyberware.Add(objCyberware);
                    CopyCyberwareImprovements(objVessel, objMerge, objCyberware);
                }

                // Copy any Weapons the Vessel has.
                foreach (Weapon objWeapon in objVessel.Weapons)
                    objMerge.Weapons.Add(objWeapon);

                // Copy and Vehicles the Vessel has.
                foreach (Vehicle objVehicle in objVessel.Vehicles)
                    objMerge.Vehicles.Add(objVehicle);

                // Copy the character info.
                objMerge.Sex = objVessel.Sex;
                objMerge.Age = objVessel.Age;
                objMerge.Eyes = objVessel.Eyes;
                objMerge.Hair = objVessel.Hair;
                objMerge.Height = objVessel.Height;
                objMerge.Weight = objVessel.Weight;
                objMerge.Skin = objVessel.Skin;
                objMerge.Name = objVessel.Name;
                objMerge.StreetCred = objVessel.StreetCred;
                objMerge.BurntStreetCred = objVessel.BurntStreetCred;
                objMerge.Notoriety = objVessel.Notoriety;
                objMerge.PublicAwareness = objVessel.PublicAwareness;
                objMerge.Mugshot = objVessel.Mugshot;

                // Now that everything is done, save the merged character and open them.
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*";

                string strShowFileName = "";
                string[] strFile = _objCharacter.FileName.Split(Path.DirectorySeparatorChar);
                strShowFileName = strFile[strFile.Length - 1];

                if (strShowFileName == "")
                    strShowFileName = _objCharacter.Alias;
                strShowFileName = strShowFileName.Replace(".chum5", string.Empty);

                strShowFileName += " (" + LanguageManager.Instance.GetString("String_Possessed") + ")";

                saveFileDialog.FileName = strShowFileName;

                if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
                {
                    objMerge.FileName = saveFileDialog.FileName;
                    objMerge.Save();

                    // Get the name of the file and destroy the references to the Vessel and the merged character.
                    string strOpenFile = objMerge.FileName;
                    objMerge = null;
                    objVessel = null;

                    GlobalOptions.Instance.MainForm.LoadCharacter(strOpenFile);
                }
                else
                {
                    // The save process was canceled, so drop everything.
                    objMerge = null;
                    objVessel = null;
                }
            }
        }
Example #21
0
        private void cmdAddQuality_Click(object sender, EventArgs e)
        {
            frmSelectQuality frmPickQuality = new frmSelectQuality(_objCharacter);
            frmPickQuality.ShowDialog(this);

            // Don't do anything else if the form was canceled.
            if (frmPickQuality.DialogResult == DialogResult.Cancel)
                return;

            XmlDocument objXmlDocument = XmlManager.Instance.Load("qualities.xml");
            XmlNode objXmlQuality = objXmlDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + frmPickQuality.SelectedQuality + "\"]");
            TreeNode objNode = new TreeNode();
            List<Weapon> objWeapons = new List<Weapon>();
            List<TreeNode> objWeaponNodes = new List<TreeNode>();
            Quality objQuality = new Quality(_objCharacter);

            objQuality.Create(objXmlQuality, _objCharacter, QualitySource.Selected, objNode, objWeapons, objWeaponNodes);
            objNode.ContextMenuStrip = cmsQuality;
            if (objQuality.InternalId == Guid.Empty.ToString())
                return;

            if (frmPickQuality.FreeCost)
                objQuality.BP = 0;

            // If the item being checked would cause the limit of 25 BP spent on Positive Qualities to be exceed, do not let it be checked and display a message.
            string strAmount = "";
            int intMaxQualityAmount = 0;
            strAmount = _objCharacter.GameplayOptionQualityLimit.ToString() + " " + LanguageManager.Instance.GetString("String_Karma");
            intMaxQualityAmount = _objCharacter.GameplayOptionQualityLimit;

            // Make sure that adding the Quality would not cause the character to exceed their BP limits.
            int intBP = 0;
            bool blnAddItem = true;

            // Add the cost of the Quality that is being added.
            if (objQuality.ContributeToLimit)
                intBP += objQuality.BP;

            if (objQuality.Type == QualityType.Negative)
            {
                // Calculate the cost of the current Negative Qualities.
                foreach (Quality objCharacterQuality in _objCharacter.Qualities)
                {
                    if (objCharacterQuality.Type == QualityType.Negative && objCharacterQuality.ContributeToLimit)
                        intBP += objCharacterQuality.BP;
                }

                // Include the BP used by Enemies.
                if (lblEnemiesBP.Text.Contains(LanguageManager.Instance.GetString("String_BP")))
                    intBP += int.Parse(lblEnemiesBP.Text.Replace(LanguageManager.Instance.GetString("String_Karma"), ""));
                else
                    intBP += int.Parse(lblEnemiesBP.Text.Replace(" " + LanguageManager.Instance.GetString("String_Karma"), ""));

                // Include the amount from Free Negative Quality BP cost Improvements.
                intBP -= (_objImprovementManager.ValueOf(Improvement.ImprovementType.FreeNegativeQualities) * _objOptions.KarmaQuality);

                // Check if adding this Quality would put the character over their limit.
                if (!_objOptions.ExceedNegativeQualities)
                {
                    if (intBP < (intMaxQualityAmount * -1) && !_objCharacter.IgnoreRules)
                    {
                        MessageBox.Show(LanguageManager.Instance.GetString("Message_NegativeQualityLimit").Replace("{0}", strAmount), LanguageManager.Instance.GetString("MessageTitle_NegativeQualityLimit"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                        blnAddItem = false;
                    }
                    if (_objCharacter.MetatypeBP < 0)
                    {
                        if ((intBP + _objCharacter.MetatypeBP) < (intMaxQualityAmount * -1) && !_objCharacter.IgnoreRules)
                        {
                            MessageBox.Show(LanguageManager.Instance.GetString("Message_NegativeQualityAndMetatypeLimit").Replace("{0}", strAmount), LanguageManager.Instance.GetString("MessageTitle_NegativeQualityLimit"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                            blnAddItem = false;
                        }
                    }
                    {

                    }
                }
            }
            else
            {
                // Calculate the cost of the current Positive Qualities.
                foreach (Quality objCharacterQuality in _objCharacter.Qualities)
                {
                    if (objCharacterQuality.Type == QualityType.Positive && objCharacterQuality.ContributeToLimit)
                        intBP += objCharacterQuality.BP;
                }
                if (_objCharacter.BuildMethod == CharacterBuildMethod.Karma)
                    intBP *= _objOptions.KarmaQuality;

                // Include the amount from Free Negative Quality BP cost Improvements.
                intBP -= (_objImprovementManager.ValueOf(Improvement.ImprovementType.FreePositiveQualities) * _objOptions.KarmaQuality);

                // Check if adding this Quality would put the character over their limit.
                if (!_objOptions.ExceedPositiveQualities)
                {
                    if (intBP > intMaxQualityAmount && !_objCharacter.IgnoreRules)
                    {
                        MessageBox.Show(LanguageManager.Instance.GetString("Message_PositiveQualityLimit").Replace("{0}", strAmount), LanguageManager.Instance.GetString("MessageTitle_PositiveQualityLimit"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                        blnAddItem = false;
                    }
                }
            }

            if (blnAddItem)
            {
                // Add the Quality to the appropriate parent node.
                if (objQuality.Type == QualityType.Positive)
                {
                    treQualities.Nodes[0].Nodes.Add(objNode);
                    treQualities.Nodes[0].Expand();
                }
                else
                {
                    treQualities.Nodes[1].Nodes.Add(objNode);
                    treQualities.Nodes[1].Expand();
                }
                _objCharacter.Qualities.Add(objQuality);

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

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

                // Add any additional Qualities that are forced on the character.
                if (objXmlQuality.SelectNodes("addqualities/addquality").Count > 0)
                {
                    foreach (XmlNode objXmlAddQuality in objXmlQuality.SelectNodes("addqualities/addquality"))
                    {
                        XmlNode objXmlSelectedQuality = objXmlDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlAddQuality.InnerText + "\"]");
                        Quality objSubQuality = AddQuality(objXmlAddQuality, objXmlSelectedQuality, objWeapons, objWeaponNodes);
                        if (objSubQuality != null)
                            {
                            _objCharacter.Qualities.Add(objSubQuality);
                            }
                        }
                }

                // Add any Critter Powers that are gained through the Quality (Infected).
                if (objXmlQuality.SelectNodes("powers/power").Count > 0)
                {
                    objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
                    foreach (XmlNode objXmlPower in objXmlQuality.SelectNodes("powers/power"))
                    {
                        XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + objXmlPower.InnerText + "\"]");
                        TreeNode objPowerNode = new TreeNode();
                        CritterPower objPower = new CritterPower(_objCharacter);
                        string strForcedValue = "";
                        int intRating = 0;

                        if (objXmlPower.Attributes["rating"] != null)
                            intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                        if (objXmlPower.Attributes["select"] != null)
                            strForcedValue = objXmlPower.Attributes["select"].InnerText;

                        objPower.Create(objXmlCritterPower, _objCharacter, objPowerNode, intRating, strForcedValue);
                        _objCharacter.CritterPowers.Add(objPower);

                        if (objPower.Category != "Weakness")
                        {
                            treCritterPowers.Nodes[0].Nodes.Add(objPowerNode);
                            treCritterPowers.Nodes[0].Expand();
                        }
                        else
                        {
                            treCritterPowers.Nodes[1].Nodes.Add(objPowerNode);
                            treCritterPowers.Nodes[1].Expand();
                        }
                    }
                }
            }
            else
            {
                // If the Quality could not be added, remove the Improvements that were added during the Quality Creation process.
                _objImprovementManager.RemoveImprovements(Improvement.ImprovementSource.Quality, objQuality.InternalId);
            }

            // If the Quality is a mentor spirit, add any qualities particular to the mentor spirit.
            if (objQuality.Name == "Mentor Spirit")
            {
                XmlDocument objXmlMentors = XmlManager.Instance.Load("mentors.xml");
                XmlNode objXmlMentor = objXmlMentors.SelectSingleNode("/chummer/mentors/mentor[name = \"" + objQuality.Extra + "\"]");
                XmlNode objXmlAddQualities = objXmlMentor["addqualities"];

                // If there are additional qualities
                if (objXmlAddQualities != null)
                {
                    foreach (XmlNode objXmlAddQuality in objXmlAddQualities.ChildNodes)
                    {
                        XmlNode objXmlMentorQuality = objXmlDocument.SelectSingleNode("/chummer/qualities/quality[name = \"" + objXmlAddQuality.InnerText + "\"]");

                        TreeNode objMentorNode = new TreeNode();
                        List<Weapon> objMentorWeapons = new List<Weapon>();
                        List<TreeNode> objMentorWeaponNodes = new List<TreeNode>();
                        Quality objSpiritQuality = new Quality(_objCharacter);
                        string strExtra = "";
                        if (objXmlAddQuality.Attributes["select"] != null)
                        {
                            strExtra = objXmlAddQuality.Attributes["select"].InnerText.ToString();
                            objSpiritQuality.Create(objXmlMentorQuality, _objCharacter, QualitySource.Selected, objMentorNode, objMentorWeapons, objMentorWeaponNodes, strExtra);
                        }
                        else
                            objSpiritQuality.Create(objXmlMentorQuality, _objCharacter, QualitySource.Selected, objMentorNode, objMentorWeapons, objMentorWeaponNodes);

                        objSpiritQuality.BP = 0;

                        // Add the quality to the character
                        if (objSpiritQuality.Type == QualityType.Positive)
                        {
                            treQualities.Nodes[0].Nodes.Add(objMentorNode);
                            treQualities.Nodes[0].Expand();
                        }
                        else
                        {
                            treQualities.Nodes[1].Nodes.Add(objMentorNode);
                            treQualities.Nodes[1].Expand();
                        }
                        _objCharacter.Qualities.Add(objSpiritQuality);
                    }
                }
            }

            treQualities.SortCustom();
            UpdateMentorSpirits();
            UpdateCharacterInfo();
            RefreshMartialArts();
            RefreshPowers();
            RefreshContacts();

            _blnIsDirty = true;
            UpdateWindowTitle();

            if (frmPickQuality.AddAgain)
                cmdAddQuality_Click(sender, e);
        }
Example #22
0
        /// <summary>
        /// Load the character's Metatype information from the XML file.
        /// </summary>
        /// <param name="guiMetatype">GUID of the Metatype to load.</param>
        /// <param name="strXmlFile">Name of the XML file to load from (default: metatypes.xml).</param>
        /// <param name="intForce">Force that the Spirit was summoned with (default: 0).</param>
        /// <param name="blnBloodSpirit">Whether or not this character is a Blood Spirit (default: false).</param>
        /// <param name="blnPossessionBased">Whether or not this Spirit uses a Possession-based tradition (default: false).</param>
        /// <param name="strPossessionMethod">Possession method the Spirit uses (default: empty).</param>
        public void LoadMetatype(Guid guiMetatype, string strXmlFile = "metatypes.xml", int intForce = 0, bool blnBloodSpirit = false, bool blnPossessionBased = false, string strPossessionMethod = "")
        {
            ImprovementManager objImprovementManager = new ImprovementManager(this);
            XmlDocument objXmlDocument = XmlManager.Instance.Load(strXmlFile);

            XmlNode objXmlMetatype = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[id = \"" + guiMetatype.ToString() + "\"]");

            _guiMetatype = guiMetatype;

            // Set Metatype information.
            if (strXmlFile != "critters.xml")
            {
                BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["bodaug"].InnerText, intForce, 0));
                AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agimax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["agiaug"].InnerText, intForce, 0));
                REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["reaaug"].InnerText, intForce, 0));
                STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["strmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["straug"].InnerText, intForce, 0));
                CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chamax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["chaaug"].InnerText, intForce, 0));
                INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["intaug"].InnerText, intForce, 0));
                LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["logaug"].InnerText, intForce, 0));
                WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["wilaug"].InnerText, intForce, 0));
                MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["magaug"].InnerText, intForce, 0));
                RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["resaug"].InnerText, intForce, 0));
                EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["edgaug"].InnerText, intForce, 0));
                ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }
            else
            {
                int intMinModifier = -3;
                if (objXmlMetatype["category"].InnerText == "Mutant Critters")
                    intMinModifier = 0;
                BOD.AssignLimits(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 3));
                AGI.AssignLimits(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 3));
                REA.AssignLimits(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 3));
                STR.AssignLimits(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 3));
                CHA.AssignLimits(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 3));
                INT.AssignLimits(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 3));
                LOG.AssignLimits(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 3));
                WIL.AssignLimits(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 3));
                MAG.AssignLimits(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 3));
                RES.AssignLimits(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 3));
                EDG.AssignLimits(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, intMinModifier), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3), ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 3));
                ESS.AssignLimits(ExpressionToString(objXmlMetatype["essmin"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0), ExpressionToString(objXmlMetatype["essaug"].InnerText, intForce, 0));
            }

            // If we're working with a Critter, set the Attributes to their default values.
            if (strXmlFile == "critters.xml")
            {
                BOD.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["bodmin"].InnerText, intForce, 0));
                AGI.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["agimin"].InnerText, intForce, 0));
                REA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["reamin"].InnerText, intForce, 0));
                STR.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["strmin"].InnerText, intForce, 0));
                CHA.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["chamin"].InnerText, intForce, 0));
                INT.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["intmin"].InnerText, intForce, 0));
                LOG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["logmin"].InnerText, intForce, 0));
                WIL.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["wilmin"].InnerText, intForce, 0));
                MAG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["magmin"].InnerText, intForce, 0));
                RES.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["resmin"].InnerText, intForce, 0));
                EDG.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["edgmin"].InnerText, intForce, 0));
                ESS.Value = Convert.ToInt32(ExpressionToString(objXmlMetatype["essmax"].InnerText, intForce, 0));
            }

            // Sprites can never have Physical Attributes or WIL.
            if (objXmlMetatype["category"].InnerText.EndsWith("Sprite"))
            {
                BOD.AssignLimits("0", "0", "0");
                AGI.AssignLimits("0", "0", "0");
                REA.AssignLimits("0", "0", "0");
                STR.AssignLimits("0", "0", "0");
                WIL.AssignLimits("0", "0", "0");
            }

            Metatype = objXmlMetatype["name"].InnerText;
            MetatypeCategory = objXmlMetatype["category"].InnerText;
            Metavariant = "";
            MetatypeBP = 0;

            _intWalk = Convert.ToInt32(objXmlMetatype["walk"].InnerText);
            _intRun = Convert.ToInt32(objXmlMetatype["run"].InnerText);
            _intSprint = Convert.ToInt32(objXmlMetatype["sprint"].InnerText);

            // Load the Qualities file.
            XmlDocument objXmlQualityDocument = XmlManager.Instance.Load("qualities.xml");

            // Determine if the Metatype has any bonuses.
            if (objXmlMetatype["bonus"] != null)
                objImprovementManager.CreateImprovements(Improvement.ImprovementSource.Metatype, Metatype, objXmlMetatype.SelectSingleNode("bonus"), false, 1, Metatype);

            // Create the Qualities that come with the Metatype.
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/positive/quality"))
            {
                XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[id = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                List<Weapon> objWeapons = new List<Weapon>();
                List<TreeNode> objWeaponNodes = new List<TreeNode>();
                Quality objQuality = new Quality(this);
                string strForceValue = "";
                if (objXmlQualityItem.Attributes["select"] != null)
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                QualitySource objSource = new QualitySource();
                objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"] != null)
                    objSource = QualitySource.MetatypeRemovable;
                objQuality.Create(objXmlQuality, this, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                Qualities.Add(objQuality);

                // Add any created Weapons to the character.
                foreach (Weapon objWeapon in objWeapons)
                    Weapons.Add(objWeapon);
            }
            foreach (XmlNode objXmlQualityItem in objXmlMetatype.SelectNodes("qualities/negative/quality"))
            {
                XmlNode objXmlQuality = objXmlQualityDocument.SelectSingleNode("/chummer/qualities/quality[id = \"" + objXmlQualityItem.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                List<Weapon> objWeapons = new List<Weapon>();
                List<TreeNode> objWeaponNodes = new List<TreeNode>();
                Quality objQuality = new Quality(this);
                string strForceValue = "";
                if (objXmlQualityItem.Attributes["select"] != null)
                    strForceValue = objXmlQualityItem.Attributes["select"].InnerText;
                QualitySource objSource = new QualitySource();
                objSource = QualitySource.Metatype;
                if (objXmlQualityItem.Attributes["removable"] != null)
                    objSource = QualitySource.MetatypeRemovable;
                objQuality.Create(objXmlQuality, this, objSource, objNode, objWeapons, objWeaponNodes, strForceValue);
                Qualities.Add(objQuality);

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

            // Run through the character's Attributes one more time and make sure their value matches their minimum value.
            if (strXmlFile == "metatypes.xml")
            {
                BOD.Value = BOD.TotalMinimum;
                AGI.Value = AGI.TotalMinimum;
                REA.Value = REA.TotalMinimum;
                STR.Value = STR.TotalMinimum;
                CHA.Value = CHA.TotalMinimum;
                INT.Value = INT.TotalMinimum;
                LOG.Value = LOG.TotalMinimum;
                WIL.Value = WIL.TotalMinimum;
            }

            // Add any Critter Powers the Metatype/Critter should have.
            XmlNode objXmlCritter = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[id = \"" + guiMetatype.ToString() + "\"]");

            objXmlDocument = XmlManager.Instance.Load("critterpowers.xml");
            foreach (XmlNode objXmlPower in objXmlCritter.SelectNodes("powers/power"))
            {
                XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[id = \"" + objXmlPower.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                CritterPower objPower = new CritterPower(this);
                string strForcedValue = "";
                int intRating = 0;

                if (objXmlPower.Attributes["rating"] != null)
                    intRating = Convert.ToInt32(objXmlPower.Attributes["rating"].InnerText);
                if (objXmlPower.Attributes["select"] != null)
                    strForcedValue = objXmlPower.Attributes["select"].InnerText;

                objPower.Create(objXmlCritterPower, this, objNode, intRating, strForcedValue);
                objPower.CountTowardsLimit = false;
                CritterPowers.Add(objPower);
            }

            // If this is a Blood Spirit, add their free Critter Powers.
            if (blnBloodSpirit)
            {
                XmlNode objXmlCritterPower;
                TreeNode objNode;
                CritterPower objPower;
                bool blnAddPower = true;

                // Energy Drain.
                foreach (CritterPower objFindPower in CritterPowers)
                {
                    if (objFindPower.Name == "Energy Drain")
                    {
                        blnAddPower = false;
                        break;
                    }
                }
                if (blnAddPower)
                {
                    objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Energy Drain\"]");
                    objNode = new TreeNode();
                    objPower = new CritterPower(this);
                    objPower.Create(objXmlCritterPower, this, objNode, 0, "");
                    objPower.CountTowardsLimit = false;
                    CritterPowers.Add(objPower);
                }

                // Fear.
                blnAddPower = true;
                foreach (CritterPower objFindPower in CritterPowers)
                {
                    if (objFindPower.Name == "Fear")
                    {
                        blnAddPower = false;
                        break;
                    }
                }
                if (blnAddPower)
                {
                    objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Fear\"]");
                    objNode = new TreeNode();
                    objPower = new CritterPower(this);
                    objPower.Create(objXmlCritterPower, this, objNode, 0, "");
                    objPower.CountTowardsLimit = false;
                    CritterPowers.Add(objPower);
                }

                // Natural Weapon.
                objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Natural Weapon\"]");
                objNode = new TreeNode();
                objPower = new CritterPower(this);
                objPower.Create(objXmlCritterPower, this, objNode, 0, "DV " + intForce.ToString() + "P, AP 0");
                objPower.CountTowardsLimit = false;
                CritterPowers.Add(objPower);

                // Evanescence.
                blnAddPower = true;
                foreach (CritterPower objFindPower in CritterPowers)
                {
                    if (objFindPower.Name == "Evanescence")
                    {
                        blnAddPower = false;
                        break;
                    }
                }
                if (blnAddPower)
                {
                    objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"Evanescence\"]");
                    objNode = new TreeNode();
                    objPower = new CritterPower(this);
                    objPower.Create(objXmlCritterPower, this, objNode, 0, "");
                    objPower.CountTowardsLimit = false;
                    CritterPowers.Add(objPower);
                }
            }

            // Remove the Critter's Materialization Power if they have it. Add the Possession or Inhabitation Power if the Possession-based Tradition checkbox is checked.
            if (blnPossessionBased)
            {
                foreach (CritterPower objCritterPower in CritterPowers)
                {
                    if (objCritterPower.Name == "Materialization")
                    {
                        CritterPowers.Remove(objCritterPower);
                        break;
                    }
                }

                // Add the selected Power.
                XmlNode objXmlCritterPower = objXmlDocument.SelectSingleNode("/chummer/powers/power[name = \"" + strPossessionMethod + "\"]");
                TreeNode objNode = new TreeNode();
                CritterPower objPower = new CritterPower(this);
                objPower.Create(objXmlCritterPower, this, objNode, 0, "");
                objPower.CountTowardsLimit = false;
                CritterPowers.Add(objPower);
            }

            // Set the Skill Ratings for the Critter.
            foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/skill"))
            {
                if (objXmlSkill.InnerText.Contains("Exotic"))
                {
                    Skill objExotic = new Skill(this);
                    objExotic.ExoticSkill = true;
                    objExotic.Attribute = "AGI";
                    if (objXmlSkill.Attributes["spec"] != null)
                        objExotic.Specialization = objXmlSkill.Attributes["spec"].InnerText;
                    if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0)) > 6)
                        objExotic.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0));
                    objExotic.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0));
                    objExotic.Name = objXmlSkill.InnerText;
                    Skills.Add(objExotic);
                }
                else
                {
                    foreach (Skill objSkill in Skills)
                    {
                        if (objSkill.Name == objXmlSkill.InnerText)
                        {
                            if (objXmlSkill.Attributes["spec"] != null)
                                objSkill.Specialization = objXmlSkill.Attributes["spec"].InnerText;
                            if (Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0)) > 6)
                                objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0));
                            objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0));
                            break;
                        }
                    }
                }
            }

            // Set the Skill Group Ratings for the Critter.
            foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/group"))
            {
                foreach (SkillGroup objSkill in SkillGroups)
                {
                    if (objSkill.Name == objXmlSkill.InnerText)
                    {
                        objSkill.RatingMaximum = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0));
                        objSkill.Rating = Convert.ToInt32(ExpressionToString(objXmlSkill.Attributes["rating"].InnerText, intForce, 0));
                        break;
                    }
                }
            }

            // Set the Knowledge Skill Ratings for the Critter.
            foreach (XmlNode objXmlSkill in objXmlCritter.SelectNodes("skills/knowledge"))
            {
                Skill objKnowledge = new Skill(this);
                objKnowledge.Name = objXmlSkill.InnerText;
                objKnowledge.KnowledgeSkill = true;
                if (objXmlSkill.Attributes["spec"] != null)
                    objKnowledge.Specialization = objXmlSkill.Attributes["spec"].InnerText;
                objKnowledge.SkillCategory = objXmlSkill.Attributes["category"].InnerText;
                if (Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText) > 6)
                    objKnowledge.RatingMaximum = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                objKnowledge.Rating = Convert.ToInt32(objXmlSkill.Attributes["rating"].InnerText);
                Skills.Add(objKnowledge);
            }

            // If this is a Critter with a Force (which dictates their Skill Rating/Maximum Skill Rating), set their Skill Rating Maximums.
            if (intForce > 0)
            {
                int intMaxRating = intForce;
                // Determine the highest Skill Rating the Critter has.
                foreach (Skill objSkill in Skills)
                {
                    if (objSkill.RatingMaximum > intMaxRating)
                        intMaxRating = objSkill.RatingMaximum;
                }

                // Now that we know the upper limit, set all of the Skill Rating Maximums to match.
                foreach (Skill objSkill in Skills)
                    objSkill.RatingMaximum = intMaxRating;
                foreach (SkillGroup objGroup in SkillGroups)
                    objGroup.RatingMaximum = intMaxRating;

                // Set the MaxSkillRating for the character so it can be used later when they add new Knowledge Skills or Exotic Skills.
                MaxSkillRating = intMaxRating;
            }

            // Add any Complex Forms the Critter comes with (typically Sprites)
            XmlDocument objXmlProgramDocument = XmlManager.Instance.Load("programs.xml");
            foreach (XmlNode objXmlComplexForm in objXmlCritter.SelectNodes("complexforms/complexform"))
            {
                int intRating = 0;
                if (objXmlComplexForm.Attributes["rating"] != null)
                    intRating = Convert.ToInt32(ExpressionToString(objXmlComplexForm.Attributes["rating"].InnerText, intForce, 0));
                string strForceValue = "";
                if (objXmlComplexForm.Attributes["select"] != null)
                    strForceValue = objXmlComplexForm.Attributes["select"].InnerText;
                XmlNode objXmlProgram = objXmlProgramDocument.SelectSingleNode("/chummer/programs/program[name = \"" + objXmlComplexForm.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                TechProgram objProgram = new TechProgram(this);
                objProgram.Create(objXmlProgram, this, objNode, strForceValue);
                objProgram.Rating = intRating;
                TechPrograms.Add(objProgram);

                // Add the Program Option if applicable.
                if (objXmlComplexForm.Attributes["option"] != null)
                {
                    int intOptRating = 0;
                    if (objXmlComplexForm.Attributes["optionrating"] != null)
                        intOptRating = Convert.ToInt32(ExpressionToString(objXmlComplexForm.Attributes["optionrating"].InnerText, intForce, 0));
                    string strOptForceValue = "";
                    if (objXmlComplexForm.Attributes["optionselect"] != null)
                        strOptForceValue = objXmlComplexForm.Attributes["optionselect"].InnerText;
                    XmlNode objXmlOption = objXmlProgramDocument.SelectSingleNode("/chummer/options/option[name = \"" + objXmlComplexForm.Attributes["option"].InnerText + "\"]");
                    TreeNode objNodeOpt = new TreeNode();
                    TechProgramOption objOption = new TechProgramOption(this);
                    objOption.Create(objXmlOption, this, objNodeOpt, strOptForceValue);
                    objOption.Rating = intOptRating;
                    objProgram.Options.Add(objOption);
                }
            }

            // Add any Gear the Critter comes with (typically Programs for A.I.s)
            XmlDocument objXmlGearDocument = XmlManager.Instance.Load("gear.xml");
            foreach (XmlNode objXmlGear in objXmlCritter.SelectNodes("gears/gear"))
            {
                int intRating = 0;
                if (objXmlGear.Attributes["rating"] != null)
                    intRating = Convert.ToInt32(ExpressionToString(objXmlGear.Attributes["rating"].InnerText, intForce, 0));
                string strForceValue = "";
                if (objXmlGear.Attributes["select"] != null)
                    strForceValue = objXmlGear.Attributes["select"].InnerText;
                XmlNode objXmlGearItem = objXmlGearDocument.SelectSingleNode("/chummer/gears/gear[id = \"" + objXmlGear.InnerText + "\"]");
                TreeNode objNode = new TreeNode();
                Gear objGear = new Gear(this);
                List<Weapon> lstWeapons = new List<Weapon>();
                List<TreeNode> lstWeaponNodes = new List<TreeNode>();
                objGear.Create(objXmlGearItem, this, objNode, intRating, lstWeapons, lstWeaponNodes, strForceValue);
                objGear.Cost = "0";
                objGear.Cost3 = "0";
                objGear.Cost6 = "0";
                objGear.Cost10 = "0";
                Gear.Add(objGear);
            }

            // If this is a Mutant Critter, count up the number of Skill points they start with.
            if (MetatypeCategory == "Mutant Critters")
            {
                foreach (Skill objSkill in Skills)
                    MutantCritterBaseSkills += objSkill.Rating;
            }
        }