Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SaveOurLoot v1.5.3
SaveOurLoot.dll
Decompiled 6 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SaveOurLoot")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Mod for Lethal Company, that allow adjusting item loss after mission")] [assembly: AssemblyFileVersion("1.5.3.0")] [assembly: AssemblyInformationalVersion("1.5.3+78f1d57b01d70e8d0dbd53df2cadd3c0ed79b09b")] [assembly: AssemblyProduct("SaveOurLoot")] [assembly: AssemblyTitle("SaveOurLoot")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SaveOurLoot { public class Config { public static ConfigEntry<float> saveAllChance; public static ConfigEntry<float> saveEachChance; public static ConfigEntry<int> scrapLossMax; public static ConfigEntry<bool> valueSaveEnabled; public static ConfigEntry<float> valueSavePercent; public static ConfigEntry<bool> equipmentLossEnabled; public static ConfigEntry<float> equipmentLossChance; public static ConfigEntry<int> equipmentLossMax; public static ConfigEntry<bool> hoardingBugInfestationEnabled; public static ConfigEntry<float> hoardingBugInfestationChance; public static ConfigEntry<float> hoardingBugInfestationLossEachChance; public static ConfigEntry<int> hoardingBugInfestationLossMax; public static ConfigEntry<bool> hoardingBugInfestationValueLossEnabled; public static ConfigEntry<float> hoardingBugInfestationValueLossPercent; public static ConfigEntry<bool> hoardingBugInfestationEquipmentLossEnabled; public static ConfigEntry<float> hoardingBugInfestationEquipmentLossChance; public static ConfigEntry<int> hoardingBugInfestationEquipmentLossMax; public static void Load() { saveAllChance = Plugin.config.Bind<float>("LootSaving", "SaveAllChance", 0.25f, "A chance of all item being saved.\nVanilla value 0. Values between 0-1."); saveEachChance = Plugin.config.Bind<float>("LootSaving", "SaveEachChance", 0.5f, "A chance of each item being saved.\nApplied after SaveAllChance\nVanilla value 0. Values between 0-1."); scrapLossMax = Plugin.config.Bind<int>("LootSaving", "ScrapLossMax", int.MaxValue, $"The maximum amount of items that can be lost.\nApplied after SaveEachChance\nVanilla value {int.MaxValue}. Values between 0-{int.MaxValue}."); valueSaveEnabled = Plugin.config.Bind<bool>("LootSaving", "ValueSaveEnabled", false, "Will it try to save item based on it scrap value?\nApplied after SaveAllChance and prevent SaveEachChance\nVanilla value False."); valueSavePercent = Plugin.config.Bind<float>("LootSaving", "ValueSavePercent", 0.25f, "What percentage of total scrap value will be saved among loot.\nVanilla value 0. Values between 0-1."); equipmentLossEnabled = Plugin.config.Bind<bool>("EquipmentLoss", "EquipmentLossEnabled", false, "Will it allow equipment to be lost?\nVanilla value False."); equipmentLossChance = Plugin.config.Bind<float>("EquipmentLoss", "EquipmentLossChance", 0.1f, "A chance of each equipment being lost.\nApplied after SaveAllChance\nVanilla value 0. Values between 0-1."); equipmentLossMax = Plugin.config.Bind<int>("EquipmentLoss", "EquipmentLossMax", int.MaxValue, $"The maximum amount of equipment that can be lost.\nApplied after EquipmentLossChance\nVanilla value 0. Values between 0-{int.MaxValue}."); hoardingBugInfestationEnabled = Plugin.config.Bind<bool>("HoardingBugInfestation", "HoardingBugInfestationEnabled", false, "Space is a dangerous place. Bug Mafia will protect you for a little part of your loot.\nYour Ship is infested with Hoarding Bugs, which steal your loot while you sleep between missions.\nEnable all features related to this category?\nVanilla value False."); hoardingBugInfestationChance = Plugin.config.Bind<float>("HoardingBugInfestation", "HoardingBugInfestationChance", 1f, "A chance of items being stolen by Hoarding Bugs each night on the Ship.\nValues between 0-1."); hoardingBugInfestationLossEachChance = Plugin.config.Bind<float>("HoardingBugInfestation", "HoardingBugInfestationLossEachChance", 0.1f, "A chance of each item being stolen by Hoarding Bugs.\nValues between 0-1."); hoardingBugInfestationLossMax = Plugin.config.Bind<int>("HoardingBugInfestation", "HoardingBugInfestationLossMax", int.MaxValue, $"The maximum amount of items that can be lost.\nApplied after HoardingBugInfestationLossEachChance\nVanilla value {int.MaxValue}. Values between 0-{int.MaxValue}."); hoardingBugInfestationValueLossEnabled = Plugin.config.Bind<bool>("HoardingBugInfestation", "HoardingBugInfestationValueLossEnabled", true, "Will it try to steal items based on it scrap value?\nPrevent HoardingBugInfestationLossEachChance\nVanilla value False."); hoardingBugInfestationValueLossPercent = Plugin.config.Bind<float>("HoardingBugInfestation", "HoardingBugInfestationValueLossPercent", 0.1f, "What percentage of total scrap value will be stolen among loot.\nValues between 0-1."); hoardingBugInfestationEquipmentLossEnabled = Plugin.config.Bind<bool>("HoardingBugInfestation", "HoardingBugInfestationEquipmentLossEnabled", true, "Will it allow stealing of equipment?"); hoardingBugInfestationEquipmentLossChance = Plugin.config.Bind<float>("HoardingBugInfestation", "HoardingBugInfestationEquipmentLossChance", 0.05f, "A chance of each equipment being stollen.\nValues between 0-1."); hoardingBugInfestationEquipmentLossMax = Plugin.config.Bind<int>("HoardingBugInfestation", "HoardingBugInfestationEquipmentLossMax", int.MaxValue, $"The maximum amount of equipment that can be stollen.\nApplied after EquipmentLossChance\nValues between 0-{int.MaxValue}."); } } public class HarmonyPatches { private static readonly Type patchType; static HarmonyPatches() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown patchType = typeof(HarmonyPatches); new Harmony("LethalCompany.MrHydralisk.SaveOurLoot").Patch((MethodBase)AccessTools.Method(typeof(RoundManager), "DespawnPropsAtEndOfRound", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(patchType, "RM_DespawnPropsAtEndOfRound_Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); } public static IEnumerable<CodeInstruction> RM_DespawnPropsAtEndOfRound_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator il) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown int num = -1; int num2 = -1; List<CodeInstruction> list = new List<CodeInstruction>(instructions); for (int i = 0; i < list.Count; i++) { if (!(list[i].opcode == OpCodes.Stloc_0)) { continue; } num = i; for (int j = num + 1; j < list.Count; j++) { if (CodeInstructionExtensions.Is(list[j], OpCodes.Ldstr, (object)"TemporaryEffect")) { num2 = j; break; } } if (num2 > -1) { break; } } if (num > -1 && num2 > -1) { Label label = il.DefineLabel(); list[num2].labels.Add(label); List<CodeInstruction> list2 = new List<CodeInstruction>(); list2.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list2.Add(new CodeInstruction(OpCodes.Ldloc_0, (object)null)); list2.Add(new CodeInstruction(OpCodes.Ldarg_1, (object)null)); list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(HarmonyPatches), "CustomDespawnProps", (Type[])null, (Type[])null))); list2.Add(new CodeInstruction(OpCodes.Brtrue_S, (object)label)); list.InsertRange(num + 1, list2); } return list.AsEnumerable(); } public static bool CustomDespawnProps(RoundManager rManager, GrabbableObject[] gObjects, bool despawnAllItems = false) { if (despawnAllItems) { return false; } Random random = new Random(StartOfRound.Instance.randomMapSeed + 369); gObjects.ToList(); List<GrabbableObject> list = new List<GrabbableObject>(); try { VehicleController[] array = Object.FindObjectsByType<VehicleController>((FindObjectsSortMode)0); foreach (VehicleController val in array) { if (!val.magnetedToShip) { if ((Object)(object)((NetworkBehaviour)val).NetworkObject != (Object)null) { Debug.Log((object)"Despawn vehicle"); ((NetworkBehaviour)val).NetworkObject.Despawn(false); } } else { val.CollectItemsInTruck(); } } } catch (Exception arg) { Debug.LogError((object)$"Error despawning vehicle: {arg}"); } BeltBagItem[] array2 = Object.FindObjectsByType<BeltBagItem>((FindObjectsSortMode)0); foreach (BeltBagItem val2 in array2) { if (Object.op_Implicit((Object)(object)val2.insideAnotherBeltBag) && (((GrabbableObject)val2.insideAnotherBeltBag).isInShipRoom || ((GrabbableObject)val2.insideAnotherBeltBag).isHeld)) { ((GrabbableObject)val2).isInElevator = true; ((GrabbableObject)val2).isInShipRoom = true; } if (((GrabbableObject)val2).isInShipRoom || ((GrabbableObject)val2).isHeld) { for (int k = 0; k < val2.objectsInBag.Count; k++) { val2.objectsInBag[k].isInElevator = true; val2.objectsInBag[k].isInShipRoom = true; } } } foreach (GrabbableObject val3 in gObjects) { if (!((Object)(object)val3 == (Object)null)) { if ((!val3.isInShipRoom && !val3.isHeld) || val3.deactivated) { Plugin.MLogS.LogInfo((object)(((Object)val3).name + " Lost Outside")); DespawnItem(val3); } else { list.Add(val3); } } } ILookup<bool, GrabbableObject> lookup = list.ToLookup((GrabbableObject go) => go.itemProperties.isScrap); List<GrabbableObject> list2 = lookup[true].ToList(); List<GrabbableObject> list3 = lookup[false].ToList(); ConfigEntry<bool> hoardingBugInfestationEnabled = Config.hoardingBugInfestationEnabled; if (hoardingBugInfestationEnabled != null && hoardingBugInfestationEnabled.Value && random.NextDouble() >= (double)(1f - (Config.hoardingBugInfestationChance?.Value ?? 1f))) { List<string> list4 = new List<string>(); ConfigEntry<bool> hoardingBugInfestationValueLossEnabled = Config.hoardingBugInfestationValueLossEnabled; if (hoardingBugInfestationValueLossEnabled != null && hoardingBugInfestationValueLossEnabled.Value) { list2 = list2.OrderByDescending((GrabbableObject go) => go.scrapValue).ToList(); float num = (float)list2.Sum((GrabbableObject go) => go.scrapValue) * (Config.hoardingBugInfestationValueLossPercent?.Value ?? 0.1f); int num2 = 0; foreach (GrabbableObject item in list2) { num2 += item.scrapValue; Plugin.MLogS.LogInfo((object)$"{((Object)item).name} Lost Value Mafia {item.scrapValue}"); list4.Add(item.itemProperties?.itemName ?? ((Object)item).name); DespawnItem(item); if ((float)num2 >= num) { Plugin.MLogS.LogInfo((object)$"{num2} Scrap Value Lost Mafia"); break; } } } else { int num3 = 0; foreach (GrabbableObject item2 in list2) { if (random.NextDouble() >= (double)(1f - (Config.hoardingBugInfestationLossEachChance?.Value ?? 0.1f))) { Plugin.MLogS.LogInfo((object)(((Object)item2).name + " Lost Mafia")); list4.Add(item2.itemProperties?.itemName ?? ((Object)item2).name); DespawnItem(item2); num3++; if (num3 >= (Config.hoardingBugInfestationLossMax?.Value ?? int.MaxValue)) { Plugin.MLogS.LogInfo((object)$"Lost Mafia total {num3}"); break; } } } } ConfigEntry<bool> hoardingBugInfestationEquipmentLossEnabled = Config.hoardingBugInfestationEquipmentLossEnabled; if (hoardingBugInfestationEquipmentLossEnabled != null && hoardingBugInfestationEquipmentLossEnabled.Value) { int num4 = 0; foreach (GrabbableObject item3 in list3) { if (random.NextDouble() >= (double)(1f - (Config.hoardingBugInfestationEquipmentLossChance?.Value ?? 0.05f))) { Plugin.MLogS.LogInfo((object)(((Object)item3).name + " Equipment Lost Mafia")); list4.Add(item3.itemProperties?.itemName ?? ((Object)item3).name); DespawnItem(item3); num4++; if (num4 >= (Config.hoardingBugInfestationEquipmentLossMax?.Value ?? int.MaxValue)) { Plugin.MLogS.LogInfo((object)$"Equipment Lost Mafia total {num4}"); break; } } } } if (list4.Count() > 0) { string text = $"Lost to Bug Mafia ({list4.Count()}/{list.Count()}): "; text += string.Join("; ", from s in list4 group s by s into s select new { name = s.Key, count = s.Count() } into item select (item.count <= 1) ? item.name : $"{item.name} x{item.count}"); ((MonoBehaviour)HUDManager.Instance).StartCoroutine(DisplayAlert("Bug Mafia", "Space ain't no picnic, see? We kept you safe out there, so a little somethin' for our troubles, understand?", text)); } } if (StartOfRound.Instance.allPlayersDead) { if (random.NextDouble() >= (double)(1f - (Config.saveAllChance?.Value ?? 0.25f))) { Plugin.MLogS.LogInfo((object)"All Saved"); ((MonoBehaviour)HUDManager.Instance).StartCoroutine(DisplayAlert("Save Our Loot", "You got lucky. All items was saved.", "You got lucky. All items was saved.")); } else { list2.RemoveAll((GrabbableObject go) => !((NetworkBehaviour)go).IsSpawned); List<string> list5 = new List<string>(); ConfigEntry<bool> valueSaveEnabled = Config.valueSaveEnabled; if (valueSaveEnabled != null && valueSaveEnabled.Value) { list2 = list2.OrderByDescending((GrabbableObject go) => go.scrapValue).ToList(); int num5 = list2.Sum((GrabbableObject go) => go.scrapValue); float num6 = (float)num5 * (Config.valueSavePercent?.Value ?? 0.25f); foreach (GrabbableObject item4 in list2) { num5 -= item4.scrapValue; Plugin.MLogS.LogInfo((object)$"{((Object)item4).name} Lost Value {item4.scrapValue}"); list5.Add(item4.itemProperties?.itemName ?? ((Object)item4).name); DespawnItem(item4); if ((float)num5 < num6) { Plugin.MLogS.LogInfo((object)$"{num5} Scrap Value Saved"); break; } } } else { int num7 = 0; foreach (GrabbableObject item5 in list2) { if (random.NextDouble() >= (double)(1f - (Config.saveEachChance?.Value ?? 0.5f))) { Plugin.MLogS.LogInfo((object)(((Object)item5).name + " Saved")); continue; } Plugin.MLogS.LogInfo((object)(((Object)item5).name + " Lost")); list5.Add(item5.itemProperties?.itemName ?? ((Object)item5).name); DespawnItem(item5); num7++; if (num7 < (Config.scrapLossMax?.Value ?? int.MaxValue)) { continue; } Plugin.MLogS.LogInfo((object)$"Lost total {num7}"); break; } } ConfigEntry<bool> equipmentLossEnabled = Config.equipmentLossEnabled; if (equipmentLossEnabled != null && equipmentLossEnabled.Value) { list3.RemoveAll((GrabbableObject go) => !((NetworkBehaviour)go).IsSpawned); int num8 = 0; foreach (GrabbableObject item6 in list3) { if (random.NextDouble() >= (double)(1f - (Config.equipmentLossChance?.Value ?? 0.1f))) { Plugin.MLogS.LogInfo((object)(((Object)item6).name + " Equipment Lost")); list5.Add(item6.itemProperties?.itemName ?? ((Object)item6).name); DespawnItem(item6); num8++; if (num8 >= (Config.equipmentLossMax?.Value ?? int.MaxValue)) { Plugin.MLogS.LogInfo((object)$"Equipment Lost total {num8}"); break; } } } } if (list5.Count() > 0) { string text2 = $"Lost items ({list5.Count()}/{list.Count()}): "; text2 += string.Join("; ", from s in list5 group s by s into s select new { name = s.Key, count = s.Count() } into item select (item.count <= 1) ? item.name : $"{item.name} x{item.count}"); ((MonoBehaviour)HUDManager.Instance).StartCoroutine(DisplayAlert("Save Our Loot", "Some of your loot was lost.", text2)); } } } return true; void DespawnItem(GrabbableObject gObject) { if (gObject.isHeld && (Object)(object)gObject.playerHeldBy != (Object)null) { gObject.playerHeldBy.DropAllHeldItems(true, false); } ((Component)gObject).gameObject.GetComponent<NetworkObject>().Despawn(true); if (rManager.spawnedSyncedObjects.Contains(((Component)gObject).gameObject)) { rManager.spawnedSyncedObjects.Remove(((Component)gObject).gameObject); } } static IEnumerator DisplayAlert(string headerAlertText = "Save Our Loot", string bodyAlertText = "", string messageText = "") { int index = 0; while (index < 20 && !StartOfRound.Instance.inShipPhase) { index++; yield return (object)new WaitForSeconds(5f); } yield return (object)new WaitForSeconds(2f); if (!string.IsNullOrEmpty(headerAlertText) || !string.IsNullOrEmpty(bodyAlertText)) { HUDManager.Instance.DisplayTip(headerAlertText, bodyAlertText, false, false, "LC_Tip1"); } if (!string.IsNullOrEmpty(messageText)) { HUDManager.Instance.AddTextToChatOnServer(messageText, -1); } } } } [BepInPlugin("MrHydralisk.SaveOurLoot", "Save Our Loot", "1.5.3")] public class Plugin : BaseUnityPlugin { private const string MOD_GUID = "MrHydralisk.SaveOurLoot"; private const string MOD_NAME = "Save Our Loot"; public static Plugin instance; public static ManualLogSource MLogS; public static ConfigFile config; private void Awake() { MLogS = Logger.CreateLogSource("MrHydralisk.SaveOurLoot"); config = ((BaseUnityPlugin)this).Config; Config.Load(); instance = this; try { RuntimeHelpers.RunClassConstructor(typeof(HarmonyPatches).TypeHandle); } catch (Exception ex) { MLogS.LogError((object)string.Concat("Error in static constructor of ", typeof(HarmonyPatches), ": ", ex)); } MLogS.LogInfo((object)"Plugin is loaded!"); } } public static class PluginInfo { public const string PLUGIN_GUID = "SaveOurLoot"; public const string PLUGIN_NAME = "SaveOurLoot"; public const string PLUGIN_VERSION = "1.5.3"; } }