public static float GetMechArmor(this MechDef m)
        {
            float r = 0;

            foreach (ChassisLocations l in Locations)
            {
                LocationLoadoutDef v = m.GetLocationLoadoutDef(l);
                r += v.AssignedArmor;
            }
            foreach (ChassisLocations l in RearArmoredLocs)
            {
                LocationLoadoutDef v = m.GetLocationLoadoutDef(l);
                r += v.AssignedRearArmor;
            }
            return(r);
        }
Example #2
0
        // Evaluates whether a given mech needs any structure repaired
        public static bool CheckStructureDamage(MechDef mech)
        {
            // Default to not requesting any structure repair
            bool mechNeedsRepair = false;

            // Using the repair priority for loop here as it is faster and simpler than foreach'ing over ChassisLocations and filtering out ones that don't have armor
            for (int index = 0; index < Globals.repairPriorities.Count; index++)
            {
                // Set current ChassisLocation
                ChassisLocations thisLoc = Globals.repairPriorities.ElementAt(index).Value;
                // Get current mech location loadout from the looped chassis definitions
                LocationLoadoutDef thisLocLoadout = mech.GetLocationLoadoutDef(thisLoc);
                // Friendly name for this location
                string thisLocName = thisLoc.ToString();

                // Work out difference of armor lost for each location - default to 0
                int   structureDifference = 0;
                float currentStructure    = thisLocLoadout.CurrentInternalStructure;
                float definedStructure    = mech.GetChassisLocationDef(thisLoc).InternalStructure;
                structureDifference = (int)Mathf.Abs(currentStructure - definedStructure);

                // If any difference betwen the location's current and assigned armor is detected, flag this mech for armor repair
                if (structureDifference > 0)
                {
                    Logger.LogDebug(mech.Name + " requires structure repair based on damage to: " + thisLocName);
                    mechNeedsRepair = true;
                    break; // Stop evaluating other locations once a repair requirement is determined
                }
            }

            return(mechNeedsRepair);
        }
        private static bool ProcessMechArmorStructureRatioForLocation(
            MechDef mechDef,
            ChassisLocations location,
            Dictionary <MechValidationType, List <Text> > errorMessages = null,
            bool applyChanges = false)
        {
            var mechLocationDef    = mechDef.GetLocationLoadoutDef(location);
            var chassisLocationDef = mechDef.Chassis.GetLocationDef(location);

            var armor     = Mathf.Max(mechLocationDef.AssignedArmor, 0);
            var armorRear = Mathf.Max(mechLocationDef.AssignedRearArmor, 0);

            var structure = chassisLocationDef.InternalStructure;

            var ratio = location == ChassisLocations.Head ? 3 : 2;

            var total    = armor + armorRear;
            var totalMax = ratio * structure;

            if (total <= totalMax)
            {
                return(true);
            }

            if (applyChanges)
            {
//                Control.mod.Logger.LogDebug($"structure={structure} location={location} totalMax={totalMax}");
//                Control.mod.Logger.LogDebug($"before AssignedArmor={mechLocationDef.AssignedArmor} AssignedRearArmor={mechLocationDef.AssignedRearArmor}");

                if ((location & ChassisLocations.Torso) != 0)
                {
                    mechLocationDef.AssignedArmor     = PrecisionUtils.RoundUp((totalMax * 2 / 3), 5);
                    mechLocationDef.CurrentArmor      = mechLocationDef.AssignedArmor;
                    mechLocationDef.AssignedRearArmor = PrecisionUtils.RoundDown((totalMax * 1 / 3), 5);
                    mechLocationDef.CurrentRearArmor  = mechLocationDef.AssignedRearArmor;
                }
                else
                {
                    mechLocationDef.AssignedArmor = totalMax;
                    mechLocationDef.CurrentArmor  = mechLocationDef.AssignedArmor;
                }

                Control.mod.Logger.LogDebug($"set AssignedArmor={mechLocationDef.AssignedArmor} AssignedRearArmor={mechLocationDef.AssignedRearArmor} on location={location}");
            }

            //Control.mod.Logger.LogDebug($"{Mech.GetAbbreviatedChassisLocation(location)} armor={armor} armorRear={armorRear} structure={structure}");

            if (errorMessages != null)
            {
                var locationName = Mech.GetLongChassisLocation(location);
                errorMessages[MechValidationType.InvalidHardpoints].Add(new Text($"ARMOR {locationName}: Armor can only be {ratio} times more than structure."));
            }

            return(false);
        }
Example #4
0
        // Evaluates whether a given mech needs any armor repaired
        public static bool CheckArmorDamage(MechDef mech)
        {
            // Default to not requesting any armor repair
            bool mechNeedsArmor = false;

            // Using the repair priority for loop here as it is faster and simpler than foreach'ing over ChassisLocations and filtering out ones that don't have armor
            for (int index = 0; index < Globals.repairPriorities.Count; index++)
            {
                // Set current ChassisLocation
                ChassisLocations thisLoc = Globals.repairPriorities.ElementAt(index).Value;
                // Get current mech location loadout from the looped chassis definitions
                LocationLoadoutDef thisLocLoadout = mech.GetLocationLoadoutDef(thisLoc);
                // Friendly name for this location
                string thisLocName = thisLoc.ToString();

                // Work out difference of armor lost for each location - default to 0
                int armorDifference = 0;

                // Consider rear armour in difference calculation if this is a RT, CT or LT
                if (thisLocLoadout == mech.CenterTorso || thisLocLoadout == mech.RightTorso || thisLocLoadout == mech.LeftTorso)
                {
                    armorDifference = (int)Mathf.Abs(thisLocLoadout.CurrentArmor - thisLocLoadout.AssignedArmor) + (int)Mathf.Abs(thisLocLoadout.CurrentRearArmor - thisLocLoadout.AssignedRearArmor);
                }
                else
                {
                    armorDifference = (int)Mathf.Abs(thisLocLoadout.CurrentArmor - thisLocLoadout.AssignedArmor);
                }

                // If any difference betwen the location's current and assigned armor is detected, flag this mech for armor repair
                if (armorDifference > 0)
                {
                    Logger.LogDebug(mech.Name + " requires armor repair based on armor loss from: " + thisLocName);
                    mechNeedsArmor = true;
                    break; // Stop evaluating other locations once a repair requirement is determined on any location (no point checking further)
                }
            }

            if (!mechNeedsArmor)
            {
                Logger.LogInfo(mech.Name + " does not require armor repairs.");
            }

            return(mechNeedsArmor);
        }
 private static bool IsStructureDamaged(ref float percent, Mech mech, MechDef mechDef, ChassisLocations location)
 {
     if (float.IsNaN(percent))
     {
         float hp, maxHp;
         if (mech != null)
         {
             hp    = mech.GetCurrentStructure(location);
             maxHp = mech.GetMaxStructure(location);
         }
         else // if ( mechDef != null )
         {
             hp    = mechDef.GetLocationLoadoutDef(location).CurrentInternalStructure;
             maxHp = mechDef.GetChassisLocationDef(location).InternalStructure;
         }
         percent = hp / maxHp;
     }
     return(percent < 1f);
 }
        public static bool Prefix(SimGameState __instance, WorkOrderEntry_RepairMechStructure order)
        {
            if (order.IsMechLabComplete)
            {
                return(true);
            }
            else
            {
                MechDef            mechByID           = __instance.GetMechByID(order.MechLabParent.MechID);
                LocationLoadoutDef locationLoadoutDef = mechByID.GetLocationLoadoutDef(order.Location);
                locationLoadoutDef.CurrentInternalStructure = mechByID.GetChassisLocationDef(order.Location).InternalStructure;
                // Original method resets currentArmor to assignedArmor here for some reason! Removed them from this override
                Logger.LogDebug("ALERT: Intercepted armor reset from ML_RepairMech and prevented it.");
                mechByID.RefreshBattleValue();
                order.SetMechLabComplete(true);

                return(false); // Prevent original method from firing
            }
        }
Example #7
0
        static bool Prefix(Contract __instance, List <UnitResult> enemyMechs, List <VehicleDef> enemyVehicles, List <UnitResult> lostUnits, bool logResults = false)
        {
            try {
                Settings settings = Helper.LoadSettings();
                if (__instance.BattleTechGame.Simulation == null)
                {
                    return(false);
                }
                ReflectionHelper.SetPrivateField(__instance, "finalPotentialSalvage", new List <SalvageDef>());
                ReflectionHelper.InvokePrivateMethode(__instance, "set_SalvagedChassis", new object[] { new List <SalvageDef>() });
                ReflectionHelper.InvokePrivateMethode(__instance, "set_LostMechs", new object[] { new List <MechDef>() });
                ReflectionHelper.InvokePrivateMethode(__instance, "set_SalvageResults", new object[] { new List <SalvageDef>() });
                SimGameState     simulation = __instance.BattleTechGame.Simulation;
                SimGameConstants constants  = simulation.Constants;
                for (int i = 0; i < lostUnits.Count; i++)
                {
                    MechDef mech  = lostUnits[i].mech;
                    Pilot   pilot = lostUnits[i].pilot;
                    float   num   = simulation.NetworkRandom.Float(0f, 1f);
                    float   ejectRecoveryBonus         = 0;
                    float   incapacitatedRecoveryBonus = 0;
                    bool    notDestroyed = !mech.IsLocationDestroyed(ChassisLocations.CenterTorso) && !mech.IsLocationDestroyed(ChassisLocations.Head) &&
                                           (!mech.IsLocationDestroyed(ChassisLocations.LeftLeg) && !mech.IsLocationDestroyed(ChassisLocations.RightLeg));
                    if (pilot.HasEjected)
                    {
                        ejectRecoveryBonus = settings.ejectRecoveryBonus;
                    }
                    else if (mech.IsLocationDestroyed(ChassisLocations.Head) || (pilot.IsIncapacitated && notDestroyed))
                    {
                        incapacitatedRecoveryBonus = settings.incapacitatedRecoveryBonus;
                    }
                    bool flag = num <= constants.Salvage.DestroyedMechRecoveryChance + ejectRecoveryBonus + incapacitatedRecoveryBonus;

                    // keep mech if the roll is good enough, or if CT + head + legs are intact and the pilot isn't incapacitated
                    if (flag || (notDestroyed && !pilot.IsIncapacitated))
                    {
                        lostUnits[i].mechLost = false;
                    }
                    else
                    {
                        lostUnits[i].mechLost = true;

                        float mechparts = simulation.Constants.Story.DefaultMechPartMax;
                        if (mech.IsLocationDestroyed(ChassisLocations.CenterTorso))
                        {
                            mechparts = settings.centerTorsoSalvageValue;
                        }
                        else
                        {
                            if (mech.IsLocationDestroyed(ChassisLocations.LeftArm))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                            if (mech.IsLocationDestroyed(ChassisLocations.RightArm))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                            if (mech.IsLocationDestroyed(ChassisLocations.LeftLeg))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                            if (mech.IsLocationDestroyed(ChassisLocations.RightLeg))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                        }


                        SalvageDef def = (SalvageDef)ReflectionHelper.InvokePrivateMethode(__instance, "CreateMechPart", new object[] { constants, mech });
                        if (settings.ownMechsForFree)
                        {
                            for (int s = 0; s < Mathf.RoundToInt(mechparts); s++)
                            {
                                __instance.SalvageResults.Add(def);
                            }
                        }
                        else
                        {
                            List <SalvageDef> finalPotentialSalvage = (List <SalvageDef>)ReflectionHelper.GetPrivateField(__instance, "finalPotentialSalvage");
                            ReflectionHelper.InvokePrivateMethode(__instance, "CreateAndAddMechPart", new object[] { constants, mech, Mathf.RoundToInt(mechparts), finalPotentialSalvage });
                        }
                        if (settings.ownMechsForFree)
                        {
                            foreach (MechComponentRef mechComponentRef in mech.Inventory)
                            {
                                if (!mech.IsLocationDestroyed(mechComponentRef.MountedLocation) && mechComponentRef.DamageLevel != ComponentDamageLevel.Destroyed)
                                {
                                    ReflectionHelper.InvokePrivateMethode(__instance, "AddToFinalSalvage", new object[] { new SalvageDef {
                                                                                                                              MechComponentDef = mechComponentRef.Def,
                                                                                                                              Description      = new DescriptionDef(mechComponentRef.Def.Description),
                                                                                                                              RewardID         = __instance.GenerateRewardUID(),
                                                                                                                              Type             = SalvageDef.SalvageType.COMPONENT,
                                                                                                                              ComponentType    = mechComponentRef.Def.ComponentType,
                                                                                                                              Damaged          = false,
                                                                                                                              Count            = 1
                                                                                                                          } });
                                }
                            }
                        }
                        else
                        {
                            foreach (MechComponentRef mechComponentRef in mech.Inventory)
                            {
                                if (!mech.IsLocationDestroyed(mechComponentRef.MountedLocation) && mechComponentRef.DamageLevel != ComponentDamageLevel.Destroyed)
                                {
                                    List <SalvageDef> finalPotentialSalvage = (List <SalvageDef>)ReflectionHelper.GetPrivateField(__instance, "finalPotentialSalvage");
                                    ReflectionHelper.InvokePrivateMethode(__instance, "AddMechComponentToSalvage", new object[] { finalPotentialSalvage, mechComponentRef.Def, ComponentDamageLevel.Functional, false, constants, simulation.NetworkRandom, true });
                                }
                            }
                        }
                    }
                }
                int k = 0;
                while (k < enemyMechs.Count)
                {
                    MechDef           mech2                 = enemyMechs[k].mech;
                    Pilot             pilot                 = enemyMechs[k].pilot;
                    SalvageDef        salvageDef            = null;
                    bool              flag2                 = false;
                    bool              flag3                 = false;
                    List <SalvageDef> finalPotentialSalvage = (List <SalvageDef>)ReflectionHelper.GetPrivateField(__instance, "finalPotentialSalvage");

                    if (pilot.IsIncapacitated || mech2.IsDestroyed || mech2.Inventory.Any(cref => cref.Def != null && cref.Def.CriticalComponent && cref.DamageLevel == ComponentDamageLevel.Destroyed))
                    {
                        float mechparts = simulation.Constants.Story.DefaultMechPartMax;
                        if (mech2.IsLocationDestroyed(ChassisLocations.CenterTorso))
                        {
                            mechparts = settings.centerTorsoSalvageValue;
                        }
                        else
                        {
                            if (mech2.IsLocationDestroyed(ChassisLocations.LeftArm))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                            if (mech2.IsLocationDestroyed(ChassisLocations.RightArm))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                            if (mech2.IsLocationDestroyed(ChassisLocations.LeftLeg))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                            if (mech2.IsLocationDestroyed(ChassisLocations.RightLeg))
                            {
                                mechparts -= (simulation.Constants.Story.DefaultMechPartMax / 5);
                            }
                        }

                        ReflectionHelper.InvokePrivateMethode(__instance, "CreateAndAddMechPart", new object[] { constants, mech2, Mathf.RoundToInt(mechparts), finalPotentialSalvage });
                        goto IL_2E4;
                    }
IL_4AB:
                    k++;
                    continue;
IL_2E4:
                    foreach (MechComponentRef mechComponentRef2 in mech2.Inventory)
                    {
                        if (!mech2.IsLocationDestroyed(mechComponentRef2.MountedLocation) && mechComponentRef2.DamageLevel != ComponentDamageLevel.Destroyed)
                        {
                            ReflectionHelper.InvokePrivateMethode(__instance, "AddMechComponentToSalvage", new object[] { finalPotentialSalvage, mechComponentRef2.Def, ComponentDamageLevel.Functional, false, constants, simulation.NetworkRandom, true });
                        }
                    }
                    if (flag3)
                    {
                        salvageDef             = new SalvageDef();
                        salvageDef.Type        = SalvageDef.SalvageType.CHASSIS;
                        salvageDef.Description = new DescriptionDef(mech2.Chassis.Description);
                        salvageDef.Count       = 1;
                        IEnumerator enumerator = Enum.GetValues(typeof(ChassisLocations)).GetEnumerator();
                        try {
                            while (enumerator.MoveNext())
                            {
                                object           obj = enumerator.Current;
                                ChassisLocations chassisLocations = (ChassisLocations)obj;
                                if (chassisLocations != ChassisLocations.None && chassisLocations != ChassisLocations.All && chassisLocations != ChassisLocations.Arms && chassisLocations != ChassisLocations.Legs && chassisLocations != ChassisLocations.Torso && chassisLocations != ChassisLocations.MainBody)
                                {
                                    salvageDef.ChassisLocations.Add(chassisLocations);
                                    salvageDef.ChassisStructure.Add(mech2.GetLocationLoadoutDef(chassisLocations).CurrentInternalStructure);
                                }
                            }
                        }
                        finally {
                            IDisposable disposable;
                            if ((disposable = (enumerator as IDisposable)) != null)
                            {
                                disposable.Dispose();
                            }
                        }
                        if (flag2)
                        {
                            for (int m = 0; m < salvageDef.ChassisLocations.Count; m++)
                            {
                                List <float> chassisStructure;
                                int          index;
                                (chassisStructure = salvageDef.ChassisStructure)[index = m] = chassisStructure[index] / 2f;
                            }
                        }
                        salvageDef.Weight = constants.Salvage.DefaultChassisWeight;
                        __instance.SalvagedChassis.Add(salvageDef);
                        goto IL_4AB;
                    }
                    goto IL_4AB;
                }
                for (int n = 0; n < enemyVehicles.Count; n++)
                {
                    VehicleDef        vehicleDef            = enemyVehicles[n];
                    List <SalvageDef> finalPotentialSalvage = (List <SalvageDef>)ReflectionHelper.GetPrivateField(__instance, "finalPotentialSalvage");
                    foreach (VehicleComponentRef vehicleComponentRef in vehicleDef.Inventory)
                    {
                        ReflectionHelper.InvokePrivateMethode(__instance, "AddMechComponentToSalvage", new object[] { finalPotentialSalvage, vehicleComponentRef.Def, ComponentDamageLevel.Functional, false, constants, simulation.NetworkRandom, true });
                    }
                }
                int   num2 = __instance.SalvagePotential;
                float num3 = constants.Salvage.VictorySalvageChance;
                float num4 = constants.Salvage.VictorySalvageLostPerMechDestroyed;
                if (__instance.State == Contract.ContractState.Failed)
                {
                    num3 = constants.Salvage.DefeatSalvageChance;
                    num4 = constants.Salvage.DefeatSalvageLostPerMechDestroyed;
                }
                else if (__instance.State == Contract.ContractState.Retreated)
                {
                    num3 = constants.Salvage.RetreatSalvageChance;
                    num4 = constants.Salvage.RetreatSalvageLostPerMechDestroyed;
                }
                float num5 = num3;
                float num6 = (float)num2 * __instance.PercentageContractSalvage;
                if (num2 > 0)
                {
                    num6 += (float)constants.Finances.ContractFloorSalvageBonus;
                }
                num3 = Mathf.Max(0f, num5 - num4 * (float)lostUnits.Count);
                int num7 = Mathf.FloorToInt(num6 * num3);
                if (num2 > 0)
                {
                    num2 += constants.Finances.ContractFloorSalvageBonus;
                }
                ReflectionHelper.InvokePrivateMethode(__instance, "set_FinalSalvageCount", new object[] { num7 });
                ReflectionHelper.InvokePrivateMethode(__instance, "set_FinalPrioritySalvageCount", new object[] { Mathf.FloorToInt((float)num7 * constants.Salvage.PrioritySalvageModifier) });

                return(false);
            }
            catch (Exception e) {
                Logger.LogError(e);
                return(false);
            }
        }
        public static void ApplyLoadout(this MechLabPanel mechLabPanel, string mechDefId)
        {
            try
            {
                // Check first
                if (!mechLabPanel.Sim.DataManager.Exists(BattleTechResourceType.MechDef, mechDefId))
                {
                    GenericPopupBuilder
                    .Create("Apply Loadout failed", "The requested MechDef " + mechDefId + " was not found")
                    .AddButton("Confirm", null, true, null)
                    .AddFader(new UIColorRef?(LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.PopupBackfill), 0f, true)
                    .SetAlwaysOnTop()
                    .SetOnClose(delegate
                    {
                        // Nothing
                    })
                    .Render();

                    // Abort!
                    return;
                }
                MechDef activeMechDef    = mechLabPanel.activeMechDef;
                MechDef requestedMechDef = new MechDef(mechLabPanel.Sim.DataManager.MechDefs.Get(mechDefId), null, true);

                // Check second
                List <string> errorDescriptions = new List <string>();
                if (!mechLabPanel.CanApplyLoadout(requestedMechDef, out errorDescriptions))
                {
                    string popupTitle = "Apply Loadout failed";
                    //string popupBody = "The following problems were encountered:" + Environment.NewLine;
                    string popupBody = "";

                    foreach (string errorDescription in errorDescriptions)
                    {
                        popupBody += errorDescription + Environment.NewLine;
                    }

                    GenericPopupBuilder
                    .Create(popupTitle, popupBody)
                    .AddButton("Confirm", null, true, null)
                    .AddFader(new UIColorRef?(LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.PopupBackfill), 0f, true)
                    .SetAlwaysOnTop()
                    .SetOnClose(delegate
                    {
                        // Nothing
                    })
                    .Render();

                    // Abort!
                    return;
                }
                // Checks done



                // Hard cleanup upfront
                mechLabPanel.OnRevertMech();

                // Get data
                MechLabInventoryWidget inventoryWidget = (MechLabInventoryWidget)AccessTools.Field(typeof(MechLabPanel), "inventoryWidget").GetValue(mechLabPanel);
                MechLabDismountWidget  dismountWidget  = (MechLabDismountWidget)AccessTools.Field(typeof(MechLabPanel), "dismountWidget").GetValue(mechLabPanel);
                MechLabMechInfoWidget  mechInfoWidget  = (MechLabMechInfoWidget)AccessTools.Field(typeof(MechLabPanel), "mechInfoWidget").GetValue(mechLabPanel);
                HBS_InputField         mechNickname    = (HBS_InputField)AccessTools.Field(typeof(MechLabMechInfoWidget), "mechNickname").GetValue(mechInfoWidget);

                List <MechComponentRef> dropshipInventory            = mechLabPanel.Sim.GetAllInventoryItemDefs();
                List <MechComponentRef> storageInventory             = mechLabPanel.storageInventory;
                List <MechComponentRef> activeMechInventory          = mechLabPanel.activeMechInventory;
                MechComponentRef[]      requestedMechComponentsArray = (MechComponentRef[])AccessTools.Field(typeof(MechDef), "inventory").GetValue(requestedMechDef);
                List <MechComponentRef> requestedMechComponents      = requestedMechComponentsArray.ToList();

                // Remove fixed equipment as it will be ignored from dismounting et all
                for (int i = requestedMechComponents.Count - 1; i >= 0; i--)
                {
                    if (requestedMechComponents[i].IsFixed)
                    {
                        Logger.Debug("[Extensions.ResetToStock] FOUND AND WILL REMOVE FIXED EQUIPMENT: " + requestedMechComponents[i].ComponentDefID);
                        requestedMechComponents.RemoveAt(i);
                    }
                }

                // This puts the current equipment into dismountWidget and also clears the Mechs inventory
                // NOTE that fixed equipment will stay where it is -> must be removed from requestedComponents manually!
                mechLabPanel.OnStripEquipment();

                // Collect items from dismountWidget and/or inventoryWidget
                List <MechComponentRef> requestedMechComponentsRequired = requestedMechComponents.ToList();

                //List<MechLabItemSlotElement> activeMechDismountedItems = new List<MechLabItemSlotElement>(dismountWidget.localInventory);
                List <MechLabItemSlotElement> activeMechDismountedItems = dismountWidget.localInventory;

                //List<InventoryItemElement_NotListView> localInventoryItems = new List<InventoryItemElement_NotListView>(inventoryWidget.localInventory);
                List <InventoryItemElement_NotListView> localInventoryItems = inventoryWidget.localInventory;

                List <MechLabItemSlotElement>           itemsCollectedFromDismount  = new List <MechLabItemSlotElement>();
                List <InventoryItemElement_NotListView> itemsCollectedFromInventory = new List <InventoryItemElement_NotListView>();

                // CHECK
                foreach (MechComponentRef comp in requestedMechComponentsRequired)
                {
                    Logger.Debug("[Extensions.ResetToStock] INIT requestedMechComponentsRequired: " + comp.ComponentDefID);
                }



                // Check for required items in dismountWidget first, remove/add from/to applicable Lists
                // @ToDo: Put in method
                for (int i = requestedMechComponentsRequired.Count - 1; i >= 0; i--)
                {
                    bool found = false;
                    for (int j = activeMechDismountedItems.Count - 1; j >= 0; j--)
                    {
                        if (requestedMechComponentsRequired[i].ComponentDefID == activeMechDismountedItems[j].ComponentRef.ComponentDefID)
                        {
                            Logger.Debug("[Extensions.ResetToStock] FOUND in activeMechDismountedItems: " + requestedMechComponentsRequired[i].ComponentDefID);
                            found = true;
                            requestedMechComponentsRequired.RemoveAt(i);
                            itemsCollectedFromDismount.Add(activeMechDismountedItems[j]);

                            // Remove visually
                            // Do not forget to refresh the widget
                            MechLabItemSlotElement mechLabItemSlotElement = activeMechDismountedItems[j];
                            mechLabItemSlotElement.gameObject.transform.SetParent(null, false);
                            mechLabPanel.dataManager.PoolGameObject(MechLabPanel.MECHCOMPONENT_ITEM_PREFAB, mechLabItemSlotElement.gameObject);

                            // Remove data AFTERWARDS too
                            activeMechDismountedItems.RemoveAt(j);

                            break;
                        }
                    }
                    if (!found)
                    {
                        Logger.Debug("[Extensions.ResetToStock] NOT FOUND in activeMechDismountedItems: " + requestedMechComponentsRequired[i].ComponentDefID);
                    }
                }
                // Refresh UI
                ReflectionHelper.InvokePrivateMethode(dismountWidget, "RefreshComponentCountText", null);



                // CHECK
                foreach (MechLabItemSlotElement item in itemsCollectedFromDismount)
                {
                    Logger.Debug("[Extensions.ResetToStock] itemsCollectedFromDismount: " + item.ComponentRef.ComponentDefID + ", MountedLocation: " + item.MountedLocation + ", DropParent: " + item.DropParent);
                }



                // Check for REMAINING required items in inventoryWidget, remove/add from/to applicable Lists
                // NEEDS conversion of remaining components to inventory items via custom type
                List <InventoryItemElement_Simple> requestedMechItemsRequired = Utilities.ComponentsToInventoryItems(requestedMechComponentsRequired, true);
                List <InventoryItemElement_Simple> missingItems = new List <InventoryItemElement_Simple>();
                bool itemsAvailableInInventory = mechLabPanel.ItemsAvailableInInventory(requestedMechItemsRequired, localInventoryItems, out missingItems);
                Logger.Debug("[Extensions.ResetToStock] itemsAvailableInInventory: " + itemsAvailableInInventory);

                if (itemsAvailableInInventory)
                {
                    itemsCollectedFromInventory = mechLabPanel.PullItemsFromInventory(requestedMechItemsRequired, localInventoryItems);
                    // Clear required components list
                    requestedMechComponentsRequired.Clear();
                }
                else
                {
                    // Hard exit, SHOULD NEVER END UP HERE!
                    Logger.Debug("[Extensions.ResetToStock] MISSING ITEMS. ABORTING. YOU SHOULD NEVER SEE THIS!");
                    mechLabPanel.OnRevertMech();
                    return;
                }

                // CHECK
                foreach (InventoryItemElement_NotListView item in itemsCollectedFromInventory)
                {
                    Logger.Debug("[Extensions.ResetToStock] itemsCollectedFromInventory: " + item.ComponentRef.ComponentDefID + ", MountedLocation: " + item.MountedLocation + ", DropParent: " + item.DropParent);
                }



                // At this point inventoryWidget.localInventory AND dismountWidget.localInventory already have the potentially reusable components REMOVED
                // So, in "SetEquipment" they must be SPAWNED otherwise they are lost forever



                // Helper Dictionary
                Dictionary <ChassisLocations, MechLabLocationWidget> LocationHandler = new Dictionary <ChassisLocations, MechLabLocationWidget>();
                LocationHandler.Add(ChassisLocations.Head, mechLabPanel.headWidget);
                LocationHandler.Add(ChassisLocations.CenterTorso, mechLabPanel.centerTorsoWidget);
                LocationHandler.Add(ChassisLocations.LeftTorso, mechLabPanel.leftTorsoWidget);
                LocationHandler.Add(ChassisLocations.RightTorso, mechLabPanel.rightTorsoWidget);
                LocationHandler.Add(ChassisLocations.LeftArm, mechLabPanel.leftArmWidget);
                LocationHandler.Add(ChassisLocations.RightArm, mechLabPanel.rightArmWidget);
                LocationHandler.Add(ChassisLocations.LeftLeg, mechLabPanel.leftLegWidget);
                LocationHandler.Add(ChassisLocations.RightLeg, mechLabPanel.rightLegWidget);

                // Prepare custom equipment with info about desired origin beforehand
                List <InventoryItemElement_Simple> requestedEquipment = new List <InventoryItemElement_Simple>();
                List <MechLabItemSlotElement>      dismountedItems    = itemsCollectedFromDismount.ToList();
                foreach (MechComponentRef requestedItem in requestedMechComponents)
                {
                    InventoryItemElement_Simple requestedInventoryItem = new InventoryItemElement_Simple();
                    requestedInventoryItem.ComponentRef = requestedItem;
                    requestedInventoryItem.Origin       = MechLabDropTargetType.InventoryList;

                    for (int i = dismountedItems.Count - 1; i >= 0; i--)
                    {
                        if (requestedItem.ComponentDefID == dismountedItems[i].ComponentRef.ComponentDefID)
                        {
                            requestedInventoryItem.Origin = MechLabDropTargetType.Dismount;
                            dismountedItems.RemoveAt(i);
                            break;
                        }
                    }
                    requestedEquipment.Add(requestedInventoryItem);
                }
                // CHECK
                foreach (MechComponentRef item in requestedMechComponents)
                {
                    Logger.Debug("[Extensions.ResetToStock] baseMechComponents: " + item.ComponentDefID);
                }
                foreach (InventoryItemElement_Simple item in requestedEquipment)
                {
                    Logger.Debug("[Extensions.ResetToStock] requestedEquipment: " + item.ComponentRef.ComponentDefID + ", Origin: " + item.Origin);
                }

                // Set inventory including a hint to where the components were taken from
                // Example manual call: mechLabPanel.SetEquipment(requestedEquipment, mechLabPanel.centerTorsoWidget, requestedMechDef.GetLocationLoadoutDef(ChassisLocations.CenterTorso));
                foreach (KeyValuePair <ChassisLocations, MechLabLocationWidget> LocationPair in LocationHandler)
                {
                    mechLabPanel.SetEquipment(requestedEquipment, LocationPair.Value, requestedMechDef.GetLocationLoadoutDef(LocationPair.Key));
                    mechLabPanel.SetArmor(LocationPair.Value, requestedMechDef.GetLocationLoadoutDef(LocationPair.Key));
                }

                // Refresh main inventory
                mechLabPanel.activeMechInventory = new List <MechComponentRef>(requestedMechDef.Inventory);
                //ReflectionHelper.InvokePrivateMethode(mechLabPanel.activeMechDef, "InsertFixedEquipmentIntoInventory", null);

                // Better as it calls RefreshInventory()? -> No, Tonnage is not adjusted... need to look into it somewhen
                //mechLabPanel.activeMechDef.SetInventory(requestedMechDef.Inventory);



                // Update dependent widgets (also calls CalculateCBillValue() -> CalculateSimGameWorkOrderCost() -> PruneWorkOrder())
                mechInfoWidget.RefreshInfo();

                // Mark as modified
                Traverse.Create(mechLabPanel).Field("Modified").SetValue(true);
                GameObject modifiedIcon = (GameObject)AccessTools.Field(typeof(MechLabPanel), "modifiedIcon").GetValue(mechLabPanel);
                modifiedIcon.SetActive(mechLabPanel.Modified);

                // Validate
                mechLabPanel.ValidateLoadout(true);
                ReflectionHelper.InvokePrivateMethode(mechLabPanel, "RefreshInventorySelectability", null);

                // Set Nickname
                mechNickname.SetText(requestedMechDef.Description.Name);

                // @ToDo: Inform user about what components were installed from where
            }
            catch (Exception e)
            {
                Logger.Error(e);
            }
        }
Example #9
0
            public static bool Prefix(MechBayPanel __instance, MechBayMechUnitElement mechElement)
            {
                Logger.LogDebug("We are repairing, yes?");
                Logger.Log("We are repairing, yes?");
                if (!Core.Settings.RepairRearm)
                {
                    return(true);
                }

                var     sim     = UnityGameInstance.BattleTechGame.Simulation;
                MechDef mechDef = mechElement.MechDef;
                WorkOrderEntry_MechLab workOrderEntry_MechLab = __instance.Sim.GetWorkOrderEntryForMech(mechDef);
                bool flag = false;

                for (int i = 0; i < mechDef.Inventory.Length; i++)
                {
                    MechComponentRef mechComponentRef = mechDef.Inventory[i];
                    if (mechComponentRef.DamageLevel != ComponentDamageLevel.Functional && mechComponentRef.DamageLevel
                        != ComponentDamageLevel.Installing && !MechValidationRules.MechComponentUnderMaintenance(mechComponentRef, MechValidationLevel.MechLab, workOrderEntry_MechLab))
                    {
                        flag = true;
                        break;
                    }
                }
                if (!mechDef.IsDamaged && !flag)
                {
                    return(false);
                }
                List <ChassisLocations> list = new List <ChassisLocations>();

                __instance.pendingWorkOrderNew = false;
                __instance.pendingWorkOrderEntriesToAdd.Clear();
                if (workOrderEntry_MechLab == null)
                {
                    workOrderEntry_MechLab = new WorkOrderEntry_MechLab(WorkOrderType.MechLabGeneric, "MechLab-BaseWorkOrder", Strings.T("Modify 'Mech - {0}", new object[]
                    {
                        mechDef.Description.Name
                    }), mechDef.GUID, 0, Strings.T(__instance.Sim.Constants.Story.GeneralMechWorkOrderCompletedText, new object[]
                    {
                        mechDef.Description.Name
                    }));
                    workOrderEntry_MechLab.SetMechDef(mechDef);
                    __instance.pendingWorkOrderNew = true;
                }
                __instance.pendingWorkOrder = workOrderEntry_MechLab;
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.Head, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.Head.CurrentInternalStructure < mechDef.Chassis.Head.InternalStructure)
                {
                    list.Add(ChassisLocations.Head);
                }
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.CenterTorso, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.CenterTorso.CurrentInternalStructure < mechDef.Chassis.CenterTorso.InternalStructure)
                {
                    list.Add(ChassisLocations.CenterTorso);
                }
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.LeftTorso, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.LeftTorso.CurrentInternalStructure < mechDef.Chassis.LeftTorso.InternalStructure)
                {
                    list.Add(ChassisLocations.LeftTorso);
                }
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.RightTorso, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.RightTorso.CurrentInternalStructure < mechDef.Chassis.RightTorso.InternalStructure)
                {
                    list.Add(ChassisLocations.RightTorso);
                }
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.LeftLeg, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.LeftLeg.CurrentInternalStructure < mechDef.Chassis.LeftLeg.InternalStructure)
                {
                    list.Add(ChassisLocations.LeftLeg);
                }
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.RightLeg, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.RightLeg.CurrentInternalStructure < mechDef.Chassis.RightLeg.InternalStructure)
                {
                    list.Add(ChassisLocations.RightLeg);
                }
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.LeftArm, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.LeftArm.CurrentInternalStructure < mechDef.Chassis.LeftArm.InternalStructure)
                {
                    list.Add(ChassisLocations.LeftArm);
                }
                if (!MechValidationRules.MechStructureUnderMaintenance(ChassisLocations.RightArm, MechValidationLevel.MechLab, workOrderEntry_MechLab) && mechDef.RightArm.CurrentInternalStructure < mechDef.Chassis.RightArm.InternalStructure)
                {
                    list.Add(ChassisLocations.RightArm);
                }
                if (list.Count < 1 && !flag)
                {
                    GenericPopupBuilder.Create("Repair Already Ordered", string.Format("A repair order has already been queued for " +
                                                                                       "{0}", mechDef.Name)).AddFader(new UIColorRef?(LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.PopupBackfill), 0f, true).Render();
                    __instance.OnRepairAllCancelled();
                    return(false);
                }
                int num  = 0;
                int num2 = 0;

                for (int j = 0; j < list.Count; j++)
                {
                    LocationDef        chassisLocationDef = mechDef.GetChassisLocationDef(list[j]);
                    LocationLoadoutDef locationLoadoutDef = mechDef.GetLocationLoadoutDef(list[j]);
                    int structureCount = Mathf.RoundToInt(Mathf.Max(0f, chassisLocationDef.InternalStructure - locationLoadoutDef.CurrentInternalStructure));
                    WorkOrderEntry_RepairMechStructure workOrderEntry_RepairMechStructure = __instance.Sim.CreateMechRepairWorkOrder(mechDef.GUID, list[j], structureCount);
                    __instance.pendingWorkOrderEntriesToAdd.Add(workOrderEntry_RepairMechStructure);
                    num  += workOrderEntry_RepairMechStructure.GetCost();
                    num2 += workOrderEntry_RepairMechStructure.GetCBillCost();
                }
                StringBuilder stringBuilder = new StringBuilder();
                int           num3          = 0;

                for (int k = 0; k < mechDef.Inventory.Length; k++)
                {
                    MechComponentRef mechComponentRef2 = mechDef.Inventory[k];
                    if (string.IsNullOrEmpty(mechComponentRef2.SimGameUID))
                    {
                        mechComponentRef2.SetSimGameUID(__instance.Sim.GenerateSimGameUID());
                    }
                    if (mechComponentRef2.DamageLevel == ComponentDamageLevel.Destroyed)
                    {
                        if (num3 < 1)
                        {
                            stringBuilder.Append("\n\nThe following components have been Destroyed. If you continue with the Repair, " +
                                                 "replacement Components will NOT be installed. If you want to replace them with identical or " +
                                                 "different Components, you must Refit the 'Mech.\n\n");
                        }
                        if (num3 < 5)
                        {
                            stringBuilder.Append(mechComponentRef2.MountedLocation.ToString());
                            stringBuilder.Append(": ");
                            stringBuilder.Append(mechComponentRef2.Def.Description.Name);
                            stringBuilder.Append("\n");
                        }
                        num3++;
                        WorkOrderEntry_InstallComponent workOrderEntry_InstallComponent = sim.CreateComponentInstallWorkOrder(__instance.selectedMech.MechDef.GUID,
                                                                                                                              mechComponentRef2, ChassisLocations.None, mechComponentRef2.MountedLocation);
                        __instance.pendingWorkOrderEntriesToAdd.Insert(0, workOrderEntry_InstallComponent);
                        num  += workOrderEntry_InstallComponent.GetCost();
                        num2 += workOrderEntry_InstallComponent.GetCBillCost();
                    }
                    else if (mechComponentRef2.DamageLevel != ComponentDamageLevel.Functional && mechComponentRef2.DamageLevel != ComponentDamageLevel.Installing)
                    {
                        WorkOrderEntry_RepairComponent workOrderEntry_RepairComponent = __instance.Sim.CreateComponentRepairWorkOrder(mechComponentRef2, true);
                        __instance.pendingWorkOrderEntriesToAdd.Add(workOrderEntry_RepairComponent);
                        num  += workOrderEntry_RepairComponent.GetCost();
                        num2 += workOrderEntry_RepairComponent.GetCBillCost();
                    }
                }

                foreach (var foo in __instance.pendingWorkOrderEntriesToAdd)
                {
                    Logger.LogDebug(foo.ID);
                }
                Logger.LogDebug("Armor Repair Section");
                float armorLoss = 1;
                bool  armorTag  = false;

                foreach (var tag in mechDef.MechTags)
                {
                    Logger.LogDebug(tag);
                    if (tag.StartsWith("XLRPArmor"))
                    {
                        armorTag = true;
                        string[] parsedString = tag.Split('_');
                        armorLoss = float.Parse(parsedString[1]);
                    }
                    Logger.LogDebug(armorLoss.ToString());
                }
                if (armorTag)
                {
                    if (!mechDef.MechTags.Contains("XLRP_Armor_Repairing"))
                    {
                        mechDef.MechTags.Add("XLRP_Armor_Repairing");
                    }
                    int brokenArmor = (int)((1 - armorLoss) * mechDef.MechDefAssignedArmor);
                    int frontArmor  = (int)(mechDef.MechDefAssignedArmor - mechDef.CenterTorso.AssignedRearArmor -
                                            mechDef.LeftTorso.AssignedRearArmor - mechDef.RightTorso.AssignedRearArmor);
                    int rearArmor = (int)(mechDef.CenterTorso.AssignedRearArmor +
                                          mechDef.LeftTorso.AssignedRearArmor + mechDef.RightTorso.AssignedRearArmor);
                    Logger.LogDebug($"brokenAmor: {brokenArmor}, frontArmor: {frontArmor}, rearArmor: {rearArmor}");
                    WorkOrderEntry_ModifyMechArmor subEntry = sim.CreateMechArmorModifyWorkOrder(__instance.selectedMech.MechDef.GUID,
                                                                                                 ChassisLocations.All, brokenArmor, frontArmor, rearArmor);

                    __instance.pendingWorkOrderEntriesToAdd.Add(subEntry);
                    num  += subEntry.GetCost();
                    num2 += subEntry.GetCBillCost();
                }

                num = Mathf.Max(1, Mathf.CeilToInt((float)num / (float)__instance.Sim.MechTechSkill));
                if (num3 > 5)
                {
                    stringBuilder.Append(Strings.T("...\nAnd {0} additional destroyed components.\n", new object[]
                    {
                        num3 - 5
                    }));
                }
                string body = Strings.T("Repairing {0} will cost {1:n0} C-Bills and take {2} Days.{3}\n\nProceed?", new object[]
                {
                    mechDef.Name,
                    num2,
                    num,
                    stringBuilder.ToString()
                });

                GenericPopupBuilder.Create("Repair 'Mech?", body).AddButton("Cancel", new Action(__instance.OnRepairAllCancelled), true, null).
                AddButton("Repair", new Action(__instance.OnRepairAllAccepted), true, null).AddFader(new UIColorRef?(LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.PopupBackfill), 0f, true).Render();
                return(false);
            }
Example #10
0
        private static DumperDataEntry FillMech(MechDef d, int parts, int maxparts, int storage, int active, int sma_parts)
        {
            DumperDataEntry r = new DumperDataEntry();

            r.DataTxt    = new string[9];
            r.DataTxt[0] = ((storage + active) > 0 ? "+" : "-") + d.Chassis.Tonnage + "t " + TryLoc(d.Chassis.Description.UIName) + " " + TryLoc(d.Chassis.VariantName);
            r.DataTxt[1] = TryLoc(d.Chassis.StockRole) + "";
            int bal = 0;
            int en  = 0;
            int mis = 0;
            int sup = 0;

            foreach (ChassisLocations c in AllChassisLocs)
            {
                MechStatisticsRules.GetHardpointCountForLocation(d, c, ref bal, ref en, ref mis, ref sup);
            }
            r.DataTxt[2] = bal + "/" + en + "/" + mis + "/" + sup;
            r.DataTxt[3] = (d.Chassis.Tonnage - d.Chassis.InitialTonnage) + "/" + d.Chassis.Heatsinks;
            float carmor = 0;
            float marmor = 0;

            foreach (ChassisLocations c in AllChassisLocs)
            {
                carmor += d.GetLocationLoadoutDef(c).AssignedArmor;
                marmor += d.GetChassisLocationDef(c).MaxArmor;
                if (d.GetChassisLocationDef(c).MaxRearArmor > 0)
                {
                    carmor += d.GetLocationLoadoutDef(c).AssignedRearArmor;
                    marmor += d.GetChassisLocationDef(c).MaxRearArmor;
                }
            }
            float div = UnityGameInstance.BattleTechGame.MechStatisticsConstants.ARMOR_PER_TENTH_TON * 10f;

            if (d.Chassis.ChassisTags.Contains("chassis_ferro"))
            {
                if (d.Chassis.ChassisTags.Contains("chassis_clan"))
                {
                    div = UnityGameInstance.BattleTechGame.MechStatisticsConstants.ARMOR_PER_TENTH_TON * 12f;
                }
                else
                {
                    div = UnityGameInstance.BattleTechGame.MechStatisticsConstants.ARMOR_PER_TENTH_TON * 11.2f;
                }
            }
            carmor       /= div;
            marmor       /= div;
            carmor        = Mathf.Round(carmor * 10) / 10;
            marmor        = Mathf.Round(marmor * 10) / 10;
            r.DataTxt[3] += "/" + carmor + "/" + marmor + "/" + (d.Chassis.Tonnage - d.Chassis.InitialTonnage - marmor);
            if (d.Chassis.MovementCapDef == null)
            {
                d.Chassis.RefreshMovementCaps();
                if (d.Chassis.MovementCapDef == null)
                {
                    r.DataTxt[4] = "??/" + d.Chassis.MaxJumpjets;
                }
                else
                {
                    r.DataTxt[4] = d.Chassis.MovementCapDef.MaxWalkDistance + "/" + d.Chassis.MaxJumpjets;
                }
            }
            else
            {
                r.DataTxt[4] = d.Chassis.MovementCapDef.MaxWalkDistance + "/" + d.Chassis.MaxJumpjets;
            }
            r.DataTxt[5] = d.Chassis.MeleeDamage + "/" + d.Chassis.MeleeInstability + "/" + d.Chassis.DFADamage + "/" + d.Chassis.DFAInstability;
            r.DataTxt[6] = active + "/" + storage + "/" + parts;
            if (sma_parts >= 0)
            {
                r.DataTxt[6] += "(" + sma_parts + ")";
            }
            r.DataTxt[6] += "/" + maxparts;
            r.DataTxt[7]  = d.Chassis.Description.Id + "/" + d.Description.Id;
            Dictionary <string, int> eq  = new Dictionary <string, int>();
            Dictionary <string, int> feq = new Dictionary <string, int>();

            foreach (MechComponentRef c in d.Inventory)
            {
                if (c.ComponentDefType == ComponentType.Weapon)
                {
                    WeaponDef wep = c.Def as WeaponDef;
                    if (wep != null && wep.WeaponCategoryValue.IsMelee || wep.WeaponSubType == WeaponSubType.AIImaginary || wep.WeaponEffectID.Contains("WeaponEffect-Artillery"))
                    {
                        continue;
                    }
                }
                string key = c.Def.Description.Id;
                if (c.IsFixed)
                {
                    if (feq.ContainsKey(key))
                    {
                        feq[key]++;
                    }
                    else
                    {
                        feq.Add(key, 1);
                    }
                }
                else
                {
                    if (eq.ContainsKey(key))
                    {
                        eq[key]++;
                    }
                    else
                    {
                        eq.Add(key, 1);
                    }
                }
            }
            string txteq  = "";
            string txtfeq = "";

            foreach (string key in eq.Keys.OrderBy((k) => k))
            {
                if (!string.IsNullOrEmpty(txteq))
                {
                    txteq += ",";
                }
                txteq += key + ":" + eq[key];
            }
            foreach (string key in feq.Keys.OrderBy((k) => k))
            {
                if (!string.IsNullOrEmpty(txtfeq))
                {
                    txtfeq += ",";
                }
                txtfeq += key + ":" + feq[key];
            }
            string txtext = "";

            foreach (string ex in ExtrasToNote)
            {
                if (d.Chassis.ChassisTags.Contains(ex))
                {
                    if (!string.IsNullOrEmpty(txtext))
                    {
                        txtext += ",";
                    }
                    txtext += ex;
                }
            }
            r.DataTxt[8] = txtext + "/" + txteq + "/" + txtfeq;
            r.Sort       = string.Format("{0,3}_{1}", new object[] { d.Chassis.Tonnage, d.Chassis.VariantName });
            r.DataCsv    = d.Chassis.Tonnage + ";" + d.Chassis.Description.UIName + ";" + d.Chassis.VariantName + ";" + d.Chassis.StockRole;
            r.DataCsv   += ";" + bal + ";" + en + ";" + mis + ";" + sup;
            r.DataCsv   += ";" + (d.Chassis.Tonnage - d.Chassis.InitialTonnage) + ";" + d.Chassis.Heatsinks + ";" + carmor + ";" + marmor + ";" + (d.Chassis.Tonnage - d.Chassis.InitialTonnage - marmor);
            r.DataCsv   += ";" + (d.Chassis.MovementCapDef == null ? -1f : d.Chassis.MovementCapDef.MaxWalkDistance) + ";" + d.Chassis.MaxJumpjets;
            r.DataCsv   += ";" + d.Chassis.MeleeDamage + ";" + d.Chassis.MeleeInstability + ";" + d.Chassis.DFADamage + ";" + d.Chassis.DFAInstability;
            r.DataCsv   += ";" + active + ";" + storage + ";" + parts;
            if (sma_parts >= 0)
            {
                r.DataCsv += "(" + sma_parts + ")";
            }
            r.DataCsv += ";" + maxparts;
            r.DataCsv += ";" + d.Chassis.Description.Id + ";" + d.Description.Id;
            r.DataCsv += ";" + txtext + ";" + txteq + ";" + txtfeq;
            return(r);
        }
Example #11
0
        public void ModifyMech(MechDef mDef, SimGameState s, UpgradeList ulist, ref float _, List <string[]> changedAmmoTypes, MechDef fromData)
        {
            float tonnage = 0;
            float max     = 0;

            MechStatisticsRules.CalculateTonnage(mDef, ref tonnage, ref max);
            float armorfact = mDef.GetMechArmorPointFactor();

            BTRandomMechComponentUpgrader_Init.Log.Log($"correcting tonnage 2: armor (each armor point costs {armorfact} t)");
            while (tonnage + armorfact <= mDef.Chassis.Tonnage)
            {
                bool assOne = false;
                foreach (ChassisLocations c in RMCU_Helper.Locations)
                {
                    if (tonnage + armorfact >= mDef.Chassis.Tonnage)
                    {
                        break;
                    }
                    LocationLoadoutDef l = mDef.GetLocationLoadoutDef(c);
                    if (l.AssignedArmor >= mDef.GetChassisLocationDef(c).MaxArmor)
                    {
                        continue;
                    }
                    l.AssignedArmor += 1;
                    l.CurrentArmor  += 1;
                    tonnage         += armorfact;
                    BTRandomMechComponentUpgrader_Init.Log.Log($"increased {c} armor to {l.AssignedArmor}");
                    assOne = true;
                }
                foreach (ChassisLocations c in RMCU_Helper.RearArmoredLocs)
                {
                    if (tonnage + armorfact >= mDef.Chassis.Tonnage)
                    {
                        break;
                    }
                    LocationLoadoutDef l = mDef.GetLocationLoadoutDef(c);
                    if (l.AssignedRearArmor >= mDef.GetChassisLocationDef(c).MaxRearArmor)
                    {
                        continue;
                    }
                    l.AssignedRearArmor += 1;
                    l.CurrentRearArmor  += 1;
                    tonnage             += armorfact;
                    BTRandomMechComponentUpgrader_Init.Log.Log($"increased {c} rear armor to {l.AssignedRearArmor}");
                    assOne = true;
                }
                if (!assOne)
                {
                    BTRandomMechComponentUpgrader_Init.Log.Log("no free armor location found!");
                    break;
                }
            }
            while (tonnage > mDef.Chassis.Tonnage)
            {
                bool assOne = false;
                foreach (ChassisLocations c in RMCU_Helper.Locations)
                {
                    if (tonnage <= mDef.Chassis.Tonnage)
                    {
                        break;
                    }
                    LocationLoadoutDef l = mDef.GetLocationLoadoutDef(c);
                    if (l.AssignedArmor <= 1)
                    {
                        continue;
                    }
                    l.AssignedArmor -= 1;
                    l.CurrentArmor  -= 1;
                    tonnage         -= armorfact;
                    BTRandomMechComponentUpgrader_Init.Log.Log($"decreased {c} armor to {l.AssignedArmor}");
                    assOne = true;
                }
                foreach (ChassisLocations c in RMCU_Helper.RearArmoredLocs)
                {
                    if (tonnage <= mDef.Chassis.Tonnage)
                    {
                        break;
                    }
                    LocationLoadoutDef l = mDef.GetLocationLoadoutDef(c);
                    if (l.AssignedRearArmor <= 1)
                    {
                        continue;
                    }
                    l.AssignedRearArmor -= 1;
                    l.CurrentRearArmor  -= 1;
                    tonnage             -= armorfact;
                    BTRandomMechComponentUpgrader_Init.Log.Log($"decreased {c} rear armor to {l.AssignedRearArmor}");
                    assOne = true;
                }
                if (!assOne)
                {
                    BTRandomMechComponentUpgrader_Init.Log.Log("no free armor location found!");
                    break;
                }
            }

            BTRandomMechComponentUpgrader_Init.Log.Log($"final weight: {tonnage}/{mDef.Chassis.Tonnage}");
        }
Example #12
0
        public static bool Prefix(SimGameState __instance, MechDef mech)
        {
            try
            {
                // Start of analysing a mech for armor repair
                Logger.LogInfo("Analysing Mech: " + mech.Name);
                Logger.LogInfo("============================================");

                // Base generic MechLab WO for a mech that requires armor or structure repair - each individual locational subentry WO has to be added to this base WO later
                WorkOrderEntry_MechLab newMechLabWorkOrder = null;

                /* STRUCTURE DAMAGE CHECKS
                 * ------------------------
                 * Check if the given mech needs any structure repaired and that EnableStructureRepair is true in the mod settings
                 *
                 */
                if (ArmorRepair.ModSettings.EnableStructureRepair)
                {
                    if (Helpers.CheckStructureDamage(mech))
                    {
                        Logger.LogDebug("SimGameConstant: StructureRepairTechPoints: " + __instance.Constants.MechLab.StructureRepairTechPoints);
                        Logger.LogDebug("SimGameConstant: StructureRepairCost: " + __instance.Constants.MechLab.StructureRepairCost);

                        // Loop over the ChassisLocations for repair in their highest -> lowest priority order from the dictionary defined in Helpers
                        for (int index = 0; index < Globals.repairPriorities.Count; index++)
                        {
                            // Set current looped ChassisLocation
                            ChassisLocations thisLoc = Globals.repairPriorities.ElementAt(index).Value;
                            // Get current mech's loadout definition from the looped chassis location
                            LocationLoadoutDef thisLocLoadout = mech.GetLocationLoadoutDef(thisLoc);
                            // Friendly name for this location
                            string thisLocName = thisLoc.ToString();

                            Logger.LogDebug("Analysing location: " + thisLocName);

                            // Check if a new base MechLab order needs to be created or not
                            if (newMechLabWorkOrder == null)
                            {
                                // Create new base work order of the generic MechLab type if it doesn't already exist
                                newMechLabWorkOrder = Helpers.CreateBaseMechLabOrder(__instance, mech);
                            }

                            float currentStructure = thisLocLoadout.CurrentInternalStructure;
                            float definedStructure = mech.GetChassisLocationDef(thisLoc).InternalStructure;

                            // Only create work orders for repairing structure if this location has taken damage in combat
                            if (currentStructure != definedStructure)
                            {
                                // Work out difference of structure lost for each location - default to 0
                                int structureDifference = 0;
                                structureDifference = (int)Mathf.Abs(currentStructure - definedStructure);

                                Logger.LogInfo("Total structure difference for " + thisLocName + " is " + structureDifference);

                                Logger.LogInfo("Creating MechRepair work order entry for " + thisLocName);
                                Logger.LogDebug("Calling CreateMechRepairWorkOrder with params - GUID: " +
                                                mech.GUID.ToString() +
                                                " | Location: " + thisLocName +
                                                " | structureDifference: " + structureDifference
                                                );

                                WorkOrderEntry_RepairMechStructure newRepairWorkOrder = __instance.CreateMechRepairWorkOrder(
                                    mech.GUID,
                                    thisLocLoadout.Location,
                                    structureDifference
                                    );

                                Logger.LogDebug("Adding WO subentry to repair missing " + thisLocName + " structure.");
                                newMechLabWorkOrder.AddSubEntry(newRepairWorkOrder);
                            }
                            else
                            {
                                Logger.LogDebug("Structure repair not required for: " + thisLocName);
                            }
                        }
                    }
                }

                /* COMPONENT DAMAGE CHECKS
                 * -----------------------
                 * Check if the given mech needs any critted components repaired
                 *
                 * NOTE: Not yet working. Repair components are added to work order but not actually repaired after WO completes. Noticed there is another queue involved on SGS.WorkOrderComponents we need to debug.
                 * Currently throws "SimGameState [ERROR] ML_RepairComponent MechBay - RepairComponent - SGRef_490 had an invalid mechComponentID Ammo_AmmunitionBox_Generic_AC5, skipping" in SimGame logger on WO completion.
                 * if (Helpers.CheckDamagedComponents(mech))
                 * {
                 *  for (int index = 0; index < mech.Inventory.Length; index++)
                 *  {
                 *      MechComponentRef mechComponentRef = mech.Inventory[index];
                 *
                 *      // Penalized = Critted Component
                 *      if (mechComponentRef.DamageLevel == ComponentDamageLevel.Penalized)
                 *      {
                 *          // Check if a new base MechLab order needs to be created or not
                 *          if (newMechLabWorkOrder == null)
                 *          {
                 *              // Create new base work order of the generic MechLab type if it doesn't already exist
                 *              newMechLabWorkOrder = Helpers.CreateBaseMechLabOrder(__instance, mech);
                 *          }
                 *
                 *          // Create a new component repair work order for this component
                 *          Logger.LogInfo("Creating Component Repair work order entry for " + mechComponentRef.ComponentDefID);
                 *          WorkOrderEntry_RepairComponent newComponentRepairOrder = __instance.CreateComponentRepairWorkOrder(mechComponentRef, false);
                 *
                 *          // Attach as a child to the base Mech Lab order.
                 *          Logger.LogDebug("Adding WO subentry to repair component " + mechComponentRef.ComponentDefID);
                 *          newMechLabWorkOrder.AddSubEntry(newComponentRepairOrder);
                 *      }
                 *  }
                 * }
                 */


                /* ARMOR DAMAGE CHECKS
                 * -------------------
                 * Check if the given mech needs any structure repaired
                 *
                 */
                if (Helpers.CheckArmorDamage(mech))
                {
                    Logger.LogDebug("SimGameConstant: ArmorInstallTechPoints: " + __instance.Constants.MechLab.ArmorInstallTechPoints);
                    Logger.LogDebug("SimGameConstant: ArmorInstallCost: " + __instance.Constants.MechLab.ArmorInstallCost);

                    // Loop over the ChassisLocations for repair in their highest -> lowest priority order from the dictionary defined in Helpers
                    for (int index = 0; index < Globals.repairPriorities.Count; index++)
                    {
                        // Set current ChassisLocation
                        ChassisLocations thisLoc = Globals.repairPriorities.ElementAt(index).Value;
                        // Get current mech's loadout from the looped chassis location
                        LocationLoadoutDef thisLocLoadout = mech.GetLocationLoadoutDef(thisLoc);
                        // Friendly name for this location
                        string thisLocName = thisLoc.ToString();

                        Logger.LogDebug("Analysing location: " + thisLocName);

                        // Check if a new base MechLab order needs to be created
                        if (newMechLabWorkOrder == null)
                        {
                            // Create new base work order of the generic MechLab type if it doesn't already exist
                            newMechLabWorkOrder = Helpers.CreateBaseMechLabOrder(__instance, mech);
                        }

                        // Work out difference of armor lost for each location - default to 0
                        int armorDifference = 0;

                        // Consider rear armour in difference calculation if this is a RT, CT or LT
                        if (thisLocLoadout == mech.CenterTorso || thisLocLoadout == mech.RightTorso || thisLocLoadout == mech.LeftTorso)
                        {
                            Logger.LogDebug("Location also has rear armor.");
                            armorDifference = (int)Mathf.Abs(thisLocLoadout.CurrentArmor - thisLocLoadout.AssignedArmor) + (int)Mathf.Abs(thisLocLoadout.CurrentRearArmor - thisLocLoadout.AssignedRearArmor);
                        }
                        else
                        {
                            armorDifference = (int)Mathf.Abs(thisLocLoadout.CurrentArmor - thisLocLoadout.AssignedArmor);
                        }
                        // Only create work orders for repairing armor if this location has taken armor damage in combat
                        if (armorDifference != 0)
                        {
                            Logger.LogInfo("Total armor difference for " + thisLocName + " is " + armorDifference);
                            Logger.LogInfo("Creating ModifyMechArmor work order entry for " + thisLocName);
                            Logger.LogDebug("Calling ModifyMechArmor WO with params - GUID: " +
                                            mech.GUID.ToString() +
                                            " | Location: " + thisLocName +
                                            " | armorDifference: " + armorDifference +
                                            " | AssignedArmor: " + thisLocLoadout.AssignedArmor +
                                            " | AssignedRearArmor: " + thisLocLoadout.AssignedRearArmor
                                            );
                            WorkOrderEntry_ModifyMechArmor newArmorWorkOrder = __instance.CreateMechArmorModifyWorkOrder(
                                mech.GUID,
                                thisLocLoadout.Location,
                                armorDifference,
                                (int)(thisLocLoadout.AssignedArmor),
                                (int)(thisLocLoadout.AssignedRearArmor)
                                );

                            /* IMPORTANT!
                             * This has turned out to be required as CurrentArmor appears to be reset to AssignedArmor from somewhere unknown in the game after battle
                             * So if we don't reset AssignedArmor now, player can cancel the work order to get a free armor reset anyway!
                             *
                             * NOTE: CeilToInt (or similar rounding) is vital to prevent fractions of armor from causing Mech tonnage / validation issues for the player
                             */
                            Logger.LogDebug("Forcing assignment of Assigned Armor: " + thisLocLoadout.AssignedArmor + " To Current Armor (CeilToInt): " + Mathf.CeilToInt(thisLocLoadout.CurrentArmor));
                            thisLocLoadout.AssignedArmor     = Mathf.CeilToInt(thisLocLoadout.CurrentArmor);
                            thisLocLoadout.AssignedRearArmor = Mathf.CeilToInt(thisLocLoadout.CurrentRearArmor);

                            Logger.LogInfo("Adding WO subentry to install missing " + thisLocName + " armor.");
                            newMechLabWorkOrder.AddSubEntry(newArmorWorkOrder);
                        }
                        else
                        {
                            Logger.LogDebug("Armor repair not required for: " + thisLocName);
                        }
                    }
                }


                /* WORK ORDER SUBMISSION
                 * ---------------------
                 * Submit the complete work order for the mech, which will include any repair armor / structure subentries for each location
                 *
                 */
                if (newMechLabWorkOrder != null)
                {
                    if (newMechLabWorkOrder.SubEntryCount > 0)
                    {
                        // Submit work order to our temporary queue for internal processing
                        Helpers.SubmitTempWorkOrder(
                            __instance,
                            newMechLabWorkOrder,
                            mech
                            );
                    }
                    else
                    {
                        Logger.LogInfo(mech.Name + " did not require repairs.");
                    }
                }

                // Lifted from original RestoreMechPostCombat method - resets any non-functional mech components back to functional
                foreach (MechComponentRef mechComponentRef in mech.Inventory)
                {
                    if (mechComponentRef.DamageLevel == ComponentDamageLevel.NonFunctional)
                    {
                        Logger.LogDebug("Resetting non-functional mech component: " + mechComponentRef.ToString());
                        mechComponentRef.DamageLevel = ComponentDamageLevel.Functional;
                    }
                }

                return(false); // Finally, prevent firing the original method
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                return(true); // Allow original method to fire if there is an exception
            }
        }