view api/Objects/Race.cs @ 101:f7b9423c2a5a

Big mess of updates, breaking our rules on "commit little and often" because the code was so ugly. This revision will be broken for the WinForms UI, but as MonoDevelop/eSVN don't have a way of committing multiple projects in one go it can't be helped (Eclipse's Team Sync view could handle it) Fixes #122: Make usage of percentage or ratio common * All usage of ratio amounts for equipment items should now assume percentage * Properly calculate number taken for ratio selection (divide by 0 now we're using percentages) Fixes #118: Allow equipment amounts of "ratio" equipment to be define as absolute or ratio amounts * Added extra commands that differentiate between ratio and absolute amounts Fixes #120: Numeric limit equipment items show large percentages * Now made formatting treat ratios as percentages (don't multiply by 100) * Move string formatting to UnitEquipmentItem...Selection classes * Add method to Unit to say whether an equipment item is a numeric or ratio amount
author IBBoard <dev@ibboard.co.uk>
date Thu, 13 Aug 2009 21:09:20 +0000
parents 46ad6f478203
children 2f3cafb69799
line wrap: on
line source

// This file (Race.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.Generic;
using System.IO;
using System.Xml;
using IBBoard.IO;
using IBBoard.WarFoundry.API.Factories;

namespace IBBoard.WarFoundry.API.Objects
{
	public class Race : WarFoundryStagedLoadingObject
	{		
		public static string SYSTEM_DEFAULT_RACE_ID = "GameDefault"; 
		
		private string subID;
		private GameSystem system;
		private Dictionary<Category, Dictionary<string, UnitType>> unitTypesByCat;
		private Dictionary<string, UnitType> unitTypes = new Dictionary<string,UnitType>();
		private Dictionary<string, EquipmentItem> equipment = new Dictionary<string,EquipmentItem>();
		private Dictionary<string, Ability> abilities = new Dictionary<string,Ability>();
		private Dictionary<string, Category> categories = new Dictionary<string,Category>();
		
		public Race(string raceID, string raceName, GameSystem gameSystem, IWarFoundryFactory creatingFactory) : this(raceID, "", raceName, gameSystem, creatingFactory)
		{
		}
		
		public Race(string raceID, string raceSubID, string raceName, GameSystem gameSystem, IWarFoundryFactory creatingFactory) : base(raceID + (raceSubID!="" ? "_"+raceSubID : ""), raceName, creatingFactory)
		{
			subID = (raceSubID == null ? "" : raceSubID);
			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
		{
			get { return subID; }
			set { subID = (value == null ? "" : value.Trim()); }
		}

		public GameSystem GameSystem
		{
			get { return system; }
			set
			{
				if (value == null)
				{
					throw new ArgumentException("Game system for a race cannot be null");
				}
				
				system = value;
			}
		}
		
		public void AddCategory(Category cat)
		{
			categories[cat.ID] = cat;
		}

		/// <summary>
		/// Gets a category from its ID. Attempts to get the category from the race's overrides, or else it falls back to getting the Game System's category with that ID.
		/// </summary>
		/// <param name="id">
		/// The ID of the category to get
		/// </param>
		/// <returns>
		/// The <code>Category</code> with the specified ID, or null if one doesn't exist. 
		/// </returns>
		public Category GetCategory(string id)
		{
			EnsureFullyLoaded();
			Category cat = null;
			categories.TryGetValue(id, out cat);
			
			if (cat == null)
			{
				cat = GameSystem.GetCategory(id);
			}
						
			return cat;
		}

		public Category[] Categories
		{
			get 
			{ 
				EnsureFullyLoaded();
				Category[] cats;
				
				if (!HasCategoryOverrides())
				{
					cats = GameSystem.Categories;
				}
				else
				{
					cats = DictionaryUtils.ToArray<string, Category>(categories);
				}
				
				return cats;
			}
		}

		public bool HasCategoryOverrides()
		{
			return categories.Count > 0;
		}

		public void AddEquipmentItem(EquipmentItem item)
		{
			//TODO: Throw DuplicateItemException
			equipment.Add(item.ID, item);
		}

		[Obsolete("Use AddEquipmentItem method instead")]
		public void SetEquipmentItems(Dictionary<string, EquipmentItem> items)
		{
			foreach (EquipmentItem item in items.Values)
			{
				AddEquipmentItem(item);
			}
		}

		public EquipmentItem GetEquipmentItem(string id)
		{
			EnsureFullyLoaded();
			return DictionaryUtils.GetValue(equipment, id);
		}
		
		public List<EquipmentItem> GetEquipmentList()
		{
			List<EquipmentItem> items = new List<EquipmentItem>();
			
			foreach (EquipmentItem item in equipment.Values)
			{
				items.Add(item);
			}
			
			return items;
		}

		public void AddUnitType(UnitType type)
		{
			CacheUnitType(type);
			unitTypes.Add(type.ID, type);
		}

		[Obsolete("Use AddUnitType method instead")]
		public void SetUnitTypes(Dictionary<string, UnitType> types)
		{
			foreach (UnitType type in types.Values)
			{
				AddUnitType(type);
			}
		}

		public UnitType[] GetUnitTypes(Category cat)
		{		
			BuildUnitTypesByCategoryCache();
			Dictionary<string, UnitType> unitTypesDictionary;
			unitTypesByCat.TryGetValue(cat, out unitTypesDictionary);
			UnitType[] unitTypesArray;
			
			if (unitTypesDictionary == null)
			{
				unitTypesArray = new UnitType[0];
			}
			else
			{
				unitTypesArray = DictionaryUtils.ToArray<string, UnitType>(unitTypesDictionary);
			}
			
			return unitTypesArray;
		}

		private void CacheUnitType(UnitType unit)
		{
			BuildUnitTypesByCategoryCache();
			Dictionary<string,UnitType> catUnitTypes;
			unitTypesByCat.TryGetValue(unit.MainCategory, out catUnitTypes);

			if (catUnitTypes == null)
			{
				throw new InvalidFileException(String.Format("Unit type {0} with name {1} is a unit of an undefined category", unit.ID, unit.Name));
			}

			catUnitTypes.Add(unit.ID, unit);
		}
		
		private void BuildUnitTypesByCategoryCache()
		{
			if (unitTypesByCat == null)
			{
				DoBuildUnitTypesByCategoryCache();
			}
		}

		private void DoBuildUnitTypesByCategoryCache()
		{
			unitTypesByCat = new Dictionary<Category,Dictionary<string,UnitType>>();
				
			foreach (Category category in Categories)
			{ 
				unitTypesByCat.Add(category, new Dictionary<string, UnitType>());
			}
			
			foreach (UnitType unit in unitTypes.Values)
			{
				CacheUnitType(unit);
			}
		}

		public UnitType GetUnitType(string id)
		{
			UnitType type = null;
			unitTypes.TryGetValue(id, out type);
			return type;
		}
		
		public List<Ability> GetAbilityList()
		{
			List<Ability> items = new List<Ability>();
			items.AddRange(abilities.Values);			
			return items;
		}
		
		public void AddAbility(Ability newAbility)
		{
			//TODO: Throw DuplicateItemException
			abilities.Add(newAbility.ID, newAbility);
		}

		[Obsolete("Use AddAbility method instead")]
		public void SetAbilities(Dictionary<string, Ability> newAbilities)
		{
			foreach (Ability ability in newAbilities.Values)
			{
				AddAbility(ability);
			}
		}
				
		public Ability GetAbility(string id)
		{
			Ability ability = null;
			abilities.TryGetValue(id, out ability);
			return ability;
		}
		
		protected virtual Dictionary<string, UnitType> RaceUnitTypes
		{
			get { return RaceRawUnitTypes; }
			set	{ RaceRawUnitTypes = value; }
		}
		
		protected virtual Dictionary<string, EquipmentItem> RaceEquipment
		{
			get { return RaceRawEquipment; }
			set { RaceRawEquipment = value; }
		}
		
		protected virtual Dictionary<string, Ability> RaceAbilities
		{
			get { return RaceRawAbilities; }
			set { RaceRawAbilities = value; }
		}
		
		protected Dictionary<string, UnitType> RaceRawUnitTypes
		{
			get { return unitTypes; }
			set	{ unitTypes = value; }
		}
		
		protected Dictionary<string, EquipmentItem> RaceRawEquipment
		{
			get { return equipment; }
			set { equipment = value; }
		}
		
		protected Dictionary<string, Ability> RaceRawAbilities
		{
			get { return abilities; }
			set { abilities = value; }
		}
	}
}