Mercurial > repos > IBBoard.WarFoundry.API
view API/Util/UnitEquipmentUtil.cs @ 494:4f01fdc3bb41
Re #410: Create "N units per M models in parent unit" requirement
* Make sure that adding context is in at the top level and propagated through requirement handling
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Mon, 06 Aug 2012 20:50:59 +0100 |
parents | c8002429ab45 |
children |
line wrap: on
line source
// This file (UnitEquipmentUtil.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.Text; using IBBoard.CustomMath; using IBBoard.Limits; using IBBoard.WarFoundry.API.Objects; namespace IBBoard.WarFoundry.API.Util { public class UnitEquipmentUtil { /// <summary> /// Gets an array of allowed <see cref="UnitEquipmentItem"/>s based on the current selections of the unit, taking in to account Mutex groups and other limits. /// </summary> /// <param name="unit">The <see cref="Unit"/> to get equipment items for</param> /// <returns>The array of allowed <see cref="UnitEquipmentItem"/>s</returns> public static UnitEquipmentItem[] GetAllowedEquipmentItems(Unit unit) { List<UnitEquipmentItem> list = new List<UnitEquipmentItem>(); UnitEquipmentItem[] currItems = unit.GetEquipment(); foreach (UnitEquipmentItem item in GetAllEquipmentItems(unit)) { bool allowed = IsAllowedByMutex(item, currItems); if (allowed) { list.Add(item); } } return list.ToArray(); } private static bool IsAllowedByMutex(UnitEquipmentItem item, UnitEquipmentItem[] currItems) { bool allowed = true; foreach (UnitEquipmentItem currItem in currItems) { if (ItemsAreMutuallyExclusive(currItem, item)) { allowed = false; break; } } return allowed; } /// <summary> /// Gets a list of all <see cref="UnitEquipmentItem"/>s that would stop the unit taking <code>item</code> because of mutex groups. /// </summary> /// <param name="unit">The unit that wants to take the equipment item</param> /// <param name="item">The item to check blocking items for</param> /// <returns>a list of all <see cref="UnitEquipmentItem"/>s that would stop the unit taking <code>item</code></returns> public static List<UnitEquipmentItem> GetBlockingEquipmentItems(Unit unit, UnitEquipmentItem item) { List<UnitEquipmentItem> items = new List<UnitEquipmentItem>(); UnitEquipmentItem[] currItems = unit.GetEquipment(); foreach (UnitEquipmentItem unitItem in currItems) { if (ItemsAreMutuallyExclusive(unitItem, item)) { items.Add(unitItem); } } return items; } public static UnitEquipmentItem[] GetAllEquipmentItems(Unit unit) { return unit.UnitType.GetEquipmentItems(); } public static bool ItemsAreMutuallyExclusive(UnitEquipmentItem item1, UnitEquipmentItem item2) { bool areMutex = false; string[] item1mutex = item1.MutexGroups; string[] item2mutex = item2.MutexGroups; foreach (string mutex in item1mutex) { foreach (string otherMutex in item2mutex) { if (mutex.Equals(otherMutex)) { areMutex = true; goto postLoop; } } } postLoop: return areMutex; } public static int GetMaxEquipmentCount (Unit unit, UnitEquipmentItem equip) { return GetEquipmentCountLimit (unit, equip.MaxLimit.GetLimit(unit.Size), equip); } private static int GetEquipmentCountLimit (Unit unit, int currLimit, UnitEquipmentItem equip) { int newLimit = currLimit; ILimit limit = GetSlotLimitForItem(unit, equip); if (!(limit is UnlimitedLimit)) { int slotMax = limit.GetLimit (unit.Size) - unit.GetEquipmentAmountInSlotExcludingItem(equip); newLimit = Math.Min (slotMax, newLimit); } return newLimit; } private static ILimit GetSlotLimitForItem(Unit unit, UnitEquipmentItem equip) { return unit.UnitType.GetEquipmentSlotLimit(equip.SlotName); } public static int GetMinEquipmentCount (Unit unit, UnitEquipmentItem equip) { return GetEquipmentCountLimit (unit, equip.MinLimit.GetLimit(unit.Size), equip); } public static bool IsEquipmentRatioLimited(Unit unit, UnitEquipmentItem equip) { ILimit limit = GetSlotLimitForItem(unit, equip); return equip.IsRatioLimit && (limit is IPercentageLimit || limit is UnlimitedLimit); } public static double GetMaxEquipmentPercentage(Unit unit, UnitEquipmentItem equip) { return GetMinOfSlotLimitAndEquipmentLimit(equip, equip.MaxLimit, unit); } private static double GetPercentageOfUnitSize(int number, Unit unit) { return IBBMath.Percentage(number, unit.Size); } private static double GetMinOfSlotLimitAndEquipmentLimit(UnitEquipmentItem equip, ILimit equipLimit, Unit unit) { double limit = 0; ILimit slotLimit = GetSlotLimitForItem(unit, equip); if (slotLimit is IPercentageLimit) { limit = ((IPercentageLimit)slotLimit).Percentage - GetPercentageOfUnitSize(unit.GetEquipmentAmountInSlotExcludingItem(equip), unit); } else { int remaining = slotLimit.GetLimit(unit.Size) - unit.GetEquipmentAmountInSlotExcludingItem(equip); limit = GetPercentageOfUnitSize(remaining, unit); } if (equip.IsRatioLimit) { limit = Math.Min(limit, ((IPercentageLimit)equipLimit).Percentage); } else { limit = Math.Min(limit, GetPercentageOfUnitSize(equipLimit.GetLimit(unit.Size), unit)); } return limit; } public static double GetMinEquipmentPercentage(Unit unit, UnitEquipmentItem equip) { return GetMinOfSlotLimitAndEquipmentLimit(equip, equip.MinLimit, unit); } public static double GetEquipmentAmount(Unit unit, UnitEquipmentItem item) { double amount = 0; AbstractUnitEquipmentItemSelection selection = unit.GetEquipmentSelection(item); if (selection != null) { amount = selection.AmountTaken; } return amount; } public static bool GetEquipmentAmountIsRatio(Unit unit, UnitEquipmentItem item) { return (unit.GetEquipmentSelection(item) is UnitEquipmentRatioSelection); } public static int GetEquipmentAmountTaken(Unit unit, UnitEquipmentItem item) { AbstractUnitEquipmentItemSelection selection = unit.GetEquipmentSelection(item); return (selection == null ? 0 : selection.NumberTaken); } public static bool CanEditEquipmentAmount(Unit unit, UnitEquipmentItem item) { return item !=null && (item.MaxLimit.GetLimit(unit.Size) != item.MinLimit.GetLimit(unit.Size)); } public static int CalculateEquipmentAmountTakenFromRatio(Unit unit, UnitEquipmentItem equipItem, double newAmount) { return (int)IBBMath.Round(unit.Size * (newAmount / 100), equipItem.RoundNumberUp); } } }