Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of Lithium v1.4.0
mods/Lithium.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using HarmonyLib; using Il2Cpp; using Il2CppFishNet; using Il2CppFishNet.Connection; using Il2CppFishNet.Object; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.Building.Doors; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Dialogue; using Il2CppScheduleOne.Doors; using Il2CppScheduleOne.Economy; using Il2CppScheduleOne.Effects; using Il2CppScheduleOne.Employees; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.GameTime; using Il2CppScheduleOne.Growing; using Il2CppScheduleOne.Interaction; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Law; using Il2CppScheduleOne.Levelling; using Il2CppScheduleOne.Management; using Il2CppScheduleOne.Map; using Il2CppScheduleOne.Messaging; using Il2CppScheduleOne.Misc; using Il2CppScheduleOne.Money; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.NPCs.Behaviour; using Il2CppScheduleOne.NPCs.CharacterClasses; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.Packaging; using Il2CppScheduleOne.Persistence; using Il2CppScheduleOne.Persistence.Datas; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.Police; using Il2CppScheduleOne.Product; using Il2CppScheduleOne.Product.Packaging; using Il2CppScheduleOne.Property; using Il2CppScheduleOne.Quests; using Il2CppScheduleOne.StationFramework; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.Tiles; using Il2CppScheduleOne.Trash; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.ATM; using Il2CppScheduleOne.UI.Handover; using Il2CppScheduleOne.UI.Items; using Il2CppScheduleOne.UI.Phone; using Il2CppScheduleOne.UI.Phone.ContactsApp; using Il2CppScheduleOne.UI.Phone.Delivery; using Il2CppScheduleOne.UI.Phone.Messages; using Il2CppScheduleOne.UI.Phone.ProductManagerApp; using Il2CppScheduleOne.UI.Shop; using Il2CppScheduleOne.UI.Stations; using Il2CppScheduleOne.UI.Stations.Drying_rack; using Il2CppScheduleOne.Variables; using Il2CppScheduleOne.Vehicles; using Il2CppScheduleOne.Vehicles.Modification; using Il2CppScheduleOne.Vision; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using Il2CppTMPro; using Lithium; using Lithium.Helper; using Lithium.Modules; using Lithium.Modules.Banking; using Lithium.Modules.BrickPress; using Lithium.Modules.ChemistryStation; using Lithium.Modules.Customers; using Lithium.Modules.Customers.Architecture; using Lithium.Modules.Customers.Behaviours; using Lithium.Modules.Customers.BonusPayments; using Lithium.Modules.Customers.Patches; using Lithium.Modules.Dealers; using Lithium.Modules.Dealers.Architecture; using Lithium.Modules.DryingRacks; using Lithium.Modules.EffectCombos; using Lithium.Modules.EffectCombos.BonusPayments; using Lithium.Modules.ElectricBill; using Lithium.Modules.Employees; using Lithium.Modules.Employees.ProductionOrders; using Lithium.Modules.EndOfDayFreeze; using Lithium.Modules.LabOven; using Lithium.Modules.MixingStations; using Lithium.Modules.PhoneApp; using Lithium.Modules.PlantGrowth; using Lithium.Modules.PlantGrowth.Behaviours; using Lithium.Modules.Police; using Lithium.Modules.Police.Contraband; using Lithium.Modules.Police.PoliceEntry; using Lithium.Modules.Police.PropertyContraband; using Lithium.Modules.Products; using Lithium.Modules.PropertyPrices; using Lithium.Modules.Rent; using Lithium.Modules.Repairs; using Lithium.Modules.Shops; using Lithium.Modules.StackSizes; using Lithium.Modules.Storyline; using Lithium.Modules.TrashGrabber; using Lithium.Modules.Vehicles; using Lithium.Modules.Warehouse; using Lithium.Modules.WateringCans; using Lithium.Modules.Weapons; using Lithium.Util; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Core), "Lithium", "1.4.0", "DerTomDer & YukiSora", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: MelonOptionalDependencies(new string[] { "ModManager&PhoneApp" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Lithium")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+e2be586eaee486cf2bafe4d9e662842f5c3fc404")] [assembly: AssemblyProduct("Lithium")] [assembly: AssemblyTitle("Lithium")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [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 Lithium { public class Core : MelonMod { public static readonly List<ModuleBase> Modules = new List<ModuleBase>(27) { new ModPropertyPrices(), new ModPlants(), new ModDryingRacks(), new ModCustomers(), new ModStackSizes(), new ModLabOven(), new ModTrashGrabber(), new ModMixingStations(), new ModStoryline(), new ModShops(), new ModEmployees(), new ModChemistryStation(), new ModWateringCan(), new ModEffectCombos(), new ModVehicles(), new ModEndOfDayFreeze(), new ModProducts(), new ModBanking(), new ModElectricBill(), new ModRent(), new ModBrickPress(), new ModDealers(), new ModRepairs(), new ModWeapons(), new ModWarehouse(), new ModPolice(), new ModPhoneApp() }; private bool _isFirstStart = true; public static Instance Logger { get; set; } public static bool IsInMainScene { get; private set; } public static T Get<T>() where T : ModuleBase { return Modules.OfType<T>().FirstOrDefault(); } public override void OnInitializeMelon() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown Logger = ((MelonBase)this).LoggerInstance; LithiumConfig.Load(); foreach (ModuleBase module in Modules) { Log.Info("Loading " + module.GetType().Name); module.Load(); } Harmony val = new Harmony("com.lithium"); val.PatchAll(); LithiumModMenu.Initialize(); Log.Info("Lithium initialized"); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if (sceneName == "Main") { foreach (ModuleBase module in Modules) { Log.Info("Loading " + module.GetType().Name); module.Apply(); } _isFirstStart = false; IsInMainScene = true; } else if (sceneName.Equals("Menu", StringComparison.OrdinalIgnoreCase) && !_isFirstStart) { _isFirstStart = true; IsInMainScene = false; } } public override void OnPreferencesSaved() { LithiumModMenu.OnPreferencesSaved(); } public static void ReloadConfiguration() { Log.Warning("[Lithium] Reloading all configuration..."); LithiumConfig.Load(); foreach (ModuleBase module in Modules) { try { module.Load(); } catch (Exception value) { Log.Error($"[Lithium] {module.GetType().Name}.Load() failed during reload: {value}"); } } if (IsInMainScene) { foreach (ModuleBase module2 in Modules) { try { module2.Apply(); } catch (Exception value2) { Log.Error($"[Lithium] {module2.GetType().Name}.Apply() failed during reload: {value2}"); } } } Log.Warning(IsInMainScene ? "[Lithium] Configuration reloaded and reapplied." : "[Lithium] Configuration reloaded (no save loaded — runtime reapply skipped)."); } public override void OnUpdate() { ((MelonBase)this).OnUpdate(); Get<ModPhoneApp>()?.DriveUpdate(); Get<ModPolice>()?.DriveUpdate(); Get<ModElectricBill>()?.DriveUpdate(); Get<ModRent>()?.DriveUpdate(); Get<ModProducts>()?.DriveUpdate(); Get<ModEmployees>()?.DriveUpdate(); } } public class LithiumConfig { public bool Debug = false; public static LithiumConfig Instance { get; private set; } = new LithiumConfig(); private static string ConfigFolder => Path.Combine(MelonEnvironment.UserDataDirectory, "Lithium"); private static string FilePath => Path.Combine(ConfigFolder, "Lithium.json"); public static void Load() { try { if (File.Exists(FilePath)) { JsonConvert.PopulateObject(File.ReadAllText(FilePath), (object)Instance); } Save(); } catch (Exception ex) { MelonLogger.Warning("[Lithium] Failed to load Lithium.json: " + ex.Message); } } public static void Save() { try { Directory.CreateDirectory(ConfigFolder); File.WriteAllText(FilePath, JsonConvert.SerializeObject((object)Instance, (Formatting)1)); } catch (Exception ex) { MelonLogger.Warning("[Lithium] Failed to save Lithium.json: " + ex.Message); } } } public static class LithiumModMenu { private sealed class Tool { public readonly string Name; public readonly bool RequiresSave; public readonly Action Run; public Tool(string name, bool requiresSave, Action run) { Name = name; RequiresSave = requiresSave; Run = run; } } private const string GeneralId = "Lithium_General"; private static MelonPreferences_Category _generalCategory; private static MelonPreferences_Entry<bool> _debugEntry; private static readonly List<Tool> Tools = new List<Tool>(); private static readonly List<Action> RootedHandlers = new List<Action>(); public static void Initialize() { try { _generalCategory = MelonPreferences.CreateCategory("Lithium_General", "Lithium - General"); _debugEntry = _generalCategory.CreateEntry<bool>("Debug", LithiumConfig.Instance.Debug, "Debug logging", "Verbose Log.Info output to the MelonLoader console.", false, false, (ValueValidator)null, (string)null); _debugEntry.Value = LithiumConfig.Instance.Debug; _generalCategory.SaveToFile(false); BuildToolTable(); TryHookModManager(); Log.Info("[Lithium] Mod Manager menu initialized."); } catch (Exception value) { Log.Error($"[Lithium] Mod Manager menu init failed: {value}"); } } private static void BuildToolTable() { Tools.Clear(); Tools.Add(new Tool("Reload & reapply all configs", requiresSave: false, Core.ReloadConfiguration)); Tools.Add(new Tool("Dump rent / dead-drop info", requiresSave: true, RentDebug.Dump)); Tools.Add(new Tool("Dump buildables / appliances", requiresSave: true, BuildablesDebug.Dump)); Tools.Add(new Tool("Dump RV furniture", requiresSave: true, RVFurnitureDebug.Dump)); Tools.Add(new Tool("Dump customer order patterns", requiresSave: true, OrderPatternDebug.Dump)); Tools.Add(new Tool("Dump NPC roster", requiresSave: true, NpcRosterDebug.Dump)); Tools.Add(new Tool("Dump police contraband scan", requiresSave: true, PoliceContrabandDebug.Dump)); Tools.Add(new Tool("Expand Veeper storage", requiresSave: true, ExpandVeeperStorage)); Tools.Add(new Tool("Toggle rent lockout (test)", requiresSave: true, delegate { Core.Get<ModRent>()?.DebugToggleLockout(); })); } public static void OnPreferencesSaved() { if (_debugEntry != null && _debugEntry.Value != LithiumConfig.Instance.Debug) { LithiumConfig.Instance.Debug = _debugEntry.Value; LithiumConfig.Save(); Log.Warning("[Lithium] Debug logging " + (_debugEntry.Value ? "enabled" : "disabled") + " via Mod Manager."); } } private static void TryHookModManager() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("ModManagerPhoneApp.ModSettingsAppCreator"); if (type == null) { Log.Info("[Lithium] ModManager app not installed — tool buttons unavailable."); return; } MethodInfo methodInfo = AccessTools.Method(type, "PopulateModSettings", (Type[])null, (Type[])null); if (methodInfo == null) { Log.Warning("[Lithium] ModManager.PopulateModSettings not found — tool buttons unavailable."); return; } MethodInfo method = typeof(LithiumModMenu).GetMethod("InjectToolButtons", BindingFlags.Static | BindingFlags.NonPublic); new Harmony("com.lithium.modmenu").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.Info("[Lithium] ModManager tool-button hook applied."); } catch (Exception ex) { Log.Warning("[Lithium] Could not hook the ModManager UI: " + ex.Message); } } private static void InjectToolButtons(object __instance, MelonBase __0) { //IL_017e: Unknown result type (might be due to invalid IL or missing references) try { object obj; if (__0 == null) { obj = null; } else { MelonInfoAttribute info = __0.Info; obj = ((info != null) ? info.Name : null); } if ((string?)obj != "Lithium") { return; } GameObject value = Traverse.Create(__instance).Field("modManagerAppInstance").GetValue<GameObject>(); if ((Object)(object)value == (Object)null) { return; } Transform val = value.transform.Find("RightPanel/ConfigPanel/Viewport/Content"); Transform val2 = value.transform.Find("RightPanel/SaveButton"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } RootedHandlers.Clear(); GameObject value2 = Traverse.Create(__instance).Field("categoryTemplate").GetValue<GameObject>(); if ((Object)(object)value2 != (Object)null) { GameObject val3 = Object.Instantiate<GameObject>(value2, val); ((Object)val3).name = "Lithium_ToolsHeader"; Transform val4 = val3.transform.Find("Title"); if ((Object)(object)val4 != (Object)null) { TMP_Text component = ((Component)val4).GetComponent<TMP_Text>(); if ((Object)(object)component != (Object)null) { component.SetText("Debug Tools (press to run)"); } } val3.SetActive(true); } foreach (Tool tool in Tools) { GameObject val5 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val); ((Object)val5).name = "Lithium_Tool_" + tool.Name; val5.transform.localScale = Vector3.one; Button component2 = val5.GetComponent<Button>(); if ((Object)(object)component2 == (Object)null) { Object.Destroy((Object)(object)val5); continue; } ((UnityEventBase)component2.onClick).RemoveAllListeners(); TMP_Text componentInChildren = val5.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.SetText(tool.Name); componentInChildren.enableAutoSizing = true; componentInChildren.fontSizeMin = 6f; } LayoutElement val6 = val5.GetComponent<LayoutElement>(); if ((Object)(object)val6 == (Object)null) { val6 = val5.AddComponent<LayoutElement>(); } val6.minHeight = 48f; val6.preferredHeight = 48f; val6.flexibleWidth = 1f; Tool captured = tool; Action action = delegate { RunTool(captured); }; RootedHandlers.Add(action); ((UnityEvent)component2.onClick).AddListener(UnityAction.op_Implicit(action)); val5.SetActive(true); } } catch (Exception value3) { Log.Error($"[Lithium] Injecting tool buttons failed: {value3}"); } } private static void RunTool(Tool tool) { if (tool.RequiresSave && !Core.IsInMainScene) { Log.Warning("[Lithium] '" + tool.Name + "' needs a loaded save — load a game first."); return; } try { Log.Warning("[Lithium] Running '" + tool.Name + "' from Mod Manager."); tool.Run(); } catch (Exception value) { Log.Error($"[Lithium] '{tool.Name}' failed: {value}"); } } private static void ExpandVeeperStorage() { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown LandVehicle[] array = (from v in (IEnumerable<LandVehicle>)NetworkSingleton<VehicleManager>.Instance.AllVehicles.ToArray() where v.IsPlayerOwned where v.VehicleCode == "veeper" select v).ToArray(); LandVehicle[] array2 = array; foreach (LandVehicle val in array2) { val.Storage.SlotCount = 20; for (int num2 = val.Storage.ItemSlots.Count; num2 <= val.Storage.SlotCount; num2++) { val.Storage.ItemSlots.Add(new ItemSlot()); } } } } public static class Log { public static bool DebugEnabled => LithiumConfig.Instance.Debug; public static void Info(string message) { if (LithiumConfig.Instance.Debug) { MelonLogger.Msg(message); } } public static void Warning(string message) { MelonLogger.Warning(message); } public static void Error(string message) { MelonLogger.Error(message); } } } namespace Lithium.Util { public static class DeliveryUtils { public static void ApplyDeliveryOverrides() { Dictionary<string, DeliveryShop> dictionary = (from s in ((IEnumerable<DeliveryShop>)Object.FindObjectsOfType<DeliveryShop>(true)).ToList() where (Object)(object)s != (Object)null && (Object)(object)s.MatchingShop != (Object)null select s).ToDictionary((DeliveryShop s) => s.MatchingShop.ShopName, (DeliveryShop s) => s); ModShopsConfiguration configuration = Core.Get<ModShops>().Configuration; foreach (KeyValuePair<string, DeliverySettings> delivery in configuration.Deliveries) { if (!dictionary.TryGetValue(delivery.Key, out var value)) { continue; } bool flag; switch (delivery.Value.Availability) { case DeliveryAvailabilitySettings.Unchanged: switch (value.MatchingShop.ShopName) { case "Albert Hoover": { Albert val3 = Object.FindObjectOfType<Albert>(); value.AvailableByDefault = ((NPC)val3).RelationData.RelationDelta > Supplier.DELIVERY_RELATIONSHIP_REQUIREMENT; break; } case "Shirley Watts": { Shirley val2 = Object.FindObjectOfType<Shirley>(); value.AvailableByDefault = ((NPC)val2).RelationData.RelationDelta > Supplier.DELIVERY_RELATIONSHIP_REQUIREMENT; break; } case "Salvador Moreno": { Salvador val = Object.FindObjectOfType<Salvador>(); value.AvailableByDefault = ((NPC)val).RelationData.RelationDelta > Supplier.DELIVERY_RELATIONSHIP_REQUIREMENT; break; } } continue; case DeliveryAvailabilitySettings.Never: flag = false; break; case DeliveryAvailabilitySettings.Always: flag = true; break; case DeliveryAvailabilitySettings.AfterReachingXP: flag = NetworkSingleton<LevelManager>.Instance.TotalXP >= delivery.Value.XPRequirement; break; default: throw new ArgumentOutOfRangeException(); } value.AvailableByDefault = flag; if ((Object)(object)value.DeliveryFeeLabel != (Object)null) { value.DeliveryFeeLabel.text = $"${delivery.Value.DeliveryFee}"; } ((Component)value).gameObject.SetActive(flag); } } } public static class SuccessChanceCalculator { public static float CalculateSuccess(EDrugType drugType, EQuality quality, float qualityLevelModifier, ECustomerStandard standard, string[] desires, string[] effects, CustomerAffinityData affinities, bool includeDrugPreference, float baseAcceptance, bool requireEffectMatch, int maxQualityOverDeliveryLevels, float drugAffinitySharpness) { //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected I4, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) float num2; if (desires.Length != 0) { int num = 0; foreach (string item in desires.Where((string d) => !string.IsNullOrEmpty(d))) { num += (((ReadOnlySpan<string>)effects).Contains(item) ? 1 : 0); } if (requireEffectMatch && num == 0) { Log.Info("Sample offering: covers no desired effects - rejected (effect match required)."); return 0f; } num2 = (float)num / (float)desires.Length; Log.Info($"Sample offering: Covered {num} desires. Base acceptance {num2 * 100f:F1}%"); } else { Log.Info("Sample offering: No desired. Base acceptance 100%"); num2 = 1f; } int num3 = quality - standard; int num4 = ((num3 > 0) ? Math.Min(num3, maxQualityOverDeliveryLevels) : num3); Log.Info($"Sample offering: Quality difference {num3} levels (effective {num4})"); num2 += qualityLevelModifier * (float)num4; Log.Info($"Adjusted acceptance: {num2 * 100f:F1}%"); if (includeDrugPreference) { Enumerator<ProductTypeAffinity> enumerator2 = affinities.ProductAffinities.GetEnumerator(); while (enumerator2.MoveNext()) { ProductTypeAffinity current2 = enumerator2.Current; if (current2.DrugType == drugType) { float affinity = current2.Affinity; float num5 = ((affinity <= 0f) ? 0f : Mathf.Pow(Mathf.Clamp01(affinity), drugAffinitySharpness)); Log.Info($"Sample offering: Drug affinity {affinity:0.##} -> factor {num5 * 100f:F1}%"); num2 *= num5; break; } } } num2 += baseAcceptance; Log.Info($"Sample offering: Final acceptance is {Mathf.Clamp01(num2):F1}%"); return Mathf.Clamp01(num2); } } public class WeightedNormalizer { private readonly List<float> _weights = new List<float>(); private readonly List<float> _values = new List<float>(); private readonly List<float> _cdf = new List<float>(); private bool _isInitialized; public void Add(float weight, float value) { if (weight < 0f) { throw new ArgumentOutOfRangeException("weight", "Weight must be non-negative."); } _weights.Add(weight); _values.Add(value); _isInitialized = false; } private void Initialize() { _cdf.Clear(); float num = _weights.Sum(); if (num == 0f) { _cdf.Clear(); _cdf.Add(1f); _isInitialized = true; return; } float num2 = 0f; foreach (float weight in _weights) { num2 += weight / num; _cdf.Add(num2); } _isInitialized = true; } public float Evaluate(float n) { if (!_isInitialized) { Initialize(); } if (_values.Count == 0) { throw new InvalidOperationException("No values added to normalize."); } float num = n; float num2 = num; if (!(num2 <= 0f)) { if (num2 >= 1f) { List<float> values = _values; return values[values.Count - 1]; } int num3 = _cdf.FindIndex((float x) => x > n); switch (num3) { case -1: { List<float> values2 = _values; return values2[values2.Count - 1]; } case 0: return _values[0]; default: { int index = num3 - 1; float num4 = _cdf[index]; float num5 = _cdf[num3]; float num6 = (n - num4) / (num5 - num4); float num7 = _values[index]; float num8 = _values[num3]; return num7 + (num8 - num7) * num6; } } } return _values[0]; } } public class PickerEmptyException : Exception { } public class WeightedPicker<T> { private readonly Random _random; private bool _hasChanged; private readonly Dictionary<T, float> _dictionary = new Dictionary<T, float>(); private double _totalWeight; public int Count => _dictionary.Count; public float this[T key] { get { return _dictionary[key]; } set { _dictionary[key] = value; _hasChanged = true; } } public WeightedPicker(Random random) { _random = random; } public WeightedPicker() : this(new Random(Guid.NewGuid().GetHashCode())) { } public T Pick() { if (_hasChanged) { Rebuild(); } float value = (float)_random.Next((int)(_totalWeight * 100.0)) / 100f; return PickManually(value); } public T PickManually(float value) { if (_hasChanged) { Rebuild(); } value = Math.Min((float)_totalWeight, Math.Max(0f, value)); float num = 0f; KeyValuePair<T, float>? keyValuePair = null; foreach (KeyValuePair<T, float> item in _dictionary) { if (num > value) { break; } keyValuePair = item; num += item.Value; } if (!keyValuePair.HasValue) { throw new PickerEmptyException(); } return keyValuePair.Value.Key; } private void Rebuild() { _totalWeight = _dictionary.Values.Sum(); _hasChanged = false; } public void Add(T value, float weight) { _dictionary.Add(value, weight); _hasChanged = true; } public void AddRange(IEnumerable<KeyValuePair<T, float>> entries) { foreach (KeyValuePair<T, float> entry in entries) { _dictionary.Add(entry.Key, entry.Value); } _hasChanged = true; } public bool Remove(T key) { _hasChanged = true; return _dictionary.Remove(key); } public void Clear() { _dictionary.Clear(); _hasChanged = true; } } } namespace Lithium.Modules { public abstract class ModuleBase { public abstract void Load(); public abstract void Apply(); } public abstract class ModuleBase<TConfiguration> : ModuleBase where TConfiguration : ModuleConfiguration { public TConfiguration Configuration { get; private set; } protected virtual void OnBeforeConfigurationLoaded() { } public override void Load() { Configuration = Activator.CreateInstance<TConfiguration>(); OnBeforeConfigurationLoaded(); Configuration.LoadConfiguration(); Configuration.Validate(); } } public abstract class ModuleConfiguration { private static readonly string ConfigFolder = Path.Combine(MelonEnvironment.UserDataDirectory, "Lithium"); [JsonProperty(Order = -500)] public bool Enabled; [JsonIgnore] public abstract string Name { get; } public string GetConfigFile() { return Path.Combine(ConfigFolder, Name + ".json"); } public virtual void Validate() { } public void SaveConfiguration() { if (!Directory.Exists(ConfigFolder)) { Directory.CreateDirectory(ConfigFolder); } string configFile = GetConfigFile(); string contents = JsonConvert.SerializeObject((object)this, (Formatting)1); File.WriteAllText(configFile, contents); } public void LoadConfiguration() { string configFile = GetConfigFile(); if (File.Exists(configFile)) { string text = File.ReadAllText(configFile); JsonConvert.PopulateObject(text, (object)this); SaveConfiguration(); } else { SaveConfiguration(); } } } } namespace Lithium.Modules.Products { public class ModProductsConfiguration : ModuleConfiguration { public override string Name => "Products"; public bool ShowMixRecipes { get; set; } = true; public string MixesHeader { get; set; } = "Mix recipes:"; public string Arrow { get; set; } = "→"; public string Bullet { get; set; } = "• "; public int MaxLines { get; set; } = 0; public float FontSize { get; set; } = 0f; public float IconSize { get; set; } = 24f; public float RowHeight { get; set; } = 28f; public bool EnableListFilter { get; set; } = true; public string SearchPlaceholder { get; set; } = "Search products..."; public string EffectsButtonLabel { get; set; } = "Effects"; public ModProductsConfiguration() { Enabled = true; } } public class ModProducts : ModuleBase<ModProductsConfiguration> { public override void Apply() { ProductListFilter.Reset(); } public void DriveUpdate() { ProductListFilter.DriveVisibility(); } } internal static class ProductFilterUi { private static Font _font; public static UnityAction UA(Action a) { return UnityAction.op_Implicit(a); } public static UnityAction<string> UA(Action<string> a) { return UnityAction<string>.op_Implicit(a); } public static Font ResolveFont() { if ((Object)(object)_font != (Object)null) { return _font; } Il2CppArrayBase<Text> val = Object.FindObjectsOfType<Text>(true); if (val != null) { foreach (Text item in val) { if ((Object)(object)item != (Object)null && (Object)(object)item.font != (Object)null) { _font = item.font; break; } } } if ((Object)(object)_font == (Object)null) { _font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf") ?? Resources.GetBuiltinResource<Font>("Arial.ttf"); } return _font; } public static void SetAnchored(RectTransform rt, Vector2 anchor, Vector2 pivot, Vector2 size, Vector2 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = anchor; rt.anchorMax = anchor; rt.pivot = pivot; rt.sizeDelta = size; rt.anchoredPosition = pos; } public static GameObject MakeImage(Transform parent, string name, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); val.transform.localScale = Vector3.one; ((Graphic)val.AddComponent<Image>()).color = color; return val; } public static Text MakeText(Transform parent, string name, string text, int fontSize, Color color, TextAnchor anchor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); val.transform.localScale = Vector3.one; Text val3 = val.AddComponent<Text>(); val3.font = ResolveFont(); val3.fontSize = fontSize; ((Graphic)val3).color = color; val3.alignment = anchor; val3.supportRichText = true; val3.horizontalOverflow = (HorizontalWrapMode)1; val3.verticalOverflow = (VerticalWrapMode)1; val3.text = text; return val3; } public static Button MakeButton(Transform parent, string name, string label, int fontSize, Color bgColor, Color textColor, Action onClick, out Image bg, out Text labelText) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); val.transform.localScale = Vector3.one; bg = val.AddComponent<Image>(); ((Graphic)bg).color = bgColor; Button val3 = val.AddComponent<Button>(); ((Selectable)val3).targetGraphic = (Graphic)(object)bg; labelText = MakeText(val.transform, "Label", label, fontSize, textColor, (TextAnchor)4); RectTransform rectTransform = ((Graphic)labelText).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; if (onClick != null) { ((UnityEvent)val3.onClick).AddListener(UA(onClick)); } return val3; } public static InputField CloneSearchInput(InputField template, string placeholder) { if ((Object)(object)template == (Object)null) { return null; } GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject); InputField component = val.GetComponent<InputField>(); component.contentType = (ContentType)0; component.characterValidation = (CharacterValidation)0; component.characterLimit = 0; component.lineType = (LineType)0; component.SetTextWithoutNotify(string.Empty); if ((Object)(object)component.placeholder != (Object)null) { Text val2 = ((Il2CppObjectBase)component.placeholder).TryCast<Text>(); if ((Object)(object)val2 != (Object)null) { val2.text = placeholder; val2.fontStyle = (FontStyle)2; } } return component; } public static RectTransform MakeScrollList(Transform parent, Vector2 anchor, Vector2 pivot, Vector2 size, Vector2 pos, Color background) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ScrollList"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); val.transform.localScale = Vector3.one; SetAnchored(val2, anchor, pivot, size, pos); ((Graphic)val.AddComponent<Image>()).color = background; GameObject val3 = new GameObject("Viewport"); RectTransform val4 = val3.AddComponent<RectTransform>(); ((Transform)val4).SetParent(val.transform, false); val3.transform.localScale = Vector3.one; val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; ((Graphic)val3.AddComponent<Image>()).color = Color.white; val3.AddComponent<Mask>().showMaskGraphic = false; GameObject val5 = new GameObject("Content"); RectTransform val6 = val5.AddComponent<RectTransform>(); ((Transform)val6).SetParent(val3.transform, false); val5.transform.localScale = Vector3.one; val6.anchorMin = new Vector2(0f, 1f); val6.anchorMax = new Vector2(1f, 1f); val6.pivot = new Vector2(0.5f, 1f); val6.sizeDelta = Vector2.zero; ScrollRect val7 = val.AddComponent<ScrollRect>(); val7.horizontal = false; val7.vertical = true; val7.movementType = (MovementType)2; val7.scrollSensitivity = 24f; val7.viewport = val4; val7.content = val6; return val6; } } internal static class ProductListFilter { private sealed class EffectOption { public string Id; public string Name; public Image Background; public Text Label; } private const float BarHeight = 46f; private const float RowHeight = 28f; private static readonly Color BarColor = new Color(0.1f, 0.1f, 0.12f, 0.95f); private static readonly Color PanelColor = new Color(0.08f, 0.08f, 0.1f, 0.98f); private static readonly Color ButtonColor = new Color(0.2f, 0.2f, 0.24f, 1f); private static readonly Color RowColor = new Color(0.16f, 0.16f, 0.2f, 1f); private static readonly Color RowSelectedColor = new Color(0.2f, 0.45f, 0.3f, 1f); private static readonly Color TextColor = Color.white; private static ProductManagerApp _app; private static int _appId; private static bool _built; private static GameObject _bar; private static InputField _searchInput; private static Text _effectsButtonLabel; private static GameObject _effectsPanel; private static string _nameFilter = string.Empty; private static readonly HashSet<string> _selectedEffectIds = new HashSet<string>(); private static readonly List<EffectOption> _effectOptions = new List<EffectOption>(); public static bool Enabled { get { ModProducts modProducts = Core.Get<ModProducts>(); return modProducts != null && modProducts.Configuration.Enabled && modProducts.Configuration.EnableListFilter; } } public static void Reset() { _app = null; _appId = 0; _built = false; _bar = null; _searchInput = null; _effectsButtonLabel = null; _effectsPanel = null; _nameFilter = string.Empty; _selectedEffectIds.Clear(); _effectOptions.Clear(); } public static void EnsureBuilt(ProductManagerApp app) { if (!Enabled || (Object)(object)app == (Object)null) { return; } int instanceID = ((Object)app).GetInstanceID(); if (_built && _appId == instanceID) { return; } if (_appId != instanceID) { Reset(); } try { Build(app); _app = app; _appId = instanceID; _built = true; ApplyFilter(); SetVisible(((App<ProductManagerApp>)(object)app).isOpen); } catch (Exception value) { Log.Error($"[Lithium] Products filter build failed: {value}"); } } public static void DriveVisibility() { if (_built && !((Object)(object)_bar == (Object)null) && !((Object)(object)_app == (Object)null)) { if (!Enabled) { SetVisible(visible: false); } else { SetVisible(((App<ProductManagerApp>)(object)_app).isOpen); } } } public static void SetVisible(bool visible) { if ((Object)(object)_bar != (Object)null && _bar.activeSelf != visible) { _bar.SetActive(visible); } if (!visible && (Object)(object)_effectsPanel != (Object)null && _effectsPanel.activeSelf) { _effectsPanel.SetActive(false); } } private static void Build(ProductManagerApp app) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) ProductFilterUi.ResolveFont(); RectTransform appContainer = ((App<ProductManagerApp>)(object)app).appContainer; if ((Object)(object)appContainer == (Object)null) { Log.Warning("[Lithium] Products filter: app container missing; skipping."); return; } ModProductsConfiguration configuration = Core.Get<ModProducts>().Configuration; GameObject val = (_bar = ProductFilterUi.MakeImage((Transform)(object)appContainer, "LithiumProductFilterBar", BarColor)); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = new Vector2(0f, 46f); component.anchoredPosition = Vector2.zero; InputField template = (((Object)(object)app.DetailPanel != (Object)null) ? app.DetailPanel.ValueLabel : null); _searchInput = ProductFilterUi.CloneSearchInput(template, configuration.SearchPlaceholder); if ((Object)(object)_searchInput != (Object)null) { ((Component)_searchInput).gameObject.SetActive(true); ((Component)_searchInput).transform.SetParent(val.transform, false); ((Component)_searchInput).transform.localScale = Vector3.one; RectTransform component2 = ((Component)_searchInput).GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 0f); component2.anchorMax = new Vector2(0.62f, 1f); component2.offsetMin = new Vector2(6f, 6f); component2.offsetMax = new Vector2(-4f, -6f); ((UnityEvent<string>)(object)_searchInput.onValueChanged).AddListener(ProductFilterUi.UA(OnNameChanged)); } else { Log.Warning("[Lithium] Products filter: no InputField template to clone; search unavailable."); } Image bg; Button val2 = ProductFilterUi.MakeButton(val.transform, "EffectsButton", configuration.EffectsButtonLabel, 16, ButtonColor, TextColor, ToggleEffectsPanel, out bg, out _effectsButtonLabel); RectTransform component3 = ((Component)val2).GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0.64f, 0f); component3.anchorMax = new Vector2(1f, 1f); component3.offsetMin = new Vector2(4f, 6f); component3.offsetMax = new Vector2(-6f, -6f); BuildEffectsPanel(appContainer, configuration); UpdateEffectsButtonLabel(); } private static void BuildEffectsPanel(RectTransform container, ModProductsConfiguration config) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) _effectOptions.Clear(); _effectsPanel = ProductFilterUi.MakeImage((Transform)(object)container, "LithiumEffectsPanel", PanelColor); RectTransform component = _effectsPanel.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.4f, 0.08f); component.anchorMax = new Vector2(0.99f, 0.86f); component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; Text val = ProductFilterUi.MakeText(_effectsPanel.transform, "Title", "Effects (must have all)", 15, TextColor, (TextAnchor)3); RectTransform rectTransform = ((Graphic)val).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0.7f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.sizeDelta = new Vector2(0f, 26f); rectTransform.anchoredPosition = new Vector2(8f, -4f); Image bg; Text labelText; Button val2 = ProductFilterUi.MakeButton(_effectsPanel.transform, "ClearButton", "Clear", 14, ButtonColor, TextColor, ClearEffects, out bg, out labelText); RectTransform component2 = ((Component)val2).GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.72f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(1f, 1f); component2.sizeDelta = new Vector2(0f, 24f); component2.anchoredPosition = new Vector2(-6f, -5f); RectTransform val3 = ProductFilterUi.MakeScrollList(_effectsPanel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(-12f, -36f), new Vector2(0f, 6f), PanelColor); RectTransform component3 = ((Component)((Transform)val3).parent.parent).GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(1f, 1f); component3.offsetMin = new Vector2(6f, 6f); component3.offsetMax = new Vector2(-6f, -34f); List<EffectOption> list = GatherEffects(); val3.sizeDelta = new Vector2(0f, (float)list.Count * 28f); for (int i = 0; i < list.Count; i++) { EffectOption opt = list[i]; Image bg2; Text labelText2; Button val4 = ProductFilterUi.MakeButton((Transform)(object)val3, "Effect_" + opt.Id, opt.Name, 14, RowColor, TextColor, delegate { ToggleEffect(opt.Id); }, out bg2, out labelText2); labelText2.alignment = (TextAnchor)3; RectTransform rectTransform2 = ((Graphic)labelText2).rectTransform; rectTransform2.offsetMin = new Vector2(8f, 0f); rectTransform2.offsetMax = new Vector2(-4f, 0f); RectTransform component4 = ((Component)val4).GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 1f); component4.anchorMax = new Vector2(1f, 1f); component4.pivot = new Vector2(0.5f, 1f); component4.sizeDelta = new Vector2(0f, 26f); component4.anchoredPosition = new Vector2(0f, (float)(-i) * 28f); opt.Background = bg2; opt.Label = labelText2; _effectOptions.Add(opt); } _effectsPanel.SetActive(false); } private static List<EffectOption> GatherEffects() { Dictionary<string, EffectOption> dictionary = new Dictionary<string, EffectOption>(); ProductManager instance = NetworkSingleton<ProductManager>.Instance; if ((Object)(object)instance != (Object)null && instance.AllProducts != null) { List<ProductDefinition> allProducts = instance.AllProducts; for (int i = 0; i < allProducts.Count; i++) { ProductDefinition val = allProducts[i]; if ((Object)(object)val == (Object)null || ((PropertyItemDefinition)val).Properties == null) { continue; } for (int j = 0; j < ((PropertyItemDefinition)val).Properties.Count; j++) { Effect val2 = ((PropertyItemDefinition)val).Properties[j]; if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(val2.ID) && !dictionary.ContainsKey(val2.ID)) { dictionary[val2.ID] = new EffectOption { Id = val2.ID, Name = (string.IsNullOrEmpty(val2.Name) ? val2.ID : val2.Name) }; } } } } return dictionary.Values.OrderBy<EffectOption, string>((EffectOption o) => o.Name, StringComparer.OrdinalIgnoreCase).ToList(); } private static void OnNameChanged(string value) { _nameFilter = (value ?? string.Empty).Trim(); ApplyFilter(); } private static void ToggleEffectsPanel() { if (!((Object)(object)_effectsPanel == (Object)null)) { _effectsPanel.SetActive(!_effectsPanel.activeSelf); } } private static void ToggleEffect(string id) { if (!_selectedEffectIds.Remove(id)) { _selectedEffectIds.Add(id); } RefreshEffectVisuals(); UpdateEffectsButtonLabel(); ApplyFilter(); } private static void ClearEffects() { if (_selectedEffectIds.Count != 0) { _selectedEffectIds.Clear(); RefreshEffectVisuals(); UpdateEffectsButtonLabel(); ApplyFilter(); } } private static void RefreshEffectVisuals() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) foreach (EffectOption effectOption in _effectOptions) { if ((Object)(object)effectOption.Background != (Object)null) { ((Graphic)effectOption.Background).color = (_selectedEffectIds.Contains(effectOption.Id) ? RowSelectedColor : RowColor); } if ((Object)(object)effectOption.Label != (Object)null) { effectOption.Label.text = (_selectedEffectIds.Contains(effectOption.Id) ? "✓ " : "") + effectOption.Name; } } } private static void UpdateEffectsButtonLabel() { if (!((Object)(object)_effectsButtonLabel == (Object)null)) { string effectsButtonLabel = Core.Get<ModProducts>().Configuration.EffectsButtonLabel; _effectsButtonLabel.text = ((_selectedEffectIds.Count > 0) ? $"{effectsButtonLabel} ({_selectedEffectIds.Count})" : effectsButtonLabel); } } public static void ApplyFilter() { if (!_built || (Object)(object)_app == (Object)null) { return; } try { if (_app.FavouritesContainer != null) { FilterContainer(_app.FavouritesContainer.Container); } List<ProductTypeContainer> productTypeContainers = _app.ProductTypeContainers; if (productTypeContainers != null) { for (int i = 0; i < productTypeContainers.Count; i++) { ProductTypeContainer val = productTypeContainers[i]; if (val != null) { FilterContainer(val.Container); } } } RebuildLayout(); } catch (Exception value) { Log.Error($"[Lithium] Products filter apply failed: {value}"); } } private static void RebuildLayout() { if (!((App<ProductManagerApp>)(object)_app).isOpen) { return; } _app.DelayedRebuildLayout(); Il2CppArrayBase<VerticalLayoutGroup> componentsInChildren = ((Component)_app).GetComponentsInChildren<VerticalLayoutGroup>(true); if (componentsInChildren == null) { return; } foreach (VerticalLayoutGroup item in componentsInChildren) { if (!((Object)(object)item == (Object)null)) { ((Behaviour)item).enabled = false; ((Behaviour)item).enabled = true; } } } private static void FilterContainer(RectTransform container) { if ((Object)(object)container == (Object)null) { return; } int childCount = ((Transform)container).childCount; for (int i = 0; i < childCount; i++) { Transform child = ((Transform)container).GetChild(i); if ((Object)(object)child == (Object)null) { continue; } ProductEntry component = ((Component)child).GetComponent<ProductEntry>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.Definition == (Object)null)) { bool flag = Matches(component.Definition); if (((Component)child).gameObject.activeSelf != flag) { ((Component)child).gameObject.SetActive(flag); } } } } private static bool Matches(ProductDefinition def) { if (_nameFilter.Length > 0) { string name = ((BaseItemDefinition)def).Name; if (string.IsNullOrEmpty(name) || name.IndexOf(_nameFilter, StringComparison.OrdinalIgnoreCase) < 0) { return false; } } if (_selectedEffectIds.Count > 0) { if (((PropertyItemDefinition)def).Properties == null) { return false; } foreach (string selectedEffectId in _selectedEffectIds) { if (!HasEffect(def, selectedEffectId)) { return false; } } } return true; } private static bool HasEffect(ProductDefinition def, string effectId) { List<Effect> properties = ((PropertyItemDefinition)def).Properties; for (int i = 0; i < properties.Count; i++) { Effect val = properties[i]; if ((Object)(object)val != (Object)null && val.ID == effectId) { return true; } } return false; } } } namespace Lithium.Modules.Products.Patches { [HarmonyPatch(typeof(ItemInfoPanel), "Open", new Type[] { typeof(ItemInstance), typeof(RectTransform) })] internal static class ProductInfoPanelMixesPatch { private readonly struct MixRow { public readonly Sprite MixerIcon; public readonly Sprite ResultIcon; public readonly string ResultName; public MixRow(Sprite mixerIcon, Sprite resultIcon, string resultName) { MixerIcon = mixerIcon; ResultIcon = resultIcon; ResultName = resultName; } } private const string RootName = "LithiumMixes"; private const float TopMargin = 4f; private const float HeaderHeight = 16f; private const float LeftPad = 6f; private static readonly Dictionary<int, string> _lastProduct = new Dictionary<int, string>(); [HarmonyPostfix] private static void Postfix(ItemInfoPanel __instance, ItemInstance item) { ModProductsConfiguration configuration = Core.Get<ModProducts>().Configuration; if (!configuration.Enabled || !configuration.ShowMixRecipes) { return; } try { ItemInfoContent content = __instance.content; if ((Object)(object)content == (Object)null) { return; } ProductItemInfoContent val = ((Il2CppObjectBase)content).TryCast<ProductItemInfoContent>(); if ((Object)(object)val == (Object)null || (Object)(object)((ItemInfoContent)val).DescriptionLabel == (Object)null) { return; } int instanceID = ((Object)content).GetInstanceID(); Transform val2 = ((Component)content).transform.Find("LithiumMixes"); ItemDefinition val3 = ((item != null) ? item.Definition : null); ProductDefinition val4 = (((Object)(object)val3 != (Object)null) ? ((Il2CppObjectBase)val3).TryCast<ProductDefinition>() : null); List<MixRow> list = (((Object)(object)val4 != (Object)null) ? BuildForwardRecipes(val4, configuration) : new List<MixRow>()); string text = (((Object)(object)val4 != (Object)null) ? ((BaseItemDefinition)val4).ID : ""); float num = MeasureEffectsBottom(content, val); if (list.Count == 0) { if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(false); } _lastProduct[instanceID] = ""; ResizePanel(__instance, content, content.Height); return; } float num2 = ((configuration.RowHeight > 0f) ? configuration.RowHeight : 28f); float iconSize = ((configuration.IconSize > 0f) ? configuration.IconSize : 24f); float num3 = 16f + (float)list.Count * num2 + 4f; float height = num + 4f + num3; if ((Object)(object)val2 == (Object)null || _lastProduct.GetValueOrDefault(instanceID) != text) { if ((Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val2).gameObject); } RectTransform val5 = BuildRows(content, ((ItemInfoContent)val).DescriptionLabel, list, num, num3, num2, iconSize, configuration); _lastProduct[instanceID] = text; } else { RectTransform val5 = ((Il2CppObjectBase)val2).TryCast<RectTransform>() ?? ((Component)val2).GetComponent<RectTransform>(); ((Component)val5).gameObject.SetActive(true); } ResizePanel(__instance, content, height); } catch (Exception value) { Log.Error($"[Lithium] Products tooltip failed for {((item != null && (Object)(object)item.Definition != (Object)null) ? ((BaseItemDefinition)item.Definition).ID : "?")}: {value}"); } } private static RectTransform BuildRows(ItemInfoContent content, TextMeshProUGUI template, List<MixRow> rows, float topOffset, float blockHeight, float rowHeight, float iconSize, ModProductsConfiguration config) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002c: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0095: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LithiumMixes"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(((Component)content).transform, false); val2.anchorMin = new Vector2(0f, 1f); val2.anchorMax = new Vector2(1f, 1f); val2.pivot = new Vector2(0.5f, 1f); val2.sizeDelta = new Vector2(0f, blockHeight); val2.anchoredPosition = new Vector2(0f, 0f - (topOffset + 4f)); val.transform.localScale = Vector3.one; float fontSize = ((config.FontSize > 0f) ? config.FontSize : ((TMP_Text)template).fontSize); MakeText((Transform)(object)val2, template, "<b>" + config.MixesHeader + "</b>", 6f, 0f, 160f, 16f, fontSize, (TextAlignmentOptions)257); float num = 12f; float num2 = 2f; float num3 = 6f; float num4 = num3 + iconSize + num2; float num5 = num4 + num + num2; float x = num5 + iconSize + num2; for (int i = 0; i < rows.Count; i++) { MixRow mixRow = rows[i]; float num6 = 0f - (16f + (float)i * rowHeight); float y = num6 - (rowHeight - iconSize) * 0.5f; MakeIcon((Transform)(object)val2, mixRow.MixerIcon, num3, y, iconSize); MakeText((Transform)(object)val2, template, config.Arrow, num4, num6, num, rowHeight, fontSize, (TextAlignmentOptions)4098); MakeIcon((Transform)(object)val2, mixRow.ResultIcon, num5, y, iconSize); MakeText((Transform)(object)val2, template, mixRow.ResultName, x, num6, 200f, rowHeight, fontSize, (TextAlignmentOptions)4097); } return val2; } private static void MakeIcon(Transform parent, Sprite sprite, float x, float y, float size) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)sprite == (Object)null)) { GameObject val = new GameObject("Icon"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); val2.anchorMin = new Vector2(0f, 1f); val2.anchorMax = new Vector2(0f, 1f); val2.pivot = new Vector2(0f, 1f); val2.sizeDelta = new Vector2(size, size); val2.anchoredPosition = new Vector2(x, y); val.transform.localScale = Vector3.one; Image val3 = val.AddComponent<Image>(); val3.sprite = sprite; val3.preserveAspect = true; } } private static void MakeText(Transform parent, TextMeshProUGUI template, string text, float x, float y, float w, float h, float fontSize, TextAlignmentOptions align) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent); ((Object)val).name = "Text"; val.transform.localScale = Vector3.one; TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); RectTransform rectTransform = ((TMP_Text)component).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.sizeDelta = new Vector2(w, h); rectTransform.anchoredPosition = new Vector2(x, y); ((TMP_Text)component).enableWordWrapping = false; ((TMP_Text)component).alignment = align; if (fontSize > 0f) { ((TMP_Text)component).fontSize = fontSize; } ((TMP_Text)component).text = text; val.SetActive(true); } private static float MeasureEffectsBottom(ItemInfoContent content, ProductItemInfoContent productContent) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)content).GetComponent<RectTransform>(); if ((Object)(object)component == (Object)null) { return content.Height; } Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>(4L); component.GetWorldCorners(val); float y = ((Il2CppArrayBase<Vector3>)(object)val)[1].y; float num = y; bool flag = false; List<TextMeshProUGUI> propertyLabels = productContent.PropertyLabels; if (propertyLabels != null) { for (int i = 0; i < propertyLabels.Count; i++) { TextMeshProUGUI val2 = propertyLabels[i]; if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeInHierarchy && !string.IsNullOrWhiteSpace(((TMP_Text)val2).text)) { Il2CppStructArray<Vector3> val3 = new Il2CppStructArray<Vector3>(4L); ((TMP_Text)val2).rectTransform.GetWorldCorners(val3); float num2 = Mathf.Min(((Il2CppArrayBase<Vector3>)(object)val3)[0].y, ((Il2CppArrayBase<Vector3>)(object)val3)[3].y); if (!flag || num2 < num) { num = num2; flag = true; } } } } if (!flag) { return content.Height; } float num3 = y - num; float y2 = ((Component)content).transform.lossyScale.y; return (y2 > 0.0001f) ? (num3 / y2) : num3; } private static void ResizePanel(ItemInfoPanel panel, ItemInfoContent content, float height) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) content.Height = height; RectTransform container = panel.Container; if ((Object)(object)container != (Object)null) { container.sizeDelta = new Vector2(container.sizeDelta.x, height); } } private static List<MixRow> BuildForwardRecipes(ProductDefinition product, ModProductsConfiguration config) { List<MixRow> list = new List<MixRow>(); ProductManager instance = NetworkSingleton<ProductManager>.Instance; if ((Object)(object)instance == (Object)null || instance.mixRecipes == null) { return list; } HashSet<string> hashSet = new HashSet<string>(); if (instance.ValidMixIngredients != null) { for (int i = 0; i < instance.ValidMixIngredients.Count; i++) { PropertyItemDefinition val = instance.ValidMixIngredients[i]; if ((Object)(object)val != (Object)null) { hashSet.Add(((BaseItemDefinition)val).ID); } } } HashSet<string> hashSet2 = new HashSet<string>(); foreach (ProductDefinition item3 in ProductManager.DiscoveredProducts.ToList<ProductDefinition>()) { if ((Object)(object)item3 != (Object)null) { hashSet2.Add(((BaseItemDefinition)item3).ID); } } List<StationRecipe> mixRecipes = instance.mixRecipes; for (int j = 0; j < mixRecipes.Count; j++) { StationRecipe val2 = mixRecipes[j]; if ((Object)(object)val2 == (Object)null || val2.Ingredients == null || val2.Product == null || (Object)(object)val2.Product.Item == (Object)null || val2.Ingredients.Count < 2) { continue; } ItemDefinition val3 = null; ItemDefinition val4 = null; for (int k = 0; k < val2.Ingredients.Count; k++) { ItemDefinition item = val2.Ingredients[k].Item; if (!((Object)(object)item == (Object)null)) { if ((Object)(object)val3 == (Object)null && hashSet.Contains(((BaseItemDefinition)item).ID)) { val3 = item; } else { val4 = item; } } } if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || ((BaseItemDefinition)val4).ID != ((BaseItemDefinition)product).ID) { continue; } ItemDefinition item2 = val2.Product.Item; if (!(((BaseItemDefinition)item2).ID == ((BaseItemDefinition)product).ID) && hashSet2.Contains(((BaseItemDefinition)item2).ID)) { list.Add(new MixRow(((BaseItemDefinition)val3).Icon, ((BaseItemDefinition)item2).Icon, ((BaseItemDefinition)item2).Name)); if (config.MaxLines > 0 && list.Count >= config.MaxLines) { break; } } } return list; } } [HarmonyPatch(typeof(ProductManagerApp))] internal static class ProductManagerAppFilterPatch { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(ProductManagerApp __instance) { ProductListFilter.EnsureBuilt(__instance); } [HarmonyPostfix] [HarmonyPatch("SetOpen")] private static void SetOpenPostfix(ProductManagerApp __instance, bool open) { if (!open) { ProductListFilter.SetVisible(visible: false); return; } ProductListFilter.EnsureBuilt(__instance); ProductListFilter.ApplyFilter(); ProductListFilter.SetVisible(visible: true); } [HarmonyPostfix] [HarmonyPatch("CreateEntry", new Type[] { typeof(ProductDefinition) })] private static void CreateEntryPostfix() { ProductListFilter.ApplyFilter(); } } } namespace Lithium.Modules.MixingStations { public class ModMixingStationsConfiguration : ModuleConfiguration { public override string Name => "MixingStation"; public int InputCapacity { get; set; } = 20; public int MixTimePerItem { get; set; } = 15; public int Mk2InputCapacity { get; set; } = 20; public int Mk2MixTimePerItem { get; set; } = 15; } public class ModMixingStations : ModuleBase<ModMixingStationsConfiguration> { public override void Apply() { if (base.Configuration.Enabled) { } } } } namespace Lithium.Modules.MixingStations.Patches { [HarmonyPatch(typeof(MixingStation), "Start")] public class MixingStationCapacityPatch { [HarmonyPostfix] public static void MixingStationCapacity(MixingStation __instance) { ModMixingStationsConfiguration configuration = Core.Get<ModMixingStations>().Configuration; if (configuration.Enabled) { bool flag = (Object)(object)((Il2CppObjectBase)__instance).TryCast<MixingStationMk2>() != (Object)null; __instance.MaxMixQuantity = (flag ? configuration.Mk2InputCapacity : configuration.InputCapacity); } } } [HarmonyPatch(typeof(MixingStation), "Start")] public class MixingStationDurationPatch { [HarmonyPostfix] public static void Postfix(MixingStation __instance) { ModMixingStationsConfiguration configuration = Core.Get<ModMixingStations>().Configuration; if (configuration.Enabled) { bool flag = (Object)(object)((Il2CppObjectBase)__instance).TryCast<MixingStationMk2>() != (Object)null; __instance.MixTimePerItem = Mathf.Max(1, flag ? configuration.Mk2MixTimePerItem : configuration.MixTimePerItem); } } } } namespace Lithium.Modules.TrashGrabber { public class ModTrashGrabberConfiguration : ModuleConfiguration { public override string Name => "TrashGrabber"; public int CustomCapacity { get; set; } = 20; } public class ModTrashGrabber : ModuleBase<ModTrashGrabberConfiguration> { public override void Apply() { if (base.Configuration.Enabled) { } } } } namespace Lithium.Modules.TrashGrabber.Patches { [HarmonyPatch(typeof(Equippable_TrashGrabber), "GetCapacity")] public static class EquippableTrashGrabberGetCapacityPatch { [HarmonyPostfix] public static void Postfix(ref int __result, Equippable_TrashGrabber __instance) { ModTrashGrabberConfiguration configuration = Core.Get<ModTrashGrabber>().Configuration; if (configuration.Enabled) { __result = configuration.CustomCapacity - __instance.trashGrabberInstance.GetTotalSize(); } } } [HarmonyPatch(typeof(Equippable_TrashGrabber), "Update")] public static class EquippableTrashGrabberRefreshVisualsPatch { [HarmonyPostfix] public static void Postfix(Equippable_TrashGrabber __instance) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) ModTrashGrabberConfiguration configuration = Core.Get<ModTrashGrabber>().Configuration; if (configuration.Enabled && __instance.trashGrabberInstance != null && !((Object)(object)__instance.TrashContent == (Object)null)) { int num = ((configuration.CustomCapacity > 0) ? configuration.CustomCapacity : 20); float num2 = Mathf.Clamp01((float)__instance.trashGrabberInstance.GetTotalSize() / (float)num); __instance.TrashContent.localPosition = Vector3.Lerp(__instance.TrashContent_Min.localPosition, __instance.TrashContent_Max.localPosition, num2); __instance.TrashContent.localScale = Vector3.Lerp(__instance.TrashContent_Min.localScale, __instance.TrashContent_Max.localScale, num2); ((Component)__instance.TrashContent).gameObject.SetActive(num2 > 0f); } } } [HarmonyPatch(typeof(TrashGrabberItemUI), "UpdateUI")] public static class TrashGrabberItemUIPatch { [HarmonyPostfix] public static void Postfix(TrashGrabberItemUI __instance) { ModTrashGrabberConfiguration configuration = Core.Get<ModTrashGrabber>().Configuration; if (configuration.Enabled && !((ItemUI)__instance).Destroyed && __instance.trashGrabberInstance != null && !((Object)(object)__instance.ValueLabel == (Object)null)) { int num = ((configuration.CustomCapacity > 0) ? configuration.CustomCapacity : 20); int num2 = Mathf.FloorToInt(Mathf.Clamp01((float)__instance.trashGrabberInstance.GetTotalSize() / (float)num) * 100f); ((TMP_Text)__instance.ValueLabel).text = num2 + "%"; } } } [HarmonyPatch(typeof(TrashItem), "Interacted")] public class TrashItemInteractedPatch { [HarmonyPrefix] public static bool Prefix(TrashItem __instance) { if (!Core.Get<ModTrashGrabber>().Configuration.Enabled) { return true; } if (Equippable_TrashGrabber.IsEquipped && __instance.CanGoInContainer && Equippable_TrashGrabber.Instance.GetCapacity() > 0) { Equippable_TrashGrabber.Instance.PickupTrash(__instance); } return false; } } [HarmonyPatch(typeof(TrashItem), "Hovered")] public class TrashItemHoveredPatch { [HarmonyPrefix] public static bool Prefix(TrashItem __instance) { if (!Core.Get<ModTrashGrabber>().Configuration.Enabled) { return true; } if (Equippable_TrashGrabber.IsEquipped && __instance.CanGoInContainer) { InteractableObject intObj = __instance.Draggable.IntObj; if (Equippable_TrashGrabber.Instance.GetCapacity() > 0) { intObj.SetMessage("Pick up"); intObj.SetInteractableState((EInteractableState)0); } else { intObj.SetMessage("Bin is full"); intObj.SetInteractableState((EInteractableState)1); } } return false; } } } namespace Lithium.Modules.StackSizes { public class ModStackSizesConfiguration : ModuleConfiguration { public override string Name => "StackSizes"; public bool ExperimentalCashStacking { get; set; } = false; public int CashMaxBalance { get; set; } = 100000; public Dictionary<EItemCategory, int> CategorySizes { get; set; } = new Dictionary<EItemCategory, int> { { (EItemCategory)0, 20 }, { (EItemCategory)1, 20 }, { (EItemCategory)2, 20 }, { (EItemCategory)3, 10 }, { (EItemCategory)4, 10 }, { (EItemCategory)5, 10 }, { (EItemCategory)6, 1000 }, { (EItemCategory)7, 20 }, { (EItemCategory)8, 20 }, { (EItemCategory)9, 20 }, { (EItemCategory)10, 10 }, { (EItemCategory)11, 10 }, { (EItemCategory)12, 10 } }; public Dictionary<string, int> ItemOverrides { get; set; } = new Dictionary<string, int>(); public List<string> IgnoredItems { get; set; } = new List<string>(); } public class ModStackSizes : ModuleBase<ModStackSizesConfiguration> { public override void Apply() { if (base.Configuration.Enabled) { } } } public static class ItemRegistry { public static List<ItemDefinition> AllItemDefinitions = new List<ItemDefinition>(); public static void UpdateEntireRegistry() { foreach (ItemDefinition allItemDefinition in AllItemDefinitions) { UpdateItemDefinition(allItemDefinition); } } public static void UpdateItemDefinition(ItemDefinition itemDefinition) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) ModStackSizesConfiguration configuration = Core.Get<ModStackSizes>().Configuration; if (configuration.Enabled && !configuration.IgnoredItems.Contains(((BaseItemDefinition)itemDefinition).ID)) { if (configuration.ItemOverrides.TryGetValue(((BaseItemDefinition)itemDefinition).ID, out var value)) { ((BaseItemDefinition)itemDefinition).StackLimit = value; return; } if (configuration.CategorySizes.TryGetValue(((BaseItemDefinition)itemDefinition).Category, out value)) { ((BaseItemDefinition)itemDefinition).StackLimit = value; return; } Log.Warning($"Found item for category {((BaseItemDefinition)itemDefinition).Category}, but no category value"); } } } } namespace Lithium.Modules.StackSizes.Patches { internal static class CashStackingConfig { public static float DragAmount; public static bool DragActive; private static float _lastScrollTime; private static int _lastStepFrame = -1; private static readonly int[] Ladder = BuildLadder(); public static bool TryGet(out float cap) { cap = 0f; ModStackSizes modStackSizes = Core.Get<ModStackSizes>(); if (modStackSizes == null || !modStackSizes.Configuration.Enabled || !modStackSizes.Configuration.ExperimentalCashStacking) { return false; } cap = modStackSizes.Configuration.CashMaxBalance; return true; } public static bool BeginScrollTick() { int frameCount = Time.frameCount; if (frameCount == _lastStepFrame) { return false; } _lastStepFrame = frameCount; return true; } private static int[] BuildLadder() { List<int> list = new List<int> { 1, 5 }; for (long num = 10L; num <= 100000000; num *= 10) { list.Add((int)num); list.Add((int)(2 * num)); list.Add((int)(5 * num)); } return list.ToArray(); } public static int SnapToLadder(float value) { int result = Ladder[0]; for (int i = 0; i < Ladder.Length && (float)Ladder[i] <= value; i++) { result = Ladder[i]; } return result; } public static int AcceleratedStep(float amount) { float unscaledTime = Time.unscaledTime; float num = Mathf.Max(unscaledTime - _lastScrollTime, 0.0001f); _lastScrollTime = unscaledTime; float num2 = Mathf.Clamp01((0.18f - num) / 0.16f); float num3 = num2 * num2 * num2; float num4 = Mathf.Max(5f, amount * 0.33f); return SnapToLadder(Mathf.Lerp(1f, num4, num3)); } public static float SourceMax(CashInstance source, float cap) { float num = ((source != null) ? source.Balance : cap); return Mathf.Min(cap, num); } } [HarmonyPatch(typeof(ItemUIManager), "StartDragCash")] public class CashDragStartPatch { [HarmonyPostfix] public static void Postfix(ItemUIManager __instance) { if (CashStackingConfig.TryGet(out var _)) { CashStackingConfig.DragAmount = Mathf.Max(1f, Mathf.Round(__instance.draggedCashAmount)); CashStackingConfig.DragActive = true; } } } public struct CashCombineState { public bool Valid; public CashInstance Target; public CashInstance Source; public float TargetBefore; public float SourceBefore; public float Dragged; } [HarmonyPatch(typeof(ItemUIManager), "EndCashDrag")] public class CashDragEndPatch { [HarmonyPrefix] public static void Prefix(ItemUIManager __instance, out CashCombineState __state) { __state = default(CashCombineState); if (!CashStackingConfig.TryGet(out var _) || !__instance.isDraggingCash) { return; } ItemSlotUI hoveredSlot = __instance.HoveredSlot; ItemSlotUI draggedSlot = __instance.draggedSlot; if (!((Object)(object)hoveredSlot == (Object)null) && hoveredSlot.assignedSlot != null && !((Object)(object)draggedSlot == (Object)null) && draggedSlot.assignedSlot != null) { CashInstance val = ((hoveredSlot.assignedSlot.ItemInstance != null) ? ((Il2CppObjectBase)hoveredSlot.assignedSlot.ItemInstance).TryCast<CashInstance>() : null); CashInstance val2 = ((draggedSlot.assignedSlot.ItemInstance != null) ? ((Il2CppObjectBase)draggedSlot.assignedSlot.ItemInstance).TryCast<CashInstance>() : null); if (val != null && val2 != null && !(((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)val2).Pointer)) { __state = new CashCombineState { Valid = true, Target = val, Source = val2, TargetBefore = val.Balance, SourceBefore = val2.Balance, Dragged = __instance.draggedCashAmount }; } } } [HarmonyPostfix] public static void Postfix(CashCombineState __state) { CashStackingConfig.DragActive = false; if (!__state.Valid || !CashStackingConfig.TryGet(out var cap)) { return; } float num = cap - __state.TargetBefore; if (!(num <= 0f)) { float num2 = Mathf.Min(Mathf.Min(__state.Dragged, num), __state.SourceBefore); float num3 = __state.Target.Balance - __state.TargetBefore; float num4 = num2 - num3; if (!(num4 <= 0.001f)) { __state.Target.ChangeBalance(num4); __state.Source.ChangeBalance(0f - num4); } } } } [HarmonyPatch(typeof(ItemUIManager), "AddCashAmount")] public class CashDragAddPatch { [HarmonyPostfix] public static void Postfix(ItemUIManager __instance, CashInstance __0) { if (CashStackingConfig.TryGet(out var cap) && __instance.isDraggingCash) { float num = CashStackingConfig.SourceMax(__0, cap); if (CashStackingConfig.BeginScrollTick()) { int num2 = CashStackingConfig.AcceleratedStep(CashStackingConfig.DragAmount); float num3 = CashStackingConfig.DragAmount + (float)num2; CashStackingConfig.DragAmount = ((num3 >= num) ? num : Mathf.Round(num3)); } __instance.draggedCashAmount = CashStackingConfig.DragAmount; } } } [HarmonyPatch(typeof(ItemUIManager), "SubtractCashAmount")] public class CashDragSubtractPatch { [HarmonyPostfix] public static void Postfix(ItemUIManager __instance, CashInstance __0) { if (CashStackingConfig.TryGet(out var _) && __instance.isDraggingCash) { if (CashStackingConfig.BeginScrollTick()) { int num = CashStackingConfig.AcceleratedStep(CashStackingConfig.DragAmount); CashStackingConfig.DragAmount = Mathf.Max(1f, Mathf.Round(CashStackingConfig.DragAmount - (float)num)); } __instance.draggedCashAmount = CashStackingConfig.DragAmount; } } } [HarmonyPatch(typeof(ItemUIManager), "UpdateCashDragAmount")] public class CashDragUpdatePatch { [HarmonyPostfix] public static void Postfix(ItemUIManager __instance, CashInstance __0) { if (CashStackingConfig.TryGet(out var cap) && __instance.isDraggingCash && CashStackingConfig.DragActive) { CashStackingConfig.DragAmount = Mathf.Min(CashStackingConfig.DragAmount, CashStackingConfig.SourceMax(__0, cap)); __instance.draggedCashAmount = CashStackingConfig.DragAmount; } } } [HarmonyPatch(typeof(CashInstance), "SetBalance")] public class CashSetBalancePatch { [HarmonyPostfix] public static void Postfix(CashInstance __instance, float __0) { if (CashStackingConfig.TryGet(out var cap)) { float num = Mathf.Min(__0, cap); if (__instance.Balance < num) { __instance.Balance = num; } } } } [HarmonyPatch(typeof(CashInstance), "ChangeBalance")] public class CashChangeBalancePatch { [HarmonyPrefix] public static void Prefix(CashInstance __instance, out float __state) { __state = __instance.Balance; } [HarmonyPostfix] public static void Postfix(CashInstance __instance, float __0, float __state) { if (CashStackingConfig.TryGet(out var cap)) { float num = Mathf.Min(__state + __0, cap); if (num > __instance.Balance) { __instance.Balance = num; } } } } [HarmonyPatch(typeof(ItemUIManager), "CanCashBeDraggedIntoSlot")] public class CashCanDragIntoSlotPatch { [HarmonyPostfix] public static void Postfix(ItemSlotUI __0, ref bool __result) { if (!__result && CashStackingConfig.TryGet(out var _) && !((Object)(object)__0 == (Object)null) && __0.assignedSlot != null) { ItemSlot assignedSlot = __0.assignedSlot; CashInstance val = ((assignedSlot.ItemInstance != null) ? ((Il2CppObjectBase)assignedSlot.ItemInstance).TryCast<CashInstance>() : null); if (val != null || (assignedSlot.ItemInstance == null && assignedSlot.CanSlotAcceptCash())) { __result = true; } } } } [HarmonyPatch(typeof(ItemSlot), "GetCapacityForItem")] public class CashSlotCapacityPatch { [HarmonyPostfix] public static void Postfix(ItemSlot __instance, ItemInstance __0, ref int __result) { if (!CashStackingConfig.TryGet(out var cap)) { return; } CashInstance val = ((__0 != null) ? ((Il2CppObjectBase)__0).TryCast<CashInstance>() : null); if (val == null) { return; } CashInstance val2 = ((__instance.ItemInstance != null) ? ((Il2CppObjectBase)__instance.ItemInstance).TryCast<CashInstance>() : null); if (val2 != null || (__instance.ItemInstance == null && __instance.CanSlotAcceptCash())) { float num = ((val2 != null) ? val2.Balance : 0f); int num2 = Mathf.Max(0, Mathf.FloorToInt(cap - num)); if (num2 > __result) { __result = num2; } } } } [HarmonyPatch(typeof(ItemInstance), "CanStackWith")] public class CashCanStackPatch { [HarmonyPostfix] public static void Postfix(ItemInstance __instance, ItemInstance __0, ref bool __result) { if (!__result && CashStackingConfig.TryGet(out var _)) { CashInstance val = ((__instance != null) ? ((Il2CppObjectBase)__instance).TryCast<CashInstance>() : null); CashInstance val2 = ((__0 != null) ? ((Il2CppObjectBase)__0).TryCast<CashInstance>() : null); if (val != null && val2 != null) { __result = true; } } } } [HarmonyPatch(typeof(Registry), "AddToRegistry")] public class RegistryAddToRegistryPatch { [HarmonyPostfix] public static void RegistryAddToRegistry(Registry __instance, ItemDefinition item) { CollectionExtensions.AddItem<ItemDefinition>((IEnumerable<ItemDefinition>)ItemRegistry.AllItemDefinitions, item); ItemRegistry.UpdateItemDefinition(item); } } [HarmonyPatch(typeof(Registry), "Start")] public class RegistryStartPatch { [HarmonyPostfix] public static void RegistryStart(Registry __instance) { ModStackSizesConfiguration configuration = Core.Get<ModStackSizes>().Configuration; if (configuration.Enabled) { List<ItemRegister> list = new List<ItemRegister>(); Enumerator<ItemRegister> enumerator = __instance.ItemRegistry.GetEnumerator(); while (enumerator.MoveNext()) { ItemRegister current = enumerator.Current; list.Add(current); } ItemRegistry.AllItemDefinitions = list.Select((ItemRegister itemRegister) => itemRegister.Definition).ToList(); ItemRegistry.UpdateEntireRegistry(); } } } } namespace Lithium.Modules.PhoneApp { public class ModPhoneAppConfiguration : ModuleConfiguration { public override string Name => "PhoneApp"; public ModPhoneAppConfiguration() { Enabled = true; } } public class ModPhoneApp : ModuleBase<ModPhoneAppConfiguration> { private LithiumPhoneApp _app; public override void Apply() { if (base.Configuration.Enabled && (_app == null || !_app.IsAlive)) { _app = new LithiumPhoneApp(); MelonCoroutines.Start(_app.BuildWhenReady()); } } public void DriveUpdate() { if (base.Configuration.Enabled) { _app?.Update(); } } } internal sealed class LithiumPhoneApp { private readonly struct TableCell { public readonly string Text; public readonly float XMin; public readonly float XMax; public readonly TextAnchor Anchor; public TableCell(string text, float xMin, float xMax, TextAnchor anchor) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Text = text; XMin = xMin; XMax = xMax; Anchor = anchor; } } private const string IconObjectName = "LithiumPhoneIcon"; private const float Pad = 14f; private const float RefreshInterval = 0.5f; private static readonly Color Background = Color32.op_Implicit(new Color32((byte)18, (byte)18, (byte)22, byte.MaxValue)); private static readonly Color HeaderColor = new Color(0.7f, 0.8f, 1f); private static readonly Color Gray = new Color(0.72f, 0.72f, 0.74f); private static readonly Color Red = new Color(1f, 0.32f, 0.32f); private static readonly Color IconColor = new Color(0.46f, 0.4f, 0.9f); private const string Green = "#3CCB5A"; private const string RedHex = "#FF5151"; private const string Dim = "#9AA0A6"; private static readonly Color TabSelected = new Color(0.34f, 0.3f, 0.62f, 1f); private static readonly Color TabUnselected = new Color(0.15f, 0.15f, 0.19f, 1f); private GameObject _appContainer; private GameObject _icon; private GameObject _bodyContent; private RectTransform _bodyContentRect; private Dropdown _dropdown; private Font _font; private readonly List<GameObject> _pages = new List<GameObject>(); private readonly List<Image> _tabBackgrounds = new List<Image>(); private readonly List<Text> _tabLabels = new List<Text>(); private int _tabIndex; private DailyOrdersPage _daily; private bool _isOpen; private bool _wasPhoneOpen; private float _lastRefresh; private float _y; private bool _rentEnabled; private List<ModRent.RentAppView> _locations = new List<ModRent.RentAppView>(); private int _selectedIndex; public bool IsAlive => (Object)(object)_appContainer != (Object)null; public IEnumerator BuildWhenReady() { float waited = 0f; while ((!PlayerSingleton<HomeScreen>.InstanceExists || !PlayerSingleton<AppsCanvas>.InstanceExists) && waited < 30f) { yield return (object)new WaitForSeconds(0.2f); waited += 0.2f; } if (!PlayerSingleton<HomeScreen>.InstanceExists || !PlayerSingleton<AppsCanvas>.InstanceExists) { Log.Warning("[PhoneApp] Phone UI not ready after 30s; app not created."); yield break; } try { Build(); Log.Info("[PhoneApp] Lithium app created."); } catch (Exception value) { Log.Error($"[PhoneApp] Build failed: {value}"); } } private void Build() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) _font = PhoneAppFont.Resolve(); _appContainer = PhoneAppBuilder.MakePanel("LithiumPhoneApp"); PhoneAppBuilder.MakeBackground(_appContainer, Background); Text val = PhoneAppBuilder.MakeText(_appContainer.transform, _font, "Header", 40, HeaderColor, (TextAnchor)4, wrap: false); val.fontStyle = (FontStyle)1; val.text = "Lithium"; SetRect(((Graphic)val).rectTransform, 0.05f, 0.92f, 0.95f, 0.985f); GameObject val2 = MakePage("PageProperty"); GameObject val3 = MakePage("PageDaily"); BuildTabBar(("Property", val2), ("Daily", val3)); _dropdown = PhoneAppBuilder.CloneDropdown(); if ((Object)(object)_dropdown != (Object)null) { ((Component)_dropdown).transform.SetParent(val2.transform, false); ((Component)_dropdown).transform.localScale = Vector3.one; SetRect(((Component)_dropdown).GetComponent<RectTransform>(), 0.05f, 0.775f, 0.95f, 0.845f); ((UnityEvent<int>)(object)_dropdown.onValueChanged).AddListener(PhoneAppBuilder.UA(OnDropdownChanged)); } else { Log.Warning("[PhoneApp] Could not clone a phone dropdown; selector unavailable."); } CreateBody(val2); _daily = new DailyOrdersPage(); GameObject val4 = _daily.Build(val3.transform, _font); SetRect(val4.GetComponent<RectTransform>(), 0.04f, 0.03f, 0.96f, 0.845f); SelectTab(0, refresh: false); _appContainer.SetActive(false); _icon = PhoneAppBuilder.MakeIcon("LithiumPhoneIcon", "Lithium", PhoneAppBuilder.LoadIconOrDefault(IconColor), OnIconClicked); } private GameObject MakePage(string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(_appContainer.transform, false); val.transform.localScale = Vector3.one; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; _pages.Add(val); return val; } private void BuildTabBar(params (string Label, GameObject Page)[] tabs) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Tabs"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(_appContainer.transform, false); val.transform.localScale = Vector3.one; SetRect(val2, 0.05f, 0.85f, 0.95f, 0.915f); float num = 1f / (float)tabs.Length; for (int i = 0; i < tabs.Length; i++) { int index = i; Image bg; Text labelText; Button val3 = PhoneAppBuilder.MakeButton(val.transform, _font, "Tab" + tabs[i].Label, tabs[i].Label, 26, TabUnselected, Color.white, delegate { OnTabClicked(index); }, out bg, out labelText); RectTransform component = ((Component)val3).GetComponent<RectTransform>(); component.anchorMin = new Vector2((float)i * num, 0f); component.anchorMax = new Vector2((float)(i + 1) * num, 1f); component.offsetMin = new Vector2((i == 0) ? 0f : 3f, 0f); component.offsetMax = new Vector2((i == tabs.Length - 1) ? 0f : (-3f), 0f); _tabBackgrounds.Add(bg); _tabLabels.Add(labelText); } } private void OnTabClicked(int index) { if (_tabIndex != index) { SelectTab(index, _isOpen); } } private void SelectTab(int index, bool refresh) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) _tabIndex = index; for (int i = 0; i < _pages.Count; i++) { _pages[i].SetActive(i == index); } for (int j = 0; j < _tabBackgrounds.Count; j++) { ((Graphic)_tabBackgrounds[j]).color = ((j == index) ? TabSelected : TabUnselected); ((Graphic)_tabLabels[j]).color = ((j == index) ? Color.white : Gray); } if (refresh) { if (index == 0) { RebuildBody(refreshElectric: true); } else { _daily.Rebuild(); } } } private void CreateBody(GameObject page) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Body"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(page.transform, false); val.transform.localScale = Vector3.one; SetRect(val2, 0.04f, 0.03f, 0.96f, 0.755f); GameObject val3 = new GameObject("Viewport"); RectTransform val4 = val3.AddComponent<RectTransform>(); ((Transform)val4).SetParent(val.transform, false); val3.transform.localScale = Vector3.one; val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; ((Graphic)val3.AddComponent<Image>()).color = Color.white; val3.AddComponent<Mask>().showMaskGraphic = false; GameObject val5 = new GameObject("Content"); _bodyContentRect = val5.AddComponent<RectTransform>(); ((Transform)_bodyContentRect).SetParent(val3.transform, false); val5.transform.localScale = Vector3.one; _bodyContentRect.anchorMin = new Vector2(0f, 1f); _bodyContentRect.anchorMax = new Vector2(1f, 1f); _bodyContentRect.pivot = new Vector2(0.5f, 1f); _bodyContentRect.sizeDelta = Vector2.zero; _bodyContent = val5; ScrollRect val6 = val.Ad