changeset 54:3a90f70dac73

Re #61 - Complete structure of WarFoundry API objects * Remove min/max from EquipmentItem and add description * Add min/max numbers and percentages to UnitEquipmentItem * Make Race schema define min/max number without the ratio (which is the percentage) * Replace use of EquipmentItem with UnitEquipmentItem because of increased use of UnitEquipmentItem for unit-specific data * Use doubles instead of floats for equipment amounts * Distinguish between ratio and absolute limits * Delete UnitEquipmentItemObj helper class that was purely used for UI Re #9 - Use smaller methods * Deprecate long Race and EquipmentItem constructors and ensure all getters/setters exist Also: * Migrate Unit to using genericed collections * Always use GameSystem object for Race, not ID string
author IBBoard <dev@ibboard.co.uk>
date Sun, 05 Apr 2009 13:45:23 +0000
parents 1b35eed503ef
children 9080366031c0
files IBBoard.WarFoundry.API.csproj api/Commands/ReplaceUnitEquipmentCommand.cs api/Commands/SetUnitEquipmentAmountCommand.cs api/Objects/EquipmentItem.cs api/Objects/Race.cs api/Objects/Unit.cs api/Objects/UnitEquipmentItem.cs api/Objects/UnitEquipmentItemObj.cs dtds/race.xsd
diffstat 9 files changed, 248 insertions(+), 234 deletions(-) [+]
line wrap: on
line diff
--- a/IBBoard.WarFoundry.API.csproj	Wed Apr 01 19:20:27 2009 +0000
+++ b/IBBoard.WarFoundry.API.csproj	Sun Apr 05 13:45:23 2009 +0000
@@ -93,7 +93,6 @@
     <Compile Include="api\Objects\SystemStats.cs" />
     <Compile Include="api\Objects\Unit.cs" />
     <Compile Include="api\Objects\UnitEquipmentItem.cs" />
-    <Compile Include="api\Objects\UnitEquipmentItemObj.cs" />
     <Compile Include="api\Objects\UnitType.cs" />
     <Compile Include="api\Objects\WarFoundryObject.cs" />
     <Compile Include="api\Objects\WarFoundryStagedLoadingObject.cs" />
--- a/api/Commands/ReplaceUnitEquipmentCommand.cs	Wed Apr 01 19:20:27 2009 +0000
+++ b/api/Commands/ReplaceUnitEquipmentCommand.cs	Sun Apr 05 13:45:23 2009 +0000
@@ -15,11 +15,8 @@
 	public class ReplaceUnitEquipmentCommand : Command
 	{
 		private SetUnitEquipmentAmountCommand removeOldCommand, addNewCommand;
-		//private Unit unit;
-		//private EquipmentItem oldEquip, newEquip;
-		//private float newAmount, oldAmount;
 		
-		public ReplaceUnitEquipmentCommand(Unit unit, EquipmentItem oldItem, EquipmentItem newItem, float amount)
+		public ReplaceUnitEquipmentCommand(Unit unit, UnitEquipmentItem oldItem, UnitEquipmentItem newItem, double amount)
 		{
 			removeOldCommand = new SetUnitEquipmentAmountCommand(unit, oldItem, 0);
 			addNewCommand = new SetUnitEquipmentAmountCommand(unit, newItem, amount);
--- a/api/Commands/SetUnitEquipmentAmountCommand.cs	Wed Apr 01 19:20:27 2009 +0000
+++ b/api/Commands/SetUnitEquipmentAmountCommand.cs	Sun Apr 05 13:45:23 2009 +0000
@@ -15,10 +15,11 @@
 	public class SetUnitEquipmentAmountCommand : Command
 	{
 		private Unit unit;
-		private EquipmentItem equip;
-		private float newAmount, oldAmount;
+		private UnitEquipmentItem equip;
+		private double newAmount;
+		private double oldAmount;
 		
-		public SetUnitEquipmentAmountCommand(Unit unit, EquipmentItem item, float amount)
+		public SetUnitEquipmentAmountCommand(Unit unit, UnitEquipmentItem item, double amount)
 		{
 			this.unit = unit;
 			equip = item;
@@ -33,12 +34,12 @@
 
 		public override string Description
 		{
-			get { return "Set "+StringManipulation.CutToLength(equip.Name, 20)+" amount for "+StringManipulation.CutToLength(unit.Name, 20)+" to "+UnitEquipmentItemObj.FormatEquipmentAmount(equip, newAmount); }
+			get { return "Set "+StringManipulation.CutToLength(equip.Name, 20)+" amount for "+StringManipulation.CutToLength(unit.Name, 20)+" to "+UnitEquipmentItem.FormatEquipmentAmount(equip, newAmount); }
 		}
 
 		public override string UndoDescription
 		{
-			get { return "Set "+StringManipulation.CutToLength(equip.Name, 20)+" amount for "+StringManipulation.CutToLength(unit.Name, 20)+" to "+UnitEquipmentItemObj.FormatEquipmentAmount(equip, oldAmount); }
+			get { return "Set "+StringManipulation.CutToLength(equip.Name, 20)+" amount for "+StringManipulation.CutToLength(unit.Name, 20)+" to "+UnitEquipmentItem.FormatEquipmentAmount(equip, oldAmount); }
 		}
 
 		public override bool Execute()
@@ -48,13 +49,27 @@
 		}
 
 		public override void Redo()
-		{
-			unit.SetEquipmentAmount(equip.ID, newAmount);
+		{
+			if (equip.IsRatioLimit)
+			{
+				unit.SetEquipmentRatio(equip, newAmount);
+			}
+			else
+			{
+				unit.SetEquipmentAmount(equip, (int)newAmount);
+			}
 		}
 
 		public override void Undo()
-		{
-			unit.SetEquipmentAmount(equip.ID, oldAmount);
+		{
+			if (equip.IsRatioLimit)
+			{
+				unit.SetEquipmentRatio(equip, oldAmount);
+			}
+			else
+			{
+				unit.SetEquipmentAmount(equip, (int)oldAmount);
+			}
 		}
 
 		public override string Name
@@ -62,7 +77,7 @@
 			get { return "Set equipment amount"; }
 		}
 
-		public EquipmentItem EquipItem
+		public UnitEquipmentItem EquipItem
 		{
 			get { return equip; }
 		}
--- a/api/Objects/EquipmentItem.cs	Wed Apr 01 19:20:27 2009 +0000
+++ b/api/Objects/EquipmentItem.cs	Sun Apr 05 13:45:23 2009 +0000
@@ -12,50 +12,22 @@
 	/// </summary>
 	public class EquipmentItem : WarFoundryObject
 	{
-		private double cost, min, max;
+		private double cost;
+		private string description;
 		private ArmourType armourType;
-		private Race equipForRace;
-
-		public EquipmentItem(string id, string name, double itemCost, double minimum, double maximum, ArmourType itemArmourType, Race race) : base(id, name)
+		private Race equipForRace;
+		
+		public EquipmentItem(string id, string name, Race race) : base(id, name)
 		{
-			cost = itemCost;
-			min = minimum;
-			max = maximum;
-			armourType = itemArmourType;
 			equipForRace = race;
-		}
-
-		public bool IsRatioLimit
-		{
-			get { return ((MaxNumber < 1 && MaxNumber > 0) || (MaxNumber == 1 && MinNumber > 0)); }
+			description = "";
+			armourType = ArmourType.None;
 		}
-
-		public double MinNumber
-		{
-			get { return min; }
-			set 
-			{
-				min = (value >= 0 || value == WarFoundryCore.INFINITY) ? value : 0; 
-
-				if (MaxNumber != WarFoundryCore.INFINITY && min > MaxNumber)
-				{
-					MaxNumber = min;
-				}
-			}
-		}
-
-		public double MaxNumber
-		{
-			get { return max; }
-			set 
-			{
-				max = (value > 0 || value == WarFoundryCore.INFINITY) ? value : WarFoundryCore.INFINITY; 
-
-				if (max != WarFoundryCore.INFINITY && MinNumber > max)
-				{
-					MinNumber = max;
-				}
-			}
+
+		[Obsolete("Use the three argument constructor and the appropriate 'set' methods")]
+		public EquipmentItem(string id, string name, double itemCost, double minimum, double maximum, ArmourType itemArmourType, Race race) : this(id, name, race)
+		{
+			ItemArmourType = itemArmourType;
 		}
 
 		public ArmourType ItemArmourType
@@ -67,7 +39,19 @@
 		public double Cost
 		{
 			get { return cost; }
-			set { cost = value; }
+			set
+			{
+				if (value >= 0)
+				{
+					cost = value;
+				}
+			}
+		}
+		
+		public string Description
+		{
+			get { return description; }
+			set { description = (value == null ? "" : value); }
 		}
 		
 		public Race EquipmentForRace
--- a/api/Objects/Race.cs	Wed Apr 01 19:20:27 2009 +0000
+++ b/api/Objects/Race.cs	Sun Apr 05 13:45:23 2009 +0000
@@ -16,7 +16,6 @@
 		public static string SYSTEM_DEFAULT_RACE_ID = "GameDefault"; 
 		
 		private string subID;
-		private string systemID;
 		private GameSystem system;
 		private Dictionary<Category, Dictionary<string, UnitType>> unitTypesByCat;
 		private Dictionary<string, UnitType> unitTypes = new Dictionary<string,UnitType>();
@@ -24,14 +23,24 @@
 		private Dictionary<string, Ability> abilities = new Dictionary<string,Ability>();
 		private Dictionary<string, Category> categories = new Dictionary<string,Category>();
 		
-		public Race(string raceID, string raceName, string gameSystemID, IWarFoundryFactory creatingFactory) : this(raceID, "", raceName, gameSystemID, creatingFactory)
+		public Race(string raceID, string raceName, GameSystem gameSystem, IWarFoundryFactory creatingFactory) : this(raceID, "", raceName, gameSystem, creatingFactory)
 		{
 		}
 		
-		public Race(string raceID, string raceSubID, string raceName, string gameSystemID, IWarFoundryFactory creatingFactory) : base(raceID + (raceSubID!="" ? "_"+raceSubID : ""), raceName, creatingFactory)
+		public Race(string raceID, string raceSubID, string raceName, GameSystem gameSystem, IWarFoundryFactory creatingFactory) : base(raceID + (raceSubID!="" ? "_"+raceSubID : ""), raceName, creatingFactory)
 		{
 			subID = (raceSubID == null ? "" : raceSubID);
-			systemID = gameSystemID;
+			system = gameSystem;
+		}
+		
+		[Obsolete("Use constructor with GameSystem argument instead")]
+		public Race(string raceID, string raceName, string gameSystemID, IWarFoundryFactory creatingFactory) : this(raceID, "", raceName, WarFoundryLoader.GetDefault().GetGameSystem(gameSystemID), creatingFactory)
+		{
+		}
+		
+		[Obsolete("Use constructor with GameSystem argument instead")]
+		public Race(string raceID, string raceSubID, string raceName, string gameSystemID, IWarFoundryFactory creatingFactory) : this(raceID, raceSubID, raceName, WarFoundryLoader.GetDefault().GetGameSystem(gameSystemID), creatingFactory)
+		{
 		}
 
 		public string SubID
@@ -42,15 +51,7 @@
 
 		public GameSystem GameSystem
 		{
-			get
-			{
-				if (system == null)
-				{
-					system = WarFoundryLoader.GetDefault().GetGameSystem(systemID);
-				}
-				
-				return system;
-			}
+			get { return system; }
 			set
 			{
 				if (value == null)
--- a/api/Objects/Unit.cs	Wed Apr 01 19:20:27 2009 +0000
+++ b/api/Objects/Unit.cs	Sun Apr 05 13:45:23 2009 +0000
@@ -3,7 +3,7 @@
 // The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license.
 
 using System;
-using System.Collections;
+using System.Collections.Generic;
 using System.Text;
 using System.Xml;
 using IBBoard.Lang;
@@ -21,10 +21,10 @@
 		private Race race;
 		private double points;
 		private ArmyCategory cat;
-		private Hashtable equipment = new Hashtable();
+		private Dictionary<UnitEquipmentItem, double> equipment = new Dictionary<UnitEquipmentItem, double>();
 		public event DoubleValChangedDelegate PointsValueChanged;
 		public event IntValChangedDelegate UnitSizeChanged;
-		public event FloatValChangedDelegate UnitEquipmentAmountChanged;
+		public event DoubleValChangedDelegate UnitEquipmentAmountChanged;
 
 		public Unit(UnitType unitType, Army parentArmy) : this(unitType, unitType.MinSize, parentArmy){}
 
@@ -64,8 +64,7 @@
 				{
 					if (CanEquipWithItem(unitEquip.ID))
 					{
-						EquipmentItem equipItem = unitEquip.EquipmentItem;
-						equipment[unitEquip.ID] = equipItem.MinNumber;
+						equipment[unitEquip] = unitEquip.MinNumber;
 					}
 				}
 			}
@@ -76,17 +75,13 @@
 			String oldName = HasDefaultName() ? Name : null;
 			double oldpoints = points;
 			points = type.CostPerTrooper * AdditionalTroopers + type.BaseUnitCost;
-			UnitEquipmentItem unitEquipItem;
-			EquipmentItem equipItem;
-			float count;
 
-			foreach (string key in equipment.Keys)
+			foreach (UnitEquipmentItem unitEquipItem in equipment.Keys)
 			{
-				unitEquipItem = UnitType.GetEquipmentItem(key);
-				equipItem = unitEquipItem.EquipmentItem;
-				count = (float)equipment[key];
+				EquipmentItem equipItem = unitEquipItem.EquipmentItem;
+				double count = (double)equipment[unitEquipItem];
 				
-				if (equipItem.IsRatioLimit)
+				if (unitEquipItem.IsRatioLimit)
 				{
 					if (unitEquipItem.RoundNumberUp)
 					{
@@ -204,7 +199,7 @@
 
 		public UnitEquipmentItem[] GetAllowedOptionalEquipment()
 		{
-			ArrayList list = new ArrayList();
+			List<UnitEquipmentItem> list = new List<UnitEquipmentItem>();
 
 			foreach (UnitEquipmentItem item in UnitType.GetEquipmentItems())
 			{
@@ -214,7 +209,7 @@
 				}
 			}
 
-			return (UnitEquipmentItem[])list.ToArray(typeof(UnitEquipmentItem));
+			return (UnitEquipmentItem[])list.ToArray();
 		}
 
 		public UnitEquipmentItem[] GetEquipment()
@@ -222,9 +217,9 @@
 			UnitEquipmentItem[] items = new UnitEquipmentItem[equipment.Count];
 			int i = 0;
 
-			foreach (String itemID in equipment.Keys)
+			foreach (UnitEquipmentItem item in equipment.Keys)
 			{
-				items[i++] = UnitType.GetEquipmentItem(itemID);
+				items[i++] = item;
 			}
 
 			return items;
@@ -232,88 +227,88 @@
 
 		public UnitEquipmentItem[] GetRequiredEquipment()
 		{
-			ArrayList list = new ArrayList();
-			UnitEquipmentItem item;
+			List<UnitEquipmentItem> list = new List<UnitEquipmentItem>();
 
-			foreach(String itemID in equipment.Keys)
+			foreach(UnitEquipmentItem item in equipment.Keys)
 			{
-				item = UnitType.GetEquipmentItem(itemID);
-
 				if (item.IsRequired)
 				{
 					list.Add(item);
 				}
 			}
 
-			return (UnitEquipmentItem[])list.ToArray(typeof(UnitEquipmentItem));
-		}
-
-		public float GetEquipmentAmount(UnitEquipmentItem item)
-		{
-			return GetEquipmentAmount(item.EquipmentItem.ID);
+			return (UnitEquipmentItem[])list.ToArray();
 		}
 
-		public float GetEquipmentAmount(string equipID)
-		{
-			if (equipment.ContainsKey(equipID))
-			{
-				return (float)equipment[equipID];
-			}
-			else
-			{
-				return 0;
+		public double GetEquipmentAmount(UnitEquipmentItem item)
+		{
+			if (equipment.ContainsKey(item))
+			{
+				return (double)equipment[item];
+			}
+			else
+			{
+				return 0;
 			}
 		}
 
-		public void SetEquipmentAmount(string equipID, float amount)
-		{
-			UnitEquipmentItem equip = UnitType.GetEquipmentItem(equipID);
+		public double GetEquipmentAmount(string equipID)
+		{
+			return GetEquipmentAmount(UnitType.GetEquipmentItem(equipID));
+		}
 
-			if (equip == null)
+		public void SetEquipmentAmount(UnitEquipmentItem equip, int amount)
+		{
+			if (equip.IsRatioLimit)
 			{
-				throw new InvalidOperationException("No such equipment ID "+equipID+" for unit "+ID);
+				throw new InvalidOperationException("Equipment with ID "+equip.EquipmentItemID+" for unit "+ID+" has a ratio limit, not an absolute limit");
 			}
-
-			if (equip.EquipmentItem.IsRatioLimit)
+			
+			if (amount <1 && amount != WarFoundryCore.INFINITY)
 			{
-				if (amount > 1)
-				{
-					amount = 1;
-				}
-				else if (amount < 0)
-				{
-					amount = 0;
-				}
-				//else what was passed in was okay
-			}
-			else
+				amount = 0;
+			}
+			
+			SetEquipmentAmount(equip, amount);
+		}
+		
+		public void SetEquipmentRatio(UnitEquipmentItem equip, double ratio)
+		{
+			if (!equip.IsRatioLimit)
+			{
+				throw new InvalidOperationException("Equipment with ID "+equip.EquipmentItemID+" for unit "+ID+" has an absolute limit, not a ratio limit");
+			}
+			
+			if (ratio > 1)
+			{
+				ratio = 1;
+			}
+			else if (ratio < 0)
+			{
+				ratio = 0;
+			}
+			
+			SetEquipmentAmount(equip, ratio);
+		}
+		
+		private void SetEquipmentAmount(UnitEquipmentItem equip, double amount)
+		{
+			double oldAmount = 0;
+
+			if (equipment.ContainsKey(equip))
 			{
-				if (amount >=1 || amount == WarFoundryCore.INFINITY)
-				{
-					amount = (float)Math.Round(amount);
-				}
-				else
-				{
-					amount = 0;
-				}
-			}
-
-			float oldAmount = 0;
-
-			if (equipment.ContainsKey(equipID))
-			{
-				oldAmount = (float)equipment[equipID];
+				oldAmount = equipment[equip];
 			}
 
 			if (amount!=oldAmount)
 			{
-				if (amount > 0 || amount == WarFoundryCore.INFINITY)
+				if (amount != 0)
 				{
-					equipment[equipID] = amount;
+					equipment[equip] = amount;
 				}
 				else
 				{
-					equipment.Remove(equipID);
+					equipment.Remove(equip);
 				}
 
 				OnUnitEquipmentAmountChanged(equip, oldAmount, amount);
@@ -330,9 +325,9 @@
 				return true;
 			}
 
-			foreach (string itemID in equipment.Keys)
+			foreach (UnitEquipmentItem item in equipment.Keys)
 			{
-				if (UnitType.GetEquipmentItem(itemID).MutexGroup == mutex)
+				if (item.MutexGroup == mutex)
 				{
 					return false;
 				}
@@ -357,7 +352,7 @@
 			}
 		}
 
-		private void OnUnitEquipmentAmountChanged(UnitEquipmentItem equip, float oldValue, float newValue)
+		private void OnUnitEquipmentAmountChanged(UnitEquipmentItem equip, double oldValue, double newValue)
 		{
 			if (UnitEquipmentAmountChanged!=null)
 			{
--- a/api/Objects/UnitEquipmentItem.cs	Wed Apr 01 19:20:27 2009 +0000
+++ b/api/Objects/UnitEquipmentItem.cs	Sun Apr 05 13:45:23 2009 +0000
@@ -11,23 +11,42 @@
 	/// Summary description for UnitEquipmentItem.
 	/// </summary>
 	public class UnitEquipmentItem : WarFoundryObject
-	{
-		private bool required, roundUp;
+	{
+		private EquipmentItem item;
+		private bool required;
+		private bool roundUp;
+		private int minNum;
+		private int maxNum;
+		private double minPercentage;
+		private double maxPercentage;
 		private string mutexGroup;
 		private UnitType unitType;
+
+		protected UnitEquipmentItem(EquipmentItem equipmentItem, UnitType equipForType)
+		{
+			item = equipmentItem;
+			EquipmentForUnit = equipForType;
+		}
+		
+		public override string Name
+		{
+			get {
+				return item.Name;
+			}
+			set {
+				base.Name = value;
+			}
+		}
+		
+		public string EquipmentItemID
+		{
+			get { return item.ID; }
+		}
 
-		/*public UnitEquipmentItem(XmlElement node, UnitType equipForType)
-		{
-			EquipmentForUnit = equipForType;
-			ID = node.GetAttribute("id");
-			IsRequired = bool.Parse(node.GetAttribute("required"));
-			RoundNumberUp = "up".Equals(node.GetAttribute("roundDirection").ToLower());
-			MutexGroup = node.GetAttribute("exclusivityGroup");
-		}*/
-		protected UnitEquipmentItem(UnitType equipForType)
-		{
-			EquipmentForUnit = equipForType;
-		}
+        public double Cost
+        {
+            get { return item.Cost; }
+        }
 
 		public bool IsRequired
 		{
@@ -57,11 +76,68 @@
 					unitType = value;
 				}
 			}
+		}
+		
+		public bool IsRatioLimit
+		{
+			get { return minPercentage!=100 || maxPercentage!=100; }
+		}
+		
+		public int MinNumber
+		{
+			get { return minNum; }
+			set
+			{
+				if (value >=0 || value == WarFoundryCore.INFINITY)
+				{
+					minNum = value;
+				}
+				//TODO: Check Min<Max
+			}
+		}
+		
+		public int MaxNumber
+		{
+			get { return maxNum; }
+			set
+			{
+				if (value >=0 || value == WarFoundryCore.INFINITY)
+				{
+					maxNum = value;
+				}
+				//TODO: Check Min<Max
+			}
+		}
+		
+		public double MinPercentage
+		{
+			get { return minPercentage; }
+			set
+			{
+				if (value >=0 && value <= 100)
+				{
+					minPercentage = value;
+				}
+				//TODO: Check Min<Max
+			}
+		}
+		
+		public double MaxPercentage
+		{
+			get { return maxPercentage; }
+			set
+			{
+				if (value >=0 && value <= 100)
+				{
+					maxPercentage = value;
+				}
+				//TODO: Check Min<Max
+			}
 		}
 
 		public EquipmentItem EquipmentItem
 		{
-			get { return EquipmentForUnit == null ? null : EquipmentForUnit.Race.GetEquipmentItem(ID); }
+			get { return item; }
 		}
 
 		public override string ToString()
@@ -80,6 +156,25 @@
 				//If the number of items in the MutEx group is greater than one then it must be this item plus another
 				return EquipmentForUnit.GetEquipmentItemsByExclusionGroup(MutexGroup).Length > 1;
 			}
+		}
+		
+		public static string FormatEquipmentAmount(UnitEquipmentItem item, double amount)
+		{
+			if (item.IsRatioLimit)
+			{
+				return Math.Round(amount * 100) + "%";
+			}
+			else
+			{
+				if (amount == WarFoundryCore.INFINITY)
+				{
+					return "all";
+				}
+				else
+				{
+					return amount.ToString();
+				}
+			}
 		}
 	}
 }
--- a/api/Objects/UnitEquipmentItemObj.cs	Wed Apr 01 19:20:27 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-// This file (UnitEquipmentItemObj.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 under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license.
-
-using System;
-using System.Collections;
-
-namespace IBBoard.WarFoundry.API.Objects
-{
-	/// <summary>
-	/// Summary description for UnitEquipmentItemObj.
-	/// </summary>
-	public class UnitEquipmentItemObj
-	{
-		private Unit unit;
-		private UnitEquipmentItem item;
-		private EquipmentItem equip;
-
-		private static Hashtable equipObjs = new Hashtable();
-
-		private UnitEquipmentItemObj(Unit unit, UnitEquipmentItem unitItem)
-		{
-			this.unit = unit;
-			item = unitItem;
-			equip = item.EquipmentItem;
-		}
-
-		public static UnitEquipmentItemObj GetEquipObj(Unit unit, UnitEquipmentItem unitItem)
-		{
-			if (!equipObjs.ContainsKey(unitItem))
-			{
-				equipObjs[unitItem] = new UnitEquipmentItemObj(unit, unitItem);
-			}
-			
-			return (UnitEquipmentItemObj)equipObjs[unitItem];
-		}
-
-		public override string ToString()
-		{
-			return String.Format("{0} (For {1} at {2}pts each)", equip.Name, FormatEquipmentAmount(unit, equip), equip.Cost);
-		}
-
-		public UnitEquipmentItem Item
-		{
-			get { return item; }
-		}
-
-		public static string FormatEquipmentAmount(Unit unit, EquipmentItem equip)
-		{
-			return FormatEquipmentAmount(equip, unit.GetEquipmentAmount(equip.ID));
-		}
-
-		public static string FormatEquipmentAmount(EquipmentItem equip, float amount)
-		{
-			if (equip.IsRatioLimit)
-			{
-				return Math.Round(amount * 100) + "%";
-			}
-			else
-			{
-				if (amount == WarFoundryCore.INFINITY)
-				{
-					return "all";
-				}
-				else
-				{
-					return amount.ToString();
-				}
-			}
-		}
-	}
-}
--- a/dtds/race.xsd	Wed Apr 01 19:20:27 2009 +0000
+++ b/dtds/race.xsd	Sun Apr 05 13:45:23 2009 +0000
@@ -62,8 +62,8 @@
   <xs:attribute name="id" type="xs:IDREF" />
   <xs:attribute name="required" type="xs:boolean" default="false"/>
   <xs:attribute name="exclusivityGroup" type="xs:string" default=""/>
-  <xs:attribute name="minNum" type="core:nonNegativeOrInfiniteIntegerOrRatio" default="-1"/>
-  <xs:attribute name="maxNum" type="core:nonNegativeOrInfiniteIntegerOrRatio" default="-1"/>
+  <xs:attribute name="minNum" type="core:nonNegativeOrInfiniteInteger" default="-1"/>
+  <xs:attribute name="maxNum" type="core:nonNegativeOrInfiniteInteger" default="-1"/>
   <xs:attribute name="minPercentage" type="core:percentage" default="100"/>
   <xs:attribute name="maxPercentage" type="core:percentage" default="100"/>
   <xs:attribute name="roundDirection" type="updowntype" default="up"/>