# HG changeset patch # User IBBoard # Date 1334430271 -3600 # Node ID 2ba1f24eb427bb77ec07f6a09177c96ade1dce74 # Parent 95c1b68a600b0be8f767b57550dc0b319a02f98a Re #359: Add "only contained" attribute to unit types * Add attribute to schema and load in factory Also: * Reformat line endings to be consistent diff -r 95c1b68a600b -r 2ba1f24eb427 API/Factories/Xml/WarFoundryXmlRaceFactory.cs --- a/API/Factories/Xml/WarFoundryXmlRaceFactory.cs Sat Apr 14 16:57:34 2012 +0100 +++ b/API/Factories/Xml/WarFoundryXmlRaceFactory.cs Sat Apr 14 20:04:31 2012 +0100 @@ -1,111 +1,111 @@ -// This file (WarFoundryXmlRaceFactory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 IBBoard -// -// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using IBBoard.Xml; -using IBBoard.IO; -using IBBoard.Limits; -using IBBoard.CustomMath; -using ICSharpCode.SharpZipLib.Zip; +// This file (WarFoundryXmlRaceFactory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 IBBoard +// +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using IBBoard.Xml; +using IBBoard.IO; +using IBBoard.Limits; +using IBBoard.CustomMath; +using ICSharpCode.SharpZipLib.Zip; using IBBoard.WarFoundry.API.Objects; using IBBoard.WarFoundry.API.Objects.Requirement; -using IBBoard.WarFoundry.API.Factories.Requirement; - -namespace IBBoard.WarFoundry.API.Factories.Xml -{ - /// - /// A sub-factory for loading WarFoundry Race XML files - /// - public class WarFoundryXmlRaceFactory : IRaceFactory - { - private Dictionary extraData = new Dictionary(); +using IBBoard.WarFoundry.API.Factories.Requirement; + +namespace IBBoard.WarFoundry.API.Factories.Xml +{ + /// + /// A sub-factory for loading WarFoundry Race XML files + /// + public class WarFoundryXmlRaceFactory : IRaceFactory + { + private Dictionary extraData = new Dictionary(); private WarFoundryXmlLimitParser limitParser = new WarFoundryXmlLimitParser(); - private WarFoundryXmlFactory mainFactory; - - public WarFoundryXmlRaceFactory(WarFoundryXmlFactory factory) - { - this.mainFactory = factory; - } - - private void StoreExtraData(Race wfObject, XmlElement elem) - { - extraData[wfObject] = elem.OwnerDocument; - } - - private XmlDocument GetExtraData(Race obj) - { - XmlDocument extra = null; - extraData.TryGetValue(obj, out extra); - return extra; + private WarFoundryXmlFactory mainFactory; + + public WarFoundryXmlRaceFactory(WarFoundryXmlFactory factory) + { + this.mainFactory = factory; + } + + private void StoreExtraData(Race wfObject, XmlElement elem) + { + extraData[wfObject] = elem.OwnerDocument; + } + + private XmlDocument GetExtraData(Race obj) + { + XmlDocument extra = null; + extraData.TryGetValue(obj, out extra); + return extra; } public Race CreateRace(XmlElement elem) { - string id = elem.GetAttribute("id"); - string subid = elem.GetAttribute("subid"); - string systemID = elem.GetAttribute("system"); - string name = elem.GetAttribute("name"); - string armyDefaultName = elem.GetAttribute("defaultArmyName"); - GameSystem gameSystem = WarFoundryLoader.GetDefault ().GetGameSystem (systemID); - - if (gameSystem == null) - { - throw new InvalidFileException("Referenced game system, '"+systemID+"', did not exist"); - } - - Race race = new Race(id, subid, name, gameSystem, mainFactory); - race.ArmyDefaultName = armyDefaultName; - StoreExtraData(race, elem); - return race; - } - - public void CompleteLoading(Race race) - { - if (!WarFoundryXmlFactoryUtils.CanCompleteLoading(race)) - { - return; - } - - race.SetAsLoading(); - XmlDocument extraData = GetExtraData(race); - - foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:categories/cat:cat")) - { - CreateCategoryFromElement(node, race); - } - - foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:equipment/race:equipmentItem")) - { - CreateEquipmentItemFromElement(node, race); - } - - foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:abilities/race:ability")) - { - CreateAbilityFromElement(node, race); - } - - foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:memberTypes/race:memberType")) - { - CreateMemberTypeFromElement(node, race); - } - - foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:units/race:unit")) - { - GetUnitTypeForElement(node, race); - } - - race.SetAsFullyLoaded(); - } - - private Category CreateCategoryFromElement(XmlElement elem, Race parentRace) - { - Category cat = CategoryLoader.CreateFromElement(elem); - parentRace.AddCategory(cat); - return cat; + string id = elem.GetAttribute("id"); + string subid = elem.GetAttribute("subid"); + string systemID = elem.GetAttribute("system"); + string name = elem.GetAttribute("name"); + string armyDefaultName = elem.GetAttribute("defaultArmyName"); + GameSystem gameSystem = WarFoundryLoader.GetDefault ().GetGameSystem (systemID); + + if (gameSystem == null) + { + throw new InvalidFileException("Referenced game system, '"+systemID+"', did not exist"); + } + + Race race = new Race(id, subid, name, gameSystem, mainFactory); + race.ArmyDefaultName = armyDefaultName; + StoreExtraData(race, elem); + return race; + } + + public void CompleteLoading(Race race) + { + if (!WarFoundryXmlFactoryUtils.CanCompleteLoading(race)) + { + return; + } + + race.SetAsLoading(); + XmlDocument extraData = GetExtraData(race); + + foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:categories/cat:cat")) + { + CreateCategoryFromElement(node, race); + } + + foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:equipment/race:equipmentItem")) + { + CreateEquipmentItemFromElement(node, race); + } + + foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:abilities/race:ability")) + { + CreateAbilityFromElement(node, race); + } + + foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:memberTypes/race:memberType")) + { + CreateMemberTypeFromElement(node, race); + } + + foreach (XmlElement node in WarFoundryXmlFactoryUtils.SelectNodes(extraData, "/race:race/race:units/race:unit")) + { + GetUnitTypeForElement(node, race); + } + + race.SetAsFullyLoaded(); + } + + private Category CreateCategoryFromElement(XmlElement elem, Race parentRace) + { + Category cat = CategoryLoader.CreateFromElement(elem); + parentRace.AddCategory(cat); + return cat; } @@ -124,275 +124,276 @@ } return type; - } - - private UnitType GetUnitTypeFromDocument(XmlDocument doc, string id, Race parentRace) - { - XmlElement unitWithId = WarFoundryXmlFactoryUtils.SelectSingleElement (doc, "/race:race/race:units/race:unit[@id='" + id + "']"); - - if (unitWithId == null) - { - throw new InvalidFileException("Could not find unit with ID "+id); - } - - return GetUnitTypeForElement(unitWithId, parentRace); - } - - private UnitType GetUnitTypeForElement(XmlElement elem, Race parentRace) - { - string id = elem.GetAttribute("id"); - UnitType type = parentRace.GetUnitType(id); - - if (type==null) - { - type = CreateUnitTypeFromElement(elem, id, parentRace); - } - - return type; - } - - private UnitType CreateUnitTypeFromElement(XmlElement elem, string id, Race parentRace) - { - string name = elem.GetAttribute("typeName"); - UnitType type = new UnitType(id, name, parentRace); - LoadCoreValuesForUnitType(elem, type); - parentRace.AddUnitType(type); - LoadEquipmentSlotsForUnitType(elem, type); - LoadEquipmentForUnitType(elem, type); - LoadAbilitiesForUnitType(elem, type); - LoadContainedUnitsForUnitType(elem, type); - LoadRequirementsForUnitType(elem, type); - LoadExtraDataForUnitType(elem, type); - LoadNotesForUnitType(elem, type); - return type; - } - - private void LoadCoreValuesForUnitType(XmlElement elem, UnitType type) - { - try - { - type.MaxNumber = XmlTools.GetIntValueFromAttribute(elem, "maxNum"); - type.MinNumber = XmlTools.GetIntValueFromAttribute(elem, "minNum"); - type.MaxSize = XmlTools.GetIntValueFromAttribute(elem, "maxSize"); - type.MinSize = XmlTools.GetIntValueFromAttribute(elem, "minSize"); - type.BaseSize = XmlTools.GetIntValueFromAttribute(elem, "baseSize"); - type.CostPerTrooper = XmlTools.GetDoubleValueFromAttribute(elem, "points"); - type.BaseUnitCost = XmlTools.GetDoubleValueFromAttribute(elem, "basePoints"); - } - catch (FormatException ex) - { - throw new InvalidFileException(ex.Message, ex); - } - - Race race = type.Race; - string mainCatID = elem.GetAttribute("cat"); - Category cat = race.GetCategory(mainCatID); - - if (cat == null) - { - throw new InvalidFileException(String.Format("Category with ID '{1}' did not exist for UnitType '{0}'", type.Name, mainCatID)); - } - - type.MainCategory = cat; - - XmlNodeList unitCategories = WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitCategories/race:unitCategory"); - - foreach (XmlElement unitCategory in unitCategories) - { - string catID = unitCategory.GetAttribute("catID"); - Category unitCat = race.GetCategory(catID); - - if (unitCat == null) - { - throw new InvalidFileException(String.Format("Category with ID '{1}' did not exist for UnitType '{0}'", type.Name, catID)); - } - - type.AddCategory(unitCat); - } - - XmlElement statsElement = WarFoundryXmlFactoryUtils.SelectSingleElement(elem, "race:stats"); - - if (statsElement!=null) - { - Stats unitStats = ParseUnitStats(statsElement, type.GameSystem); - type.SetUnitStats(unitStats); - } - - XmlNodeList unitMemberReferences = WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitMembers/race:unitMember"); - - foreach (XmlElement unitMemberRef in unitMemberReferences) - { - string typeID = unitMemberRef.GetAttribute("typeID"); - UnitMemberType unitMemberType = race.GetUnitMemberType(typeID); - type.AddUnitMemberType(unitMemberType); - } - } - - private void LoadEquipmentSlotsForUnitType(XmlElement elem, UnitType type) - { - foreach (XmlElement equipSlot in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:equipmentSlots/race:equipmentSlot")) - { - LoadEquipmentSlotForUnitType (type, equipSlot); - } - } - - private void LoadEquipmentSlotForUnitType(UnitType type, XmlElement equipSlot) - { - string slotName = equipSlot.GetAttribute("name"); - ILimit limit = GetMaxLimit(equipSlot); - - if (limit != null) - { - type.AddEquipmentSlot(slotName, limit); - } - } - - private ILimit GetMinLimit(XmlElement elem) - { - return limitParser.GetMinLimit(elem); - } - - private ILimit GetMaxLimit(XmlElement elem) - { - return limitParser.GetMaxLimit(elem); - } - - private void LoadEquipmentForUnitType(XmlElement elem, UnitType type) - { - foreach (XmlElement equip in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitEquipment/race:unitEquipmentItem")) - { - string id = equip.GetAttribute("id"); - EquipmentItem equipItem = type.Race.GetEquipmentItem(id); - - if (equipItem!=null) - { - string mutexGroupString = equip.GetAttribute("exclusivityGroups"); - string[] mutexGroups; - - if (mutexGroupString == "") - { - mutexGroupString = equip.GetAttribute("exclusivityGroup"); - } - - if (mutexGroupString != "") - { - string[] groups = mutexGroupString.Split(','); - int groupCount = groups.Length; - - for (int i = 0; i < groupCount; i++) - { - groups[i] = groups[i].Trim(); - } - - mutexGroups = groups; - } - else - { - mutexGroups = new string[0]; - } - - UnitEquipmentItem unitEquipItem = new UnitEquipmentItem(equipItem, type, mutexGroups); - - string equipSlot = equip.GetAttribute("equipmentSlot"); - - if (equipSlot != "") - { - if (type.HasEquipmentSlot(equipSlot)) - { - unitEquipItem.SlotName = equipSlot; - } - else - { - throw new InvalidFileException("Attribute 'equipmentSlot' of unit equipment item " + id + " for " + type.Name + " was not a valid slot name"); - } - } - - ILimit limit = GetMaxLimit(equip); - - if (limit != null) - { - unitEquipItem.MaxLimit = limit; - } - - limit = GetMinLimit(equip); - - if (limit != null) - { - unitEquipItem.MinLimit = limit; - } - - unitEquipItem.RoundNumberUp = equip.GetAttribute("roundDirection").Equals("up"); - - try - { - unitEquipItem.IsRequired = XmlTools.GetBoolValueFromAttribute(equip, "required"); - } - catch(FormatException e) - { - throw new InvalidFileException("Attribute 'required' of unit equipment item " + id + " for " + type.Name + " was not a valid boolean", e); - } - - try - { - unitEquipItem.CostMultiplier = XmlTools.GetDoubleValueFromAttribute(equip, "costMultiplier"); - } - catch (FormatException e) - { - throw new InvalidFileException("Attribute 'costMultiplier' of unit equipment item " + id + " for " + type.Name + " was not a valid decimal number", e); - } - - try - { - unitEquipItem.CostRoundType = (RoundType) Enum.Parse(typeof(RoundType), equip.GetAttribute("costRounding")); - } - catch (ArgumentException e) - { - throw new InvalidFileException("Attribute 'costRounding' of unit equipment item " + id + " for " + type.Name + " was not a valid rounding type", e); - } - } - else - { - throw new InvalidFileException("Equipment item with ID '" + id + "' was required by " + type.Name + " but was not found"); - } - } - } - - private void LoadAbilitiesForUnitType(XmlElement elem, UnitType type) - { - foreach (XmlElement abilityElem in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitAbilities/race:unitAbility")) - { - string id = abilityElem.GetAttribute("abilityID"); - Ability ability = type.Race.GetAbility(id); - - if (ability == null) - { - throw new InvalidFileException("Ability for "+type.Name+ " with ID "+id+ " did not exist in race definition"); - } - - bool required = XmlTools.GetBoolValueFromAttribute(abilityElem, "required"); - type.AddAbility(ability, required); - } - } - - private void LoadContainedUnitsForUnitType(XmlElement elem, UnitType type) - { - foreach (XmlElement containedUnitType in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:contains/race:containedUnit")) - { - string id = containedUnitType.GetAttribute("containedID"); - UnitType containedType = GetUnitTypeFromDocument(elem.OwnerDocument, id, type.Race); - - if (containedType!=null) - { - type.AddContainedUnitType(containedType); - } - else - { - throw new InvalidFileException("Unit type " + type.Name + " tried to contain undefined unit with ID "+id); - } - } - } - - private void LoadRequirementsForUnitType(XmlElement elem, UnitType type) + } + + private UnitType GetUnitTypeFromDocument(XmlDocument doc, string id, Race parentRace) + { + XmlElement unitWithId = WarFoundryXmlFactoryUtils.SelectSingleElement (doc, "/race:race/race:units/race:unit[@id='" + id + "']"); + + if (unitWithId == null) + { + throw new InvalidFileException("Could not find unit with ID "+id); + } + + return GetUnitTypeForElement(unitWithId, parentRace); + } + + private UnitType GetUnitTypeForElement(XmlElement elem, Race parentRace) + { + string id = elem.GetAttribute("id"); + UnitType type = parentRace.GetUnitType(id); + + if (type==null) + { + type = CreateUnitTypeFromElement(elem, id, parentRace); + } + + return type; + } + + private UnitType CreateUnitTypeFromElement(XmlElement elem, string id, Race parentRace) + { + string name = elem.GetAttribute("typeName"); + UnitType type = new UnitType(id, name, parentRace); + LoadCoreValuesForUnitType(elem, type); + parentRace.AddUnitType(type); + LoadEquipmentSlotsForUnitType(elem, type); + LoadEquipmentForUnitType(elem, type); + LoadAbilitiesForUnitType(elem, type); + LoadContainedUnitsForUnitType(elem, type); + LoadRequirementsForUnitType(elem, type); + LoadExtraDataForUnitType(elem, type); + LoadNotesForUnitType(elem, type); + return type; + } + + private void LoadCoreValuesForUnitType(XmlElement elem, UnitType type) + { + try + { + type.MaxNumber = XmlTools.GetIntValueFromAttribute(elem, "maxNum"); + type.MinNumber = XmlTools.GetIntValueFromAttribute(elem, "minNum"); + type.MaxSize = XmlTools.GetIntValueFromAttribute(elem, "maxSize"); + type.MinSize = XmlTools.GetIntValueFromAttribute(elem, "minSize"); + type.BaseSize = XmlTools.GetIntValueFromAttribute(elem, "baseSize"); + type.CostPerTrooper = XmlTools.GetDoubleValueFromAttribute(elem, "points"); + type.BaseUnitCost = XmlTools.GetDoubleValueFromAttribute(elem, "basePoints"); + type.IsContainedOnly = XmlTools.GetBoolValueFromAttribute(elem, "containedOnly"); + } + catch (FormatException ex) + { + throw new InvalidFileException(ex.Message, ex); + } + + Race race = type.Race; + string mainCatID = elem.GetAttribute("cat"); + Category cat = race.GetCategory(mainCatID); + + if (cat == null) + { + throw new InvalidFileException(String.Format("Category with ID '{1}' did not exist for UnitType '{0}'", type.Name, mainCatID)); + } + + type.MainCategory = cat; + + XmlNodeList unitCategories = WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitCategories/race:unitCategory"); + + foreach (XmlElement unitCategory in unitCategories) + { + string catID = unitCategory.GetAttribute("catID"); + Category unitCat = race.GetCategory(catID); + + if (unitCat == null) + { + throw new InvalidFileException(String.Format("Category with ID '{1}' did not exist for UnitType '{0}'", type.Name, catID)); + } + + type.AddCategory(unitCat); + } + + XmlElement statsElement = WarFoundryXmlFactoryUtils.SelectSingleElement(elem, "race:stats"); + + if (statsElement!=null) + { + Stats unitStats = ParseUnitStats(statsElement, type.GameSystem); + type.SetUnitStats(unitStats); + } + + XmlNodeList unitMemberReferences = WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitMembers/race:unitMember"); + + foreach (XmlElement unitMemberRef in unitMemberReferences) + { + string typeID = unitMemberRef.GetAttribute("typeID"); + UnitMemberType unitMemberType = race.GetUnitMemberType(typeID); + type.AddUnitMemberType(unitMemberType); + } + } + + private void LoadEquipmentSlotsForUnitType(XmlElement elem, UnitType type) + { + foreach (XmlElement equipSlot in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:equipmentSlots/race:equipmentSlot")) + { + LoadEquipmentSlotForUnitType (type, equipSlot); + } + } + + private void LoadEquipmentSlotForUnitType(UnitType type, XmlElement equipSlot) + { + string slotName = equipSlot.GetAttribute("name"); + ILimit limit = GetMaxLimit(equipSlot); + + if (limit != null) + { + type.AddEquipmentSlot(slotName, limit); + } + } + + private ILimit GetMinLimit(XmlElement elem) + { + return limitParser.GetMinLimit(elem); + } + + private ILimit GetMaxLimit(XmlElement elem) + { + return limitParser.GetMaxLimit(elem); + } + + private void LoadEquipmentForUnitType(XmlElement elem, UnitType type) + { + foreach (XmlElement equip in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitEquipment/race:unitEquipmentItem")) + { + string id = equip.GetAttribute("id"); + EquipmentItem equipItem = type.Race.GetEquipmentItem(id); + + if (equipItem!=null) + { + string mutexGroupString = equip.GetAttribute("exclusivityGroups"); + string[] mutexGroups; + + if (mutexGroupString == "") + { + mutexGroupString = equip.GetAttribute("exclusivityGroup"); + } + + if (mutexGroupString != "") + { + string[] groups = mutexGroupString.Split(','); + int groupCount = groups.Length; + + for (int i = 0; i < groupCount; i++) + { + groups[i] = groups[i].Trim(); + } + + mutexGroups = groups; + } + else + { + mutexGroups = new string[0]; + } + + UnitEquipmentItem unitEquipItem = new UnitEquipmentItem(equipItem, type, mutexGroups); + + string equipSlot = equip.GetAttribute("equipmentSlot"); + + if (equipSlot != "") + { + if (type.HasEquipmentSlot(equipSlot)) + { + unitEquipItem.SlotName = equipSlot; + } + else + { + throw new InvalidFileException("Attribute 'equipmentSlot' of unit equipment item " + id + " for " + type.Name + " was not a valid slot name"); + } + } + + ILimit limit = GetMaxLimit(equip); + + if (limit != null) + { + unitEquipItem.MaxLimit = limit; + } + + limit = GetMinLimit(equip); + + if (limit != null) + { + unitEquipItem.MinLimit = limit; + } + + unitEquipItem.RoundNumberUp = equip.GetAttribute("roundDirection").Equals("up"); + + try + { + unitEquipItem.IsRequired = XmlTools.GetBoolValueFromAttribute(equip, "required"); + } + catch(FormatException e) + { + throw new InvalidFileException("Attribute 'required' of unit equipment item " + id + " for " + type.Name + " was not a valid boolean", e); + } + + try + { + unitEquipItem.CostMultiplier = XmlTools.GetDoubleValueFromAttribute(equip, "costMultiplier"); + } + catch (FormatException e) + { + throw new InvalidFileException("Attribute 'costMultiplier' of unit equipment item " + id + " for " + type.Name + " was not a valid decimal number", e); + } + + try + { + unitEquipItem.CostRoundType = (RoundType) Enum.Parse(typeof(RoundType), equip.GetAttribute("costRounding")); + } + catch (ArgumentException e) + { + throw new InvalidFileException("Attribute 'costRounding' of unit equipment item " + id + " for " + type.Name + " was not a valid rounding type", e); + } + } + else + { + throw new InvalidFileException("Equipment item with ID '" + id + "' was required by " + type.Name + " but was not found"); + } + } + } + + private void LoadAbilitiesForUnitType(XmlElement elem, UnitType type) + { + foreach (XmlElement abilityElem in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:unitAbilities/race:unitAbility")) + { + string id = abilityElem.GetAttribute("abilityID"); + Ability ability = type.Race.GetAbility(id); + + if (ability == null) + { + throw new InvalidFileException("Ability for "+type.Name+ " with ID "+id+ " did not exist in race definition"); + } + + bool required = XmlTools.GetBoolValueFromAttribute(abilityElem, "required"); + type.AddAbility(ability, required); + } + } + + private void LoadContainedUnitsForUnitType(XmlElement elem, UnitType type) + { + foreach (XmlElement containedUnitType in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:contains/race:containedUnit")) + { + string id = containedUnitType.GetAttribute("containedID"); + UnitType containedType = GetUnitTypeFromDocument(elem.OwnerDocument, id, type.Race); + + if (containedType!=null) + { + type.AddContainedUnitType(containedType); + } + else + { + throw new InvalidFileException("Unit type " + type.Name + " tried to contain undefined unit with ID "+id); + } + } + } + + private void LoadRequirementsForUnitType(XmlElement elem, UnitType type) { foreach (XmlElement extraData in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:requirements/race:requirement")) { @@ -404,109 +405,109 @@ IRequirement req = reqFactory.CreateRequirement(type, data, this); type.AddRequirement(req); } - } + } + } + + private void LoadExtraDataForUnitType(XmlElement elem, UnitType type) + { + foreach (XmlElement extraData in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:extraData/race:data")) + { + string id = extraData.GetAttribute("id"); + string data = extraData.InnerXml; + type.AddExtraData(id, data); + } + } + + private void LoadNotesForUnitType(XmlElement elem, UnitType type) + { + XmlNode node = WarFoundryXmlFactoryUtils.SelectSingleNode(elem, "race:notes"); + + if (node!=null) + { + type.Notes = node.InnerText; + } + } + + private Stats ParseUnitStats(XmlElement elem, GameSystem system) + { + if (elem == null) + { + return null; + } + + String statsID = elem.GetAttribute("statSet"); + SystemStats statsSet; + + if (statsID == "") + { + statsSet = system.StandardSystemStats; + } + else + { + statsSet = system.GetSystemStatsForID(statsID); + } + + Stats stats = new Stats(statsSet); + + foreach (XmlElement stat in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:stat")) + { + String statName = stat.GetAttribute("name"); + stats.SetStatValue(statName, stat.InnerText); + } + + return stats; } - - private void LoadExtraDataForUnitType(XmlElement elem, UnitType type) - { - foreach (XmlElement extraData in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:extraData/race:data")) - { - string id = extraData.GetAttribute("id"); - string data = extraData.InnerXml; - type.AddExtraData(id, data); - } - } - - private void LoadNotesForUnitType(XmlElement elem, UnitType type) - { - XmlNode node = WarFoundryXmlFactoryUtils.SelectSingleNode(elem, "race:notes"); - - if (node!=null) - { - type.Notes = node.InnerText; - } - } - - private Stats ParseUnitStats(XmlElement elem, GameSystem system) - { - if (elem == null) - { - return null; - } - - String statsID = elem.GetAttribute("statSet"); - SystemStats statsSet; - - if (statsID == "") - { - statsSet = system.StandardSystemStats; - } - else - { - statsSet = system.GetSystemStatsForID(statsID); - } - - Stats stats = new Stats(statsSet); - - foreach (XmlElement stat in WarFoundryXmlFactoryUtils.SelectNodes(elem, "race:stat")) - { - String statName = stat.GetAttribute("name"); - stats.SetStatValue(statName, stat.InnerText); - } - - return stats; - } - - private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race) - { - string id = elem.GetAttribute("id"); - EquipmentItem item = race.GetEquipmentItem(id); - - if (item == null) - { - item = CreateEquipmentItemFromElement(elem, id, race); - } - - return item; - } - - private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, string id, Race race) - { - string name = elem.GetAttribute("name"); - EquipmentItem item = new EquipmentItem(id, name, race); - double cost = 0; - - try - { - cost = XmlTools.GetDoubleValueFromAttribute(elem, "cost"); - } - catch(FormatException ex) - { - throw new InvalidFileException("Attribute 'cost' of equipment item "+id+" was not a valid number", ex); - } - - //TODO: Parse equipment stats if there are any - item.Cost = cost; - race.AddEquipmentItem(item); - return item; - } - - private Ability CreateAbilityFromElement(XmlElement elem, Race race) - { - string id = elem.GetAttribute("id"); - string name = elem.GetAttribute("name"); - Ability ability = new Ability(id, name); - XmlNode node = WarFoundryXmlFactoryUtils.SelectSingleNode(elem, "race:description"); - ability.Description = (node == null) ? "" : node.InnerText; - race.AddAbility(ability); - return ability; - } - - private void CreateMemberTypeFromElement(XmlElement elem, Race race) - { - Stats stats = ParseUnitStats(WarFoundryXmlFactoryUtils.SelectSingleElement(elem, "race:stats"), race.GameSystem); - UnitMemberType unitMemberType = new UnitMemberType(elem.GetAttribute("id"), elem.GetAttribute("name"), stats); - race.AddUnitMemberType(unitMemberType); - } - } -} + + private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race) + { + string id = elem.GetAttribute("id"); + EquipmentItem item = race.GetEquipmentItem(id); + + if (item == null) + { + item = CreateEquipmentItemFromElement(elem, id, race); + } + + return item; + } + + private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, string id, Race race) + { + string name = elem.GetAttribute("name"); + EquipmentItem item = new EquipmentItem(id, name, race); + double cost = 0; + + try + { + cost = XmlTools.GetDoubleValueFromAttribute(elem, "cost"); + } + catch(FormatException ex) + { + throw new InvalidFileException("Attribute 'cost' of equipment item "+id+" was not a valid number", ex); + } + + //TODO: Parse equipment stats if there are any + item.Cost = cost; + race.AddEquipmentItem(item); + return item; + } + + private Ability CreateAbilityFromElement(XmlElement elem, Race race) + { + string id = elem.GetAttribute("id"); + string name = elem.GetAttribute("name"); + Ability ability = new Ability(id, name); + XmlNode node = WarFoundryXmlFactoryUtils.SelectSingleNode(elem, "race:description"); + ability.Description = (node == null) ? "" : node.InnerText; + race.AddAbility(ability); + return ability; + } + + private void CreateMemberTypeFromElement(XmlElement elem, Race race) + { + Stats stats = ParseUnitStats(WarFoundryXmlFactoryUtils.SelectSingleElement(elem, "race:stats"), race.GameSystem); + UnitMemberType unitMemberType = new UnitMemberType(elem.GetAttribute("id"), elem.GetAttribute("name"), stats); + race.AddUnitMemberType(unitMemberType); + } + } +} diff -r 95c1b68a600b -r 2ba1f24eb427 schemas/race.xsd --- a/schemas/race.xsd Sat Apr 14 16:57:34 2012 +0100 +++ b/schemas/race.xsd Sat Apr 14 20:04:31 2012 +0100 @@ -273,6 +273,7 @@ +