/// <summary> /// Shipyard modifications are done here. /// </summary> /// <param name="CurrentFaction">Current faction this shipyard belongs to.</param> /// <param name="CurrentPopulation">Current population this shipyard is on.</param> /// <param name="SYInfo">The shipyard itself.</param> private static void PerformShipyardActivity(Faction CurrentFaction, Population CurrentPopulation, Installation.ShipyardInformation SYInfo) { if (SYInfo.CurrentActivity.Activity != Constants.ShipyardInfo.ShipyardActivity.NoActivity && SYInfo.CurrentActivity.Paused == false) { float SYBP = SYInfo.CalcAnnualSYProduction() * Constants.Colony.ConstructionCycleFraction; int Adjustment = 1; if (SYInfo.ShipyardType == Constants.ShipyardInfo.SYType.Naval) { Adjustment = Constants.ShipyardInfo.NavalToCommercialRatio; } /// <summary> /// Don't bother with completion date, or progress, just add the capacity. /// </summary> if (SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansion || SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansionUntilX) { /// <summary> /// How many tons could this shipyard expand capacity by in this time increment? SYBP is the number of BP produced this cycle. BaseTotalCostOfExpansion is the cost for 500 tons. /// Adjustment is the factor that accounts for whether or not this is a commercial yard or a naval yard. /// </summary> float BaseCostIncrement = SYBP / (float)(Constants.ShipyardInfo.BaseTotalCostOfExpansion * Adjustment); float TonsPerCycle = BaseCostIncrement * (float)Constants.ShipyardInfo.TonnageDenominator; /// <summary> /// Don't build more than this many tons if the activity is CapX. /// </summary> if (SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansionUntilX) { if (SYInfo.Tonnage + (int)Math.Floor(TonsPerCycle) > SYInfo.CurrentActivity.CapExpansionLimit) { TonsPerCycle = SYInfo.CurrentActivity.CapExpansionLimit - SYInfo.Tonnage; } SYInfo.CurrentActivity.Progress = 1.0m - (((decimal)SYInfo.CurrentActivity.CapExpansionLimit - (decimal)(SYInfo.Tonnage + TonsPerCycle)) / (decimal)SYInfo.CurrentActivity.CapExpansionLimit); } decimal Cost = (Constants.ShipyardInfo.BaseTotalCostOfExpansion * Adjustment) * ((decimal)TonsPerCycle / (decimal)Constants.ShipyardInfo.TonnageDenominator) * SYInfo.Slipways * Adjustment; decimal[] mCost = new decimal[(int)Constants.Minerals.MinerialNames.MinerialCount]; mCost[(int)Constants.Minerals.MinerialNames.Duranium] = Cost / 2.0m; mCost[(int)Constants.Minerals.MinerialNames.Neutronium] = Cost / 2.0m; /// <summary> /// Can I build this tick's worth of production? /// </summary> bool CanBuild = CurrentPopulation.MineralRequirement(mCost, 1.0f); if (CanBuild == true) { CurrentPopulation.HandleShipyardCost(Cost, mCost, 1.0f); SYInfo.AddTonnage(CurrentFaction, (int)Math.Floor(TonsPerCycle)); } else { String Entry = String.Format("Not enough minerals to finish task {0} at Shipyard {1} on Population {2}", SYInfo.CurrentActivity.Activity, SYInfo, CurrentPopulation); MessageEntry NMsg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Position.System, CurrentPopulation, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); GameState.Instance.Factions[0].MessageLog.Add(NMsg); } } else { /// <summary> /// BP produced this construction cycle / the total cost of the activity. /// </summary> float CurrentProgress = SYBP / (float)SYInfo.CurrentActivity.CostOfActivity; if ((SYInfo.CurrentActivity.Progress + (decimal)CurrentProgress) > 1.0m) { CurrentProgress = (float)(1.0m - SYInfo.CurrentActivity.Progress); } bool CanBuild = CurrentPopulation.MineralRequirement(SYInfo.CurrentActivity.minerialsCost, CurrentProgress); if (CanBuild == true) { CurrentPopulation.HandleShipyardCost(SYInfo.CurrentActivity.CostOfActivity, SYInfo.CurrentActivity.minerialsCost, CurrentProgress); SYInfo.CurrentActivity.Progress = SYInfo.CurrentActivity.Progress + (decimal)CurrentProgress; } else { String Entry = String.Format("Not enough minerals to finish task {0} at Shipyard {1} on Population {2}", SYInfo.CurrentActivity.Activity, SYInfo, CurrentPopulation); MessageEntry NMsg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Position.System, CurrentPopulation, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); GameState.Instance.Factions[0].MessageLog.Add(NMsg); } /// <summary> /// handle standard task completion here. /// </summary> if (SYInfo.CurrentActivity.Progress >= 1.0m) { switch (SYInfo.CurrentActivity.Activity) { case Constants.ShipyardInfo.ShipyardActivity.AddSlipway: SYInfo.Slipways = SYInfo.Slipways + 1; break; case Constants.ShipyardInfo.ShipyardActivity.Add500Tons: SYInfo.AddTonnage(CurrentFaction, Constants.ShipyardInfo.TonnageDenominator); break; case Constants.ShipyardInfo.ShipyardActivity.Add1000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 2)); break; case Constants.ShipyardInfo.ShipyardActivity.Add2000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 4)); break; case Constants.ShipyardInfo.ShipyardActivity.Add5000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 10)); break; case Constants.ShipyardInfo.ShipyardActivity.Add10000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 20)); break; case Constants.ShipyardInfo.ShipyardActivity.Retool: SYInfo.AssignedClass = SYInfo.CurrentActivity.TargetOfRetool; if (SYInfo.AssignedClass.IsLocked == false) { SYInfo.AssignedClass.IsLocked = true; } break; } } else { /// <summary> /// Update the timer since this project won't finish just yet. /// </summary> decimal CostLeft = SYInfo.CurrentActivity.CostOfActivity * (1.0m - SYInfo.CurrentActivity.Progress); float YearsOfProduction = (float)CostLeft / SYInfo.CalcAnnualSYProduction(); DateTime EstTime = GameState.Instance.GameDateTime; if (YearsOfProduction < Constants.Colony.TimerYearMax) { float DaysInYear = (float)Constants.TimeInSeconds.RealYear / (float)Constants.TimeInSeconds.Day; int TimeToBuild = (int)Math.Floor(YearsOfProduction * DaysInYear); TimeSpan TS = new TimeSpan(TimeToBuild, 0, 0, 0); EstTime = EstTime.Add(TS); } SYInfo.CurrentActivity.CompletionDate = EstTime; } } /// <summary> /// Lastly clean up any completed activities. /// </summary> if (SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansionUntilX) { if (SYInfo.Tonnage >= SYInfo.CurrentActivity.CapExpansionLimit) { /// <summary> /// This activity has completed so end it. /// </summary> SYInfo.CurrentActivity = new Installation.ShipyardInformation.ShipyardActivity(); } } else if (SYInfo.CurrentActivity.Activity != Constants.ShipyardInfo.ShipyardActivity.CapExpansion && SYInfo.CurrentActivity.Activity != Constants.ShipyardInfo.ShipyardActivity.NoActivity) { if (SYInfo.CurrentActivity.Progress >= 1.0m) { /// <summary> /// This activity has completed so end it. /// </summary> SYInfo.CurrentActivity = new Installation.ShipyardInformation.ShipyardActivity(); } } } }
/// <summary> /// Shipyard modifications are done here. /// </summary> /// <param name="CurrentFaction">Current faction this shipyard belongs to.</param> /// <param name="CurrentPopulation">Current population this shipyard is on.</param> /// <param name="SYInfo">The shipyard itself.</param> private static void PerformShipyardActivity(Faction CurrentFaction, Population CurrentPopulation, Installation.ShipyardInformation SYInfo) { if (SYInfo.CurrentActivity.Activity != Constants.ShipyardInfo.ShipyardActivity.NoActivity && SYInfo.CurrentActivity.Paused == false) { float SYBP = SYInfo.CalcAnnualSYProduction() * Constants.Colony.ConstructionCycleFraction; int Adjustment = 1; if (SYInfo.ShipyardType == Constants.ShipyardInfo.SYType.Naval) { Adjustment = Constants.ShipyardInfo.NavalToCommercialRatio; } /// <summary> /// Don't bother with completion date, or progress, just add the capacity. /// </summary> if (SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansion || SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansionUntilX) { /// <summary> /// How many tons could this shipyard expand capacity by in this time increment? SYBP is the number of BP produced this cycle. BaseTotalCostOfExpansion is the cost for 500 tons. /// Adjustment is the factor that accounts for whether or not this is a commercial yard or a naval yard. /// </summary> float BaseCostIncrement = SYBP / (float)(Constants.ShipyardInfo.BaseTotalCostOfExpansion * Adjustment); float TonsPerCycle = BaseCostIncrement * (float)Constants.ShipyardInfo.TonnageDenominator; /// <summary> /// Don't build more than this many tons if the activity is CapX. /// </summary> if (SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansionUntilX) { if (SYInfo.Tonnage + (int)Math.Floor(TonsPerCycle) > SYInfo.CurrentActivity.CapExpansionLimit) { TonsPerCycle = SYInfo.CurrentActivity.CapExpansionLimit - SYInfo.Tonnage; } SYInfo.CurrentActivity.Progress = 1.0m - (((decimal)SYInfo.CurrentActivity.CapExpansionLimit - (decimal)(SYInfo.Tonnage + TonsPerCycle)) / (decimal)SYInfo.CurrentActivity.CapExpansionLimit); } decimal Cost = (Constants.ShipyardInfo.BaseTotalCostOfExpansion*Adjustment) * ((decimal)TonsPerCycle / (decimal)Constants.ShipyardInfo.TonnageDenominator) * SYInfo.Slipways * Adjustment; decimal[] mCost = new decimal[(int)Constants.Minerals.MinerialNames.MinerialCount]; mCost[(int)Constants.Minerals.MinerialNames.Duranium] = Cost / 2.0m; mCost[(int)Constants.Minerals.MinerialNames.Neutronium] = Cost / 2.0m; /// <summary> /// Can I build this tick's worth of production? /// </summary> bool CanBuild = CurrentPopulation.MineralRequirement(mCost, 1.0f); if (CanBuild == true) { CurrentPopulation.HandleShipyardCost(Cost, mCost, 1.0f); SYInfo.AddTonnage(CurrentFaction, (int)Math.Floor(TonsPerCycle)); } else { String Entry = String.Format("Not enough minerals to finish task {0} at Shipyard {1} on Population {2}", SYInfo.CurrentActivity.Activity, SYInfo, CurrentPopulation); MessageEntry NMsg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Position.System, CurrentPopulation, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); GameState.Instance.Factions[0].MessageLog.Add(NMsg); } } else { /// <summary> /// BP produced this construction cycle / the total cost of the activity. /// </summary> float CurrentProgress = SYBP / (float)SYInfo.CurrentActivity.CostOfActivity; if ((SYInfo.CurrentActivity.Progress + (decimal)CurrentProgress) > 1.0m) { CurrentProgress = (float)(1.0m - SYInfo.CurrentActivity.Progress); } bool CanBuild = CurrentPopulation.MineralRequirement(SYInfo.CurrentActivity.minerialsCost, CurrentProgress); if (CanBuild == true) { CurrentPopulation.HandleShipyardCost(SYInfo.CurrentActivity.CostOfActivity, SYInfo.CurrentActivity.minerialsCost, CurrentProgress); SYInfo.CurrentActivity.Progress = SYInfo.CurrentActivity.Progress + (decimal)CurrentProgress; } else { String Entry = String.Format("Not enough minerals to finish task {0} at Shipyard {1} on Population {2}", SYInfo.CurrentActivity.Activity, SYInfo, CurrentPopulation); MessageEntry NMsg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Position.System, CurrentPopulation, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); GameState.Instance.Factions[0].MessageLog.Add(NMsg); } /// <summary> /// handle standard task completion here. /// </summary> if (SYInfo.CurrentActivity.Progress >= 1.0m) { switch (SYInfo.CurrentActivity.Activity) { case Constants.ShipyardInfo.ShipyardActivity.AddSlipway: SYInfo.Slipways = SYInfo.Slipways + 1; break; case Constants.ShipyardInfo.ShipyardActivity.Add500Tons: SYInfo.AddTonnage(CurrentFaction, Constants.ShipyardInfo.TonnageDenominator); break; case Constants.ShipyardInfo.ShipyardActivity.Add1000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 2)); break; case Constants.ShipyardInfo.ShipyardActivity.Add2000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 4)); break; case Constants.ShipyardInfo.ShipyardActivity.Add5000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 10)); break; case Constants.ShipyardInfo.ShipyardActivity.Add10000Tons: SYInfo.AddTonnage(CurrentFaction, (Constants.ShipyardInfo.TonnageDenominator * 20)); break; case Constants.ShipyardInfo.ShipyardActivity.Retool: SYInfo.AssignedClass = SYInfo.CurrentActivity.TargetOfRetool; if (SYInfo.AssignedClass.IsLocked == false) SYInfo.AssignedClass.IsLocked = true; break; } } else { /// <summary> /// Update the timer since this project won't finish just yet. /// </summary> decimal CostLeft = SYInfo.CurrentActivity.CostOfActivity * (1.0m - SYInfo.CurrentActivity.Progress); float YearsOfProduction = (float)CostLeft / SYInfo.CalcAnnualSYProduction(); DateTime EstTime = GameState.Instance.GameDateTime; if (YearsOfProduction < Constants.Colony.TimerYearMax) { float DaysInYear = (float)Constants.TimeInSeconds.RealYear / (float)Constants.TimeInSeconds.Day; int TimeToBuild = (int)Math.Floor(YearsOfProduction * DaysInYear); TimeSpan TS = new TimeSpan(TimeToBuild, 0, 0, 0); EstTime = EstTime.Add(TS); } SYInfo.CurrentActivity.CompletionDate = EstTime; } } /// <summary> /// Lastly clean up any completed activities. /// </summary> if (SYInfo.CurrentActivity.Activity == Constants.ShipyardInfo.ShipyardActivity.CapExpansionUntilX) { if (SYInfo.Tonnage >= SYInfo.CurrentActivity.CapExpansionLimit) { /// <summary> /// This activity has completed so end it. /// </summary> SYInfo.CurrentActivity = new Installation.ShipyardInformation.ShipyardActivity(); } } else if (SYInfo.CurrentActivity.Activity != Constants.ShipyardInfo.ShipyardActivity.CapExpansion && SYInfo.CurrentActivity.Activity != Constants.ShipyardInfo.ShipyardActivity.NoActivity) { if (SYInfo.CurrentActivity.Progress >= 1.0m) { /// <summary> /// This activity has completed so end it. /// </summary> SYInfo.CurrentActivity = new Installation.ShipyardInformation.ShipyardActivity(); } } } }
/// <summary> /// Do all of the tasks that this shipyard has assigned to it. /// </summary> /// <param name="CurrentFaction">Faction both the population and the shipyard belong to.</param> /// <param name="CurrentPopulation">Population the shipyard is on</param> /// <param name="SYInfo">Shipyard the tasks are happening at</param> private static void BuildShips(Faction CurrentFaction, Population CurrentPopulation, List <Installation.ShipyardInformation.ShipyardTask> SortedList) { BindingList <Installation.ShipyardInformation.ShipyardTask> TasksToRemove = new BindingList <Installation.ShipyardInformation.ShipyardTask>(); foreach (Installation.ShipyardInformation.ShipyardTask Task in SortedList) { if (Task.IsPaused() == true) { continue; } /// <summary> /// the Annual Build Rate(ABR) is the number of BP per year that will be devoted to this activity. this is the number of BP produced only this cycle. /// </summary> float CycleBuildRate = Task.ABR * Constants.Colony.ConstructionCycleFraction; /// <summary> /// How much of this task will be completed this construction cycle? /// </summary> float CurrentProgress = CycleBuildRate / (float)Task.Cost; if ((Task.Progress + (decimal)CurrentProgress) > 1.0m) { CurrentProgress = (float)(1.0m - Task.Progress); } /// <summary> /// Can this shipyard Task be built this construction cycle? /// </summary> bool CanBuild = CurrentPopulation.MineralRequirement(Task.minerialsCost, CurrentProgress); if (CanBuild == true && Task.CurrentTask != Constants.ShipyardInfo.Task.Scrap) { CurrentPopulation.HandleShipyardCost(Task.Cost, Task.minerialsCost, CurrentProgress); Task.Progress = Task.Progress + (decimal)CurrentProgress; } else if (Task.CurrentTask == Constants.ShipyardInfo.Task.Scrap) { /// <summary> /// Return money to the population from the scrap. /// </summary> CurrentPopulation.HandleShipyardCost(Task.Cost, Task.minerialsCost, (CurrentProgress * -1.0f)); Task.Progress = Task.Progress + (decimal)CurrentProgress; } else { String Entry = String.Format("Not enough minerals to finish task {0} at Shipyard {1} on Population {2}", Task.CurrentTask, CurrentPopulation.ShipyardTasks[Task], CurrentPopulation); MessageEntry NMsg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Position.System, CurrentPopulation, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); GameState.Instance.Factions[0].MessageLog.Add(NMsg); } /// <summary> /// handle standard task completion here. /// </summary> if (Task.Progress >= 1.0m) { TasksToRemove.Add(Task); switch (Task.CurrentTask) { case Constants.ShipyardInfo.Task.Construction: Task.AssignedTaskGroup.AddShip(Task.ConstructRefitTarget, Task.Title); CurrentPopulation.FuelStockpile = Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].Refuel(CurrentPopulation.FuelStockpile); break; case Constants.ShipyardInfo.Task.Repair: /// <summary> /// Set the Armor to fully repaired, set all components as not destroyed, and reduce the maintenance clock by a certain amount. /// </summary> #warning maintenance clock work should be performed here and in refit as well. Task.CurrentShip.ShipArmor.RepairAllArmor(); foreach (ComponentTN CurComp in Task.CurrentShip.ShipComponents) { CurComp.isDestroyed = false; } break; case Constants.ShipyardInfo.Task.Refit: /// <summary> /// need to remove the old ship, put in the new ship, copy over important information, adjust refueling,MSP,etc? /// </summary> /// <summary> /// Credit the population with the fuel and ordnance on the ship. the old ships MSP will be considered where the new ship got its MSP from. /// </summary> CurrentPopulation.FuelStockpile = CurrentPopulation.FuelStockpile + Task.CurrentShip.CurrentFuel; foreach (KeyValuePair <OrdnanceDefTN, int> OrdnancePair in Task.CurrentShip.ShipOrdnance) { CurrentPopulation.LoadMissileToStockpile(OrdnancePair.Key, (float)OrdnancePair.Value); } /// <summary> /// Destroy the ship. just use the existing code to remove the ship from the simulation, no point in reduplicating all of it. /// </summary> Task.CurrentShip.IsDestroyed = true; if (CurrentFaction.RechargeList.ContainsKey(Task.CurrentShip) == true) { if ((CurrentFaction.RechargeList[Task.CurrentShip] & (int)Faction.RechargeStatus.Destroyed) != (int)Faction.RechargeStatus.Destroyed) { CurrentFaction.RechargeList[Task.CurrentShip] = CurrentFaction.RechargeList[Task.CurrentShip] + (int)Faction.RechargeStatus.Destroyed; } } else { CurrentFaction.RechargeList.Add(Task.CurrentShip, (int)Faction.RechargeStatus.Destroyed); } /// <summary> /// Add in the "new" ship. /// </summary> Task.AssignedTaskGroup.AddShip(Task.ConstructRefitTarget, Task.CurrentShip.Name); Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].TFTraining = Task.CurrentShip.TFTraining; Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].ShipGrade = Task.CurrentShip.ShipGrade; CurrentPopulation.FuelStockpile = Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].Refuel(CurrentPopulation.FuelStockpile); break; case Constants.ShipyardInfo.Task.Scrap: /// <summary> /// All non-destroyed components from the ship need to be put into the population stockpile. /// This further includes fuel, MSP, and ordnance as well as eventually officers and crew. /// </summary> #warning Handle officers and crew on ship scrapping. BindingList <ComponentDefTN> CompDefList = Task.CurrentShip.ShipClass.ListOfComponentDefs; BindingList <short> CompDefCount = Task.CurrentShip.ShipClass.ListOfComponentDefsCount; BindingList <ComponentTN> ShipCompList = Task.CurrentShip.ShipComponents; BindingList <ushort> ComponentDefIndex = Task.CurrentShip.ComponentDefIndex; int DefCount = Task.CurrentShip.ShipClass.ListOfComponentDefs.Count; for (int CompDefIndex = 0; CompDefIndex < DefCount; CompDefIndex++) { ComponentDefTN CurrentCompDef = CompDefList[CompDefIndex]; short CurrentCompCount = CompDefCount[CompDefIndex]; int destCount = 0; for (int CompIndex = 0; CompIndex < CurrentCompCount; CompIndex++) { if (ShipCompList[ComponentDefIndex[CompDefIndex] + CompIndex].isDestroyed == true) { destCount++; } } if (destCount != CurrentCompCount) { CurrentPopulation.AddComponentsToStockpile(CurrentCompDef, (float)(CurrentCompCount - destCount)); } } CurrentPopulation.FuelStockpile = CurrentPopulation.FuelStockpile + Task.CurrentShip.CurrentFuel; CurrentPopulation.MaintenanceSupplies = CurrentPopulation.MaintenanceSupplies + Task.CurrentShip.CurrentMSP; foreach (KeyValuePair <OrdnanceDefTN, int> OrdnancePair in Task.CurrentShip.ShipOrdnance) { CurrentPopulation.LoadMissileToStockpile(OrdnancePair.Key, (float)OrdnancePair.Value); } /// <summary> /// Finally destroy the ship. just use the existing code to remove the ship from the simulation, no point in reduplicating all of it. /// </summary> Task.CurrentShip.IsDestroyed = true; if (CurrentFaction.RechargeList.ContainsKey(Task.CurrentShip) == true) { if ((CurrentFaction.RechargeList[Task.CurrentShip] & (int)Faction.RechargeStatus.Destroyed) != (int)Faction.RechargeStatus.Destroyed) { CurrentFaction.RechargeList[Task.CurrentShip] = CurrentFaction.RechargeList[Task.CurrentShip] + (int)Faction.RechargeStatus.Destroyed; } } else { CurrentFaction.RechargeList.Add(Task.CurrentShip, (int)Faction.RechargeStatus.Destroyed); } break; } } else { /// <summary> /// Update the timer since this project won't finish just yet. /// </summary> decimal CostLeft = Task.Cost * (1.0m - Task.Progress); float YearsOfProduction = (float)CostLeft / Task.ABR; DateTime EstTime = GameState.Instance.GameDateTime; if (YearsOfProduction < Constants.Colony.TimerYearMax) { float DaysInYear = (float)Constants.TimeInSeconds.RealYear / (float)Constants.TimeInSeconds.Day; int TimeToBuild = (int)Math.Floor(YearsOfProduction * DaysInYear); TimeSpan TS = new TimeSpan(TimeToBuild, 0, 0, 0); EstTime = EstTime.Add(TS); } Task.CompletionDate = EstTime; } } /// <summary> /// Remove all the tasks that are now completed. /// </summary> foreach (Installation.ShipyardInformation.ShipyardTask Task in TasksToRemove) { /// <summary> /// Sanity check here. /// </summary> if (Task.Progress >= 1.0m) { Installation.ShipyardInformation SYI = CurrentPopulation.ShipyardTasks[Task]; SYI.BuildingShips.Remove(Task); CurrentPopulation.ShipyardTasks.Remove(Task); } } TasksToRemove.Clear(); }
/// <summary> /// Do all of the tasks that this shipyard has assigned to it. /// </summary> /// <param name="CurrentFaction">Faction both the population and the shipyard belong to.</param> /// <param name="CurrentPopulation">Population the shipyard is on</param> /// <param name="SYInfo">Shipyard the tasks are happening at</param> private static void BuildShips(Faction CurrentFaction, Population CurrentPopulation, List<Installation.ShipyardInformation.ShipyardTask> SortedList) { BindingList<Installation.ShipyardInformation.ShipyardTask> TasksToRemove = new BindingList<Installation.ShipyardInformation.ShipyardTask>(); foreach(Installation.ShipyardInformation.ShipyardTask Task in SortedList) { if (Task.IsPaused() == true) continue; /// <summary> /// the Annual Build Rate(ABR) is the number of BP per year that will be devoted to this activity. this is the number of BP produced only this cycle. /// </summary> float CycleBuildRate = Task.ABR * Constants.Colony.ConstructionCycleFraction; /// <summary> /// How much of this task will be completed this construction cycle? /// </summary> float CurrentProgress = CycleBuildRate / (float)Task.Cost; if ((Task.Progress + (decimal)CurrentProgress) > 1.0m) { CurrentProgress = (float)(1.0m - Task.Progress); } /// <summary> /// Can this shipyard Task be built this construction cycle? /// </summary> bool CanBuild = CurrentPopulation.MineralRequirement(Task.minerialsCost, CurrentProgress); if (CanBuild == true && Task.CurrentTask != Constants.ShipyardInfo.Task.Scrap) { CurrentPopulation.HandleShipyardCost(Task.Cost, Task.minerialsCost, CurrentProgress); Task.Progress = Task.Progress + (decimal)CurrentProgress; } else if (Task.CurrentTask == Constants.ShipyardInfo.Task.Scrap) { /// <summary> /// Return money to the population from the scrap. /// </summary> CurrentPopulation.HandleShipyardCost(Task.Cost, Task.minerialsCost, (CurrentProgress * -1.0f)); Task.Progress = Task.Progress + (decimal)CurrentProgress; } else { String Entry = String.Format("Not enough minerals to finish task {0} at Shipyard {1} on Population {2}", Task.CurrentTask, CurrentPopulation.ShipyardTasks[Task], CurrentPopulation); MessageEntry NMsg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Position.System, CurrentPopulation, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); GameState.Instance.Factions[0].MessageLog.Add(NMsg); } /// <summary> /// handle standard task completion here. /// </summary> if (Task.Progress >= 1.0m) { TasksToRemove.Add(Task); switch (Task.CurrentTask) { case Constants.ShipyardInfo.Task.Construction: Task.AssignedTaskGroup.AddShip(Task.ConstructRefitTarget, Task.Title); CurrentPopulation.FuelStockpile = Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].Refuel(CurrentPopulation.FuelStockpile); break; case Constants.ShipyardInfo.Task.Repair: /// <summary> /// Set the Armor to fully repaired, set all components as not destroyed, and reduce the maintenance clock by a certain amount. /// </summary> #warning maintenance clock work should be performed here and in refit as well. Task.CurrentShip.ShipArmor.RepairAllArmor(); foreach (ComponentTN CurComp in Task.CurrentShip.ShipComponents) { CurComp.isDestroyed = false; } break; case Constants.ShipyardInfo.Task.Refit: /// <summary> /// need to remove the old ship, put in the new ship, copy over important information, adjust refueling,MSP,etc? /// </summary> /// <summary> /// Credit the population with the fuel and ordnance on the ship. the old ships MSP will be considered where the new ship got its MSP from. /// </summary> CurrentPopulation.FuelStockpile = CurrentPopulation.FuelStockpile + Task.CurrentShip.CurrentFuel; foreach (KeyValuePair<OrdnanceDefTN, int> OrdnancePair in Task.CurrentShip.ShipOrdnance) { CurrentPopulation.LoadMissileToStockpile(OrdnancePair.Key, (float)OrdnancePair.Value); } /// <summary> /// Destroy the ship. just use the existing code to remove the ship from the simulation, no point in reduplicating all of it. /// </summary> Task.CurrentShip.IsDestroyed = true; if (CurrentFaction.RechargeList.ContainsKey(Task.CurrentShip) == true) { if ((CurrentFaction.RechargeList[Task.CurrentShip] & (int)Faction.RechargeStatus.Destroyed) != (int)Faction.RechargeStatus.Destroyed) { CurrentFaction.RechargeList[Task.CurrentShip] = CurrentFaction.RechargeList[Task.CurrentShip] + (int)Faction.RechargeStatus.Destroyed; } } else { CurrentFaction.RechargeList.Add(Task.CurrentShip, (int)Faction.RechargeStatus.Destroyed); } /// <summary> /// Add in the "new" ship. /// </summary> Task.AssignedTaskGroup.AddShip(Task.ConstructRefitTarget,Task.CurrentShip.Name); Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].TFTraining = Task.CurrentShip.TFTraining; Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].ShipGrade = Task.CurrentShip.ShipGrade; CurrentPopulation.FuelStockpile = Task.AssignedTaskGroup.Ships[Task.AssignedTaskGroup.Ships.Count - 1].Refuel(CurrentPopulation.FuelStockpile); break; case Constants.ShipyardInfo.Task.Scrap: /// <summary> /// All non-destroyed components from the ship need to be put into the population stockpile. /// This further includes fuel, MSP, and ordnance as well as eventually officers and crew. /// </summary> #warning Handle officers and crew on ship scrapping. BindingList<ComponentDefTN> CompDefList = Task.CurrentShip.ShipClass.ListOfComponentDefs; BindingList<short> CompDefCount = Task.CurrentShip.ShipClass.ListOfComponentDefsCount; BindingList<ComponentTN> ShipCompList = Task.CurrentShip.ShipComponents; BindingList<ushort> ComponentDefIndex = Task.CurrentShip.ComponentDefIndex; int DefCount = Task.CurrentShip.ShipClass.ListOfComponentDefs.Count; for (int CompDefIndex = 0; CompDefIndex < DefCount; CompDefIndex++) { ComponentDefTN CurrentCompDef = CompDefList[CompDefIndex]; short CurrentCompCount = CompDefCount[CompDefIndex]; int destCount = 0; for (int CompIndex = 0; CompIndex < CurrentCompCount; CompIndex++) { if (ShipCompList[ComponentDefIndex[CompDefIndex] + CompIndex].isDestroyed == true) { destCount++; } } if (destCount != CurrentCompCount) { CurrentPopulation.AddComponentsToStockpile(CurrentCompDef, (float)(CurrentCompCount - destCount)); } } CurrentPopulation.FuelStockpile = CurrentPopulation.FuelStockpile + Task.CurrentShip.CurrentFuel; CurrentPopulation.MaintenanceSupplies = CurrentPopulation.MaintenanceSupplies + Task.CurrentShip.CurrentMSP; foreach (KeyValuePair<OrdnanceDefTN, int> OrdnancePair in Task.CurrentShip.ShipOrdnance) { CurrentPopulation.LoadMissileToStockpile(OrdnancePair.Key, (float)OrdnancePair.Value); } /// <summary> /// Finally destroy the ship. just use the existing code to remove the ship from the simulation, no point in reduplicating all of it. /// </summary> Task.CurrentShip.IsDestroyed = true; if (CurrentFaction.RechargeList.ContainsKey(Task.CurrentShip) == true) { if ((CurrentFaction.RechargeList[Task.CurrentShip] & (int)Faction.RechargeStatus.Destroyed) != (int)Faction.RechargeStatus.Destroyed) { CurrentFaction.RechargeList[Task.CurrentShip] = CurrentFaction.RechargeList[Task.CurrentShip] + (int)Faction.RechargeStatus.Destroyed; } } else { CurrentFaction.RechargeList.Add(Task.CurrentShip, (int)Faction.RechargeStatus.Destroyed); } break; } } else { /// <summary> /// Update the timer since this project won't finish just yet. /// </summary> decimal CostLeft = Task.Cost * (1.0m - Task.Progress); float YearsOfProduction = (float)CostLeft / Task.ABR; DateTime EstTime = GameState.Instance.GameDateTime; if (YearsOfProduction < Constants.Colony.TimerYearMax) { float DaysInYear = (float)Constants.TimeInSeconds.RealYear / (float)Constants.TimeInSeconds.Day; int TimeToBuild = (int)Math.Floor(YearsOfProduction * DaysInYear); TimeSpan TS = new TimeSpan(TimeToBuild, 0, 0, 0); EstTime = EstTime.Add(TS); } Task.CompletionDate = EstTime; } } /// <summary> /// Remove all the tasks that are now completed. /// </summary> foreach (Installation.ShipyardInformation.ShipyardTask Task in TasksToRemove) { /// <summary> /// Sanity check here. /// </summary> if (Task.Progress >= 1.0m) { Installation.ShipyardInformation SYI = CurrentPopulation.ShipyardTasks[Task]; SYI.BuildingShips.Remove(Task); CurrentPopulation.ShipyardTasks.Remove(Task); } } TasksToRemove.Clear(); }