/// <summary> /// Load from XML: Initializing constructor from an XML node. /// </summary> /// <param name="node">An <see cref="XmlNode"/> within /// a Nova component definition file (xml document). /// </param> public Component(XmlNode node) : base(node) { Properties = new Dictionary <string, ComponentProperty>(); XmlNode mainNode = node.FirstChild; while (mainNode != null) { try { switch (mainNode.Name.ToLower()) { case "mass": Mass = int.Parse(mainNode.FirstChild.Value, System.Globalization.CultureInfo.InvariantCulture); break; case "cost": Cost = new Resources(mainNode); break; case "tech": RequiredTech = new TechLevel(mainNode); break; case "description": XmlText xmltxtDescription = (XmlText)mainNode.FirstChild; if (xmltxtDescription != null) { this.Description = xmltxtDescription.Value; } break; case "race_restrictions": Restrictions = new RaceRestriction(mainNode); break; case "image": { // Paths are always stored in external files using forward slashes. ImageFile = mainNode.FirstChild.Value; ImageFile = ImageFile.Replace('/', Path.DirectorySeparatorChar); // relative or absolute path? we normally store the relative path but will handle loading either incase the file has been manually modified. try { FileInfo info = new FileInfo(ImageFile); if (info.Exists) { // was absolute, so keep as is and load up the image ComponentImage = new Bitmap(ImageFile); } else { { string graphicsPath = FileSearcher.GetGraphicsPath(); if (graphicsPath != null) { ImageFile = Path.Combine(graphicsPath, ImageFile); info = new FileInfo(ImageFile); } } if (info.Exists) { // now we have an absolute path, load the image ComponentImage = new Bitmap(ImageFile); } else { // No further action. FileSearcher will report an error (once only) if the graphics are not available. } } } catch (System.NotSupportedException) { // The path doesn't make sense, maybe it wasn't relative. // Don't change anything and don't load the image ImageFile = mainNode.FirstChild.Value.Replace('/', Path.DirectorySeparatorChar); ComponentImage = null; Report.Error("Unable to locate the image file " + ImageFile); } break; } case "property": { // Load the property. It may be of any type (Bomb, IntegerProperty, Hull, etc), so // check the save file first to determine what to load, and use the appropriate constructor. string propertyType = mainNode.SelectSingleNode("Type").FirstChild.Value; ComponentProperty newProperty; switch (propertyType.ToLower()) { case "armor": { newProperty = new IntegerProperty(mainNode); break; } case "battle movement": { newProperty = new DoubleProperty(mainNode); break; } case "beam deflector": { newProperty = new ProbabilityProperty(mainNode); break; } case "bomb": { newProperty = new Bomb(mainNode); break; } case "capacitor": { newProperty = new CapacitorProperty(mainNode); break; } case "cloak": { newProperty = new ProbabilityProperty(mainNode); break; } case "defense": { newProperty = new Defense(mainNode); break; } case "energy dampener": { newProperty = new DoubleProperty(mainNode); break; } case "cargo": { newProperty = new IntegerProperty(mainNode); break; } case "colonizer": { newProperty = new Colonizer(mainNode); break; } case "computer": { newProperty = new Computer(mainNode); break; } case "engine": { newProperty = new Engine(mainNode); break; } case "fuel": { newProperty = new Fuel(mainNode); break; } case "gate": { newProperty = new Gate(mainNode); break; } case "hull": { newProperty = new Hull(mainNode); break; } case "hull affinity": { newProperty = new HullAffinity(mainNode); break; } case "jammer": { newProperty = new ProbabilityProperty(mainNode); break; } case "mass driver": { newProperty = new MassDriver(mainNode); break; } case "mine layer": { newProperty = new MineLayer(mainNode); break; } case "mine layer efficiency": { newProperty = new DoubleProperty(mainNode); break; } case "mining robot": { newProperty = new IntegerProperty(mainNode); break; } case "orbital adjuster": { newProperty = new IntegerProperty(mainNode); break; } case "radiation": { newProperty = new Radiation(mainNode); break; } case "shield": { newProperty = new IntegerProperty(mainNode); break; } case "scanner": { newProperty = new Scanner(mainNode); break; } case "tachyon detector": { newProperty = new ProbabilityProperty(mainNode); break; } case "terraform": { newProperty = new Terraform(mainNode); break; } case "transport ships only": { newProperty = new SimpleProperty(mainNode); break; } case "weapon": { newProperty = new Weapon(mainNode); break; } default: { // it is an error to arrive here, but try to recover using an integer property Report.Error("Component property type " + propertyType + " not recognised, using default constructor"); newProperty = new IntegerProperty(mainNode); break; } } if (newProperty != null) { this.Properties.Add(propertyType, newProperty); } break; } } } catch (Exception e) { Report.FatalError(e.Message + "\n Details: \n" + e.ToString()); } mainNode = mainNode.NextSibling; } }
/// <summary> /// Copy constructor. /// </summary> /// <param name="existing"></param> public ProbabilityProperty(ProbabilityProperty existing) { this.Value = existing.Value; }