Mercurial > repos > IBBoard.WarFoundry.API
view api/Objects/Unit.cs @ 150:b36cc4af435b
Re #176: Bug when saving recently edited army
* Try to make sure that we clear up more of our open streams
Bug seems to be state related in some way since I can only trigger it when loading the file as the first action, but doesn't seem to be related to file loading of other data files since a diagnostic hard-coded "LoadFiles()" call in the FrmMain constructor doesn't change the behaviour
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sat, 26 Sep 2009 10:43:28 +0000 |
parents | c01366bd1627 |
children | 1d13820b3d96 |
line wrap: on
line source
// This file (Unit.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 2007, 2008, 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 System.Xml; using IBBoard.Lang; namespace IBBoard.WarFoundry.API.Objects { /// <summary> /// Summary description for UnitInstance. /// </summary> public class Unit : WarFoundryObject, ICostedWarFoundryObject { private UnitType type; private int size; private Unit parentUnit; private double points; private ArmyCategory cat; private Dictionary<UnitEquipmentItem, AbstractUnitEquipmentItemSelection> equipment = new Dictionary<UnitEquipmentItem, AbstractUnitEquipmentItemSelection>(); private List<Unit> containedUnits = new List<Unit>(); public event DoubleValChangedDelegate PointsValueChanged; public event IntValChangedDelegate UnitSizeChanged; public event DoubleValChangedDelegate UnitEquipmentAmountChanged; public Unit(UnitType unitType, ArmyCategory parentArmyCat) : this(unitType, unitType.MinSize, parentArmyCat) { } public Unit(UnitType unitType, int startSize, ArmyCategory parentArmyCat) : this("", "", startSize, unitType, parentArmyCat) { SetInitialEquipment(); } public Unit(string id, string name, int startSize, UnitType unitType, ArmyCategory parentArmyCat) : base(id, name) { Category = parentArmyCat; type = unitType; Size = startSize; CalcCost(); UnitEquipmentAmountChanged+= new DoubleValChangedDelegate(UnitEquipmentAmountChangedHandler); UnitSizeChanged+= new IntValChangedDelegate(UnitSizeChangedHandler); } private void UnitEquipmentAmountChangedHandler(WarFoundryObject obj, double oldVal, double newVal) { CalcCost(); } private void UnitSizeChangedHandler(WarFoundryObject obj, int oldVal, int newVal) { CalcCost(); if (HasDefaultName()) { OnNameChanged("", Name); } } 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)) { if (unitEquip.IsRatioLimit) { SetEquipmentRatio(unitEquip, unitEquip.MinPercentage); } else { SetEquipmentAmount(unitEquip, unitEquip.MinNumber); } } } } } private void CalcCost() { double oldpoints = points; points = type.CostPerTrooper * AdditionalTroopers + type.BaseUnitCost; foreach (AbstractUnitEquipmentItemSelection equipSelection in equipment.Values) { points += equipSelection.TotalCost; } if (oldpoints!=points) { OnPointsValueChanged(oldpoints, points); } } 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); OnUnitSizeChanged(oldValue, size); } } } public UnitType UnitType { get { return type; } } public Army Army { get { return (Category == null ? null : Category.ParentArmy); } } public Race Race { get { return UnitType.Race; } } public ArmyCategory Category { get { return cat; } set { cat = value; } } [Obsolete("Use Points instead")] public double PointsValue { get { return Points; } } public double Points { get { if (points == 0) { CalcCost(); } return points; } } public Unit[] ContainedUnits { get { return containedUnits.ToArray(); } } public void AddContainedUnit(Unit unit) { if (UnitType.CanContainUnit(unit)) { if (!containedUnits.Contains(unit)) { containedUnits.Add(unit); } unit.ParentUnit = this; } else { throw new InvalidContainershipException(this, unit); } } public void RemoveContainedUnit(Unit unit) { containedUnits.Remove(unit); } public Unit ParentUnit { get { return parentUnit; } set { if (!(parentUnit == value || (parentUnit != null && parentUnit.Equals(value)))) { parentUnit = value; if (value!=null) { value.AddContainedUnit(this); } } } } public UnitEquipmentItem[] GetAllowedOptionalEquipment() { List<UnitEquipmentItem> list = new List<UnitEquipmentItem>(); foreach (UnitEquipmentItem item in UnitType.GetEquipmentItems()) { if (!item.IsRequired) { list.Add(item); } } return list.ToArray(); } public UnitEquipmentItem[] GetEquipment() { return DictionaryUtils.ToKeyArray(equipment); } public EquipmentItem[] GetRequiredEquipment() { List<EquipmentItem> list = new List<EquipmentItem>(); foreach(UnitEquipmentItem item in GetEquipment()) { if (item.IsRequired) { list.Add(item.EquipmentItem); } } return list.ToArray(); } public double GetEquipmentAmount(UnitEquipmentItem item) { double amount = 0; AbstractUnitEquipmentItemSelection selection = DictionaryUtils.GetValue(equipment, item); if (selection != null) { amount = selection.AmountTaken; } return amount; } public double GetEquipmentAmount(string equipID) { return GetEquipmentAmount(UnitType.GetEquipmentItem(equipID)); } public bool GetEquipmentAmountIsRatio(UnitEquipmentItem item) { return IsEquipmentAmountRatio(GetEquipmentSelection(item)); } private AbstractUnitEquipmentItemSelection GetEquipmentSelection(UnitEquipmentItem item) { return DictionaryUtils.GetValue(equipment, item); } private bool IsEquipmentAmountRatio(AbstractUnitEquipmentItemSelection selection) { return (selection is UnitEquipmentRatioSelection); } public bool GetEquipmentAmountIsRatio(string itemID) { return GetEquipmentAmountIsRatio(UnitType.GetEquipmentItem(itemID)); } public string GetEquipmentAmountString(string equipID) { return GetEquipmentAmountString(UnitType.GetEquipmentItem(equipID)); } public string GetEquipmentAmountString(UnitEquipmentItem item) { String amountString = ""; AbstractUnitEquipmentItemSelection selection = GetEquipmentSelection(item); if (IsEquipmentAmountRatio(selection)) { amountString = UnitEquipmentRatioSelection.GetEquipmentAmountString(GetEquipmentAmount(item)); } else { amountString = UnitEquipmentNumericSelection.GetEquipmentAmountString(GetEquipmentAmount(item)); } return amountString; } public void SetEquipmentAmount(UnitEquipmentItem equip, int amount) { if (amount <1 && amount != WarFoundryCore.INFINITY) { amount = 0; } if (amount == 0) { RemoveEquipmentItem(equip); } else { AbstractUnitEquipmentItemSelection currSelection = DictionaryUtils.GetValue(equipment, equip); double oldAmount = (currSelection == null ? 0 : currSelection.AmountTaken); if (amount != oldAmount) { if (oldAmount == 0) { AddEquipmentAmount(equip, amount); } else if (currSelection is UnitEquipmentNumericSelection) { //A UnitEquipmentItem shouldn't change its IsRatio value, so assume we already have the right sub-type currSelection.AmountTaken = amount; } else { equipment.Remove(equip); AddEquipmentAmount(equip, amount); } OnUnitEquipmentAmountChanged(equip, oldAmount, amount); } } } private void AddEquipmentAmount(UnitEquipmentItem equip, int amount) { AbstractUnitEquipmentItemSelection newItem = null; if (equip.IsRatioLimit) { newItem = new UnitEquipmentNumericForRatioSelection(this, equip, amount); } else { newItem = new UnitEquipmentNumericSelection(this, equip, amount); } equipment[equip] = newItem; } public void SetEquipmentRatio(UnitEquipmentItem equip, double ratio) { if (!equip.IsRatioLimit) { throw new InvalidOperationException("Equipment with ID "+equip.ID+" for unit of type "+UnitType.ID+" has an absolute limit, not a ratio limit"); } if (ratio > 100) { ratio = 100; } else if (ratio < 0) { ratio = 0; } if (ratio == 0) { RemoveEquipmentItem(equip); } else { AbstractUnitEquipmentItemSelection currSelection = DictionaryUtils.GetValue(equipment, equip); double oldRatio = (currSelection == null ? 0 : currSelection.AmountTaken); if (ratio != oldRatio) { if (oldRatio == 0) { AddEquipmentRatio(equip, ratio); } else if (currSelection is UnitEquipmentRatioSelection) { currSelection.AmountTaken = ratio; } else { equipment.Remove(equip); AddEquipmentRatio(equip, ratio); } OnUnitEquipmentAmountChanged(equip, oldRatio, ratio); } } } private void AddEquipmentRatio(UnitEquipmentItem equip, double ratio) { equipment[equip] = new UnitEquipmentRatioSelection(this, equip, ratio); } private void RemoveEquipmentItem(UnitEquipmentItem equip) { double oldAmount = GetEquipmentAmount(equip); if (oldAmount != 0) { equipment.Remove(equip); OnUnitEquipmentAmountChanged(equip, oldAmount, 0); } } public bool CanEquipWithItem(UnitEquipmentItem item) { string mutex = item.MutexGroup; if (mutex == "") { return true; } foreach (UnitEquipmentItem unitItem in GetEquipment()) { if (unitItem.MutexGroup == mutex) { return false; } } return true; } public bool CanEquipWithItem(string equipID) { return CanEquipWithItem(UnitType.GetEquipmentItem(equipID)); } 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, double oldValue, double newValue) { if (UnitEquipmentAmountChanged!=null) { UnitEquipmentAmountChanged(equip, oldValue, newValue); } } public Stat[] UnitStatsArray { get { return UnitType.UnitStatsArray; } } public Stat[] UnitStatsArrayWithName { get { return UnitType.UnitStatsArrayWithName; } } public string GetStatValue(string statName) { return UnitType.GetStatValue(statName); } } }