view api/Objects/Unit.cs @ 14:0770e5cbba7c

Closes #21 - File loading in order * Reworked LoadFiles to smaller methods for readability (also re #10) and structure * Now determine expected load return before loading then load all "expected GameSystem" before "expected Race" * Make "can load as race/game system/army" methods public in interface Re #22 - Get errored file loading * Created FileLoadFailure class and made LoadFiles return a list of them Also * Some code cleanup * Change to DictionaryUtils calls
author IBBoard <dev@ibboard.co.uk>
date Sun, 25 Jan 2009 14:03:20 +0000
parents 520818033bb6
children 306558904c2a
line wrap: on
line source

using System;
using System.Collections;
using System.Text;
using System.Xml;
using IBBoard.Lang;

namespace IBBoard.WarFoundry.API.Objects
{
	/// <summary>
	/// Summary description for UnitInstance.
	/// </summary>
	public class Unit : WarFoundryObject
	{
		private UnitType type;
		private int size;
		private Army army;
		private Race race;
		private double points;
		private ArmyCategory cat;
		private Hashtable equipment = new Hashtable();
		public event DoubleValChangedDelegate PointsValueChanged;
		public event IntValChangedDelegate UnitSizeChanged;
		public event FloatValChangedDelegate UnitEquipmentAmountChanged;

		public Unit(UnitType unitType, Army parentArmy) : this(unitType, unitType.MinSize, parentArmy){}

		public Unit(UnitType unitType, int startSize, Army parentArmy)
		{
			Army = parentArmy;
			type = unitType;
			Size = startSize;
			setInitialEquipment();
			CalcCost();
		}

		protected override string DefaultName()
		{
			if (type != null)
			{
				if (size == 1)
				{
					return type.Name;
				}
				else
				{
					return String.Format(Translation.GetTranslation("defaultUnitName"), size, type.Name);
				}
			}
			else
			{
				return "Unknown Unit";
			}
		}

		private void setInitialEquipment()
		{
			foreach (UnitEquipmentItem unitEquip in UnitType.GetEquipmentItems())
			{
				if (unitEquip.IsRequired)
				{
					if (CanEquipWithItem(unitEquip.ID))
					{
						EquipmentItem equipItem = unitEquip.EquipmentItem;
						equipment[unitEquip.ID] = equipItem.MinNumber;
					}
				}
			}
		}

		private void CalcCost()
		{
			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)
			{
				unitEquipItem = UnitType.GetEquipmentItem(key);
				equipItem = unitEquipItem.EquipmentItem;
				count = (float)equipment[key];
				
				if (equipItem.IsRatioLimit)
				{
					if (unitEquipItem.RoundNumberUp)
					{
						points+= Math.Ceiling(size * count) * equipItem.Cost;
					}
					else
					{
						points+= Math.Floor(size * count) * equipItem.Cost;
					}
				}
				else
				{
					if (count == -1)
					{
						points+= size * equipItem.Cost;
					}
					else
					{
						points+= count * equipItem.Cost;
					}
				}
			}

			if (oldpoints!=points)
			{
				OnPointsValueChanged(oldpoints, points);
			}

			if (oldName!=null)
			{
				OnNameChanged(oldName, Name);
			}
		}
		
		public int AdditionalTroopers
		{
			get { return Math.Max(Size - type.BaseSize, 0); }
		}

		public int Size
		{
			get { return size; }
			set 
			{
				if (value!=size)
				{
					int oldValue = size;
					size = (value>0 ? value : 1);
					CalcCost();
					OnUnitSizeChanged(oldValue, size);
				}
			}
		}

		public UnitType UnitType
		{
			get { return type; }
		}

		public Army Army
		{
			get { return army; }
			set 
			{
				army = value;

				if (army == null)
				{
					Category = null;
				}
			}
		}

		public Race Race
		{
			get { return race; }
			set { race = value; }
		}

		public ArmyCategory Category
		{
			get 
			{ 
				if (cat==null)
				{
					if (Army!=null)
					{
						return Army.GetCategory(UnitType.MainCategory);
					}
					else
					{
						return null;
					}
				}
				else
				{
					return cat; 
				}
			}
			set { cat = value; }
		}

		public double PointsValue
		{
			get 
			{
				if (points == 0)
				{
					CalcCost();
				}

				return points;
			}
		}

		public UnitEquipmentItem[] GetAllowedOptionalEquipment()
		{
			ArrayList list = new ArrayList();

			foreach (UnitEquipmentItem item in UnitType.GetEquipmentItems())
			{
				if (!item.IsRequired)
				{
					list.Add(item);
				}
			}

			return (UnitEquipmentItem[])list.ToArray(typeof(UnitEquipmentItem));
		}

		public UnitEquipmentItem[] GetEquipment()
		{
			UnitEquipmentItem[] items = new UnitEquipmentItem[equipment.Count];
			int i = 0;

			foreach (String itemID in equipment.Keys)
			{
				items[i++] = UnitType.GetEquipmentItem(itemID);
			}

			return items;
		}

		public UnitEquipmentItem[] GetRequiredEquipment()
		{
			ArrayList list = new ArrayList();
			UnitEquipmentItem item;

			foreach(String itemID 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);
		}

		public float GetEquipmentAmount(string equipID)
		{
			if (equipment.ContainsKey(equipID))
			{
				return (float)equipment[equipID];
			}
			else
			{
				return 0;
			}
		}

		public void SetEquipmentAmount(string equipID, float amount)
		{
			UnitEquipmentItem equip = UnitType.GetEquipmentItem(equipID);

			if (equip == null)
			{
				throw new InvalidOperationException("No such equipment ID "+equipID+" for unit "+ID);
			}

			if (equip.EquipmentItem.IsRatioLimit)
			{
				if (amount > 1)
				{
					amount = 1;
				}
				else if (amount < 0)
				{
					amount = 0;
				}
				//else what was passed in was okay
			}
			else
			{
				if (amount >=1 || amount == -1)
				{
					amount = (float)Math.Round(amount);
				}
				else
				{
					amount = 0;
				}
			}

			float oldAmount = 0;

			if (equipment.ContainsKey(equipID))
			{
				oldAmount = (float)equipment[equipID];
			}

			if (amount!=oldAmount)
			{
				if (amount > 0 || amount == -1)
				{
					equipment[equipID] = amount;
				}
				else
				{
					equipment.Remove(equipID);
				}

				OnUnitEquipmentAmountChanged(equip, oldAmount, amount);
				CalcCost();
			}
		}

		public bool CanEquipWithItem(string equipID)
		{
			string mutex = UnitType.GetEquipmentItem(equipID).MutexGroup;

			if (mutex == "")
			{
				return true;
			}

			foreach (string itemID in equipment.Keys)
			{
				if (UnitType.GetEquipmentItem(itemID).MutexGroup == mutex)
				{
					return false;
				}
			}

			return true;
		}

		private void OnPointsValueChanged(double oldValue, double newValue)
		{
			if (PointsValueChanged!=null)
			{
				PointsValueChanged(this, oldValue, newValue);
			}
		}

		private void OnUnitSizeChanged(int oldValue, int newValue)
		{
			if (UnitSizeChanged!=null)
			{
				UnitSizeChanged(this, oldValue, newValue);
			}
		}

		private void OnUnitEquipmentAmountChanged(UnitEquipmentItem equip, float oldValue, float newValue)
		{
			if (UnitEquipmentAmountChanged!=null)
			{
				UnitEquipmentAmountChanged(equip, oldValue, newValue);
			}
		}

		public Stats UnitStats
		{
			get { return UnitType.UnitStats; }
		}

		/*public override string ToXmlString()
		{
			StringBuilder sb = new StringBuilder();
			float amount;

			foreach(string key in equipment.Keys)
			{
				amount = (float)equipment[key];

				if (amount > 0 || amount == -1)
				{
					sb.Append("<equipItem id=\""+key+"\" amount=\""+amount+"\" />");
				}
			}

			string equipmentString;

			if (sb.Length > 0)
			{
				equipmentString = "<equipment>"+sb.ToString()+"</equipment>";
			}
			else
			{
				equipmentString = "";
			}

			if (equipmentString == "")
			{
				return "<unit id=\""+ID+"\" unitType=\""+UnitType.ID+"\" unitName=\""+name+"\" size=\""+Size+"\" />";
			}
			else
			{
				return "<unit id=\""+ID+"\" unitType=\""+UnitType.ID+"\" unitName=\""+name+"\" size=\""+Size+"\">"+equipmentString+"</unit>";
			}
		}*/
	}
}