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 CalculateScrapForQuota v1.1.0
CalculateScrapForQuota.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CalculateScrapForQuota.Scripts; using CalculateScrapForQuota.Utils; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("CalculateScrapForQuota")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("A template for Lethal Company")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("CalculateScrapForQuota")] [assembly: AssemblyTitle("CalculateScrapForQuota")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.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 CalculateScrapForQuota { public class Config { private readonly ConfigEntry<bool> _isVerbose; public readonly Color highlightColor; private readonly ConfigEntry<string> _highlightColor; public bool isVerbose => _isVerbose.Value; public Config(ConfigFile cfg) { _isVerbose = cfg.Bind<bool>("General.Debug", "isVerbose", false, "To display plugin logs in console."); _highlightColor = cfg.Bind<string>("General.Settings", "highlightColor", "#00FF00", "The hex color of the highlight material."); ColorUtility.TryParseHtmlString(_highlightColor.Value, ref highlightColor); } } [BepInPlugin("CalculateScrapForQuota", "CalculateScrapForQuota", "1.1.0")] public class Plugin : BaseUnityPlugin { private static ManualLogSource _logger; private static Config MyConfig { get; set; } private void Awake() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"CalculateScrapForQuota v1.1.0 is loaded!"); _logger = ((BaseUnityPlugin)this).Logger; MyConfig = new Config(((BaseUnityPlugin)this).Config); MaterialSwapper.swapColor = MyConfig.highlightColor; Harmony val = new Harmony("CalculateScrapForQuota"); val.PatchAll(Assembly.GetExecutingAssembly()); } internal static void Log(string m) { if (MyConfig.isVerbose) { _logger.LogMessage((object)m); } } } public static class PluginInfo { public const string PLUGIN_GUID = "CalculateScrapForQuota"; public const string PLUGIN_NAME = "CalculateScrapForQuota"; public const string PLUGIN_VERSION = "1.1.0"; } } namespace CalculateScrapForQuota.Utils { public static class DebugUtil { private const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; public static string GetGameObjectDetails(GameObject gameObject, bool ignoreProperties = false, bool ignoreFields = false) { string text = "--- GameObject Info"; text = text + "\nName: " + ((Object)gameObject).name; Component[] components = gameObject.GetComponents<Component>(); foreach (Component val in components) { text = text + "\n Component: " + ((object)val).GetType().Name; if (!ignoreProperties) { PropertyInfo[] properties = ((object)val).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { text += $"\n Property: {propertyInfo.Name}, Value: {propertyInfo.GetValue(val, null)}"; } } if (!ignoreFields) { FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { text += $"\n Field: {fieldInfo.Name}, Value: {fieldInfo.GetValue(val)}"; } } } return text; } } public class MathUtil { public static (List<T> combination, int totalValue) FindBestCombination<T>(List<T> items, int quota, Func<T, int> valueSelector) { if (items == null) { throw new ArgumentNullException("items"); } if (valueSelector == null) { throw new ArgumentNullException("valueSelector"); } if (quota < 0) { throw new ArgumentException("Quota cannot be negative.", "quota"); } int count = items.Count; int num = items.Sum((T item) => valueSelector(item)); int[,] array = new int[count + 1, num + 1]; for (int i = 0; i <= count; i++) { for (int j = 0; j <= num; j++) { if (i == 0 || j == 0) { array[i, j] = 0; continue; } int num2 = valueSelector(items[i - 1]); if (num2 <= j) { array[i, j] = Math.Max(array[i - 1, j], array[i - 1, j - num2] + num2); } else { array[i, j] = array[i - 1, j]; } } } int num3 = 0; for (int k = quota; k <= num; k++) { if (array[count, k] >= quota) { num3 = k; break; } } List<T> list = new List<T>(); int num4 = count; int num5 = num3; while (num4 > 0 && num5 > 0) { if (array[num4, num5] != array[num4 - 1, num5]) { list.Add(items[num4 - 1]); num5 -= valueSelector(items[num4 - 1]); } num4--; } list.Reverse(); return (list, num3); } } } namespace CalculateScrapForQuota.Scripts { public static class Materials { private static Shader HDRP_LIT_SHADER = Shader.Find("HDRP/Lit"); private static Material _highlightMaterialHDRP; private static Shader SRP_SHADER = Shader.Find("Standard"); private static Material _highlightMaterialSRP; public static Material HighlightMaterial { get { if (Object.op_Implicit((Object)(object)HDRP_LIT_SHADER)) { return HighlightMaterialHDRP; } if (Object.op_Implicit((Object)(object)SRP_SHADER)) { return HighlightMaterialSRP; } throw new Exception(); } } private static Material HighlightMaterialHDRP { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if ((Object)(object)_highlightMaterialHDRP != (Object)null) { return _highlightMaterialHDRP; } _highlightMaterialHDRP = new Material(HDRP_LIT_SHADER); _highlightMaterialHDRP.shader = HDRP_LIT_SHADER; _highlightMaterialHDRP.SetFloat("_SurfaceType", 1f); _highlightMaterialHDRP.SetFloat("_BlendMode", 0f); _highlightMaterialHDRP.SetFloat("_AlphaCutoffEnable", 0f); _highlightMaterialHDRP.SetFloat("_DstBlend", 10f); _highlightMaterialHDRP.SetFloat("_ZWrite", 0f); _highlightMaterialHDRP.SetFloat("_TransparentZWrite", 0f); _highlightMaterialHDRP.SetFloat("_TransparentCullMode", 0f); _highlightMaterialHDRP.SetFloat("_TransparentSortPriority", 0f); _highlightMaterialHDRP.SetFloat("_CullModeForward", 0f); return _highlightMaterialHDRP; } } private static Material HighlightMaterialSRP { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if ((Object)(object)_highlightMaterialSRP != (Object)null) { return _highlightMaterialSRP; } _highlightMaterialSRP = new Material(SRP_SHADER); _highlightMaterialSRP.shader = SRP_SHADER; _highlightMaterialSRP.SetFloat("_Mode", 3f); _highlightMaterialSRP.SetInt("_SrcBlend", 1); _highlightMaterialSRP.SetInt("_DstBlend", 10); _highlightMaterialSRP.SetInt("_ZWrite", 0); _highlightMaterialSRP.DisableKeyword("_ALPHATEST_ON"); _highlightMaterialSRP.EnableKeyword("_ALPHABLEND_ON"); _highlightMaterialSRP.DisableKeyword("_ALPHAPREMULTIPLY_ON"); _highlightMaterialSRP.renderQueue = 3000; return _highlightMaterialSRP; } } } public static class MaterialSwapper { private class Visuals { private readonly List<Component> _rootOtherComponents; private List<Transform> Transforms { get; } = new List<Transform>(); private List<MeshFilter> MeshFilters { get; } = new List<MeshFilter>(); private List<MeshRenderer> MeshRenderers { get; } = new List<MeshRenderer>(); private List<SkinnedMeshRenderer> SkinnedMeshRenderers { get; } = new List<SkinnedMeshRenderer>(); public List<Renderer> Renderers { get { List<Renderer> list = new List<Renderer>((IEnumerable<Renderer>)MeshRenderers); list.AddRange((IEnumerable<Renderer>)SkinnedMeshRenderers); return list; } } public Visuals(GameObject gameObject) { _rootOtherComponents = gameObject.GetComponentsInChildren<Component>().ToList(); Transform[] componentsInChildren = gameObject.GetComponentsInChildren<Transform>(); foreach (Transform item in componentsInChildren) { Transforms.Add(item); _rootOtherComponents.Remove((Component)(object)item); } MeshFilter[] componentsInChildren2 = gameObject.GetComponentsInChildren<MeshFilter>(); foreach (MeshFilter item2 in componentsInChildren2) { MeshFilters.Add(item2); _rootOtherComponents.Remove((Component)(object)item2); } MeshRenderer[] componentsInChildren3 = gameObject.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer item3 in componentsInChildren3) { MeshRenderers.Add(item3); _rootOtherComponents.Remove((Component)(object)item3); } SkinnedMeshRenderer[] componentsInChildren4 = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer item4 in componentsInChildren4) { SkinnedMeshRenderers.Add(item4); _rootOtherComponents.Remove((Component)(object)item4); } foreach (MeshFilter meshFilter in MeshFilters) { Plugin.Log("Preserving mesh '" + ((Object)meshFilter.mesh).name + "'"); } } public void DestroyNonVisuals() { foreach (Component rootOtherComponent in _rootOtherComponents) { Object.Destroy((Object)(object)rootOtherComponent); } _rootOtherComponents.Clear(); } } private class SwapObject { private readonly Visuals _rootVisuals; private readonly GameObject _cloneGO; private readonly Visuals _cloneVisuals; public SwapObject(GameObject original) { _cloneGO = Clone(original); _rootVisuals = new Visuals(original); _cloneVisuals = new Visuals(_cloneGO); CleanUpClone(); } private void CleanUpClone() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) _cloneVisuals.DestroyNonVisuals(); foreach (Renderer renderer in _cloneVisuals.Renderers) { for (int i = 0; i < renderer.materials.Length; i++) { renderer.materials[i] = swapMaterial; renderer.materials[i].color = new Color(swapColor.r, swapColor.g, swapColor.b); } } } public void Swap(bool on) { foreach (Renderer renderer in _rootVisuals.Renderers) { renderer.enabled = !on; } foreach (Renderer renderer2 in _cloneVisuals.Renderers) { renderer2.enabled = on; renderer2.rendererPriority = (on ? 69420 : (-69420)); } } public void Dispose() { if ((Object)(object)_cloneGO != (Object)null) { Object.Destroy((Object)(object)_cloneGO); } } } public static Material swapMaterial = Materials.HighlightMaterial; public static Color swapColor = Color.green; private static Dictionary<GameObject, SwapObject> pool = new Dictionary<GameObject, SwapObject>(); public static void SwapOn(List<GameObject> gameObjects) { foreach (GameObject gameObject in gameObjects) { Add(gameObject); pool[gameObject].Swap(on: true); } } public static void SwapOff() { foreach (KeyValuePair<GameObject, SwapObject> item in pool) { if ((Object)(object)item.Key == (Object)null) { item.Value.Dispose(); pool.Remove(item.Key); } else { item.Value.Swap(on: false); } } } private static void Add(GameObject original) { if (!pool.ContainsKey(original)) { pool.Add(original, new SwapObject(original)); } } public static void Clear() { SwapOff(); foreach (SwapObject value in pool.Values) { value.Dispose(); } pool.Clear(); } private static GameObject Clone(GameObject parent) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(parent, parent.transform.position, parent.transform.rotation); val.transform.localScale = parent.transform.localScale; val.transform.SetParent(parent.transform); ((Object)val).name = ((Object)parent).name + " (Clone for swap)"; Plugin.Log("Made '" + ((Object)val).name + "' \nAnd parented it to " + ((Object)parent).name); return val; } } } namespace CalculateScrapForQuota.Patches { [HarmonyPatch] public class GrabbableObjectPatch { [HarmonyPostfix] [HarmonyPatch(typeof(GrabbableObject), "EnableItemMeshes")] private static void EnableItemMeshes(GrabbableObject __instance, bool enable) { Plugin.Log("EnableItemMeshes() called."); GameObject gameObject = ((Component)__instance).gameObject; if (HudManagerPatch.CurrentHighlight.Contains(gameObject) && enable) { List<GameObject> list = new List<GameObject>(); list.Add(gameObject); MaterialSwapper.SwapOn(list); } } } [HarmonyPatch] public class HudManagerPatch { public static List<GameObject> CurrentHighlight = new List<GameObject>(); public static bool toggled = false; private static GameObject _textGO; private static TextMeshProUGUI _textMesh; private static GameObject shipGO => GameObject.Find("/Environment/HangarShip"); private static GameObject valueCounterGO => GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/ValueCounter"); private static int unmetQuota => Math.Max(0, TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled); private static double buyingRate => isAtCompany ? ((double)StartOfRound.Instance.companyBuyingRate) : 1.0; private static bool isAtCompany => StartOfRound.Instance.currentLevel.levelID == 3; private static bool isInShip => GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom; private static bool isScanning(HUDManager instance) { return (double)(float)typeof(HUDManager).GetField("playerPingingScan", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance) > -1.0; } private static bool canPlayerScan(HUDManager instance) { return (bool)typeof(HUDManager).GetMethod("CanPlayerScan", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(instance, null); } [HarmonyPrefix] [HarmonyPatch(typeof(HUDManager), "PingScan_performed")] private static void OnScan(HUDManager __instance, CallbackContext context) { Plugin.Log("OnScan() called."); if (!((CallbackContext)(ref context)).performed || isScanning(__instance) || !canPlayerScan(__instance) || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return; } Plugin.Log("OnScan() is valid."); CurrentHighlight.Clear(); toggled = !toggled; if (toggled) { List<GrabbableObject> items; if (isInShip && !isAtCompany) { items = GetSellableGrabbablesInChildren(shipGO); } else { if (!isAtCompany) { return; } items = GetAllSellableObjects(); } (List<GrabbableObject>, int) tuple = MathUtil.FindBestCombination(items, unmetQuota, ValueCalculation); if (tuple.Item2 >= unmetQuota) { CurrentHighlight = tuple.Item1.Select((GrabbableObject g) => ((Component)g).gameObject).ToList(); SetupText(tuple.Item2); MaterialSwapper.SwapOn(CurrentHighlight); } } else { SetupText(); MaterialSwapper.SwapOff(); MaterialSwapper.Clear(); } static int ValueCalculation(GrabbableObject grabbable) { return isAtCompany ? ((int)((double)grabbable.scrapValue * buyingRate)) : grabbable.scrapValue; } } private static List<GrabbableObject> GetAllSellableObjects() { GrabbableObject[] source = Object.FindObjectsOfType<GrabbableObject>(); return source.Where(IsGrabbableSellable).ToList(); } private static List<GrabbableObject> GetSellableGrabbablesInChildren(GameObject GO) { GrabbableObject[] componentsInChildren = GO.GetComponentsInChildren<GrabbableObject>(); return componentsInChildren.Where(IsGrabbableSellable).ToList(); } private static bool IsGrabbableSellable(GrabbableObject grabbable) { return grabbable.itemProperties.isScrap && !grabbable.isPocketed && grabbable.scrapValue > 0 && ((Object)grabbable).name != "ClipboardManual" && ((Object)grabbable).name != "StickyNoteItem" && ((Object)grabbable).name != "Gift" && ((Object)grabbable).name != "Shotgun" && ((Object)grabbable).name != "Ammo"; } private static void SetupText(int totalValue = -1) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_textGO)) { _textGO = Object.Instantiate<GameObject>(valueCounterGO.gameObject, valueCounterGO.transform.parent, false); _textGO.transform.Translate(0f, 1f, 0f); Vector3 localPosition = _textGO.transform.localPosition; _textGO.transform.localPosition = new Vector3(localPosition.x + 50f, -100f, localPosition.z); _textMesh = _textGO.GetComponentInChildren<TextMeshProUGUI>(); ((TMP_Text)_textMesh).fontSize = 12f; } if (totalValue > 0) { _textGO.SetActive(true); ((TMP_Text)_textMesh).text = $"Optimal: {totalValue}"; } else { _textGO.SetActive(false); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }