예제 #1
0
        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}");
            }
        }
예제 #4
0
        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());
        }
예제 #5
0
        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());
        }