public void AutoFixMechDef(MechDef mechDef, float originalTotalTonnage) { //Control.mod.Logger.LogDebug($"ArmActuatorHandler.AutoFixMechDef"); //Control.mod.Logger.LogDebug($" chassis={mechDef.Chassis.Description.Id}"); var builder = new MechDefBuilder(mechDef.Chassis, mechDef.Inventory.ToList()); UpgradeDef GetComponent(ArmActuator.TypeDef type) { switch (type) { case ArmActuator.TypeDef.Hand: return(mechDef.DataManager.UpgradeDefs.Get("emod_arm_hand")); case ArmActuator.TypeDef.Lower: return(mechDef.DataManager.UpgradeDefs.Get("emod_arm_lower")); case ArmActuator.TypeDef.Upper: return(mechDef.DataManager.UpgradeDefs.Get("emod_arm_upper")); default: return(null); } } void AddActuatorToArm(ChassisLocations location, ArmActuator.TypeDef limit) { if (mechDef.Inventory.Any(r => r.MountedLocation == location && r.Def.Is <ArmActuator>())) { return; } //Control.mod.Logger.LogDebug($" AddActuatorToArm"); //Control.mod.Logger.LogDebug($" location={location} limit={limit}"); foreach (var candidate in Enum.GetValues(typeof(ArmActuator.TypeDef)).Cast <ArmActuator.TypeDef>().Where(type => type >= limit)) { //Control.mod.Logger.LogDebug($" candidate={candidate}"); var component = GetComponent(candidate); if (candidate <= ArmActuator.TypeDef.Upper && builder.GetFreeSlots(location) < component.InventorySize) { continue; } //Control.mod.Logger.LogDebug($" add"); builder.Add(component, location); break; } } var limits = mechDef.Chassis.GetComponent <ArmActuatorSupport>() ?? new ArmActuatorSupport(); var beforeCount = builder.Inventory.Count; AddActuatorToArm(ChassisLocations.LeftArm, limits.LeftLimit); AddActuatorToArm(ChassisLocations.RightArm, limits.RightLimit); if (builder.Inventory.Count != beforeCount) { mechDef.SetInventory(builder.Inventory.ToArray()); } }
private static bool IsReorderable(MechComponentDef def) { if (!(def.ComponentType >= ComponentType.AmmunitionBox && def.ComponentType <= ComponentType.Upgrade)) { return(false); } if (MechDefBuilder.LocationCount(def.AllowedLocations) == 1) { return(false); } if (def.Is <Category>(out var category) && category.CategoryDescriptor.UniqueForLocation) { return(false); } return(true); }
public void AutoFixMechDef(MechDef mechDef, float originalTotalTonnage) { var builder = new MechDefBuilder(mechDef.Chassis, mechDef.Inventory.ToList()); // find any overused location if (!builder.HasOveruse()) { return; } // heatsinks, upgrades var itemsToBeReordered = mechDef.Inventory .Where(c => IsReorderable(c.Def)) .OrderBy(c => MechDefBuilder.LocationCount(c.Def.AllowedLocations)) .ThenByDescending(c => c.Def.InventorySize) .ThenByDescending(c => { switch (c.ComponentDefType) { case ComponentType.Upgrade: return(2); case ComponentType.AmmunitionBox: return(1); default: return(0); } }) .ToList(); // remove all items that can be reordered: heatsinks, upgrades foreach (var item in itemsToBeReordered) { builder.Remove(item); } // then add most restricting, and then largest items first (probably double head sinks) foreach (var item in itemsToBeReordered) { // couldn't add everything if (!builder.Add(item.Def)) { return; } } // if reorder does not work perfectly, ignore if (builder.HasOveruse()) { return; } // save mechDef.SetInventory(builder.Inventory.ToArray()); //Control.mod.Logger.LogDebug($"Name={mechDef.Name} ChassisID={mechDef.ChassisID}"); foreach (var item in mechDef.Inventory) { //Control.mod.Logger.LogDebug($" ComponentDefID={item.ComponentDefID} MountedLocation={item.MountedLocation}"); } }
public void AutoFixMechDef(MechDef mechDef, float originalTotalTonnage) { if (mechDef.Inventory.Any(c => c.Def.GetComponent <EngineCoreDef>() != null)) { return; } var inventory = new List <MechComponentRef>(mechDef.Inventory); var standardHeatSinkDef = mechDef.DataManager.GetDefaultEngineHeatSinkDef(); var engineHeatSinkDef = inventory .Select(r => r.Def.GetComponent <EngineHeatSink>()) .FirstOrDefault(d => d != null && d != standardHeatSinkDef) ?? standardHeatSinkDef; if (!Control.settings.AllowMixingHeatSinkTypes) { // remove incompatible heat sinks inventory.RemoveAll(r => r.Def.Is <EngineHeatSink>(out var engineHeatSink) && engineHeatSink.HSCategory != engineHeatSinkDef.HSCategory); } float freeTonnage; { float currentTotalTonnage = 0, maxValue = 0; MechStatisticsRules.CalculateTonnage(mechDef, ref currentTotalTonnage, ref maxValue); var originalInitialTonnage = ChassisHandler.GetOriginalTonnage(mechDef.Chassis); if (originalInitialTonnage.HasValue) // either use the freed up tonnage from the initial tonnage fix { freeTonnage = originalInitialTonnage.Value - mechDef.Chassis.InitialTonnage; freeTonnage -= currentTotalTonnage - originalTotalTonnage; } else // or use up available total tonnage { freeTonnage = mechDef.Chassis.Tonnage - currentTotalTonnage; } } //Control.mod.Logger.LogDebug("C maxEngineTonnage=" + maxEngineTonnage); var standardWeights = new Weights(); // use default gyro and weights var stanardEngineType = mechDef.DataManager.HeatSinkDefs.Get(Control.settings.AutoFixMechDefEngineTypeDef); var engineCoreDefs = mechDef.DataManager.HeatSinkDefs .Select(hs => hs.Value) .Select(hs => hs.GetComponent <EngineCoreDef>()) .Where(c => c != null) .OrderByDescending(x => x.Rating); var maxEngine = engineCoreDefs .Select(coreDef => new EngineCoreRef(engineHeatSinkDef, coreDef)) .Select(coreRef => new Engine(coreRef, standardWeights, Enumerable.Empty <MechComponentRef>())) .FirstOrDefault(engine => !(engine.TotalTonnage > freeTonnage)); if (maxEngine == null) { return; } // Control.mod.Logger.LogDebug("D maxEngine=" + maxEngine.CoreDef); { // remove superfluous jump jets var maxJetCount = maxEngine.CoreDef.GetMovement(mechDef.Chassis.Tonnage).JumpJetCount; var jumpJetList = inventory.Where(x => x.ComponentDefType == ComponentType.JumpJet).ToList(); for (var i = 0; i < jumpJetList.Count - maxJetCount; i++) { inventory.Remove(jumpJetList[i]); } } var builder = new MechDefBuilder(mechDef.Chassis, inventory); // add engine builder.Add( maxEngine.CoreDef.Def, ChassisLocations.CenterTorso, engineHeatSinkDef != standardHeatSinkDef ? "/ihstype=" + engineHeatSinkDef.Def.Description.Id : null ); // add standard shielding builder.Add(stanardEngineType, ChassisLocations.CenterTorso); // add free heatsinks { var count = 0; while (count < maxEngine.CoreDef.MaxFreeExternalHeatSinks) { if (builder.Add(engineHeatSinkDef.Def)) { count++; } else { break; } } } mechDef.SetInventory(inventory.ToArray()); }
public void AutoFixMechDef(MechDef mechDef, float originalTotalTonnage) { if (mechDef.Inventory.Any(c => c.Def.GetComponent <EngineCoreDef>() != null)) { return; } float freeTonnage; { float currentTotalTonnage = 0, maxValue = 0; MechStatisticsRules.CalculateTonnage(mechDef, ref currentTotalTonnage, ref maxValue); var originalInitialTonnage = ChassisHandler.GetOriginalTonnage(mechDef.Chassis); if (originalInitialTonnage.HasValue) // either use the freed up tonnage from the initial tonnage fix { freeTonnage = originalInitialTonnage.Value - mechDef.Chassis.InitialTonnage; freeTonnage -= currentTotalTonnage - originalTotalTonnage; } else // or use up available total tonnage { freeTonnage = mechDef.Chassis.Tonnage - currentTotalTonnage; } } var maxEngine = (Engine)null; //Control.mod.Logger.LogDebug("C maxEngineTonnage=" + maxEngineTonnage); var standardEngineType = mechDef.DataManager.HeatSinkDefs.Get(Control.settings.AutoFixMechDefEngineTypeDef).GetComponent <EngineType>(); var standardHeatSinkDef = mechDef.DataManager.GetDefaultEngineHeatSinkDef(); var engineHeatSinkdef = mechDef.Inventory .Select(r => r.Def.GetComponent <EngineHeatSink>()) .FirstOrDefault(d => d != null && d != standardHeatSinkDef) ?? standardHeatSinkDef; foreach (var keyvalue in mechDef.DataManager.HeatSinkDefs) { var heatSinkDef = keyvalue.Value; var coreDef = heatSinkDef.GetComponent <EngineCoreDef>(); if (coreDef == null) { continue; } var coreRef = new EngineCoreRef(engineHeatSinkdef, coreDef); var engine = new Engine(coreRef, standardEngineType, Enumerable.Empty <MechComponentRef>()); if (engine.TotalTonnage > freeTonnage) { continue; } if (maxEngine != null && maxEngine.CoreDef.Rating >= coreDef.Rating) { continue; } maxEngine = engine; } if (maxEngine == null) { return; } // Control.mod.Logger.LogDebug("D maxEngine=" + maxEngine.CoreDef); var componentRefs = new List <MechComponentRef>(mechDef.Inventory); { // remove superfluous jump jets var maxJetCount = maxEngine.CoreDef.GetMovement(mechDef.Chassis.Tonnage).JumpJetCount; var jumpJetList = componentRefs.Where(x => x.ComponentDefType == ComponentType.JumpJet).ToList(); for (var i = 0; i < jumpJetList.Count - maxJetCount; i++) { componentRefs.Remove(jumpJetList[i]); } } var builder = new MechDefBuilder(mechDef.Chassis, componentRefs); // add engine builder.Add( maxEngine.CoreDef.Def, ChassisLocations.CenterTorso, engineHeatSinkdef != standardHeatSinkDef ? "/ihstype=" + engineHeatSinkdef.Def.Description.Id : null ); // add standard shielding builder.Add(standardEngineType.Def, ChassisLocations.CenterTorso); // add free heatsinks { var count = 0; while (count < maxEngine.CoreDef.MaxFreeExternalHeatSinks) { if (builder.Add(engineHeatSinkdef.Def)) { count++; } else { break; } } } mechDef.SetInventory(componentRefs.ToArray()); }