Decompiled source of SyncDiskSuite v1.0.0

BepInEx/plugins/SoDDiskPack/SoDDiskPack.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.Helpers.SyncDiskObjects;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SoDDiskPack")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.12.0.0")]
[assembly: AssemblyInformationalVersion("0.12.0")]
[assembly: AssemblyProduct("SoDDiskPack")]
[assembly: AssemblyTitle("SoDDiskPack")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.12.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SoDDiskPack
{
	public class DiskDef
	{
		public string Key;

		public string DiskName;

		public string EffectName;

		public string EffectDesc;

		public Effect Effect;

		public float Value;

		public int Price;

		public Rarity Rarity;

		public Manufacturer Manufacturer;

		public string[] SaleLocations;

		public string[] TierDescs;

		public UpgradeEffect[] TierEffects;

		public float[] TierValues;

		public Effect SideEffect;

		public float SideValue;

		public string SideName;

		public string SideDesc;

		public bool Enabled = true;

		public bool TiersInCode;
	}
	public static class Disks
	{
		public static readonly DiskDef[] All = new DiskDef[19]
		{
			new DiskDef
			{
				Key = "Quickstep",
				DiskName = "Quickstep",
				EffectName = "Fleet Foot",
				EffectDesc = "You move faster on foot.",
				Effect = (Effect)57,
				Value = 0.15f,
				Price = 2500,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)0,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = new string[3] { "You move faster still.", "Your pace improves further.", "You move considerably faster." },
				TiersInCode = true
			},
			new DiskDef
			{
				Key = "LowProfile",
				DiskName = "Low Profile",
				Enabled = false,
				EffectName = "Unremarkable",
				EffectDesc = "Citizens are less easily alarmed by you.",
				Effect = (Effect)62,
				Value = -0.15f,
				Price = 1000,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)5,
				SaleLocations = new string[1] { "BlackmarketSyncClinic" },
				TierDescs = new string[3] { "Citizens are calmer still.", "You draw less attention again.", "You are markedly harder to alarm." }
			},
			new DiskDef
			{
				Key = "SquattersRights",
				DiskName = "Squatter's Rights",
				Enabled = false,
				EffectName = "Belong Here",
				EffectDesc = "You are given longer before trespassing is reported.",
				Effect = (Effect)63,
				Value = 0.5f,
				Price = 1000,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)5,
				SaleLocations = new string[1] { "BlackmarketSyncClinic" },
				TierDescs = new string[3] { "You are given longer still.", "Further grace before you are reported.", "A considerable delay before you are reported." }
			},
			new DiskDef
			{
				Key = "Homebound",
				DiskName = "Homebound",
				Enabled = false,
				EffectName = "Homebound",
				EffectDesc = "You may travel directly to your apartment.",
				Effect = (Effect)65,
				Value = 1f,
				Price = 1500,
				Rarity = (Rarity)3,
				Manufacturer = (Manufacturer)2,
				SaleLocations = new string[1] { "SyncClinic" }
			},
			new DiskDef
			{
				Key = "Signpost",
				DiskName = "Signpost",
				Enabled = false,
				EffectName = "Signpost",
				EffectDesc = "You may travel using street signage.",
				Effect = (Effect)67,
				Value = 1f,
				Price = 1500,
				Rarity = (Rarity)3,
				Manufacturer = (Manufacturer)2,
				SaleLocations = new string[1] { "SyncClinic" }
			},
			new DiskDef
			{
				Key = "PersonaNonGrata",
				DiskName = "Persona Non Grata",
				Enabled = false,
				EffectName = "Persona Non Grata",
				EffectDesc = "Loitering is no longer held against you.",
				Effect = (Effect)69,
				Value = 1f,
				Price = 1000,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)5,
				SaleLocations = new string[1] { "BlackmarketSyncClinic" }
			},
			new DiskDef
			{
				Key = "FreeRein",
				DiskName = "Free Rein",
				Enabled = false,
				EffectName = "Free Rein",
				EffectDesc = "Your presence at crime scenes is permitted.",
				Effect = (Effect)61,
				Value = 1f,
				Price = 1500,
				Rarity = (Rarity)3,
				Manufacturer = (Manufacturer)2,
				SaleLocations = new string[1] { "SyncClinic" }
			},
			new DiskDef
			{
				Key = "DeepPockets",
				DiskName = "Deep Pockets",
				EffectName = "Deep Pockets",
				EffectDesc = "Increase your inventory capacity.",
				Effect = (Effect)11,
				Value = 1f,
				Price = 3000,
				Rarity = (Rarity)3,
				Manufacturer = (Manufacturer)5,
				SaleLocations = new string[1] { "BlackmarketSyncClinic" },
				TierDescs = null
			},
			new DiskDef
			{
				Key = "SprintersCurse",
				DiskName = "Sprinter's Curse",
				EffectName = "Fast Twitch",
				EffectDesc = "You move considerably faster on foot.",
				Effect = (Effect)57,
				Value = 0.2f,
				SideEffect = (Effect)27,
				SideValue = 0.25f,
				SideName = "Brittle",
				SideDesc = "Your reworked frame takes damage badly. This cannot be removed.",
				Price = 2500,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)0,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = new string[3] { "You run faster, and tire sooner for it.", "You run faster again. Your skin splits more easily.", "You run faster still, and the ground meets you harder." },
				TiersInCode = true
			},
			new DiskDef
			{
				Key = "IronLung",
				DiskName = "Iron Lung",
				EffectName = "Dense Tissue",
				EffectDesc = "You take considerably less damage.",
				Effect = (Effect)27,
				Value = -0.25f,
				SideEffect = (Effect)57,
				SideValue = -0.2f,
				SideName = "Heavy Gait",
				SideDesc = "Your added mass slows you down.",
				Price = 2500,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)0,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = new string[3] { "You tire far more slowly.", "Your body knits itself back together faster.", "Your gait is corrected." },
				TiersInCode = true
			},
			new DiskDef
			{
				Key = "Leap",
				DiskName = "Leap",
				EffectName = "Leap",
				EffectDesc = "You jump considerably higher, but land harder.",
				Effect = (Effect)0,
				Value = 0f,
				Price = 3500,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)0,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = new string[3] { "You jump higher still.", "Your leap improves again.", "You clear considerable heights." },
				TiersInCode = true
			},
			new DiskDef
			{
				Key = "DeadAir",
				DiskName = "Dead Air",
				EffectName = "Slow Response",
				EffectDesc = "Security systems take longer to react to you.",
				Effect = (Effect)44,
				Value = 0.5f,
				Price = 1250,
				Rarity = (Rarity)1,
				Manufacturer = (Manufacturer)5,
				SaleLocations = new string[1] { "BlackmarketSyncClinic" },
				TierDescs = new string[2] { "Tripped breakers stay down longer.", "Disabled security is slower to wake." },
				TiersInCode = true
			},
			new DiskDef
			{
				Key = "PlusOne",
				DiskName = "Plus One",
				EffectName = "On The List",
				EffectDesc = "You obtain guest passes more readily.",
				Effect = (Effect)64,
				Value = 0.25f,
				Price = 2000,
				Rarity = (Rarity)1,
				Manufacturer = (Manufacturer)2,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = null
			},
			new DiskDef
			{
				Key = "Muckraker",
				DiskName = "Muckraker",
				EffectName = "Expose",
				EffectDesc = "Earn money photographing illegal operations.",
				Effect = (Effect)50,
				Value = 40f,
				Price = 500,
				Rarity = (Rarity)0,
				Manufacturer = (Manufacturer)4,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = null
			},
			new DiskDef
			{
				Key = "BlankFace",
				DiskName = "Blank Face",
				Enabled = false,
				EffectName = "Unmemorable",
				EffectDesc = "Citizens are far less easily alarmed by you.",
				Effect = (Effect)62,
				Value = -0.3f,
				SideEffect = (Effect)14,
				SideValue = -0.3f,
				SideName = "Forgettable",
				SideDesc = "Citizens are less willing to talk to you.",
				Price = 2000,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)5,
				SaleLocations = new string[1] { "BlackmarketSyncClinic" },
				TierDescs = null
			},
			new DiskDef
			{
				Key = "CompanyMan",
				DiskName = "Company Man",
				EffectName = "Staff Discount",
				EffectDesc = "Everything you buy costs considerably less.",
				Effect = (Effect)13,
				Value = 0.2f,
				SideEffect = (Effect)14,
				SideValue = -0.2f,
				SideName = "Corporate Stink",
				SideDesc = "Citizens trust you less. This cannot be removed.",
				Price = 1500,
				Rarity = (Rarity)1,
				Manufacturer = (Manufacturer)2,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = null
			},
			new DiskDef
			{
				Key = "SecondWind",
				DiskName = "Second Wind",
				EffectName = "Second Wind",
				EffectDesc = "You recover health more quickly.",
				Effect = (Effect)12,
				Value = 0.1f,
				Price = 2000,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)0,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = new string[3] { "Your wounds close faster still.", "Your reserves last longer.", "Your flesh bruises less readily." },
				TiersInCode = true
			},
			new DiskDef
			{
				Key = "LongArm",
				DiskName = "Long Arm",
				EffectName = "Long Arm",
				EffectDesc = "You can reach further.",
				Effect = (Effect)23,
				Value = 0.1f,
				Price = 1000,
				Rarity = (Rarity)0,
				Manufacturer = (Manufacturer)0,
				SaleLocations = new string[1] { "SyncClinic" },
				TierDescs = new string[2] { "You can reach further still.", "You throw with considerably more force." },
				TiersInCode = true
			},
			new DiskDef
			{
				Key = "LightsOut",
				DiskName = "Lights Out",
				EffectName = "Lights Out",
				EffectDesc = "Citizens you knock out stay unconscious longer.",
				Effect = (Effect)42,
				Value = 0.5f,
				Price = 2000,
				Rarity = (Rarity)2,
				Manufacturer = (Manufacturer)5,
				SaleLocations = new string[1] { "BlackmarketSyncClinic" },
				TierDescs = null
			}
		};
	}
	[BepInPlugin("ta.sod.syncdiskpack", "SoD Disk Pack", "0.12.0")]
	public class Plugin : BasePlugin
	{
		public const string GUID = "ta.sod.syncdiskpack";

		public const string VER = "0.12.0";

		internal static ManualLogSource L;

		internal static ConfigEntry<string> DisableList;

		internal static ConfigEntry<string> RemoveList;

		internal static ConfigEntry<float> QsTier1;

		internal static ConfigEntry<float> QsTier2;

		internal static ConfigEntry<float> QsTier3;

		internal static ConfigEntry<float> LeapJump0;

		internal static ConfigEntry<float> LeapJump1;

		internal static ConfigEntry<float> LeapJump2;

		internal static ConfigEntry<float> LeapJump3;

		internal static ConfigEntry<float> LeapFall0;

		internal static ConfigEntry<float> LeapFall1;

		internal static ConfigEntry<float> LeapFall2;

		internal static ConfigEntry<float> LeapFall3;

		internal static ConfigEntry<float> IlTiredness;

		internal static ConfigEntry<float> IlRecovery;

		internal static ConfigEntry<float> IlHunger;

		internal static ConfigEntry<float> IlThirst;

		internal static ConfigEntry<float> IlGaitCure;

		internal static ConfigEntry<float> ScSpeedPerTier;

		internal static ConfigEntry<float> ScTiredness;

		internal static ConfigEntry<float> ScBleeding;

		internal static ConfigEntry<float> ScFallDamage;

		internal static ConfigEntry<float> DaBreakerReset;

		internal static ConfigEntry<float> DaSecurityReset;

		internal static ConfigEntry<int> DaTamperGrace;

		internal static ConfigEntry<float> LaInteractionRange;

		internal static ConfigEntry<float> LaCarryDistance;

		internal static ConfigEntry<float> LaThrowForce;

		internal static ConfigEntry<float> SwRecovery;

		internal static ConfigEntry<float> SwEnergy;

		internal static ConfigEntry<float> SwBruised;

		internal static float? BaseRunSpeed;

		internal static float? BaseJumpHeight;

		internal static float? BaseFallDamage;

		internal static float? BaseTiredness;

		internal static float? BaseRecovery;

		internal static float? BaseHunger;

		internal static float? BaseThirst;

		internal static float? BaseBleeding;

		internal static float? BaseBreakerReset;

		internal static float? BaseSecurityReset;

		internal static int? BaseTamperGrace;

		internal static float? BaseInteractionRange;

		internal static float? BaseCarryDistance;

		internal static float? BaseThrowForce;

		internal static float? BaseEnergyRate;

		internal static float? BaseBruised;

		public override void Load()
		{
			L = ((BasePlugin)this).Log;
			L.LogInfo((object)"=== SoDDiskPack 0.12.0 starting ===");
			DisableList = ((BasePlugin)this).Config.Bind<string>("_Experimental", "DisableVanillaDisks", "", "TEST ONLY. Comma-separated vanilla preset names to set disabled=true. Leave empty to change nothing.");
			RemoveList = ((BasePlugin)this).Config.Bind<string>("_Experimental", "RemoveVanillaDisks", "", "TEST ONLY. Comma-separated vanilla preset names to REMOVE from Toolbox.allSyncDisks and from every MenuPreset stock list. Suppresses VENDOR stock only; world loot in an existing city is unaffected. Throwaway saves only. Leave empty.");
			QsTier1 = ((BasePlugin)this).Config.Bind<float>("Quickstep", "Tier1RunSpeedFraction", 0.05f, "Quickstep tier 1. Fraction added to base playerRunSpeed. Cumulative.");
			QsTier2 = ((BasePlugin)this).Config.Bind<float>("Quickstep", "Tier2RunSpeedFraction", 0.05f, "Quickstep tier 2. Fraction added to base playerRunSpeed. Cumulative.");
			QsTier3 = ((BasePlugin)this).Config.Bind<float>("Quickstep", "Tier3RunSpeedFraction", 0.1f, "Quickstep tier 3. Fraction added to base playerRunSpeed. Cumulative.");
			LeapJump0 = ((BasePlugin)this).Config.Bind<float>("Leap", "JumpHeightInstalled", 6f, "GameplayControls.jumpHeight while Leap is installed, unupgraded. Game baseline is 4.5. Absolute value, not a fraction.");
			LeapJump1 = ((BasePlugin)this).Config.Bind<float>("Leap", "JumpHeightTier1", 7f, "jumpHeight at tier 1. Absolute.");
			LeapJump2 = ((BasePlugin)this).Config.Bind<float>("Leap", "JumpHeightTier2", 8f, "jumpHeight at tier 2. Absolute.");
			LeapJump3 = ((BasePlugin)this).Config.Bind<float>("Leap", "JumpHeightTier3", 9f, "jumpHeight at tier 3. Absolute. 9.0 was play-tested as a good ceiling.");
			LeapFall0 = ((BasePlugin)this).Config.Bind<float>("Leap", "FallDamageInstalled", 1f, "fallDamageMultiplier while Leap is installed. Game baseline is 0.85. This is Leap's cost. The cure is the Stability split disk, not a tier.");
			LeapFall1 = ((BasePlugin)this).Config.Bind<float>("Leap", "FallDamageTier1", 1.1f, "fallDamageMultiplier at tier 1.");
			LeapFall2 = ((BasePlugin)this).Config.Bind<float>("Leap", "FallDamageTier2", 1.2f, "fallDamageMultiplier at tier 2.");
			LeapFall3 = ((BasePlugin)this).Config.Bind<float>("Leap", "FallDamageTier3", 1.3f, "fallDamageMultiplier at tier 3.");
			IlTiredness = ((BasePlugin)this).Config.Bind<float>("IronLung", "Tier1TirednessFraction", -0.3f, "Iron Lung tier 1. Fraction applied to base playerTirednessRate (0.06). Negative tires you more slowly. Deliberately ASYMMETRIC against Sprinter's Curse tier 1 (+0.25): if the two were equal and opposite a player running both disks would see an upgrade do literally nothing.");
			IlRecovery = ((BasePlugin)this).Config.Bind<float>("IronLung", "Tier2RecoveryFraction", 0.25f, "Iron Lung tier 2. Fraction applied to base playerRecoveryRate (0.225). Positive heals faster. SUMMED with Second Wind tier 1 if both installed.");
			IlHunger = ((BasePlugin)this).Config.Bind<float>("IronLung", "Tier3HungerFraction", -0.2f, "Iron Lung tier 3. Fraction applied to base playerHungerRate (0.125).");
			IlThirst = ((BasePlugin)this).Config.Bind<float>("IronLung", "Tier3ThirstFraction", -0.2f, "Iron Lung tier 3. Fraction applied to base playerThirstRate (0.15).");
			IlGaitCure = ((BasePlugin)this).Config.Bind<float>("IronLung", "Tier3GaitCureFraction", 0.25f, "Iron Lung tier 3 compensates for the Heavy Gait side effect. The enum gives maxSpeedModifier -0.2 (x0.8); this writes playerRunSpeed +25% on top. The two compose multiplicatively, so in ISOLATION 0.8 x 1.25 returns you to normal exactly. NOTE: run-speed fractions from all disks are summed and applied once to the baseline, so the cure is DILUTED when Quickstep or Sprinter's Curse are also installed - roughly 5% short with both at tier 3. This is expected behaviour.");
			ScSpeedPerTier = ((BasePlugin)this).Config.Bind<float>("SprintersCurse", "SpeedFractionPerTier", 0.08f, "Sprinter's Curse. Fraction added to base playerRunSpeed per tier. Cumulative.");
			ScTiredness = ((BasePlugin)this).Config.Bind<float>("SprintersCurse", "Tier1TirednessFraction", 0.25f, "Sprinter's Curse tier 1 cost. Fraction applied to base playerTirednessRate. Positive tires you faster. See IronLung Tier1TirednessFraction for why these two are not equal and opposite.");
			ScBleeding = ((BasePlugin)this).Config.Bind<float>("SprintersCurse", "Tier2BleedingFraction", 0.5f, "Sprinter's Curse tier 2 cost. Fraction applied to base combatHitChanceOfBleeding (0.1). combatHitChanceOfBrokenLeg was rejected for this: at a 0.01 base it is imperceptible even tripled.");
			ScFallDamage = ((BasePlugin)this).Config.Bind<float>("SprintersCurse", "Tier3FallDamageFraction", 0.3f, "Sprinter's Curse tier 3 cost. Fraction applied to whatever fallDamageMultiplier already is, so it stacks on top of Leap.");
			DaBreakerReset = ((BasePlugin)this).Config.Bind<float>("DeadAir", "Tier1BreakerResetFraction", 0.5f, "Dead Air tier 1. Fraction applied to base breakerResetTime (0.5). POSITIVE means tripped breakers stay down LONGER, which is the stealth benefit. The sign was inverted before 0.10.0 and shortened the outage instead.");
			DaSecurityReset = ((BasePlugin)this).Config.Bind<float>("DeadAir", "Tier2SecurityResetFraction", 0.5f, "Dead Air tier 2. Fraction applied to base securityResetTime (3). POSITIVE means disabled security takes LONGER to come back online. Same sign inversion as tier 1, fixed in 0.10.0.");
			DaTamperGrace = ((BasePlugin)this).Config.Bind<int>("DeadAir", "Tier3TamperGraceAbsolute", 5, "UNUSED as of 0.10.0. Dead Air ships as a two-tier chain. tamperGrace is unobservable by construction: the tampering action completes in under 3 seconds, so the grace window never expires at any value. The key is retained so existing configs are not disturbed.");
			LaInteractionRange = ((BasePlugin)this).Config.Bind<float>("LongArm", "Tier1InteractionRangeFraction", 0.2f, "Long Arm tier 1. Fraction applied to base interactionRange (1.585). This is interaction reach, and it stacks with the disk's own reachModifier main effect and with Tenacity/Brawn tier 1. Confirmed read live and observed in play.");
			LaCarryDistance = ((BasePlugin)this).Config.Bind<float>("LongArm", "Tier2CarryDistanceFraction", 0.4f, "UNUSED as of 0.10.0. carryDistance is owned by PlacementPlus while that mod is enabled, so writes to it do nothing. The key is retained so existing configs are not disturbed.");
			LaThrowForce = ((BasePlugin)this).Config.Bind<float>("LongArm", "Tier3ThrowForceFraction", 0.4f, "Long Arm tier 2 as of 0.10.0, despite the key name, which is kept to avoid orphaning the value on existing installs. Fraction applied to base throwForce (6.4). Raised from 0.25 because 0.25 was too weak to feel in play.");
			SwRecovery = ((BasePlugin)this).Config.Bind<float>("SecondWind", "Tier1RecoveryFraction", 0.2f, "Second Wind tier 1. Fraction applied to base playerRecoveryRate (0.225). SUMMED with Iron Lung tier 2, which writes the same field.");
			SwEnergy = ((BasePlugin)this).Config.Bind<float>("SecondWind", "Tier2EnergyFraction", -0.2f, "Second Wind tier 2. Fraction applied to base playerEnergyRate (0.116). UNTESTED IN PLAY: this field has never been confirmed to be read live rather than consumed once at startup. It will log correctly either way.");
			SwBruised = ((BasePlugin)this).Config.Bind<float>("SecondWind", "Tier3BruisedFraction", -0.4f, "Second Wind tier 3. Fraction applied to base combatHitChanceOfBruised (0.1). Negative means you bruise less often. A small effect by design; no vanilla disk claims this field.");
			int num = 0;
			int num2 = 0;
			DiskDef[] all = Disks.All;
			foreach (DiskDef diskDef in all)
			{
				if (!((BasePlugin)this).Config.Bind<bool>(diskDef.Key, "Enabled", diskDef.Enabled, "Register this disk.").Value)
				{
					L.LogInfo((object)("skipped: " + diskDef.DiskName));
					continue;
				}
				int value = ((BasePlugin)this).Config.Bind<int>(diskDef.Key, "Price", diskDef.Price, "Purchase price.").Value;
				float value2 = ((BasePlugin)this).Config.Bind<float>(diskDef.Key, "Value", diskDef.Value, "Base effect value. Fractions are percentages (0.1 = 10%). Ignored on disks whose effect is applied in code.").Value;
				if (diskDef.TierDescs != null && diskDef.TierDescs.Length != 0 && !diskDef.TiersInCode)
				{
					num2++;
					L.LogWarning((object)("*** " + diskDef.DiskName + " has upgrade options but no code in RecomputeAll. Those upgrades will do NOTHING. ***"));
				}
				try
				{
					Register(diskDef, value, value2);
					num++;
				}
				catch (Exception ex)
				{
					L.LogError((object)("FAILED " + diskDef.DiskName + ": " + ex));
				}
			}
			Harmony.CreateAndPatchAll(typeof(DisablePatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(TierPatch), (string)null);
			L.LogInfo((object)("=== SoDDiskPack done: " + num + " registered, " + num2 + " with unimplemented tiers ==="));
		}

		private static void Register(DiskDef d, int price, float value)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Invalid comparison between Unknown and I4
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			int num = default(int);
			SyncDiskBuilder val = Lib.SyncDisks.Builder(d.DiskName, "ta.sod.syncdiskpack", true).AddEffect(d.EffectName, d.EffectDesc, ref num, (string)null);
			if ((int)d.SideEffect != 0)
			{
				int num2 = default(int);
				val.AddSideEffect(d.SideName, d.SideDesc, ref num2);
			}
			if (d.SaleLocations != null && d.SaleLocations.Length != 0)
			{
				val.AddSaleLocation(d.SaleLocations);
			}
			if (d.TierDescs != null && d.TierDescs.Length != 0)
			{
				Options val2 = default(Options);
				if (d.TierDescs.Length == 1)
				{
					((Options)(ref val2))..ctor(d.TierDescs[0]);
				}
				else if (d.TierDescs.Length == 2)
				{
					((Options)(ref val2))..ctor(d.TierDescs[0], d.TierDescs[1]);
				}
				else
				{
					((Options)(ref val2))..ctor(d.TierDescs[0], d.TierDescs[1], d.TierDescs[2]);
				}
				OptionIds val3 = default(OptionIds);
				val.AddUpgradeOption(val2, ref val3);
			}
			SyncDiskPreset preset = val.CreateAndRegister().Preset;
			bool flag = (int)d.Effect == 0;
			if (!flag)
			{
				preset.mainEffect1 = d.Effect;
				preset.mainEffect1Value = value;
			}
			preset.mainEffect2 = (Effect)0;
			preset.mainEffect2Value = 0f;
			preset.mainEffect3 = (Effect)0;
			preset.mainEffect3Value = 0f;
			preset.price = price;
			preset.rarity = d.Rarity;
			preset.manufacturer = d.Manufacturer;
			preset.canBeSideJobReward = true;
			preset.minimumWealthLevel = 0f;
			if ((int)d.SideEffect != 0)
			{
				preset.sideEffect = d.SideEffect;
				preset.sideEffectValue = d.SideValue;
			}
			int num3 = 0;
			try
			{
				num3 = preset.option1UpgradeEffects.Count;
			}
			catch
			{
			}
			L.LogInfo((object)("registered " + d.DiskName + " | effect=" + ((object)preset.mainEffect1/*cast due to .constrained prefix*/).ToString() + " value=" + preset.mainEffect1Value + " mfr=" + ((object)preset.manufacturer/*cast due to .constrained prefix*/).ToString() + " side=" + ((object)preset.sideEffect/*cast due to .constrained prefix*/).ToString() + " sideVal=" + preset.sideEffectValue + " price=" + preset.price + " optionSlots=" + num3 + " customId=" + num + (flag ? " CODE-DRIVEN" : "") + (d.TiersInCode ? " TIERS-IN-CODE" : "")));
		}

		private static int LevelOf(string suffix)
		{
			try
			{
				UpgradesController instance = UpgradesController.Instance;
				if ((Object)(object)instance == (Object)null || instance.upgrades == null)
				{
					return -1;
				}
				Enumerator<Upgrades> enumerator = instance.upgrades.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Upgrades current = enumerator.Current;
					if (current != null && !((SoCustomComparison)(object)current.preset == (SoCustomComparison)null))
					{
						string name = ((Object)current.preset).name;
						if (name != null && name.EndsWith(suffix))
						{
							return current.level;
						}
					}
				}
			}
			catch
			{
			}
			return -1;
		}

		internal static void RecomputeAll()
		{
			try
			{
				GameplayControls instance = GameplayControls.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					if (!BaseRunSpeed.HasValue)
					{
						BaseRunSpeed = instance.playerRunSpeed;
						BaseJumpHeight = instance.jumpHeight;
						BaseFallDamage = instance.fallDamageMultiplier;
						BaseTiredness = instance.playerTirednessRate;
						BaseRecovery = instance.playerRecoveryRate;
						BaseHunger = instance.playerHungerRate;
						BaseThirst = instance.playerThirstRate;
						BaseBleeding = instance.combatHitChanceOfBleeding;
						BaseBreakerReset = instance.breakerResetTime;
						BaseSecurityReset = instance.securityResetTime;
						BaseTamperGrace = instance.tamperGrace;
						BaseInteractionRange = instance.interactionRange;
						BaseCarryDistance = instance.carryDistance;
						BaseThrowForce = instance.throwForce;
						BaseEnergyRate = instance.playerEnergyRate;
						BaseBruised = instance.combatHitChanceOfBruised;
						ManualLogSource l = L;
						string[] array = new string[32];
						array[0] = "[TIER] captured baselines runSpeed=";
						float? baseRunSpeed = BaseRunSpeed;
						array[1] = baseRunSpeed.ToString();
						array[2] = " jump=";
						baseRunSpeed = BaseJumpHeight;
						array[3] = baseRunSpeed.ToString();
						array[4] = " fall=";
						baseRunSpeed = BaseFallDamage;
						array[5] = baseRunSpeed.ToString();
						array[6] = " tired=";
						baseRunSpeed = BaseTiredness;
						array[7] = baseRunSpeed.ToString();
						array[8] = " recovery=";
						baseRunSpeed = BaseRecovery;
						array[9] = baseRunSpeed.ToString();
						array[10] = " hunger=";
						baseRunSpeed = BaseHunger;
						array[11] = baseRunSpeed.ToString();
						array[12] = " thirst=";
						baseRunSpeed = BaseThirst;
						array[13] = baseRunSpeed.ToString();
						array[14] = " bleeding=";
						baseRunSpeed = BaseBleeding;
						array[15] = baseRunSpeed.ToString();
						array[16] = " breakerReset=";
						baseRunSpeed = BaseBreakerReset;
						array[17] = baseRunSpeed.ToString();
						array[18] = " securityReset=";
						baseRunSpeed = BaseSecurityReset;
						array[19] = baseRunSpeed.ToString();
						array[20] = " tamperGrace=";
						int? baseTamperGrace = BaseTamperGrace;
						array[21] = baseTamperGrace.ToString();
						array[22] = " interactionRange=";
						baseRunSpeed = BaseInteractionRange;
						array[23] = baseRunSpeed.ToString();
						array[24] = " carryDistance=";
						baseRunSpeed = BaseCarryDistance;
						array[25] = baseRunSpeed.ToString();
						array[26] = " throwForce=";
						baseRunSpeed = BaseThrowForce;
						array[27] = baseRunSpeed.ToString();
						array[28] = " energy=";
						baseRunSpeed = BaseEnergyRate;
						array[29] = baseRunSpeed.ToString();
						array[30] = " bruised=";
						baseRunSpeed = BaseBruised;
						array[31] = baseRunSpeed.ToString();
						l.LogInfo((object)string.Concat(array));
					}
					int num = LevelOf("_Quickstep");
					int num2 = LevelOf("_Leap");
					int num3 = LevelOf("_Iron Lung");
					int num4 = LevelOf("_Sprinter's Curse");
					int num5 = LevelOf("_Dead Air");
					int num6 = LevelOf("_Long Arm");
					int num7 = LevelOf("_Second Wind");
					float num8 = 0f;
					if (num >= 1)
					{
						num8 += QsTier1.Value;
					}
					if (num >= 2)
					{
						num8 += QsTier2.Value;
					}
					if (num >= 3)
					{
						num8 += QsTier3.Value;
					}
					if (num4 >= 1)
					{
						num8 += ScSpeedPerTier.Value;
					}
					if (num4 >= 2)
					{
						num8 += ScSpeedPerTier.Value;
					}
					if (num4 >= 3)
					{
						num8 += ScSpeedPerTier.Value;
					}
					if (num3 >= 3)
					{
						num8 += IlGaitCure.Value;
					}
					instance.playerRunSpeed = BaseRunSpeed.Value * (1f + num8);
					float value = BaseJumpHeight.Value;
					float num9 = BaseFallDamage.Value;
					if (num2 == 0)
					{
						value = LeapJump0.Value;
						num9 = LeapFall0.Value;
					}
					else if (num2 == 1)
					{
						value = LeapJump1.Value;
						num9 = LeapFall1.Value;
					}
					else if (num2 == 2)
					{
						value = LeapJump2.Value;
						num9 = LeapFall2.Value;
					}
					else if (num2 >= 3)
					{
						value = LeapJump3.Value;
						num9 = LeapFall3.Value;
					}
					if (num4 >= 3)
					{
						num9 *= 1f + ScFallDamage.Value;
					}
					instance.jumpHeight = value;
					instance.fallDamageMultiplier = num9;
					float num10 = 0f;
					if (num3 >= 1)
					{
						num10 += IlTiredness.Value;
					}
					if (num4 >= 1)
					{
						num10 += ScTiredness.Value;
					}
					instance.playerTirednessRate = BaseTiredness.Value * (1f + num10);
					float num11 = 0f;
					if (num3 >= 2)
					{
						num11 += IlRecovery.Value;
					}
					if (num7 >= 1)
					{
						num11 += SwRecovery.Value;
					}
					instance.playerRecoveryRate = BaseRecovery.Value * (1f + num11);
					instance.playerHungerRate = BaseHunger.Value * (1f + ((num3 >= 3) ? IlHunger.Value : 0f));
					instance.playerThirstRate = BaseThirst.Value * (1f + ((num3 >= 3) ? IlThirst.Value : 0f));
					instance.combatHitChanceOfBleeding = BaseBleeding.Value * (1f + ((num4 >= 2) ? ScBleeding.Value : 0f));
					instance.breakerResetTime = BaseBreakerReset.Value * (1f + ((num5 >= 1) ? DaBreakerReset.Value : 0f));
					instance.securityResetTime = BaseSecurityReset.Value * (1f + ((num5 >= 2) ? DaSecurityReset.Value : 0f));
					instance.tamperGrace = BaseTamperGrace.Value;
					instance.interactionRange = BaseInteractionRange.Value * (1f + ((num6 >= 1) ? LaInteractionRange.Value : 0f));
					instance.carryDistance = BaseCarryDistance.Value;
					instance.throwForce = BaseThrowForce.Value * (1f + ((num6 >= 2) ? LaThrowForce.Value : 0f));
					instance.playerEnergyRate = BaseEnergyRate.Value * (1f + ((num7 >= 2) ? SwEnergy.Value : 0f));
					instance.combatHitChanceOfBruised = BaseBruised.Value * (1f + ((num7 >= 3) ? SwBruised.Value : 0f));
					L.LogInfo((object)("[TIER] qs=" + num + " leap=" + num2 + " il=" + num3 + " sc=" + num4 + " da=" + num5 + " la=" + num6 + " sw=" + num7 + " | runSpeed=" + instance.playerRunSpeed + " jump=" + instance.jumpHeight + " fall=" + instance.fallDamageMultiplier + " tired=" + instance.playerTirednessRate + " recovery=" + instance.playerRecoveryRate + " hunger=" + instance.playerHungerRate + " thirst=" + instance.playerThirstRate + " bleeding=" + instance.combatHitChanceOfBleeding + " breakerReset=" + instance.breakerResetTime + " securityReset=" + instance.securityResetTime + " tamperGrace=" + instance.tamperGrace + " interactionRange=" + instance.interactionRange + " carryDistance=" + instance.carryDistance + " throwForce=" + instance.throwForce + " energy=" + instance.playerEnergyRate + " bruised=" + instance.combatHitChanceOfBruised));
				}
			}
			catch (Exception ex)
			{
				L.LogError((object)("[TIER] RecomputeAll failed: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(UpgradeEffectController), "OnSyncDiskChange")]
	public static class TierPatch
	{
		private static void Postfix()
		{
			Plugin.RecomputeAll();
		}
	}
	[HarmonyPatch(typeof(Toolbox), "Start")]
	public static class DisablePatch
	{
		private static bool done;

		private static List<string> ParseNames(string raw)
		{
			List<string> list = new List<string>();
			if (string.IsNullOrWhiteSpace(raw))
			{
				return list;
			}
			string[] array = raw.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					list.Add(text);
				}
			}
			return list;
		}

		private static void Postfix()
		{
			if (!done)
			{
				done = true;
				DoDisable();
				DoRemove();
			}
		}

		private static void DoDisable()
		{
			List<string> list = ParseNames(Plugin.DisableList.Value);
			if (list.Count == 0)
			{
				Plugin.L.LogInfo((object)"=== DisableVanillaDisks empty, nothing flagged ===");
				return;
			}
			int num = 0;
			Enumerator<SyncDiskPreset> enumerator = Toolbox.Instance.allSyncDisks.GetEnumerator();
			while (enumerator.MoveNext())
			{
				SyncDiskPreset current = enumerator.Current;
				foreach (string item in list)
				{
					if (((Object)current).name == item)
					{
						current.disabled = true;
						num++;
						Plugin.L.LogInfo((object)("=== DISABLED vanilla preset: " + ((Object)current).name + " ==="));
					}
				}
			}
			Plugin.L.LogInfo((object)("=== disable pass complete, " + num + " of " + list.Count + " names matched ==="));
		}

		private static void DoRemove()
		{
			List<string> list = ParseNames(Plugin.RemoveList.Value);
			if (list.Count == 0)
			{
				Plugin.L.LogInfo((object)"=== RemoveVanillaDisks empty, nothing removed ===");
				return;
			}
			int num = 0;
			Toolbox instance = Toolbox.Instance;
			if ((Object)(object)instance != (Object)null && instance.allSyncDisks != null)
			{
				for (int num2 = instance.allSyncDisks.Count - 1; num2 >= 0; num2--)
				{
					SyncDiskPreset val = instance.allSyncDisks[num2];
					if (!((SoCustomComparison)(object)val == (SoCustomComparison)null))
					{
						foreach (string item in list)
						{
							if (((Object)val).name == item)
							{
								instance.allSyncDisks.RemoveAt(num2);
								num++;
								Plugin.L.LogInfo((object)("=== REMOVED from Toolbox.allSyncDisks: " + item + " ==="));
								break;
							}
						}
					}
				}
			}
			else
			{
				Plugin.L.LogWarning((object)"=== Toolbox.allSyncDisks null, toolbox removal skipped ===");
			}
			int num3 = 0;
			int num4 = 0;
			Il2CppArrayBase<MenuPreset> val2 = Resources.FindObjectsOfTypeAll<MenuPreset>();
			if (val2 != null)
			{
				foreach (MenuPreset item2 in val2)
				{
					if ((SoCustomComparison)(object)item2 == (SoCustomComparison)null || item2.syncDisks == null)
					{
						continue;
					}
					num4++;
					for (int num5 = item2.syncDisks.Count - 1; num5 >= 0; num5--)
					{
						SyncDiskPreset val3 = item2.syncDisks[num5];
						if (!((SoCustomComparison)(object)val3 == (SoCustomComparison)null))
						{
							foreach (string item3 in list)
							{
								if (((Object)val3).name == item3)
								{
									item2.syncDisks.RemoveAt(num5);
									num3++;
									break;
								}
							}
						}
					}
				}
			}
			Plugin.L.LogInfo((object)("=== remove pass complete: " + num + " from Toolbox, " + num3 + " across " + num4 + " menu presets ==="));
		}
	}
}

BepInEx/plugins/SoDVanillaSplit/SoDVanillaSplit.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.Helpers.SyncDiskObjects;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SoDVanillaSplit")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0")]
[assembly: AssemblyProduct("SoDVanillaSplit")]
[assembly: AssemblyTitle("SoDVanillaSplit")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SoDVanillaSplit
{
	[BepInPlugin("ta.sod.vanillasplit", "SoD Vanilla Split", "0.4.0")]
	public class Plugin : BasePlugin
	{
		public const string GUID = "ta.sod.vanillasplit";

		internal static ManualLogSource L;

		internal static ConfigEntry<bool> RemoveParents;

		internal static ConfigEntry<bool> ClearParentSpawnData;

		internal static ConfigEntry<string> SaleLocation;

		internal static readonly Dictionary<string, SyncDiskPreset> Made = new Dictionary<string, SyncDiskPreset>();

		internal static readonly Dictionary<string, SplitDef> Defs = new Dictionary<string, SplitDef>();

		internal static readonly Dictionary<string, int> Prices = new Dictionary<string, int>();

		public override void Load()
		{
			L = ((BasePlugin)this).Log;
			L.LogInfo((object)"=== SoDVanillaSplit 0.4.0 starting ===");
			RemoveParents = ((BasePlugin)this).Config.Bind<bool>("General", "RemoveVanillaParents", false, "Remove the 17 split parent presets from Toolbox.allSyncDisks so only the split disks are sold. Starch-SugarDaddy is never removed. Leave false to run the splits ALONGSIDE vanilla.");
			ClearParentSpawnData = ((BasePlugin)this).Config.Bind<bool>("General", "ClearParentSpawnData", true, "Also clear occupation and trait spawn data on the removed parents. Toolbox removal alone suppresses vendor stock but NOT world loot: a combined parent can still be found in the world. Only applies when RemoveVanillaParents is true.");
			SaleLocation = ((BasePlugin)this).Config.Bind<string>("General", "SaleLocation", "SyncClinic", "Menu preset the split disks are added to. Blank for none.");
			string loc = ((SaleLocation.Value == null) ? "" : SaleLocation.Value.Trim());
			int num = 0;
			SplitDef[] all = Splits.All;
			foreach (SplitDef splitDef in all)
			{
				if (!((BasePlugin)this).Config.Bind<bool>(splitDef.Parent, splitDef.DiskName, true, "Register this split disk.").Value)
				{
					L.LogInfo((object)("skipped: " + splitDef.DiskName));
					continue;
				}
				Prices[splitDef.DiskName] = ((BasePlugin)this).Config.Bind<int>(splitDef.Parent, splitDef.DiskName + " price", splitDef.Price, "Credits. Split disks are priced for what the branch does, not what the parent cost, so a set of splits costs more in total than the disk they came from. Price is not a save key and can be changed on a live save.").Value;
				try
				{
					Register(splitDef, loc);
					num++;
				}
				catch (Exception ex)
				{
					L.LogError((object)("FAILED to register " + splitDef.DiskName + ": " + ex));
				}
			}
			Harmony.CreateAndPatchAll(typeof(SplitPatch), (string)null);
			L.LogInfo((object)("=== SoDVanillaSplit phase 1 done, " + num + " of " + Splits.All.Length + " registered ==="));
		}

		private static void Register(SplitDef d, string loc)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			int num = default(int);
			SyncDiskBuilder val = Lib.SyncDisks.Builder(d.DiskName, "ta.sod.vanillasplit", true).AddEffect(d.DiskName, "Pending vanilla data.", ref num, (string)null);
			if (loc.Length > 0)
			{
				val.AddSaleLocation(new string[1] { loc });
			}
			if (d.Tiers > 0)
			{
				string text = d.DiskName + " upgrade one.";
				string text2 = d.DiskName + " upgrade two.";
				string text3 = d.DiskName + " upgrade three.";
				Options val2 = default(Options);
				if (d.Tiers == 1)
				{
					((Options)(ref val2))..ctor(text);
				}
				else if (d.Tiers == 2)
				{
					((Options)(ref val2))..ctor(text, text2);
				}
				else
				{
					((Options)(ref val2))..ctor(text, text2, text3);
				}
				OptionIds val3 = default(OptionIds);
				val.AddUpgradeOption(val2, ref val3);
			}
			SyncDiskPreset preset = val.CreateAndRegister().Preset;
			preset.mainEffect2 = (Effect)0;
			preset.mainEffect2Value = 0f;
			preset.mainEffect3 = (Effect)0;
			preset.mainEffect3Value = 0f;
			Made[d.DiskName] = preset;
			Defs[d.DiskName] = d;
			L.LogInfo((object)("shell registered: " + d.DiskName + " <- " + d.Parent + " branch " + d.Branch + " tiers " + d.Tiers + " customId " + num));
		}
	}
	[HarmonyPatch(typeof(Toolbox), "Start")]
	public static class SplitPatch
	{
		[HarmonyPatch(typeof(InteriorCreator), "StartLoading")]
		public static class LootRemovePatch
		{
			private static void Prefix()
			{
				if (!Plugin.RemoveParents.Value)
				{
					return;
				}
				Toolbox instance = Toolbox.Instance;
				List<SyncDiskPreset> val = ((instance != null) ? instance.allSyncDisks : null);
				if (val == null)
				{
					return;
				}
				int num = 0;
				for (int num2 = val.Count - 1; num2 >= 0; num2--)
				{
					SyncDiskPreset val2 = val[num2];
					if (!((SoCustomComparison)(object)val2 == (SoCustomComparison)null))
					{
						string[] parents = Splits.Parents;
						foreach (string text in parents)
						{
							if (((Object)val2).name == text)
							{
								val.RemoveAt(num2);
								num++;
								break;
							}
						}
					}
				}
				if (num > 0)
				{
					Plugin.L.LogInfo((object)("=== LOOT PASS: removed " + num + " parents at chunk generation ==="));
				}
			}
		}

		private static bool done;

		private static void Postfix()
		{
			if (!done)
			{
				done = true;
				Dictionary<string, SyncDiskPreset> parents = Index();
				Copy(parents);
				Remove(parents);
			}
		}

		private static Dictionary<string, SyncDiskPreset> Index()
		{
			Dictionary<string, SyncDiskPreset> dictionary = new Dictionary<string, SyncDiskPreset>();
			List<SyncDiskPreset> allSyncDisks = Toolbox.Instance.allSyncDisks;
			if (allSyncDisks == null)
			{
				Plugin.L.LogError((object)"=== Toolbox.allSyncDisks is null, phase 2 aborted ===");
				return dictionary;
			}
			Enumerator<SyncDiskPreset> enumerator = allSyncDisks.GetEnumerator();
			while (enumerator.MoveNext())
			{
				SyncDiskPreset current = enumerator.Current;
				if ((SoCustomComparison)(object)current == (SoCustomComparison)null)
				{
					continue;
				}
				string[] parents = Splits.Parents;
				foreach (string text in parents)
				{
					if (((Object)current).name == text && !dictionary.ContainsKey(text))
					{
						dictionary[text] = current;
					}
				}
			}
			Plugin.L.LogInfo((object)("=== indexed " + dictionary.Count + " of " + Splits.Parents.Length + " parent presets ==="));
			return dictionary;
		}

		private static void Copy(Dictionary<string, SyncDiskPreset> parents)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int num2 = 0;
			foreach (KeyValuePair<string, SyncDiskPreset> item in Plugin.Made)
			{
				SyncDiskPreset value = item.Value;
				SplitDef splitDef = Plugin.Defs[item.Key];
				if (!parents.TryGetValue(splitDef.Parent, out var value2) || (SoCustomComparison)(object)value2 == (SoCustomComparison)null)
				{
					Plugin.L.LogWarning((object)("parent NOT FOUND for " + splitDef.DiskName + " (" + splitDef.Parent + ") - disk left as placeholder"));
					num2++;
					continue;
				}
				value.price = (Plugin.Prices.TryGetValue(splitDef.DiskName, out var value3) ? value3 : value2.price);
				value.rarity = value2.rarity;
				value.manufacturer = value2.manufacturer;
				value.uninstallCost = value2.uninstallCost;
				value.minimumWealthLevel = value2.minimumWealthLevel;
				value.canBeSideJobReward = value2.canBeSideJobReward;
				value.sideEffect = value2.sideEffect;
				value.sideEffectValue = value2.sideEffectValue;
				value.sideEffectDescription = value2.sideEffectDescription;
				if (splitDef.Branch == 1)
				{
					value.mainEffect1 = value2.mainEffect1;
					value.mainEffect1Value = value2.mainEffect1Value;
					value.mainEffect1Description = value2.mainEffect1Description;
					value.mainEffect1Icon = value2.mainEffect1Icon;
					List<UpgradeEffect> option1UpgradeEffects = value2.option1UpgradeEffects;
					List<float> option1UpgradeValues = value2.option1UpgradeValues;
					List<string> option1UpgradeNameReferences = value2.option1UpgradeNameReferences;
					List<UpgradeEffect> option1UpgradeEffects2 = value.option1UpgradeEffects;
					List<float> option1UpgradeValues2 = value.option1UpgradeValues;
					List<string> option1UpgradeNameReferences2 = value.option1UpgradeNameReferences;
					for (int i = 0; i < splitDef.Tiers && i < option1UpgradeEffects.Count && i < option1UpgradeEffects2.Count; i++)
					{
						option1UpgradeEffects2[i] = Fix(option1UpgradeEffects[i], splitDef, i);
						option1UpgradeValues2[i] = option1UpgradeValues[i];
						if (i < option1UpgradeNameReferences.Count && i < option1UpgradeNameReferences2.Count)
						{
							option1UpgradeNameReferences2[i] = option1UpgradeNameReferences[i];
						}
					}
				}
				else if (splitDef.Branch == 2)
				{
					value.mainEffect1 = value2.mainEffect2;
					value.mainEffect1Value = value2.mainEffect2Value;
					value.mainEffect1Description = value2.mainEffect2Description;
					value.mainEffect1Icon = value2.mainEffect2Icon;
					List<UpgradeEffect> option2UpgradeEffects = value2.option2UpgradeEffects;
					List<float> option2UpgradeValues = value2.option2UpgradeValues;
					List<string> option2UpgradeNameReferences = value2.option2UpgradeNameReferences;
					List<UpgradeEffect> option1UpgradeEffects3 = value.option1UpgradeEffects;
					List<float> option1UpgradeValues3 = value.option1UpgradeValues;
					List<string> option1UpgradeNameReferences3 = value.option1UpgradeNameReferences;
					for (int j = 0; j < splitDef.Tiers && j < option2UpgradeEffects.Count && j < option1UpgradeEffects3.Count; j++)
					{
						option1UpgradeEffects3[j] = Fix(option2UpgradeEffects[j], splitDef, j);
						option1UpgradeValues3[j] = option2UpgradeValues[j];
						if (j < option2UpgradeNameReferences.Count && j < option1UpgradeNameReferences3.Count)
						{
							option1UpgradeNameReferences3[j] = option2UpgradeNameReferences[j];
						}
					}
				}
				else
				{
					value.mainEffect1 = value2.mainEffect3;
					value.mainEffect1Value = value2.mainEffect3Value;
					value.mainEffect1Description = value2.mainEffect3Description;
					value.mainEffect1Icon = value2.mainEffect3Icon;
					List<UpgradeEffect> option3UpgradeEffects = value2.option3UpgradeEffects;
					List<float> option3UpgradeValues = value2.option3UpgradeValues;
					List<string> option3UpgradeNameReferences = value2.option3UpgradeNameReferences;
					List<UpgradeEffect> option1UpgradeEffects4 = value.option1UpgradeEffects;
					List<float> option1UpgradeValues4 = value.option1UpgradeValues;
					List<string> option1UpgradeNameReferences4 = value.option1UpgradeNameReferences;
					for (int k = 0; k < splitDef.Tiers && k < option3UpgradeEffects.Count && k < option1UpgradeEffects4.Count; k++)
					{
						option1UpgradeEffects4[k] = Fix(option3UpgradeEffects[k], splitDef, k);
						option1UpgradeValues4[k] = option3UpgradeValues[k];
						if (k < option3UpgradeNameReferences.Count && k < option1UpgradeNameReferences4.Count)
						{
							option1UpgradeNameReferences4[k] = option3UpgradeNameReferences[k];
						}
					}
				}
				num++;
				Plugin.L.LogInfo((object)("copied " + splitDef.DiskName + " | effect=" + ((object)value.mainEffect1/*cast due to .constrained prefix*/).ToString() + " value=" + value.mainEffect1Value + " mfr=" + ((object)value.manufacturer/*cast due to .constrained prefix*/).ToString() + " price=" + value.price + " side=" + ((object)value.sideEffect/*cast due to .constrained prefix*/).ToString() + " tiers=" + splitDef.Tiers));
			}
			Plugin.L.LogInfo((object)("=== copy pass complete: " + num + " copied, " + num2 + " missing parents ==="));
		}

		private static UpgradeEffect Fix(UpgradeEffect e, SplitDef d, int tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)e == 2)
			{
				Plugin.L.LogInfo((object)("override: " + d.DiskName + " tier " + (tier + 1) + " bothConfigurations -> modifyEffect"));
				return (UpgradeEffect)1;
			}
			return e;
		}

		private static void ClearSpawnData(Dictionary<string, SyncDiskPreset> parents)
		{
			if (!Plugin.ClearParentSpawnData.Value)
			{
				Plugin.L.LogInfo((object)"=== ClearParentSpawnData false, spawn data left intact ===");
				return;
			}
			int num = 0;
			foreach (KeyValuePair<string, SyncDiskPreset> parent in parents)
			{
				SyncDiskPreset value = parent.Value;
				if ((SoCustomComparison)(object)value == (SoCustomComparison)null)
				{
					continue;
				}
				try
				{
					int num2 = 0;
					int num3 = 0;
					try
					{
						if (value.occupation != null)
						{
							num2 = value.occupation.Count;
						}
					}
					catch
					{
					}
					try
					{
						if (value.traits != null)
						{
							num3 = value.traits.Count;
						}
					}
					catch
					{
					}
					if (value.occupation != null)
					{
						value.occupation.Clear();
					}
					value.occupationWeight = 0;
					if (value.traits != null)
					{
						value.traits.Clear();
					}
					value.traitWeight = 0;
					num++;
					Plugin.L.LogInfo((object)("=== SPAWN CLEARED: " + parent.Key + " occ " + num2 + "->0 traits " + num3 + "->0 ==="));
				}
				catch (Exception ex)
				{
					Plugin.L.LogError((object)("spawn clear FAILED for " + parent.Key + ": " + ex));
				}
			}
			Plugin.L.LogInfo((object)("=== spawn clear complete: " + num + " of " + parents.Count + " parents ==="));
		}

		private static void Remove(Dictionary<string, SyncDiskPreset> parents)
		{
			if (!Plugin.RemoveParents.Value)
			{
				Plugin.L.LogInfo((object)"=== RemoveVanillaParents false, parents left in place ===");
				return;
			}
			ClearSpawnData(parents);
			int num = 0;
			List<SyncDiskPreset> allSyncDisks = Toolbox.Instance.allSyncDisks;
			if (allSyncDisks != null)
			{
				for (int num2 = allSyncDisks.Count - 1; num2 >= 0; num2--)
				{
					SyncDiskPreset val = allSyncDisks[num2];
					if (!((SoCustomComparison)(object)val == (SoCustomComparison)null))
					{
						string[] parents2 = Splits.Parents;
						foreach (string text in parents2)
						{
							if (((Object)val).name == text)
							{
								allSyncDisks.RemoveAt(num2);
								num++;
								Plugin.L.LogInfo((object)("=== REMOVED from Toolbox.allSyncDisks: " + text + " ==="));
								break;
							}
						}
					}
				}
			}
			int num3 = 0;
			int num4 = 0;
			Il2CppArrayBase<MenuPreset> val2 = Resources.FindObjectsOfTypeAll<MenuPreset>();
			if (val2 != null)
			{
				foreach (MenuPreset item in val2)
				{
					if ((SoCustomComparison)(object)item == (SoCustomComparison)null || item.syncDisks == null)
					{
						continue;
					}
					num4++;
					for (int num5 = item.syncDisks.Count - 1; num5 >= 0; num5--)
					{
						SyncDiskPreset val3 = item.syncDisks[num5];
						if (!((SoCustomComparison)(object)val3 == (SoCustomComparison)null))
						{
							string[] parents2 = Splits.Parents;
							foreach (string text2 in parents2)
							{
								if (((Object)val3).name == text2)
								{
									item.syncDisks.RemoveAt(num5);
									num3++;
									break;
								}
							}
						}
					}
				}
			}
			Plugin.L.LogInfo((object)("=== remove pass complete: " + num + " from Toolbox, " + num3 + " across " + num4 + " menu presets ==="));
		}
	}
	public class SplitDef
	{
		public string DiskName;

		public string Parent;

		public int Branch;

		public int Tiers;

		public int Price;
	}
	public static class Splits
	{
		public static readonly SplitDef[] All = new SplitDef[37]
		{
			new SplitDef
			{
				DiskName = "Clout",
				Parent = "ElGen-Tenacity",
				Branch = 1,
				Tiers = 3,
				Price = 1500
			},
			new SplitDef
			{
				DiskName = "Brawn",
				Parent = "ElGen-Tenacity",
				Branch = 2,
				Tiers = 3,
				Price = 1250
			},
			new SplitDef
			{
				DiskName = "Reflexes",
				Parent = "ElGen-Tenacity",
				Branch = 3,
				Tiers = 3,
				Price = 2500
			},
			new SplitDef
			{
				DiskName = "Lockpicker",
				Parent = "BlackMarket-Trespasser",
				Branch = 1,
				Tiers = 0,
				Price = 1750
			},
			new SplitDef
			{
				DiskName = "Resourceful",
				Parent = "BlackMarket-Trespasser",
				Branch = 2,
				Tiers = 0,
				Price = 1750
			},
			new SplitDef
			{
				DiskName = "Invisible",
				Parent = "BlackMarket-Trespasser",
				Branch = 3,
				Tiers = 0,
				Price = 1250
			},
			new SplitDef
			{
				DiskName = "Gold Medical Cover",
				Parent = "Kensington-SpartanInsuranceSchemes",
				Branch = 1,
				Tiers = 2,
				Price = 1000
			},
			new SplitDef
			{
				DiskName = "Gold Legal Cover",
				Parent = "Kensington-SpartanInsuranceSchemes",
				Branch = 2,
				Tiers = 2,
				Price = 1250
			},
			new SplitDef
			{
				DiskName = "Gold Accident Cover",
				Parent = "Kensington-SpartanInsuranceSchemes",
				Branch = 3,
				Tiers = 2,
				Price = 750
			},
			new SplitDef
			{
				DiskName = "Street Cleaner",
				Parent = "Candor-ModelCitizen",
				Branch = 1,
				Tiers = 3,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Bookworm",
				Parent = "Candor-ModelCitizen",
				Branch = 2,
				Tiers = 3,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Power",
				Parent = "ElGen-Vigor",
				Branch = 1,
				Tiers = 0,
				Price = 2500
			},
			new SplitDef
			{
				DiskName = "Stability",
				Parent = "ElGen-Vigor",
				Branch = 2,
				Tiers = 0,
				Price = 3000
			},
			new SplitDef
			{
				DiskName = "Physiological Perception",
				Parent = "Kaizen-DovePlus",
				Branch = 1,
				Tiers = 3,
				Price = 1750
			},
			new SplitDef
			{
				DiskName = "Socioeconomic Perception",
				Parent = "Kaizen-DovePlus",
				Branch = 2,
				Tiers = 3,
				Price = 1000
			},
			new SplitDef
			{
				DiskName = "Food Hygeine Inspector",
				Parent = "Candor-PublicService",
				Branch = 1,
				Tiers = 3,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Sanitary Hygeine Inspector",
				Parent = "Candor-PublicService",
				Branch = 2,
				Tiers = 3,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Rogue",
				Parent = "BlackMarket-Infiltrator",
				Branch = 1,
				Tiers = 1,
				Price = 1750
			},
			new SplitDef
			{
				DiskName = "Hacker",
				Parent = "BlackMarket-Infiltrator",
				Branch = 2,
				Tiers = 1,
				Price = 1750
			},
			new SplitDef
			{
				DiskName = "Cash Flow",
				Parent = "Kensington-AmbassadorScheme",
				Branch = 1,
				Tiers = 3,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Competitor Data Mining",
				Parent = "Kensington-AmbassadorScheme",
				Branch = 2,
				Tiers = 3,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Fortitude",
				Parent = "ElGen-Physique",
				Branch = 1,
				Tiers = 1,
				Price = 1750
			},
			new SplitDef
			{
				DiskName = "Vitality",
				Parent = "ElGen-Physique",
				Branch = 2,
				Tiers = 1,
				Price = 1500
			},
			new SplitDef
			{
				DiskName = "Allure",
				Parent = "ElGen-Beauty",
				Branch = 1,
				Tiers = 3,
				Price = 1500
			},
			new SplitDef
			{
				DiskName = "Charm",
				Parent = "ElGen-Beauty",
				Branch = 2,
				Tiers = 3,
				Price = 1500
			},
			new SplitDef
			{
				DiskName = "Chemistry",
				Parent = "ElGen-Constitution",
				Branch = 1,
				Tiers = 2,
				Price = 2000
			},
			new SplitDef
			{
				DiskName = "Cardiovascular",
				Parent = "ElGen-Constitution",
				Branch = 2,
				Tiers = 2,
				Price = 2000
			},
			new SplitDef
			{
				DiskName = "Spread the word!",
				Parent = "Starch-BrandAmbassador",
				Branch = 1,
				Tiers = 2,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Put some life into it!",
				Parent = "Starch-BrandAmbassador",
				Branch = 2,
				Tiers = 2,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Urbex Cartographer",
				Parent = "Candor-Cartographer",
				Branch = 1,
				Tiers = 0,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Crawlspace Engineer",
				Parent = "Candor-Cartographer",
				Branch = 2,
				Tiers = 0,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Care in the Community",
				Parent = "Candor-Community",
				Branch = 1,
				Tiers = 1,
				Price = 750
			},
			new SplitDef
			{
				DiskName = "Heavy Lifter",
				Parent = "Candor-Community",
				Branch = 2,
				Tiers = 1,
				Price = 1500
			},
			new SplitDef
			{
				DiskName = "Statuesque",
				Parent = "ElGen-Frame",
				Branch = 1,
				Tiers = 2,
				Price = 750
			},
			new SplitDef
			{
				DiskName = "Compact",
				Parent = "ElGen-Frame",
				Branch = 2,
				Tiers = 2,
				Price = 750
			},
			new SplitDef
			{
				DiskName = "Mailing List",
				Parent = "BlackMarket-Interceptor",
				Branch = 1,
				Tiers = 0,
				Price = 500
			},
			new SplitDef
			{
				DiskName = "Safecacker",
				Parent = "BlackMarket-Interceptor",
				Branch = 2,
				Tiers = 0,
				Price = 500
			}
		};

		public static readonly string[] Parents = new string[17]
		{
			"ElGen-Tenacity", "BlackMarket-Trespasser", "Kensington-SpartanInsuranceSchemes", "Candor-ModelCitizen", "ElGen-Vigor", "Kaizen-DovePlus", "Candor-PublicService", "BlackMarket-Infiltrator", "Kensington-AmbassadorScheme", "ElGen-Physique",
			"ElGen-Beauty", "ElGen-Constitution", "Starch-BrandAmbassador", "Candor-Cartographer", "Candor-Community", "ElGen-Frame", "BlackMarket-Interceptor"
		};
	}
}

BepInEx/plugins/SoDDiskAvailability/SoDDiskAvailability.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SoDDiskAvailability")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("SoDDiskAvailability")]
[assembly: AssemblyTitle("SoDDiskAvailability")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SoDDiskAvailability
{
	[BepInPlugin("ta.sod.diskavailability", "SoD Disk Availability", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		public const string GUID = "ta.sod.diskavailability";

		public const string VER = "0.1.0";

		internal static ManualLogSource L;

		internal static ConfigEntry<string> Mode;

		internal static ConfigEntry<int> Salt;

		internal static ConfigEntry<bool> LogStock;

		internal static readonly List<Pool> Pools = new List<Pool>();

		public override void Load()
		{
			L = ((BasePlugin)this).Log;
			L.LogInfo((object)"=== SoD Disk Availability 0.1.0 starting ===");
			Mode = ((BasePlugin)this).Config.Bind<string>("General", "Mode", "Rotation", "Unrestricted = every disk stocked everywhere, always. Vanilla = restore the stock lists as the game shipped them. Rotation = each vendor stocks a small set that changes daily.");
			Salt = ((BasePlugin)this).Config.Bind<int>("General", "RotationSalt", 0, "Change this number to get a different rotation sequence. Rotation is derived from the in-game day plus this salt, so the same day always produces the same stock and reloading never rerolls it.");
			LogStock = ((BasePlugin)this).Config.Bind<bool>("General", "LogStockToConsole", true, "Write the chosen stock to the BepInEx log on every rotation.");
			Add("SyncClinic", "SyncClinics", 4, 0, "The ordinary sync clinics. There are usually six or seven in a city and they all share one stock list, so they will show the same disks as each other.");
			Add("BlackmarketSyncClinic", "BlackMarketClinic", 6, 0, "The black market doctor. Stocks independently of the ordinary clinics.");
			Add("BlackmarketTrader", "BlackMarketTrader", 3, 0, "The black market trader. Vanilla sells almost no disks here.");
			Add("WeaponsDealer", "WeaponsDealer", 3, 0, "The arms dealer. Vanilla sells no disks here at all, so this gives a reason to visit in person.");
			Add("Newsstand", "Newsstands", 2, 0, "Street newsstands. Vanilla draws one random CandorNews disk.");
			Add("NewspaperBox", "NewspaperBoxes", 2, 0, "Coin-operated newspaper boxes. Vanilla sells no disks here.");
			Harmony.CreateAndPatchAll(typeof(StockPatch), (string)null);
			((BasePlugin)this).AddComponent<DayWatcher>();
			L.LogInfo((object)("=== SoD Disk Availability ready, mode=" + Mode.Value + " ==="));
		}

		private void Add(string preset, string section, int count, int slots, string blurb)
		{
			Pool item = new Pool
			{
				Preset = preset,
				Enabled = ((BasePlugin)this).Config.Bind<bool>(section, "Enabled", true, blurb + " Set false to leave this vendor exactly as the game left it."),
				Count = ((BasePlugin)this).Config.Bind<int>(section, "DisksInStock", count, "How many disks this vendor offers at once in Rotation mode. 0 for none."),
				Slots = ((BasePlugin)this).Config.Bind<int>(section, "ExtraRandomSlots", slots, "Additional disks the game draws at random on top of the list above, filtered by the manufacturers below. Vanilla uses 1 for sync clinics."),
				Manufacturers = ((BasePlugin)this).Config.Bind<string>(section, "RestrictToManufacturers", "", "Comma separated. Blank means draw from every disk in the game. Valid names: ElGen, Kaizen, KensingtonIndigo, StarchKola, CandorNews, BlackMarket.")
			};
			Pools.Add(item);
		}
	}
	internal class Pool
	{
		public string Preset;

		public ConfigEntry<bool> Enabled;

		public ConfigEntry<int> Count;

		public ConfigEntry<int> Slots;

		public ConfigEntry<string> Manufacturers;
	}
	[HarmonyPatch(typeof(Toolbox), "Start")]
	public static class StockPatch
	{
		private static bool captured;

		[HarmonyPriority(0)]
		private static void Postfix()
		{
			if (captured)
			{
				return;
			}
			captured = true;
			try
			{
				Stock.CaptureOriginals();
				Stock.Apply(force: true);
			}
			catch (Exception ex)
			{
				Plugin.L.LogError((object)("initial stock pass failed: " + ex));
			}
		}
	}
	public class DayWatcher : MonoBehaviour
	{
		private float _next;

		public DayWatcher(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Update()
		{
			if (Time.time < _next)
			{
				return;
			}
			_next = Time.time + 1f;
			try
			{
				Stock.Apply(force: false);
			}
			catch
			{
			}
		}
	}
	internal static class Stock
	{
		private static readonly List<SyncDiskPreset> MasterPool = new List<SyncDiskPreset>();

		private static readonly Dictionary<string, List<SyncDiskPreset>> Originals = new Dictionary<string, List<SyncDiskPreset>>();

		private static readonly Dictionary<string, int> OriginalSlots = new Dictionary<string, int>();

		private static int _lastDay = int.MinValue;

		private static string _lastMode = null;

		public static void CaptureOriginals()
		{
			MasterPool.Clear();
			Originals.Clear();
			OriginalSlots.Clear();
			List<SyncDiskPreset> allSyncDisks = Toolbox.Instance.allSyncDisks;
			if (allSyncDisks == null)
			{
				Plugin.L.LogError((object)"Toolbox.allSyncDisks null - availability disabled this session");
				return;
			}
			for (int i = 0; i < allSyncDisks.Count; i++)
			{
				SyncDiskPreset val = allSyncDisks[i];
				if (!((SoCustomComparison)(object)val == (SoCustomComparison)null) && !val.disabled)
				{
					MasterPool.Add(val);
				}
			}
			Il2CppArrayBase<MenuPreset> val2 = Resources.FindObjectsOfTypeAll<MenuPreset>();
			if (val2 != null)
			{
				foreach (MenuPreset item in val2)
				{
					if ((SoCustomComparison)(object)item == (SoCustomComparison)null || ((Object)item).name == null || Originals.ContainsKey(((Object)item).name))
					{
						continue;
					}
					List<SyncDiskPreset> list = new List<SyncDiskPreset>();
					if (item.syncDisks != null)
					{
						for (int j = 0; j < item.syncDisks.Count; j++)
						{
							SyncDiskPreset val3 = item.syncDisks[j];
							if ((SoCustomComparison)(object)val3 != (SoCustomComparison)null)
							{
								list.Add(val3);
							}
						}
					}
					Originals[((Object)item).name] = list;
					OriginalSlots[((Object)item).name] = item.syncDiskSlots;
				}
			}
			Plugin.L.LogInfo((object)("=== captured " + MasterPool.Count + " disks in the master pool, " + Originals.Count + " menu presets snapshotted ==="));
		}

		private static int CurrentDay()
		{
			try
			{
				return SessionData.Instance.dayInt;
			}
			catch
			{
				return 0;
			}
		}

		public static void Apply(bool force)
		{
			if (MasterPool.Count == 0)
			{
				return;
			}
			string text = (Plugin.Mode.Value ?? "Rotation").Trim();
			int num = CurrentDay();
			if (!force && num == _lastDay && text == _lastMode)
			{
				return;
			}
			_lastDay = num;
			_lastMode = text;
			bool flag = text.Equals("Unrestricted", StringComparison.OrdinalIgnoreCase);
			bool flag2 = text.Equals("Vanilla", StringComparison.OrdinalIgnoreCase);
			foreach (Pool pool in Plugin.Pools)
			{
				if (!pool.Enabled.Value)
				{
					continue;
				}
				Il2CppArrayBase<MenuPreset> val = Resources.FindObjectsOfTypeAll<MenuPreset>();
				if (val == null)
				{
					continue;
				}
				foreach (MenuPreset item in val)
				{
					if ((SoCustomComparison)(object)item == (SoCustomComparison)null || ((Object)item).name != pool.Preset || item.syncDisks == null)
					{
						continue;
					}
					if (flag2)
					{
						WriteList(item, Originals.ContainsKey(((Object)item).name) ? Originals[((Object)item).name] : new List<SyncDiskPreset>());
						if (OriginalSlots.ContainsKey(((Object)item).name))
						{
							item.syncDiskSlots = OriginalSlots[((Object)item).name];
						}
						continue;
					}
					if (flag)
					{
						WriteList(item, MasterPool);
						item.syncDiskSlots = pool.Slots.Value;
						continue;
					}
					List<SyncDiskPreset> list = Pick(Filter(pool.Manufacturers.Value), pool.Count.Value, num, pool.Preset);
					WriteList(item, list);
					item.syncDiskSlots = pool.Slots.Value;
					if (!Plugin.LogStock.Value)
					{
						continue;
					}
					StringBuilder stringBuilder = new StringBuilder();
					foreach (SyncDiskPreset item2 in list)
					{
						if (stringBuilder.Length > 0)
						{
							stringBuilder.Append(", ");
						}
						stringBuilder.Append(Short(((Object)item2).name));
					}
					Plugin.L.LogInfo((object)("[STOCK] day " + num + " " + pool.Preset + " (" + list.Count + "): " + stringBuilder));
				}
			}
		}

		private static string Short(string n)
		{
			if (string.IsNullOrEmpty(n))
			{
				return "?";
			}
			int num = n.LastIndexOf('_');
			if (num < 0 || num >= n.Length - 1)
			{
				return n;
			}
			return n.Substring(num + 1);
		}

		private static void WriteList(MenuPreset m, List<SyncDiskPreset> items)
		{
			m.syncDisks.Clear();
			foreach (SyncDiskPreset item in items)
			{
				if ((SoCustomComparison)(object)item != (SoCustomComparison)null)
				{
					m.syncDisks.Add(item);
				}
			}
		}

		private static List<SyncDiskPreset> Filter(string csv)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(csv) || csv.Trim().Length == 0)
			{
				return MasterPool;
			}
			List<string> list = new List<string>();
			string[] array = csv.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					list.Add(text);
				}
			}
			if (list.Count == 0)
			{
				return MasterPool;
			}
			List<SyncDiskPreset> list2 = new List<SyncDiskPreset>();
			foreach (SyncDiskPreset item in MasterPool)
			{
				string a;
				try
				{
					a = ((object)item.manufacturer/*cast due to .constrained prefix*/).ToString();
				}
				catch
				{
					continue;
				}
				foreach (string item2 in list)
				{
					if (string.Equals(a, item2, StringComparison.OrdinalIgnoreCase))
					{
						list2.Add(item);
						break;
					}
				}
			}
			if (list2.Count <= 0)
			{
				return MasterPool;
			}
			return list2;
		}

		private static List<SyncDiskPreset> Pick(List<SyncDiskPreset> from, int count, int day, string vendor)
		{
			List<SyncDiskPreset> list = new List<SyncDiskPreset>();
			if (count <= 0 || from.Count == 0)
			{
				return list;
			}
			if (count >= from.Count)
			{
				list.AddRange(from);
				return list;
			}
			uint num = (uint)(day * 2654435761u);
			num ^= (uint)(Plugin.Salt.Value * 40503);
			foreach (char c in vendor)
			{
				num = num * 31 + c;
			}
			if (num == 0)
			{
				num = 2463534242u;
			}
			List<int> list2 = new List<int>();
			for (int j = 0; j < from.Count; j++)
			{
				list2.Add(j);
			}
			for (int num2 = list2.Count - 1; num2 > 0; num2--)
			{
				num ^= num << 13;
				num ^= num >> 17;
				num ^= num << 5;
				int index = (int)(num % (uint)(num2 + 1));
				int value = list2[num2];
				list2[num2] = list2[index];
				list2[index] = value;
			}
			for (int k = 0; k < count; k++)
			{
				list.Add(from[list2[k]]);
			}
			return list;
		}
	}
}