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