// 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 HardpointDataDef._WeaponHardpointData GetWeaponData(ChassisLocations location) { var locationString = location.ToString().ToLower(); var weaponsData = chassisDef.HardpointDataDef.HardpointData.FirstOrDefault(x => x.location == locationString); return(weaponsData); }
private static void Postfix(ref SimGameState __instance, ref string mechSimGameUID, ref ChassisLocations location, ref int structureCount, ref WorkOrderEntry_RepairMechStructure __result) { try { float mechTonnageModifier = 1f; // Original method code, this is still needed to work out zero structure modifiers string id = string.Format("MechLab - RepairMech - {0}", __instance.GenerateSimGameUID()); bool flag = false; float num = 1f; float num2 = 1f; foreach (MechDef mechDef in __instance.ActiveMechs.Values) { if (mechDef.GUID == mechSimGameUID) { // If ScaleStructureCostByTonnage is enabled, make the mech tonnage work as a percentage tech cost reduction (95 tons = 0.95 or "95%" of the cost, 50 tons = 0.05 or "50%" of the cost etc) if (ArmorRepair.ModSettings.ScaleStructureCostByTonnage) { mechTonnageModifier = mechDef.Chassis.Tonnage * 0.01f; } if (mechDef.GetChassisLocationDef(location).InternalStructure == (float)structureCount) { flag = true; } break; } } if (flag) { num = __instance.Constants.MechLab.ZeroStructureCBillModifier; num2 = __instance.Constants.MechLab.ZeroStructureTechPointModifier; } int techCost = Mathf.CeilToInt((__instance.Constants.MechLab.StructureRepairTechPoints * (float)structureCount * num2) * mechTonnageModifier); int cbillCost = Mathf.CeilToInt((float)((__instance.Constants.MechLab.StructureRepairCost * structureCount) * num) * mechTonnageModifier); Logger.LogDebug("Structure WO Subentry Costing:"); Logger.LogDebug("***************************************"); Logger.LogDebug("location: " + location.ToString()); Logger.LogDebug("structureCount: " + structureCount); Logger.LogDebug("mechTonnageModifier: " + mechTonnageModifier); Logger.LogDebug("techCost: " + techCost); Logger.LogDebug("cBill cost: " + cbillCost); Logger.LogDebug("***************************************"); __result = new WorkOrderEntry_RepairMechStructure(id, string.Format("Repair 'Mech - {0}", location.ToString()), mechSimGameUID, techCost, location, structureCount, cbillCost, string.Empty); } catch (Exception ex) { Logger.LogError(ex); } }
public override string ToString() { var sb = new StringBuilder("Allowed Locations for " + Tag); sb.Append("\n- Default: " + Default.ToString()); if (UnitTypes != null && UnitTypes.Length > 0) { foreach (var unitType in UnitTypes) { sb.Append("\n- " + unitType.UnitType + ": " + unitType.Location.ToString()); } } return(sb.ToString()); }
// 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 void Postfix(ref SimGameState __instance, ref string mechSimGameUID, ref ChassisLocations location, ref int armorDiff, ref int frontArmor, ref int rearArmor, ref WorkOrderEntry_ModifyMechArmor __result) { string id = string.Format("MechLab - ModifyArmor - {0}", __instance.GenerateSimGameUID()); try { float mechTonnageModifier = 1f; int techCost = 0; int cbillCost = 0; foreach (MechDef mechDef in __instance.ActiveMechs.Values) { if (mechDef.GUID == mechSimGameUID) { // If ScaleArmorCostByTonnage is enabled, make the mech tonnage work as a percentage tech cost reduction (95 tons = 0.95 or "95%" of the cost, 50 tons = 0.05 or "50%" of the cost etc) if (ArmorRepair.ModSettings.ScaleArmorCostByTonnage) { mechTonnageModifier = mechDef.Chassis.Tonnage * 0.01f; } float locationTechCost = ((armorDiff * mechTonnageModifier) * __instance.Constants.MechLab.ArmorInstallTechPoints); float locationCbillCost = ((armorDiff * mechTonnageModifier) * __instance.Constants.MechLab.ArmorInstallCost); techCost = Mathf.CeilToInt(locationTechCost); cbillCost = Mathf.CeilToInt(locationCbillCost); Logger.LogDebug("Armor WO SubEntry Costing: "); Logger.LogDebug("***************************************"); Logger.LogDebug("location: " + location.ToString()); Logger.LogDebug("armorDifference: " + armorDiff); Logger.LogDebug("mechTonnage: " + mechDef.Chassis.Tonnage); Logger.LogDebug("mechTonnageModifier: " + mechTonnageModifier); Logger.LogDebug("techCost: " + techCost); Logger.LogDebug("cbillCost: " + cbillCost); Logger.LogDebug("***************************************"); } } __result = new WorkOrderEntry_ModifyMechArmor(id, string.Format("Modify Armor - {0}", location.ToString()), mechSimGameUID, techCost, location, frontArmor, rearArmor, cbillCost, string.Empty); } catch (Exception ex) { Logger.LogError(ex); } }
private static void Postfix(ref SimGameState __instance, ref string mechSimGameUID, ref ChassisLocations location, ref int armorDiff, ref int frontArmor, ref int rearArmor, ref WorkOrderEntry_ModifyMechArmor __result) { string id = string.Format("MechLab - ModifyArmor - {0}", __instance.GenerateSimGameUID()); try { float mechTonnageModifier = 1f; int techCost = 0; int cbillCost = 0; foreach (MechDef mechDef in __instance.ActiveMechs.Values) { if (mechDef.GUID == mechSimGameUID) { ArmorRepairFactor armor = null; MechComponentRef armoritem = null; foreach (var item in mechDef.Inventory) { if (item.IsCategory(ArmorRepair.ModSettings.ArmorCategory)) { armor = item.GetComponent <ArmorRepairFactor>(); armoritem = item; break; } } Logger.LogDebug("Armor WO SubEntry Costing: "); Logger.LogDebug("***************************************"); Logger.LogDebug(" location: " + location.ToString()); Logger.LogDebug(" armorDifference: " + armorDiff); Logger.LogDebug(" mechTonnage: " + mechDef.Chassis.Tonnage); Logger.LogDebug(" mechTonnageModifier: " + mechTonnageModifier); if (armor != null) { Logger.LogDebug($" ArmorRepair mods tp:{armor.ArmorTPCost:0.00} cb:{armor.ArmorCBCost:0.00}"); } float atpcost = armor?.ArmorTPCost ?? 1; float acbcost = armor?.ArmorCBCost ?? 1; if (ArmorRepair.ModSettings.RepairCostByTag != null && ArmorRepair.ModSettings.RepairCostByTag.Length > 0) { foreach (var cost in ArmorRepair.ModSettings.RepairCostByTag) { if (mechDef.Chassis.ChassisTags.Contains(cost.Tag)) { Logger.LogDebug($" Chassis {cost.Tag} mods tp:{cost.ArmorTPCost:0.00} cb:{cost.ArmorCBCost:0.00}"); atpcost *= cost.ArmorTPCost; acbcost *= cost.ArmorCBCost; } if (armoritem != null && armoritem.Def.ComponentTags.Contains(cost.Tag)) { Logger.LogDebug($" {armoritem.ComponentDefID} {cost.Tag} mods tp:{cost.ArmorTPCost:0.00} cb:{cost.ArmorCBCost:0.00}"); atpcost *= cost.ArmorTPCost; acbcost *= cost.ArmorCBCost; } } } // If ScaleArmorCostByTonnage is enabled, make the mech tonnage work as a percentage tech cost reduction (95 tons = 0.95 or "95%" of the cost, 50 tons = 0.05 or "50%" of the cost etc) if (ArmorRepair.ModSettings.ScaleArmorCostByTonnage) { mechTonnageModifier = mechDef.Chassis.Tonnage * 0.01f; } float locationTechCost = ((armorDiff * mechTonnageModifier) * __instance.Constants.MechLab.ArmorInstallTechPoints) * atpcost; float locationCbillCost = ((armorDiff * mechTonnageModifier) * __instance.Constants.MechLab.ArmorInstallCost) * acbcost; techCost = Mathf.CeilToInt(locationTechCost); cbillCost = Mathf.CeilToInt(locationCbillCost); Logger.LogDebug($" tpmod: {atpcost:0.000}"); Logger.LogDebug($" cbmod: {acbcost:0.000}"); Logger.LogDebug(" techCost: " + techCost); Logger.LogDebug(" cbillCost: " + cbillCost); Logger.LogDebug("***************************************"); } } __result = new WorkOrderEntry_ModifyMechArmor(id, string.Format("Modify Armor - {0}", location.ToString()), mechSimGameUID, techCost, location, frontArmor, rearArmor, cbillCost, string.Empty); } catch (Exception ex) { Logger.LogError(ex); } }
internal static string GetStringFromLocation(ChassisLocations location) { return(location.ToString().ToLower()); }
internal bool ValidateMech( out string error, MechDef mechDef, ChassisLocations dropLocation, MechComponentRef droppedComponent = null, Dictionary <MechValidationType, List <Text> > errors = null) { error = null; var tagsOnMech = new HashSet <string>(); // chassis { var chassis = mechDef.Chassis; // tags if (chassis.ChassisTags != null) { tagsOnMech.UnionWith(chassis.ChassisTags); } // id var identifier = chassis.Description.Id; tagsOnMech.Add(identifier); } void ProcessComponent(MechComponentRef item, HashSet <string> tagsForComponent, string location) { // tags if (item.Def.ComponentTags != null) { tagsForComponent.UnionWith(item.Def.ComponentTags.Select(i => i.Replace("{location}", location))); } // id var identifier = item.ComponentDefID; tagsForComponent.Add(identifier); // category for component foreach (var component in item.GetComponents <Category>()) { tagsForComponent.Add(component.CategoryID); if (!string.IsNullOrEmpty(component.Tag)) { tagsForComponent.Add(component.Tag); } } } // components foreach (var def in mechDef.Inventory) { ProcessComponent(def, tagsOnMech, def.MountedLocation.ToString()); } HashSet <string> tagsForDropped = null; if (droppedComponent != null) { tagsForDropped = new HashSet <string>(); ProcessComponent(droppedComponent, tagsForDropped, dropLocation.ToString()); tagsOnMech.UnionWith(tagsForDropped); // used for incompatible check } var checkRequiresForTags = tagsOnMech; if (tagsForDropped != null) { checkRequiresForTags = tagsForDropped; if (!Control.Settings.TagRestrictionDropValidateRequiredTags) { checkRequiresForTags = new HashSet <string>(); } } foreach (var tag in checkRequiresForTags) { var requiredAnyTags = RequiredAnyTags(tag); var hasMetAnyRequiredAnyTags = true; // no required any tags = ok foreach (var requiredAnyTag in requiredAnyTags) { hasMetAnyRequiredAnyTags = false; // at least one required any tag check = nok if (tagsOnMech.Contains(requiredAnyTag)) { hasMetAnyRequiredAnyTags = true; // at least on required any tag found = ok break; } } if (hasMetAnyRequiredAnyTags) { continue; } var tagName = NameForTag(tag); error = $"{tagName} requirements are not met"; if (errors == null) { return(false); } errors[MechValidationType.InvalidInventorySlots].Add(new Text(error)); } foreach (var tag in checkRequiresForTags) { var requiredTags = RequiredTags(tag); foreach (var requiredTag in requiredTags) { if (tagsOnMech.Contains(requiredTag)) { continue; } var tagName = NameForTag(tag); var requiredTagName = NameForTag(requiredTag); error = $"{tagName} requires {requiredTagName}"; if (errors == null) { return(false); } errors[MechValidationType.InvalidInventorySlots].Add(new Text(error)); } } var checkIncompatiblesForTags = tagsOnMech; if (tagsForDropped != null) { if (!Control.Settings.TagRestrictionDropValidateIncompatibleTags) { checkIncompatiblesForTags = new HashSet <string>(); } } foreach (var tag in checkIncompatiblesForTags) { var tagsPool = tagsOnMech; // if dropping we either want only to check either: // - the "dropped tags incompatibles" with mech+items // - each "mech+items incompatibles" with dropped tags if (tagsForDropped != null && !tagsForDropped.Contains(tag)) { tagsPool = tagsForDropped; } var incompatibleTags = IncompatibleTags(tag); foreach (var incompatibleTag in incompatibleTags) { if (!tagsPool.Contains(incompatibleTag)) { continue; } var tagName = NameForTag(tag); var incompatibleTagName = NameForTag(incompatibleTag); error = $"{tagName} can't be used with {incompatibleTagName}"; if (errors == null) { return(false); } errors[MechValidationType.InvalidInventorySlots].Add(new Text(error)); } } return(error == null); }
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 } }
private static void Postfix(ref SimGameState __instance, ref string mechSimGameUID, ref ChassisLocations location, ref int structureCount, ref WorkOrderEntry_RepairMechStructure __result) { try { float mechTonnageModifier = 1f; // Original method code, this is still needed to work out zero structure modifiers string id = string.Format("MechLab - RepairMech - {0}", __instance.GenerateSimGameUID()); bool is_repaired = false; float cbmod = 1f; float tpmod = 1f; foreach (MechDef mechDef in __instance.ActiveMechs.Values) { if (mechDef.GUID == mechSimGameUID) { if (mechDef.GetChassisLocationDef(location).InternalStructure == (float)structureCount) { is_repaired = true; break; } Logger.LogDebug("Structure WO Subentry Costing:"); Logger.LogDebug("***************************************"); Logger.LogDebug(" location: " + location.ToString()); Logger.LogDebug(" structureCount: " + structureCount); Logger.LogDebug(" mechTonnageModifier: " + mechTonnageModifier); // If ScaleStructureCostByTonnage is enabled, make the mech tonnage work as a percentage tech cost reduction (95 tons = 0.95 or "95%" of the cost, 50 tons = 0.05 or "50%" of the cost etc) if (ArmorRepair.ModSettings.ScaleStructureCostByTonnage) { mechTonnageModifier = mechDef.Chassis.Tonnage * 0.01f; } StructureRepairFactor str = null; MechComponentRef structitem = null; foreach (var item in mechDef.Inventory) { if (item.IsCategory(ArmorRepair.ModSettings.StructureCategory)) { str = item.GetComponent <StructureRepairFactor>(); structitem = item; break; } } if (str != null) { Logger.LogDebug($" StructRepair mods tp:{str.StructureTPCost:0.00} cb:{str.StructureCBCost:0.00}"); } tpmod *= str?.StructureTPCost ?? 1; cbmod *= str?.StructureTPCost ?? 1; if (ArmorRepair.ModSettings.RepairCostByTag != null && ArmorRepair.ModSettings.RepairCostByTag.Length > 0) { foreach (var cost in ArmorRepair.ModSettings.RepairCostByTag) { if (mechDef.Chassis.ChassisTags.Contains(cost.Tag)) { Logger.LogDebug($" Chassis {cost.Tag} mods tp:{cost.StructureTPCost:0.00} cb:{cost.StructureCBCost:0.00}"); tpmod *= cost.StructureTPCost; cbmod *= cost.StructureCBCost; } if (structitem != null && structitem.Def.ComponentTags.Contains(cost.Tag)) { Logger.LogDebug($" {structitem.ComponentDefID} {cost.Tag} mods tp:{cost.StructureTPCost:0.00} cb:{cost.StructureCBCost:0.00}"); tpmod *= cost.StructureTPCost; cbmod *= cost.StructureCBCost; } } } break; } } if (is_repaired) { cbmod = __instance.Constants.MechLab.ZeroStructureCBillModifier; tpmod = __instance.Constants.MechLab.ZeroStructureTechPointModifier; } int techCost = Mathf.CeilToInt((__instance.Constants.MechLab.StructureRepairTechPoints * (float)structureCount * tpmod) * mechTonnageModifier); int cbillCost = Mathf.CeilToInt((float)((__instance.Constants.MechLab.StructureRepairCost * structureCount) * cbmod) * mechTonnageModifier); Logger.LogDebug($" tpmod: {tpmod:0.000}"); Logger.LogDebug($" cbmod: {cbmod:0.000}"); Logger.LogDebug(" techCost: " + techCost); Logger.LogDebug(" cBill cost: " + cbillCost); Logger.LogDebug("***************************************"); __result = new WorkOrderEntry_RepairMechStructure(id, string.Format("Repair 'Mech - {0}", location.ToString()), mechSimGameUID, techCost, location, structureCount, cbillCost, string.Empty); } catch (Exception ex) { Logger.LogError(ex); } }